GCC Code Coverage Report


Directory: ./
File: submodules/raylib/src/external/glfw/src/context.c
Date: 2023-09-29 04:53:15
Exec Total Coverage
Lines: 0 256 0.0%
Branches: 0 260 0.0%

Line Branch Exec Source
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
766