Atlas - context.c

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