Make general_composite_rect() just another fast path.
authorSøren Sandmann Pedersen <sandmann@redhat.com>
Sun, 13 Sep 2009 09:29:48 +0000 (05:29 -0400)
committerSøren Sandmann Pedersen <sandmann@redhat.com>
Sun, 14 Feb 2010 16:10:15 +0000 (11:10 -0500)
We introduce a new PIXMAN_OP_any fake operator and a PIXMAN_any fake
format that match anything. Then general_composite_rect() can be used
as another fast path.

Because general_composite_rect() does not require the sources to cover
the clip region, we add a new flag FAST_PATH_COVERS_CLIP which is part
of the set of standard flags for fast paths.

Because this flag cannot be computed until after the clip region is
available, we have to call pixman_compute_composite_region32() before
checking for fast paths. This will resolve itself when we get to the
point where _pixman_run_fast_path() is only called once per composite
operation.

pixman/pixman-general.c
pixman/pixman-private.h
pixman/pixman-utils.c

index c96a3f9..83500b9 100644 (file)
@@ -264,6 +264,17 @@ general_composite_rect  (pixman_implementation_t *imp,
        free (scanline_buffer);
 }
 
+static const pixman_fast_path_t general_fast_path[] =
+{
+    {   PIXMAN_OP_any,
+       PIXMAN_any,             0,
+       PIXMAN_any,             0,
+       PIXMAN_any,             0,
+       general_composite_rect,
+    },
+    {  PIXMAN_OP_NONE  }
+};
+
 static void
 general_composite (pixman_implementation_t * imp,
                    pixman_op_t               op,
@@ -279,10 +290,16 @@ general_composite (pixman_implementation_t * imp,
                    int32_t                   width,
                    int32_t                   height)
 {
-    _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
-                                   mask_x, mask_y, dest_x, dest_y,
-                                  width, height,
-                                   general_composite_rect);
+    pixman_bool_t result;
+
+    result = _pixman_run_fast_path (general_fast_path, imp,
+                                   op, src, mask, dest,
+                                   src_x, src_y,
+                                   mask_x, mask_y,
+                                   dest_x, dest_y,
+                                   width, height);
+    
+    assert (result);
 }
 
 static pixman_bool_t
index c99b101..0ed3662 100644 (file)
@@ -564,6 +564,9 @@ _pixman_choose_implementation (void);
 #define PIXMAN_pixbuf          PIXMAN_FORMAT (0, 2, 0, 0, 0, 0)
 #define PIXMAN_rpixbuf         PIXMAN_FORMAT (0, 3, 0, 0, 0, 0)
 #define PIXMAN_unknown         PIXMAN_FORMAT (0, 4, 0, 0, 0, 0)
+#define PIXMAN_any             PIXMAN_FORMAT (0, 5, 0, 0, 0, 0)        
+
+#define PIXMAN_OP_any          (PIXMAN_N_OPERATORS + 1)
 
 #define FAST_PATH_ID_TRANSFORM                 (1 << 0)
 #define FAST_PATH_NO_ALPHA_MAP                 (1 << 1)
@@ -572,7 +575,7 @@ _pixman_choose_implementation (void);
 #define FAST_PATH_NO_REFLECT_REPEAT            (1 << 4)
 #define FAST_PATH_NO_ACCESSORS                 (1 << 5)
 #define FAST_PATH_NO_WIDE_FORMAT               (1 << 6)
-#define FAST_PATH_reserved                     (1 << 7)
+#define FAST_PATH_COVERS_CLIP                  (1 << 7)
 #define FAST_PATH_COMPONENT_ALPHA              (1 << 8)
 #define FAST_PATH_UNIFIED_ALPHA                        (1 << 9)
 
@@ -583,7 +586,8 @@ _pixman_choose_implementation (void);
      FAST_PATH_NO_PAD_REPEAT           |                               \
      FAST_PATH_NO_REFLECT_REPEAT       |                               \
      FAST_PATH_NO_ACCESSORS            |                               \
-     FAST_PATH_NO_WIDE_FORMAT)
+     FAST_PATH_NO_WIDE_FORMAT          |                               \
+     FAST_PATH_COVERS_CLIP)
 
 #define FAST_PATH_STD_SRC_FLAGS                                                \
     _FAST_PATH_STANDARD_FLAGS
index 5441b6b..66bdb30 100644 (file)
@@ -614,7 +614,9 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
     pixman_composite_func_t func;
     const pixman_fast_path_t *info;
     pixman_bool_t result;
