Commit 44c899ce authored by Camilla Berglund's avatar Camilla Berglund
Browse files

Added support for GL_KHR_context_flush_control.

parent cfc47abf
......@@ -63,6 +63,9 @@ GLFW bundles a number of dependencies in the `deps/` directory.
automatically iconify (and restore the previous video mode) on focus loss
- Added `GLFW_DONT_CARE` for indicating that any value is acceptable
- Added `GLFW_DOUBLEBUFFER` for controlling whether to use double buffering
- Added `GLFW_CONTEXT_RELEASE_BEHAVIOR` and values
`GLFW_ANY_RELEASE_BEHAVIOR`, `GLFW_RELEASE_BEHAVIOR_FLUSH` and
`GLFW_RELEASE_BEHAVIOR_NONE` for `GL_KHR_context_flush_control` support
- Added `GLFW_INCLUDE_ES31` for including the OpenGL ES 3.1 header
- Added `GLFW_FLOATING` for creating always-on-top windowed mode windows
- Added *partial and experimental* support for Wayland
......
......@@ -222,39 +222,53 @@ used by the context. This can be one of `GLFW_NO_RESET_NOTIFICATION` or
`GLFW_LOSE_CONTEXT_ON_RESET`, or `GLFW_NO_ROBUSTNESS` to not request
a robustness strategy.
The `GLFW_CONTEXT_RELEASE_BEHAVIOR` hint specifies the release behavior to be
used by the context. Possible values are one of `GLFW_ANY_RELEASE_BEHAVIOR`,
`GLFW_RELEASE_BEHAVIOR_FLUSH` or `GLFW_RELEASE_BEHAVIOR_NONE`. If the
behavior is `GLFW_ANY_RELEASE_BEHAVIOR`, the default behavior of the context
creation API will be used. If the behavior is `GLFW_RELEASE_BEHAVIOR_FLUSH`,
the pipeline will be flushed whenever the context is released from being the
current one. If the behavior is `GLFW_RELEASE_BEHAVIOR_NONE`, the pipeline will
not be flushed on release.
@note Context release behaviors are described in detail by the
[GL_KHR_context_flush_control](https://www.opengl.org/registry/specs/KHR/context_flush_control.txt)
extension.
@subsection window_hints_values Supported and default values
| Name | Default value | Supported values |
| ---------------------------- | ------------------------- | ----------------------- |
| `GLFW_RESIZABLE` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_VISIBLE` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_DECORATED` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_AUTO_ICONIFY` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_FLOATING` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_GREEN_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_BLUE_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ALPHA_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_DEPTH_BITS` | 24 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_STENCIL_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ACCUM_RED_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ACCUM_GREEN_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ACCUM_BLUE_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ACCUM_ALPHA_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_AUX_BUFFERS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_SAMPLES` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_REFRESH_RATE` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_STEREO` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_SRGB_CAPABLE` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_DOUBLEBUFFER` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API` or `GLFW_OPENGL_ES_API` |
| `GLFW_CONTEXT_VERSION_MAJOR` | 1 | Any valid major version number of the chosen client API |
| `GLFW_CONTEXT_VERSION_MINOR` | 0 | Any valid minor version number of the chosen client API |
| `GLFW_CONTEXT_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET` |
| `GLFW_OPENGL_FORWARD_COMPAT` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_OPENGL_DEBUG_CONTEXT` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_OPENGL_PROFILE` | `GLFW_OPENGL_ANY_PROFILE` | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE` |
| Name | Default value | Supported values |
| ------------------------------- | --------------------------- | ----------------------- |
| `GLFW_RESIZABLE` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_VISIBLE` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_DECORATED` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_AUTO_ICONIFY` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_FLOATING` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_RED_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_GREEN_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_BLUE_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ALPHA_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_DEPTH_BITS` | 24 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_STENCIL_BITS` | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ACCUM_RED_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ACCUM_GREEN_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ACCUM_BLUE_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_ACCUM_ALPHA_BITS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_AUX_BUFFERS` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_SAMPLES` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_REFRESH_RATE` | 0 | 0 to `INT_MAX` or `GLFW_DONT_CARE` |
| `GLFW_STEREO` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_SRGB_CAPABLE` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_DOUBLEBUFFER` | `GL_TRUE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_CLIENT_API` | `GLFW_OPENGL_API` | `GLFW_OPENGL_API` or `GLFW_OPENGL_ES_API` |
| `GLFW_CONTEXT_VERSION_MAJOR` | 1 | Any valid major version number of the chosen client API |
| `GLFW_CONTEXT_VERSION_MINOR` | 0 | Any valid minor version number of the chosen client API |
| `GLFW_CONTEXT_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS` | `GLFW_NO_ROBUSTNESS`, `GLFW_NO_RESET_NOTIFICATION` or `GLFW_LOSE_CONTEXT_ON_RESET` |
| `GLFW_CONTEXT_RELEASE_BEHAVIOR` | `GLFW_ANY_RELEASE_BEHAVIOR` | `GLFW_ANY_RELEASE_BEHAVIOR`, `GLFW_RELEASE_BEHAVIOR_FLUSH` or `GLFW_RELEASE_BEHAVIOR_NONE` |
| `GLFW_OPENGL_FORWARD_COMPAT` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_OPENGL_DEBUG_CONTEXT` | `GL_FALSE` | `GL_TRUE` or `GL_FALSE` |
| `GLFW_OPENGL_PROFILE` | `GLFW_OPENGL_ANY_PROFILE` | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE` |
@section window_close Window close flag
......
......@@ -525,6 +525,7 @@ extern "C" {
#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006
#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007
#define GLFW_OPENGL_PROFILE 0x00022008
#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
#define GLFW_OPENGL_API 0x00030001
#define GLFW_OPENGL_ES_API 0x00030002
......@@ -545,6 +546,10 @@ extern "C" {
#define GLFW_CURSOR_HIDDEN 0x00034002
#define GLFW_CURSOR_DISABLED 0x00034003
#define GLFW_ANY_RELEASE_BEHAVIOR 0
#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002
#define GLFW_CONNECTED 0x00040001
#define GLFW_DISCONNECTED 0x00040002
......
......@@ -198,6 +198,17 @@ GLboolean _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
}
}
if (ctxconfig->release)
{
if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
{
_glfwInputError(GLFW_INVALID_VALUE,
"Invalid context release behavior requested");
return GL_FALSE;
}
}
return GL_TRUE;
}
......@@ -468,6 +479,17 @@ GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
}
}
if (glfwExtensionSupported("GL_KHR_context_flush_control"))
{
GLint behavior;
glGetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
if (behavior == GL_NONE)
window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
}
#endif // _GLFW_USE_OPENGL
return GL_TRUE;
......
......@@ -381,6 +381,9 @@ int _glfwCreateContext(_GLFWwindow* window,
setEGLattrib(EGL_NONE, EGL_NONE);
}
// Context release behaviors (GL_KHR_context_flush_control) are not yet
// supported on EGL but are not a hard constraint, so ignore and continue
window->egl.context = eglCreateContext(_glfw.egl.display,
config, share, attribs);
......
......@@ -255,6 +255,9 @@ int _glfwInitContextAPI(void)
if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile"))
_glfw.glx.EXT_create_context_es2_profile = GL_TRUE;
if (_glfwPlatformExtensionSupported("GLX_ARB_context_flush_control"))
_glfw.glx.ARB_context_flush_control = GL_TRUE;
return GL_TRUE;
}
......@@ -384,6 +387,23 @@ int _glfwCreateContext(_GLFWwindow* window,
}
}
if (ctxconfig->release)
{
if (_glfw.glx.ARB_context_flush_control)
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
}
}
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
// NOTE: Only request an explicitly versioned context when
......
......@@ -105,6 +105,7 @@ typedef struct _GLFWlibraryGLX
GLboolean ARB_create_context_profile;
GLboolean ARB_create_context_robustness;
GLboolean EXT_create_context_es2_profile;
GLboolean ARB_context_flush_control;
#if defined(_GLFW_DLOPEN_LIBGL)
void* libGL; // dlopen handle for libGL.so
......
......@@ -173,6 +173,7 @@ struct _GLFWctxconfig
GLboolean debug;
int profile;
int robustness;
int release;
_GLFWwindow* share;
};
......@@ -242,6 +243,7 @@ struct _GLFWwindow
GLboolean forward, debug;
int profile;
int robustness;
int release;
} context;
#if defined(_GLFW_USE_OPENGL)
......@@ -338,6 +340,7 @@ struct _GLFWlibrary
int debug;
int profile;
int robustness;
int release;
} hints;
double cursorPosX, cursorPosY;
......
......@@ -115,6 +115,9 @@ int _glfwCreateContext(_GLFWwindow* window,
// Context robustness modes (GL_KHR_robustness) are not yet supported on
// OS X but are not a hard constraint, so ignore and continue
// Context release behaviors (GL_KHR_context_flush_control) are not yet
// supported on OS X but are not a hard constraint, so ignore and continue
#define ADD_ATTR(x) { attributes[attributeCount++] = x; }
#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
......
......@@ -57,6 +57,7 @@ static void initWGLExtensions(_GLFWwindow* window)
window->wgl.ARB_create_context_robustness = GL_FALSE;
window->wgl.EXT_swap_control = GL_FALSE;
window->wgl.ARB_pixel_format = GL_FALSE;
window->wgl.ARB_context_flush_control = GL_FALSE;
window->wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
wglGetProcAddress("wglGetExtensionsStringEXT");
......@@ -119,6 +120,9 @@ static void initWGLExtensions(_GLFWwindow* window)
if (window->wgl.GetPixelFormatAttribivARB)
window->wgl.ARB_pixel_format = GL_TRUE;
}
if (_glfwPlatformExtensionSupported("WGL_ARB_context_flush_control"))
window->wgl.ARB_context_flush_control = GL_TRUE;
}
// Returns the specified attribute of the specified pixel format
......@@ -421,6 +425,23 @@ int _glfwCreateContext(_GLFWwindow* window,
}
}
if (ctxconfig->release)
{
if (window->wgl.ARB_context_flush_control)
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
}
}
}
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
// NOTE: Only request an explicitly versioned context when
......@@ -535,6 +556,12 @@ int _glfwAnalyzeContext(const _GLFWwindow* window,
required = GL_TRUE;
}
if (ctxconfig->release)
{
if (window->wgl.ARB_context_flush_control)
required = GL_TRUE;
}
}
else
{
......
......@@ -65,6 +65,7 @@ typedef struct _GLFWcontextWGL
GLboolean ARB_create_context_profile;
GLboolean EXT_create_context_es2_profile;
GLboolean ARB_create_context_robustness;
GLboolean ARB_context_flush_control;
} _GLFWcontextWGL;
......
......@@ -178,6 +178,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
ctxconfig.debug = _glfw.hints.debug ? GL_TRUE : GL_FALSE;
ctxconfig.profile = _glfw.hints.profile;
ctxconfig.robustness = _glfw.hints.robustness;
ctxconfig.release = _glfw.hints.release;
ctxconfig.share = (_GLFWwindow*) share;
// Check the OpenGL bits of the window config
......@@ -272,7 +273,7 @@ void glfwDefaultWindowHints(void)
memset(&_glfw.hints, 0, sizeof(_glfw.hints));
// The default is OpenGL with minimum version 1.0
_glfw.hints.api = GLFW_OPENGL_API;
_glfw.hints.api = GLFW_OPENGL_API;
_glfw.hints.major = 1;
_glfw.hints.minor = 0;
......@@ -383,6 +384,9 @@ GLFWAPI void glfwWindowHint(int target, int hint)
case GLFW_OPENGL_PROFILE:
_glfw.hints.profile = hint;
break;
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
_glfw.hints.release = hint;
break;
default:
_glfwInputError(GLFW_INVALID_ENUM, NULL);
break;
......@@ -623,6 +627,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->context.debug;
case GLFW_OPENGL_PROFILE:
return window->context.profile;
case GLFW_CONTEXT_RELEASE_BEHAVIOR:
return window->context.release;
}
_glfwInputError(GLFW_INVALID_ENUM, NULL);
......
......@@ -48,14 +48,18 @@
#define PROFILE_NAME_CORE "core"
#define PROFILE_NAME_COMPAT "compat"
#define STRATEGY_NAME_NONE "none"
#define STRATEGY_NAME_LOSE "lose"
#define STRATEGY_NAME_NONE "none"
#define STRATEGY_NAME_LOSE "lose"
#define BEHAVIOR_NAME_NONE "none"
#define BEHAVIOR_NAME_FLUSH "flush"
static void usage(void)
{
printf("Usage: glfwinfo [-h] [-a API] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-r STRATEGY]\n");
printf("Usage: glfwinfo [-h] [-a API] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-s STRATEGY] [-b BEHAVIOR]\n");
printf("Options:\n");
printf(" -a the client API to use (" API_OPENGL " or " API_OPENGL_ES ")\n");
printf(" -b the release behavior to use (" BEHAVIOR_NAME_NONE " or " BEHAVIOR_NAME_FLUSH ")\n");
printf(" -d request a debug context\n");
printf(" -f require a forward-compatible context\n");
printf(" -h show this help\n");
......@@ -63,7 +67,7 @@ static void usage(void)
printf(" -m the major number of the requred client API version\n");
printf(" -n the minor number of the requred client API version\n");
printf(" -p the OpenGL profile to use (" PROFILE_NAME_CORE " or " PROFILE_NAME_COMPAT ")\n");
printf(" -r the robustness strategy to use (" STRATEGY_NAME_NONE " or " STRATEGY_NAME_LOSE ")\n");
printf(" -s the robustness strategy to use (" STRATEGY_NAME_NONE " or " STRATEGY_NAME_LOSE ")\n");
}
static void error_callback(int error, const char* description)
......@@ -188,12 +192,12 @@ static GLboolean valid_version(void)
int main(int argc, char** argv)
{
int ch, api = 0, profile = 0, strategy = 0, major = 1, minor = 0, revision;
int ch, api = 0, profile = 0, strategy = 0, behavior = 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, "a:dfhlm:n:p:r:")) != -1)
while ((ch = getopt(argc, argv, "a:b:dfhlm:n:p:s:")) != -1)
{
switch (ch)
{
......@@ -208,6 +212,17 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE);
}
break;
case 'b':
if (strcasecmp(optarg, BEHAVIOR_NAME_NONE) == 0)
behavior = GLFW_RELEASE_BEHAVIOR_NONE;
else if (strcasecmp(optarg, BEHAVIOR_NAME_FLUSH) == 0)
behavior = GLFW_RELEASE_BEHAVIOR_FLUSH;
else
{
usage();
exit(EXIT_FAILURE);
}
break;
case 'd':
debug = GL_TRUE;
break;
......@@ -237,7 +252,7 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE);
}
break;
case 'r':
case 's':
if (strcasecmp(optarg, STRATEGY_NAME_NONE) == 0)
strategy = GLFW_NO_RESET_NOTIFICATION;
else if (strcasecmp(optarg, STRATEGY_NAME_LOSE) == 0)
......@@ -285,6 +300,9 @@ int main(int argc, char** argv)
if (strategy)
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, strategy);
if (behavior)
glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR, behavior);
glfwWindowHint(GLFW_RED_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_GREEN_BITS, GLFW_DONT_CARE);
glfwWindowHint(GLFW_BLUE_BITS, GLFW_DONT_CARE);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment