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 (®);
}
-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