From 7fe35f0e6b660f5667ff653f3b753bc3e5d07901 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Fri, 18 Sep 2009 14:10:31 -0400 Subject: 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. --- pixman/pixman.c | 133 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 46 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index b43ea926..bbd978cc 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 (); -- cgit v1.2.3 From 58be9c71d2b1d0ed9d8feed1db0581b250d0a7d2 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Sat, 19 Sep 2009 02:32:28 -0400 Subject: Store the operator table more compactly. The four cases for each operator: none-are-opaque, src-is-opaque, dest-is-opaque, both-are-opaque are packed into one uint32_t per operator. The relevant strength reduced operator can then be found by packing the source-is-opaque and dest-is-opaque into two bits and shifting that number of bytes. Chris Wilson pointed out a bug in the original version of this commit: dest_is_opaque and source_is_opaque were used as booleans, but their actual values were the results of a logical AND with the FAST_PATH_OPAQUE flag, so the shift value was wildly wrong. The only reason it actually passed the test suite (on x86) was that the compiler computed the shift amount in the cl register, and the low byte of FAST_PATH_OPAQUE happens to be 0, so no shifting actually took place, and the original operator was returned. --- pixman/pixman.c | 182 ++++++++++++++++++++++++++------------------------------ 1 file changed, 84 insertions(+), 98 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index bbd978cc..21565298 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -30,97 +30,90 @@ #include -/* - * Operator optimizations based on source or destination opacity - */ -typedef struct -{ - pixman_op_t op; - pixman_op_t op_src_dst_opaque; - pixman_op_t op_src_opaque; - pixman_op_t op_dst_opaque; -} operator_info_t; +static pixman_implementation_t *imp; -#define NO_OPTIMIZATION(a) (a), (a), (a), (a) +#define PACK(a, b, c, d) \ + (((uint8_t)PIXMAN_OP_ ## a << 0) | \ + ((uint8_t)PIXMAN_OP_ ## b << 8) | \ + ((uint8_t)PIXMAN_OP_ ## c << 16) | \ + ((uint8_t)PIXMAN_OP_ ## d << 24)) -static const operator_info_t operator_table[] = +static const uint32_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 }, - { 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 }, - { 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 } + /* Neither Opaque Src Opaque Dst Opaque Both Opaque */ + PACK (CLEAR, CLEAR, CLEAR, CLEAR), + PACK (SRC, SRC, SRC, SRC), + PACK (DST, DST, DST, DST), + PACK (OVER, SRC, OVER, SRC), + PACK (OVER_REVERSE, OVER_REVERSE, DST, DST), + PACK (IN, IN, SRC, SRC), + PACK (IN_REVERSE, DST, IN_REVERSE, DST), + PACK (OUT, OUT, CLEAR, CLEAR), + PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR), + PACK (ATOP, IN, OVER, SRC), + PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST), + PACK (XOR, OUT, OUT_REVERSE, CLEAR), + PACK (ADD, ADD, ADD, ADD), + PACK (SATURATE, OVER_REVERSE, DST, DST), + + 0 /* 0x0e */, + 0 /* 0x0f */, + + PACK (DISJOINT_CLEAR, DISJOINT_CLEAR, DISJOINT_CLEAR, DISJOINT_CLEAR), + PACK (DISJOINT_SRC, DISJOINT_SRC, DISJOINT_SRC, DISJOINT_SRC), + PACK (DISJOINT_DST, DISJOINT_DST, DISJOINT_DST, DISJOINT_DST), + PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER), + PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE), + PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN), + PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE), + PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT), + PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE), + PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP), + PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE), + PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR), + + 0 /* 0x1c */, + 0 /* 0x1d */, + 0 /* 0x1e */, + 0 /* 0x1f */, + + PACK (CONJOINT_CLEAR, CONJOINT_CLEAR, CONJOINT_CLEAR, CONJOINT_CLEAR), + PACK (CONJOINT_SRC, CONJOINT_SRC, CONJOINT_SRC, CONJOINT_SRC), + PACK (CONJOINT_DST, CONJOINT_DST, CONJOINT_DST, CONJOINT_DST), + PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER), + PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE), + PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN), + PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE), + PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT), + PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE), + PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP), + PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE), + PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR), + + 0 /* 0x2c */, + 0 /* 0x2d */, + 0 /* 0x2e */, + 0 /* 0x2f */, + + PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY), + PACK (SCREEN, SCREEN, SCREEN, SCREEN), + PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY), + PACK (DARKEN, DARKEN, DARKEN, DARKEN), + PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN), + PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE), + PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN), + PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT), + PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT), + PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE), + PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION), + PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE), + PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION), + PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR), + PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY), + + 0 }; -static pixman_implementation_t *imp; - /* * Optimize the current operator based on opacity of source or destination * The output operator should be mathematically equivalent to the source. @@ -131,22 +124,15 @@ optimize_operator (pixman_op_t op, uint32_t mask_flags, uint32_t dst_flags) { - const operator_info_t *info = &(operator_table[op]); pixman_bool_t is_source_opaque, is_dest_opaque; + int shift; - assert (info->op == op); - - is_source_opaque = (src_flags & mask_flags) & FAST_PATH_IS_OPAQUE; - is_dest_opaque = dst_flags & FAST_PATH_IS_OPAQUE; + is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0; + is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0; - if (is_source_opaque && is_dest_opaque) - return info->op_src_dst_opaque; - else if (is_source_opaque) - return info->op_src_opaque; - else if (is_dest_opaque) - return info->op_dst_opaque; + shift = 8 * ((is_dest_opaque << 1) | is_source_opaque); - return op; + return (operator_table[op] >> shift) & 0xff; } static void -- cgit v1.2.3 From 94d75ebd2167b44c142a6202b2d7bbe238dfd830 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Sat, 19 Sep 2009 02:40:56 -0400 Subject: Strength reduce certain conjoint/disjoint to their normal counterparts. This allows us to not test for them later on. --- pixman/pixman.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index 21565298..924ef7cd 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -59,9 +59,9 @@ static const uint32_t operator_table[] = 0 /* 0x0e */, 0 /* 0x0f */, - PACK (DISJOINT_CLEAR, DISJOINT_CLEAR, DISJOINT_CLEAR, DISJOINT_CLEAR), - PACK (DISJOINT_SRC, DISJOINT_SRC, DISJOINT_SRC, DISJOINT_SRC), - PACK (DISJOINT_DST, DISJOINT_DST, DISJOINT_DST, DISJOINT_DST), + PACK (CLEAR, CLEAR, CLEAR, CLEAR), + PACK (SRC, SRC, SRC, SRC), + PACK (DST, DST, DST, DST), PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER), PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE), PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN), @@ -77,9 +77,9 @@ static const uint32_t operator_table[] = 0 /* 0x1e */, 0 /* 0x1f */, - PACK (CONJOINT_CLEAR, CONJOINT_CLEAR, CONJOINT_CLEAR, CONJOINT_CLEAR), - PACK (CONJOINT_SRC, CONJOINT_SRC, CONJOINT_SRC, CONJOINT_SRC), - PACK (CONJOINT_DST, CONJOINT_DST, CONJOINT_DST, CONJOINT_DST), + PACK (CLEAR, CLEAR, CLEAR, CLEAR), + PACK (SRC, SRC, SRC, SRC), + PACK (DST, DST, DST, DST), PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER), PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE), PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN), @@ -588,13 +588,10 @@ do_composite (pixman_implementation_t *imp, * 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) - { + if (op == PIXMAN_OP_DST) return; - } + /* Check cache for fast paths */ cache = tls_cache; for (i = 0; i < N_CACHED_FAST_PATHS; ++i) -- cgit v1.2.3 From f534509d007de40592dedc574e7eb78445453ec0 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Sat, 30 Jan 2010 11:37:25 -0500 Subject: Change operator table to be an array of arrays of four bytes. This makes gcc generate slightly better code for optimize_operator. --- pixman/pixman.c | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/pixman/pixman.c b/pixman/pixman.c index 924ef7cd..c71617e2 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -32,13 +32,20 @@ static pixman_implementation_t *imp; -#define PACK(a, b, c, d) \ - (((uint8_t)PIXMAN_OP_ ## a << 0) | \ - ((uint8_t)PIXMAN_OP_ ## b << 8) | \ - ((uint8_t)PIXMAN_OP_ ## c << 16) | \ - ((uint8_t)PIXMAN_OP_ ## d << 24)) +typedef struct operator_info_t operator_info_t; -static const uint32_t operator_table[] = +struct operator_info_t +{ + uint8_t opaque_info[4]; +}; + +#define PACK(neither, src, dest, both) \ + {{ (uint8_t)PIXMAN_OP_ ## neither, \ + (uint8_t)PIXMAN_OP_ ## src, \ + (uint8_t)PIXMAN_OP_ ## dest, \ + (uint8_t)PIXMAN_OP_ ## both }} + +static const operator_info_t operator_table[] = { /* Neither Opaque Src Opaque Dst Opaque Both Opaque */ PACK (CLEAR, CLEAR, CLEAR, CLEAR), @@ -56,8 +63,8 @@ static const uint32_t operator_table[] = PACK (ADD, ADD, ADD, ADD), PACK (SATURATE, OVER_REVERSE, DST, DST), - 0 /* 0x0e */, - 0 /* 0x0f */, + {{ 0 /* 0x0e */ }}, + {{ 0 /* 0x0f */ }}, PACK (CLEAR, CLEAR, CLEAR, CLEAR), PACK (SRC, SRC, SRC, SRC), @@ -72,10 +79,10 @@ static const uint32_t operator_table[] = PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE), PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR), - 0 /* 0x1c */, - 0 /* 0x1d */, - 0 /* 0x1e */, - 0 /* 0x1f */, + {{ 0 /* 0x1c */ }}, + {{ 0 /* 0x1d */ }}, + {{ 0 /* 0x1e */ }}, + {{ 0 /* 0x1f */ }}, PACK (CLEAR, CLEAR, CLEAR, CLEAR), PACK (SRC, SRC, SRC, SRC), @@ -90,10 +97,10 @@ static const uint32_t operator_table[] = PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE), PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR), - 0 /* 0x2c */, - 0 /* 0x2d */, - 0 /* 0x2e */, - 0 /* 0x2f */, + {{ 0 /* 0x2c */ }}, + {{ 0 /* 0x2d */ }}, + {{ 0 /* 0x2e */ }}, + {{ 0 /* 0x2f */ }}, PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY), PACK (SCREEN, SCREEN, SCREEN, SCREEN), @@ -110,8 +117,6 @@ static const uint32_t operator_table[] = PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION), PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR), PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY), - - 0 }; /* @@ -125,14 +130,14 @@ optimize_operator (pixman_op_t op, uint32_t dst_flags) { pixman_bool_t is_source_opaque, is_dest_opaque; - int shift; + int opaqueness; is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0; is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0; - shift = 8 * ((is_dest_opaque << 1) | is_source_opaque); + opaqueness = ((is_dest_opaque << 1) | is_source_opaque); - return (operator_table[op] >> shift) & 0xff; + return operator_table[op].opaque_info[opaqueness]; } static void -- cgit v1.2.3