github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/context.c (about) 1 //======================================================================== 2 // GLFW 3.4 - 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 // 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 <stdio.h> 34 #include <string.h> 35 #include <limits.h> 36 #include <stdio.h> 37 38 39 ////////////////////////////////////////////////////////////////////////// 40 ////// GLFW internal API ////// 41 ////////////////////////////////////////////////////////////////////////// 42 43 // Checks whether the desired context attributes are valid 44 // 45 // This function checks things like whether the specified client API version 46 // exists and whether all relevant options have supported and non-conflicting 47 // values 48 // 49 GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) 50 { 51 if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API && 52 ctxconfig->source != GLFW_EGL_CONTEXT_API && 53 ctxconfig->source != GLFW_OSMESA_CONTEXT_API) 54 { 55 _glfwInputError(GLFW_INVALID_ENUM, 56 "Invalid context creation API 0x%08X", 57 ctxconfig->source); 58 return GLFW_FALSE; 59 } 60 61 if (ctxconfig->client != GLFW_NO_API && 62 ctxconfig->client != GLFW_OPENGL_API && 63 ctxconfig->client != GLFW_OPENGL_ES_API) 64 { 65 _glfwInputError(GLFW_INVALID_ENUM, 66 "Invalid client API 0x%08X", 67 ctxconfig->client); 68 return GLFW_FALSE; 69 } 70 71 if (ctxconfig->share) 72 { 73 if (ctxconfig->client == GLFW_NO_API || 74 ctxconfig->share->context.client == GLFW_NO_API) 75 { 76 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); 77 return GLFW_FALSE; 78 } 79 80 if (ctxconfig->source != ctxconfig->share->context.source) 81 { 82 _glfwInputError(GLFW_INVALID_ENUM, 83 "Context creation APIs do not match between contexts"); 84 return GLFW_FALSE; 85 } 86 } 87 88 if (ctxconfig->client == GLFW_OPENGL_API) 89 { 90 if ((ctxconfig->major < 1 || ctxconfig->minor < 0) || 91 (ctxconfig->major == 1 && ctxconfig->minor > 5) || 92 (ctxconfig->major == 2 && ctxconfig->minor > 1) || 93 (ctxconfig->major == 3 && ctxconfig->minor > 3)) 94 { 95 // OpenGL 1.0 is the smallest valid version 96 // OpenGL 1.x series ended with version 1.5 97 // OpenGL 2.x series ended with version 2.1 98 // OpenGL 3.x series ended with version 3.3 99 // For now, let everything else through 100 101 _glfwInputError(GLFW_INVALID_VALUE, 102 "Invalid OpenGL version %i.%i", 103 ctxconfig->major, ctxconfig->minor); 104 return GLFW_FALSE; 105 } 106 107 if (ctxconfig->profile) 108 { 109 if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE && 110 ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE) 111 { 112 _glfwInputError(GLFW_INVALID_ENUM, 113 "Invalid OpenGL profile 0x%08X", 114 ctxconfig->profile); 115 return GLFW_FALSE; 116 } 117 118 if (ctxconfig->major <= 2 || 119 (ctxconfig->major == 3 && ctxconfig->minor < 2)) 120 { 121 // Desktop OpenGL context profiles are only defined for version 3.2 122 // and above 123 124 _glfwInputError(GLFW_INVALID_VALUE, 125 "Context profiles are only defined for OpenGL version 3.2 and above"); 126 return GLFW_FALSE; 127 } 128 } 129 130 if (ctxconfig->forward && ctxconfig->major <= 2) 131 { 132 // Forward-compatible contexts are only defined for OpenGL version 3.0 and above 133 _glfwInputError(GLFW_INVALID_VALUE, 134 "Forward-compatibility is only defined for OpenGL version 3.0 and above"); 135 return GLFW_FALSE; 136 } 137 } 138 else if (ctxconfig->client == GLFW_OPENGL_ES_API) 139 { 140 if (ctxconfig->major < 1 || ctxconfig->minor < 0 || 141 (ctxconfig->major == 1 && ctxconfig->minor > 1) || 142 (ctxconfig->major == 2 && ctxconfig->minor > 0)) 143 { 144 // OpenGL ES 1.0 is the smallest valid version 145 // OpenGL ES 1.x series ended with version 1.1 146 // OpenGL ES 2.x series ended with version 2.0 147 // For now, let everything else through 148 149 _glfwInputError(GLFW_INVALID_VALUE, 150 "Invalid OpenGL ES version %i.%i", 151 ctxconfig->major, ctxconfig->minor); 152 return GLFW_FALSE; 153 } 154 } 155 156 if (ctxconfig->robustness) 157 { 158 if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION && 159 ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET) 160 { 161 _glfwInputError(GLFW_INVALID_ENUM, 162 "Invalid context robustness mode 0x%08X", 163 ctxconfig->robustness); 164 return GLFW_FALSE; 165 } 166 } 167 168 if (ctxconfig->release) 169 { 170 if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE && 171 ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH) 172 { 173 _glfwInputError(GLFW_INVALID_ENUM, 174 "Invalid context release behavior 0x%08X", 175 ctxconfig->release); 176 return GLFW_FALSE; 177 } 178 } 179 180 return GLFW_TRUE; 181 } 182 183 // Chooses the framebuffer config that best matches the desired one 184 // 185 const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, 186 const _GLFWfbconfig* alternatives, 187 unsigned int count) 188 { 189 unsigned int i; 190 unsigned int missing, leastMissing = UINT_MAX; 191 unsigned int colorDiff, leastColorDiff = UINT_MAX; 192 unsigned int extraDiff, leastExtraDiff = UINT_MAX; 193 const _GLFWfbconfig* current; 194 const _GLFWfbconfig* closest = NULL; 195 196 for (i = 0; i < count; i++) 197 { 198 current = alternatives + i; 199 200 if (desired->stereo > 0 && current->stereo == 0) 201 { 202 // Stereo is a hard constraint 203 continue; 204 } 205 206 // Count number of missing buffers 207 { 208 missing = 0; 209 210 if (desired->alphaBits > 0 && current->alphaBits == 0) 211 missing++; 212 213 if (desired->depthBits > 0 && current->depthBits == 0) 214 missing++; 215 216 if (desired->stencilBits > 0 && current->stencilBits == 0) 217 missing++; 218 219 if (desired->auxBuffers > 0 && 220 current->auxBuffers < desired->auxBuffers) 221 { 222 missing += desired->auxBuffers - current->auxBuffers; 223 } 224 225 if (desired->samples > 0 && current->samples == 0) 226 { 227 // Technically, several multisampling buffers could be 228 // involved, but that's a lower level implementation detail and 229 // not important to us here, so we count them as one 230 missing++; 231 } 232 233 if (desired->transparent != current->transparent) 234 missing++; 235 } 236 237 // These polynomials make many small channel size differences matter 238 // less than one large channel size difference 239 240 // Calculate color channel size difference value 241 { 242 colorDiff = 0; 243 244 if (desired->redBits != GLFW_DONT_CARE) 245 { 246 colorDiff += (desired->redBits - current->redBits) * 247 (desired->redBits - current->redBits); 248 } 249 250 if (desired->greenBits != GLFW_DONT_CARE) 251 { 252 colorDiff += (desired->greenBits - current->greenBits) * 253 (desired->greenBits - current->greenBits); 254 } 255 256 if (desired->blueBits != GLFW_DONT_CARE) 257 { 258 colorDiff += (desired->blueBits - current->blueBits) * 259 (desired->blueBits - current->blueBits); 260 } 261 } 262 263 // Calculate non-color channel size difference value 264 { 265 extraDiff = 0; 266 267 if (desired->alphaBits != GLFW_DONT_CARE) 268 { 269 extraDiff += (desired->alphaBits - current->alphaBits) * 270 (desired->alphaBits - current->alphaBits); 271 } 272 273 if (desired->depthBits != GLFW_DONT_CARE) 274 { 275 extraDiff += (desired->depthBits - current->depthBits) * 276 (desired->depthBits - current->depthBits); 277 } 278 279 if (desired->stencilBits != GLFW_DONT_CARE) 280 { 281 extraDiff += (desired->stencilBits - current->stencilBits) * 282 (desired->stencilBits - current->stencilBits); 283 } 284 285 if (desired->accumRedBits != GLFW_DONT_CARE) 286 { 287 extraDiff += (desired->accumRedBits - current->accumRedBits) * 288 (desired->accumRedBits - current->accumRedBits); 289 } 290 291 if (desired->accumGreenBits != GLFW_DONT_CARE) 292 { 293 extraDiff += (desired->accumGreenBits - current->accumGreenBits) * 294 (desired->accumGreenBits - current->accumGreenBits); 295 } 296 297 if (desired->accumBlueBits != GLFW_DONT_CARE) 298 { 299 extraDiff += (desired->accumBlueBits - current->accumBlueBits) * 300 (desired->accumBlueBits - current->accumBlueBits); 301 } 302 303 if (desired->accumAlphaBits != GLFW_DONT_CARE) 304 { 305 extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) * 306 (desired->accumAlphaBits - current->accumAlphaBits); 307 } 308 309 if (desired->samples != GLFW_DONT_CARE) 310 { 311 extraDiff += (desired->samples - current->samples) * 312 (desired->samples - current->samples); 313 } 314 315 if (desired->sRGB && !current->sRGB) 316 extraDiff++; 317 } 318 319 // Figure out if the current one is better than the best one found so far 320 // Least number of missing buffers is the most important heuristic, 321 // then color buffer size match and lastly size match for other buffers 322 323 if (missing < leastMissing) 324 closest = current; 325 else if (missing == leastMissing) 326 { 327 if ((colorDiff < leastColorDiff) || 328 (colorDiff == leastColorDiff && extraDiff < leastExtraDiff)) 329 { 330 closest = current; 331 } 332 } 333 334 if (current == closest) 335 { 336 leastMissing = missing; 337 leastColorDiff = colorDiff; 338 leastExtraDiff = extraDiff; 339 } 340 } 341 342 return closest; 343 } 344 345 // Retrieves the attributes of the current context 346 // 347 GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window, 348 const _GLFWctxconfig* ctxconfig) 349 { 350 int i; 351 _GLFWwindow* previous; 352 const char* version; 353 const char* prefixes[] = 354 { 355 "OpenGL ES-CM ", 356 "OpenGL ES-CL ", 357 "OpenGL ES ", 358 NULL 359 }; 360 361 window->context.source = ctxconfig->source; 362 window->context.client = GLFW_OPENGL_API; 363 364 previous = _glfwPlatformGetTls(&_glfw.contextSlot); 365 glfwMakeContextCurrent((GLFWwindow*) window); 366 367 window->context.GetIntegerv = (PFNGLGETINTEGERVPROC) 368 window->context.getProcAddress("glGetIntegerv"); 369 window->context.GetString = (PFNGLGETSTRINGPROC) 370 window->context.getProcAddress("glGetString"); 371 if (!window->context.GetIntegerv || !window->context.GetString) 372 { 373 _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken"); 374 glfwMakeContextCurrent((GLFWwindow*) previous); 375 return GLFW_FALSE; 376 } 377 378 version = (const char*) window->context.GetString(GL_VERSION); 379 if (!version) 380 { 381 if (ctxconfig->client == GLFW_OPENGL_API) 382 { 383 _glfwInputError(GLFW_PLATFORM_ERROR, 384 "OpenGL version string retrieval is broken"); 385 } 386 else 387 { 388 _glfwInputError(GLFW_PLATFORM_ERROR, 389 "OpenGL ES version string retrieval is broken"); 390 } 391 392 glfwMakeContextCurrent((GLFWwindow*) previous); 393 return GLFW_FALSE; 394 } 395 396 for (i = 0; prefixes[i]; i++) 397 { 398 const size_t length = strlen(prefixes[i]); 399 400 if (strncmp(version, prefixes[i], length) == 0) 401 { 402 version += length; 403 window->context.client = GLFW_OPENGL_ES_API; 404 break; 405 } 406 } 407 408 if (!sscanf(version, "%d.%d.%d", 409 &window->context.major, 410 &window->context.minor, 411 &window->context.revision)) 412 { 413 if (window->context.client == GLFW_OPENGL_API) 414 { 415 _glfwInputError(GLFW_PLATFORM_ERROR, 416 "No version found in OpenGL version string"); 417 } 418 else 419 { 420 _glfwInputError(GLFW_PLATFORM_ERROR, 421 "No version found in OpenGL ES version string"); 422 } 423 424 glfwMakeContextCurrent((GLFWwindow*) previous); 425 return GLFW_FALSE; 426 } 427 428 if (window->context.major < ctxconfig->major || 429 (window->context.major == ctxconfig->major && 430 window->context.minor < ctxconfig->minor)) 431 { 432 // The desired OpenGL version is greater than the actual version 433 // This only happens if the machine lacks {GLX|WGL}_ARB_create_context 434 // /and/ the user has requested an OpenGL version greater than 1.0 435 436 // For API consistency, we emulate the behavior of the 437 // {GLX|WGL}_ARB_create_context extension and fail here 438 439 if (window->context.client == GLFW_OPENGL_API) 440 { 441 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 442 "Requested OpenGL version %i.%i, got version %i.%i", 443 ctxconfig->major, ctxconfig->minor, 444 window->context.major, window->context.minor); 445 } 446 else 447 { 448 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 449 "Requested OpenGL ES version %i.%i, got version %i.%i", 450 ctxconfig->major, ctxconfig->minor, 451 window->context.major, window->context.minor); 452 } 453 454 glfwMakeContextCurrent((GLFWwindow*) previous); 455 return GLFW_FALSE; 456 } 457 458 if (window->context.major >= 3) 459 { 460 // OpenGL 3.0+ uses a different function for extension string retrieval 461 // We cache it here instead of in glfwExtensionSupported mostly to alert 462 // users as early as possible that their build may be broken 463 464 window->context.GetStringi = (PFNGLGETSTRINGIPROC) 465 window->context.getProcAddress("glGetStringi"); 466 if (!window->context.GetStringi) 467 { 468 _glfwInputError(GLFW_PLATFORM_ERROR, 469 "Entry point retrieval is broken"); 470 glfwMakeContextCurrent((GLFWwindow*) previous); 471 return GLFW_FALSE; 472 } 473 } 474 475 if (window->context.client == GLFW_OPENGL_API) 476 { 477 // Read back context flags (OpenGL 3.0 and above) 478 if (window->context.major >= 3) 479 { 480 GLint flags; 481 window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags); 482 483 if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) 484 window->context.forward = GLFW_TRUE; 485 486 if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) 487 window->context.debug = GLFW_TRUE; 488 else if (glfwExtensionSupported("GL_ARB_debug_output") && 489 ctxconfig->debug) 490 { 491 // HACK: This is a workaround for older drivers (pre KHR_debug) 492 // not setting the debug bit in the context flags for 493 // debug contexts 494 window->context.debug = GLFW_TRUE; 495 } 496 497 if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR) 498 window->context.noerror = GLFW_TRUE; 499 } 500 501 // Read back OpenGL context profile (OpenGL 3.2 and above) 502 if (window->context.major >= 4 || 503 (window->context.major == 3 && window->context.minor >= 2)) 504 { 505 GLint mask; 506 window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); 507 508 if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) 509 window->context.profile = GLFW_OPENGL_COMPAT_PROFILE; 510 else if (mask & GL_CONTEXT_CORE_PROFILE_BIT) 511 window->context.profile = GLFW_OPENGL_CORE_PROFILE; 512 else if (glfwExtensionSupported("GL_ARB_compatibility")) 513 { 514 // HACK: This is a workaround for the compatibility profile bit 515 // not being set in the context flags if an OpenGL 3.2+ 516 // context was created without having requested a specific 517 // version 518 window->context.profile = GLFW_OPENGL_COMPAT_PROFILE; 519 } 520 } 521 522 // Read back robustness strategy 523 if (glfwExtensionSupported("GL_ARB_robustness")) 524 { 525 // NOTE: We avoid using the context flags for detection, as they are 526 // only present from 3.0 while the extension applies from 1.1 527 528 GLint strategy; 529 window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, 530 &strategy); 531 532 if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB) 533 window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET; 534 else if (strategy == GL_NO_RESET_NOTIFICATION_ARB) 535 window->context.robustness = GLFW_NO_RESET_NOTIFICATION; 536 } 537 } 538 else 539 { 540 // Read back robustness strategy 541 if (glfwExtensionSupported("GL_EXT_robustness")) 542 { 543 // NOTE: The values of these constants match those of the OpenGL ARB 544 // one, so we can reuse them here 545 546 GLint strategy; 547 window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, 548 &strategy); 549 550 if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB) 551 window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET; 552 else if (strategy == GL_NO_RESET_NOTIFICATION_ARB) 553 window->context.robustness = GLFW_NO_RESET_NOTIFICATION; 554 } 555 } 556 557 if (glfwExtensionSupported("GL_KHR_context_flush_control")) 558 { 559 GLint behavior; 560 window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior); 561 562 if (behavior == GL_NONE) 563 window->context.release = GLFW_RELEASE_BEHAVIOR_NONE; 564 else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH) 565 window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH; 566 } 567 568 // Clearing the front buffer to black to avoid garbage pixels left over from 569 // previous uses of our bit of VRAM 570 { 571 PFNGLCLEARPROC glClear = (PFNGLCLEARPROC) 572 window->context.getProcAddress("glClear"); 573 glClear(GL_COLOR_BUFFER_BIT); 574 575 if (window->doublebuffer) 576 window->context.swapBuffers(window); 577 } 578 579 glfwMakeContextCurrent((GLFWwindow*) previous); 580 return GLFW_TRUE; 581 } 582 583 // Searches an extension string for the specified extension 584 // 585 GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions) 586 { 587 const char* start = extensions; 588 589 for (;;) 590 { 591 const char* where; 592 const char* terminator; 593 594 where = strstr(start, string); 595 if (!where) 596 return GLFW_FALSE; 597 598 terminator = where + strlen(string); 599 if (where == start || *(where - 1) == ' ') 600 { 601 if (*terminator == ' ' || *terminator == '\0') 602 break; 603 } 604 605 start = terminator; 606 } 607 608 return GLFW_TRUE; 609 } 610 611 612 ////////////////////////////////////////////////////////////////////////// 613 ////// GLFW public API ////// 614 ////////////////////////////////////////////////////////////////////////// 615 616 GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) 617 { 618 _GLFWwindow* window = (_GLFWwindow*) handle; 619 _GLFWwindow* previous; 620 621 _GLFW_REQUIRE_INIT(); 622 623 previous = _glfwPlatformGetTls(&_glfw.contextSlot); 624 625 if (window && window->context.client == GLFW_NO_API) 626 { 627 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, 628 "Cannot make current with a window that has no OpenGL or OpenGL ES context"); 629 return; 630 } 631 632 if (previous) 633 { 634 if (!window || window->context.source != previous->context.source) 635 previous->context.makeCurrent(NULL); 636 } 637 638 if (window) 639 window->context.makeCurrent(window); 640 } 641 642 GLFWAPI GLFWwindow* glfwGetCurrentContext(void) 643 { 644 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 645 return _glfwPlatformGetTls(&_glfw.contextSlot); 646 } 647 648 GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) 649 { 650 _GLFWwindow* window = (_GLFWwindow*) handle; 651 assert(window != NULL); 652 653 _GLFW_REQUIRE_INIT(); 654 655 if (window->context.client == GLFW_NO_API) 656 { 657 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, 658 "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context"); 659 return; 660 } 661 662 window->context.swapBuffers(window); 663 } 664 665 GLFWAPI void glfwSwapInterval(int interval) 666 { 667 _GLFWwindow* window; 668 669 _GLFW_REQUIRE_INIT(); 670 671 window = _glfwPlatformGetTls(&_glfw.contextSlot); 672 if (!window) 673 { 674 _glfwInputError(GLFW_NO_CURRENT_CONTEXT, 675 "Cannot set swap interval without a current OpenGL or OpenGL ES context"); 676 return; 677 } 678 679 window->context.swapInterval(interval); 680 } 681 682 GLFWAPI int glfwExtensionSupported(const char* extension) 683 { 684 _GLFWwindow* window; 685 assert(extension != NULL); 686 687 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 688 689 window = _glfwPlatformGetTls(&_glfw.contextSlot); 690 if (!window) 691 { 692 _glfwInputError(GLFW_NO_CURRENT_CONTEXT, 693 "Cannot query extension without a current OpenGL or OpenGL ES context"); 694 return GLFW_FALSE; 695 } 696 697 if (*extension == '\0') 698 { 699 _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string"); 700 return GLFW_FALSE; 701 } 702 703 if (window->context.major >= 3) 704 { 705 int i; 706 GLint count; 707 708 // Check if extension is in the modern OpenGL extensions string list 709 710 window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count); 711 712 for (i = 0; i < count; i++) 713 { 714 const char* en = (const char*) 715 window->context.GetStringi(GL_EXTENSIONS, i); 716 if (!en) 717 { 718 _glfwInputError(GLFW_PLATFORM_ERROR, 719 "Extension string retrieval is broken"); 720 return GLFW_FALSE; 721 } 722 723 if (strcmp(en, extension) == 0) 724 return GLFW_TRUE; 725 } 726 } 727 else 728 { 729 // Check if extension is in the old style OpenGL extensions string 730 731 const char* extensions = (const char*) 732 window->context.GetString(GL_EXTENSIONS); 733 if (!extensions) 734 { 735 _glfwInputError(GLFW_PLATFORM_ERROR, 736 "Extension string retrieval is broken"); 737 return GLFW_FALSE; 738 } 739 740 if (_glfwStringInExtensionString(extension, extensions)) 741 return GLFW_TRUE; 742 } 743 744 // Check if extension is in the platform-specific string 745 return window->context.extensionSupported(extension); 746 } 747 748 GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) 749 { 750 _GLFWwindow* window; 751 assert(procname != NULL); 752 753 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 754 755 window = _glfwPlatformGetTls(&_glfw.contextSlot); 756 if (!window) 757 { 758 _glfwInputError(GLFW_NO_CURRENT_CONTEXT, 759 "Cannot query entry point without a current OpenGL or OpenGL ES context"); 760 return NULL; 761 } 762 763 return window->context.getProcAddress(procname); 764 } 765