[mutter/gbsneto/content: 105/111] WIP shaped-texture: Implement ClutterContent



commit 2d62d1be3252060b69aa6a0ceca44b9fb3430076
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Wed Dec 26 13:41:26 2018 -0200

    WIP shaped-texture: Implement ClutterContent
    
     * MetaShapedTexture now manually tracks scale-x and
       scale-y
    
     * We now paint into ClutterPaintNode instead of the
       direct framebuffer.
    
     * Various pieces of Wayland code now use MetaSurfaceActor
       instead of MetaShapedTexture.
    
     * MetaSurfaceActorWayland doesn't override size negotiation
       vfuncs anymore

 src/compositor/meta-shaped-texture-private.h |   8 +
 src/compositor/meta-shaped-texture.c         | 526 ++++++++++++++++++++-------
 src/compositor/meta-surface-actor-wayland.c  |  50 ---
 src/compositor/meta-surface-actor.c          |  16 +-
 src/compositor/meta-window-actor.c           |  16 +-
 src/meta/meta-window-actor.h                 |   3 +-
 src/wayland/meta-wayland-actor-surface.c     |   2 +-
 src/wayland/meta-wayland-data-device.c       |   2 +-
 src/wayland/meta-wayland-surface.c           |   4 +-
 src/wayland/meta-wayland-tablet-tool.c       |   2 +-
 10 files changed, 429 insertions(+), 200 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
index 44816a14d..f926a272c 100644
--- a/src/compositor/meta-shaped-texture-private.h
+++ b/src/compositor/meta-shaped-texture-private.h
@@ -44,5 +44,13 @@ gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
 cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex);
 void meta_shaped_texture_set_transform (MetaShapedTexture    *stex,
                                         MetaMonitorTransform  transform);
+void meta_shaped_texture_cull_out (MetaShapedTexture *stex,
+                                   cairo_region_t    *unobscured_region,
+                                   cairo_region_t    *clip_region,
+                                   uint8_t            opacity);
+void meta_shaped_texture_reset_culling (MetaShapedTexture *stex);
+void meta_shaped_texture_set_scale (MetaShapedTexture *stex,
+                                    double             scale);
+double meta_shaped_texture_get_scale (MetaShapedTexture *stex);
 
 #endif
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 9f96d6718..bc56168b1 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -57,21 +57,7 @@
 
 static void meta_shaped_texture_dispose  (GObject    *object);
 
-static void meta_shaped_texture_paint (ClutterActor       *actor);
-
-static void meta_shaped_texture_get_preferred_width (ClutterActor *self,
-                                                     gfloat        for_height,
-                                                     gfloat       *min_width_p,
-                                                     gfloat       *natural_width_p);
-
-static void meta_shaped_texture_get_preferred_height (ClutterActor *self,
-                                                      gfloat        for_width,
-                                                      gfloat       *min_height_p,
-                                                      gfloat       *natural_height_p);
-
-static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume);
-
-static void cullable_iface_init (MetaCullableInterface *iface);
+static void clutter_content_iface_init (ClutterContentIface *iface);
 
 enum {
   SIZE_CHANGED,
@@ -83,7 +69,7 @@ static guint signals[LAST_SIGNAL];
 
 struct _MetaShapedTexture
 {
-  ClutterActor parent;
+  GObject parent;
 
   MetaTextureTower *paint_tower;
 
@@ -116,25 +102,23 @@ struct _MetaShapedTexture
   guint remipmap_timeout_id;
   gint64 earliest_remipmap;
 
+  unsigned int attached_actors;
+
+  double scale;
+
   guint create_mipmaps : 1;
 };
 
-G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_ACTOR,
-                         G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
+G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, clutter_content_iface_init));
 
 static void
 meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
-  ClutterActorClass *actor_class = (ClutterActorClass *) klass;
 
   gobject_class->dispose = meta_shaped_texture_dispose;
 
