[mutter] shaped-texture: If we have too many rectangles, don't paint the opaque region first



commit 01a47c7d6d237da913468df97bd5753f9142c6b5
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sun Aug 24 12:02:53 2014 -0400

    shaped-texture: If we have too many rectangles, don't paint the opaque
    region first
    
    If we're going to render the entire texture blended, then don't bother
    painting the unblended stuff, since we're just going to draw on top
    anyway.

 src/compositor/meta-shaped-texture.c |  186 ++++++++++++++++++----------------
 1 files changed, 98 insertions(+), 88 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 7ae1913..afa08de 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -298,10 +298,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
   guchar opacity;
   CoglContext *ctx;
   CoglFramebuffer *fb;
-  CoglPipeline *pipeline = NULL;
   CoglTexture *paint_tex;
   ClutterActorBox alloc;
-  cairo_region_t *blended_region = NULL;
   CoglPipelineFilter filter;
 
   if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
@@ -339,6 +337,8 @@ meta_shaped_texture_paint (ClutterActor *actor)
   if (tex_width == 0 || tex_height == 0) /* no contents yet */
     return;
 
+  cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
+
   /* Use nearest-pixel interpolation if the texture is unscaled. This
    * improves performance, especially with software rendering.
    */
@@ -354,7 +354,45 @@ meta_shaped_texture_paint (ClutterActor *actor)
   opacity = clutter_actor_get_paint_opacity (actor);
   clutter_actor_get_allocation_box (actor, &alloc);
 
-  if (priv->opaque_region != NULL && opacity == 255)
+  cairo_region_t *blended_region;
+  gboolean use_opaque_region = (priv->opaque_region != NULL && opacity == 255);
+
+  if (use_opaque_region)
+    {
+      if (priv->clip_region != NULL)
+        blended_region = cairo_region_copy (priv->clip_region);
+      else
+        blended_region = cairo_region_create_rectangle (&tex_rect);
+
+      cairo_region_subtract (blended_region, priv->opaque_region);
+    }
+  else
+    {
+      if (priv->clip_region != NULL)
+        blended_region = cairo_region_reference (priv->clip_region);
+      else
+        blended_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_region != NULL)
+    {
+      int n_rects = cairo_region_num_rectangles (blended_region);
+      if (n_rects > MAX_RECTS)
+        {
+          /* Fall back to taking the fully blended path. */
+          use_opaque_region = FALSE;
+
+          cairo_region_destroy (blended_region);
+          blended_region = NULL;
+        }
+    }
+
+  /* First, paint the unblended parts, which are part of the opaque region. */
+  if (use_opaque_region)
     {
       CoglPipeline *opaque_pipeline;
       cairo_region_t *region;
@@ -371,104 +409,76 @@ meta_shaped_texture_paint (ClutterActor *actor)
           region = cairo_region_reference (priv->opaque_region);
         }
 
-      if (cairo_region_is_empty (region))
-        goto paint_blended;
-
-      opaque_pipeline = get_unblended_pipeline (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++)
+      if (!cairo_region_is_empty (region))
         {
-          cairo_rectangle_int_t rect;
-          cairo_region_get_rectangle (region, i, &rect);
-          paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
-        }
-
-      cogl_object_unref (opaque_pipeline);
+          opaque_pipeline = get_unblended_pipeline (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 (fb, opaque_pipeline, &rect, &alloc);
+            }
 
-      if (priv->clip_region != NULL)
-        {
-          blended_region = cairo_region_copy (priv->clip_region);
+          cogl_object_unref (opaque_pipeline);
         }
-      else
-        {
-          cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
-          blended_region = cairo_region_create_rectangle (&rect);
-        }
-
-      cairo_region_subtract (blended_region, priv->opaque_region);
 
-    paint_blended:
       cairo_region_destroy (region);
     }
 
-  if (blended_region == NULL && priv->clip_region != NULL)
-    blended_region = cairo_region_reference (priv->clip_region);
-
-  if (blended_region != NULL && cairo_region_is_empty (blended_region))
-    goto out;
-
-  if (priv->mask_texture == NULL)
-    {
-      pipeline = get_unmasked_pipeline (ctx);
-    }
-  else
-    {
-      pipeline = get_masked_pipeline (ctx);
-      cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
-      cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter);
-    }
-
-  cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
-  cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
-
+  /* Now, go ahead and paint the blended parts. */
   {
+    CoglPipeline *blended_pipeline;
+
+    if (priv->mask_texture == NULL)
+      {
+        blended_pipeline = get_unmasked_pipeline (ctx);
+      }
+    else
+      {
+        blended_pipeline = get_masked_pipeline (ctx);
+        cogl_pipeline_set_layer_texture (blended_pipeline, 1, priv->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 (pipeline, &color);
+    cogl_pipeline_set_color (blended_pipeline, &color);
+
+    if (blended_region != NULL && !cairo_region_is_empty (blended_region))
+      {
+        int i;
+        int n_rects = cairo_region_num_rectangles (blended_region);
+
+        for (i = 0; i < n_rects; i++)
+          {
+            cairo_rectangle_int_t rect;
+            cairo_region_get_rectangle (blended_region, i, &rect);
+
+            if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
+              continue;
+
+            paint_clipped_rectangle (fb, blended_pipeline, &rect, &alloc);
+          }
+      }
+    else
+      {
+        cogl_framebuffer_draw_rectangle (fb, blended_pipeline,
+                                         0, 0,
+                                         alloc.x2 - alloc.x1,
+                                         alloc.y2 - alloc.y1);
+      }
+
+    cogl_object_unref (blended_pipeline);
   }
 
   if (blended_region != NULL)
-    {
-      int n_rects;
-
-      /* Limit to how many separate rectangles we'll draw; beyond this just
-       * fall back and draw the whole thing */
-#     define MAX_RECTS 16
-
-      n_rects = cairo_region_num_rectangles (blended_region);
-      if (n_rects <= MAX_RECTS)
-       {
-          int i;
-          cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
-
-         for (i = 0; i < n_rects; i++)
-           {
-             cairo_rectangle_int_t rect;
-
-             cairo_region_get_rectangle (blended_region, i, &rect);
-
-             if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
-               continue;
-
-              paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
-            }
-
-          goto out;
-       }
-    }
-
-  cogl_framebuffer_draw_rectangle (fb, pipeline,
-                                   0, 0,
-                                   alloc.x2 - alloc.x1,
-                                   alloc.y2 - alloc.y1);
-
- out:
-  if (pipeline != NULL)
-    cogl_object_unref (pipeline);
-  if (blended_region != NULL)
     cairo_region_destroy (blended_region);
 }
 


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