diff --git a/docs/window.dox b/docs/window.dox index 32271e3a..58dab33b 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -437,6 +437,18 @@ 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. +@anchor GLFW_CONTEXT_PRIORITY_hint +__GLFW_CONTEXT_PRIORITY__ specifies the context priority to be used by the +context. Possible values are one of `GLFW_PRIORITY_LOW`, `GLFW_PRIORITY_MEDIUM`, +`GLFW_PRIORITY_HIGH` or `GLFW_PRIORITY_REALTIME`. This functionality is currently +only implemented for the EGL context creating API. + +Context priorities are described in detail by the +[EGL_NV_context_priority_realtime](https://www.khronos.org/registry/EGL/extensions/NV/EGL_NV_context_priority_realtime.txt) +and +[EGL_IMG_context_priority](https://www.khronos.org/registry/EGL/extensions/IMG/EGL_IMG_context_priority.txt) +extensions. + @anchor GLFW_CONTEXT_NO_ERROR_hint __GLFW_CONTEXT_NO_ERROR__ specifies whether errors should be generated by the context. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. If enabled, @@ -531,6 +543,7 @@ GLFW_CONTEXT_VERSION_MAJOR | 1 | Any valid major ve 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_CONTEXT_PRIORITY | `GLFW_PRIORITY_MEDIUM` | `GLFW_PRIORITY_LOW`, `GLFW_PRIORITY_MEDIUM`, `GLFW_PRIORITY_HIGH`, `GLFW_PRIORITY_REALTIME` GLFW_OPENGL_FORWARD_COMPAT | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_CONTEXT_DEBUG | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_OPENGL_PROFILE | `GLFW_OPENGL_ANY_PROFILE` | `GLFW_OPENGL_ANY_PROFILE`, `GLFW_OPENGL_COMPAT_PROFILE` or `GLFW_OPENGL_CORE_PROFILE` diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 3f320065..8ab7f697 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1085,6 +1085,11 @@ extern "C" { * [window hint](@ref GLFW_SCALE_TO_MONITOR). */ #define GLFW_SCALE_TO_MONITOR 0x0002200C +/*! @brief Context priority. + * + * Context priority hint [hint](@ref GLFW_CONTEXT_PRIORITY_hint). + */ +#define GLFW_CONTEXT_PRIORITY 0x0002200D /*! @brief macOS specific * [window hint](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint). */ @@ -1146,6 +1151,11 @@ extern "C" { #define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007 #define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008 +#define GLFW_PRIORITY_LOW 0x00038001 +#define GLFW_PRIORITY_MEDIUM 0x00038002 +#define GLFW_PRIORITY_HIGH 0x00038003 +#define GLFW_PRIORITY_REALTIME 0x00038004 + /*! @defgroup shapes Standard cursor shapes * @brief Standard system cursor shapes. * diff --git a/src/context.c b/src/context.c index f6629f55..199a7d13 100644 --- a/src/context.c +++ b/src/context.c @@ -170,6 +170,20 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) } } + if (ctxconfig->priority) + { + if (ctxconfig->priority != GLFW_PRIORITY_LOW && + ctxconfig->priority != GLFW_PRIORITY_MEDIUM && + ctxconfig->priority != GLFW_PRIORITY_HIGH && + ctxconfig->priority != GLFW_PRIORITY_REALTIME) + { + _glfwInputError(GLFW_INVALID_ENUM, + "Invalid context priority 0x%08X", + ctxconfig->priority); + return GLFW_FALSE; + } + } + return GLFW_TRUE; } diff --git a/src/egl_context.c b/src/egl_context.c index f8850fa2..6c7a1cae 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -485,6 +485,8 @@ GLFWbool _glfwInitEGL(void) extensionSupportedEGL("EGL_KHR_context_flush_control"); _glfw.egl.EXT_present_opaque = extensionSupportedEGL("EGL_EXT_present_opaque"); + _glfw.egl.IMG_context_priority = + extensionSupportedEGL("EGL_IMG_context_priority"); return GLFW_TRUE; } @@ -634,6 +636,24 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, } } + if (_glfw.egl.IMG_context_priority && ctxconfig->priority != GLFW_PRIORITY_MEDIUM) + { + if (ctxconfig->priority == GLFW_PRIORITY_LOW) + { + SET_ATTRIB(EGL_CONTEXT_PRIORITY_LEVEL_IMG, + EGL_CONTEXT_PRIORITY_LOW_IMG); + } else if (ctxconfig->priority == GLFW_PRIORITY_HIGH) + { + SET_ATTRIB(EGL_CONTEXT_PRIORITY_LEVEL_IMG, + EGL_CONTEXT_PRIORITY_HIGH_IMG); + } + else if (ctxconfig->priority == GLFW_PRIORITY_REALTIME) + { + SET_ATTRIB(EGL_CONTEXT_PRIORITY_LEVEL_IMG, + EGL_CONTEXT_PRIORITY_REALTIME_NV); + } + } + SET_ATTRIB(EGL_NONE, EGL_NONE); window->context.egl.handle = eglCreateContext(_glfw.egl.display, diff --git a/src/internal.h b/src/internal.h index b7dc13a0..5d7fa4ad 100644 --- a/src/internal.h +++ b/src/internal.h @@ -187,6 +187,11 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint); #define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450 #define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489 #define EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE 0x348f +#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 +#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 +#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 +#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 +#define EGL_CONTEXT_PRIORITY_REALTIME_NV 0x3357 typedef int EGLint; typedef unsigned int EGLBoolean; @@ -441,6 +446,7 @@ struct _GLFWctxconfig int profile; int robustness; int release; + int priority; _GLFWwindow* share; struct { GLFWbool offline; @@ -810,6 +816,7 @@ struct _GLFWlibrary GLFWbool ANGLE_platform_angle_d3d; GLFWbool ANGLE_platform_angle_vulkan; GLFWbool ANGLE_platform_angle_metal; + GLFWbool IMG_context_priority; void* handle; diff --git a/src/window.c b/src/window.c index a24feb60..742bc01b 100644 --- a/src/window.c +++ b/src/window.c @@ -262,6 +262,7 @@ void glfwDefaultWindowHints(void) _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API; _glfw.hints.context.major = 1; _glfw.hints.context.minor = 0; + _glfw.hints.context.priority = GLFW_PRIORITY_MEDIUM; // The default is a focused, visible, resizable window with decorations memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window)); @@ -420,6 +421,9 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_REFRESH_RATE: _glfw.hints.refreshRate = value; return; + case GLFW_CONTEXT_PRIORITY: + _glfw.hints.context.priority = value; + return; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint); diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index 14347e4b..bebc384f 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -71,6 +71,11 @@ #define PLATFORM_NAME_X11 "x11" #define PLATFORM_NAME_NULL "null" +#define PRIORITY_LOW "low" +#define PRIORITY_MEDIUM "medium" +#define PRIORITY_HIGH "high" +#define PRIORITY_REALTIME "realtime" + static void usage(void) { printf("Usage: glfwinfo [OPTION]...\n"); @@ -133,6 +138,11 @@ static void usage(void) ANGLE_TYPE_METAL ")\n"); printf(" --graphics-switching request macOS graphics switching\n"); printf(" --disable-xcb-surface disable VK_KHR_xcb_surface extension\n"); + printf(" --priority=PRIORITY request context priority to use (" + PRIORITY_LOW "," + PRIORITY_MEDIUM "," + PRIORITY_HIGH "," + PRIORITY_REALTIME ")\n"); } static void error_callback(int error, const char* description) @@ -391,6 +401,7 @@ int main(int argc, char** argv) int context_robustness = GLFW_NO_ROBUSTNESS; bool context_debug = false; bool context_no_error = false; + int context_priority = GLFW_PRIORITY_MEDIUM; bool opengl_forward = false; int opengl_profile = GLFW_OPENGL_ANY_PROFILE; int fb_red_bits = 8; @@ -418,7 +429,7 @@ int main(int argc, char** argv) REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS, ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS, AUXBUFFERS, SAMPLES, STEREO, SRGB, SINGLEBUFFER, NOERROR_SRSLY, - ANGLE_TYPE, GRAPHICS_SWITCHING, XCB_SURFACE }; + ANGLE_TYPE, GRAPHICS_SWITCHING, XCB_SURFACE, PRIORITY }; const struct option options[] = { { "platform", 1, NULL, PLATFORM }, @@ -454,6 +465,7 @@ int main(int argc, char** argv) { "angle-type", 1, NULL, ANGLE_TYPE }, { "graphics-switching", 0, NULL, GRAPHICS_SWITCHING }, { "vk-xcb-surface", 0, NULL, XCB_SURFACE }, + { "priority", 1, NULL, PRIORITY }, { NULL, 0, NULL, 0 } }; @@ -682,6 +694,22 @@ int main(int argc, char** argv) case XCB_SURFACE: disable_xcb_surface = true; break; + case PRIORITY: + if (strcasecmp(optarg, PRIORITY_LOW) == 0) + context_priority = GLFW_PRIORITY_LOW; + else if (strcasecmp(optarg, PRIORITY_MEDIUM) == 0) + context_priority = GLFW_PRIORITY_MEDIUM; + else if (strcasecmp(optarg, PRIORITY_HIGH) == 0) + context_priority = GLFW_PRIORITY_HIGH; + else if (strcasecmp(optarg, PRIORITY_REALTIME) == 0) + context_priority = GLFW_PRIORITY_REALTIME; + else + { + usage(); + exit(EXIT_FAILURE); + } + break; + default: usage(); exit(EXIT_FAILURE); @@ -720,6 +748,7 @@ int main(int argc, char** argv) glfwWindowHint(GLFW_CONTEXT_NO_ERROR, context_no_error); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, opengl_forward); glfwWindowHint(GLFW_OPENGL_PROFILE, opengl_profile); + glfwWindowHint(GLFW_CONTEXT_PRIORITY, context_priority); glfwWindowHint(GLFW_RED_BITS, fb_red_bits); glfwWindowHint(GLFW_BLUE_BITS, fb_blue_bits);