123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- //========================================================================
- // GLFW 3.4 - www.glfw.org
- //------------------------------------------------------------------------
- // Copyright (c) 2002-2006 Marcus Geelnard
- // Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
- //
- // This software is provided 'as-is', without any express or implied
- // warranty. In no event will the authors be held liable for any damages
- // arising from the use of this software.
- //
- // Permission is granted to anyone to use this software for any purpose,
- // including commercial applications, and to alter it and redistribute it
- // freely, subject to the following restrictions:
- //
- // 1. The origin of this software must not be misrepresented; you must not
- // claim that you wrote the original software. If you use this software
- // in a product, an acknowledgment in the product documentation would
- // be appreciated but is not required.
- //
- // 2. Altered source versions must be plainly marked as such, and must not
- // be misrepresented as being the original software.
- //
- // 3. This notice may not be removed or altered from any source
- // distribution.
- //
- //========================================================================
- // Please use C89 style variable declarations in this file because VS 2010
- //========================================================================
- #include "internal.h"
- #include <assert.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdio.h>
- //////////////////////////////////////////////////////////////////////////
- ////// GLFW internal API //////
- //////////////////////////////////////////////////////////////////////////
- // Checks whether the desired context attributes are valid
- //
- // This function checks things like whether the specified client API version
- // exists and whether all relevant options have supported and non-conflicting
- // values
- //
- bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
- {
- if (ctxconfig->share)
- {
- if (ctxconfig->client == GLFW_NO_API ||
- ctxconfig->share->context.client == GLFW_NO_API)
- {
- _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
- return false;
- }
- }
- if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
- ctxconfig->source != GLFW_EGL_CONTEXT_API &&
- ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
- {
- _glfwInputError(GLFW_INVALID_ENUM,
- "Invalid context creation API 0x%08X",
- ctxconfig->source);
- return false;
- }
- if (ctxconfig->client != GLFW_NO_API &&
- ctxconfig->client != GLFW_OPENGL_API &&
- ctxconfig->client != GLFW_OPENGL_ES_API)
- {
- _glfwInputError(GLFW_INVALID_ENUM,
- "Invalid client API 0x%08X",
- ctxconfig->client);
- return false;
- }
- if (ctxconfig->client == GLFW_OPENGL_API)
- {
- if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
- (ctxconfig->major == 1 && ctxconfig->minor > 5) ||
- (ctxconfig->major == 2 && ctxconfig->minor > 1) ||
- (ctxconfig->major == 3 && ctxconfig->minor > 3))
- {
- // OpenGL 1.0 is the smallest valid version
- // OpenGL 1.x series ended with version 1.5
- // OpenGL 2.x series ended with version 2.1
- // OpenGL 3.x series ended with version 3.3
- // For now, let everything else through
- _glfwInputError(GLFW_INVALID_VALUE,
- "Invalid OpenGL version %i.%i",
- ctxconfig->major, ctxconfig->minor);
- return false;
- }
- if (ctxconfig->profile)
- {
- if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
- ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
- {
- _glfwInputError(GLFW_INVALID_ENUM,
- "Invalid OpenGL profile 0x%08X",
- ctxconfig->profile);
- return false;
- }
- if (ctxconfig->major <= 2 ||
- (ctxconfig->major == 3 && ctxconfig->minor < 2))
- {
- // Desktop OpenGL context profiles are only defined for version 3.2
- // and above
- _glfwInputError(GLFW_INVALID_VALUE,
- "Context profiles are only defined for OpenGL version 3.2 and above");
- return false;
- }
- }
- if (ctxconfig->forward && ctxconfig->major <= 2)
- {
- // Forward-compatible contexts are only defined for OpenGL version 3.0 and above
- _glfwInputError(GLFW_INVALID_VALUE,
- "Forward-compatibility is only defined for OpenGL version 3.0 and above");
- return false;
- }
- }
- else if (ctxconfig->client == GLFW_OPENGL_ES_API)
- {
- if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
- (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
- (ctxconfig->major == 2 && ctxconfig->minor > 0))
- {
- // OpenGL ES 1.0 is the smallest valid version
- // OpenGL ES 1.x series ended with version 1.1
- // OpenGL ES 2.x series ended with version 2.0
- // For now, let everything else through
- _glfwInputError(GLFW_INVALID_VALUE,
- "Invalid OpenGL ES version %i.%i",
- ctxconfig->major, ctxconfig->minor);
- return false;
- }
- }
- if (ctxconfig->robustness)
- {
- if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
- ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
- {
- _glfwInputError(GLFW_INVALID_ENUM,
- "Invalid context robustness mode 0x%08X",
- ctxconfig->robustness);
- return false;
- }
- }
- if (ctxconfig->release)
- {
- if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
- ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
- {
- _glfwInputError(GLFW_INVALID_ENUM,
- "Invalid context release behavior 0x%08X",
- ctxconfig->release);
- return false;
- }
- }
- return true;
- }
- // Retrieves the attributes of the current context
- //
- bool _glfwRefreshContextAttribs(_GLFWwindow* window,
- const _GLFWctxconfig* ctxconfig)
- {
- int i;
- _GLFWwindow* previous;
- const char* version;
- const char* prefixes[] =
- {
- "OpenGL ES-CM ",
- "OpenGL ES-CL ",
- "OpenGL ES ",
- NULL
- };
- window->context.source = ctxconfig->source;
- window->context.client = GLFW_OPENGL_API;
- previous = _glfwPlatformGetTls(&_glfw.contextSlot);
- glfwMakeContextCurrent((GLFWwindow*) window);
- window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
- window->context.getProcAddress("glGetIntegerv");
- window->context.GetString = (PFNGLGETSTRINGPROC)
- window->context.getProcAddress("glGetString");
- if (!window->context.GetIntegerv || !window->context.GetString)
- {
- _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
- glfwMakeContextCurrent((GLFWwindow*) previous);
- return false;
- }
- version = (const char*) window->context.GetString(GL_VERSION);
- if (!version)
- {
- if (ctxconfig->client == GLFW_OPENGL_API)
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "OpenGL version string retrieval is broken");
- }
- else
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "OpenGL ES version string retrieval is broken");
- }
- glfwMakeContextCurrent((GLFWwindow*) previous);
- return false;
- }
- for (i = 0; prefixes[i]; i++)
- {
- const size_t length = strlen(prefixes[i]);
- if (strncmp(version, prefixes[i], length) == 0)
- {
- version += length;
- window->context.client = GLFW_OPENGL_ES_API;
- break;
- }
- }
- if (sscanf(version, "%d.%d.%d",
- &window->context.major,
- &window->context.minor,
- &window->context.revision) < 1)
- {
- if (window->context.client == GLFW_OPENGL_API)
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "No version found in OpenGL version string");
- }
- else
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "No version found in OpenGL ES version string");
- }
- glfwMakeContextCurrent((GLFWwindow*) previous);
- return false;
- }
- if (window->context.major < ctxconfig->major ||
- (window->context.major == ctxconfig->major &&
- window->context.minor < ctxconfig->minor))
- {
- // The desired OpenGL version is greater than the actual version
- // This only happens if the machine lacks {GLX|WGL}_ARB_create_context
- // /and/ the user has requested an OpenGL version greater than 1.0
- // For API consistency, we emulate the behavior of the
- // {GLX|WGL}_ARB_create_context extension and fail here
- if (window->context.client == GLFW_OPENGL_API)
- {
- _glfwInputError(GLFW_VERSION_UNAVAILABLE,
- "Requested OpenGL version %i.%i, got version %i.%i",
- ctxconfig->major, ctxconfig->minor,
- window->context.major, window->context.minor);
- }
- else
- {
- _glfwInputError(GLFW_VERSION_UNAVAILABLE,
- "Requested OpenGL ES version %i.%i, got version %i.%i",
- ctxconfig->major, ctxconfig->minor,
- window->context.major, window->context.minor);
- }
- glfwMakeContextCurrent((GLFWwindow*) previous);
- return false;
- }
- if (window->context.major >= 3)
- {
- // OpenGL 3.0+ uses a different function for extension string retrieval
- // We cache it here instead of in glfwExtensionSupported mostly to alert
- // users as early as possible that their build may be broken
- window->context.GetStringi = (PFNGLGETSTRINGIPROC)
- window->context.getProcAddress("glGetStringi");
- if (!window->context.GetStringi)
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "Entry point retrieval is broken");
- glfwMakeContextCurrent((GLFWwindow*) previous);
- return false;
- }
- }
- if (window->context.client == GLFW_OPENGL_API)
- {
- // Read back context flags (OpenGL 3.0 and above)
- if (window->context.major >= 3)
- {
- GLint flags;
- window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
- if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
- window->context.forward = true;
- if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
- window->context.debug = true;
- else if (glfwExtensionSupported("GL_ARB_debug_output") &&
- ctxconfig->debug)
- {
- // HACK: This is a workaround for older drivers (pre KHR_debug)
- // not setting the debug bit in the context flags for
- // debug contexts
- window->context.debug = true;
- }
- if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)
- window->context.noerror = true;
- }
- // Read back OpenGL context profile (OpenGL 3.2 and above)
- if (window->context.major >= 4 ||
- (window->context.major == 3 && window->context.minor >= 2))
- {
- GLint mask;
- window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
- if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
- window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
- else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
- window->context.profile = GLFW_OPENGL_CORE_PROFILE;
- else if (glfwExtensionSupported("GL_ARB_compatibility"))
- {
- // HACK: This is a workaround for the compatibility profile bit
- // not being set in the context flags if an OpenGL 3.2+
- // context was created without having requested a specific
- // version
- window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
- }
- }
- // Read back robustness strategy
- if (glfwExtensionSupported("GL_ARB_robustness"))
- {
- // NOTE: We avoid using the context flags for detection, as they are
- // only present from 3.0 while the extension applies from 1.1
- GLint strategy;
- window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
- &strategy);
- if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
- window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
- else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
- window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
- }
- }
- else
- {
- // Read back robustness strategy
- if (glfwExtensionSupported("GL_EXT_robustness"))
- {
- // NOTE: The values of these constants match those of the OpenGL ARB
- // one, so we can reuse them here
- GLint strategy;
- window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
- &strategy);
- if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
- window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
- else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
- window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
- }
- }
- if (glfwExtensionSupported("GL_KHR_context_flush_control"))
- {
- GLint behavior;
- window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
- if (behavior == GL_NONE)
- window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
- else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
- window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
- }
- glfwMakeContextCurrent((GLFWwindow*) previous);
- return true;
- }
- // Searches an extension string for the specified extension
- //
- bool _glfwStringInExtensionString(const char* string, const char* extensions)
- {
- const char* start = extensions;
- for (;;)
- {
- const char* where;
- const char* terminator;
- where = strstr(start, string);
- if (!where)
- return false;
- terminator = where + strlen(string);
- if (where == start || *(where - 1) == ' ')
- {
- if (*terminator == ' ' || *terminator == '\0')
- break;
- }
- start = terminator;
- }
- return true;
- }
- //////////////////////////////////////////////////////////////////////////
- ////// GLFW public API //////
- //////////////////////////////////////////////////////////////////////////
- GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
- {
- _GLFW_REQUIRE_INIT();
- _GLFWwindow* window = (_GLFWwindow*) handle;
- _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
- if (window && window->context.client == GLFW_NO_API)
- {
- _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
- "Cannot make current with a window that has no OpenGL or OpenGL ES context");
- return;
- }
- if (previous)
- {
- if (!window || window->context.source != previous->context.source)
- previous->context.makeCurrent(NULL);
- }
- if (window)
- window->context.makeCurrent(window);
- }
- GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
- {
- _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
- return _glfwPlatformGetTls(&_glfw.contextSlot);
- }
- GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
- {
- _GLFWwindow* window = (_GLFWwindow*) handle;
- assert(window != NULL);
- _GLFW_REQUIRE_INIT();
- if (window->context.client == GLFW_NO_API)
- {
- _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
- "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
- return;
- }
- window->context.swapBuffers(window);
- #ifdef _GLFW_WAYLAND
- _glfwWaylandAfterBufferSwap(window);
- #endif
- }
- GLFWAPI void glfwSwapInterval(int interval)
- {
- _GLFWwindow* window;
- _GLFW_REQUIRE_INIT();
- window = _glfwPlatformGetTls(&_glfw.contextSlot);
- if (!window)
- {
- _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
- "Cannot set swap interval without a current OpenGL or OpenGL ES context");
- return;
- }
- window->context.swapInterval(interval);
- }
- GLFWAPI int glfwExtensionSupported(const char* extension)
- {
- _GLFWwindow* window;
- assert(extension != NULL);
- _GLFW_REQUIRE_INIT_OR_RETURN(false);
- window = _glfwPlatformGetTls(&_glfw.contextSlot);
- if (!window)
- {
- _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
- "Cannot query extension without a current OpenGL or OpenGL ES context");
- return false;
- }
- if (*extension == '\0')
- {
- _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
- return false;
- }
- if (window->context.major >= 3)
- {
- int i;
- GLint count;
- // Check if extension is in the modern OpenGL extensions string list
- window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count);
- for (i = 0; i < count; i++)
- {
- const char* en = (const char*)
- window->context.GetStringi(GL_EXTENSIONS, i);
- if (!en)
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "Extension string retrieval is broken");
- return false;
- }
- if (strcmp(en, extension) == 0)
- return true;
- }
- }
- else
- {
- // Check if extension is in the old style OpenGL extensions string
- const char* extensions = (const char*)
- window->context.GetString(GL_EXTENSIONS);
- if (!extensions)
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "Extension string retrieval is broken");
- return false;
- }
- if (_glfwStringInExtensionString(extension, extensions))
- return true;
- }
- // Check if extension is in the platform-specific string
- return window->context.extensionSupported(extension);
- }
- GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
- {
- _GLFWwindow* window;
- assert(procname != NULL);
- _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
- window = _glfwPlatformGetTls(&_glfw.contextSlot);
- if (!window)
- {
- _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
- "Cannot query entry point without a current OpenGL or OpenGL ES context");
- return NULL;
- }
- return window->context.getProcAddress(procname);
- }
|