summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2016-03-16 14:58:16 +0800
committerJonas Ådahl <jadahl@gmail.com>2016-03-29 18:26:10 +0800
commit7173937a7d5f0bc0fdb1a980bf40f58e2aee6b96 (patch)
tree9be9f8c764b2c43088c1af49ff816d0907882f8f
parentf44238a72f2879a2a9b13a50fd42752bb84ff1b9 (diff)
downloadmutter-7173937a7d5f0bc0fdb1a980bf40f58e2aee6b96.tar.gz
wayland/cursor: Keep a private use count and reference to active buffer
In order for the native cursor renderer to be able to create a hw cursor in response to wl_pointer.set_cursor(), keep a private use-count and reference to the active buffer, stopping it from being released until it is consumed, replaced, or the surface is destroyed. https://bugzilla.gnome.org/show_bug.cgi?id=762828
-rw-r--r--src/wayland/meta-wayland-pointer.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 173d7d055..aad9aaa9c 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -80,6 +80,8 @@ struct _MetaWaylandSurfaceRoleCursor
int hot_x;
int hot_y;
MetaCursorSprite *cursor_sprite;
+
+ MetaWaylandBuffer *buffer;
};
G_DEFINE_TYPE (MetaWaylandSurfaceRoleCursor,
@@ -977,14 +979,18 @@ update_cursor_sprite_texture (MetaWaylandSurface *surface)
cursor_role->hot_x * surface->scale,
cursor_role->hot_y * surface->scale);
- if (surface->buffer_ref.use_count > 0)
+ if (cursor_role->buffer)
{
struct wl_resource *buffer_resource;
+ g_assert (cursor_role->buffer == buffer);
buffer_resource = buffer->resource;
meta_cursor_renderer_realize_cursor_from_wl_buffer (cursor_renderer,
cursor_sprite,
buffer_resource);
+
+ meta_wayland_surface_unref_buffer_use_count (surface);
+ g_clear_object (&cursor_role->buffer);
}
}
else
@@ -1260,18 +1266,53 @@ meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
static void
cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
{
+ MetaWaylandSurfaceRoleCursor *cursor_role =
+ META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
+ MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
+
+ if (buffer)
+ {
+ g_set_object (&cursor_role->buffer, buffer);
+ meta_wayland_surface_ref_buffer_use_count (surface);
+ }
meta_wayland_surface_queue_pending_frame_callbacks (surface);
}
static void
+cursor_surface_role_pre_commit (MetaWaylandSurfaceRole *surface_role,
+ MetaWaylandPendingState *pending)
+{
+ MetaWaylandSurfaceRoleCursor *cursor_role =
+ META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
+ MetaWaylandSurface *surface =
+ meta_wayland_surface_role_get_surface (surface_role);
+
+ if (pending->newly_attached && cursor_role->buffer)
+ {
+ meta_wayland_surface_unref_buffer_use_count (surface);
+ g_clear_object (&cursor_role->buffer);
+ }
+}
+
+static void
cursor_surface_role_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
{
+ MetaWaylandSurfaceRoleCursor *cursor_role =
+ META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role);
MetaWaylandSurface *surface =
meta_wayland_surface_role_get_surface (surface_role);
+ MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
+
+ if (pending->newly_attached)
+ {
+ g_set_object (&cursor_role->buffer, buffer);
+ if (cursor_role->buffer)
+ meta_wayland_surface_ref_buffer_use_count (surface);
+ }
meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
@@ -1326,6 +1367,12 @@ cursor_surface_role_dispose (GObject *object)
g_clear_object (&cursor_role->cursor_sprite);
+ if (cursor_role->buffer)
+ {
+ meta_wayland_surface_unref_buffer_use_count (surface);
+ g_clear_object (&cursor_role->buffer);
+ }
+
G_OBJECT_CLASS (meta_wayland_surface_role_cursor_parent_class)->dispose (object);
}
@@ -1342,6 +1389,7 @@ meta_wayland_surface_role_cursor_class_init (MetaWaylandSurfaceRoleCursorClass *
GObjectClass *object_class = G_OBJECT_CLASS (klass);
surface_role_class->assigned = cursor_surface_role_assigned;
+ surface_role_class->pre_commit = cursor_surface_role_pre_commit;
surface_role_class->commit = cursor_surface_role_commit;
surface_role_class->is_on_output = cursor_surface_role_is_on_output;