From 79dc41499df7b149e3735a2810d7f07a1c64009e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Wed, 13 Jul 2022 17:10:05 +0200 Subject: [PATCH] wayland/surface: Call meta_wayland_buffer_attach from surface commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preparation for potentially calling meta_wayland_transaction_apply some time after surface commit, in which case doing it in the former would be too late: The client may legally destroy the attached wl_buffer immediately after commit, in which case meta_wayland_buffer_attach would spuriously fail and disconnect the client (or possibly even crash mutter due to NULL error). Requires splitting up the surface texture between protocol and output state, and propagating from the former to the latter via MetaWaylandSurfaceState. v2: (Jonas Ã…dahl) * Move meta_wayland_surface_get_texture call to separate line. * Use g_autoptr for GError. Part-of: --- src/wayland/meta-wayland-actor-surface.c | 4 +- src/wayland/meta-wayland-buffer.c | 2 - src/wayland/meta-wayland-surface.c | 76 ++++++++++++++---------- src/wayland/meta-wayland-surface.h | 4 +- 4 files changed, 48 insertions(+), 38 deletions(-) diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c index 71ef652a8..a057366e5 100644 --- a/src/wayland/meta-wayland-actor-surface.c +++ b/src/wayland/meta-wayland-actor-surface.c @@ -189,11 +189,13 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor { CoglSnippet *snippet; gboolean is_y_inverted; + CoglTexture *texture; snippet = meta_wayland_buffer_create_snippet (buffer); is_y_inverted = meta_wayland_buffer_is_y_inverted (buffer); - meta_shaped_texture_set_texture (stex, surface->texture); + texture = meta_wayland_surface_get_texture (surface); + meta_shaped_texture_set_texture (stex, texture); meta_shaped_texture_set_snippet (stex, snippet); meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted); meta_shaped_texture_set_buffer_scale (stex, surface->scale); diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c index 910d5edc4..bbf0ae2ad 100644 --- a/src/wayland/meta-wayland-buffer.c +++ b/src/wayland/meta-wayland-buffer.c @@ -561,8 +561,6 @@ meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, CoglTexture **texture, GError **error) { - g_return_val_if_fail (buffer->resource, FALSE); - COGL_TRACE_BEGIN_SCOPED (MetaWaylandBufferAttach, "WaylandBuffer (attach)"); if (!meta_wayland_buffer_is_realized (buffer)) diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index f5487936d..31ffff1c5 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -311,7 +311,7 @@ get_buffer_width (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); if (buffer) - return cogl_texture_get_width (surface->texture); + return cogl_texture_get_width (surface->output_state.texture); else return 0; } @@ -322,7 +322,7 @@ get_buffer_height (MetaWaylandSurface *surface) MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); if (buffer) - return cogl_texture_get_height (surface->texture); + return cogl_texture_get_height (surface->output_state.texture); else return 0; } @@ -418,7 +418,8 @@ surface_process_damage (MetaWaylandSurface *surface, cairo_region_intersect_rectangle (buffer_region, &buffer_rect); - meta_wayland_buffer_process_damage (buffer, surface->texture, buffer_region); + meta_wayland_buffer_process_damage (buffer, surface->output_state.texture, + buffer_region); actor = meta_wayland_surface_get_actor (surface); if (actor) @@ -469,6 +470,7 @@ meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state) { state->newly_attached = FALSE; state->buffer = NULL; + state->texture = NULL; state->buffer_destroy_handler_id = 0; state->dx = 0; state->dy = 0; @@ -514,6 +516,8 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state) { MetaWaylandFrameCallback *cb, *next; + cogl_clear_object (&state->texture); + g_clear_pointer (&state->surface_damage, cairo_region_destroy); g_clear_pointer (&state->buffer_damage, cairo_region_destroy); g_clear_pointer (&state->input_region, cairo_region_destroy); @@ -549,6 +553,9 @@ meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from, to->newly_attached = TRUE; to->buffer = from->buffer; + + cogl_clear_object (&to->texture); + to->texture = g_steal_pointer (&from->texture); } to->dx += from->dx; @@ -799,30 +806,8 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, if (state->buffer) meta_wayland_surface_ref_buffer_use_count (surface); - if (state->buffer) - { - GError *error = NULL; - - if (!meta_wayland_buffer_attach (state->buffer, - &surface->texture, - &error)) - { - g_warning ("Could not import pending buffer: %s", error->message); - if (surface->resource) - { - wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_NO_MEMORY, - "Failed to attach buffer to surface %i: %s", - wl_resource_get_id (surface->resource), - error->message); - } - g_error_free (error); - goto cleanup; - } - } - else - { - cogl_clear_object (&surface->texture); - } + cogl_clear_object (&surface->output_state.texture); + surface->output_state.texture = g_steal_pointer (&state->texture); /* If the newly attached buffer is going to be accessed directly without * making a copy, such as an EGL buffer, mark it as in-use don't release @@ -949,7 +934,6 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, if (state->subsurface_placement_ops) meta_wayland_surface_notify_subsurface_state_changed (surface); -cleanup: /* If we have a buffer that we are not using, decrease the use count so it may * be released if no-one else has a use-reference to it. */ @@ -1000,15 +984,39 @@ static void meta_wayland_surface_commit (MetaWaylandSurface *surface) { MetaWaylandSurfaceState *pending = surface->pending_state; + MetaWaylandBuffer *buffer = pending->buffer; MetaWaylandTransaction *transaction; MetaWaylandSurface *subsurface_surface; COGL_TRACE_BEGIN_SCOPED (MetaWaylandSurfaceCommit, "WaylandSurface (commit)"); - if (pending->buffer && - !meta_wayland_buffer_is_realized (pending->buffer)) - meta_wayland_buffer_realize (pending->buffer); + if (buffer) + { + g_autoptr (GError) error = NULL; + + if (!meta_wayland_buffer_is_realized (buffer)) + meta_wayland_buffer_realize (buffer); + + if (!meta_wayland_buffer_attach (buffer, + &surface->protocol_state.texture, + &error)) + { + g_warning ("Could not import pending buffer: %s", error->message); + + wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_NO_MEMORY, + "Failed to attach buffer to surface %i: %s", + wl_resource_get_id (surface->resource), + error->message); + return; + } + + pending->texture = cogl_object_ref (surface->protocol_state.texture); + } + else if (pending->newly_attached) + { + cogl_clear_object (&surface->protocol_state.texture); + } if (meta_wayland_surface_is_synchronized (surface)) transaction = meta_wayland_surface_ensure_transaction (surface); @@ -1483,7 +1491,7 @@ meta_wayland_surface_finalize (GObject *object) if (surface->buffer_held) meta_wayland_surface_unref_buffer_use_count (surface); - g_clear_pointer (&surface->texture, cogl_object_unref); + g_clear_pointer (&surface->output_state.texture, cogl_object_unref); g_clear_pointer (&surface->buffer_ref, meta_wayland_buffer_ref_unref); if (surface->opaque_region) @@ -1535,6 +1543,8 @@ wl_surface_destructor (struct wl_resource *resource) g_clear_pointer (&surface->wl_subsurface, wl_resource_destroy); g_clear_pointer (&surface->protocol_state.subsurface_branch_node, g_node_destroy); + cogl_clear_object (&surface->protocol_state.texture); + /* * Any transactions referencing this surface will keep it alive until they get * applied/destroyed. The last reference will be dropped in @@ -2117,7 +2127,7 @@ meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, CoglTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface) { - return surface->texture; + return surface->output_state.texture; } MetaSurfaceActor * diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 7aab3f2c7..072d7f8eb 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -80,6 +80,7 @@ struct _MetaWaylandSurfaceState /* wl_surface.attach */ gboolean newly_attached; MetaWaylandBuffer *buffer; + CoglTexture *texture; gulong buffer_destroy_handler_id; int32_t dx; int32_t dy; @@ -169,8 +170,6 @@ struct _MetaWaylandSurface GHashTable *outputs; MetaMonitorTransform buffer_transform; - CoglTexture *texture; - /* Buffer reference state. */ MetaWaylandBufferRef *buffer_ref; @@ -194,6 +193,7 @@ struct _MetaWaylandSurface MetaWaylandSurface *parent; GNode *subsurface_branch_node; GNode *subsurface_leaf_node; + CoglTexture *texture; } output_state, protocol_state; /* Extension resources. */