diff options
author | Søren Sandmann Pedersen <sandmann@redhat.com> | 2009-09-18 14:10:31 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-03-14 12:11:47 -0400 |
commit | 7fe35f0e6b660f5667ff653f3b753bc3e5d07901 (patch) | |
tree | 3dbf1752b4618118d862e85bf2e519627c70c3a8 | |
parent | 54e39e00386fd2fd0eb76ead6396ddb93f1cf6c2 (diff) |
Make the operator strength reduction constant time.
By extending the operator information table to cover all operators we
can replace the loop with a table look-up. At the same time, base the
operator optimization on the computed flags rather than the ones in
the image struct.
Finally, as an extra optimization, we no longer ignore the case where
there is a mask. Instead we consider the source opaque if both source
and mask are opaque, or if the source is opaque and the mask is
missing.
-rw-r--r-- | pixman/pixman.c | 133 |
1 files changed, 87 insertions, 46 deletions
diff --git a/pixman/pixman.c b/pixman/pixman.c index b43ea92..bbd978c 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -39,11 +39,16 @@ typedef struct pixman_op_t op_src_dst_opaque; pixman_op_t op_src_opaque; pixman_op_t op_dst_opaque; -} optimized_operator_info_t; +} operator_info_t; -static const optimized_operator_info_t optimized_operators[] = +#define NO_OPTIMIZATION(a) (a), (a), (a), (a) + +static const operator_info_t operator_table[] = { /* Input Operator SRC&DST Opaque SRC Opaque DST Opaque */ + { NO_OPTIMIZATION (PIXMAN_OP_CLEAR) }, + { NO_OPTIMIZATION (PIXMAN_OP_SRC) }, + { NO_OPTIMIZATION (PIXMAN_OP_DST) }, { 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 }, @@ -53,49 +58,86 @@ static const optimized_operator_info_t optimized_operators[] = { 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 }, + { NO_OPTIMIZATION (PIXMAN_OP_ADD) }, { PIXMAN_OP_SATURATE, PIXMAN_OP_DST, PIXMAN_OP_OVER_REVERSE, PIXMAN_OP_DST }, + + { PIXMAN_OP_NONE /* 0x0e */ }, + { PIXMAN_OP_NONE /* 0x0f */ }, + + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_CLEAR) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_SRC) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_DST) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_OVER) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_OVER_REVERSE) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_IN) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_IN_REVERSE) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_OUT) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_OUT_REVERSE) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_ATOP) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_ATOP_REVERSE) }, + { NO_OPTIMIZATION (PIXMAN_OP_DISJOINT_XOR) }, + + { PIXMAN_OP_NONE /* 0x1c */ }, + { PIXMAN_OP_NONE /* 0x1d */ }, + { PIXMAN_OP_NONE /* 0x1e */ }, + { PIXMAN_OP_NONE /* 0x1f */ }, + + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_CLEAR) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_SRC) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_DST) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_OVER) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_OVER_REVERSE) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_IN) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_IN_REVERSE) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_OUT) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_OUT_REVERSE) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_ATOP) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_ATOP_REVERSE) }, + { NO_OPTIMIZATION (PIXMAN_OP_CONJOINT_XOR) }, + + { PIXMAN_OP_NONE /* 0x2c */ }, + { PIXMAN_OP_NONE /* 0x2d */ }, + { PIXMAN_OP_NONE /* 0x2e */ }, + { PIXMAN_OP_NONE /* 0x2f */ }, + + { NO_OPTIMIZATION (PIXMAN_OP_MULTIPLY) }, + { NO_OPTIMIZATION (PIXMAN_OP_SCREEN) }, + { NO_OPTIMIZATION (PIXMAN_OP_OVERLAY) }, + { NO_OPTIMIZATION (PIXMAN_OP_DARKEN) }, + { NO_OPTIMIZATION (PIXMAN_OP_LIGHTEN) }, + { NO_OPTIMIZATION (PIXMAN_OP_COLOR_DODGE) }, + { NO_OPTIMIZATION (PIXMAN_OP_COLOR_BURN) }, + { NO_OPTIMIZATION (PIXMAN_OP_HARD_LIGHT) }, + { NO_OPTIMIZATION (PIXMAN_OP_SOFT_LIGHT) }, + { NO_OPTIMIZATION (PIXMAN_OP_DIFFERENCE) }, + { NO_OPTIMIZATION (PIXMAN_OP_EXCLUSION) }, + { NO_OPTIMIZATION (PIXMAN_OP_HSL_HUE) }, + { NO_OPTIMIZATION (PIXMAN_OP_HSL_SATURATION) }, + { NO_OPTIMIZATION (PIXMAN_OP_HSL_COLOR) }, + { NO_OPTIMIZATION (PIXMAN_OP_HSL_LUMINOSITY) }, + { PIXMAN_OP_NONE } }; static pixman_implementation_t *imp; /* - * Check if the current operator could be optimized - */ -static const optimized_operator_info_t* -pixman_operator_can_be_optimized (pixman_op_t op) -{ - const optimized_operator_info_t *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 *src_image, - pixman_image_t *mask_image, - pixman_image_t *dst_image) +optimize_operator (pixman_op_t op, + uint32_t src_flags, + uint32_t mask_flags, + uint32_t dst_flags) { - pixman_bool_t is_source_opaque; - pixman_bool_t is_dest_opaque; - const optimized_operator_info_t *info = pixman_operator_can_be_optimized (op); - if (!info || mask_image) - return op; + const operator_info_t *info = &(operator_table[op]); + pixman_bool_t is_source_opaque, is_dest_opaque; - is_source_opaque = src_image->common.flags & FAST_PATH_IS_OPAQUE; - is_dest_opaque = dst_image->common.flags & FAST_PATH_IS_OPAQUE; + assert (info->op == op); - if (!is_source_opaque && !is_dest_opaque) - return op; + is_source_opaque = (src_flags & mask_flags) & FAST_PATH_IS_OPAQUE; + is_dest_opaque = dst_flags & FAST_PATH_IS_OPAQUE; if (is_source_opaque && is_dest_opaque) return info->op_src_dst_opaque; @@ -105,7 +147,6 @@ pixman_optimize_operator (pixman_op_t op, return info->op_dst_opaque; return op; - } static void @@ -510,7 +551,7 @@ do_composite (pixman_implementation_t *imp, else { mask_format = PIXMAN_null; - mask_flags = 0; + mask_flags = FAST_PATH_IS_OPAQUE; } dest_format = dest->common.extended_format_code; @@ -555,6 +596,19 @@ do_composite (pixman_implementation_t *imp, if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y)) mask_flags |= FAST_PATH_COVERS_CLIP; + /* + * 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 = optimize_operator (op, src_flags, mask_flags, dest_flags); + if (op == PIXMAN_OP_DST || + op == PIXMAN_OP_CONJOINT_DST || + op == PIXMAN_OP_DISJOINT_DST) + { + return; + } + cache = tls_cache; for (i = 0; i < N_CACHED_FAST_PATHS; ++i) @@ -713,19 +767,6 @@ pixman_image_composite32 (pixman_op_t op, if (mask) _pixman_image_validate (mask); _pixman_image_validate (dest); - - /* - * 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, src, mask, dest); - if (op == PIXMAN_OP_DST || - op == PIXMAN_OP_CONJOINT_DST || - op == PIXMAN_OP_DISJOINT_DST) - { - return; - } if (!imp) imp = _pixman_choose_implementation (); |