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.
This commit is contained in:
Benjamin Otte 2024-08-09 04:32:47 +02:00
parent 8ac1806015
commit 523cd0dff7
6 changed files with 39 additions and 22 deletions

View File

@ -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 >

View File

@ -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),
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));
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);

View File

@ -123,7 +123,8 @@ 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);
GdkSurface *surface,
gboolean surface_attached);
gboolean gdk_gl_context_is_api_allowed (GdkGLContext *self,
GdkGLAPI api,

View File

@ -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);
}
/**

View File

@ -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);

View File

@ -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);