diff --git a/README.md b/README.md index 7ffa12f9..77911385 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs/window.dox b/docs/window.dox index de988eaa..098f0170 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -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 diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 13d0a52e..32173e50 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -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 diff --git a/src/context.c b/src/context.c index 61c3400d..fe94af76 100644 --- a/src/context.c +++ b/src/context.c @@ -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; diff --git a/src/egl_context.c b/src/egl_context.c index a0d77765..e5692928 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -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); diff --git a/src/glx_context.c b/src/glx_context.c index 2e33c369..562abf7f 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -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 diff --git a/src/glx_context.h b/src/glx_context.h index cc939d35..628232ef 100644 --- a/src/glx_context.h +++ b/src/glx_context.h @@ -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 diff --git a/src/internal.h b/src/internal.h index 252f20c0..59c03fdd 100644 --- a/src/internal.h +++ b/src/internal.h @@ -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; diff --git a/src/nsgl_context.m b/src/nsgl_context.m index faf6676d..cbdf284d 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -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); } diff --git a/src/wgl_context.c b/src/wgl_context.c index 792cca12..7b3b9c90 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -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 { diff --git a/src/wgl_context.h b/src/wgl_context.h index 0de99aec..e57072c6 100644 --- a/src/wgl_context.h +++ b/src/wgl_context.h @@ -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; diff --git a/src/window.c b/src/window.c index 448cf362..b937d3a2 100644 --- a/src/window.c +++ b/src/window.c @@ -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); diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index 12a5048b..dcf53537 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -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);