diff --git a/examples/boing.c b/examples/boing.c index a5914f9d..660f5b60 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, "Boing (classic Amiga demo)", NULL, 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 52e11498..26b898cb 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, "Spinning Triangle", NULL, 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 a1bfde57..6e9bdade 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, "Wave Simulation", NULL, 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 517fe4d9..7329a697 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -985,25 +985,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. @@ -1298,6 +1279,10 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height, const char* title, GL * @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 diff --git a/readme.html b/readme.html index 190b05f7..512b1e78 100644 --- a/readme.html +++ b/readme.html @@ -275,8 +275,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 glfwGetWindowMonitor for querying the monitor, if any, of the specified window
  • diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 2ecc1079..d381d778 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -118,7 +118,7 @@ int _glfwPlatformInit(void) // Close window, if open, and shut down GLFW //======================================================================== -int _glfwPlatformTerminate(void) +void _glfwPlatformTerminate(void) { // TODO: Probably other cleanup @@ -142,8 +142,6 @@ int _glfwPlatformTerminate(void) _glfwTerminateJoysticks(); _glfwTerminateOpenGL(); - - return GL_TRUE; } diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 51fecbbe..10b65f3b 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -120,5 +120,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 9c81b369..d438ca8e 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->monitor) - { - 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/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; diff --git a/src/init.c b/src/init.c index e0a1e6f3..be63ff53 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; } @@ -158,8 +181,7 @@ GLFWAPI void glfwTerminate(void) _glfwDestroyMonitors(); - if (!_glfwPlatformTerminate()) - return; + _glfwPlatformTerminate(); _glfwInitialized = GL_FALSE; } @@ -194,54 +216,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/src/internal.h b/src/internal.h index fa272524..047e1d69 100644 --- a/src/internal.h +++ b/src/internal.h @@ -289,12 +289,10 @@ extern _GLFWlibrary _glfwLibrary; // Platform init and version int _glfwPlatformInit(void); -int _glfwPlatformTerminate(void); +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); diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 66518140..315c39d5 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,184 @@ 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 ////// +////////////////////////////////////////////////////////////////////////// + //======================================================================== // Make the OpenGL context associated with the specified window current //======================================================================== 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; } diff --git a/tests/accuracy.c b/tests/accuracy.c index e26d0456..5356b893 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, "", NULL, 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 b986174e..20a6a515 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 211071d9..5477d8ba 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 aca2e793..c2170ab9 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", @@ -370,11 +375,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"); @@ -382,8 +386,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 a80f79ec..42029c10 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 5024ab7d..f9be20d5 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, "Fullscreen focus", glfwGetPrimaryMonitor(), 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 ebbe1ff8..9f48c5c5 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 (monitor) { @@ -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 b9783234..87258809 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 46c996e0..964e9274 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; @@ -95,12 +100,6 @@ int main(int argc, char** argv) GLFWmonitor monitor = NULL; GLFWwindow window; - if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); - exit(EXIT_FAILURE); - } - while ((ch = getopt(argc, argv, "fh")) != -1) { switch (ch) @@ -119,6 +118,11 @@ int main(int argc, char** argv) } } + glfwSetErrorCallback(error_callback); + + if (!glfwInit()) + exit(EXIT_FAILURE); + if (monitor) { GLFWvidmode mode; @@ -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 560dd208..c2b3607e 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, "Joystick Test", NULL, 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 5a294eee..6410447e 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 5097b65b..2071e4fe 100644 --- a/tests/reopen.c +++ b/tests/reopen.c @@ -41,6 +41,11 @@ static GLFWwindow window_handle = NULL; static GLboolean closed = GL_FALSE; +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); @@ -71,16 +76,14 @@ static GLboolean open_window(int width, int height, GLFWmonitor monitor) { double base; + if (!glfwInit()) + return GL_FALSE; + base = glfwGetTime(); window_handle = glfwCreateWindow(width, height, "Window Re-opener", monitor, NULL); if (!window_handle) - { - fprintf(stderr, "Failed to open %s mode GLFW window: %s\n", - monitor ? "fullscreen" : "windowed", - glfwErrorString(glfwGetError())); return GL_FALSE; - } glfwMakeContextCurrent(window_handle); glfwSwapInterval(1); @@ -110,11 +113,7 @@ int main(int argc, char** argv) { int count = 0; - if (!glfwInit()) - { - fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError())); - return GL_FALSE; - } + glfwSetErrorCallback(error_callback); for (;;) { diff --git a/tests/sharing.c b/tests/sharing.c index 69c4c4cb..041f2ba7 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 881d7b50..97ddafb4 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, "", NULL, 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 27cb7b06..9cec021b 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++) { @@ -96,8 +99,7 @@ int main(void) NULL, NULL); if (!threads[i].window) { - fprintf(stderr, "Failed to open GLFW window: %s\n", - glfwErrorString(glfwGetError())); + glfwTerminate(); exit(EXIT_FAILURE); } @@ -105,6 +107,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 f7e216a8..d8289f99 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, "English 日本語 русский язык 官話", NULL, 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 dc2eec77..a9275bb3 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, titles[i], NULL, NULL); if (!windows[i]) { - fprintf(stderr, "Failed to open GLFW window: %s\n", - glfwErrorString(glfwGetError())); - glfwTerminate(); exit(EXIT_FAILURE); }