diff options
-rw-r--r-- | pixman/pixman.c | 177 |
1 files changed, 103 insertions, 74 deletions
diff --git a/pixman/pixman.c b/pixman/pixman.c index b43ea926..c71617e2 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -30,82 +30,114 @@ #include <stdlib.h> -/* - * 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; -} optimized_operator_info_t; +static pixman_implementation_t *imp; -static const optimized_operator_info_t optimized_operators[] = +typedef struct operator_info_t operator_info_t; + +struct operator_info_t { - /* 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 } + uint8_t opaque_info[4]; }; -static pixman_implementation_t *imp; +#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 }} -/* - * Check if the current operator could be optimized - */ -static const optimized_operator_info_t* -pixman_operator_can_be_optimized (pixman_op_t op) +static const operator_info_t operator_table[] = { - const optimized_operator_info_t *info; - - for (info = optimized_operators; info->op != PIXMAN_OP_NONE; info++) - { - if (info->op == op) - return info; - } - return NULL; -} + /* 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 (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), + 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 (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), + 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), +}; /* * 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; - - is_source_opaque = src_image->common.flags & FAST_PATH_IS_OPAQUE; - is_dest_opaque = dst_image->common.flags & FAST_PATH_IS_OPAQUE; - - if (!is_source_opaque && !is_dest_opaque) - return op; + pixman_bool_t is_source_opaque, is_dest_opaque; + int opaqueness; - 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; + is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0; + is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0; - return op; + opaqueness = ((is_dest_opaque << 1) | is_source_opaque); + return operator_table[op].opaque_info[opaqueness]; } static void @@ -510,7 +542,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 +587,16 @@ 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) + return; + + /* Check cache for fast paths */ cache = tls_cache; for (i = 0; i < N_CACHED_FAST_PATHS; ++i) @@ -713,19 +755,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 (); |