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

     1  //========================================================================
     2  // GLFW 3.4 - www.glfw.org
     3  //------------------------------------------------------------------------
     4  // Copyright (c) 2002-2006 Marcus Geelnard
     5  // Copyright (c) 2006-2018 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 <string.h>
    33  #include <stdlib.h>
    34  #include <stdio.h>
    35  #include <stdarg.h>
    36  #include <assert.h>
    37  
    38  
    39  // NOTE: The global variables below comprise all mutable global data in GLFW
    40  //       Any other mutable global variable is a bug
    41  
    42  // This contains all mutable state shared between compilation units of GLFW
    43  //
    44  _GLFWlibrary _glfw = { GLFW_FALSE };
    45  
    46  // These are outside of _glfw so they can be used before initialization and
    47  // after termination without special handling when _glfw is cleared to zero
    48  //
    49  static _GLFWerror _glfwMainThreadError;
    50  static GLFWerrorfun _glfwErrorCallback;
    51  static GLFWallocator _glfwInitAllocator;
    52  static _GLFWinitconfig _glfwInitHints =
    53  {
    54      GLFW_TRUE,      // hat buttons
    55      GLFW_ANGLE_PLATFORM_TYPE_NONE, // ANGLE backend
    56      GLFW_ANY_PLATFORM, // preferred platform
    57      NULL,           // vkGetInstanceProcAddr function
    58      {
    59          GLFW_TRUE,  // macOS menu bar
    60          GLFW_TRUE   // macOS bundle chdir
    61      },
    62      {
    63          GLFW_TRUE,  // X11 XCB Vulkan surface
    64      },
    65  };
    66  
    67  // The allocation function used when no custom allocator is set
    68  //
    69  static void* defaultAllocate(size_t size, void* user)
    70  {
    71      return malloc(size);
    72  }
    73  
    74  // The deallocation function used when no custom allocator is set
    75  //
    76  static void defaultDeallocate(void* block, void* user)
    77  {
    78      free(block);
    79  }
    80  
    81  // The reallocation function used when no custom allocator is set
    82  //
    83  static void* defaultReallocate(void* block, size_t size, void* user)
    84  {
    85      return realloc(block, size);
    86  }
    87  
    88  // Terminate the library
    89  //
    90  static void terminate(void)
    91  {
    92      int i;
    93  
    94      memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
    95  
    96      while (_glfw.windowListHead)
    97          glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
    98  
    99      while (_glfw.cursorListHead)
   100          glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
   101  
   102      for (i = 0;  i < _glfw.monitorCount;  i++)
   103      {
   104          _GLFWmonitor* monitor = _glfw.monitors[i];
   105          if (monitor->originalRamp.size)
   106              _glfw.platform.setGammaRamp(monitor, &monitor->originalRamp);
   107          _glfwFreeMonitor(monitor);
   108      }
   109  
   110      _glfw_free(_glfw.monitors);
   111      _glfw.monitors = NULL;
   112      _glfw.monitorCount = 0;
   113  
   114      _glfw_free(_glfw.mappings);
   115      _glfw.mappings = NULL;
   116      _glfw.mappingCount = 0;
   117  
   118      _glfwTerminateVulkan();
   119      _glfw.platform.terminateJoysticks();
   120      _glfw.platform.terminate();
   121  
   122      _glfw.initialized = GLFW_FALSE;
   123  
   124      while (_glfw.errorListHead)
   125      {
   126          _GLFWerror* error = _glfw.errorListHead;
   127          _glfw.errorListHead = error->next;
   128          _glfw_free(error);
   129      }
   130  
   131      _glfwPlatformDestroyTls(&_glfw.contextSlot);
   132      _glfwPlatformDestroyTls(&_glfw.errorSlot);
   133      _glfwPlatformDestroyMutex(&_glfw.errorLock);
   134  
   135      memset(&_glfw, 0, sizeof(_glfw));
   136  }
   137  
   138  
   139  //////////////////////////////////////////////////////////////////////////
   140  //////                       GLFW internal API                      //////
   141  //////////////////////////////////////////////////////////////////////////
   142  
   143  // Encode a Unicode code point to a UTF-8 stream
   144  // Based on cutef8 by Jeff Bezanson (Public Domain)
   145  //
   146  size_t _glfwEncodeUTF8(char* s, uint32_t codepoint)
   147  {
   148      size_t count = 0;
   149  
   150      if (codepoint < 0x80)
   151          s[count++] = (char) codepoint;
   152      else if (codepoint < 0x800)
   153      {
   154          s[count++] = (codepoint >> 6) | 0xc0;
   155          s[count++] = (codepoint & 0x3f) | 0x80;
   156      }
   157      else if (codepoint < 0x10000)
   158      {
   159          s[count++] = (codepoint >> 12) | 0xe0;
   160          s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
   161          s[count++] = (codepoint & 0x3f) | 0x80;
   162      }
   163      else if (codepoint < 0x110000)
   164      {
   165          s[count++] = (codepoint >> 18) | 0xf0;
   166          s[count++] = ((codepoint >> 12) & 0x3f) | 0x80;
   167          s[count++] = ((codepoint >> 6) & 0x3f) | 0x80;
   168          s[count++] = (codepoint & 0x3f) | 0x80;
   169      }
   170  
   171      return count;
   172  }
   173  
   174  // Splits and translates a text/uri-list into separate file paths
   175  // NOTE: This function destroys the provided string
   176  //
   177  char** _glfwParseUriList(char* text, int* count)
   178  {
   179      const char* prefix = "file://";
   180      char** paths = NULL;
   181      char* line;
   182  
   183      *count = 0;
   184  
   185      while ((line = strtok(text, "\r\n")))
   186      {
   187          char* path;
   188  
   189          text = NULL;
   190  
   191          if (line[0] == '#')
   192              continue;
   193  
   194          if (strncmp(line, prefix, strlen(prefix)) == 0)
   195          {
   196              line += strlen(prefix);
   197              // TODO: Validate hostname
   198              while (*line != '/')
   199                  line++;
   200          }
   201  
   202          (*count)++;
   203  
   204          path = _glfw_calloc(strlen(line) + 1, 1);
   205          paths = _glfw_realloc(paths, *count * sizeof(char*));
   206          paths[*count - 1] = path;
   207  
   208          while (*line)
   209          {
   210              if (line[0] == '%' && line[1] && line[2])
   211              {
   212                  const char digits[3] = { line[1], line[2], '\0' };
   213                  *path = (char) strtol(digits, NULL, 16);
   214                  line += 2;
   215              }
   216              else
   217                  *path = *line;
   218  
   219              path++;
   220              line++;
   221          }
   222      }
   223  
   224      return paths;
   225  }
   226  
   227  char* _glfw_strdup(const char* source)
   228  {
   229      const size_t length = strlen(source);
   230      char* result = _glfw_calloc(length + 1, 1);
   231      strcpy(result, source);
   232      return result;
   233  }
   234  
   235  int _glfw_min(int a, int b)
   236  {
   237      return a < b ? a : b;
   238  }
   239  
   240  int _glfw_max(int a, int b)
   241  {
   242      return a > b ? a : b;
   243  }
   244  
   245  float _glfw_fminf(float a, float b)
   246  {
   247      if (a != a)
   248          return b;
   249      else if (b != b)
   250          return a;
   251      else if (a < b)
   252          return a;
   253      else
   254          return b;
   255  }
   256  
   257  float _glfw_fmaxf(float a, float b)
   258  {
   259      if (a != a)
   260          return b;
   261      else if (b != b)
   262          return a;
   263      else if (a > b)
   264          return a;
   265      else
   266          return b;
   267  }
   268  
   269  void* _glfw_calloc(size_t count, size_t size)
   270  {
   271      if (count && size)
   272      {
   273          void* block;
   274  
   275          if (count > SIZE_MAX / size)
   276          {
   277              _glfwInputError(GLFW_INVALID_VALUE, "Allocation size overflow");
   278              return NULL;
   279          }
   280  
   281          block = _glfw.allocator.allocate(count * size, _glfw.allocator.user);
   282          if (block)
   283              return memset(block, 0, count * size);
   284          else
   285          {
   286              _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
   287              return NULL;
   288          }
   289      }
   290      else
   291          return NULL;
   292  }
   293  
   294  void* _glfw_realloc(void* block, size_t size)
   295  {
   296      if (block && size)
   297      {
   298          void* resized = _glfw.allocator.reallocate(block, size, _glfw.allocator.user);
   299          if (resized)
   300              return resized;
   301          else
   302          {
   303              _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
   304              return NULL;
   305          }
   306      }
   307      else if (block)
   308      {
   309          _glfw_free(block);
   310          return NULL;
   311      }
   312      else
   313          return _glfw_calloc(1, size);
   314  }
   315  
   316  void _glfw_free(void* block)
   317  {
   318      if (block)
   319          _glfw.allocator.deallocate(block, _glfw.allocator.user);
   320  }
   321  
   322  
   323  //////////////////////////////////////////////////////////////////////////
   324  //////                         GLFW event API                       //////
   325  //////////////////////////////////////////////////////////////////////////
   326  
   327  // Notifies shared code of an error
   328  //
   329  void _glfwInputError(int code, const char* format, ...)
   330  {
   331      _GLFWerror* error;
   332      char description[_GLFW_MESSAGE_SIZE];
   333  
   334      if (format)
   335      {
   336          va_list vl;
   337  
   338          va_start(vl, format);
   339          vsnprintf(description, sizeof(description), format, vl);
   340          va_end(vl);
   341  
   342          description[sizeof(description) - 1] = '\0';
   343      }
   344      else
   345      {
   346          if (code == GLFW_NOT_INITIALIZED)
   347              strcpy(description, "The GLFW library is not initialized");
   348          else if (code == GLFW_NO_CURRENT_CONTEXT)
   349              strcpy(description, "There is no current context");
   350          else if (code == GLFW_INVALID_ENUM)
   351              strcpy(description, "Invalid argument for enum parameter");
   352          else if (code == GLFW_INVALID_VALUE)
   353              strcpy(description, "Invalid value for parameter");
   354          else if (code == GLFW_OUT_OF_MEMORY)
   355              strcpy(description, "Out of memory");
   356          else if (code == GLFW_API_UNAVAILABLE)
   357              strcpy(description, "The requested API is unavailable");
   358          else if (code == GLFW_VERSION_UNAVAILABLE)
   359              strcpy(description, "The requested API version is unavailable");
   360          else if (code == GLFW_PLATFORM_ERROR)
   361              strcpy(description, "A platform-specific error occurred");
   362          else if (code == GLFW_FORMAT_UNAVAILABLE)
   363              strcpy(description, "The requested format is unavailable");
   364          else if (code == GLFW_NO_WINDOW_CONTEXT)
   365              strcpy(description, "The specified window has no context");
   366          else if (code == GLFW_CURSOR_UNAVAILABLE)
   367              strcpy(description, "The specified cursor shape is unavailable");
   368          else if (code == GLFW_FEATURE_UNAVAILABLE)
   369              strcpy(description, "The requested feature cannot be implemented for this platform");
   370          else if (code == GLFW_FEATURE_UNIMPLEMENTED)
   371              strcpy(description, "The requested feature has not yet been implemented for this platform");
   372          else if (code == GLFW_PLATFORM_UNAVAILABLE)
   373              strcpy(description, "The requested platform is unavailable");
   374          else
   375              strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
   376      }
   377  
   378      if (_glfw.initialized)
   379      {
   380          error = _glfwPlatformGetTls(&_glfw.errorSlot);
   381          if (!error)
   382          {
   383              error = _glfw_calloc(1, sizeof(_GLFWerror));
   384              _glfwPlatformSetTls(&_glfw.errorSlot, error);
   385              _glfwPlatformLockMutex(&_glfw.errorLock);
   386              error->next = _glfw.errorListHead;
   387              _glfw.errorListHead = error;
   388              _glfwPlatformUnlockMutex(&_glfw.errorLock);
   389          }
   390      }
   391      else
   392          error = &_glfwMainThreadError;
   393  
   394      error->code = code;
   395      strcpy(error->description, description);
   396  
   397      if (_glfwErrorCallback)
   398          _glfwErrorCallback(code, description);
   399  }
   400  
   401  
   402  //////////////////////////////////////////////////////////////////////////
   403  //////                        GLFW public API                       //////
   404  //////////////////////////////////////////////////////////////////////////
   405  
   406  GLFWAPI int glfwInit(void)
   407  {
   408      if (_glfw.initialized)
   409          return GLFW_TRUE;
   410  
   411      memset(&_glfw, 0, sizeof(_glfw));
   412      _glfw.hints.init = _glfwInitHints;
   413  
   414      _glfw.allocator = _glfwInitAllocator;
   415      if (!_glfw.allocator.allocate)
   416      {
   417          _glfw.allocator.allocate   = defaultAllocate;
   418          _glfw.allocator.reallocate = defaultReallocate;
   419          _glfw.allocator.deallocate = defaultDeallocate;
   420      }
   421  
   422      if (!_glfwSelectPlatform(_glfw.hints.init.platformID, &_glfw.platform))
   423          return GLFW_FALSE;
   424  
   425      if (!_glfw.platform.init())
   426      {
   427          terminate();
   428          return GLFW_FALSE;
   429      }
   430  
   431      if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
   432          !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
   433          !_glfwPlatformCreateTls(&_glfw.contextSlot))
   434      {
   435          terminate();
   436          return GLFW_FALSE;
   437      }
   438  
   439      _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
   440  
   441      _glfwInitGamepadMappings();
   442  
   443      _glfwPlatformInitTimer();
   444      _glfw.timer.offset = _glfwPlatformGetTimerValue();
   445  
   446      _glfw.initialized = GLFW_TRUE;
   447  
   448      glfwDefaultWindowHints();
   449      return GLFW_TRUE;
   450  }
   451  
   452  GLFWAPI void glfwTerminate(void)
   453  {
   454      if (!_glfw.initialized)
   455          return;
   456  
   457      terminate();
   458  }
   459  
   460  GLFWAPI void glfwInitHint(int hint, int value)
   461  {
   462      switch (hint)
   463      {
   464          case GLFW_JOYSTICK_HAT_BUTTONS:
   465              _glfwInitHints.hatButtons = value;
   466              return;
   467          case GLFW_ANGLE_PLATFORM_TYPE:
   468              _glfwInitHints.angleType = value;
   469              return;
   470          case GLFW_PLATFORM:
   471              _glfwInitHints.platformID = value;
   472              return;
   473          case GLFW_COCOA_CHDIR_RESOURCES:
   474              _glfwInitHints.ns.chdir = value;
   475              return;
   476          case GLFW_COCOA_MENUBAR:
   477              _glfwInitHints.ns.menubar = value;
   478              return;
   479          case GLFW_X11_XCB_VULKAN_SURFACE:
   480              _glfwInitHints.x11.xcbVulkanSurface = value;
   481              return;
   482      }
   483  
   484      _glfwInputError(GLFW_INVALID_ENUM,
   485                      "Invalid init hint 0x%08X", hint);
   486  }
   487  
   488  GLFWAPI void glfwInitAllocator(const GLFWallocator* allocator)
   489  {
   490      if (allocator)
   491      {
   492          if (allocator->allocate && allocator->reallocate && allocator->deallocate)
   493              _glfwInitAllocator = *allocator;
   494          else
   495              _glfwInputError(GLFW_INVALID_VALUE, "Missing function in allocator");
   496      }
   497      else
   498          memset(&_glfwInitAllocator, 0, sizeof(GLFWallocator));
   499  }
   500  
   501  GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader)
   502  {
   503      _glfwInitHints.vulkanLoader = loader;
   504  }
   505  
   506  GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
   507  {
   508      if (major != NULL)
   509          *major = GLFW_VERSION_MAJOR;
   510      if (minor != NULL)
   511          *minor = GLFW_VERSION_MINOR;
   512      if (rev != NULL)
   513          *rev = GLFW_VERSION_REVISION;
   514  }
   515  
   516  GLFWAPI int glfwGetError(const char** description)
   517  {
   518      _GLFWerror* error;
   519      int code = GLFW_NO_ERROR;
   520  
   521      if (description)
   522          *description = NULL;
   523  
   524      if (_glfw.initialized)
   525          error = _glfwPlatformGetTls(&_glfw.errorSlot);
   526      else
   527          error = &_glfwMainThreadError;
   528  
   529      if (error)
   530      {
   531          code = error->code;
   532          error->code = GLFW_NO_ERROR;
   533          if (description && code)
   534              *description = error->description;
   535      }
   536  
   537      return code;
   538  }
   539  
   540  GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
   541  {
   542      _GLFW_SWAP(GLFWerrorfun, _glfwErrorCallback, cbfun);
   543      return cbfun;
   544  }
   545