[Pixman] [PATCH 16/18] Skip fetching pixels when possible

Søren Sandmann sandmann at cs.au.dk
Wed Jan 5 18:28:00 PST 2011


From: Søren Sandmann Pedersen <ssp at redhat.com>

Add two new iterator flags, ITER_IGNORE_ALPHA and ITER_IGNORE_RGB that
are set when the alpha and rgb values are not needed. If both are set,
then we can skip fetching entirely and just use
_pixman_iter_get_scanline_noop.
---
 pixman/pixman-bits-image.c     |   11 +++++-
 pixman/pixman-general.c        |   74 +++++++++++++++++++++++++++------------
 pixman/pixman-implementation.c |    7 ++++
 pixman/pixman-private.h        |    4 ++-
 4 files changed, 71 insertions(+), 25 deletions(-)

diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c
index df8d56e..7d588a9 100644
--- a/pixman/pixman-bits-image.c
+++ b/pixman/pixman-bits-image.c
@@ -1444,7 +1444,16 @@ _pixman_bits_image_iter_init (pixman_image_t *image,
 	}
 	else
 	{
-	    iter->get_scanline = get_scanline_narrow;
+	    if ((flags & (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA)) ==
+		 (ITER_IGNORE_RGB | ITER_IGNORE_ALPHA))
+	    {
+		iter->get_scanline = _pixman_iter_get_scanline_noop;
+	    }
+	    else
+	    {
+		iter->get_scanline = get_scanline_narrow;
+	    }
+
 	    iter->next_line = next_line_write_narrow;
 	}
     }
diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c
index 84b52c2..25d1fe4 100644
--- a/pixman/pixman-general.c
+++ b/pixman/pixman-general.c
@@ -83,6 +83,34 @@ general_iter_init (pixman_implementation_t *imp,
     }
 }
 
+typedef struct op_info_t op_info_t;
+struct op_info_t
+{
+    uint8_t src, dst;
+};
+
+#define ITER_IGNORE_BOTH						\
+    (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
+
+static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
+{
+    /* Src                   Dst                   */
+    { ITER_IGNORE_BOTH,      ITER_IGNORE_BOTH      }, /* CLEAR */
+    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_BOTH      }, /* SRC */
+    { ITER_IGNORE_BOTH,      ITER_LOCALIZED_ALPHA  }, /* DST */
+    { 0,                     ITER_LOCALIZED_ALPHA  }, /* OVER */
+    { ITER_LOCALIZED_ALPHA,  0                     }, /* OVER_REVERSE */
+    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_RGB       }, /* IN */
+    { ITER_IGNORE_RGB,       ITER_LOCALIZED_ALPHA  }, /* IN_REVERSE */
+    { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_RGB       }, /* OUT */
+    { ITER_IGNORE_RGB,       ITER_LOCALIZED_ALPHA  }, /* OUT_REVERSE */
+    { 0,                     0                     }, /* ATOP */
+    { 0,                     0                     }, /* ATOP_REVERSE */
+    { 0,                     0                     }, /* XOR */
+    { ITER_LOCALIZED_ALPHA,  ITER_LOCALIZED_ALPHA  }, /* ADD */
+    { 0,                     0                     }, /* SATURATE */
+};
+
 #define SCANLINE_BUFFER_LENGTH 8192
 
 static void
@@ -106,7 +134,7 @@ general_composite_rect  (pixman_implementation_t *imp,
     pixman_iter_t src_iter, mask_iter, dest_iter;
     pixman_combine_32_func_t compose;
     pixman_bool_t component_alpha;
-    iter_flags_t narrow, dest_flags;
+    iter_flags_t narrow, src_flags;
     int Bpp;
     int i;
 
@@ -135,39 +163,39 @@ general_composite_rect  (pixman_implementation_t *imp,
     mask_buffer = src_buffer + width * Bpp;
     dest_buffer = mask_buffer + width * Bpp;
 
+    /* src iter */
+    src_flags = narrow | op_flags[op].src;
+
     _pixman_implementation_iter_init (imp->toplevel, &src_iter, src,
 				      src_x, src_y, width, height,
-				      src_buffer, narrow);
-
-    _pixman_implementation_iter_init (imp->toplevel, &mask_iter, mask,
-				      mask_x, mask_y, width, height,
-				      mask_buffer, narrow);
-
-    if (op == PIXMAN_OP_CLEAR		||
-	op == PIXMAN_OP_SRC		||
-	op == PIXMAN_OP_DST		||
-	op == PIXMAN_OP_OVER		||
-	op == PIXMAN_OP_IN_REVERSE	||
-	op == PIXMAN_OP_OUT_REVERSE	||
-	op == PIXMAN_OP_ADD)
-    {
-	dest_flags = narrow | ITER_WRITE | ITER_LOCALIZED_ALPHA;
-    }
-    else
+				      src_buffer, src_flags);
+
+    /* mask iter */
+    if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
+	(ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
     {
-	dest_flags = narrow | ITER_WRITE;
+	/* If it doesn't matter what the source is, then it doesn't matter
+	 * what the mask is
+	 */
+	mask = NULL;
     }
 
-    _pixman_implementation_iter_init (imp->toplevel, &dest_iter, dest,
-				      dest_x, dest_y, width, height,
-				      dest_buffer, dest_flags);
-
     component_alpha =
         mask                            &&
         mask->common.type == BITS       &&
         mask->common.component_alpha    &&
         PIXMAN_FORMAT_RGB (mask->bits.format);
 
+    _pixman_implementation_iter_init (
+	imp->toplevel, &mask_iter, mask, mask_x, mask_y, width, height,
+	mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB));
+
+    /* dest iter */
+    _pixman_implementation_iter_init (imp->toplevel, &dest_iter, dest,
+				      dest_x, dest_y, width, height,
+				      dest_buffer,
+				      narrow | ITER_WRITE | op_flags[op].dst);
+
     if (narrow)
     {
 	if (component_alpha)
diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c
index 1aa28d1..57134cb 100644
--- a/pixman/pixman-implementation.c
+++ b/pixman/pixman-implementation.c
@@ -258,11 +258,18 @@ _pixman_implementation_iter_init (pixman_implementation_t	*imp,
 				  uint8_t			*buffer,
 				  iter_flags_t		         flags)
 {
+#define NOOP  (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)
+
     if (!image)
     {
 	iter->get_scanline = get_scanline_null;
 	iter->next_line = _pixman_iter_next_line_noop;
     }
+    else if ((flags & (NOOP | ITER_WRITE)) == NOOP)
+    {
+	iter->get_scanline = _pixman_iter_get_scanline_noop;
+	iter->next_line = _pixman_iter_next_line_noop;
+    }
     else
     {
 	(*imp->iter_init) (
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 8532b98..2a00dc4 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -201,7 +201,9 @@ typedef enum
      * we can treat it as ARGB, which means in some cases we can avoid copying
      * it to a temporary buffer.
      */
-    ITER_LOCALIZED_ALPHA =	(1 << 2)
+    ITER_LOCALIZED_ALPHA =	(1 << 2),
+    ITER_IGNORE_ALPHA =		(1 << 3),
+    ITER_IGNORE_RGB =		(1 << 4)
 } iter_flags_t;
 
 struct pixman_iter_t
-- 
1.6.0.6



More information about the Pixman mailing list