diff options
author | Søren Sandmann Pedersen <sandmann@redhat.com> | 2009-05-30 02:50:38 -0400 |
---|---|---|
committer | Søren Sandmann Pedersen <sandmann@redhat.com> | 2010-02-13 16:41:53 -0500 |
commit | e5972110750b32929a474c35362f4639dbbd1222 (patch) | |
tree | f0f2b44ff169f59a56c9ae619f1ad49e982c611e | |
parent | 337e916473069a76a44757b3664f8d49da350773 (diff) |
Generalize and optimize fast_composite_src_scaled_nearest()
- Make it work for PIXMAN_OP_OVER
- Split repeat computation for x and y, and only the x part in the
inner loop.
- Move stride multiplication outside of inner loop
-rw-r--r-- | pixman/pixman-fast-path.c | 201 |
1 files changed, 118 insertions, 83 deletions
diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 54b74229..37a97192 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1403,30 +1403,64 @@ static const pixman_fast_path_t c_fast_paths[] = { PIXMAN_OP_NONE }, }; +static force_inline pixman_bool_t +repeat (pixman_repeat_t repeat, int *c, int size) +{ + if (repeat == PIXMAN_REPEAT_NONE) + { + if (*c < 0 || *c >= size) + return FALSE; + } + else if (repeat == PIXMAN_REPEAT_NORMAL) + { + while (*c >= size) + *c -= size; + while (*c < 0) + *c += size; + } + else if (repeat == PIXMAN_REPEAT_PAD) + { + *c = CLIP (*c, 0, size - 1); + } + else /* REFLECT */ + { + *c = MOD (*c, size * 2); + if (*c >= size) + *c = size * 2 - *c - 1; + } + return TRUE; +} + static void -fast_composite_src_scale_nearest (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dst_image, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +fast_composite_scaled_nearest (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { uint32_t *dst; uint32_t *src; int dst_stride, src_stride; - int i, j; + int i; + int src_width, src_height; + pixman_repeat_t src_repeat; + pixman_fixed_t unit_x, unit_y; + pixman_format_code_t src_format; pixman_vector_t v; + pixman_fixed_t vy; PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst, 1); /* pass in 0 instead of src_x and src_y because src_x and src_y need to be - * transformed from destination space to source space */ + * transformed from destination space to source space + */ PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, uint32_t, src_stride, src, 1); /* reference point is the center of the pixel */ @@ -1437,81 +1471,82 @@ fast_composite_src_scale_nearest (pixman_implementation_t *imp, if (!pixman_transform_point_3d (src_image->common.transform, &v)) return; + unit_x = src_image->common.transform->matrix[0][0]; + unit_y = src_image->common.transform->matrix[1][1]; + /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ v.vector[0] -= pixman_fixed_e; v.vector[1] -= pixman_fixed_e; - for (j = 0; j < height; j++) + src_height = src_image->bits.height; + src_width = src_image->bits.width; + src_repeat = src_image->common.repeat; + src_format = src_image->bits.format; + + vy = v.vector[1]; + while (height--) { - pixman_fixed_t vx = v.vector[0]; - pixman_fixed_t vy = v.vector[1]; + pixman_fixed_t vx = v.vector[0]; + uint32_t *src_line; + int y = pixman_fixed_to_int (vy); - for (i = 0; i < width; ++i) + if (!repeat (src_repeat, &y, src_height)) { - pixman_bool_t inside_bounds; - uint32_t result; - int x, y; - x = vx >> 16; - y = vy >> 16; - - /* apply the repeat function */ - switch (src_image->common.repeat) - { - case PIXMAN_REPEAT_NORMAL: - x = MOD (x, src_image->bits.width); - y = MOD (y, src_image->bits.height); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_PAD: - x = CLIP (x, 0, src_image->bits.width - 1); - y = CLIP (y, 0, src_image->bits.height - 1); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_REFLECT: - x = MOD (x, src_image->bits.width * 2); - if (x >= src_image->bits.width) - x = src_image->bits.width * 2 - x - 1; - y = MOD (y, src_image->bits.height * 2); - if (y >= src_image->bits.height) - y = src_image->bits.height * 2 - y - 1; - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_NONE: - default: - inside_bounds = - (x >= 0 && - x < src_image->bits.width && - y >= 0 && - y < src_image->bits.height); - break; - } + if (op == PIXMAN_OP_SRC) + memset (dst, 0, sizeof (*dst) * width); + } + else + { + src_line = src + y * src_stride; - if (inside_bounds) - { - /* XXX: we should move this multiplication out of the loop */ - result = *(src + y * src_stride + x); - } - else + for (i = 0; i < width; ++i) { - result = 0; - } - *(dst + i) = result; + uint32_t s, d; + int x; + x = pixman_fixed_to_int (vx); - /* adjust the x location by a unit vector in the x direction: - * this is equivalent to transforming x+1 of the destination - * point to source space - */ - vx += src_image->common.transform->matrix[0][0]; + if (!repeat (src_repeat, &x, src_width)) + { + s = 0; + } + else + { + s = *(src_line + x); + + if (src_format == PIXMAN_x8r8g8b8) + s |= 0xff000000; + } + + d = s; + if (op == PIXMAN_OP_OVER) + { + uint8_t ia; + + if (!s) + goto skip_write; + + ia = 0xff - (s >> 24); + + if (ia) + { + d = *(dst + i); + + UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s); + } + } + *(dst + i) = d; + + skip_write: + /* adjust the x location by a unit vector in the x direction: + * this is equivalent to transforming x+1 of the destination point to source space */ + vx += unit_x; + } } - /* adjust the y location by a unit vector in the y direction - * this is equivalent to transforming y+1 of the destination point - * to source space - */ - v.vector[1] += src_image->common.transform->matrix[1][1]; - dst += dst_stride; + + /* adjust the y location by a unit vector in the y direction + * this is equivalent to transforming y+1 of the destination point to source space */ + vy += unit_y; + dst += dst_stride; } } @@ -1533,11 +1568,11 @@ fast_path_composite (pixman_implementation_t *imp, if (src->type == BITS && src->common.transform && !mask - && op == PIXMAN_OP_SRC + && (op == PIXMAN_OP_SRC || op == PIXMAN_OP_OVER) && !src->common.alpha_map && !dest->common.alpha_map && (src->common.filter == PIXMAN_FILTER_NEAREST) - && PIXMAN_FORMAT_BPP (dest->bits.format) == 32 - && src->bits.format == dest->bits.format + && (dest->bits.format == PIXMAN_a8r8g8b8 || dest->bits.format == PIXMAN_x8r8g8b8) + && (src->bits.format == PIXMAN_a8r8g8b8 || src->bits.format == PIXMAN_x8r8g8b8) && !src->bits.read_func && !src->bits.write_func && !dest->bits.read_func && !dest->bits.write_func) { @@ -1554,7 +1589,7 @@ fast_path_composite (pixman_implementation_t *imp, mask_x, mask_y, dest_x, dest_y, width, height, - fast_composite_src_scale_nearest); + fast_composite_scaled_nearest); return; } } |