wayland: Rework how we handle EGLWindows

This essentially reverts the changes from
c230546a2c but implies new semantics.

Namely, surface-attached contexts can now be bound to EGL_NO_SURFACE if
the windowing system isn't ready yet.

It is the task of the windowing system to make sure the context is
properly rebound when the contents become available.
We ensure this by checking in begin_frame() if we created the EGL window
and if we did, we make_current(). This works because creating the EGL
window creates the EGL surface and that does a clear_current(), so this
is always going to have the desired effect of re-making the current
context.

It is very convoluted though.

Fixes: #6964
Related: https://gitlab.freedesktop.org/mesa/mesa/-/issues/11784
This commit is contained in:
Benjamin Otte 2024-08-28 18:56:34 +02:00
parent ea9c2a72d9
commit 447bc18c48
4 changed files with 27 additions and 21 deletions

View File

@ -1160,8 +1160,6 @@ gdk_surface_get_egl_surface (GdkSurface *self)
{
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
gdk_surface_ensure_egl_surface (self, priv->egl_surface_depth);
return priv->egl_surface;
}

View File

@ -46,14 +46,21 @@
G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
static gboolean
gdk_wayland_gl_context_make_current (GdkGLContext *context,
gboolean surfaceless)
static void
gdk_wayland_gl_context_begin_frame (GdkDrawContext *draw_context,
GdkMemoryDepth depth,
cairo_region_t *region,
GdkColorState **out_color_state,
GdkMemoryDepth *out_depth)
{
if (!surfaceless)
gdk_wayland_surface_ensure_wl_egl_window (gdk_gl_context_get_surface (context));
gboolean created_window;
return GDK_GL_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->make_current (context, surfaceless);
created_window = gdk_wayland_surface_ensure_wl_egl_window (gdk_draw_context_get_surface (draw_context));
GDK_DRAW_CONTEXT_CLASS (gdk_wayland_gl_context_parent_class)->begin_frame (draw_context, depth, region, out_color_state, out_depth);
if (created_window)
gdk_gl_context_make_current (GDK_GL_CONTEXT (draw_context));
}
static void
@ -95,13 +102,13 @@ static void
gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
{
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
GdkGLContextClass *gl_context_class = GDK_GL_CONTEXT_CLASS (klass);
GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
draw_context_class->begin_frame = gdk_wayland_gl_context_begin_frame;
draw_context_class->end_frame = gdk_wayland_gl_context_end_frame;
draw_context_class->empty_frame = gdk_wayland_gl_context_empty_frame;
gl_context_class->make_current = gdk_wayland_gl_context_make_current;
gl_context_class->backend_type = GDK_GL_EGL;
context_class->backend_type = GDK_GL_EGL;
}
static void

View File

@ -1447,20 +1447,21 @@ _gdk_wayland_surface_offset_next_wl_buffer (GdkSurface *surface,
impl->pending_buffer_offset_y = y;
}
void
gboolean
gdk_wayland_surface_ensure_wl_egl_window (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
int width, height;
if (impl->display_server.egl_window == NULL)
{
int width, height;
if (impl->display_server.egl_window != NULL)
return FALSE;
get_egl_window_size (surface, &width, &height);
impl->display_server.egl_window =
wl_egl_window_create (impl->display_server.wl_surface, width, height);
gdk_surface_set_egl_native_window (surface, impl->display_server.egl_window);
}
get_egl_window_size (surface, &width, &height);
impl->display_server.egl_window =
wl_egl_window_create (impl->display_server.wl_surface, width, height);
gdk_surface_set_egl_native_window (surface, impl->display_server.egl_window);
return TRUE;
}
/* }}} */

View File

@ -26,6 +26,6 @@
G_BEGIN_DECLS
void gdk_wayland_surface_ensure_wl_egl_window (GdkSurface *surface);
gboolean gdk_wayland_surface_ensure_wl_egl_window (GdkSurface *surface);
G_END_DECLS