volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

monitor.c (15194B)


      1 //========================================================================
      2 // GLFW 3.4 - www.glfw.org
      3 //------------------------------------------------------------------------
      4 // Copyright (c) 2002-2006 Marcus Geelnard
      5 // Copyright (c) 2006-2019 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     // Then sort on width
     58     if (fm->width != sm->width)
     59         return fm->width - sm->width;
     60 
     61     // Lastly sort on refresh rate
     62     return fm->refreshRate - sm->refreshRate;
     63 }
     64 
     65 // Retrieves the available modes for the specified monitor
     66 //
     67 static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
     68 {
     69     int modeCount;
     70     GLFWvidmode* modes;
     71 
     72     if (monitor->modes)
     73         return GLFW_TRUE;
     74 
     75     modes = _glfw.platform.getVideoModes(monitor, &modeCount);
     76     if (!modes)
     77         return GLFW_FALSE;
     78 
     79     qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
     80 
     81     _glfw_free(monitor->modes);
     82     monitor->modes = modes;
     83     monitor->modeCount = modeCount;
     84 
     85     return GLFW_TRUE;
     86 }
     87 
     88 
     89 //////////////////////////////////////////////////////////////////////////
     90 //////                         GLFW event API                       //////
     91 //////////////////////////////////////////////////////////////////////////
     92 
     93 // Notifies shared code of a monitor connection or disconnection
     94 //
     95 void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
     96 {
     97     assert(monitor != NULL);
     98     assert(action == GLFW_CONNECTED || action == GLFW_DISCONNECTED);
     99     assert(placement == _GLFW_INSERT_FIRST || placement == _GLFW_INSERT_LAST);
    100 
    101     if (action == GLFW_CONNECTED)
    102     {
    103         _glfw.monitorCount++;
    104         _glfw.monitors =
    105             _glfw_realloc(_glfw.monitors,
    106                           sizeof(_GLFWmonitor*) * _glfw.monitorCount);
    107 
    108         if (placement == _GLFW_INSERT_FIRST)
    109         {
    110             memmove(_glfw.monitors + 1,
    111                     _glfw.monitors,
    112                     ((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
    113             _glfw.monitors[0] = monitor;
    114         }
    115         else
    116             _glfw.monitors[_glfw.monitorCount - 1] = monitor;
    117     }
    118     else if (action == GLFW_DISCONNECTED)
    119     {
    120         int i;
    121         _GLFWwindow* window;
    122 
    123         for (window = _glfw.windowListHead;  window;  window = window->next)
    124         {
    125             if (window->monitor == monitor)
    126             {
    127                 int width, height, xoff, yoff;
    128                 _glfw.platform.getWindowSize(window, &width, &height);
    129                 _glfw.platform.setWindowMonitor(window, NULL, 0, 0, width, height, 0);
    130                 _glfw.platform.getWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
    131                 _glfw.platform.setWindowPos(window, xoff, yoff);
    132             }
    133         }
    134 
    135         for (i = 0;  i < _glfw.monitorCount;  i++)
    136         {
    137             if (_glfw.monitors[i] == monitor)
    138             {
    139                 _glfw.monitorCount--;
    140                 memmove(_glfw.monitors + i,
    141                         _glfw.monitors + i + 1,
    142                         ((size_t) _glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
    143                 break;
    144             }
    145         }
    146     }
    147 
    148     if (_glfw.callbacks.monitor)
    149         _glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
    150 
    151     if (action == GLFW_DISCONNECTED)
    152         _glfwFreeMonitor(monitor);
    153 }
    154 
    155 // Notifies shared code that a full screen window has acquired or released
    156 // a monitor
    157 //
    158 void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
    159 {
    160     assert(monitor != NULL);
    161     monitor->window = window;
    162 }
    163 
    164 
    165 //////////////////////////////////////////////////////////////////////////
    166 //////                       GLFW internal API                      //////
    167 //////////////////////////////////////////////////////////////////////////
    168 
    169 // Allocates and returns a monitor object with the specified name and dimensions
    170 //
    171 _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
    172 {
    173     _GLFWmonitor* monitor = _glfw_calloc(1, sizeof(_GLFWmonitor));
    174     monitor->widthMM = widthMM;
    175     monitor->heightMM = heightMM;
    176 
    177     strncpy(monitor->name, name, sizeof(monitor->name) - 1);
    178 
    179     return monitor;
    180 }
    181 
    182 // Frees a monitor object and any data associated with it
    183 //
    184 void _glfwFreeMonitor(_GLFWmonitor* monitor)
    185 {
    186     if (monitor == NULL)
    187         return;
    188 
    189     _glfw.platform.freeMonitor(monitor);
    190 
    191     _glfwFreeGammaArrays(&monitor->originalRamp);
    192     _glfwFreeGammaArrays(&monitor->currentRamp);
    193 
    194     _glfw_free(monitor->modes);
    195     _glfw_free(monitor);
    196 }
    197 
    198 // Allocates red, green and blue value arrays of the specified size
    199 //
    200 void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
    201 {
    202     ramp->red = _glfw_calloc(size, sizeof(unsigned short));
    203     ramp->green = _glfw_calloc(size, sizeof(unsigned short));
    204     ramp->blue = _glfw_calloc(size, sizeof(unsigned short));
    205     ramp->size = size;
    206 }
    207 
    208 // Frees the red, green and blue value arrays and clears the struct
    209 //
    210 void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
    211 {
    212     _glfw_free(ramp->red);
    213     _glfw_free(ramp->green);
    214     _glfw_free(ramp->blue);
    215 
    216     memset(ramp, 0, sizeof(GLFWgammaramp));
    217 }
    218 
    219 // Chooses the video mode most closely matching the desired one
    220 //
    221 const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
    222                                         const GLFWvidmode* desired)
    223 {
    224     int i;
    225     unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
    226     unsigned int rateDiff, leastRateDiff = UINT_MAX;
    227     unsigned int colorDiff, leastColorDiff = UINT_MAX;
    228     const GLFWvidmode* current;
    229     const GLFWvidmode* closest = NULL;
    230 
    231     if (!refreshVideoModes(monitor))
    232         return NULL;
    233 
    234     for (i = 0;  i < monitor->modeCount;  i++)
    235     {
    236         current = monitor->modes + i;
    237 
    238         colorDiff = 0;
    239 
    240         if (desired->redBits != GLFW_DONT_CARE)
    241             colorDiff += abs(current->redBits - desired->redBits);
    242         if (desired->greenBits != GLFW_DONT_CARE)
    243             colorDiff += abs(current->greenBits - desired->greenBits);
    244         if (desired->blueBits != GLFW_DONT_CARE)
    245             colorDiff += abs(current->blueBits - desired->blueBits);
    246 
    247         sizeDiff = abs((current->width - desired->width) *
    248                        (current->width - desired->width) +
    249                        (current->height - desired->height) *
    250                        (current->height - desired->height));
    251 
    252         if (desired->refreshRate != GLFW_DONT_CARE)
    253             rateDiff = abs(current->refreshRate - desired->refreshRate);
    254         else
    255             rateDiff = UINT_MAX - current->refreshRate;
    256 
    257         if ((colorDiff < leastColorDiff) ||
    258             (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
    259             (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
    260         {
    261             closest = current;
    262             leastSizeDiff = sizeDiff;
    263             leastRateDiff = rateDiff;
    264             leastColorDiff = colorDiff;
    265         }
    266     }
    267 
    268     return closest;
    269 }
    270 
    271 // Performs lexical comparison between two @ref GLFWvidmode structures
    272 //
    273 int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
    274 {
    275     return compareVideoModes(fm, sm);
    276 }
    277 
    278 // Splits a color depth into red, green and blue bit depths
    279 //
    280 void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
    281 {
    282     int delta;
    283 
    284     // We assume that by 32 the user really meant 24
    285     if (bpp == 32)
    286         bpp = 24;
    287 
    288     // Convert "bits per pixel" to red, green & blue sizes
    289 
    290     *red = *green = *blue = bpp / 3;
    291     delta = bpp - (*red * 3);
    292     if (delta >= 1)
    293         *green = *green + 1;
    294 
    295     if (delta == 2)
    296         *red = *red + 1;
    297 }
    298 
    299 
    300 //////////////////////////////////////////////////////////////////////////
    301 //////                        GLFW public API                       //////
    302 //////////////////////////////////////////////////////////////////////////
    303 
    304 GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
    305 {
    306     assert(count != NULL);
    307 
    308     *count = 0;
    309 
    310     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    311 
    312     *count = _glfw.monitorCount;
    313     return (GLFWmonitor**) _glfw.monitors;
    314 }
    315 
    316 GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
    317 {
    318     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    319 
    320     if (!_glfw.monitorCount)
    321         return NULL;
    322 
    323     return (GLFWmonitor*) _glfw.monitors[0];
    324 }
    325 
    326 GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
    327 {
    328     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    329     assert(monitor != NULL);
    330 
    331     if (xpos)
    332         *xpos = 0;
    333     if (ypos)
    334         *ypos = 0;
    335 
    336     _GLFW_REQUIRE_INIT();
    337 
    338     _glfw.platform.getMonitorPos(monitor, xpos, ypos);
    339 }
    340 
    341 GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
    342                                     int* xpos, int* ypos,
    343                                     int* width, int* height)
    344 {
    345     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    346     assert(monitor != NULL);
    347 
    348     if (xpos)
    349         *xpos = 0;
    350     if (ypos)
    351         *ypos = 0;
    352     if (width)
    353         *width = 0;
    354     if (height)
    355         *height = 0;
    356 
    357     _GLFW_REQUIRE_INIT();
    358 
    359     _glfw.platform.getMonitorWorkarea(monitor, xpos, ypos, width, height);
    360 }
    361 
    362 GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
    363 {
    364     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    365     assert(monitor != NULL);
    366 
    367     if (widthMM)
    368         *widthMM = 0;
    369     if (heightMM)
    370         *heightMM = 0;
    371 
    372     _GLFW_REQUIRE_INIT();
    373 
    374     if (widthMM)
    375         *widthMM = monitor->widthMM;
    376     if (heightMM)
    377         *heightMM = monitor->heightMM;
    378 }
    379 
    380 GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
    381                                         float* xscale, float* yscale)
    382 {
    383     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    384     assert(monitor != NULL);
    385 
    386     if (xscale)
    387         *xscale = 0.f;
    388     if (yscale)
    389         *yscale = 0.f;
    390 
    391     _GLFW_REQUIRE_INIT();
    392     _glfw.platform.getMonitorContentScale(monitor, xscale, yscale);
    393 }
    394 
    395 GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
    396 {
    397     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    398     assert(monitor != NULL);
    399 
    400     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    401     return monitor->name;
    402 }
    403 
    404 GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
    405 {
    406     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    407     assert(monitor != NULL);
    408 
    409     _GLFW_REQUIRE_INIT();
    410     monitor->userPointer = pointer;
    411 }
    412 
    413 GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
    414 {
    415     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    416     assert(monitor != NULL);
    417 
    418     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    419     return monitor->userPointer;
    420 }
    421 
    422 GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
    423 {
    424     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    425     _GLFW_SWAP(GLFWmonitorfun, _glfw.callbacks.monitor, cbfun);
    426     return cbfun;
    427 }
    428 
    429 GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
    430 {
    431     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    432     assert(monitor != NULL);
    433     assert(count != NULL);
    434 
    435     *count = 0;
    436 
    437     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    438 
    439     if (!refreshVideoModes(monitor))
    440         return NULL;
    441 
    442     *count = monitor->modeCount;
    443     return monitor->modes;
    444 }
    445 
    446 GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
    447 {
    448     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    449     assert(monitor != NULL);
    450 
    451     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    452 
    453     if (!_glfw.platform.getVideoMode(monitor, &monitor->currentMode))
    454         return NULL;
    455 
    456     return &monitor->currentMode;
    457 }
    458 
    459 GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
    460 {
    461     unsigned int i;
    462     unsigned short* values;
    463     GLFWgammaramp ramp;
    464     const GLFWgammaramp* original;
    465     assert(handle != NULL);
    466     assert(gamma > 0.f);
    467     assert(gamma <= FLT_MAX);
    468 
    469     _GLFW_REQUIRE_INIT();
    470 
    471     if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
    472     {
    473         _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
    474         return;
    475     }
    476 
    477     original = glfwGetGammaRamp(handle);
    478     if (!original)
    479         return;
    480 
    481     values = _glfw_calloc(original->size, sizeof(unsigned short));
    482 
    483     for (i = 0;  i < original->size;  i++)
    484     {
    485         float value;
    486 
    487         // Calculate intensity
    488         value = i / (float) (original->size - 1);
    489         // Apply gamma curve
    490         value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
    491         // Clamp to value range
    492         value = fminf(value, 65535.f);
    493 
    494         values[i] = (unsigned short) value;
    495     }
    496 
    497     ramp.red = values;
    498     ramp.green = values;
    499     ramp.blue = values;
    500     ramp.size = original->size;
    501 
    502     glfwSetGammaRamp(handle, &ramp);
    503     _glfw_free(values);
    504 }
    505 
    506 GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
    507 {
    508     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    509     assert(monitor != NULL);
    510 
    511     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
    512 
    513     _glfwFreeGammaArrays(&monitor->currentRamp);
    514     if (!_glfw.platform.getGammaRamp(monitor, &monitor->currentRamp))
    515         return NULL;
    516 
    517     return &monitor->currentRamp;
    518 }
    519 
    520 GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
    521 {
    522     _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    523     assert(monitor != NULL);
    524     assert(ramp != NULL);
    525     assert(ramp->size > 0);
    526     assert(ramp->red != NULL);
    527     assert(ramp->green != NULL);
    528     assert(ramp->blue != NULL);
    529 
    530     _GLFW_REQUIRE_INIT();
    531 
    532     if (ramp->size <= 0)
    533     {
    534         _glfwInputError(GLFW_INVALID_VALUE,
    535                         "Invalid gamma ramp size %i",
    536                         ramp->size);
    537         return;
    538     }
    539 
    540     if (!monitor->originalRamp.size)
    541     {
    542         if (!_glfw.platform.getGammaRamp(monitor, &monitor->originalRamp))
    543             return;
    544     }
    545 
    546     _glfw.platform.setGammaRamp(monitor, ramp);
    547 }
    548