-  actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width;
-  actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height;
-  actor_class->paint = meta_shaped_texture_paint;
-  actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
-
   signals[SIZE_CHANGED] = g_signal_new ("size-changed",
                                         G_TYPE_FROM_CLASS (gobject_class),
                                         G_SIGNAL_RUN_LAST,
@@ -154,16 +138,12 @@ meta_shaped_texture_init (MetaShapedTexture *stex)
 {
   stex->paint_tower = meta_texture_tower_new ();
 
+  stex->scale = 1.0;
   stex->texture = NULL;
   stex->mask_texture = NULL;
   stex->create_mipmaps = TRUE;
   stex->is_y_inverted = TRUE;
   stex->transform = META_MONITOR_TRANSFORM_NORMAL;
-
-  g_signal_connect (stex,
-                    "notify::scale-x",
-                    G_CALLBACK (invalidate_size),
-                    stex);
 }
 
 static void
@@ -207,7 +187,7 @@ update_size (MetaShapedTexture *stex)
       stex->dst_width = dst_width;
       stex->dst_height = dst_height;
       meta_shaped_texture_set_mask_texture (stex, NULL);
-      clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
+      clutter_content_invalidate_size (CLUTTER_CONTENT (stex));
       g_signal_emit (stex, signals[SIZE_CHANGED], 0);
     }
 }
@@ -436,6 +416,40 @@ paint_clipped_rectangle (CoglFramebuffer       *fb,
                                                  &coords[0], 8);
 }
 
+static void
+paint_clipped_rectangle_node (ClutterPaintNode      *root_node,
+                              CoglPipeline          *pipeline,
+                              cairo_rectangle_int_t *rect,
+                              ClutterActorBox       *alloc)
+{
+  g_autoptr(ClutterPaintNode) node = NULL;
+  float coords[8];
+
+  coords[0] = rect->x / (alloc->x2 - alloc->x1);
+  coords[1] = rect->y / (alloc->y2 - alloc->y1);
+  coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1);
+  coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1);
+
+  coords[4] = coords[0];
+  coords[5] = coords[1];
+  coords[6] = coords[2];
+  coords[7] = coords[3];
+
+  node = clutter_pipeline_node_new (pipeline);
+  clutter_paint_node_set_name (node, "MetaShapedTexture (clipped)");
+  clutter_paint_node_add_child (root_node, node);
+
+  clutter_paint_node_add_multitexture_rectangle (node,
+                                                 &(ClutterActorBox)
+                                                   {
+                                                     .x1 = rect->x,
+                                                     .x2 = rect->x + rect->width,
+                                                     .y1 = rect->y,
+                                                     .y2 = rect->y + rect->height,
+                                                   },
+                                                 coords, 8);
+}
+
 static void
 set_cogl_texture (MetaShapedTexture *stex,
                   CoglTexture       *cogl_tex)
@@ -476,6 +490,8 @@ set_cogl_texture (MetaShapedTexture *stex,
 
   if (stex->create_mipmaps)
     meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
+
+  clutter_content_invalidate (CLUTTER_CONTENT (stex));
 }
 
 static gboolean
@@ -486,12 +502,31 @@ texture_is_idle_and_not_mipmapped (gpointer user_data)
   if ((g_get_monotonic_time () - stex->earliest_remipmap) < 0)
     return G_SOURCE_CONTINUE;
 
-  clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
+  clutter_content_invalidate (CLUTTER_CONTENT (stex));
   stex->remipmap_timeout_id = 0;
 
   return G_SOURCE_REMOVE;
 }
 
