diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index ee622b20..e902964c 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -412,6 +412,12 @@ extern "C" { #define GLFW_OPENGL_FORWARD_COMPAT 0x00020015 #define GLFW_OPENGL_DEBUG_CONTEXT 0x00020016 #define GLFW_OPENGL_PROFILE 0x00020017 +#define GLFW_OPENGL_ROBUSTNESS 0x00020018 + +/* GLFW_OPENGL_ROBUSTNESS mode tokens */ +#define GLFW_OPENGL_NO_ROBUSTNESS 0x00000000 +#define GLFW_OPENGL_NO_RESET_NOTIFICATION 0x00000001 +#define GLFW_OPENGL_LOSE_CONTEXT_ON_RESET 0x00000002 /* GLFW_OPENGL_PROFILE bit tokens */ #define GLFW_OPENGL_CORE_PROFILE 0x00000001 diff --git a/readme.html b/readme.html index 6d54174f..314b1cdd 100644 --- a/readme.html +++ b/readme.html @@ -274,6 +274,7 @@ version of GLFW.

  • Added glfwGetCurrentWindow function for retrieving the window whose OpenGL context is current
  • Added glfwInitWithModels function and GLFWallocator and GLFWthreadmodel types for pluggable memory allocation and threading models
  • Added GLFW_OPENGL_ES2_PROFILE profile for creating OpenGL ES 2.0 contexts using the GLX_EXT_create_context_es2_profile and WGL_EXT_create_context_es2_profile extensions
  • +
  • Added GLFW_OPENGL_ROBUSTNESS window hint and associated strategy tokens for GL_ARB_robustness support
  • Added windows simple multi-window test program
  • Added sharing simple OpenGL object sharing test program
  • Added a parameter to glfwOpenWindow for specifying a context the new window's context will share objects with
  • diff --git a/src/cocoa/cocoa_window.m b/src/cocoa/cocoa_window.m index 974dbdbc..b6c97fbd 100644 --- a/src/cocoa/cocoa_window.m +++ b/src/cocoa/cocoa_window.m @@ -479,6 +479,13 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, return GL_FALSE; } + // Fail if a robustness strategy was requested + if (wndconfig->glRobustness) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, "Cocoa/NSOpenGL: Mac OS X does not support OpenGL robustness strategies"); + return GL_FALSE; + } + // We can only have one application delegate, but we only allocate it the // first time we create a window to keep all window code in this file if (_glfwLibrary.NS.delegate == nil) diff --git a/src/internal.h b/src/internal.h index 2d24b004..c942707b 100644 --- a/src/internal.h +++ b/src/internal.h @@ -99,6 +99,7 @@ struct _GLFWhints GLboolean glForward; GLboolean glDebug; int glProfile; + int glRobustness; }; @@ -119,6 +120,7 @@ struct _GLFWwndconfig GLboolean glForward; GLboolean glDebug; int glProfile; + int glRobustness; _GLFWwindow* share; }; @@ -196,6 +198,7 @@ struct _GLFWwindow int glMajor, glMinor, glRevision; GLboolean glForward, glDebug; int glProfile; + int glRobustness; PFNGLGETSTRINGIPROC GetStringi; // These are defined in the current port's platform.h diff --git a/src/opengl.c b/src/opengl.c index 31e3bbea..a08f97f9 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -320,6 +320,16 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig) return GL_FALSE; } + if (wndconfig->glRobustness) + { + if (wndconfig->glRobustness != GLFW_OPENGL_NO_RESET_NOTIFICATION && + wndconfig->glRobustness != GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) + { + _glfwSetError(GLFW_INVALID_VALUE, "glfwOpenWindow: Invalid OpenGL robustness mode requested"); + return GL_FALSE; + } + } + return GL_TRUE; } @@ -335,6 +345,7 @@ GLboolean _glfwIsValidContext(_GLFWwindow* window, _GLFWwndconfig* wndconfig) // As these are hard constraints when non-zero, we can simply copy them window->glProfile = wndconfig->glProfile; window->glForward = wndconfig->glForward; + window->glRobustness = wndconfig->glRobustness; if (window->glMajor < wndconfig->glMajor || (window->glMajor == wndconfig->glMajor && diff --git a/src/win32/platform.h b/src/win32/platform.h index 08a15183..d6a5787d 100644 --- a/src/win32/platform.h +++ b/src/win32/platform.h @@ -232,6 +232,7 @@ typedef struct _GLFWcontextWGL GLboolean has_WGL_ARB_create_context; GLboolean has_WGL_ARB_create_context_profile; GLboolean has_WGL_EXT_create_context_es2_profile; + GLboolean has_WGL_ARB_create_context_robustness; } _GLFWcontextWGL; diff --git a/src/win32/win32_window.c b/src/win32/win32_window.c index 2def3a82..91f437b0 100644 --- a/src/win32/win32_window.c +++ b/src/win32/win32_window.c @@ -323,7 +323,7 @@ static GLboolean createContext(_GLFWwindow* window, int pixelFormat) { PIXELFORMATDESCRIPTOR pfd; - int i = 0, attribs[9]; + int i = 0, attribs[40]; HGLRC share = NULL; if (wndconfig->share) @@ -355,7 +355,7 @@ static GLboolean createContext(_GLFWwindow* window, attribs[i++] = wndconfig->glMinor; } - if (wndconfig->glForward || wndconfig->glDebug) + if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness) { int flags = 0; @@ -365,6 +365,9 @@ static GLboolean createContext(_GLFWwindow* window, if (wndconfig->glDebug) flags |= WGL_CONTEXT_DEBUG_BIT_ARB; + if (wndconfig->glRobustness) + flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; + attribs[i++] = WGL_CONTEXT_FLAGS_ARB; attribs[i++] = flags; } @@ -397,6 +400,25 @@ static GLboolean createContext(_GLFWwindow* window, attribs[i++] = flags; } + if (wndconfig->glRobustness) + { + int strategy; + + if (!window->WGL.has_WGL_ARB_create_context_robustness) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, "Win32/WGL: An OpenGL robustness strategy was requested but WGL_ARB_create_context_robustness is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glRobustness == GLFW_OPENGL_NO_RESET_NOTIFICATION) + strategy = WGL_NO_RESET_NOTIFICATION_ARB; + else if (wndconfig->glRobustness == GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) + strategy = WGL_LOSE_CONTEXT_ON_RESET_ARB; + + attribs[i++] = WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB; + attribs[i++] = strategy; + } + attribs[i++] = 0; window->WGL.context = window->WGL.CreateContextAttribsARB(window->WGL.DC, @@ -1067,6 +1089,7 @@ static void initWGLExtensions(_GLFWwindow* window) window->WGL.has_WGL_ARB_create_context = GL_FALSE; window->WGL.has_WGL_ARB_create_context_profile = GL_FALSE; window->WGL.has_WGL_EXT_create_context_es2_profile = GL_FALSE; + window->WGL.has_WGL_ARB_create_context_robustness = GL_FALSE; window->WGL.has_WGL_EXT_swap_control = GL_FALSE; window->WGL.has_WGL_ARB_pixel_format = GL_FALSE; @@ -1105,6 +1128,12 @@ static void initWGLExtensions(_GLFWwindow* window) window->WGL.has_WGL_EXT_create_context_es2_profile = GL_TRUE; } + if (window->WGL.has_WGL_ARB_create_context) + { + if (_glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness")) + window->WGL.has_WGL_ARB_create_context_robustness = GL_TRUE; + } + if (_glfwPlatformExtensionSupported("WGL_EXT_swap_control")) { window->WGL.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) diff --git a/src/window.c b/src/window.c index 20d436ed..f0f504c5 100644 --- a/src/window.c +++ b/src/window.c @@ -277,6 +277,7 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, wndconfig.glForward = _glfwLibrary.hints.glForward ? GL_TRUE : GL_FALSE; wndconfig.glDebug = _glfwLibrary.hints.glDebug ? GL_TRUE : GL_FALSE; wndconfig.glProfile = _glfwLibrary.hints.glProfile; + wndconfig.glRobustness = _glfwLibrary.hints.glRobustness ? GL_TRUE : GL_FALSE; wndconfig.share = share; // Reset to default values for the next call @@ -499,6 +500,9 @@ GLFWAPI void glfwOpenWindowHint(int target, int hint) case GLFW_OPENGL_PROFILE: _glfwLibrary.hints.glProfile = hint; break; + case GLFW_OPENGL_ROBUSTNESS: + _glfwLibrary.hints.glRobustness = hint; + break; default: break; } @@ -776,6 +780,8 @@ GLFWAPI int glfwGetWindowParam(GLFWwindow handle, int param) return window->glDebug; case GLFW_OPENGL_PROFILE: return window->glProfile; + case GLFW_OPENGL_ROBUSTNESS: + return window->glRobustness; default: _glfwSetError(GLFW_INVALID_ENUM, "glfwGetWindowParam: Invalid enum value for 'param' parameter"); return 0; diff --git a/src/x11/platform.h b/src/x11/platform.h index bdaa6d8f..204e9cc3 100644 --- a/src/x11/platform.h +++ b/src/x11/platform.h @@ -107,6 +107,7 @@ typedef struct _GLFWcontextGLX GLboolean has_GLX_ARB_multisample; GLboolean has_GLX_ARB_create_context; GLboolean has_GLX_ARB_create_context_profile; + GLboolean has_GLX_ARB_create_context_robustness; GLboolean has_GLX_EXT_create_context_es2_profile; } _GLFWcontextGLX; diff --git a/src/x11/x11_window.c b/src/x11/x11_window.c index 051be402..47af01f6 100644 --- a/src/x11/x11_window.c +++ b/src/x11/x11_window.c @@ -445,7 +445,7 @@ static int createContext(_GLFWwindow* window, setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor); } - if (wndconfig->glForward || wndconfig->glDebug) + if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness) { int flags = 0; @@ -455,6 +455,9 @@ static int createContext(_GLFWwindow* window, if (wndconfig->glDebug) flags |= GLX_CONTEXT_DEBUG_BIT_ARB; + if (wndconfig->glRobustness) + flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; + setGLXattrib(attribs, index, GLX_CONTEXT_FLAGS_ARB, flags); } @@ -485,6 +488,24 @@ static int createContext(_GLFWwindow* window, setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags); } + if (wndconfig->glRobustness) + { + int strategy; + + if (!window->GLX.has_GLX_ARB_create_context_robustness) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE, "X11/GLX: An OpenGL robustness strategy was requested but GLX_ARB_create_context_robustness is unavailable"); + return GL_FALSE; + } + + if (wndconfig->glRobustness == GLFW_OPENGL_NO_RESET_NOTIFICATION) + strategy = GLX_NO_RESET_NOTIFICATION_ARB; + else if (wndconfig->glRobustness == GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) + strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB; + + setGLXattrib(attribs, index, GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy); + } + setGLXattrib(attribs, index, None, None); // This is the only place we set an Xlib error handler, and we only do @@ -613,6 +634,12 @@ static void initGLXExtensions(_GLFWwindow* window) if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) window->GLX.has_GLX_EXT_create_context_es2_profile = GL_TRUE; } + + if (window->GLX.has_GLX_ARB_create_context) + { + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness")) + window->GLX.has_GLX_ARB_create_context_robustness = GL_TRUE; + } } diff --git a/tests/version.c b/tests/version.c index af0c33a6..e473ef55 100644 --- a/tests/version.c +++ b/tests/version.c @@ -44,8 +44,9 @@ static void usage(void) { - printf("Usage: version [-h] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE]\n"); + printf("Usage: version [-h] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-r STRATEGY]\n"); printf("available profiles: core compat es2\n"); + printf("available strategies: none lose\n"); } static void error_callback(int error, const char* description) @@ -113,12 +114,12 @@ static void list_extensions(int major, int minor) int main(int argc, char** argv) { - int ch, profile = 0, major = 1, minor = 0, revision; + int ch, profile = 0, strategy = 0, major = 1, minor = 0, revision; GLboolean debug = GL_FALSE, forward = GL_FALSE, list = GL_FALSE; GLint flags, mask; GLFWwindow window; - while ((ch = getopt(argc, argv, "dfhlm:n:p:")) != -1) + while ((ch = getopt(argc, argv, "dfhlm:n:p:r:")) != -1) { switch (ch) { @@ -153,6 +154,17 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } break; + case 'r': + if (strcasecmp(optarg, "none") == 0) + strategy = GLFW_OPENGL_NO_RESET_NOTIFICATION; + else if (strcasecmp(optarg, "lose") == 0) + strategy = GLFW_OPENGL_LOSE_CONTEXT_ON_RESET; + else + { + usage(); + exit(EXIT_FAILURE); + } + break; default: usage(); exit(EXIT_FAILURE); @@ -185,6 +197,9 @@ int main(int argc, char** argv) if (profile != 0) glfwOpenWindowHint(GLFW_OPENGL_PROFILE, profile); + if (strategy) + glfwOpenWindowHint(GLFW_OPENGL_ROBUSTNESS, strategy); + // We assume here that we stand a better chance of success by leaving all // possible details of pixel format selection to GLFW