00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "internal.h"
00029
00030 #include <math.h>
00031 #include <float.h>
00032 #include <string.h>
00033 #include <stdlib.h>
00034 #include <limits.h>
00035
00036
00037
00038
00039 static int compareVideoModes(const void* firstPtr, const void* secondPtr)
00040 {
00041 int firstBPP, secondBPP, firstSize, secondSize;
00042 const GLFWvidmode* first = firstPtr;
00043 const GLFWvidmode* second = secondPtr;
00044
00045
00046 firstBPP = first->redBits + first->greenBits + first->blueBits;
00047 secondBPP = second->redBits + second->greenBits + second->blueBits;
00048 if (firstBPP != secondBPP)
00049 return firstBPP - secondBPP;
00050
00051
00052 firstSize = first->width * first->height;
00053 secondSize = second->width * second->height;
00054 if (firstSize != secondSize)
00055 return firstSize - secondSize;
00056
00057
00058 return first->refreshRate - second->refreshRate;
00059 }
00060
00061
00062
00063 static int refreshVideoModes(_GLFWmonitor* monitor)
00064 {
00065 int modeCount;
00066 GLFWvidmode* modes;
00067
00068 if (monitor->modes)
00069 return GL_TRUE;
00070
00071 modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
00072 if (!modes)
00073 return GL_FALSE;
00074
00075 qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
00076
00077 free(monitor->modes);
00078 monitor->modes = modes;
00079 monitor->modeCount = modeCount;
00080
00081 return GL_TRUE;
00082 }
00083
00084
00088
00089 void _glfwInputMonitorChange(void)
00090 {
00091 int i, j, monitorCount = _glfw.monitorCount;
00092 _GLFWmonitor** monitors = _glfw.monitors;
00093
00094 _glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
00095
00096
00097
00098 for (i = 0; i < _glfw.monitorCount; i++)
00099 {
00100 for (j = 0; j < monitorCount; j++)
00101 {
00102 if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j]))
00103 {
00104 _glfwFreeMonitor(_glfw.monitors[i]);
00105 _glfw.monitors[i] = monitors[j];
00106 break;
00107 }
00108 }
00109 }
00110
00111
00112
00113 for (i = 0; i < monitorCount; i++)
00114 {
00115 _GLFWwindow* window;
00116
00117 for (j = 0; j < _glfw.monitorCount; j++)
00118 {
00119 if (monitors[i] == _glfw.monitors[j])
00120 break;
00121 }
00122
00123 if (j < _glfw.monitorCount)
00124 continue;
00125
00126 for (window = _glfw.windowListHead; window; window = window->next)
00127 {
00128 if (window->monitor == monitors[i])
00129 window->monitor = NULL;
00130 }
00131
00132 if (_glfw.callbacks.monitor)
00133 _glfw.callbacks.monitor((GLFWmonitor*) monitors[i], GLFW_DISCONNECTED);
00134 }
00135
00136
00137
00138
00139
00140 for (i = 0; i < _glfw.monitorCount; i++)
00141 {
00142 for (j = 0; j < monitorCount; j++)
00143 {
00144 if (_glfw.monitors[i] == monitors[j])
00145 {
00146 monitors[j] = NULL;
00147 break;
00148 }
00149 }
00150
00151 if (j < monitorCount)
00152 continue;
00153
00154 if (_glfw.callbacks.monitor)
00155 _glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED);
00156 }
00157
00158 _glfwFreeMonitors(monitors, monitorCount);
00159 }
00160
00161
00165
00166 _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
00167 {
00168 _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
00169 monitor->name = strdup(name);
00170 monitor->widthMM = widthMM;
00171 monitor->heightMM = heightMM;
00172
00173 return monitor;
00174 }
00175
00176 void _glfwFreeMonitor(_GLFWmonitor* monitor)
00177 {
00178 if (monitor == NULL)
00179 return;
00180
00181 _glfwFreeGammaArrays(&monitor->originalRamp);
00182 _glfwFreeGammaArrays(&monitor->currentRamp);
00183
00184 free(monitor->modes);
00185 free(monitor->name);
00186 free(monitor);
00187 }
00188
00189 void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
00190 {
00191 ramp->red = calloc(size, sizeof(unsigned short));
00192 ramp->green = calloc(size, sizeof(unsigned short));
00193 ramp->blue = calloc(size, sizeof(unsigned short));
00194 ramp->size = size;
00195 }
00196
00197 void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
00198 {
00199 free(ramp->red);
00200 free(ramp->green);
00201 free(ramp->blue);
00202
00203 memset(ramp, 0, sizeof(GLFWgammaramp));
00204 }
00205
00206 void _glfwFreeMonitors(_GLFWmonitor** monitors, int count)
00207 {
00208 int i;
00209
00210 for (i = 0; i < count; i++)
00211 _glfwFreeMonitor(monitors[i]);
00212
00213 free(monitors);
00214 }
00215
00216 const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
00217 const GLFWvidmode* desired)
00218 {
00219 int i;
00220 unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
00221 unsigned int rateDiff, leastRateDiff = UINT_MAX;
00222 unsigned int colorDiff, leastColorDiff = UINT_MAX;
00223 const GLFWvidmode* current;
00224 const GLFWvidmode* closest = NULL;
00225
00226 if (!refreshVideoModes(monitor))
00227 return NULL;
00228
00229 for (i = 0; i < monitor->modeCount; i++)
00230 {
00231 current = monitor->modes + i;
00232
00233 colorDiff = 0;
00234
00235 if (desired->redBits != GLFW_DONT_CARE)
00236 colorDiff += abs(current->redBits - desired->redBits);
00237 if (desired->greenBits != GLFW_DONT_CARE)
00238 colorDiff += abs(current->greenBits - desired->greenBits);
00239 if (desired->blueBits != GLFW_DONT_CARE)
00240 colorDiff += abs(current->blueBits - desired->blueBits);
00241
00242 sizeDiff = abs((current->width - desired->width) *
00243 (current->width - desired->width) +
00244 (current->height - desired->height) *
00245 (current->height - desired->height));
00246
00247 if (desired->refreshRate != GLFW_DONT_CARE)
00248 rateDiff = abs(current->refreshRate - desired->refreshRate);
00249 else
00250 rateDiff = UINT_MAX - current->refreshRate;
00251
00252 if ((colorDiff < leastColorDiff) ||
00253 (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
00254 (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
00255 {
00256 closest = current;
00257 leastSizeDiff = sizeDiff;
00258 leastRateDiff = rateDiff;
00259 leastColorDiff = colorDiff;
00260 }
00261 }
00262
00263 return closest;
00264 }
00265
00266 int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second)
00267 {
00268 return compareVideoModes(first, second);
00269 }
00270
00271 void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
00272 {
00273 int delta;
00274
00275
00276 if (bpp == 32)
00277 bpp = 24;
00278
00279
00280
00281 *red = *green = *blue = bpp / 3;
00282 delta = bpp - (*red * 3);
00283 if (delta >= 1)
00284 *green = *green + 1;
00285
00286 if (delta == 2)
00287 *red = *red + 1;
00288 }
00289
00290
00294
00295 GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
00296 {
00297 *count = 0;
00298
00299 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00300
00301 *count = _glfw.monitorCount;
00302 return (GLFWmonitor**) _glfw.monitors;
00303 }
00304
00305 GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
00306 {
00307 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00308
00309 if (!_glfw.monitorCount)
00310 return NULL;
00311
00312 return (GLFWmonitor*) _glfw.monitors[0];
00313 }
00314
00315 GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
00316 {
00317 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
00318
00319 if (xpos)
00320 *xpos = 0;
00321 if (ypos)
00322 *ypos = 0;
00323
00324 _GLFW_REQUIRE_INIT();
00325
00326 _glfwPlatformGetMonitorPos(monitor, xpos, ypos);
00327 }
00328
00329 GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
00330 {
00331 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
00332
00333 if (widthMM)
00334 *widthMM = 0;
00335 if (heightMM)
00336 *heightMM = 0;
00337
00338 _GLFW_REQUIRE_INIT();
00339
00340 if (widthMM)
00341 *widthMM = monitor->widthMM;
00342 if (heightMM)
00343 *heightMM = monitor->heightMM;
00344 }
00345
00346 GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
00347 {
00348 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
00349 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00350 return monitor->name;
00351 }
00352
00353 GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
00354 {
00355 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00356 _GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun);
00357 return cbfun;
00358 }
00359
00360 GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
00361 {
00362 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
00363
00364 *count = 0;
00365
00366 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00367
00368 if (!refreshVideoModes(monitor))
00369 return NULL;
00370
00371 *count = monitor->modeCount;
00372 return monitor->modes;
00373 }
00374
00375 GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
00376 {
00377 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
00378
00379 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00380
00381 _glfwPlatformGetVideoMode(monitor, &monitor->currentMode);
00382 return &monitor->currentMode;
00383 }
00384
00385 GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
00386 {
00387 int i;
00388 unsigned short values[256];
00389 GLFWgammaramp ramp;
00390
00391 _GLFW_REQUIRE_INIT();
00392
00393 if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
00394 {
00395 _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value");
00396 return;
00397 }
00398
00399 for (i = 0; i < 256; i++)
00400 {
00401 double value;
00402
00403
00404 value = i / 255.0;
00405
00406 value = pow(value, 1.0 / gamma) * 65535.0 + 0.5;
00407
00408
00409 if (value > 65535.0)
00410 value = 65535.0;
00411
00412 values[i] = (unsigned short) value;
00413 }
00414
00415 ramp.red = values;
00416 ramp.green = values;
00417 ramp.blue = values;
00418 ramp.size = 256;
00419
00420 glfwSetGammaRamp(handle, &ramp);
00421 }
00422
00423 GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
00424 {
00425 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
00426
00427 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00428
00429 _glfwFreeGammaArrays(&monitor->currentRamp);
00430 _glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
00431
00432 return &monitor->currentRamp;
00433 }
00434
00435 GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
00436 {
00437 _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
00438
00439 _GLFW_REQUIRE_INIT();
00440
00441 if (!monitor->originalRamp.size)
00442 _glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
00443
00444 _glfwPlatformSetGammaRamp(monitor, ramp);
00445 }
00446