+static cairo_region_t *
+effective_unobscured_region (MetaShapedTexture *stex)
+{
+  /*
+  ClutterActor *actor;
+
+  actor = CLUTTER_ACTOR (stex);
+  do
+    {
+      if (clutter_actor_has_mapped_clones (actor))
+        return NULL;
+      actor = clutter_actor_get_parent (actor);
+    }
+  while (actor != NULL);
+   */
+
+  return stex->unobscured_region;
+}
+
 static void
 do_paint (MetaShapedTexture *stex,
           CoglFramebuffer   *fb,
@@ -696,52 +731,234 @@ do_paint (MetaShapedTexture *stex,
 }
 
 static void
-meta_shaped_texture_paint (ClutterActor *actor)
+do_paint_content (MetaShapedTexture *stex,
+                  ClutterPaintNode  *root_node,
+                  CoglTexture       *paint_tex,
+                  ClutterActorBox   *alloc,
+                  double             tex_scale,
+                  guchar             opacity)
+
 {
-  MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor);
-  CoglTexture *paint_tex;
-  CoglFramebuffer *fb;
+  int dst_width, dst_height;
+  cairo_rectangle_int_t tex_rect;
+  gboolean use_opaque_region;
+  cairo_region_t *clip_tex_region;
+  cairo_region_t *opaque_tex_region;
+  cairo_region_t *blended_tex_region;
+  CoglContext *ctx;
+  CoglPipelineFilter filter;
 
-  if (!stex->texture)
-    return;
+  ensure_size_valid (stex);
 
-  if (stex->clip_region && cairo_region_is_empty (stex->clip_region))
+  dst_width = stex->dst_width;
+  dst_height = stex->dst_height;
+
+  if (dst_width == 0 || dst_height == 0) /* no contents yet */
     return;
 
-  if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
-    clutter_actor_realize (CLUTTER_ACTOR (stex));
+  tex_rect = (cairo_rectangle_int_t) { 0, 0, dst_width, dst_height };
 
-  /* The GL EXT_texture_from_pixmap extension does allow for it to be
-   * used together with SGIS_generate_mipmap, however this is very
-   * rarely supported. Also, even when it is supported there
-   * are distinct performance implications from:
-   *
-   *  - Updating mipmaps that we don't need
-   *  - Having to reallocate pixmaps on the server into larger buffers
+  /* Use nearest-pixel interpolation if the texture is unscaled. This
+   * improves performance, especially with software rendering.
+   */
+
+  filter = COGL_PIPELINE_FILTER_LINEAR;
+
+  /* FIXME: evil cogl_get_draw_framebuffer() */
+  if (meta_actor_painting_untransformed (cogl_get_draw_framebuffer (),
+                                         dst_width, dst_height,
+                                         NULL, NULL))
+    filter = COGL_PIPELINE_FILTER_NEAREST;
+
+  ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+
+  if (stex->opaque_region && opacity == 255)
+    {
+      opaque_tex_region =
+        meta_region_scale_double (stex->opaque_region,
+                                  1.0 / tex_scale,
+                                  META_ROUNDING_STRATEGY_SHRINK);
+      use_opaque_region = TRUE;
+    }
+  else
+    {
+      opaque_tex_region = NULL;
+      use_opaque_region = FALSE;
+    }
+
+  if (stex->clip_region)
+    {
+      clip_tex_region =
+        meta_region_scale_double (stex->clip_region,
+                                  1.0 / tex_scale,
+                                  META_ROUNDING_STRATEGY_GROW);
+    }
+  else
+    {
+      clip_tex_region = NULL;
+    }
+
+  if (use_opaque_region)
+    {
+      if (clip_tex_region)
+        blended_tex_region = cairo_region_copy (clip_tex_region);
+      else
+        blended_tex_region = cairo_region_create_rectangle (&tex_rect);
+
+      cairo_region_subtract (blended_tex_region, opaque_tex_region);
+    }
+  else
+    {
+      if (clip_tex_region)
+        blended_tex_region = cairo_region_reference (clip_tex_region);
+      else
+        blended_tex_region = NULL;
+    }
+
+  /* Limit to how many separate rectangles we'll draw; beyond this just
+   * fall back and draw the whole thing */
+#define MAX_RECTS 16
+
+  if (blended_tex_region)
+    {
+      int n_rects = cairo_region_num_rectangles (blended_tex_region);
+      if (n_rects > MAX_RECTS)
+        {
+          /* Fall back to taking the fully blended path. */
+          use_opaque_region = FALSE;
+
+          g_clear_pointer (&blended_tex_region, cairo_region_destroy);
+        }
+    }
+
+  /* First, paint the unblended parts, which are part of the opaque region. */
+  if (use_opaque_region)
+    {
+      cairo_region_t *region;
+      int n_rects;
+      int i;
+
+      if (clip_tex_region)
+        {
+          region = cairo_region_copy (clip_tex_region);
+          cairo_region_intersect (region, opaque_tex_region);
+        }
+      else
+        {
+          region = cairo_region_reference (opaque_tex_region);
+        }
+
+      if (!cairo_region_is_empty (region))
+        {
+          CoglPipeline *opaque_pipeline;
+
+          opaque_pipeline = get_unblended_pipeline (stex, ctx);
+          cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
+          cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
+
+          n_rects = cairo_region_num_rectangles (region);
+          for (i = 0; i < n_rects; i++)
+            {
+              cairo_rectangle_int_t rect;
+              cairo_region_get_rectangle (region, i, &rect);
+              paint_clipped_rectangle_node (root_node, opaque_pipeline, &rect, alloc);
+            }
+        }
+
+      cairo_region_destroy (region);
+    }
+
+  /* Now, go ahead and paint the blended parts. */
+
+  /* We have three cases:
+   *   1) blended_tex_region has rectangles - paint the rectangles.
+   *   2) blended_tex_region is empty - don't paint anything
+   *   3) blended_tex_region is NULL - paint fully-blended.
    *
-   * So, we just unconditionally use our mipmap emulation code. If we
-   * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to
-   * see if it was supported (no API currently), and then if and only
-   * if that was the case, set the clutter texture quality to HIGH.
-   * Setting the texture quality to high without SGIS_generate_mipmap
-   * support for TFP textures will result in fallbacks to XGetImage.
+   *   1) and 3) are the times where we have to paint stuff. This tests
+   *   for 1) and 3).
    */
-  if (stex->create_mipmaps)
+  if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region))
     {
-      int64_t now = g_get_monotonic_time ();
-      int64_t age = now - stex->last_invalidation;
+      CoglPipeline *blended_pipeline;
 
-      if (age >= MIN_MIPMAP_AGE_USEC ||
-          stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
+      if (stex->mask_texture == NULL)
         {
-          paint_tex = meta_texture_tower_get_paint_texture (stex->paint_tower);
-          if (!paint_tex)
-            paint_tex = stex->texture;
+          blended_pipeline = get_unmasked_pipeline (stex, ctx);
         }
       else
         {
-          paint_tex = stex->texture;
+          blended_pipeline = get_masked_pipeline (stex, ctx);
+          cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture);
+          cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
+        }
 
+      cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
+      cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
+
+      CoglColor color;
+      cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
+      cogl_pipeline_set_color (blended_pipeline, &color);
+
+      if (blended_tex_region)
+        {
+          /* 1) blended_tex_region is not empty. Paint the rectangles. */
+          int i;
+          int n_rects = cairo_region_num_rectangles (blended_tex_region);
+
+          for (i = 0; i < n_rects; i++)
+            {
+              cairo_rectangle_int_t rect;
+              cairo_region_get_rectangle (blended_tex_region, i, &rect);
+
+              if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
+                continue;
+
+              paint_clipped_rectangle_node (root_node, blended_pipeline, &rect, alloc);
+            }
+        }
+      else
+        {
+          g_autoptr(ClutterPaintNode) node = NULL;
+
+          node = clutter_pipeline_node_new (blended_pipeline);
+          clutter_paint_node_set_name (node, "MetaShapedTexture (unclipped)");
+          clutter_paint_node_add_child (root_node, node);
+
+          /* 3) blended_tex_region is NULL. Do a full paint. */
+          clutter_paint_node_add_rectangle (node, alloc);
+        }
+    }
+
+  g_clear_pointer (&clip_tex_region, cairo_region_destroy);
+  g_clear_pointer (&opaque_tex_region, cairo_region_destroy);
+  g_clear_pointer (&blended_tex_region, cairo_region_destroy);
+}
+
+static CoglTexture *
+select_texture_for_paint (MetaShapedTexture *stex)
+{
+  CoglTexture *texture = NULL;
+  gint64 now = g_get_monotonic_time ();
+
+  if (stex->create_mipmaps && stex->last_invalidation)
+    {
+      gint64 age = now - stex->last_invalidation;
+
+      if (age >= MIN_MIPMAP_AGE_USEC ||
+          stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
+        texture = meta_texture_tower_get_paint_texture (stex->paint_tower);
+    }
+
+  if (texture == NULL)
+    {
+      texture = COGL_TEXTURE (stex->texture);
+
+      if (texture == NULL)
+        return NULL;
+
+      if (stex->create_mipmaps)
+        {
           /* Minus 1000 to ensure we don't fail the age test in timeout */
           stex->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000;
 
@@ -752,74 +969,97 @@ meta_shaped_texture_paint (ClutterActor *actor)
                              stex);
         }
     }
-  else
-    {
-      paint_tex = COGL_TEXTURE (stex->texture);
-    }
 
-  if (cogl_texture_get_width (paint_tex) == 0 ||
-      cogl_texture_get_height (paint_tex) == 0)
+  return texture;
+}
+
+static void
+meta_shaped_texture_paint_content (ClutterContent   *content,
+                                   ClutterActor     *actor,
+                                   ClutterPaintNode *root_node)
+{
+  MetaShapedTexture *stex = META_SHAPED_TEXTURE (content);
+  ClutterActorBox alloc;
+  CoglTexture *paint_tex = NULL;
+  double tex_scale;
+  guchar opacity;
+
+  if (stex->clip_region && cairo_region_is_empty (stex->clip_region))
+    return;
+
+  /* The GL EXT_texture_from_pixmap extension does allow for it to be
+   * used together with SGIS_generate_mipmap, however this is very
+   * rarely supported. Also, even when it is supported there
+   * are distinct performance implications from:
+   *
+   *  - Updating mipmaps that we don't need
+   *  - Having to reallocate pixmaps on the server into larger buffers
+   *
+   * So, we just unconditionally use our mipmap emulation code. If we
+   * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to
+   * see if it was supported (no API currently), and then if and only
+   * if that was the case, set the clutter texture quality to HIGH.
+   * Setting the texture quality to high without SGIS_generate_mipmap
+   * support for TFP textures will result in fallbacks to XGetImage.
+   */
+  paint_tex = select_texture_for_paint (stex);
+  if (!paint_tex)
     return;
 
-  fb = cogl_get_draw_framebuffer ();
-  do_paint (META_SHAPED_TEXTURE (actor), fb, paint_tex, stex->clip_region);
+  clutter_actor_get_scale (actor, &tex_scale, NULL);
+  opacity = clutter_actor_get_paint_opacity (actor);
+  clutter_actor_get_content_box (actor, &alloc);
+
+  do_paint_content (stex, root_node, paint_tex, &alloc, tex_scale, opacity);
 }
 
