medfall

A super great game engine
Log | Files | Refs

monitor.cc (11895B)


      1 //========================================================================
      2 // GLFW 3.3 - www.glfw.org
      3 //------------------------------------------------------------------------
      4 // Copyright (c) 2002-2006 Marcus Geelnard
      5 // Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
      6 //
      7 // This software is provided 'as-is', without any express or implied
      8 // warranty. In no event will the authors be held liable for any damages
      9 // arising from the use of this software.
     10 //
     11 // Permission is granted to anyone to use this software for any purpose,
     12 // including commercial applications, and to alter it and redistribute it
     13 // freely, subject to the following restrictions:
     14 //
     15 // 1. The origin of this software must not be misrepresented; you must not
     16 //    claim that you wrote the original software. If you use this software
     17 //    in a product, an acknowledgment in the product documentation would
     18 //    be appreciated but is not required.
     19 //
     20 // 2. Altered source versions must be plainly marked as such, and must not
     21 //    be misrepresented as being the original software.
     22 //
     23 // 3. This notice may not be removed or altered from any source
     24 //    distribution.
     25 //
     26 //========================================================================
     27 
     28 #include "internal.h"
     29 
     30 #include <assert.h>
     31 #include <math.h>
     32 #include <float.h>
     33 #include <string.h>
     34 #include <stdlib.h>
     35 #include <limits.h>
     36 
     37 
     38 // Lexically compare video modes, used by qsort
     39 //
     40 static int compareVideoModes(const void* fp, const void* sp)
     41 {
     42     const GLFWvidmode* fm = fp;
     43     const GLFWvidmode* sm = sp;
     44     const int fbpp = fm->redBits + fm->greenBits + fm->blueBits;
     45     const int sbpp = sm->redBits + sm->greenBits + sm->blueBits;
     46     const int farea = fm->width * fm->height;
     47     const int sarea = sm->width * sm->height;
     48 
     49     // First sort on color bits per pixel
     50     if (fbpp != sbpp)
     51         return fbpp - sbpp;
     52 
     53     // Then sort on screen area
     54     if (farea != sarea)
     55         return farea - sarea;
     56 
     57     // Lastly sort on refresh rate
     58     return fm->refreshRate - sm->refreshRate;
     59 }
     60 
     61 // Retrieves the available modes for the specified monitor
     62 //
     63 static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
     64 {
     65     int modeCount;
     66     GLFWvidmode* modes;
     67 
     68     if (monitor->modes)
     69         return GLFW_TRUE;
     70 
     71     modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
     72     if (!modes)
     73         return GLFW_FALSE;
     74 
     75     qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
     76 
     77     free(monitor->modes);
     78     monitor->modes = modes;
     79     monitor->modeCount = modeCount;
     80 
     81     return GLFW_TRUE;
     82 }
     83 
     84 
     85 //////////////////////////////////////////////////////////////////////////
     86 //////                         GLFW event API                       //////
     87 //////////////////////////////////////////////////////////////////////////
     88 
     89 void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
     90 {
     91     if (action == GLFW_CONNECTED)
     92     {
     93         _glfw.monitorCount++;
     94         _glfw.monitors =
     95             realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
     96 
     97         if (placement == _GLFW_INSERT_FIRST)
     98         {
     99             memmove(_glfw.monitors + 1,
    100                     _glfw.monitors,
    101                     (_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
    102             _glfw.monitors[0] = monitor;
    103         }
    104         else
    105             _glfw.monitors[_glfw.monitorCount - 1] = monitor;
    106     }
    107     else if (action == GLFW_DISCONNECTED)
    108     {
    109         int i;
    110 
    111         for (i = 0;  i < _glfw.monitorCount;  i++)
    112         {
    113             if (_glfw.monitors[i] == monitor)
    114             {
    115                 _glfw.monitorCount--;
    116                 memmove(_glfw.monitors + i,
    117                         _glfw.monitors + i + 1,
    118                         (_glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
    119                 break;
    120             }
    121         }
    122     }
    123 
    124     if (_glfw.callbacks.monitor)
    125         _glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
    126 
    127     if (action == GLFW_DISCONNECTED)
    128         _glfwFreeMonitor(monitor);
    129 }
    130 
    131 void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
    132 {
    133     monitor->window = window;
    134 }
    135 
    136 
    137 //////////////////////////////////////////////////////////////////////////
    138 //////                       GLFW internal API                      //////
    139 //////////////////////////////////////////////////////////////////////////
    140 
    141 _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
    142 {
    143     _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
    144     monitor->widthMM = widthMM;
    145     monitor->heightMM = heightMM;
    146 
    147     if (name)
    148         monitor->name = strdup(name);
    149 
    150     return monitor;
    151 }
    152 
    153 void _glfwFreeMonitor(_GLFWmonitor* monitor)
    154 {
    155     if (monitor == NULL)
    156         return;
    157 
    158     _glfwFreeGammaArrays(&monitor->originalRamp);
    159     _glfwFreeGammaArrays(&monitor->currentRamp);
    160 
    161     free(monitor->modes);
    162     free(monitor->name);
    163     free(monitor);
    164 }
    165 
    166 void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
    167 {
    168     ramp->red = calloc(size, sizeof(unsigned short));
    169     ramp->green = calloc(size, sizeof(unsigned short));
    170     ramp->blue = calloc(size, sizeof(unsigned short));
    171     ramp->size = size;
    172 }
    173 
    174 void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
    175 {
    176     free(ramp->red);
    177     free(ramp->green);
    178     free(ramp->blue);
    179 
    180     memset(ramp, 0, sizeof(GLFWgammaramp));
    181 }
    182 
    183 const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
    184                                         const GLFWvidmode* desired)
    185 {
    186     int i;
    187     unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
    188     unsigned int rateDiff, leastRateDiff = UINT_MAX;
    189     unsigned int colorDiff, leastColorDiff = UINT_MAX;
    190     const GLFWvidmode* current;
    191     const GLFWvidmode* closest = NULL;
    192 
    193     if (!refreshVideoModes(monitor))
    194         return NULL;
    195 
    196     for (i = 0;  i < monitor->modeCount;  i++)
    197     {
    198         current = monitor->modes + i;
    199 
    200         colorDiff = 0;
    201 
    202         if (desired->redBits != GLFW_DONT_CARE)
    203             colorDiff += abs(current->redBits - desired->redBits);
    204         if (desired->greenBits != GLFW_DONT_CARE)
    205             colorDiff += abs(current->greenBits - desired->greenBits);
    206         if (desired->blueBits != GLFW_DONT_CARE)
    207             colorDiff += abs(current->blueBits - desired->blueBits);
    208 
    209         sizeDiff = abs((current->width - desired->width) *
    210                        (current->width - desired->width) +
    211                        (current->height - desired->height) *
    212                        (current->height - desired->height));
    213 
    214         if (desired->refreshRate != GLFW_DONT_CARE)
    215             rateDiff = abs(current->refreshRate - desired->refreshRate);
    216         else
    217             rateDiff = UINT_MAX - current->refreshRate;
    218 
    219         if ((colorDiff < leastColorDiff) ||
    220             (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
    221             (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
    222         {
    223             closest = current;
    224             leastSizeDiff = sizeDiff;
    225             leastRateDiff = rateDiff;
    226             leastColorDiff = colorDiff;
    227         }
    228     }
    229 
    230     return closest;
    231 }
    232 
    233 int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
    234 {
    235     return compareVideoModes(fm, sm);
    236 }
    237 
    238 void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
    239 {
    240     int delta;
    241 
    242     // We assume that by 32 the user really meant 24
    243     if (bpp == 32)
    244         bpp = 24;
    245 
    246     // Convert "bits per pixel" to red, green & blue sizes
    247 
    248     *red = *green = *blue = bpp / 3;
    249     delta = bpp - (*red * 3);
    250     if (delta >= 1)
    251         *green = *green + 1;
    252 
    253     if (delta == 2)
    254         *red = *red + 1;
    255 }
    256 
    257 
    258 //////////////////////////////////////////////////////////////////////////
    259 //////                        GLFW public API                       //////
    260 //////////////////////////////////////////////////////////////////////////
    261 
    262 GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
    263 {
    264     assert(count != NULL);
    265 
    266     *count = 0;
    267 
    268     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    269 
    270     *count = _glfw.monitorCount;
    271     return (GLFWmonitor**) _glfw.monitors;
    272 }
    273 
    274 GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
    275 {
    276     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    277 
    278     if (!_glfw.monitorCount)
    279         return NULL;
    280 
    281     return (GLFWmonitor*) _glfw.monitors[0];
    282 }
    283 
    284 GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
    285 {
    286     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    287     assert(monitor != NULL);
    288 
    289     if (xpos)
    290         *xpos = 0;
    291     if (ypos)
    292         *ypos = 0;
    293 
    294     _GLFW_REQUIRE_INIT();
    295 
    296     _glfwPlatformGetMonitorPos(monitor, xpos, ypos);
    297 }
    298 
    299 GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
    300 {
    301     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    302     assert(monitor != NULL);
    303 
    304     if (widthMM)
    305         *widthMM = 0;
    306     if (heightMM)
    307         *heightMM = 0;
    308 
    309     _GLFW_REQUIRE_INIT();
    310 
    311     if (widthMM)
    312         *widthMM = monitor->widthMM;
    313     if (heightMM)
    314         *heightMM = monitor->heightMM;
    315 }
    316 
    317 GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
    318 {
    319     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    320     assert(monitor != NULL);
    321 
    322     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    323     return monitor->name;
    324 }
    325 
    326 GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
    327 {
    328     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    329     _GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun);
    330     return cbfun;
    331 }
    332 
    333 GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
    334 {
    335     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    336     assert(monitor != NULL);
    337     assert(count != NULL);
    338 
    339     *count = 0;
    340 
    341     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    342 
    343     if (!refreshVideoModes(monitor))
    344         return NULL;
    345 
    346     *count = monitor->modeCount;
    347     return monitor->modes;
    348 }
    349 
    350 GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
    351 {
    352     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    353     assert(monitor != NULL);
    354 
    355     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    356 
    357     _glfwPlatformGetVideoMode(monitor, &monitor->currentMode);
    358     return &monitor->currentMode;
    359 }
    360 
    361 GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
    362 {
    363     int i;
    364     unsigned short values[256];
    365     GLFWgammaramp ramp;
    366     assert(handle != NULL);
    367     assert(gamma == gamma);
    368     assert(gamma >= 0.f);
    369     assert(gamma <= FLT_MAX);
    370 
    371     _GLFW_REQUIRE_INIT();
    372 
    373     if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
    374     {
    375         _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
    376         return;
    377     }
    378 
    379     for (i = 0;  i < 256;  i++)
    380     {
    381         double value;
    382 
    383         // Calculate intensity
    384         value = i / 255.0;
    385         // Apply gamma curve
    386         value = pow(value, 1.0 / gamma) * 65535.0 + 0.5;
    387 
    388         // Clamp to value range
    389         if (value > 65535.0)
    390             value = 65535.0;
    391 
    392         values[i] = (unsigned short) value;
    393     }
    394 
    395     ramp.red = values;
    396     ramp.green = values;
    397     ramp.blue = values;
    398     ramp.size = 256;
    399 
    400     glfwSetGammaRamp(handle, &ramp);
    401 }
    402 
    403 GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
    404 {
    405     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    406     assert(monitor != NULL);
    407 
    408     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    409 
    410     _glfwFreeGammaArrays(&monitor->currentRamp);
    411     _glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
    412 
    413     return &monitor->currentRamp;
    414 }
    415 
    416 GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
    417 {
    418     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    419     assert(monitor != NULL);
    420     assert(ramp != NULL);
    421     assert(ramp->size > 0);
    422     assert(ramp->red != NULL);
    423     assert(ramp->green != NULL);
    424     assert(ramp->blue != NULL);
    425 
    426     if (ramp->size <= 0)
    427     {
    428         _glfwInputError(GLFW_INVALID_VALUE,
    429                         "Invalid gamma ramp size %i",
    430                         ramp->size);
    431         return;
    432     }
    433 
    434     _GLFW_REQUIRE_INIT();
    435 
    436     if (!monitor->originalRamp.size)
    437         _glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
    438 
    439     _glfwPlatformSetGammaRamp(monitor, ramp);
    440 }
    441