From d43e0b50d0e331b5705ee598fe6c144e813c81a8 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Mon, 7 Mar 2011 20:51:34 +0100
Subject: [PATCH 1/2] Added initial ARB_robustness support.
---
include/GL/glfw3.h | 6 ++++++
readme.html | 1 +
src/cocoa/cocoa_window.m | 7 +++++++
src/internal.h | 3 +++
src/opengl.c | 11 +++++++++++
src/win32/platform.h | 1 +
src/win32/win32_window.c | 33 +++++++++++++++++++++++++++++++--
src/window.c | 6 ++++++
src/x11/platform.h | 1 +
src/x11/x11_window.c | 29 ++++++++++++++++++++++++++++-
tests/version.c | 21 ++++++++++++++++++---
11 files changed, 113 insertions(+), 6 deletions(-)
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
From 849977c7b2df2a4cb423fc47789abc49169f72f3 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 8 Mar 2011 23:14:42 +0100
Subject: [PATCH 2/2] Allow closing of NULL.
---
src/window.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/window.c b/src/window.c
index f0f504c5..5ce8cfa0 100644
--- a/src/window.c
+++ b/src/window.c
@@ -523,6 +523,10 @@ GLFWAPI void glfwCloseWindow(GLFWwindow handle)
_GLFWwindow* window = (_GLFWwindow*) handle;
+ // Allow closing of NULL (to match the behavior of free)
+ if (window == NULL)
+ return;
+
// Show mouse pointer again (if hidden)
if (window == _glfwLibrary.cursorLockWindow)
glfwEnable(window, GLFW_MOUSE_CURSOR);