-static void
-meta_shaped_texture_get_preferred_width (ClutterActor *self,
-                                         gfloat        for_height,
-                                         gfloat       *min_width_p,
-                                         gfloat       *natural_width_p)
+static gboolean
+meta_shaped_texture_get_preferred_size (ClutterContent *content,
+                                        float          *width,
+                                        float          *height)
 {
-  MetaShapedTexture *stex = META_SHAPED_TEXTURE (self);
+  MetaShapedTexture *stex = META_SHAPED_TEXTURE (content);
 
   ensure_size_valid (stex);
 
-  if (min_width_p)
-    *min_width_p = stex->dst_width;
-  if (natural_width_p)
-    *natural_width_p = stex->dst_width;
+  if (width)
+    *width = stex->dst_width * stex->scale;
+
+  if (height)
+    *height = stex->dst_height * stex->scale;
+
+  return TRUE;
 }
 
 static void
-meta_shaped_texture_get_preferred_height (ClutterActor *self,
-                                          gfloat        for_width,
-                                          gfloat       *min_height_p,
-                                          gfloat       *natural_height_p)
+meta_shaped_texture_attached (ClutterContent *content,
+                            ClutterActor   *actor)
 {
-  MetaShapedTexture *stex = META_SHAPED_TEXTURE (self);
+  MetaShapedTexture *shaped_texture = META_SHAPED_TEXTURE (content);
 
-  ensure_size_valid (stex);
+  shaped_texture->attached_actors++;
 
-  if (min_height_p)
-    *min_height_p = stex->dst_height;
-  if (natural_height_p)
-    *natural_height_p = stex->dst_height;
+  g_message ("%s: Attached! (%u)", G_STRFUNC, shaped_texture->attached_actors);
 }
 
