pixman: Branch 'master'

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Sun Apr 6 09:51:46 PDT 2008


 pixman/pixman-combine.c |    3 -
 pixman/pixman-image.c   |   84 +++++++++++++++++++++++++++++++++
 pixman/pixman-pict.c    |  121 ++++++++++++++++++++++++++++++++++--------------
 pixman/pixman-private.h |    6 ++
 4 files changed, 179 insertions(+), 35 deletions(-)

New commits:
commit 0b207ae11065c740f2644a89fc13207a5343554e
Author: Antoine Azar <cairo at antoineazar.com>
Date:   Sun Apr 6 10:56:53 2008 -0400

    Optimize operators based on source or dest opacity.
    
    Check if we can replace our operator by a simpler one if the src or
    dest are opaque The output operator should be mathematically
    equivalent to the source.

diff --git a/pixman/pixman-combine.c b/pixman/pixman-combine.c
index be08af4..d201736 100644
--- a/pixman/pixman-combine.c
+++ b/pixman/pixman-combine.c
@@ -13,7 +13,6 @@
  * this difference will have two versions using the same convention.
  */
 
-
 /*
  * Combine src and mask
  */
@@ -1210,6 +1209,7 @@ static CombineFuncU pixman_fbCombineFuncU[] = {
     fbCombineConjointAtopU,
     fbCombineConjointAtopReverseU,
     fbCombineConjointXorU,
+    NULL /* Noop */
 };
 
 static CombineFuncC pixman_fbCombineFuncC[] = {
@@ -1257,6 +1257,7 @@ static CombineFuncC pixman_fbCombineFuncC[] = {
     fbCombineConjointAtopC,
     fbCombineConjointAtopReverseC,
     fbCombineConjointXorC,
+    NULL /* Noop */
 };
 
 FbComposeFunctions pixman_composeFunctions = {
diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c
index 9b6846e..30c294b 100644
--- a/pixman/pixman-image.c
+++ b/pixman/pixman-image.c
@@ -717,3 +717,87 @@ pixman_image_fill_rectangles (pixman_op_t		    op,
 
     return TRUE;
 }
+
+pixman_bool_t
+pixman_image_can_get_solid (pixman_image_t *image)
+{
+    if (image->type == SOLID)
+	return TRUE;
+
+    if (image->type != BITS	||
+	image->bits.width != 1	||
+	image->bits.height != 1)
+    {
+	return FALSE;
+    }
+
+    if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
+	return FALSE;
+
+    switch (image->bits.format)
+    {
+    case PIXMAN_a8r8g8b8:
+    case PIXMAN_x8r8g8b8:
+    case PIXMAN_a8b8g8r8:
+    case PIXMAN_x8b8g8r8:
+    case PIXMAN_r8g8b8:
+    case PIXMAN_b8g8r8:
+    case PIXMAN_r5g6b5:
+    case PIXMAN_b5g6r5:
+	return TRUE;
+    default:
+	return FALSE;
+    }
+}
+
+pixman_bool_t
+pixman_image_is_opaque(pixman_image_t *image)
+{
+    int i = 0;
+    int gradientNumberOfColors = 0;
+
+    if(image->common.alpha_map)
+        return FALSE;
+
+    switch(image->type)
+    {
+    case BITS:
+        if(PIXMAN_FORMAT_A(image->bits.format))
+            return FALSE;
+        break;
+
+    case LINEAR:
+    case CONICAL:
+    case RADIAL:
+        gradientNumberOfColors = image->gradient.n_stops;
+        i=0;
+        while(i<gradientNumberOfColors)
+        {
+            if(image->gradient.stops[i].color.alpha != 0xffff)
+                return FALSE;
+            i++;
+        }
+        break;
+
+    case SOLID:
+         if(Alpha(image->solid.color) != 0xff)
+            return FALSE;
+        break;
+    }
+
+    /* Convolution filters can introduce translucency if the sum of the weights
+       is lower than 1. */
+    if (image->common.filter == PIXMAN_FILTER_CONVOLUTION)
+         return FALSE;
+
+    if (image->common.repeat == PIXMAN_REPEAT_NONE)
+    {
+        if (image->common.filter != PIXMAN_FILTER_NEAREST)
+            return FALSE;
+
+        if (image->common.transform)
+            return FALSE;
+    }
+
+     return TRUE;
+}
\ No newline at end of file
diff --git a/pixman/pixman-pict.c b/pixman/pixman-pict.c
index b7c0773..f01a643 100644
--- a/pixman/pixman-pict.c
+++ b/pixman/pixman-pict.c
@@ -1261,38 +1261,6 @@ pixman_walk_composite_region (pixman_op_t op,
     pixman_region_fini (&reg);
 }
 
-static pixman_bool_t
-can_get_solid (pixman_image_t *image)
-{
-    if (image->type == SOLID)
-	return TRUE;
-
-    if (image->type != BITS	||
-	image->bits.width != 1	||
-	image->bits.height != 1)
-    {
-	return FALSE;
-    }
-
-    if (image->common.repeat != PIXMAN_REPEAT_NORMAL)
-	return FALSE;
-
-    switch (image->bits.format)
-    {
-    case PIXMAN_a8r8g8b8:
-    case PIXMAN_x8r8g8b8:
-    case PIXMAN_a8b8g8r8:
-    case PIXMAN_x8b8g8r8:
-    case PIXMAN_r8g8b8:
-    case PIXMAN_b8g8r8:
-    case PIXMAN_r5g6b5:
-    case PIXMAN_b5g6r5:
-	return TRUE;
-    default:
-	return FALSE;
-    }
-}
-
 #define SCANLINE_BUFFER_LENGTH 2048
 
 static void
@@ -1554,7 +1522,7 @@ get_fast_path (const FastPathInfo *fast_paths,
 	if (info->op != op)
 	    continue;
 
-	if ((info->src_format == PIXMAN_solid && can_get_solid (pSrc))		||
+	if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc))		||
 	    (pSrc->type == BITS && info->src_format == pSrc->bits.format))
 	{
 	    valid_src = TRUE;
@@ -1596,6 +1564,82 @@ get_fast_path (const FastPathInfo *fast_paths,
     return NULL;
 }
 
+/*
+ * Operator optimizations based on source or destination opacity
+ */
+typedef struct
+{
+    pixman_op_t			op;
+    pixman_op_t			opSrcDstOpaque;
+    pixman_op_t			opSrcOpaque;
+    pixman_op_t			opDstOpaque;
+} OptimizedOperatorInfo;
+
+static const OptimizedOperatorInfo optimized_operators[] =
+{
+    /* Input Operator           SRC&DST Opaque          SRC Opaque              DST Opaque      */
+    { PIXMAN_OP_OVER,           PIXMAN_OP_SRC,          PIXMAN_OP_SRC,          PIXMAN_OP_OVER },
+    { PIXMAN_OP_OVER_REVERSE,   PIXMAN_OP_DST,          PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_DST },
+    { PIXMAN_OP_IN,             PIXMAN_OP_SRC,          PIXMAN_OP_IN,           PIXMAN_OP_SRC },
+    { PIXMAN_OP_IN_REVERSE,     PIXMAN_OP_DST,          PIXMAN_OP_DST,          PIXMAN_OP_IN_REVERSE },
+    { PIXMAN_OP_OUT,            PIXMAN_OP_CLEAR,        PIXMAN_OP_OUT,          PIXMAN_OP_CLEAR },
+    { PIXMAN_OP_OUT_REVERSE,    PIXMAN_OP_CLEAR,        PIXMAN_OP_CLEAR,        PIXMAN_OP_OUT_REVERSE },
+    { PIXMAN_OP_ATOP,           PIXMAN_OP_SRC,          PIXMAN_OP_IN,           PIXMAN_OP_OVER },
+    { PIXMAN_OP_ATOP_REVERSE,   PIXMAN_OP_DST,          PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_IN_REVERSE },
+    { PIXMAN_OP_XOR,            PIXMAN_OP_CLEAR,        PIXMAN_OP_OUT,          PIXMAN_OP_OUT_REVERSE },
+    { PIXMAN_OP_SATURATE,       PIXMAN_OP_DST,          PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_DST },
+    { PIXMAN_OP_NONE }
+};
+
+
+/*
+ * Check if the current operator could be optimized
+ */
+static const OptimizedOperatorInfo*
+pixman_operator_can_be_optimized(pixman_op_t op)
+{
+    const OptimizedOperatorInfo *info;
+
+    for (info = optimized_operators; info->op != PIXMAN_OP_NONE; info++)
+    {
+        if(info->op == op)
+            return info;
+    }
+    return NULL;
+}
+
+/*
+ * Optimize the current operator based on opacity of source or destination
+ * The output operator should be mathematically equivalent to the source.
+ */
+static pixman_op_t
+pixman_optimize_operator(pixman_op_t op, pixman_image_t *pSrc, pixman_image_t *pMask, pixman_image_t *pDst )
+{
+    pixman_bool_t is_source_opaque;
+    pixman_bool_t is_dest_opaque;
+    const OptimizedOperatorInfo *info = pixman_operator_can_be_optimized(op);
+
+    if(!info || pMask)
+        return op;
+
+    is_source_opaque = pixman_image_is_opaque(pSrc);
+    is_dest_opaque = pixman_image_is_opaque(pDst);
+
+    if(is_source_opaque == FALSE && is_dest_opaque == FALSE)
+        return op;
+
+    if(is_source_opaque && is_dest_opaque)
+        return info->opSrcDstOpaque;
+    else if(is_source_opaque)
+        return info->opSrcOpaque;
+    else if(is_dest_opaque)
+        return info->opDstOpaque;
+
+    return op;
+
+}
+
+
 void
 pixman_image_composite (pixman_op_t      op,
 			pixman_image_t * pSrc,
@@ -1652,7 +1696,15 @@ pixman_image_composite (pixman_op_t      op,
 	}
     }
 
-    if ((pSrc->type == BITS || can_get_solid (pSrc)) && (!pMask || pMask->type == BITS)
+    /*
+    * Check if we can replace our operator by a simpler one if the src or dest are opaque
+    * The output operator should be mathematically equivalent to the source.
+    */
+    op = pixman_optimize_operator(op, pSrc, pMask, pDst);
+    if(op == PIXMAN_OP_DST)
+        return;
+
+    if ((pSrc->type == BITS || pixman_image_can_get_solid (pSrc)) && (!pMask || pMask->type == BITS)
         && !srcTransform && !maskTransform
         && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
         && (pSrc->common.filter != PIXMAN_FILTER_CONVOLUTION)
@@ -1753,6 +1805,7 @@ pixman_image_composite (pixman_op_t      op,
 }
 
 
+
 #ifdef USE_MMX
 /* The CPU detection code needs to be in a file not compiled with
  * "-mmmx -msse", as gcc would generate CMOV instructions otherwise
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index 2da0b41..e236767 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -837,6 +837,12 @@ pixman_rasterize_edges_accessors (pixman_image_t *image,
 				  pixman_fixed_t	t,
 				  pixman_fixed_t	b);
 
+pixman_bool_t
+pixman_image_is_opaque(pixman_image_t *image);
+
+pixman_bool_t
+pixman_image_can_get_solid (pixman_image_t *image);
+
 
 #ifdef PIXMAN_TIMING
 


More information about the xorg-commit mailing list