[mutter] backends: Allow multiple "SW" cursor overlays on the stage



commit 362ab781dda2e5eec05b756d935335b7605761d3
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon May 2 13:49:13 2016 +0200

    backends: Allow multiple "SW" cursor overlays on the stage
    
    All the upper layers are prepared for multiple onscreen cursors, but
    this. All MetaCursorRenderers created would poke the same internal
    MetaOverlay in the stage.
    
    This will lead to multiple cursor renderers resorting to the "SW"
    rendering paths (as it can be seen with tablet support) to reuse the
    same overlay, thus leading to flickering when a different
    MetaCursorRenderer takes over the overlay.
    
    Fix this by allowing per-cursor-renderer overlays, their lifetime
    is attached to the cursor renderer, so is expected to be tear down
    if the relevant device (eg. tablet) disappears.

 src/backends/meta-cursor-renderer.c |   24 ++++++++++++-
 src/backends/meta-stage.c           |   69 +++++++++++++++++++++++++++--------
 src/backends/meta-stage.h           |   12 +++++--
 3 files changed, 85 insertions(+), 20 deletions(-)
---
diff --git a/src/backends/meta-cursor-renderer.c b/src/backends/meta-cursor-renderer.c
index b20871a..da3f99a 100644
--- a/src/backends/meta-cursor-renderer.c
+++ b/src/backends/meta-cursor-renderer.c
@@ -40,6 +40,7 @@ struct _MetaCursorRendererPrivate
   int current_x, current_y;
 
   MetaCursorSprite *displayed_cursor;
+  MetaOverlay *stage_overlay;
   gboolean handled_by_backend;
 };
 typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
@@ -63,12 +64,16 @@ queue_redraw (MetaCursorRenderer *renderer,
   if (!stage)
     return;
 
+  if (!priv->stage_overlay)
+    priv->stage_overlay = meta_stage_create_cursor_overlay (META_STAGE (stage));
+
   if (cursor_sprite && !priv->handled_by_backend)
     texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
   else
     texture = NULL;
 
-  meta_stage_set_cursor (META_STAGE (stage), texture, &rect);
+  meta_stage_update_cursor_overlay (META_STAGE (stage), priv->stage_overlay,
+                                    texture, &rect);
 }
 
 static gboolean
@@ -82,8 +87,25 @@ meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer,
 }
 
 static void
+meta_cursor_renderer_finalize (GObject *object)
+{
+  MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object);
+  MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
+  MetaBackend *backend = meta_get_backend ();
+  ClutterActor *stage = meta_backend_get_stage (backend);
+
+  if (priv->stage_overlay)
+    meta_stage_remove_cursor_overlay (META_STAGE (stage), priv->stage_overlay);
+
+  G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->finalize (object);
+}
+
+static void
 meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_cursor_renderer_finalize;
   klass->update_cursor = meta_cursor_renderer_real_update_cursor;
 }
 
diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c
index eb270f1..5ac15d5 100644
--- a/src/backends/meta-stage.c
+++ b/src/backends/meta-stage.c
@@ -27,7 +27,7 @@
 #include <meta/meta-backend.h>
 #include <meta/util.h>
 
-typedef struct {
+struct _MetaOverlay {
   gboolean enabled;
 
   CoglPipeline *pipeline;
@@ -36,22 +36,26 @@ typedef struct {
   MetaRectangle current_rect;
   MetaRectangle previous_rect;
   gboolean previous_is_valid;
-} MetaOverlay;
+};
 
 struct _MetaStagePrivate {
-  MetaOverlay cursor_overlay;
+  GList *overlays;
   gboolean is_active;
 };
 typedef struct _MetaStagePrivate MetaStagePrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE);
 
-static void
-meta_overlay_init (MetaOverlay *overlay)
+static MetaOverlay *
+meta_overlay_new ()
 {
+  MetaOverlay *overlay;
   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
 
+  overlay = g_slice_new0 (MetaOverlay);
   overlay->pipeline = cogl_pipeline_new (ctx);
+
+  return overlay;
 }
 
 static void