-static cairo_region_t *
-effective_unobscured_region (MetaShapedTexture *stex)
+static void
+meta_shaped_texture_detached (ClutterContent *content,
+                            ClutterActor   *actor)
 {
-  ClutterActor *actor;
+  MetaShapedTexture *shaped_texture = META_SHAPED_TEXTURE (content);
 
-  /* Fail if we have any mapped clones. */
-  actor = CLUTTER_ACTOR (stex);
-  do
-    {
-      if (clutter_actor_has_mapped_clones (actor))
-        return NULL;
-      actor = clutter_actor_get_parent (actor);
-    }
-  while (actor != NULL);
+  shaped_texture->attached_actors--;
 
-  return stex->unobscured_region;
+  g_message ("%s: Detached! (%u)", G_STRFUNC, shaped_texture->attached_actors);
 }
 
-static gboolean
-meta_shaped_texture_get_paint_volume (ClutterActor *actor,
-                                      ClutterPaintVolume *volume)
+static void
+clutter_content_iface_init (ClutterContentIface *iface)
 {
-  return clutter_paint_volume_set_from_allocation (volume, actor);
+  iface->paint_content = meta_shaped_texture_paint_content;
+  iface->get_preferred_size = meta_shaped_texture_get_preferred_size;
+  iface->attached = meta_shaped_texture_attached;
+  iface->detached = meta_shaped_texture_detached;
 }
 
 void
