00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "internal.h"
00029
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <limits.h>
00033 #include <stdio.h>
00034
00035
00036
00037
00038 static GLboolean parseVersionString(int* api, int* major, int* minor, int* rev)
00039 {
00040 int i;
00041 _GLFWwindow* window;
00042 const char* version;
00043 const char* prefixes[] =
00044 {
00045 "OpenGL ES-CM ",
00046 "OpenGL ES-CL ",
00047 "OpenGL ES ",
00048 NULL
00049 };
00050
00051 *api = GLFW_OPENGL_API;
00052
00053 window = _glfwPlatformGetCurrentContext();
00054
00055 version = (const char*) window->GetString(GL_VERSION);
00056 if (!version)
00057 {
00058 _glfwInputError(GLFW_PLATFORM_ERROR,
00059 "Failed to retrieve context version string");
00060 return GL_FALSE;
00061 }
00062
00063 for (i = 0; prefixes[i]; i++)
00064 {
00065 const size_t length = strlen(prefixes[i]);
00066
00067 if (strncmp(version, prefixes[i], length) == 0)
00068 {
00069 version += length;
00070 *api = GLFW_OPENGL_ES_API;
00071 break;
00072 }
00073 }
00074
00075 if (!sscanf(version, "%d.%d.%d", major, minor, rev))
00076 {
00077 _glfwInputError(GLFW_PLATFORM_ERROR,
00078 "No version found in context version string");
00079 return GL_FALSE;
00080 }
00081
00082 return GL_TRUE;
00083 }
00084
00085
00089
00090 GLboolean _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
00091 {
00092 if (ctxconfig->api != GLFW_OPENGL_API &&
00093 ctxconfig->api != GLFW_OPENGL_ES_API)
00094 {
00095 _glfwInputError(GLFW_INVALID_ENUM, "Invalid client API");
00096 return GL_FALSE;
00097 }
00098
00099 if (ctxconfig->api == GLFW_OPENGL_API)
00100 {
00101 if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
00102 (ctxconfig->major == 1 && ctxconfig->minor > 5) ||
00103 (ctxconfig->major == 2 && ctxconfig->minor > 1) ||
00104 (ctxconfig->major == 3 && ctxconfig->minor > 3))
00105 {
00106
00107
00108
00109
00110
00111
00112 _glfwInputError(GLFW_INVALID_VALUE,
00113 "Invalid OpenGL version %i.%i",
00114 ctxconfig->major, ctxconfig->minor);
00115 return GL_FALSE;
00116 }
00117
00118 if (ctxconfig->profile)
00119 {
00120 if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
00121 ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
00122 {
00123 _glfwInputError(GLFW_INVALID_ENUM,
00124 "Invalid OpenGL profile");
00125 return GL_FALSE;
00126 }
00127
00128 if (ctxconfig->major < 3 ||
00129 (ctxconfig->major == 3 && ctxconfig->minor < 2))
00130 {
00131
00132
00133
00134 _glfwInputError(GLFW_INVALID_VALUE,
00135 "Context profiles are only defined for OpenGL version 3.2 and above");
00136 return GL_FALSE;
00137 }
00138 }
00139
00140 if (ctxconfig->forward && ctxconfig->major < 3)
00141 {
00142
00143 _glfwInputError(GLFW_INVALID_VALUE,
00144 "Forward-compatibility is only defined for OpenGL version 3.0 and above");
00145 return GL_FALSE;
00146 }
00147 }
00148 else if (ctxconfig->api == GLFW_OPENGL_ES_API)
00149 {
00150 if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
00151 (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
00152 (ctxconfig->major == 2 && ctxconfig->minor > 0))
00153 {
00154
00155
00156
00157
00158
00159 _glfwInputError(GLFW_INVALID_VALUE,
00160 "Invalid OpenGL ES version %i.%i",
00161 ctxconfig->major, ctxconfig->minor);
00162 return GL_FALSE;
00163 }
00164 }
00165
00166 if (ctxconfig->robustness)
00167 {
00168 if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
00169 ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
00170 {
00171 _glfwInputError(GLFW_INVALID_ENUM,
00172 "Invalid context robustness mode");
00173 return GL_FALSE;
00174 }
00175 }
00176
00177 if (ctxconfig->release)
00178 {
00179 if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
00180 ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
00181 {
00182 _glfwInputError(GLFW_INVALID_ENUM,
00183 "Invalid context release behavior");
00184 return GL_FALSE;
00185 }
00186 }
00187
00188 return GL_TRUE;
00189 }
00190
00191 const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
00192 const _GLFWfbconfig* alternatives,
00193 unsigned int count)
00194 {
00195 unsigned int i;
00196 unsigned int missing, leastMissing = UINT_MAX;
00197 unsigned int colorDiff, leastColorDiff = UINT_MAX;
00198 unsigned int extraDiff, leastExtraDiff = UINT_MAX;
00199 const _GLFWfbconfig* current;
00200 const _GLFWfbconfig* closest = NULL;
00201
00202 for (i = 0; i < count; i++)
00203 {
00204 current = alternatives + i;
00205
00206 if (desired->stereo > 0 && current->stereo == 0)
00207 {
00208
00209 continue;
00210 }
00211
00212 if (desired->doublebuffer != current->doublebuffer)
00213 {
00214
00215 continue;
00216 }
00217
00218
00219 {
00220 missing = 0;
00221
00222 if (desired->alphaBits > 0 && current->alphaBits == 0)
00223 missing++;
00224
00225 if (desired->depthBits > 0 && current->depthBits == 0)
00226 missing++;
00227
00228 if (desired->stencilBits > 0 && current->stencilBits == 0)
00229 missing++;
00230
00231 if (desired->auxBuffers > 0 &&
00232 current->auxBuffers < desired->auxBuffers)
00233 {
00234 missing += desired->auxBuffers - current->auxBuffers;
00235 }
00236
00237 if (desired->samples > 0 && current->samples == 0)
00238 {
00239
00240
00241
00242 missing++;
00243 }
00244 }
00245
00246
00247
00248
00249
00250 {
00251 colorDiff = 0;
00252
00253 if (desired->redBits != GLFW_DONT_CARE)
00254 {
00255 colorDiff += (desired->redBits - current->redBits) *
00256 (desired->redBits - current->redBits);
00257 }
00258
00259 if (desired->greenBits != GLFW_DONT_CARE)
00260 {
00261 colorDiff += (desired->greenBits - current->greenBits) *
00262 (desired->greenBits - current->greenBits);
00263 }
00264
00265 if (desired->blueBits != GLFW_DONT_CARE)
00266 {
00267 colorDiff += (desired->blueBits - current->blueBits) *
00268 (desired->blueBits - current->blueBits);
00269 }
00270 }
00271
00272
00273 {
00274 extraDiff = 0;
00275
00276 if (desired->alphaBits != GLFW_DONT_CARE)
00277 {
00278 extraDiff += (desired->alphaBits - current->alphaBits) *
00279 (desired->alphaBits - current->alphaBits);
00280 }
00281
00282 if (desired->depthBits != GLFW_DONT_CARE)
00283 {
00284 extraDiff += (desired->depthBits - current->depthBits) *
00285 (desired->depthBits - current->depthBits);
00286 }
00287
00288 if (desired->stencilBits != GLFW_DONT_CARE)
00289 {
00290 extraDiff += (desired->stencilBits - current->stencilBits) *
00291 (desired->stencilBits - current->stencilBits);
00292 }
00293
00294 if (desired->accumRedBits != GLFW_DONT_CARE)
00295 {
00296 extraDiff += (desired->accumRedBits - current->accumRedBits) *
00297 (desired->accumRedBits - current->accumRedBits);
00298 }
00299
00300 if (desired->accumGreenBits != GLFW_DONT_CARE)
00301 {
00302 extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
00303 (desired->accumGreenBits - current->accumGreenBits);
00304 }
00305
00306 if (desired->accumBlueBits != GLFW_DONT_CARE)
00307 {
00308 extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
00309 (desired->accumBlueBits - current->accumBlueBits);
00310 }
00311
00312 if (desired->accumAlphaBits != GLFW_DONT_CARE)
00313 {
00314 extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
00315 (desired->accumAlphaBits - current->accumAlphaBits);
00316 }
00317
00318 if (desired->samples != GLFW_DONT_CARE)
00319 {
00320 extraDiff += (desired->samples - current->samples) *
00321 (desired->samples - current->samples);
00322 }
00323
00324 if (desired->sRGB && !current->sRGB)
00325 extraDiff++;
00326 }
00327
00328
00329
00330
00331
00332 if (missing < leastMissing)
00333 closest = current;
00334 else if (missing == leastMissing)
00335 {
00336 if ((colorDiff < leastColorDiff) ||
00337 (colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
00338 {
00339 closest = current;
00340 }
00341 }
00342
00343 if (current == closest)
00344 {
00345 leastMissing = missing;
00346 leastColorDiff = colorDiff;
00347 leastExtraDiff = extraDiff;
00348 }
00349 }
00350
00351 return closest;
00352 }
00353
00354 GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
00355 {
00356 _GLFWwindow* window = _glfwPlatformGetCurrentContext();
00357
00358 window->GetIntegerv = (PFNGLGETINTEGERVPROC) glfwGetProcAddress("glGetIntegerv");
00359 window->GetString = (PFNGLGETSTRINGPROC) glfwGetProcAddress("glGetString");
00360 window->Clear = (PFNGLCLEARPROC) glfwGetProcAddress("glClear");
00361
00362 if (!parseVersionString(&window->context.api,
00363 &window->context.major,
00364 &window->context.minor,
00365 &window->context.revision))
00366 {
00367 return GL_FALSE;
00368 }
00369
00370 #if defined(_GLFW_USE_OPENGL)
00371 if (window->context.major > 2)
00372 {
00373
00374
00375
00376
00377 window->GetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");
00378 if (!window->GetStringi)
00379 {
00380 _glfwInputError(GLFW_PLATFORM_ERROR,
00381 "Entry point retrieval is broken");
00382 return GL_FALSE;
00383 }
00384 }
00385
00386 if (window->context.api == GLFW_OPENGL_API)
00387 {
00388
00389 if (window->context.major >= 3)
00390 {
00391 GLint flags;
00392 window->GetIntegerv(GL_CONTEXT_FLAGS, &flags);
00393
00394 if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
00395 window->context.forward = GL_TRUE;
00396
00397 if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
00398 window->context.debug = GL_TRUE;
00399 else if (glfwExtensionSupported("GL_ARB_debug_output") &&
00400 ctxconfig->debug)
00401 {
00402
00403
00404
00405 window->context.debug = GL_TRUE;
00406 }
00407 }
00408
00409
00410 if (window->context.major > 3 ||
00411 (window->context.major == 3 && window->context.minor >= 2))
00412 {
00413 GLint mask;
00414 window->GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
00415
00416 if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
00417 window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
00418 else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
00419 window->context.profile = GLFW_OPENGL_CORE_PROFILE;
00420 else if (glfwExtensionSupported("GL_ARB_compatibility"))
00421 {
00422
00423
00424
00425
00426 window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
00427 }
00428 }
00429
00430
00431 if (glfwExtensionSupported("GL_ARB_robustness"))
00432 {
00433
00434
00435
00436 GLint strategy;
00437 window->GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
00438
00439 if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
00440 window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
00441 else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
00442 window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
00443 }
00444 }
00445 else
00446 {
00447
00448 if (glfwExtensionSupported("GL_EXT_robustness"))
00449 {
00450
00451
00452
00453 GLint strategy;
00454 window->GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
00455
00456 if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
00457 window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
00458 else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
00459 window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
00460 }
00461 }
00462
00463 if (glfwExtensionSupported("GL_KHR_context_flush_control"))
00464 {
00465 GLint behavior;
00466 window->GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
00467
00468 if (behavior == GL_NONE)
00469 window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
00470 else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
00471 window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
00472 }
00473 #endif // _GLFW_USE_OPENGL
00474
00475 return GL_TRUE;
00476 }
00477
00478 GLboolean _glfwIsValidContext(const _GLFWctxconfig* ctxconfig)
00479 {
00480 _GLFWwindow* window = _glfwPlatformGetCurrentContext();
00481
00482 if (window->context.major < ctxconfig->major ||
00483 (window->context.major == ctxconfig->major &&
00484 window->context.minor < ctxconfig->minor))
00485 {
00486
00487
00488
00489
00490
00491
00492
00493 _glfwInputError(GLFW_VERSION_UNAVAILABLE, NULL);
00494 return GL_FALSE;
00495 }
00496
00497 return GL_TRUE;
00498 }
00499
00500 int _glfwStringInExtensionString(const char* string, const char* extensions)
00501 {
00502 const char* start = extensions;
00503
00504 for (;;)
00505 {
00506 const char* where;
00507 const char* terminator;
00508
00509 where = strstr(start, string);
00510 if (!where)
00511 return GL_FALSE;
00512
00513 terminator = where + strlen(string);
00514 if (where == start || *(where - 1) == ' ')
00515 {
00516 if (*terminator == ' ' || *terminator == '\0')
00517 break;
00518 }
00519
00520 start = terminator;
00521 }
00522
00523 return GL_TRUE;
00524 }
00525
00526
00530
00531 GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
00532 {
00533 _GLFWwindow* window = (_GLFWwindow*) handle;
00534 _GLFW_REQUIRE_INIT();
00535 _glfwPlatformMakeContextCurrent(window);
00536 }
00537
00538 GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
00539 {
00540 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00541 return (GLFWwindow*) _glfwPlatformGetCurrentContext();
00542 }
00543
00544 GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
00545 {
00546 _GLFWwindow* window = (_GLFWwindow*) handle;
00547 _GLFW_REQUIRE_INIT();
00548 _glfwPlatformSwapBuffers(window);
00549 }
00550
00551 GLFWAPI void glfwSwapInterval(int interval)
00552 {
00553 _GLFW_REQUIRE_INIT();
00554
00555 if (!_glfwPlatformGetCurrentContext())
00556 {
00557 _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
00558 return;
00559 }
00560
00561 _glfwPlatformSwapInterval(interval);
00562 }
00563
00564 GLFWAPI int glfwExtensionSupported(const char* extension)
00565 {
00566 _GLFWwindow* window;
00567
00568 _GLFW_REQUIRE_INIT_OR_RETURN(GL_FALSE);
00569
00570 window = _glfwPlatformGetCurrentContext();
00571 if (!window)
00572 {
00573 _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
00574 return GL_FALSE;
00575 }
00576
00577 if (*extension == '\0')
00578 {
00579 _glfwInputError(GLFW_INVALID_VALUE, NULL);
00580 return GL_FALSE;
00581 }
00582
00583 #if defined(_GLFW_USE_OPENGL)
00584 if (window->context.major >= 3)
00585 {
00586 int i;
00587 GLint count;
00588
00589
00590
00591 window->GetIntegerv(GL_NUM_EXTENSIONS, &count);
00592
00593 for (i = 0; i < count; i++)
00594 {
00595 const char* en = (const char*) window->GetStringi(GL_EXTENSIONS, i);
00596 if (!en)
00597 {
00598 _glfwInputError(GLFW_PLATFORM_ERROR,
00599 "Failed to retrieve extension string %i", i);
00600 return GL_FALSE;
00601 }
00602
00603 if (strcmp(en, extension) == 0)
00604 return GL_TRUE;
00605 }
00606 }
00607 else
00608 #endif // _GLFW_USE_OPENGL
00609 {
00610
00611
00612 const char* extensions = (const char*) window->GetString(GL_EXTENSIONS);
00613 if (!extensions)
00614 {
00615 _glfwInputError(GLFW_PLATFORM_ERROR,
00616 "Failed to retrieve extension string");
00617 return GL_FALSE;
00618 }
00619
00620 if (_glfwStringInExtensionString(extension, extensions))
00621 return GL_TRUE;
00622 }
00623
00624
00625 return _glfwPlatformExtensionSupported(extension);
00626 }
00627
00628 GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
00629 {
00630 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
00631
00632 if (!_glfwPlatformGetCurrentContext())
00633 {
00634 _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
00635 return NULL;
00636 }
00637
00638 return _glfwPlatformGetProcAddress(procname);
00639 }
00640