@@ -59,6 +63,8 @@ meta_overlay_free (MetaOverlay *overlay)
 {
   if (overlay->pipeline)
     cogl_object_unref (overlay->pipeline);
+
+  g_slice_free (MetaOverlay, overlay);
 }
 
 static void
@@ -111,8 +117,15 @@ meta_stage_finalize (GObject *object)
 {
   MetaStage *stage = META_STAGE (object);
   MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+  GList *l = priv->overlays;
 
-  meta_overlay_free (&priv->cursor_overlay);
+  while (l)
+    {
+      meta_overlay_free (l->data);
+      l = g_list_delete_link (l, l);
+    }
+
+  G_OBJECT_CLASS (meta_stage_parent_class)->finalize (object);
 }
 
 static void
@@ -120,10 +133,12 @@ meta_stage_paint (ClutterActor *actor)
 {
   MetaStage *stage = META_STAGE (actor);
   MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+  GList *l;
 
   CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
 
-  meta_overlay_paint (&priv->cursor_overlay);
+  for (l = priv->overlays; l; l = l->next)
+    meta_overlay_paint (l->data);
 }
 
 static void
@@ -166,10 +181,6 @@ meta_stage_class_init (MetaStageClass *klass)
 static void
 meta_stage_init (MetaStage *stage)
 {
-  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
-
-  meta_overlay_init (&priv->cursor_overlay);
-
   clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
 }
 
@@ -209,17 +220,43 @@ queue_redraw_for_overlay (MetaStage   *stage,
     }
 }
 
+MetaOverlay *
+meta_stage_create_cursor_overlay (MetaStage *stage)
+{
+  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+  MetaOverlay *overlay;
+
+  overlay = meta_overlay_new ();
+  priv->overlays = g_list_prepend (priv->overlays, overlay);
+
+  return overlay;
+}
+
 void
-meta_stage_set_cursor (MetaStage     *stage,
-                       CoglTexture   *texture,
-                       MetaRectangle *rect)
+meta_stage_remove_cursor_overlay (MetaStage   *stage,
+                                  MetaOverlay *overlay)
 {
   MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+  GList *link;
 
+  link = g_list_find (priv->overlays, overlay);
+  if (!link)
+    return;
+
+  priv->overlays = g_list_delete_link (priv->overlays, link);
+  meta_overlay_free (overlay);
+}
+
+void
+meta_stage_update_cursor_overlay (MetaStage          *stage,
+                                  MetaOverlay        *overlay,
+                                  CoglTexture        *texture,
+                                  MetaRectangle      *rect)
+{
   g_assert (meta_is_wayland_compositor () || texture == NULL);
 
-  meta_overlay_set (&priv->cursor_overlay, texture, rect);
-  queue_redraw_for_overlay (stage, &priv->cursor_overlay);
+  meta_overlay_set (overlay, texture, rect);
+  queue_redraw_for_overlay (stage, overlay);
 }
 
 void
diff --git a/src/backends/meta-stage.h b/src/backends/meta-stage.h
index 262d68f..5376c7a 100644
--- a/src/backends/meta-stage.h
+++ b/src/backends/meta-stage.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 
 typedef struct _MetaStage      MetaStage;
 typedef struct _MetaStageClass MetaStageClass;
+typedef struct _MetaOverlay    MetaOverlay;
 
 struct _MetaStageClass
 {
@@ -51,9 +52,14 @@ GType             meta_stage_get_type                (void) G_GNUC_CONST;
 
 ClutterActor     *meta_stage_new                     (void);
 
-void meta_stage_set_cursor (MetaStage     *stage,
-                            CoglTexture   *texture,
-                            MetaRectangle *rect);
+MetaOverlay      *meta_stage_create_cursor_overlay   (MetaStage   *stage);
+void              meta_stage_remove_cursor_overlay   (MetaStage   *stage,
+                                                     MetaOverlay *overlay);
+
+void              meta_stage_update_cursor_overlay   (MetaStage     *stage,
+                                                     MetaOverlay   *overlay,
+                                                     CoglTexture   *texture,
+                                                     MetaRectangle *rect);
 
 void meta_stage_set_active (MetaStage *stage,
                             gboolean   is_active);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]