@@ -853,7 +1093,7 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
       cogl_object_ref (stex->mask_texture);
     }
 
-  clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
+  clutter_content_invalidate (CLUTTER_CONTENT (stex));
 }
 
 gboolean
@@ -944,7 +1184,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
         {
           cairo_rectangle_int_t damage_rect;
           cairo_region_get_extents (intersection, &damage_rect);
-          clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect);
+          clutter_content_invalidate (CLUTTER_CONTENT (stex));
+          //clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect);
           cairo_region_destroy (intersection);
           return TRUE;
         }
@@ -954,7 +1195,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
     }
   else
     {
-      clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
+      clutter_content_invalidate (CLUTTER_CONTENT (stex));
+      //clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
       return TRUE;
     }
 }
@@ -1230,7 +1472,7 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
 
       transformed_clip = alloca (sizeof (cairo_rectangle_int_t));
 
-      clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL);
+      tex_scale = stex->scale;
       meta_rectangle_scale_double (clip, 1.0 / tex_scale,
                                    META_ROUNDING_STRATEGY_GROW,
                                    transformed_clip);
@@ -1318,17 +1560,47 @@ meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
   invalidate_size (stex);
 }
 
-static void
-meta_shaped_texture_cull_out (MetaCullable   *cullable,
-                              cairo_region_t *unobscured_region,
-                              cairo_region_t *clip_region)
+ClutterActor *
+meta_shaped_texture_new (void)
 {
-  MetaShapedTexture *stex = META_SHAPED_TEXTURE (cullable);
+  return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
+}
+
+void
+meta_shaped_texture_set_scale (MetaShapedTexture *stex,
+                               double             scale)
+{
+  g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
+
+  if (scale == stex->scale)
+    return;
+
+  stex->scale = scale;
+
+  invalidate_size (stex);
+  clutter_content_invalidate_size (CLUTTER_CONTENT (stex));
+}
+
+double
+meta_shaped_texture_get_scale (MetaShapedTexture *stex)
+{
+  g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 0.0);
+
+  return stex->scale;
+}
+
+void
+meta_shaped_texture_cull_out (MetaShapedTexture *stex,
+                              cairo_region_t    *unobscured_region,
+                              cairo_region_t    *clip_region,
+                              uint8_t            opacity)
+{
+  g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
 
   set_unobscured_region (stex, unobscured_region);
   set_clip_region (stex, clip_region);
 
-  if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (stex)) == 0xff)
+  if (opacity == 0xff)
     {
       if (stex->opaque_region)
         {
@@ -1340,22 +1612,10 @@ meta_shaped_texture_cull_out (MetaCullable   *cullable,
     }
 }
 
-static void
-meta_shaped_texture_reset_culling (MetaCullable *cullable)
-{
-  MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable);
-  set_clip_region (self, NULL);
-}
-
-static void
-cullable_iface_init (MetaCullableInterface *iface)
+void
+meta_shaped_texture_reset_culling (MetaShapedTexture *stex)
 {
-  iface->cull_out = meta_shaped_texture_cull_out;
-  iface->reset_culling = meta_shaped_texture_reset_culling;
-}
+  g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
 
