From 0a898628ff1881764fed85668d3dc97711a30a74 Mon Sep 17 00:00:00 2001 From: Gregor Burger Date: Fri, 1 Apr 2022 12:52:12 +0200 Subject: [PATCH] EGL: add context priority for the EGL context creation API Allows to specify context priority low, medium, high or realtime if the extension is available. This is currently only implemented for the EGL context creation API. --- docs/window.dox | 13 +++++++++++++ include/GLFW/glfw3.h | 10 ++++++++++ src/context.c | 14 ++++++++++++++ src/egl_context.c | 20 ++++++++++++++++++++ src/internal.h | 7 +++++++ src/window.c | 4 ++++ tests/glfwinfo.c | 31 ++++++++++++++++++++++++++++++- 7 files changed, 98 insertions(+), 1 deletion(-) 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);