From 523cd0dff7b7cb87a8c6613c42ea2160c11fea2b Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 9 Aug 2024 04:32:47 +0200 Subject: [PATCH] glcontext: Add a surface_attached flag GLContexts marked as surface_attached are always attached to the surface in make_current(). Other contexts continue to only get attached to their surface between begin_frame() and end_frame(). All our renderer use surface-attached contexts now. Public API only gives out non-surface-attached contexts. The benefit here is that we can now choose whenever we want to call make_current() because it will not cause a re-make_current() if we call it outside vs inside the begin/end_frame() region. Or in other words: I want to call make_current() before begin_frame() without a performance penalty, and now I can. --- gdk/gdkdisplay.c | 2 +- gdk/gdkglcontext.c | 33 ++++++++++++++++++++++++++------- gdk/gdkglcontextprivate.h | 5 +++-- gdk/gdksurface.c | 2 +- gsk/gl/gskglrenderer.c | 10 +++++----- gsk/gpu/gsknglrenderer.c | 9 +++------ 6 files changed, 39 insertions(+), 22 deletions(-) diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c index bf7b748db9..b2f807746f 100644 --- a/gdk/gdkdisplay.c +++ b/gdk/gdkdisplay.c @@ -1477,7 +1477,7 @@ gdk_display_create_gl_context (GdkDisplay *self, if (!gdk_display_prepare_gl (self, error)) return NULL; - return gdk_gl_context_new (self, NULL); + return gdk_gl_context_new (self, NULL, FALSE); } /*< private > diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c index daeab6fbae..45e2a71d6e 100644 --- a/gdk/gdkglcontext.c +++ b/gdk/gdkglcontext.c @@ -122,6 +122,7 @@ struct _GdkGLContextPrivate GdkGLMemoryFlags memory_flags[GDK_MEMORY_N_FORMATS]; GdkGLFeatures features; + guint surface_attached : 1; guint use_khr_debug : 1; guint has_debug_output : 1; guint extensions_checked : 1; @@ -829,20 +830,28 @@ gdk_gl_context_init (GdkGLContext *self) /* Must have called gdk_display_prepare_gl() before */ GdkGLContext * gdk_gl_context_new (GdkDisplay *display, - GdkSurface *surface) + GdkSurface *surface, + gboolean surface_attached) { - GdkGLContext *shared; + GdkGLContextPrivate *priv; + GdkGLContext *shared, *result; g_assert (surface == NULL || display == gdk_surface_get_display (surface)); + g_assert (!surface_attached || surface != NULL); /* assert gdk_display_prepare_gl() had been called */ shared = gdk_display_get_gl_context (display); g_assert (shared); - return g_object_new (G_OBJECT_TYPE (shared), - "display", display, - "surface", surface, - NULL); + result = g_object_new (G_OBJECT_TYPE (shared), + "display", display, + "surface", surface, + NULL); + + priv = gdk_gl_context_get_instance_private (result); + priv->surface_attached = surface_attached; + + return result; } void @@ -1825,12 +1834,22 @@ gdk_gl_context_check_is_current (GdkGLContext *context) void gdk_gl_context_make_current (GdkGLContext *context) { + GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context); MaskedContext *current, *masked_context; gboolean surfaceless; g_return_if_fail (GDK_IS_GL_CONTEXT (context)); - surfaceless = !gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)); + if (priv->surface_attached) + { + surfaceless = FALSE; + } + else + { +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + surfaceless = !gdk_draw_context_is_in_frame (GDK_DRAW_CONTEXT (context)); +G_GNUC_END_IGNORE_DEPRECATIONS + } masked_context = mask_context (context, surfaceless); current = g_private_get (&thread_current_context); diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h index db9b6bb5b2..99591fac51 100644 --- a/gdk/gdkglcontextprivate.h +++ b/gdk/gdkglcontextprivate.h @@ -122,8 +122,9 @@ void gdk_gl_backend_use (GdkGLBackend void gdk_gl_context_clear_current_if_surface (GdkSurface *surface); -GdkGLContext * gdk_gl_context_new (GdkDisplay *display, - GdkSurface *surface); +GdkGLContext * gdk_gl_context_new (GdkDisplay *display, + GdkSurface *surface, + gboolean surface_attached); gboolean gdk_gl_context_is_api_allowed (GdkGLContext *self, GdkGLAPI api, diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c index cc13438c92..ac2ca1fc3c 100644 --- a/gdk/gdksurface.c +++ b/gdk/gdksurface.c @@ -1256,7 +1256,7 @@ gdk_surface_create_gl_context (GdkSurface *surface, if (!gdk_display_prepare_gl (surface->display, error)) return NULL; - return gdk_gl_context_new (surface->display, surface); + return gdk_gl_context_new (surface->display, surface, FALSE); } /** diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index b59605d684..63703f27c2 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -192,12 +192,12 @@ gsk_gl_renderer_realize (GskRenderer *renderer, g_assert (self->context == NULL); g_assert (self->command_queue == NULL); - if (surface == NULL) - context = gdk_display_create_gl_context (display, error); - else - context = gdk_surface_create_gl_context (surface, error); + if (!gdk_display_prepare_gl (display, error)) + goto failure; - if (!context || !gdk_gl_context_realize (context, error)) + context = gdk_gl_context_new (display, surface, surface != NULL); + + if (!gdk_gl_context_realize (context, error)) goto failure; api = gdk_gl_context_get_api (context); diff --git a/gsk/gpu/gsknglrenderer.c b/gsk/gpu/gsknglrenderer.c index e3590033ef..880c7f1b0c 100644 --- a/gsk/gpu/gsknglrenderer.c +++ b/gsk/gpu/gsknglrenderer.c @@ -45,14 +45,11 @@ gsk_ngl_renderer_create_context (GskGpuRenderer *renderer, { GdkGLContext *context; - if (surface) - context = gdk_surface_create_gl_context (surface, error); - else - context = gdk_display_create_gl_context (display, error); - - if (context == NULL) + if (!gdk_display_prepare_gl (display, error)) return NULL; + context = gdk_gl_context_new (display, surface, surface != NULL); + /* GLES 2 is not supported */ gdk_gl_context_set_required_version (context, 3, 0);