-ClutterActor *
-meta_shaped_texture_new (void)
-{
-  return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
+  set_clip_region (stex, NULL);
 }
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
index f8d6c32b7..27c600c59 100644
--- a/src/compositor/meta-surface-actor-wayland.c
+++ b/src/compositor/meta-surface-actor-wayland.c
@@ -110,54 +110,6 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
   return surface->window;
 }
 
-static void
-meta_surface_actor_wayland_get_preferred_width  (ClutterActor *actor,
-                                                 gfloat        for_height,
-                                                 gfloat       *min_width_p,
-                                                 gfloat       *natural_width_p)
-{
-  MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
-  MetaShapedTexture *stex;
-  double scale;
-
-  stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
-  clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale, NULL);
-  clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex),
-                                     for_height,
-                                     min_width_p,
-                                     natural_width_p);
-
-  if (min_width_p)
-     *min_width_p *= scale;
-
-  if (natural_width_p)
-    *natural_width_p *= scale;
-}
-
-static void
-meta_surface_actor_wayland_get_preferred_height  (ClutterActor *actor,
-                                                  gfloat        for_width,
-                                                  gfloat       *min_height_p,
-                                                  gfloat       *natural_height_p)
-{
-  MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
-  MetaShapedTexture *stex;
-  double scale;
-
-  stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
-  clutter_actor_get_scale (CLUTTER_ACTOR (stex), NULL, &scale);
-  clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex),
-                                      for_width,
-                                      min_height_p,
-                                      natural_height_p);
-
-  if (min_height_p)
-     *min_height_p *= scale;
-
-  if (natural_height_p)
-    *natural_height_p *= scale;
-}
-
 static void
 meta_surface_actor_wayland_paint (ClutterActor *actor)
 {
@@ -203,8 +155,6 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width;
-  actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height;
   actor_class->paint = meta_surface_actor_wayland_paint;
 
   surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
index 9a7d0ef5b..6d02dbbcc 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -158,13 +158,22 @@ meta_surface_actor_cull_out (MetaCullable   *cullable,
                              cairo_region_t *unobscured_region,
                              cairo_region_t *clip_region)
 {
-  meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
+  MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable);
+  MetaSurfaceActorPrivate *priv =
+    meta_surface_actor_get_instance_private (surface_actor);
+  uint8_t opacity = clutter_actor_get_opacity (CLUTTER_ACTOR (cullable));
+
+  meta_shaped_texture_cull_out (priv->texture, unobscured_region, clip_region, opacity);
 }
 
 static void
 meta_surface_actor_reset_culling (MetaCullable *cullable)
 {
-  meta_cullable_reset_culling_children (cullable);
+  MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable);
+  MetaSurfaceActorPrivate *priv =
+    meta_surface_actor_get_instance_private (surface_actor);
+
+  meta_shaped_texture_reset_culling (priv->texture);
 }
 
 static void
@@ -191,7 +200,8 @@ meta_surface_actor_init (MetaSurfaceActor *self)
   priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ());
   g_signal_connect_object (priv->texture, "size-changed",
                            G_CALLBACK (texture_size_changed), self, 0);
-  clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture));
+  clutter_actor_set_content (CLUTTER_ACTOR (self), CLUTTER_CONTENT (priv->texture));
+  clutter_actor_set_request_mode (CLUTTER_ACTOR (self), CLUTTER_REQUEST_CONTENT_SIZE);
 }
 
 cairo_surface_t *
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 20a22062f..d471f622a 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -829,14 +829,14 @@ meta_window_actor_get_meta_window (MetaWindowActor *self)
  *
  * Return value: (transfer none): the #ClutterActor for the contents
  */
-ClutterActor *
+MetaShapedTexture *
 meta_window_actor_get_texture (MetaWindowActor *self)
 {
   MetaWindowActorPrivate *priv =
     meta_window_actor_get_instance_private (self);
 
   if (priv->surface)
-    return CLUTTER_ACTOR (meta_surface_actor_get_texture (priv->surface));
+    return meta_surface_actor_get_texture (priv->surface);
   else
     return NULL;
 }
