From 948be592bead5a666174d452a384ab813b778ab8 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 27 Dec 2012 18:26:51 +0100 Subject: [PATCH 1/7] Documented callback clearing at window destruction time. --- include/GL/glfw3.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 9ceae2c2..bd968a6c 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -1212,6 +1212,10 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height, int mode, const char* * @note If the window's context is current on the main thread, it is * detached before being destroyed. * + * @note On calling this function, no further callbacks will be called for + * the specified window, even if their associated events occur during window + * destruction. + * * @warning The window's context must not be current on any other thread. * * @sa glfwCreateWindow From 0a7a57b74fe8364e660c9350693b2b6fb265ce54 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 30 Dec 2012 00:45:22 +0100 Subject: [PATCH 2/7] Moved internal API functions to correct section. --- src/nsgl_context.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 66518140..caf4353a 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -39,7 +39,7 @@ static pthread_key_t _glfwCurrentTLS; ////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// +////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// //======================================================================== @@ -69,6 +69,10 @@ void _glfwTerminateOpenGL(void) } +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + //======================================================================== // Make the OpenGL context associated with the specified window current //======================================================================== From a8403c10d300e43fdcd6e311c287733264c35ee8 Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 30 Dec 2012 00:58:18 +0100 Subject: [PATCH 3/7] Moved NSGL context creation to proper module. --- src/cocoa_platform.h | 4 + src/cocoa_window.m | 168 +---------------------------------------- src/nsgl_context.m | 174 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+), 166 deletions(-) diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 21589a69..3a1c4d26 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -109,5 +109,9 @@ void _glfwRestoreVideoMode(void); // OpenGL support int _glfwInitOpenGL(void); void _glfwTerminateOpenGL(void); +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig); +void _glfwDestroyContext(_GLFWwindow* window); #endif // _cocoa_platform_h_ diff --git a/src/cocoa_window.m b/src/cocoa_window.m index aa28d241..fc090119 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -711,166 +711,6 @@ static GLboolean createWindow(_GLFWwindow* window, } -//======================================================================== -// Create the OpenGL context -//======================================================================== - -static GLboolean createContext(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) -{ - unsigned int attributeCount = 0; - - // Mac OS X needs non-zero color size, so set resonable values - int colorBits = fbconfig->redBits + fbconfig->greenBits + fbconfig->blueBits; - if (colorBits == 0) - colorBits = 24; - else if (colorBits < 15) - colorBits = 15; - - if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: This API does not support OpenGL ES"); - return GL_FALSE; - } - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - // Fail if any OpenGL version above 2.1 other than 3.2 was requested - if (wndconfig->glMajor > 3 || - (wndconfig->glMajor == 3 && wndconfig->glMinor != 2)) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: The targeted version of Mac OS X does not " - "support any OpenGL version above 2.1 except 3.2"); - return GL_FALSE; - } - - if (wndconfig->glMajor > 2) - { - if (!wndconfig->glForward) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: The targeted version of Mac OS X only " - "supports OpenGL 3.2 contexts if they are " - "forward-compatible"); - return GL_FALSE; - } - - if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: The targeted version of Mac OS X only " - "supports OpenGL 3.2 contexts if they use the " - "core profile"); - return GL_FALSE; - } - } -#else - // Fail if OpenGL 3.0 or above was requested - if (wndconfig->glMajor > 2) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: The targeted version of Mac OS X does not " - "support OpenGL version 3.0 or above"); - return GL_FALSE; - } -#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ - - // Fail if a robustness strategy was requested - if (wndconfig->glRobustness) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "NSOpenGL: Mac OS X does not support OpenGL robustness " - "strategies"); - return GL_FALSE; - } - -#define ADD_ATTR(x) { attributes[attributeCount++] = x; } -#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); } - - // Arbitrary array size here - NSOpenGLPixelFormatAttribute attributes[40]; - - ADD_ATTR(NSOpenGLPFADoubleBuffer); - - if (wndconfig->mode == GLFW_FULLSCREEN) - { - ADD_ATTR(NSOpenGLPFANoRecovery); - ADD_ATTR2(NSOpenGLPFAScreenMask, - CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID())); - } - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - if (wndconfig->glMajor > 2) - ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); -#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ - - ADD_ATTR2(NSOpenGLPFAColorSize, colorBits); - - if (fbconfig->alphaBits > 0) - ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); - - if (fbconfig->depthBits > 0) - ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits); - - if (fbconfig->stencilBits > 0) - ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits); - - int accumBits = fbconfig->accumRedBits + fbconfig->accumGreenBits + - fbconfig->accumBlueBits + fbconfig->accumAlphaBits; - - if (accumBits > 0) - ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits); - - if (fbconfig->auxBuffers > 0) - ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); - - if (fbconfig->stereo) - ADD_ATTR(NSOpenGLPFAStereo); - - if (fbconfig->samples > 0) - { - ADD_ATTR2(NSOpenGLPFASampleBuffers, 1); - ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples); - } - - // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB - // frambuffer, so there's no need (and no way) to request it - - ADD_ATTR(0); - -#undef ADD_ATTR -#undef ADD_ATTR2 - - window->NSGL.pixelFormat = - [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - if (window->NSGL.pixelFormat == nil) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "NSOpenGL: Failed to create OpenGL pixel format"); - return GL_FALSE; - } - - NSOpenGLContext* share = NULL; - - if (wndconfig->share) - share = wndconfig->share->NSGL.context; - - window->NSGL.context = - [[NSOpenGLContext alloc] initWithFormat:window->NSGL.pixelFormat - shareContext:share]; - if (window->NSGL.context == nil) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "NSOpenGL: Failed to create OpenGL context"); - return GL_FALSE; - } - - return GL_TRUE; -} - - ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -923,7 +763,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, if (!createWindow(window, wndconfig)) return GL_FALSE; - if (!createContext(window, wndconfig, fbconfig)) + if (!_glfwCreateContext(window, wndconfig, fbconfig)) return GL_FALSE; [window->NSGL.context setView:[window->NS.object contentView]]; @@ -968,11 +808,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) _glfwRestoreVideoMode(); } - [window->NSGL.pixelFormat release]; - window->NSGL.pixelFormat = nil; - - [window->NSGL.context release]; - window->NSGL.context = nil; + _glfwDestroyContext(window); [window->NS.object setDelegate:nil]; [window->NS.delegate release]; diff --git a/src/nsgl_context.m b/src/nsgl_context.m index caf4353a..315c39d5 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -69,6 +69,180 @@ void _glfwTerminateOpenGL(void) } +//======================================================================== +// Create the OpenGL context +//======================================================================== + +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) +{ + unsigned int attributeCount = 0; + + // Mac OS X needs non-zero color size, so set resonable values + int colorBits = fbconfig->redBits + fbconfig->greenBits + fbconfig->blueBits; + if (colorBits == 0) + colorBits = 24; + else if (colorBits < 15) + colorBits = 15; + + if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: This API does not support OpenGL ES"); + return GL_FALSE; + } + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + // Fail if any OpenGL version above 2.1 other than 3.2 was requested + if (wndconfig->glMajor > 3 || + (wndconfig->glMajor == 3 && wndconfig->glMinor != 2)) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: The targeted version of Mac OS X does not " + "support any OpenGL version above 2.1 except 3.2"); + return GL_FALSE; + } + + if (wndconfig->glMajor > 2) + { + if (!wndconfig->glForward) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: The targeted version of Mac OS X only " + "supports OpenGL 3.2 contexts if they are " + "forward-compatible"); + return GL_FALSE; + } + + if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: The targeted version of Mac OS X only " + "supports OpenGL 3.2 contexts if they use the " + "core profile"); + return GL_FALSE; + } + } +#else + // Fail if OpenGL 3.0 or above was requested + if (wndconfig->glMajor > 2) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: The targeted version of Mac OS X does not " + "support OpenGL version 3.0 or above"); + return GL_FALSE; + } +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ + + // Fail if a robustness strategy was requested + if (wndconfig->glRobustness) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, + "NSOpenGL: Mac OS X does not support OpenGL robustness " + "strategies"); + return GL_FALSE; + } + +#define ADD_ATTR(x) { attributes[attributeCount++] = x; } +#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); } + + // Arbitrary array size here + NSOpenGLPixelFormatAttribute attributes[40]; + + ADD_ATTR(NSOpenGLPFADoubleBuffer); + + if (wndconfig->mode == GLFW_FULLSCREEN) + { + ADD_ATTR(NSOpenGLPFANoRecovery); + ADD_ATTR2(NSOpenGLPFAScreenMask, + CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID())); + } + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if (wndconfig->glMajor > 2) + ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ + + ADD_ATTR2(NSOpenGLPFAColorSize, colorBits); + + if (fbconfig->alphaBits > 0) + ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits); + + if (fbconfig->depthBits > 0) + ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits); + + if (fbconfig->stencilBits > 0) + ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits); + + int accumBits = fbconfig->accumRedBits + fbconfig->accumGreenBits + + fbconfig->accumBlueBits + fbconfig->accumAlphaBits; + + if (accumBits > 0) + ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits); + + if (fbconfig->auxBuffers > 0) + ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers); + + if (fbconfig->stereo) + ADD_ATTR(NSOpenGLPFAStereo); + + if (fbconfig->samples > 0) + { + ADD_ATTR2(NSOpenGLPFASampleBuffers, 1); + ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples); + } + + // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB + // frambuffer, so there's no need (and no way) to request it + + ADD_ATTR(0); + +#undef ADD_ATTR +#undef ADD_ATTR2 + + window->NSGL.pixelFormat = + [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + if (window->NSGL.pixelFormat == nil) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "NSOpenGL: Failed to create OpenGL pixel format"); + return GL_FALSE; + } + + NSOpenGLContext* share = NULL; + + if (wndconfig->share) + share = wndconfig->share->NSGL.context; + + window->NSGL.context = + [[NSOpenGLContext alloc] initWithFormat:window->NSGL.pixelFormat + shareContext:share]; + if (window->NSGL.context == nil) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "NSOpenGL: Failed to create OpenGL context"); + return GL_FALSE; + } + + return GL_TRUE; +} + + +//======================================================================== +// Destroy the OpenGL context +//======================================================================== + +void _glfwDestroyContext(_GLFWwindow* window) +{ + [window->NSGL.pixelFormat release]; + window->NSGL.pixelFormat = nil; + + [window->NSGL.context release]; + window->NSGL.context = nil; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// From 9af61d06cfb8fba7e51e72eb07fde93b92df4adf Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 30 Dec 2012 01:15:48 +0100 Subject: [PATCH 4/7] Removed return value of _glfwPlatformTerminate. --- src/cocoa_init.m | 4 +--- src/init.c | 3 +-- src/internal.h | 2 +- src/win32_init.c | 4 +--- src/x11_init.c | 4 +--- 5 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index e4de641e..99638710 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -120,7 +120,7 @@ int _glfwPlatformInit(void) // Close window, if open, and shut down GLFW //======================================================================== -int _glfwPlatformTerminate(void) +void _glfwPlatformTerminate(void) { // TODO: Probably other cleanup @@ -146,8 +146,6 @@ int _glfwPlatformTerminate(void) _glfwTerminateJoysticks(); _glfwTerminateOpenGL(); - - return GL_TRUE; } diff --git a/src/init.c b/src/init.c index 4d7b731e..521674ab 100644 --- a/src/init.c +++ b/src/init.c @@ -149,8 +149,7 @@ GLFWAPI void glfwTerminate(void) while (_glfwLibrary.windowListHead) glfwDestroyWindow(_glfwLibrary.windowListHead); - if (!_glfwPlatformTerminate()) - return; + _glfwPlatformTerminate(); if (_glfwLibrary.modes) free(_glfwLibrary.modes); diff --git a/src/internal.h b/src/internal.h index d2619e2e..c8530bd5 100644 --- a/src/internal.h +++ b/src/internal.h @@ -260,7 +260,7 @@ extern _GLFWlibrary _glfwLibrary; // Platform init and version int _glfwPlatformInit(void); -int _glfwPlatformTerminate(void); +void _glfwPlatformTerminate(void); const char* _glfwPlatformGetVersionString(void); // Input mode support diff --git a/src/win32_init.c b/src/win32_init.c index 62d6c94b..490b2aca 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -200,7 +200,7 @@ int _glfwPlatformInit(void) // Close window and shut down library //======================================================================== -int _glfwPlatformTerminate(void) +void _glfwPlatformTerminate(void) { // Restore the original gamma ramp if (_glfwLibrary.rampChanged) @@ -220,8 +220,6 @@ int _glfwPlatformTerminate(void) SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(_glfwLibrary.Win32.foregroundLockTimeout), SPIF_SENDCHANGE); - - return GL_TRUE; } diff --git a/src/x11_init.c b/src/x11_init.c index b5631fba..e260c6cc 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -662,7 +662,7 @@ int _glfwPlatformInit(void) // Close window and shut down library //======================================================================== -int _glfwPlatformTerminate(void) +void _glfwPlatformTerminate(void) { if (_glfwLibrary.X11.cursor) { @@ -681,8 +681,6 @@ int _glfwPlatformTerminate(void) // Free clipboard memory if (_glfwLibrary.X11.selection.string) free(_glfwLibrary.X11.selection.string); - - return GL_TRUE; } From 9cc8fc0d0af6ee3e583601dc832913bed6f1aadd Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 30 Dec 2012 01:42:14 +0100 Subject: [PATCH 5/7] Removed glfwGetError and glfwErrorString. The cached error code cannot be made per-thread unless it required glfwInit (due to lack of __thread on OS X), which would be confusing and partially defeats the purpose of it. Beginners would use the generic error string facility instead of the error callback and then be confused by its nondescript messages. Storing the provided error code from within the error callback, whether globally or per-thread, requires just a few lines of code and hands control to the user without compromising thread safety. --- examples/boing.c | 4 -- examples/triangle.c | 12 +++--- examples/wave.c | 17 ++++++-- include/GL/glfw3.h | 19 --------- readme.html | 3 +- src/init.c | 95 +++++++++++++++++---------------------------- tests/accuracy.c | 12 +++--- tests/clipboard.c | 10 ++--- tests/defaults.c | 12 +++--- tests/events.c | 12 +++--- tests/fsaa.c | 14 +++---- tests/fsfocus.c | 12 +++--- tests/gamma.c | 12 +++--- tests/glfwinfo.c | 3 -- tests/iconify.c | 12 +++--- tests/joysticks.c | 12 +++--- tests/peter.c | 14 +++---- tests/reopen.c | 13 ++++--- tests/sharing.c | 14 +++---- tests/tearing.c | 12 +++--- tests/threads.c | 16 +++++--- tests/title.c | 12 +++--- tests/windows.c | 14 +++---- 23 files changed, 169 insertions(+), 187 deletions(-) diff --git a/examples/boing.c b/examples/boing.c index 5a1993ff..f9771122 100644 --- a/examples/boing.c +++ b/examples/boing.c @@ -572,17 +572,13 @@ int main( void ) /* Init GLFW */ if( !glfwInit() ) - { - fprintf( stderr, "Failed to initialize GLFW\n" ); exit( EXIT_FAILURE ); - } glfwWindowHint(GLFW_DEPTH_BITS, 16); window = glfwCreateWindow( 400, 400, GLFW_WINDOWED, "Boing (classic Amiga demo)", NULL ); if (!window) { - fprintf( stderr, "Failed to open GLFW window\n" ); glfwTerminate(); exit( EXIT_FAILURE ); } diff --git a/examples/triangle.c b/examples/triangle.c index 3a1cef94..13ef0a98 100644 --- a/examples/triangle.c +++ b/examples/triangle.c @@ -10,24 +10,26 @@ #define GLFW_INCLUDE_GLU #include +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + int main(void) { int width, height, x; GLFWwindow window; + glfwSetErrorCallback(error_callback); + // Initialise GLFW if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW\n"); exit(EXIT_FAILURE); - } // Open a window and create its OpenGL context window = glfwCreateWindow(640, 480, GLFW_WINDOWED, "Spinning Triangle", NULL); if (!window) { - fprintf(stderr, "Failed to open GLFW window\n"); - glfwTerminate(); exit(EXIT_FAILURE); } diff --git a/examples/wave.c b/examples/wave.c index 7b4b4c32..28065d30 100644 --- a/examples/wave.c +++ b/examples/wave.c @@ -257,6 +257,16 @@ void calc_grid(void) } +//======================================================================== +// Print errors +//======================================================================== + +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + + //======================================================================== // Handle key strokes //======================================================================== @@ -393,16 +403,15 @@ int main(int argc, char* argv[]) double t, dt_total, t_old; int width, height; + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "GLFW initialization failed\n"); exit(EXIT_FAILURE); - } window = glfwCreateWindow(640, 480, GLFW_WINDOWED, "Wave Simulation", NULL); if (!window) { - fprintf(stderr, "Could not open window\n"); + glfwTerminate(); exit(EXIT_FAILURE); } diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index bd968a6c..46db151f 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -951,25 +951,6 @@ GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev); */ GLFWAPI const char* glfwGetVersionString(void); -/*! @brief Retrieves the latest error. - * @return The latest @link errors error code @endlink. - * @ingroup error - * - * @remarks This function may be called before @ref glfwInit. - */ -GLFWAPI int glfwGetError(void); - -/*! @brief Retrieves a generic, human readable description of the specified error. - * @param[in] error The @link errors error code @endlink to be described. - * @return A UTF-8 encoded string describing the error. - * @ingroup error - * - * @remarks This function may be called before @ref glfwInit. - * - * @remarks This function may be called from secondary threads. - */ -GLFWAPI const char* glfwErrorString(int error); - /*! @brief Sets the error callback. * @param[in] cbfun The new callback, or @c NULL to remove the currently set * callback. diff --git a/readme.html b/readme.html index 8e25c743..d5e9d922 100644 --- a/readme.html +++ b/readme.html @@ -270,8 +270,7 @@ version of GLFW.

  • Added GLFWwindow window handle type and updated window-related functions and callbacks to take a window handle
  • Added glfwDefaultWindowHints function for resetting all window hints to their default values
  • Added glfwMakeContextCurrent function for making the context of the specified window current
  • -
  • Added glfwGetError and glfwErrorString error reporting functions and a number of error tokens
  • -
  • Added glfwSetErrorCallback function and GLFWerrorfun type for receiving more specific and/or nested errors
  • +
  • Added glfwSetErrorCallback function and GLFWerrorfun type for receiving error descriptions
  • Added glfwSetWindowUserPointer and glfwGetWindowUserPointer functions for per-window user pointers
  • Added glfwGetVersionString function for determining which code paths were enabled at compile time
  • Added glfwSetWindowPosCallback function and GLFWwindowposfun type for reciving window position events
  • diff --git a/src/init.c b/src/init.c index 521674ab..dbdbc48d 100644 --- a/src/init.c +++ b/src/init.c @@ -50,15 +50,6 @@ GLboolean _glfwInitialized = GL_FALSE; _GLFWlibrary _glfwLibrary; -//------------------------------------------------------------------------ -// The current GLFW error code -// This is outside of _glfwLibrary so it can be initialized and usable -// before glfwInit is called, which lets that function report errors -// TODO: Make this thread-local -//------------------------------------------------------------------------ -static int _glfwError = GLFW_NO_ERROR; - - //------------------------------------------------------------------------ // The current error callback // This is outside of _glfwLibrary so it can be initialized and usable @@ -67,6 +58,40 @@ static int _glfwError = GLFW_NO_ERROR; static GLFWerrorfun _glfwErrorCallback = NULL; +//======================================================================== +// Returns a generic string representation of the specified error +//======================================================================== + +static const char* getErrorString(int error) +{ + switch (error) + { + case GLFW_NO_ERROR: + return "No error"; + case GLFW_NOT_INITIALIZED: + return "The GLFW library is not initialized"; + case GLFW_NO_CURRENT_CONTEXT: + return "There is no current context"; + case GLFW_INVALID_ENUM: + return "Invalid argument for enum parameter"; + case GLFW_INVALID_VALUE: + return "Invalid value for parameter"; + case GLFW_OUT_OF_MEMORY: + return "Out of memory"; + case GLFW_API_UNAVAILABLE: + return "The requested client API is unavailable"; + case GLFW_VERSION_UNAVAILABLE: + return "The requested client API version is unavailable"; + case GLFW_PLATFORM_ERROR: + return "A platform-specific error occurred"; + case GLFW_FORMAT_UNAVAILABLE: + return "The requested format is unavailable"; + } + + return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString"; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// @@ -97,12 +122,10 @@ void _glfwSetError(int error, const char* format, ...) description = buffer; } else - description = glfwErrorString(error); + description = getErrorString(error); _glfwErrorCallback(error, description); } - else - _glfwError = error; } @@ -187,54 +210,6 @@ GLFWAPI const char* glfwGetVersionString(void) } -//======================================================================== -// Returns the current error value -// This function may be called without GLFW having been initialized -//======================================================================== - -GLFWAPI int glfwGetError(void) -{ - int error = _glfwError; - _glfwError = GLFW_NO_ERROR; - return error; -} - - -//======================================================================== -// Returns a string representation of the specified error value -// This function may be called without GLFW having been initialized -//======================================================================== - -GLFWAPI const char* glfwErrorString(int error) -{ - switch (error) - { - case GLFW_NO_ERROR: - return "No error"; - case GLFW_NOT_INITIALIZED: - return "The GLFW library is not initialized"; - case GLFW_NO_CURRENT_CONTEXT: - return "There is no current context"; - case GLFW_INVALID_ENUM: - return "Invalid argument for enum parameter"; - case GLFW_INVALID_VALUE: - return "Invalid value for parameter"; - case GLFW_OUT_OF_MEMORY: - return "Out of memory"; - case GLFW_API_UNAVAILABLE: - return "The requested client API is unavailable"; - case GLFW_VERSION_UNAVAILABLE: - return "The requested client API version is unavailable"; - case GLFW_PLATFORM_ERROR: - return "A platform-specific error occurred"; - case GLFW_FORMAT_UNAVAILABLE: - return "The requested format is unavailable"; - } - - return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString"; -} - - //======================================================================== // Sets the callback function for GLFW errors // This function may be called without GLFW having been initialized diff --git a/tests/accuracy.c b/tests/accuracy.c index d320f64c..099a619c 100644 --- a/tests/accuracy.c +++ b/tests/accuracy.c @@ -51,6 +51,11 @@ static void set_swap_interval(GLFWwindow window, int interval) glfwSetWindowTitle(window, title); } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void window_size_callback(GLFWwindow window, int width, int height) { window_width = width; @@ -80,18 +85,15 @@ int main(void) GLFWwindow window; int width, height; + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } window = glfwCreateWindow(window_width, window_height, GLFW_WINDOWED, "", NULL); if (!window) { glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } diff --git a/tests/clipboard.c b/tests/clipboard.c index c3746f19..7c931220 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -47,6 +47,11 @@ static GLboolean control_is_down(GLFWwindow window) glfwGetKey(window, GLFW_KEY_RIGHT_CONTROL); } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static int window_close_callback(GLFWwindow window) { closed = GL_TRUE; @@ -93,11 +98,6 @@ static void window_size_callback(GLFWwindow window, int width, int height) glViewport(0, 0, width, height); } -static void error_callback(int error, const char* description) -{ - fprintf(stderr, "Error in %s\n", description); -} - int main(int argc, char** argv) { int ch; diff --git a/tests/defaults.c b/tests/defaults.c index 8f08889b..3b457695 100644 --- a/tests/defaults.c +++ b/tests/defaults.c @@ -72,16 +72,20 @@ static ParamGLFW glfw_params[] = { 0, NULL } }; +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + int main(void) { int i, width, height; GLFWwindow window; + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } glfwWindowHint(GLFW_VISIBLE, GL_FALSE); @@ -89,8 +93,6 @@ int main(void) if (!window) { glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } diff --git a/tests/events.c b/tests/events.c index 46bde2ab..c79af8b8 100644 --- a/tests/events.c +++ b/tests/events.c @@ -218,6 +218,11 @@ static const char* get_character_string(int character) return result; } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void window_pos_callback(GLFWwindow window, int x, int y) { printf("%08x at %0.3f: Window position: %i %i\n", @@ -344,11 +349,10 @@ int main(void) setlocale(LC_ALL, ""); + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } printf("Library initialized\n"); @@ -356,8 +360,6 @@ int main(void) if (!window) { glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } diff --git a/tests/fsaa.c b/tests/fsaa.c index 735a1f5f..b564bfe4 100644 --- a/tests/fsaa.c +++ b/tests/fsaa.c @@ -38,6 +38,11 @@ #include "getopt.h" +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void window_size_callback(GLFWwindow window, int width, int height) { glViewport(0, 0, width, height); @@ -82,11 +87,10 @@ int main(int argc, char** argv) } } + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } if (samples) printf("Requesting FSAA with %i samples\n", samples); @@ -99,8 +103,6 @@ int main(int argc, char** argv) if (!window) { glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } @@ -113,8 +115,6 @@ int main(int argc, char** argv) if (!glfwExtensionSupported("GL_ARB_multisample")) { glfwTerminate(); - - fprintf(stderr, "Context reports GL_ARB_multisample is not supported\n"); exit(EXIT_FAILURE); } diff --git a/tests/fsfocus.c b/tests/fsfocus.c index a87d136a..c83e1668 100644 --- a/tests/fsfocus.c +++ b/tests/fsfocus.c @@ -35,6 +35,11 @@ static GLboolean running = GL_TRUE; +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void window_focus_callback(GLFWwindow window, int focused) { printf("%0.3f: Window %s\n", @@ -76,18 +81,15 @@ int main(void) { GLFWwindow window; + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } window = glfwCreateWindow(640, 480, GLFW_FULLSCREEN, "Fullscreen focus", NULL); if (!window) { glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } diff --git a/tests/gamma.c b/tests/gamma.c index 8b995afc..324238d6 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -52,6 +52,11 @@ static void set_gamma(float value) glfwSetGamma(gamma_value); } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static int window_close_callback(GLFWwindow window) { closed = GL_TRUE; @@ -118,11 +123,10 @@ int main(int argc, char** argv) } } + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } if (mode == GLFW_FULLSCREEN) { @@ -141,8 +145,6 @@ int main(int argc, char** argv) if (!window) { glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index 8db99111..bd0251dd 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -257,10 +257,7 @@ int main(int argc, char** argv) glfwSetErrorCallback(error_callback); if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } if (major != 1 || minor != 0) { diff --git a/tests/iconify.c b/tests/iconify.c index b0b6b6a1..0432e602 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -42,6 +42,11 @@ static void usage(void) printf("Usage: iconify [-h] [-f]\n"); } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static int window_close_callback(GLFWwindow window) { closed = GL_TRUE; @@ -113,11 +118,10 @@ int main(int argc, char** argv) } } + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } if (mode == GLFW_FULLSCREEN) { @@ -136,8 +140,6 @@ int main(int argc, char** argv) if (!window) { glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } diff --git a/tests/joysticks.c b/tests/joysticks.c index 2b243687..d297a3f4 100644 --- a/tests/joysticks.c +++ b/tests/joysticks.c @@ -47,6 +47,11 @@ typedef struct Joystick static Joystick joysticks[GLFW_JOYSTICK_LAST - GLFW_JOYSTICK_1 + 1]; static int joystick_count = 0; +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void window_size_callback(GLFWwindow window, int width, int height) { glViewport(0, 0, width, height); @@ -185,18 +190,15 @@ int main(void) memset(joysticks, 0, sizeof(joysticks)); + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } window = glfwCreateWindow(640, 480, GLFW_WINDOWED, "Joystick Test", NULL); if (!window) { glfwTerminate(); - - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } diff --git a/tests/peter.c b/tests/peter.c index 30690e68..d7209e3a 100644 --- a/tests/peter.c +++ b/tests/peter.c @@ -56,6 +56,11 @@ static void toggle_cursor(GLFWwindow window) } } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void cursor_position_callback(GLFWwindow window, int x, int y) { printf("Cursor moved to: %i %i (%i %i)\n", x, y, x - cursor_x, y - cursor_y); @@ -111,16 +116,13 @@ static GLboolean open_window(void) int main(void) { + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } if (!open_window()) { - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); - glfwTerminate(); exit(EXIT_FAILURE); } @@ -139,8 +141,6 @@ int main(void) glfwDestroyWindow(window_handle); if (!open_window()) { - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); - glfwTerminate(); exit(EXIT_FAILURE); } diff --git a/tests/reopen.c b/tests/reopen.c index 212c108d..cd085488 100644 --- a/tests/reopen.c +++ b/tests/reopen.c @@ -54,6 +54,11 @@ static const char* get_mode_name(int mode) } } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void window_size_callback(GLFWwindow window, int width, int height) { glViewport(0, 0, width, height); @@ -85,19 +90,13 @@ static GLboolean open_window(int width, int height, int mode) double base; if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); return GL_FALSE; - } base = glfwGetTime(); window_handle = glfwCreateWindow(width, height, mode, "Window Re-opener", NULL); if (!window_handle) - { - fprintf(stderr, "Failed to open %s mode GLFW window: %s\n", get_mode_name(mode), glfwErrorString(glfwGetError())); return GL_FALSE; - } glfwMakeContextCurrent(window_handle); glfwSwapInterval(1); @@ -129,6 +128,8 @@ int main(int argc, char** argv) { int count = 0; + glfwSetErrorCallback(error_callback); + for (;;) { if (!open_window(640, 480, (count & 1) ? GLFW_FULLSCREEN : GLFW_WINDOWED)) diff --git a/tests/sharing.c b/tests/sharing.c index 0042a858..b77aaf26 100644 --- a/tests/sharing.c +++ b/tests/sharing.c @@ -39,6 +39,11 @@ static GLFWwindow windows[2]; static GLboolean closed = GL_FALSE; +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void key_callback(GLFWwindow window, int key, int action) { if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE) @@ -128,17 +133,14 @@ int main(int argc, char** argv) { GLuint texture; + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } windows[0] = open_window("First", NULL, 0, 0); if (!windows[0]) { - fprintf(stderr, "Failed to open first GLFW window: %s\n", glfwErrorString(glfwGetError())); - glfwTerminate(); exit(EXIT_FAILURE); } @@ -152,8 +154,6 @@ int main(int argc, char** argv) windows[1] = open_window("Second", windows[0], WIDTH + 50, 0); if (!windows[1]) { - fprintf(stderr, "Failed to open second GLFW window: %s\n", glfwErrorString(glfwGetError())); - glfwTerminate(); exit(EXIT_FAILURE); } diff --git a/tests/tearing.c b/tests/tearing.c index 63ece2ba..8ab6a1d4 100644 --- a/tests/tearing.c +++ b/tests/tearing.c @@ -48,6 +48,11 @@ static void set_swap_interval(GLFWwindow window, int interval) glfwSetWindowTitle(window, title); } +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void window_size_callback(GLFWwindow window, int width, int height) { glViewport(0, 0, width, height); @@ -64,17 +69,14 @@ int main(void) float position; GLFWwindow window; + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } window = glfwCreateWindow(640, 480, GLFW_WINDOWED, "", NULL); if (!window) { - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); - glfwTerminate(); exit(EXIT_FAILURE); } diff --git a/tests/threads.c b/tests/threads.c index 8b06b1d3..9cc78975 100644 --- a/tests/threads.c +++ b/tests/threads.c @@ -47,6 +47,11 @@ typedef struct static volatile GLboolean running = GL_TRUE; +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static int thread_main(void* data) { const Thread* thread = (const Thread*) data; @@ -80,12 +85,10 @@ int main(void) }; const int count = sizeof(threads) / sizeof(Thread); + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", - glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } for (i = 0; i < count; i++) { @@ -97,8 +100,7 @@ int main(void) NULL); if (!threads[i].window) { - fprintf(stderr, "Failed to open GLFW window: %s\n", - glfwErrorString(glfwGetError())); + glfwTerminate(); exit(EXIT_FAILURE); } @@ -106,6 +108,8 @@ int main(void) thrd_success) { fprintf(stderr, "Failed to create secondary thread\n"); + + glfwTerminate(); exit(EXIT_FAILURE); } } diff --git a/tests/title.c b/tests/title.c index 62690f9c..b23f0ab2 100644 --- a/tests/title.c +++ b/tests/title.c @@ -32,6 +32,11 @@ #include #include +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + static void window_size_callback(GLFWwindow window, int width, int height) { glViewport(0, 0, width, height); @@ -41,17 +46,14 @@ int main(void) { GLFWwindow window; + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } window = glfwCreateWindow(400, 400, GLFW_WINDOWED, "English 日本語 русский язык 官話", NULL); if (!window) { - fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); - glfwTerminate(); exit(EXIT_FAILURE); } diff --git a/tests/windows.c b/tests/windows.c index 187248c2..d0006836 100644 --- a/tests/windows.c +++ b/tests/windows.c @@ -40,18 +40,21 @@ static const char* titles[] = "Quux" }; +static void error_callback(int error, const char* description) +{ + fprintf(stderr, "Error: %s\n", description); +} + int main(void) { int i; GLboolean running = GL_TRUE; GLFWwindow windows[4]; + glfwSetErrorCallback(error_callback); + if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", - glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); - } for (i = 0; i < 4; i++) { @@ -60,9 +63,6 @@ int main(void) windows[i] = glfwCreateWindow(200, 200, GLFW_WINDOWED, titles[i], NULL); if (!windows[i]) { - fprintf(stderr, "Failed to open GLFW window: %s\n", - glfwErrorString(glfwGetError())); - glfwTerminate(); exit(EXIT_FAILURE); } From ea1ddfd7a4521e0a090bf516df65867812c45cac Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 30 Dec 2012 02:28:52 +0100 Subject: [PATCH 6/7] Removed declarations of removed functions. --- src/internal.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/internal.h b/src/internal.h index c8530bd5..73bb6fcd 100644 --- a/src/internal.h +++ b/src/internal.h @@ -264,8 +264,6 @@ void _glfwPlatformTerminate(void); const char* _glfwPlatformGetVersionString(void); // Input mode support -void _glfwPlatformEnableSystemKeys(_GLFWwindow* window); -void _glfwPlatformDisableSystemKeys(_GLFWwindow* window); void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y); void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); From 9e9457767f3d1c2dd0a5b85191c36f1648f7c0bb Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Sun, 30 Dec 2012 18:13:04 +0100 Subject: [PATCH 7/7] Added workaround for broken Mesa GLX_ARB_create_context_profile. --- src/glx_context.c | 91 ++++++++++++++++++++++++++++++++-------------- src/glx_platform.h | 2 + 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/glx_context.c b/src/glx_context.c index 7a8f50d8..dbd7dd91 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -38,6 +38,11 @@ void (*glXGetProcAddressEXT(const GLubyte* procName))(); +#ifndef GLXBadProfileARB + #define GLXBadProfileARB 13 +#endif + + //======================================================================== // Thread local storage attribute macro //======================================================================== @@ -48,6 +53,12 @@ void (*glXGetProcAddressEXT(const GLubyte* procName))(); #endif +//======================================================================== +// The X error code as provided to the X error handler +//======================================================================== +static unsigned long _glfwErrorCode = Success; + + //======================================================================== // The per-thread current context/window pointer //======================================================================== @@ -207,18 +218,48 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) //======================================================================== -// Error handler for BadMatch errors when requesting context with -// unavailable OpenGL versions using the GLX_ARB_create_context extension +// Error handler used when creating a context with the GLX_ARB_create_context +// extension set //======================================================================== static int errorHandler(Display *display, XErrorEvent* event) { + _glfwErrorCode = event->error_code; return 0; } //======================================================================== -// Create the actual OpenGL context +// Create the OpenGL context using legacy API +//======================================================================== + +static void createLegacyContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + GLXFBConfig fbconfig, + GLXContext share) +{ + if (_glfwLibrary.GLX.SGIX_fbconfig) + { + window->GLX.context = + _glfwLibrary.GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, + fbconfig, + GLX_RGBA_TYPE, + share, + True); + } + else + { + window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display, + fbconfig, + GLX_RGBA_TYPE, + share, + True); + } +} + + +//======================================================================== +// Create the OpenGL context //======================================================================== #define setGLXattrib(attribName, attribValue) \ @@ -386,6 +427,7 @@ static int createContext(_GLFWwindow* window, // it because glXCreateContextAttribsARB generates a BadMatch error if // the requested OpenGL version is unavailable (instead of a civilized // response like returning NULL) + _glfwErrorCode = Success; XSetErrorHandler(errorHandler); window->GLX.context = @@ -397,36 +439,29 @@ static int createContext(_GLFWwindow* window, // We are done, so unset the error handler again (see above) XSetErrorHandler(NULL); + + if (window->GLX.context == NULL) + { + // HACK: This is a fallback for the broken Mesa implementation of + // GLX_ARB_create_context_profile, which fails default 1.0 context + // creation with a GLXBadProfileARB error in violation of the spec + if (_glfwErrorCode == _glfwLibrary.GLX.errorBase + GLXBadProfileARB && + wndconfig->clientAPI == GLFW_OPENGL_API && + wndconfig->glProfile == GLFW_OPENGL_NO_PROFILE && + wndconfig->glForward == GL_FALSE) + { + createLegacyContext(window, wndconfig, *fbconfig, share); + } + } } else - { - if (_glfwLibrary.GLX.SGIX_fbconfig) - { - window->GLX.context = - _glfwLibrary.GLX.CreateContextWithConfigSGIX(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - else - { - window->GLX.context = glXCreateNewContext(_glfwLibrary.X11.display, - *fbconfig, - GLX_RGBA_TYPE, - share, - True); - } - } + createLegacyContext(window, wndconfig, *fbconfig, share); XFree(fbconfig); if (window->GLX.context == NULL) { - // TODO: Handle all the various error codes here - - _glfwSetError(GLFW_PLATFORM_ERROR, - "GLX: Failed to create context"); + _glfwSetError(GLFW_PLATFORM_ERROR, "GLX: Failed to create context"); return GL_FALSE; } @@ -472,7 +507,9 @@ int _glfwInitOpenGL(void) #endif // Check if GLX is supported on this display - if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) + if (!glXQueryExtension(_glfwLibrary.X11.display, + &_glfwLibrary.GLX.errorBase, + &_glfwLibrary.GLX.eventBase)) { _glfwSetError(GLFW_API_UNAVAILABLE, "GLX: GLX support not found"); return GL_FALSE; diff --git a/src/glx_platform.h b/src/glx_platform.h index d1a7c963..60c2a46d 100644 --- a/src/glx_platform.h +++ b/src/glx_platform.h @@ -90,6 +90,8 @@ typedef struct _GLFWlibraryGLX { // Server-side GLX version int majorVersion, minorVersion; + int eventBase; + int errorBase; // GLX extensions PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;