[gtk/wip.win32.fixes: 13/23] glcontext: Refactor realize function, fix interaction with shared context
- From: Chun-wei Fan <fanchunwei src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip.win32.fixes: 13/23] glcontext: Refactor realize function, fix interaction with shared context
- Date: Wed, 1 Jun 2022 02:26:59 +0000 (UTC)
commit 6437843f8280069705bc59aa369cc7904acda55b
Author: Pablo Correa Gómez <ablocorrea hotmail com>
Date: Fri May 6 21:43:30 2022 +0200
glcontext: Refactor realize function, fix interaction with shared context
gdk/gdkglcontext.c | 294 +++++++++++++++++++++++++++-------------------
gdk/gdkglcontextprivate.h | 21 ++++
2 files changed, 195 insertions(+), 120 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 92b08ceafc..1fe7b7b06b 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -256,179 +256,191 @@ 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 void
+
+gdk_gl_context_setup_context_attributes (EGLint *context_attribs,
+ GdkGLAPI api,
+ int major,
+ int minor,
+ gboolean legacy,
+ int flags)
+{
+ int i = 0;
+
+ if (api == GDK_GL_API_GL)
+ {
+ /* We want a core profile, unless in legacy mode */
+ context_attribs[i++] = EGL_CONTEXT_OPENGL_PROFILE_MASK;
+ context_attribs[i++] = legacy
+ ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT
+ : EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT;
+ }
+
+ /* Before, ~FORWARD_COMPATIBLE was only in one of the code paths.
+ * Does it make sense to have legacy with FORWARD_COMPATIBLE?
+ * If not, then there should likely also be some assert somewhere!
+ *
+ * TODO: Remove this comment before merging!
+ */
+ 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;
+
+ context_attribs[i++] = EGL_NONE;
+ g_assert (i < N_EGL_ATTRS);
+}
+
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;
+ gboolean debug_bit, forward_bit;
+ int min_major, min_minor, major = 0, minor = 0, flags = 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))
- {
- /* 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;
- }
-
- /* 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_gl_context_setup_context_attributes (context_attribs, api, major, minor, legacy, flags);
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",
+ 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)
@@ -961,6 +973,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 0bd9cbad57..bd66172eba 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,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]