From 0f21f6c273f0f65eb9b5fd06d2bc5acf8701f397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Fri, 6 May 2022 16:40:13 +0200 Subject: glcontext: Make the creation of EGL context more obvious By splitting it into its own function it becomes more that the EGL code is a shared implementation. --- gdk/gdkglcontext.c | 296 +++++++++++++++++++++++++++-------------------------- 1 file changed, 151 insertions(+), 145 deletions(-) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 1678f3d85c..c0f96c0fec 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -1,7 +1,7 @@ /* GDK - The GIMP Drawing Kit * * gdkglcontext.c: GL context abstraction - * + * * Copyright © 2014 Emmanuele Bassi * * This library is free software; you can redistribute it and/or @@ -258,178 +258,185 @@ gdk_gl_context_get_property (GObject *object, #define N_EGL_ATTRS 16 static GdkGLAPI -gdk_gl_context_real_realize (GdkGLContext *context, - GError **error) +gdk_gl_context_realize_egl (GdkGLContext *context, + GError **error) { -#ifdef HAVE_EGL GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); GdkDisplay *display = gdk_gl_context_get_display (context); EGLDisplay egl_display = gdk_display_get_egl_display (display); - if (egl_display) - { - EGLConfig egl_config; - GdkGLContext *share = gdk_display_get_gl_context (display); - GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share); - EGLContext ctx; - EGLint context_attribs[N_EGL_ATTRS]; - int major, minor, flags; - gboolean debug_bit, forward_bit, legacy_bit; - GdkGLAPI api; - int i = 0; - G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME; - - if (share != NULL) - gdk_gl_context_get_required_version (share, &major, &minor); - else - gdk_gl_context_get_required_version (context, &major, &minor); + EGLConfig egl_config; + GdkGLContext *share = gdk_display_get_gl_context (display); + GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share); + EGLContext ctx; + EGLint context_attribs[N_EGL_ATTRS]; + int major, minor, flags; + gboolean debug_bit, forward_bit, legacy_bit; + GdkGLAPI api; + int i = 0; + G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME; + + if (share != NULL) + gdk_gl_context_get_required_version (share, &major, &minor); + else + gdk_gl_context_get_required_version (context, &major, &minor); - debug_bit = gdk_gl_context_get_debug_enabled (context); - forward_bit = gdk_gl_context_get_forward_compatible (context); - legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) || - (share != NULL && gdk_gl_context_is_legacy (share)); + debug_bit = gdk_gl_context_get_debug_enabled (context); + forward_bit = gdk_gl_context_get_forward_compatible (context); + legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) || + (share != NULL && gdk_gl_context_is_legacy (share)); - if (display->have_egl_no_config_context) - egl_config = NULL; - else - egl_config = gdk_display_get_egl_config (display); + if (display->have_egl_no_config_context) + egl_config = NULL; + else + egl_config = gdk_display_get_egl_config (display); - flags = 0; + flags = 0; - if (debug_bit) - flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; - if (forward_bit) - flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; + if (debug_bit) + flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; + if (forward_bit) + flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; - if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) && - eglBindAPI (EGL_OPENGL_API)) - { - /* We want a core profile, unless in legacy mode */ - context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; - context_attribs[i++] = legacy_bit - ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR - : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; - - /* Specify the version */ - context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR; - context_attribs[i++] = legacy_bit ? 3 : major; - context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR; - context_attribs[i++] = legacy_bit ? 0 : minor; - api = GDK_GL_API_GL; - } - else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) && - eglBindAPI (EGL_OPENGL_ES_API)) - { - context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION; - if (major == 3) - context_attribs[i++] = 3; - else - context_attribs[i++] = 2; - api = GDK_GL_API_GLES; - } + if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) && + eglBindAPI (EGL_OPENGL_API)) + { + /* We want a core profile, unless in legacy mode */ + context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; + context_attribs[i++] = legacy_bit + ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR + : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; + + /* Specify the version */ + context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR; + context_attribs[i++] = legacy_bit ? 3 : major; + context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR; + context_attribs[i++] = legacy_bit ? 0 : minor; + api = GDK_GL_API_GL; + } + else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) && + eglBindAPI (EGL_OPENGL_ES_API)) + { + context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION; + if (major == 3) + context_attribs[i++] = 3; else - { - g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, - _("The EGL implementation does not support any allowed APIs")); - return 0; - } + context_attribs[i++] = 2; + api = GDK_GL_API_GLES; + } + else + { + g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, + _("The EGL implementation does not support any allowed APIs")); + return 0; + } - /* Specify the flags */ + /* Specify the flags */ + context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR; + context_attribs[i++] = flags; + + context_attribs[i++] = EGL_NONE; + g_assert (i < N_EGL_ATTRS); + + GDK_DISPLAY_NOTE (display, OPENGL, + g_message ("Creating EGL context version %d.%d (debug:%s, forward:%s, legacy:%s, es:%s)", + major, minor, + debug_bit ? "yes" : "no", + forward_bit ? "yes" : "no", + legacy_bit ? "yes" : "no", + api == GDK_GL_API_GLES ? "yes" : "no")); + + ctx = eglCreateContext (egl_display, + egl_config, + share != NULL ? share_priv->egl_context + : EGL_NO_CONTEXT, + context_attribs); + + /* If context creation failed without the ES bit, let's try again with it */ + if (ctx == NULL && gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) && eglBindAPI (EGL_OPENGL_ES_API)) + { + i = 0; + context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION; + context_attribs[i++] = 2; + context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION; + context_attribs[i++] = 0; context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR; - context_attribs[i++] = flags; - + context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; context_attribs[i++] = EGL_NONE; g_assert (i < N_EGL_ATTRS); + legacy_bit = FALSE; + api = GDK_GL_API_GLES; + GDK_DISPLAY_NOTE (display, OPENGL, - g_message ("Creating EGL context version %d.%d (debug:%s, forward:%s, legacy:%s, es:%s)", - major, minor, - debug_bit ? "yes" : "no", - forward_bit ? "yes" : "no", - legacy_bit ? "yes" : "no", - api == GDK_GL_API_GLES ? "yes" : "no")); + g_message ("eglCreateContext failed, switching to OpenGL ES")); + ctx = eglCreateContext (egl_display, + egl_config, + share != NULL ? share_priv->egl_context + : EGL_NO_CONTEXT, + context_attribs); + } + + /* If context creation failed without the legacy bit, let's try again with it */ + if (ctx == NULL && gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) && eglBindAPI (EGL_OPENGL_API)) + { + i = 0; + context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; + context_attribs[i++] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; + context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION; + context_attribs[i++] = 3; + context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION; + context_attribs[i++] = 0; + context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR; + context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; + context_attribs[i++] = EGL_NONE; + g_assert (i < N_EGL_ATTRS); + legacy_bit = TRUE; + api = GDK_GL_API_GL; + + GDK_DISPLAY_NOTE (display, OPENGL, + g_message ("eglCreateContext failed, switching to legacy")); ctx = eglCreateContext (egl_display, egl_config, share != NULL ? share_priv->egl_context - : EGL_NO_CONTEXT, + : EGL_NO_CONTEXT, context_attribs); + } - /* If context creation failed without the ES bit, let's try again with it */ - if (ctx == NULL && gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) && eglBindAPI (EGL_OPENGL_ES_API)) - { - i = 0; - context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION; - context_attribs[i++] = 2; - context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION; - context_attribs[i++] = 0; - context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR; - context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; - context_attribs[i++] = EGL_NONE; - g_assert (i < N_EGL_ATTRS); - - legacy_bit = FALSE; - api = GDK_GL_API_GLES; - - GDK_DISPLAY_NOTE (display, OPENGL, - g_message ("eglCreateContext failed, switching to OpenGL ES")); - ctx = eglCreateContext (egl_display, - egl_config, - share != NULL ? share_priv->egl_context - : EGL_NO_CONTEXT, - context_attribs); - } + if (ctx == NULL) + { + g_set_error_literal (error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("Unable to create a GL context")); + return 0; + } - /* If context creation failed without the legacy bit, let's try again with it */ - if (ctx == NULL && gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) && eglBindAPI (EGL_OPENGL_API)) - { - i = 0; - context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; - context_attribs[i++] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; - context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION; - context_attribs[i++] = 3; - context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION; - context_attribs[i++] = 0; - context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR; - context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; - context_attribs[i++] = EGL_NONE; - g_assert (i < N_EGL_ATTRS); - - legacy_bit = TRUE; - api = GDK_GL_API_GL; - - GDK_DISPLAY_NOTE (display, OPENGL, - g_message ("eglCreateContext failed, switching to legacy")); - ctx = eglCreateContext (egl_display, - egl_config, - share != NULL ? share_priv->egl_context - : EGL_NO_CONTEXT, - context_attribs); - } + GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Created EGL context[%p]", ctx)); - if (ctx == NULL) - { - g_set_error_literal (error, GDK_GL_ERROR, - GDK_GL_ERROR_NOT_AVAILABLE, - _("Unable to create a GL context")); - return 0; - } + priv->egl_context = ctx; - GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Created EGL context[%p]", ctx)); + gdk_gl_context_set_is_legacy (context, legacy_bit); - priv->egl_context = ctx; + if (epoxy_has_egl_extension (egl_display, "EGL_KHR_swap_buffers_with_damage")) + priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageKHR"); + else if (epoxy_has_egl_extension (egl_display, "EGL_EXT_swap_buffers_with_damage")) + priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageEXT"); - gdk_gl_context_set_is_legacy (context, legacy_bit); + gdk_profiler_end_mark (start_time, "realize GdkWaylandGLContext", NULL); - if (epoxy_has_egl_extension (egl_display, "EGL_KHR_swap_buffers_with_damage")) - priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageKHR"); - else if (epoxy_has_egl_extension (egl_display, "EGL_EXT_swap_buffers_with_damage")) - priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageEXT"); + return api; +} - gdk_profiler_end_mark (start_time, "realize GdkWaylandGLContext", NULL); +static GdkGLAPI +gdk_gl_context_default_realize (GdkGLContext *context, + GError **error) +{ +#ifdef HAVE_EGL + GdkDisplay *display = gdk_gl_context_get_display (context); - return api; - } + if (gdk_display_get_egl_display (display)) + return gdk_gl_context_realize_egl (context, error); #endif g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, @@ -666,7 +673,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass); - klass->realize = gdk_gl_context_real_realize; + klass->realize = gdk_gl_context_default_realize; klass->get_damage = gdk_gl_context_real_get_damage; klass->is_shared = gdk_gl_context_real_is_shared; klass->make_current = gdk_gl_context_real_make_current; @@ -1799,7 +1806,7 @@ gboolean gdk_gl_backend_can_be_used (GdkGLBackend backend_type, GError **error) { - if (the_gl_backend_type == GDK_GL_NONE || + if (the_gl_backend_type == GDK_GL_NONE || the_gl_backend_type == backend_type) return TRUE; @@ -1837,4 +1844,3 @@ gdk_gl_backend_use (GdkGLBackend backend_type) g_assert (the_gl_backend_type == backend_type); } - -- cgit v1.2.1 From 826fdc4a801c0fa24dd82d175299b45d46108677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Mon, 30 May 2022 20:47:40 +0200 Subject: glcontext: Improve documentation on get_use_es api --- gdk/gdkglcontext.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index c0f96c0fec..c566f75e06 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -1348,7 +1348,9 @@ gdk_gl_context_set_use_es (GdkGLContext *context, * * Checks whether the @context is using an OpenGL or OpenGL ES profile. * - * Returns: %TRUE if the `GdkGLContext` is using an OpenGL ES profile + * Returns: %TRUE if the `GdkGLContext` is using an OpenGL ES profile; + * %FALSE if other profile is in use of if the @context has not yet + * been realized. */ gboolean gdk_gl_context_get_use_es (GdkGLContext *context) -- cgit v1.2.1 From 6bc3ecbe56fb83a530e017bd34c1bfdc803081dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Tue, 10 May 2022 00:21:40 +0200 Subject: glcontext: Improve get_version documentation --- gdk/gdkglcontext.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index c566f75e06..8f9fe25396 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -1676,6 +1676,10 @@ gdk_gl_context_get_shared_context (GdkGLContext *context) * Retrieves the OpenGL version of the @context. * * The @context must be realized prior to calling this function. + * + * If the @context has never been made current, the version cannot + * be known and it will return 0 for both @major and @minor. + * */ void gdk_gl_context_get_version (GdkGLContext *context, -- cgit v1.2.1 From 8d175801d73612b1ca49e9fd47c3c0fed17c7552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Mon, 30 May 2022 20:14:53 +0200 Subject: glcontext: Add internal get_clipped_version function It is useful for backends to get user set preferences while ensuring the correctness of the result, which will be always greater or equal than the minimum version provided --- gdk/gdkglcontext.c | 18 ++++++++++++++++++ gdk/gdkglcontextprivate.h | 5 +++++ 2 files changed, 23 insertions(+) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 8f9fe25396..484dee3200 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -1113,6 +1113,24 @@ gdk_gl_context_get_required_version (GdkGLContext *context, else min = default_minor; +void +gdk_gl_context_get_clipped_version (GdkGLContext *context, + int min_major, + int min_minor, + int *major, + int *minor) +{ + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); + int maj = min_major, min = min_minor; + + g_return_if_fail (GDK_IS_GL_CONTEXT (context)); + + if (priv->major > maj || (priv->major == maj && priv->minor > min)) + { + maj = priv->major; + min = priv->minor; + } + if (major != NULL) *major = maj; if (minor != NULL) diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h index 0a3739f090..b97d07f34f 100644 --- a/gdk/gdkglcontextprivate.h +++ b/gdk/gdkglcontextprivate.h @@ -117,6 +117,11 @@ gboolean gdk_gl_context_check_version (GdkGLContext int required_gl_minor, int required_gles_major, int required_gles_minor); +void gdk_gl_context_get_clipped_version (GdkGLContext *context, + int min_major, + int min_minor, + int *major, + int *minor); gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context); void gdk_gl_context_push_debug_group (GdkGLContext *context, -- cgit v1.2.1 From d4f8a80f2a3d1043a37a69c2302b8293b48a4165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Sat, 28 May 2022 00:58:43 +0200 Subject: glcontext-win32-wgl: Respect user required version, use display as minimum By setting and then getting the required version in a context, the code was not respecting user requirements. Instead, simply get the requested version by the user clipped by the requirements (display version) --- gdk/win32/gdkglcontext-win32-wgl.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/gdk/win32/gdkglcontext-win32-wgl.c b/gdk/win32/gdkglcontext-win32-wgl.c index 231f2a6a01..d7ff4367f2 100644 --- a/gdk/win32/gdkglcontext-win32-wgl.c +++ b/gdk/win32/gdkglcontext-win32-wgl.c @@ -548,17 +548,12 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context, * wglCreateContextAttribsARB() may only give us the GL context version * that we ask for here, and nothing more. So, improve things here by * asking for the GL version that is reported to us via epoxy_gl_version(), - * rather than the default GL core 3.2 context. Save this up in our - * GdkGLContext so that subsequent contexts that are shared with this - * context are created likewise too. + * rather than the default GL core 3.2 context. */ - if (share != NULL) - gdk_gl_context_get_required_version (share, &major, &minor); - else - { - major = display_win32->gl_version / 10; - minor = display_win32->gl_version % 10; - } + gdk_gl_context_get_clipped_version (context, + display_win32->gl_version / 10, + display_win32->gl_version % 10, + &major, &minor); if (surface != NULL) hdc = GDK_WIN32_SURFACE (surface)->hdc; @@ -626,7 +621,6 @@ gdk_win32_gl_context_wgl_realize (GdkGLContext *context, /* Ensure that any other context is created with a legacy bit set */ gdk_gl_context_set_is_legacy (context, legacy_bit); - gdk_gl_context_set_required_version (context, major, minor); return GDK_GL_API_GL; } -- cgit v1.2.1 From f4f0daa113ecd8bdec4e1f09cd00407c648650c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Sat, 28 May 2022 01:01:19 +0200 Subject: macosglcontext: Do not rely on default from get_required_version get_required_version cannot warranty to return any default. Instead, fetch the user requisites clipped by the requirements in our backend. --- gdk/macos/gdkmacosglcontext.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c index ff7ae975c8..069d138b83 100644 --- a/gdk/macos/gdkmacosglcontext.c +++ b/gdk/macos/gdkmacosglcontext.c @@ -378,7 +378,10 @@ gdk_macos_gl_context_real_realize (GdkGLContext *context, existing = CGLGetCurrentContext (); - gdk_gl_context_get_required_version (context, &major, &minor); + gdk_gl_context_get_clipped_version (context, + GDK_GL_MIN_GL_VERSION_MAJOR, + GDK_GL_MIN_GL_VERSION_MINOR, + &major, &minor); display = gdk_gl_context_get_display (context); shared = gdk_display_get_gl_context (display); -- cgit v1.2.1 From 549a2b4c866e988b791244ca5d67d16bdbf5e006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Fri, 6 May 2022 21:43:30 +0200 Subject: glcontext: Refactor realize function, fix interaction with shared context --- gdk/gdkglcontext.c | 257 ++++++++++++++++++++++++++-------------------- gdk/gdkglcontextprivate.h | 21 ++++ 2 files changed, 166 insertions(+), 112 deletions(-) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 484dee3200..41f261f2d8 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -255,83 +255,83 @@ gdk_gl_context_get_property (GObject *object, } } -#define N_EGL_ATTRS 16 +#define N_EGL_ATTRS 16 + +#ifdef HAVE_EGL +static inline EGLenum +gdk_api_to_egl_api (GdkGLAPI api) +{ + switch (api) + { + case GDK_GL_API_GLES: + return EGL_OPENGL_ES_API; + case GDK_GL_API_GL: + default: + return EGL_OPENGL_API; + } +} static GdkGLAPI -gdk_gl_context_realize_egl (GdkGLContext *context, - GError **error) +gdk_gl_context_create_egl_context (GdkGLContext *context, + GdkGLAPI api, + gboolean legacy) { GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); GdkDisplay *display = gdk_gl_context_get_display (context); EGLDisplay egl_display = gdk_display_get_egl_display (display); - - EGLConfig egl_config; GdkGLContext *share = gdk_display_get_gl_context (display); GdkGLContextPrivate *share_priv = gdk_gl_context_get_instance_private (share); + EGLConfig egl_config; EGLContext ctx; - EGLint context_attribs[N_EGL_ATTRS]; - int major, minor, flags; - gboolean debug_bit, forward_bit, legacy_bit; - GdkGLAPI api; - int i = 0; + EGLint context_attribs[N_EGL_ATTRS], i = 0, flags = 0; + gboolean debug_bit, forward_bit; + int min_major, min_minor, major = 0, minor = 0; G_GNUC_UNUSED gint64 start_time = GDK_PROFILER_CURRENT_TIME; - if (share != NULL) - gdk_gl_context_get_required_version (share, &major, &minor); - else - gdk_gl_context_get_required_version (context, &major, &minor); + if (!gdk_gl_context_is_api_allowed (context, api, NULL)) + return 0; + + /* We will use the default version matching the context status + * unless the user requested a version which makes sense */ + gdk_gl_context_get_matching_version (api, legacy, + display->have_egl_win32_libangle, + &min_major, &min_minor); + gdk_gl_context_get_clipped_version (context, + min_major, min_minor, + &major, &minor); + + if (!eglBindAPI (gdk_api_to_egl_api (api))) + return 0; debug_bit = gdk_gl_context_get_debug_enabled (context); forward_bit = gdk_gl_context_get_forward_compatible (context); - legacy_bit = GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) || - (share != NULL && gdk_gl_context_is_legacy (share)); if (display->have_egl_no_config_context) egl_config = NULL; else egl_config = gdk_display_get_egl_config (display); - flags = 0; - if (debug_bit) flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; if (forward_bit) flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; - if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) && - eglBindAPI (EGL_OPENGL_API)) + if (api == GDK_GL_API_GL) { /* We want a core profile, unless in legacy mode */ - context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; - context_attribs[i++] = legacy_bit - ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR - : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; - - /* Specify the version */ - context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION_KHR; - context_attribs[i++] = legacy_bit ? 3 : major; - context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION_KHR; - context_attribs[i++] = legacy_bit ? 0 : minor; - api = GDK_GL_API_GL; - } - else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) && - eglBindAPI (EGL_OPENGL_ES_API)) - { - context_attribs[i++] = EGL_CONTEXT_CLIENT_VERSION; - if (major == 3) - context_attribs[i++] = 3; - else - context_attribs[i++] = 2; - api = GDK_GL_API_GLES; - } - else - { - g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE, - _("The EGL implementation does not support any allowed APIs")); - return 0; + context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK; + context_attribs[i++] = legacy + ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT + : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT; } - /* Specify the flags */ + if (legacy || api == GDK_GL_API_GLES) + flags &= ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; + + context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION; + context_attribs[i++] = major; + context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION; + context_attribs[i++] = minor; context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR; context_attribs[i++] = flags; @@ -343,91 +343,82 @@ gdk_gl_context_realize_egl (GdkGLContext *context, major, minor, debug_bit ? "yes" : "no", forward_bit ? "yes" : "no", - legacy_bit ? "yes" : "no", + legacy ? "yes" : "no", api == GDK_GL_API_GLES ? "yes" : "no")); ctx = eglCreateContext (egl_display, egl_config, - share != NULL ? share_priv->egl_context - : EGL_NO_CONTEXT, + share ? share_priv->egl_context : EGL_NO_CONTEXT, context_attribs); - /* If context creation failed without the ES bit, let's try again with it */ - if (ctx == NULL && gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) && eglBindAPI (EGL_OPENGL_ES_API)) - { - i = 0; - context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION; - context_attribs[i++] = 2; - context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION; - context_attribs[i++] = 0; - context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR; - context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; - context_attribs[i++] = EGL_NONE; - g_assert (i < N_EGL_ATTRS); - - legacy_bit = FALSE; - api = GDK_GL_API_GLES; - - GDK_DISPLAY_NOTE (display, OPENGL, - g_message ("eglCreateContext failed, switching to OpenGL ES")); - ctx = eglCreateContext (egl_display, - egl_config, - share != NULL ? share_priv->egl_context - : EGL_NO_CONTEXT, - context_attribs); - } - - /* If context creation failed without the legacy bit, let's try again with it */ - if (ctx == NULL && gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) && eglBindAPI (EGL_OPENGL_API)) - { - i = 0; - context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; - context_attribs[i++] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; - context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION; - context_attribs[i++] = 3; - context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION; - context_attribs[i++] = 0; - context_attribs[i++] = EGL_CONTEXT_FLAGS_KHR; - context_attribs[i++] = flags & ~EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; - context_attribs[i++] = EGL_NONE; - g_assert (i < N_EGL_ATTRS); - - legacy_bit = TRUE; - api = GDK_GL_API_GL; - - GDK_DISPLAY_NOTE (display, OPENGL, - g_message ("eglCreateContext failed, switching to legacy")); - ctx = eglCreateContext (egl_display, - egl_config, - share != NULL ? share_priv->egl_context - : EGL_NO_CONTEXT, - context_attribs); - } - if (ctx == NULL) - { - g_set_error_literal (error, GDK_GL_ERROR, - GDK_GL_ERROR_NOT_AVAILABLE, - _("Unable to create a GL context")); return 0; - } GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Created EGL context[%p]", ctx)); priv->egl_context = ctx; - - gdk_gl_context_set_is_legacy (context, legacy_bit); + gdk_gl_context_set_is_legacy (context, legacy); if (epoxy_has_egl_extension (egl_display, "EGL_KHR_swap_buffers_with_damage")) - priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageKHR"); + priv->eglSwapBuffersWithDamage = (gpointer) epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageKHR"); else if (epoxy_has_egl_extension (egl_display, "EGL_EXT_swap_buffers_with_damage")) - priv->eglSwapBuffersWithDamage = (gpointer)epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageEXT"); + priv->eglSwapBuffersWithDamage = (gpointer) epoxy_eglGetProcAddress ("eglSwapBuffersWithDamageEXT"); gdk_profiler_end_mark (start_time, "realize GdkWaylandGLContext", NULL); return api; } +static GdkGLAPI +gdk_gl_context_realize_egl (GdkGLContext *context, + GError **error) +{ + GdkDisplay *display = gdk_gl_context_get_display (context); + GdkGLContext *share = gdk_display_get_gl_context (display); + GdkGLAPI api, preferred_api; + gboolean prefer_legacy; + + if (share && gdk_gl_context_is_api_allowed (context, + gdk_gl_context_get_api (share), + NULL)) + preferred_api = gdk_gl_context_get_api (share); + else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL)) + preferred_api = GDK_GL_API_GL; + else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL)) + preferred_api = GDK_GL_API_GLES; + else + { + g_set_error_literal (error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("No GL API allowed.")); + return 0; + } + + prefer_legacy = (GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY) || + (share != NULL && gdk_gl_context_is_legacy (share))); + + if (preferred_api == GDK_GL_API_GL) + { + if ((api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GL, prefer_legacy)) || + (api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GLES, FALSE)) || + (api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GL, TRUE))) + return api; + } + else + { + if ((api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GLES, FALSE)) || + (api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GL, prefer_legacy)) || + (api = gdk_gl_context_create_egl_context (context, GDK_GL_API_GL, TRUE))) + return api; + } + + g_set_error_literal (error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("Unable to create a GL context")); + return 0; +} +#endif /* HAVE_EGL */ + static GdkGLAPI gdk_gl_context_default_realize (GdkGLContext *context, GError **error) @@ -966,6 +957,48 @@ gdk_gl_context_get_forward_compatible (GdkGLContext *context) return priv->forward_compatible; } +void +gdk_gl_context_get_matching_version (GdkGLAPI api, + gboolean legacy, + gboolean win32_libangle, + int *major, + int *minor) +{ + int maj, min; + + if (api == GDK_GL_API_GL) + { + if (legacy) + { + maj = GDK_GL_MIN_GL_LEGACY_VERSION_MAJOR; + min = GDK_GL_MIN_GL_LEGACY_VERSION_MINOR; + } + else + { + maj = GDK_GL_MIN_GL_VERSION_MAJOR; + min = GDK_GL_MIN_GL_VERSION_MINOR; + } + } + else + { + if (win32_libangle) + { + maj = GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MAJOR; + min = GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MINOR; + } + else + { + maj = GDK_GL_MIN_GLES_VERSION_MAJOR; + min = GDK_GL_MIN_GLES_VERSION_MINOR; + } + } + + if (major != NULL) + *major = maj; + if (minor != NULL) + *minor = min; +} + /** * gdk_gl_context_set_required_version: * @context: a `GdkGLContext` diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h index b97d07f34f..7537b71225 100644 --- a/gdk/gdkglcontextprivate.h +++ b/gdk/gdkglcontextprivate.h @@ -33,6 +33,22 @@ G_BEGIN_DECLS #define GDK_EGL_MIN_VERSION_MAJOR (1) #define GDK_EGL_MIN_VERSION_MINOR (4) +/* Minimum OpenGL versions supported by GTK. + * Backends should make sure to never create a context of a previous version. + * + * The macros refer to OpenGL; OpenGL with OPENGL_COMPATIBILITY_PROFILE_BIT as + * OPENGL_PROFILE_MASK; OpenGL ES; and OpenGL ES win32 Angle implementation, + * respectively + */ +#define GDK_GL_MIN_GL_VERSION_MAJOR (3) +#define GDK_GL_MIN_GL_VERSION_MINOR (2) +#define GDK_GL_MIN_GL_LEGACY_VERSION_MAJOR (3) +#define GDK_GL_MIN_GL_LEGACY_VERSION_MINOR (0) +#define GDK_GL_MIN_GLES_VERSION_MAJOR (2) +#define GDK_GL_MIN_GLES_VERSION_MINOR (0) +#define GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MAJOR (3) +#define GDK_GL_MIN_GLES_WIN32_ANGLE_VERSION_MINOR (0) + typedef enum { GDK_GL_NONE = 0, GDK_GL_EGL, @@ -122,6 +138,11 @@ void gdk_gl_context_get_clipped_version (GdkGLContext int min_minor, int *major, int *minor); +void gdk_gl_context_get_matching_version (GdkGLAPI api, + gboolean legacy, + gboolean win32_libangle, + int *major, + int *minor); gboolean gdk_gl_context_has_unpack_subimage (GdkGLContext *context); void gdk_gl_context_push_debug_group (GdkGLContext *context, -- cgit v1.2.1 From f97cff14541d0d24637a2971db1589e707baaedf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Mon, 30 May 2022 21:11:28 +0200 Subject: glcontext-glx: Refactor realize function Mimic the behavior of the egl context creation by stablishing some sane logic for the api and version used. Split the decision of the type of context (api, legacy) and the creation of a context of a certain version and all its properties. --- gdk/x11/gdkglcontext-glx.c | 309 +++++++++++++++++++++------------------------ 1 file changed, 142 insertions(+), 167 deletions(-) diff --git a/gdk/x11/gdkglcontext-glx.c b/gdk/x11/gdkglcontext-glx.c index d768ccf35c..d9e60bd747 100644 --- a/gdk/x11/gdkglcontext-glx.c +++ b/gdk/x11/gdkglcontext-glx.c @@ -213,7 +213,7 @@ gdk_x11_gl_context_glx_clear_current (GdkGLContext *context) static gboolean gdk_x11_gl_context_glx_make_current (GdkGLContext *context, gboolean surfaceless) - + { GdkX11GLContextGLX *self = GDK_X11_GL_CONTEXT_GLX (context); GdkDisplay *display = gdk_gl_context_get_display (context); @@ -302,68 +302,6 @@ gdk_x11_gl_context_glx_get_damage (GdkGLContext *context) return GDK_GL_CONTEXT_CLASS (gdk_x11_gl_context_glx_parent_class)->get_damage (context); } -static GLXContext -create_gl3_context (GdkDisplay *display, - GLXFBConfig config, - GdkGLContext *share, - int profile, - int flags, - int major, - int minor) -{ - int attrib_list[] = { - GLX_CONTEXT_PROFILE_MASK_ARB, profile, - GLX_CONTEXT_MAJOR_VERSION_ARB, major, - GLX_CONTEXT_MINOR_VERSION_ARB, minor, - GLX_CONTEXT_FLAGS_ARB, flags, - None, - }; - GLXContext res; - - GdkX11GLContextGLX *share_glx = NULL; - - if (share != NULL) - share_glx = GDK_X11_GL_CONTEXT_GLX (share); - - gdk_x11_display_error_trap_push (display); - - res = glXCreateContextAttribsARB (gdk_x11_display_get_xdisplay (display), - config, - share_glx != NULL ? share_glx->glx_context : NULL, - True, - attrib_list); - - if (gdk_x11_display_error_trap_pop (display)) - return NULL; - - return res; -} - -static GLXContext -create_legacy_context (GdkDisplay *display, - GLXFBConfig config, - GdkGLContext *share) -{ - GdkX11GLContextGLX *share_glx = NULL; - GLXContext res; - - if (share != NULL) - share_glx = GDK_X11_GL_CONTEXT_GLX (share); - - gdk_x11_display_error_trap_push (display); - - res = glXCreateNewContext (gdk_x11_display_get_xdisplay (display), - config, - GLX_RGBA_TYPE, - share_glx != NULL ? share_glx->glx_context : NULL, - TRUE); - - if (gdk_x11_display_error_trap_pop (display)) - return NULL; - - return res; -} - #ifdef HAVE_XDAMAGE static void bind_context_for_frame_fence (GdkX11GLContextGLX *self) @@ -507,134 +445,111 @@ on_surface_state_changed (GdkGLContext *context) */ finish_frame (context); } -#endif +#endif /* HAVE_XDAMAGE */ + +#define N_GLX_ATTRS 16 static GdkGLAPI -gdk_x11_gl_context_glx_realize (GdkGLContext *context, - GError **error) +gdk_x11_context_create_glx_context (GdkGLContext *context, + GdkGLAPI api, + gboolean legacy) { - GdkX11Display *display_x11; - GdkDisplay *display; - GdkX11GLContextGLX *context_glx; - Display *dpy; - GdkSurface *surface; - GdkGLContext *share; - gboolean debug_bit, compat_bit, legacy_bit; - int major, minor, flags; - GdkGLAPI api = 0; + GdkX11GLContextGLX *context_glx = GDK_X11_GL_CONTEXT_GLX (context);; + GdkDisplay *display = gdk_gl_context_get_display (context); + GdkX11Display *display_x11 = GDK_X11_DISPLAY (display); + Display *dpy = gdk_x11_display_get_xdisplay (display); + GdkGLContext *share = gdk_display_get_gl_context (display); + GdkX11GLContextGLX *share_glx = NULL; + GdkSurface *surface = gdk_gl_context_get_surface (context); + GLXContext ctx; + int context_attribs[N_GLX_ATTRS], i = 0, flags = 0; + int min_major, min_minor, major, minor; + gboolean debug_bit, compat_bit; - display = gdk_gl_context_get_display (context); - dpy = gdk_x11_display_get_xdisplay (display); - context_glx = GDK_X11_GL_CONTEXT_GLX (context); - display_x11 = GDK_X11_DISPLAY (display); - share = gdk_display_get_gl_context (display); - surface = gdk_gl_context_get_surface (context); + if (!gdk_gl_context_is_api_allowed (context, api, NULL)) + return 0; - gdk_gl_context_get_required_version (context, &major, &minor); - debug_bit = gdk_gl_context_get_debug_enabled (context); - compat_bit = gdk_gl_context_get_forward_compatible (context); + if (api == GDK_GL_API_GLES && legacy) + return 0; - /* If there is no glXCreateContextAttribsARB() then we default to legacy */ - legacy_bit = !display_x11->has_glx_create_context || GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY); + /* We will use the default version matching the context status + * unless the user requested a version which makes sense */ + gdk_gl_context_get_matching_version (api, legacy, 0, + &min_major, &min_minor); + gdk_gl_context_get_clipped_version (context, min_major, min_minor, + &major, &minor); - /* We cannot share legacy contexts with core profile ones, so the - * shared context is the one that decides if we're going to create - * a legacy context or not. - */ - if (share != NULL && gdk_gl_context_is_legacy (share)) - legacy_bit = TRUE; + debug_bit = gdk_gl_context_get_debug_enabled (context); + compat_bit = gdk_gl_context_get_forward_compatible (context); - flags = 0; if (debug_bit) flags |= GLX_CONTEXT_DEBUG_BIT_ARB; if (compat_bit) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; - GDK_DISPLAY_NOTE (display, OPENGL, - g_message ("Creating GLX context (GL version:%d.%d, debug:%s, forward:%s, legacy:%s, GL:%s, GLES:%s)", - major, minor, - debug_bit ? "yes" : "no", - compat_bit ? "yes" : "no", - legacy_bit ? "yes" : "no", - gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL) ? "yes" : "no", - gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL) ? "yes" : "no")); - - /* If we have access to GLX_ARB_create_context_profile then we can ask for - * a compatibility profile; if we don't, then we have to fall back to the - * old GLX 1.3 API. - */ - if (legacy_bit && !GDK_X11_DISPLAY (display)->has_glx_create_context) - { - GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Creating legacy GL context on request")); - /* do it below */ - } - else - { - if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL)) - { - int profile = legacy_bit ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB - : GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + context_attribs[i++] = GLX_CONTEXT_PROFILE_MASK_ARB; + if (api == GDK_GL_API_GL) + if (legacy) + context_attribs[i++] = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + else + context_attribs[i++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else if (api == GDK_GL_API_GLES) + context_attribs[i++] = GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + + context_attribs[i++] = GLX_CONTEXT_MAJOR_VERSION_ARB; + context_attribs[i++] = major; + context_attribs[i++] = GLX_CONTEXT_MINOR_VERSION_ARB; + context_attribs[i++] = minor; + context_attribs[i++] = GLX_CONTEXT_FLAGS_ARB; + context_attribs[i++] = flags; + + context_attribs[i++] = None; + g_assert (i < N_GLX_ATTRS); - /* We need to tweak the version, otherwise we may end up requesting - * a compatibility context with a minimum version of 3.2, which is - * an error - */ - if (legacy_bit) - { - major = 3; - minor = 0; - } + GDK_DISPLAY_NOTE (display, OPENGL, + g_message ("Creating GLX context version %d.%d (debug:%s, forward:%s, legacy:%s, es:%s)", + major, minor, + debug_bit ? "yes" : "no", + compat_bit ? "yes" : "no", + legacy ? "yes" : "no", + api == GDK_GL_API_GLES ? "yes" : "no")); - GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Creating GL3 context")); - context_glx->glx_context = create_gl3_context (display, - display_x11->glx_config, - share, - profile, - flags, major, minor); - api = GDK_GL_API_GL; - } + if (share != NULL) + share_glx = GDK_X11_GL_CONTEXT_GLX (share); - if (context_glx->glx_context == NULL && !legacy_bit && - gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL)) - { - GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Creating GL3 GLES context")); - context_glx->glx_context = create_gl3_context (display, - display_x11->glx_config, - share, - GLX_CONTEXT_ES2_PROFILE_BIT_EXT, - flags, major, minor); - api = GDK_GL_API_GLES; - } - } + gdk_x11_display_error_trap_push (display); - /* Fall back to legacy in case the GL3 context creation failed */ - if (context_glx->glx_context == NULL && - gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL)) - { - GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Creating fallback legacy context")); - context_glx->glx_context = create_legacy_context (display, display_x11->glx_config, share); - legacy_bit = TRUE; - api = GDK_GL_API_GL; - } + /* If we don't have access to GLX_ARB_create_context_profile, then + * we have to fall back to the old GLX 1.3 API. + */ + if (legacy && !display_x11->has_glx_create_context) + ctx = glXCreateNewContext (gdk_x11_display_get_xdisplay (display), + display_x11->glx_config, + GLX_RGBA_TYPE, + share_glx != NULL ? share_glx->glx_context : NULL, + TRUE); - if (context_glx->glx_context == NULL) - { - g_set_error_literal (error, GDK_GL_ERROR, - GDK_GL_ERROR_NOT_AVAILABLE, - _("Unable to create a GL context")); - return 0; - } + else + ctx = glXCreateContextAttribsARB (gdk_x11_display_get_xdisplay (display), + display_x11->glx_config, + share_glx != NULL ? share_glx->glx_context : NULL, + True, + context_attribs); - /* Ensure that any other context is created with a legacy bit set */ - gdk_gl_context_set_is_legacy (context, legacy_bit); + if (gdk_x11_display_error_trap_pop (display) || ctx == NULL) + return 0; GDK_DISPLAY_NOTE (display, OPENGL, g_message ("Realized GLX context[%p], %s, version: %d.%d", context_glx->glx_context, glXIsDirect (dpy, context_glx->glx_context) ? "direct" : "indirect", display_x11->glx_version / 10, + display_x11->glx_version % 10)); + context_glx->glx_context = ctx; + gdk_gl_context_set_is_legacy (context, legacy); + #ifdef HAVE_XDAMAGE if (display_x11->have_damage && display_x11->has_async_glx_swap_buffers) @@ -663,10 +578,70 @@ gdk_x11_gl_context_glx_realize (GdkGLContext *context, } } #endif - return api; } +static GdkGLAPI +gdk_x11_gl_context_glx_realize (GdkGLContext *context, + GError **error) +{ + GdkDisplay *display = gdk_gl_context_get_display (context); + GdkGLContext *share = gdk_display_get_gl_context (display); + gboolean legacy; + GdkGLAPI api, preferred_api; + + if (share && gdk_gl_context_is_api_allowed (context, + gdk_gl_context_get_api (share), + NULL)) + preferred_api = gdk_gl_context_get_api (share); + else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GL, NULL)) + preferred_api = GDK_GL_API_GL; + else if (gdk_gl_context_is_api_allowed (context, GDK_GL_API_GLES, NULL)) + preferred_api = GDK_GL_API_GLES; + else + { + g_set_error_literal (error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("No GL API allowed.")); + return 0; + } + + /* If there is no glXCreateContextAttribsARB() then we default to legacy */ + legacy = !GDK_X11_DISPLAY (display)->has_glx_create_context; + + if (GDK_DISPLAY_DEBUG_CHECK (display, GL_LEGACY)) + legacy = TRUE; + + /* We cannot share legacy contexts with core profile ones, so the + * shared context is the one that decides if we're going to create + * a legacy context or not. + */ + if (share != NULL && gdk_gl_context_is_legacy (share)) + legacy = TRUE; + + if (preferred_api == GDK_GL_API_GL) + { + if ((api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, legacy)) || + (api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GLES, legacy)) || + (api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, TRUE))) + return api; + } + else + { + if ((api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GLES, FALSE)) || + (api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, legacy)) || + (api = gdk_x11_context_create_glx_context (context, GDK_GL_API_GL, TRUE))) + return api; + } + + g_set_error_literal (error, GDK_GL_ERROR, + GDK_GL_ERROR_NOT_AVAILABLE, + _("Unable to create a GL context")); + return 0; +} + +#undef N_GLX_ATTRS + static void gdk_x11_gl_context_glx_dispose (GObject *gobject) { @@ -820,7 +795,7 @@ gdk_x11_display_create_glx_config (GdkX11Display *self, XFree (visinfo); continue; } - + if (!visual_is_rgba (visinfo)) { if (best_features < NO_ALPHA_VISUAL) @@ -894,7 +869,7 @@ gdk_x11_display_get_glx_version (GdkDisplay *display, /*< private > * gdk_x11_display_init_glx: - * @display_x11: an X11 display that has not been inited yet. + * @display_x11: an X11 display that has not been inited yet. * @out_visual: set to the Visual to be used with the returned config * @out_depth: set to the depth to be used with the returned config * @error: Return location for error -- cgit v1.2.1 From 9426b20759d81673ccecf0de35d307878acdddcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Wed, 25 May 2022 15:23:38 +0200 Subject: glcontext: Do not check for correctness in set_required_version There are two reasons for this: * First, the refactored realize code now makes sure that no context with unsupported version is ever created. * Second, this code could bump into false possitives and negatives, since the user is not requested, nor expected to set_required_version in any specific order relative to set_allowed_apis. Therefore, some version could be rejected or accepted based on a set of allowed apis that the user has not yet correctly configured. --- gdk/gdkglcontext.c | 41 ++++++----------------------------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 41f261f2d8..78080a236b 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -1009,7 +1009,10 @@ gdk_gl_context_get_matching_version (GdkGLAPI api, * * Setting @major and @minor to zero will use the default values. * - * The `GdkGLContext` must not be realized or made current prior to calling + * Setting @major and @minor lower than the minimum versions required + * by GTK will result in the context choosing the minimum version. + * + * The @context must not be realized or made current prior to calling * this function. */ void @@ -1018,44 +1021,12 @@ gdk_gl_context_set_required_version (GdkGLContext *context, int minor) { GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); - gboolean force_gles = FALSE; - int version, min_ver; -#ifdef G_ENABLE_DEBUG - GdkDisplay *display; -#endif g_return_if_fail (GDK_IS_GL_CONTEXT (context)); g_return_if_fail (!gdk_gl_context_is_realized (context)); - /* this will take care of the default */ - if (major == 0 && minor == 0) - { - priv->major = 0; - priv->minor = 0; - return; - } - - version = (major * 100) + minor; - -#ifdef G_ENABLE_DEBUG - display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)); - force_gles = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES); -#endif - /* Enforce a minimum context version number of 3.2 for desktop GL, - * and 2.0 for GLES - */ - if (gdk_gl_context_get_use_es (context) || force_gles) - min_ver = 200; - else - min_ver = 302; - - if (version < min_ver) - { - g_warning ("gdk_gl_context_set_required_version - GL context versions less than 3.2 are not supported."); - version = min_ver; - } - priv->major = version / 100; - priv->minor = version % 100; + priv->major = major; + priv->minor = minor; } gboolean -- cgit v1.2.1 From c4feca13118fa4a1e2d263c76458fa60de9a608e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Correa=20G=C3=B3mez?= Date: Mon, 30 May 2022 20:18:15 +0200 Subject: glcontext: Simplify get_required_version api Simplify the API to just return the requirements that the user has asked for. The rest of the code was undocumented and previously used as a buggy source for a default value from internal code. Since the buggy code is now fixed, remove all unnecessary cruft. --- gdk/gdkglcontext.c | 48 +++++++++--------------------------------------- 1 file changed, 9 insertions(+), 39 deletions(-) diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index 78080a236b..bf524a2c91 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -1065,7 +1065,10 @@ gdk_gl_context_check_version (GdkGLContext *self, * @major: (out) (nullable): return location for the major version to request * @minor: (out) (nullable): return location for the minor version to request * - * Retrieves required OpenGL version. + * Retrieves required OpenGL version set as a requirement for the @context + * realization. It will not change even if a greater OpenGL version is supported + * and used after the @context is realized. See + * [method@Gdk.GLContext.get_version] for the real version in use. * * See [method@Gdk.GLContext.set_required_version]. */ @@ -1075,47 +1078,14 @@ gdk_gl_context_get_required_version (GdkGLContext *context, int *minor) { GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); - gboolean force_gles = FALSE; - GdkDisplay *display; - int default_major, default_minor; - int maj, min; g_return_if_fail (GDK_IS_GL_CONTEXT (context)); - display = gdk_draw_context_get_display (GDK_DRAW_CONTEXT (context)); - -#ifdef G_ENABLE_DEBUG - force_gles = GDK_DISPLAY_DEBUG_CHECK (display, GL_GLES); -#endif - - /* libANGLE on Windows at least requires GLES 3.0+ */ - if (display->have_egl_win32_libangle) - force_gles = TRUE; - - /* Default fallback values for uninitialised contexts; we - * enforce a context version number of 3.2 for desktop GL, - * and 2.0 for GLES - */ - if (gdk_gl_context_get_use_es (context) || force_gles) - { - default_major = display->have_egl_win32_libangle ? 3 : 2; - default_minor = 0; - } - else - { - default_major = 3; - default_minor = 2; - } - - if (priv->major > 0) - maj = priv->major; - else - maj = default_major; - - if (priv->minor > 0) - min = priv->minor; - else - min = default_minor; + if (major != NULL) + *major = priv->major; + if (minor != NULL) + *minor = priv->minor; +} void gdk_gl_context_get_clipped_version (GdkGLContext *context, -- cgit v1.2.1