-
+    pixman_region32_t region;
+    pixman_box32_t *extents;
+    
     get_image_info (src,  &src_format,  &src_flags);
     get_image_info (mask, &mask_format, &mask_flags);
     get_image_info (dest, &dest_format, &dest_flags);
@@ -631,15 +633,40 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
            src_format = mask_format = PIXMAN_rpixbuf;
     }
 
+    pixman_region32_init (&region);
+    
+    if (!pixman_compute_composite_region32 (
+           &region, src, mask, dest,
+           src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
+    {
+       return TRUE;
+    }
+
+    result = FALSE;
+    
+    extents = pixman_region32_extents (&region);
+
+    if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
+       src_flags |= FAST_PATH_COVERS_CLIP;
+
+    if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
+       mask_flags |= FAST_PATH_COVERS_CLIP;
+
     func = NULL;
     for (info = paths; info->op != PIXMAN_OP_NONE; ++info)
     {
-       if (info->op == op                                      &&
-           (info->src_format == src_format)                    &&
+       if ((info->op == op || info->op == PIXMAN_OP_any)       &&
+           /* src */
+           ((info->src_format == src_format) ||
+            (info->src_format == PIXMAN_any))                  &&
            (info->src_flags & src_flags) == info->src_flags    &&
-           (info->mask_format == mask_format)                  &&
+           /* mask */
+           ((info->mask_format == mask_format) ||
+            (info->mask_format == PIXMAN_any))                 &&
            (info->mask_flags & mask_flags) == info->mask_flags &&
-           (info->dest_format == dest_format)                  &&
+           /* dest */
+           ((info->dest_format == dest_format) ||
+            (info->dest_format == PIXMAN_any))                 &&
            (info->dest_flags & dest_flags) == info->dest_flags)
        {
            func = info->func;
@@ -647,54 +674,36 @@ _pixman_run_fast_path (const pixman_fast_path_t *paths,
        }
     }
 
-    result = FALSE;
-    
     if (func)
     {
-       pixman_region32_t region;
-       pixman_region32_init (&region);
-
-       if (pixman_compute_composite_region32 (
-               &region, src, mask, dest,
-               src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
-       {
-           pixman_box32_t *extents = pixman_region32_extents (&region);
-
-           if (sources_cover (
-                   src, mask, extents,
-                   src_x, src_y, mask_x, mask_y, dest_x, dest_y))
-           {
-               pixman_bool_t src_repeat, mask_repeat;
-
-               src_repeat =
-                   src->type == BITS                                   &&
-                   src_flags & FAST_PATH_ID_TRANSFORM                  &&
-                   src->common.repeat == PIXMAN_REPEAT_NORMAL          &&
-                   src_format != PIXMAN_solid;
-               
-               mask_repeat =
-                   mask                                                &&
-                   mask->type == BITS                                  &&
-                   mask_flags & FAST_PATH_ID_TRANSFORM                 &&
-                   mask->common.repeat == PIXMAN_REPEAT_NORMAL         &&
-                   mask_format != PIXMAN_solid;
-               
-               walk_region_internal (imp, op,
-                                     src, mask, dest,
-                                     src_x, src_y, mask_x, mask_y,
-                                     dest_x, dest_y,
-                                     width, height,
-                                     src_repeat, mask_repeat,
-                                     &region,
-                                     func);
-
-               result = TRUE;
-           }
-
-           pixman_region32_fini (&region);
-       }
+       pixman_bool_t src_repeat, mask_repeat;
+       
+       src_repeat =
+           src->type == BITS                                   &&
+           src_flags & FAST_PATH_ID_TRANSFORM                  &&
+           src->common.repeat == PIXMAN_REPEAT_NORMAL          &&
+           src_format != PIXMAN_solid;
+       
+       mask_repeat =
+           mask                                                &&
+           mask->type == BITS                                  &&
+           mask_flags & FAST_PATH_ID_TRANSFORM                 &&
+           mask->common.repeat == PIXMAN_REPEAT_NORMAL         &&
+           mask_format != PIXMAN_solid;
+       
+       walk_region_internal (imp, op,
+                             src, mask, dest,
+                             src_x, src_y, mask_x, mask_y,
+                             dest_x, dest_y,
+                             width, height,
+                             src_repeat, mask_repeat,
+                             &region,
+                             func);
+       
+       result = TRUE;
     }
 
+    pixman_region32_fini (&region);
     return result;
 }