@@ -1875,19 +1875,19 @@ meta_window_actor_get_frame_bounds (MetaScreenCastWindow *screen_cast_window,
   MetaShapedTexture *stex;
   MetaRectangle buffer_rect;
   MetaRectangle frame_rect;
-  double scale_x, scale_y;
+  double scale;
 
   stex = meta_surface_actor_get_texture (priv->surface);
-  clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale_x, &scale_y);
+  scale = meta_shaped_texture_get_scale (stex);
 
   window = priv->window;
   meta_window_get_buffer_rect (window, &buffer_rect);
   meta_window_get_frame_rect (window, &frame_rect);
 
-  bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale_x);
-  bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale_y);
-  bounds->width = (int) ceil (frame_rect.width / scale_x);
-  bounds->height = (int) ceil (frame_rect.height / scale_y);
+  bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale);
+  bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale);
+  bounds->width = (int) ceil (frame_rect.width / scale);
+  bounds->height = (int) ceil (frame_rect.height / scale);
 }
 
 static void
diff --git a/src/meta/meta-window-actor.h b/src/meta/meta-window-actor.h
index 0b1f79d45..7de3f422e 100644
--- a/src/meta/meta-window-actor.h
+++ b/src/meta/meta-window-actor.h
@@ -27,6 +27,7 @@
 
 #include "clutter/clutter.h"
 #include "meta/compositor.h"
+#include "meta/meta-shaped-texture.h"
 
 #define META_TYPE_WINDOW_ACTOR (meta_window_actor_get_type ())
 G_DECLARE_DERIVABLE_TYPE (MetaWindowActor,
@@ -36,7 +37,7 @@ G_DECLARE_DERIVABLE_TYPE (MetaWindowActor,
 
 Window             meta_window_actor_get_x_window         (MetaWindowActor *self);
 MetaWindow *       meta_window_actor_get_meta_window      (MetaWindowActor *self);
-ClutterActor *     meta_window_actor_get_texture          (MetaWindowActor *self);
+MetaShapedTexture *meta_window_actor_get_texture          (MetaWindowActor *self);
 void               meta_window_actor_sync_visibility      (MetaWindowActor *self);
 gboolean       meta_window_actor_is_destroyed (MetaWindowActor *self);
 
diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c
index 56ea66e1e..a85fde49f 100644
--- a/src/wayland/meta-wayland-actor-surface.c
+++ b/src/wayland/meta-wayland-actor-surface.c
@@ -163,7 +163,7 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor
   stex = meta_surface_actor_get_texture (surface_actor);
 
   actor_scale = meta_wayland_actor_surface_calculate_scale (actor_surface);
-  clutter_actor_set_scale (CLUTTER_ACTOR (stex), actor_scale, actor_scale);
+  meta_shaped_texture_set_scale (stex, actor_scale);
 
   /* Wayland surface coordinate space -> stage coordinate space */
   geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface);
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c
index 122604965..447ebbda5 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -1123,7 +1123,7 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice                 *data
 
   surface_actor = meta_wayland_surface_get_actor (surface);
 
-  clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface_actor)),
+  clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor),
                                        seat->pointer->grab_x,
                                        seat->pointer->grab_y,
                                        &surface_pos.x, &surface_pos.y);
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index f75fefd87..2d0f05703 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -1514,7 +1514,7 @@ meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
   else
     {
       ClutterActor *actor =
-        CLUTTER_ACTOR (meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface)));
+        CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
 
       clutter_actor_transform_stage_point (actor, abs_x, abs_y, sx, sy);
       *sx /= surface->scale;
@@ -1530,7 +1530,7 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
                                                float               *y)
 {
   ClutterActor *actor =
-    CLUTTER_ACTOR (meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface)));
+    CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
   ClutterVertex sv = {
     .x = sx * surface->scale,
     .y = sy * surface->scale,
diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c
index 222b46633..abfe533ff 100644
--- a/src/wayland/meta-wayland-tablet-tool.c
+++ b/src/wayland/meta-wayland-tablet-tool.c
@@ -640,7 +640,7 @@ meta_wayland_tablet_tool_get_relative_coordinates (MetaWaylandTabletTool *tool,
   surface_actor = meta_wayland_surface_get_actor (surface);
 
   clutter_event_get_coords (event, &xf, &yf);
-  clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface_actor)),
+  clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor),
                                        xf, yf, &xf, &yf);
 
   *sx = wl_fixed_from_double (xf) / surface->scale;


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