github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/monitor.c (about)

     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  // Please use C89 style variable declarations in this file because VS 2010
    28  //========================================================================
    29  
    30  #include "internal.h"
    31  
    32  #include <assert.h>
    33  #include <math.h>
    34  #include <float.h>
    35  #include <string.h>
    36  #include <stdlib.h>
    37  #include <limits.h>
    38  
    39  
    40  // Lexically compare video modes, used by qsort
    41  //
    42  static int compareVideoModes(const void* fp, const void* sp)
    43  {
    44      const GLFWvidmode* fm = fp;
    45      const GLFWvidmode* sm = sp;
    46      const int fbpp = fm->redBits + fm->greenBits + fm->blueBits;
    47      const int sbpp = sm->redBits + sm->greenBits + sm->blueBits;
    48      const int farea = fm->width * fm->height;
    49      const int sarea = sm->width * sm->height;
    50  
    51      // First sort on color bits per pixel
    52      if (fbpp != sbpp)
    53          return fbpp - sbpp;
    54  
    55      // Then sort on screen area
    56      if (farea != sarea)
    57          return farea - sarea;
    58  
    59      // Then sort on width
    60      if (fm->width != sm->width)
    61          return fm->width - sm->width;
    62  
    63      // Lastly sort on refresh rate
    64      return fm->refreshRate - sm->refreshRate;
    65  }
    66  
    67  // Retrieves the available modes for the specified monitor
    68  //
    69  static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
    70  {
    71      int modeCount;
    72      GLFWvidmode* modes;
    73  
    74      if (monitor->modes)
    75          return GLFW_TRUE;
    76  
    77      modes = _glfw.platform.getVideoModes(monitor, &modeCount);
    78      if (!modes)
    79          return GLFW_FALSE;
    80  
    81      qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
    82  
    83      _glfw_free(monitor->modes);
    84      monitor->modes = modes;
    85      monitor->modeCount = modeCount;
    86  
    87      return GLFW_TRUE;
    88  }
    89  
    90  
    91  //////////////////////////////////////////////////////////////////////////
    92  //////                         GLFW event API                       //////
    93  //////////////////////////////////////////////////////////////////////////
    94  
    95  // Notifies shared code of a monitor connection or disconnection
    96  //
    97  void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
    98  {
    99      assert(monitor != NULL);
   100      assert(action == GLFW_CONNECTED || action == GLFW_DISCONNECTED);
   101      assert(placement == _GLFW_INSERT_FIRST || placement == _GLFW_INSERT_LAST);
   102  
   103      if (action == GLFW_CONNECTED)
   104      {
   105          _glfw.monitorCount++;
   106          _glfw.monitors =
   107              _glfw_realloc(_glfw.monitors,
   108                            sizeof(_GLFWmonitor*) * _glfw.monitorCount);
   109  
   110          if (placement == _GLFW_INSERT_FIRST)
   111          {
   112              memmove(_glfw.monitors + 1,
   113                      _glfw.monitors,
   114                      ((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
   115              _glfw.monitors[0] = monitor;
   116          }
   117          else
   118              _glfw.monitors[_glfw.monitorCount - 1] = monitor;
   119      }
   120      else if (action == GLFW_DISCONNECTED)
   121      {
   122          int i;
   123          _GLFWwindow* window;
   124  
   125          for (window = _glfw.windowListHead;  window;  window = window->next)
   126          {
   127              if (window->monitor == monitor)
   128              {
   129                  int width, height, xoff, yoff;
   130                  _glfw.platform.getWindowSize(window, &width, &height);
   131                  _glfw.platform.setWindowMonitor(window, NULL, 0, 0, width, height, 0);
   132                  _glfw.platform.getWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
   133                  _glfw.platform.setWindowPos(window, xoff, yoff);
   134              }
   135          }
   136  
   137          for (i = 0;  i < _glfw.monitorCount;  i++)
   138          {
   139              if (_glfw.monitors[i] == monitor)
   140              {
   141                  _glfw.monitorCount--;
   142                  memmove(_glfw.monitors + i,
   143                          _glfw.monitors + i + 1,
   144                          ((size_t) _glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
   145                  break;
   146              }
   147          }
   148      }
   149  
   150      if (_glfw.callbacks.monitor)
   151          _glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
   152  
   153      if (action == GLFW_DISCONNECTED)
   154          _glfwFreeMonitor(monitor);
   155  }
   156  
   157  // Notifies shared code that a full screen window has acquired or released
   158  // a monitor
   159  //
   160  void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
   161  {
   162      assert(monitor != NULL);
   163      monitor->window = window;
   164  }
   165  
   166  
   167  //////////////////////////////////////////////////////////////////////////
   168  //////                       GLFW internal API                      //////
   169  //////////////////////////////////////////////////////////////////////////
   170  
   171  // Allocates and returns a monitor object with the specified name and dimensions
   172  //
   173  _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
   174  {
   175      _GLFWmonitor* monitor = _glfw_calloc(1, sizeof(_GLFWmonitor));
   176      monitor->widthMM = widthMM;
   177      monitor->heightMM = heightMM;
   178  
   179      strncpy(monitor->name, name, sizeof(monitor->name) - 1);
   180  
   181      return monitor;
   182  }
   183  
   184  // Frees a monitor object and any data associated with it
   185  //
   186  void _glfwFreeMonitor(_GLFWmonitor* monitor)
   187  {
   188      if (monitor == NULL)
   189          return;
   190  
   191      _glfw.platform.freeMonitor(monitor);
   192  
   193      _glfwFreeGammaArrays(&monitor->originalRamp);
   194      _glfwFreeGammaArrays(&monitor->currentRamp);
   195  
   196      _glfw_free(monitor->modes);
   197      _glfw_free(monitor);
   198  }
   199  
   200  // Allocates red, green and blue value arrays of the specified size
   201  //
   202  void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
   203  {
   204      ramp->red = _glfw_calloc(size, sizeof(unsigned short));
   205      ramp->green = _glfw_calloc(size, sizeof(unsigned short));
   206      ramp->blue = _glfw_calloc(size, sizeof(unsigned short));
   207      ramp->size = size;
   208  }
   209  
   210  // Frees the red, green and blue value arrays and clears the struct
   211  //
   212  void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
   213  {
   214      _glfw_free(ramp->red);
   215      _glfw_free(ramp->green);
   216      _glfw_free(ramp->blue);
   217  
   218      memset(ramp, 0, sizeof(GLFWgammaramp));
   219  }
   220  
   221  // Chooses the video mode most closely matching the desired one
   222  //
   223  const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
   224                                          const GLFWvidmode* desired)
   225  {
   226      int i;
   227      unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
   228      unsigned int rateDiff, leastRateDiff = UINT_MAX;
   229      unsigned int colorDiff, leastColorDiff = UINT_MAX;
   230      const GLFWvidmode* current;
   231      const GLFWvidmode* closest = NULL;
   232  
   233      if (!refreshVideoModes(monitor))
   234          return NULL;
   235  
   236      for (i = 0;  i < monitor->modeCount;  i++)
   237      {
   238          current = monitor->modes + i;
   239  
   240          colorDiff = 0;
   241  
   242          if (desired->redBits != GLFW_DONT_CARE)
   243              colorDiff += abs(current->redBits - desired->redBits);
   244          if (desired->greenBits != GLFW_DONT_CARE)
   245              colorDiff += abs(current->greenBits - desired->greenBits);
   246          if (desired->blueBits != GLFW_DONT_CARE)
   247              colorDiff += abs(current->blueBits - desired->blueBits);
   248  
   249          sizeDiff = abs((current->width - desired->width) *
   250                         (current->width - desired->width) +
   251                         (current->height - desired->height) *
   252                         (current->height - desired->height));
   253  
   254          if (desired->refreshRate != GLFW_DONT_CARE)
   255              rateDiff = abs(current->refreshRate - desired->refreshRate);
   256          else
   257              rateDiff = UINT_MAX - current->refreshRate;
   258  
   259          if ((colorDiff < leastColorDiff) ||
   260              (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
   261              (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
   262          {
   263              closest = current;
   264              leastSizeDiff = sizeDiff;
   265              leastRateDiff = rateDiff;
   266              leastColorDiff = colorDiff;
   267          }
   268      }
   269  
   270      return closest;
   271  }
   272  
   273  // Performs lexical comparison between two @ref GLFWvidmode structures
   274  //
   275  int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
   276  {
   277      return compareVideoModes(fm, sm);
   278  }
   279  
   280  // Splits a color depth into red, green and blue bit depths
   281  //
   282  void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
   283  {
   284      int delta;
   285  
   286      // We assume that by 32 the user really meant 24
   287      if (bpp == 32)
   288          bpp = 24;
   289  
   290      // Convert "bits per pixel" to red, green & blue sizes
   291  
   292      *red = *green = *blue = bpp / 3;
   293      delta = bpp - (*red * 3);
   294      if (delta >= 1)
   295          *green = *green + 1;
   296  
   297      if (delta == 2)
   298          *red = *red + 1;
   299  }
   300  
   301  
   302  //////////////////////////////////////////////////////////////////////////
   303  //////                        GLFW public API                       //////
   304  //////////////////////////////////////////////////////////////////////////
   305  
   306  GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
   307  {
   308      assert(count != NULL);
   309  
   310      *count = 0;
   311  
   312      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   313  
   314      *count = _glfw.monitorCount;
   315      return (GLFWmonitor**) _glfw.monitors;
   316  }
   317  
   318  GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void)
   319  {
   320      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   321  
   322      if (!_glfw.monitorCount)
   323          return NULL;
   324  
   325      return (GLFWmonitor*) _glfw.monitors[0];
   326  }
   327  
   328  GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
   329  {
   330      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   331      assert(monitor != NULL);
   332  
   333      if (xpos)
   334          *xpos = 0;
   335      if (ypos)
   336          *ypos = 0;
   337  
   338      _GLFW_REQUIRE_INIT();
   339  
   340      _glfw.platform.getMonitorPos(monitor, xpos, ypos);
   341  }
   342  
   343  GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
   344                                      int* xpos, int* ypos,
   345                                      int* width, int* height)
   346  {
   347      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   348      assert(monitor != NULL);
   349  
   350      if (xpos)
   351          *xpos = 0;
   352      if (ypos)
   353          *ypos = 0;
   354      if (width)
   355          *width = 0;
   356      if (height)
   357          *height = 0;
   358  
   359      _GLFW_REQUIRE_INIT();
   360  
   361      _glfw.platform.getMonitorWorkarea(monitor, xpos, ypos, width, height);
   362  }
   363  
   364  GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
   365  {
   366      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   367      assert(monitor != NULL);
   368  
   369      if (widthMM)
   370          *widthMM = 0;
   371      if (heightMM)
   372          *heightMM = 0;
   373  
   374      _GLFW_REQUIRE_INIT();
   375  
   376      if (widthMM)
   377          *widthMM = monitor->widthMM;
   378      if (heightMM)
   379          *heightMM = monitor->heightMM;
   380  }
   381  
   382  GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
   383                                          float* xscale, float* yscale)
   384  {
   385      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   386      assert(monitor != NULL);
   387  
   388      if (xscale)
   389          *xscale = 0.f;
   390      if (yscale)
   391          *yscale = 0.f;
   392  
   393      _GLFW_REQUIRE_INIT();
   394      _glfw.platform.getMonitorContentScale(monitor, xscale, yscale);
   395  }
   396  
   397  GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
   398  {
   399      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   400      assert(monitor != NULL);
   401  
   402      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   403      return monitor->name;
   404  }
   405  
   406  GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
   407  {
   408      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   409      assert(monitor != NULL);
   410  
   411      _GLFW_REQUIRE_INIT();
   412      monitor->userPointer = pointer;
   413  }
   414  
   415  GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
   416  {
   417      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   418      assert(monitor != NULL);
   419  
   420      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   421      return monitor->userPointer;
   422  }
   423  
   424  GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
   425  {
   426      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   427      _GLFW_SWAP(GLFWmonitorfun, _glfw.callbacks.monitor, cbfun);
   428      return cbfun;
   429  }
   430  
   431  GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
   432  {
   433      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   434      assert(monitor != NULL);
   435      assert(count != NULL);
   436  
   437      *count = 0;
   438  
   439      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   440  
   441      if (!refreshVideoModes(monitor))
   442          return NULL;
   443  
   444      *count = monitor->modeCount;
   445      return monitor->modes;
   446  }
   447  
   448  GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
   449  {
   450      _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
   451      assert(monitor != NULL);
   452  
   453      _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
   454  
   455      _glfw.platform.getVideoMode(monitor, &monitor->currentMode);
   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 = _glfw_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