From: Søren Sandmann Pedersen Date: Wed, 13 May 2009 12:51:09 +0000 (-0400) Subject: Initial fast path implementation X-Git-Tag: 1.0_branch~1126 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=248ef3ec24bfcb4759f12e1839456c0c422b994c;p=profile%2Fivi%2Fpixman.git Initial fast path implementation Move fbSrcScaleNearest() here, and move _pixman_walk_composite_region() to pixman-utils.c --- diff --git a/pixman/pixman-fast-path.c b/pixman/pixman-fast-path.c index 62a39d1..8025233 100644 --- a/pixman/pixman-fast-path.c +++ b/pixman/pixman-fast-path.c @@ -1071,3 +1071,165 @@ static const FastPathInfo c_fast_path_array[] = }; const FastPathInfo *const c_fast_paths = c_fast_path_array; + +static void +fbCompositeSrcScaleNearest (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t *pSrc, + pixman_image_t *pMask, + pixman_image_t *pDst, + int32_t xSrc, + int32_t ySrc, + int32_t xMask, + int32_t yMask, + int32_t xDst, + int32_t yDst, + int32_t width, + int32_t height) +{ + uint32_t *dst; + uint32_t *src; + int dstStride, srcStride; + int i, j; + pixman_vector_t v; + + fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dst, 1); + /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be + * transformed from destination space to source space */ + fbComposeGetStart (pSrc, 0, 0, uint32_t, srcStride, src, 1); + + /* reference point is the center of the pixel */ + v.vector[0] = pixman_int_to_fixed(xSrc) + pixman_fixed_1 / 2; + v.vector[1] = pixman_int_to_fixed(ySrc) + pixman_fixed_1 / 2; + v.vector[2] = pixman_fixed_1; + + if (!pixman_transform_point_3d (pSrc->common.transform, &v)) + return; + + /* 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++) { + pixman_fixed_t vx = v.vector[0]; + pixman_fixed_t vy = v.vector[1]; + for (i = 0; i < width; ++i) { + pixman_bool_t inside_bounds; + uint32_t result; + int x, y; + x = vx >> 16; + y = vy >> 16; + + /* apply the repeat function */ + switch (pSrc->common.repeat) { + case PIXMAN_REPEAT_NORMAL: + x = MOD (x, pSrc->bits.width); + y = MOD (y, pSrc->bits.height); + inside_bounds = TRUE; + break; + + case PIXMAN_REPEAT_PAD: + x = CLIP (x, 0, pSrc->bits.width-1); + y = CLIP (y, 0, pSrc->bits.height-1); + inside_bounds = TRUE; + break; + + case PIXMAN_REPEAT_REFLECT: + x = MOD (x, pSrc->bits.width * 2); + if (x >= pSrc->bits.width) + x = pSrc->bits.width * 2 - x - 1; + y = MOD (y, pSrc->bits.height * 2); + if (y >= pSrc->bits.height) + y = pSrc->bits.height * 2 - y - 1; + inside_bounds = TRUE; + break; + + case PIXMAN_REPEAT_NONE: + default: + inside_bounds = (x >= 0 && x < pSrc->bits.width && y >= 0 && y < pSrc->bits.height); + break; + } + + if (inside_bounds) { + //XXX: we should move this multiplication out of the loop + result = READ(pSrc, src + y * srcStride + x); + } else { + result = 0; + } + WRITE(pDst, dst + i, result); + + /* 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 += pSrc->common.transform->matrix[0][0]; + } + /* 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] += pSrc->common.transform->matrix[1][1]; + dst += dstStride; + } +} + +static void +fast_path_composite (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t *src, + pixman_image_t *mask, + pixman_image_t *dest, + 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) +{ + if (src->type == BITS + && src->common.transform + && !mask + && op == PIXMAN_OP_SRC + && !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 + && src->common.src_clip == &(src->common.full_region) + && !src->common.read_func && !src->common.write_func + && !dest->common.read_func && !dest->common.write_func) + { + /* ensure that the transform matrix only has a scale */ + if (src->common.transform->matrix[0][1] == 0 && + src->common.transform->matrix[1][0] == 0 && + src->common.transform->matrix[2][0] == 0 && + src->common.transform->matrix[2][1] == 0 && + src->common.transform->matrix[2][2] == pixman_fixed_1) + { + _pixman_walk_composite_region (imp, op, + src, mask, dest, + src_x, src_y, + mask_x, mask_y, + dest_x, dest_y, + width, height, + FALSE, FALSE, + fbCompositeSrcScaleNearest); + return; + } + } + + _pixman_implementation_composite (imp->delegate, op, + src, mask, dest, + src_x, src_y, + mask_x, mask_y, + dest_x, dest_y, + width, height); +} + +pixman_implementation_t * +_pixman_implementation_create_fast_path (pixman_implementation_t *toplevel) +{ + pixman_implementation_t *general = _pixman_implementation_create_general (NULL); + pixman_implementation_t *imp = _pixman_implementation_create (toplevel, general); + + imp->composite = fast_path_composite; + + return imp; +} diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index 734dfce..f507aad 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -318,197 +318,6 @@ general_composite_rect (const FbComposeData *data) #include "pixman-combine32.h" static void -fbCompositeSrcScaleNearest (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t *pSrc, - pixman_image_t *pMask, - pixman_image_t *pDst, - int32_t xSrc, - int32_t ySrc, - int32_t xMask, - int32_t yMask, - int32_t xDst, - int32_t yDst, - int32_t width, - int32_t height) -{ - uint32_t *dst; - uint32_t *src; - int dstStride, srcStride; - int i, j; - pixman_vector_t v; - - fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dst, 1); - /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be - * transformed from destination space to source space */ - fbComposeGetStart (pSrc, 0, 0, uint32_t, srcStride, src, 1); - - /* reference point is the center of the pixel */ - v.vector[0] = pixman_int_to_fixed(xSrc) + pixman_fixed_1 / 2; - v.vector[1] = pixman_int_to_fixed(ySrc) + pixman_fixed_1 / 2; - v.vector[2] = pixman_fixed_1; - - if (!pixman_transform_point_3d (pSrc->common.transform, &v)) - return; - - /* 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++) { - pixman_fixed_t vx = v.vector[0]; - pixman_fixed_t vy = v.vector[1]; - for (i = 0; i < width; ++i) { - pixman_bool_t inside_bounds; - uint32_t result; - int x, y; - x = vx >> 16; - y = vy >> 16; - - /* apply the repeat function */ - switch (pSrc->common.repeat) { - case PIXMAN_REPEAT_NORMAL: - x = MOD (x, pSrc->bits.width); - y = MOD (y, pSrc->bits.height); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_PAD: - x = CLIP (x, 0, pSrc->bits.width-1); - y = CLIP (y, 0, pSrc->bits.height-1); - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_REFLECT: - x = MOD (x, pSrc->bits.width * 2); - if (x >= pSrc->bits.width) - x = pSrc->bits.width * 2 - x - 1; - y = MOD (y, pSrc->bits.height * 2); - if (y >= pSrc->bits.height) - y = pSrc->bits.height * 2 - y - 1; - inside_bounds = TRUE; - break; - - case PIXMAN_REPEAT_NONE: - default: - inside_bounds = (x >= 0 && x < pSrc->bits.width && y >= 0 && y < pSrc->bits.height); - break; - } - - if (inside_bounds) { - //XXX: we should move this multiplication out of the loop - result = READ(pSrc, src + y * srcStride + x); - } else { - result = 0; - } - WRITE(pDst, dst + i, result); - - /* 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 += pSrc->common.transform->matrix[0][0]; - } - /* 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] += pSrc->common.transform->matrix[1][1]; - dst += dstStride; - } -} - -static void -pixman_walk_composite_region (pixman_implementation_t *imp, - pixman_op_t op, - pixman_image_t * pSrc, - pixman_image_t * pMask, - pixman_image_t * pDst, - int16_t xSrc, - int16_t ySrc, - int16_t xMask, - int16_t yMask, - int16_t xDst, - int16_t yDst, - uint16_t width, - uint16_t height, - pixman_bool_t srcRepeat, - pixman_bool_t maskRepeat, - pixman_composite_func_t compositeRect) -{ - int n; - const pixman_box32_t *pbox; - int w, h, w_this, h_this; - int x_msk, y_msk, x_src, y_src, x_dst, y_dst; - pixman_region32_t reg; - pixman_region32_t *region; - - pixman_region32_init (®); - if (!pixman_compute_composite_region32 (®, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) - { - return; - } - - region = ® - - pbox = pixman_region32_rectangles (region, &n); - while (n--) - { - h = pbox->y2 - pbox->y1; - y_src = pbox->y1 - yDst + ySrc; - y_msk = pbox->y1 - yDst + yMask; - y_dst = pbox->y1; - while (h) - { - h_this = h; - w = pbox->x2 - pbox->x1; - x_src = pbox->x1 - xDst + xSrc; - x_msk = pbox->x1 - xDst + xMask; - x_dst = pbox->x1; - if (maskRepeat) - { - y_msk = MOD (y_msk, pMask->bits.height); - if (h_this > pMask->bits.height - y_msk) - h_this = pMask->bits.height - y_msk; - } - if (srcRepeat) - { - y_src = MOD (y_src, pSrc->bits.height); - if (h_this > pSrc->bits.height - y_src) - h_this = pSrc->bits.height - y_src; - } - while (w) - { - w_this = w; - if (maskRepeat) - { - x_msk = MOD (x_msk, pMask->bits.width); - if (w_this > pMask->bits.width - x_msk) - w_this = pMask->bits.width - x_msk; - } - if (srcRepeat) - { - x_src = MOD (x_src, pSrc->bits.width); - if (w_this > pSrc->bits.width - x_src) - w_this = pSrc->bits.width - x_src; - } - (*compositeRect) (imp, - op, pSrc, pMask, pDst, - x_src, y_src, x_msk, y_msk, x_dst, y_dst, - w_this, h_this); - w -= w_this; - x_src += w_this; - x_msk += w_this; - x_dst += w_this; - } - h -= h_this; - y_src += h_this; - y_msk += h_this; - y_dst += h_this; - } - pbox++; - } - pixman_region32_fini (®); -} - -static void pixman_image_composite_rect (pixman_implementation_t *imp, pixman_op_t op, pixman_image_t *src, @@ -702,29 +511,7 @@ general_composite (pixman_implementation_t * imp, } } - if (src->type == BITS - && srcTransform - && !mask - && op == PIXMAN_OP_SRC - && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap - && (src->common.filter == PIXMAN_FILTER_NEAREST) - && PIXMAN_FORMAT_BPP(dest->bits.format) == 32 - && src->bits.format == dest->bits.format - && src->common.src_clip == &(src->common.full_region) - && !src->common.read_func && !src->common.write_func - && !dest->common.read_func && !dest->common.write_func) - { - /* ensure that the transform matrix only has a scale */ - if (src->common.transform->matrix[0][1] == 0 && - src->common.transform->matrix[1][0] == 0 && - src->common.transform->matrix[2][0] == 0 && - src->common.transform->matrix[2][1] == 0 && - src->common.transform->matrix[2][2] == pixman_fixed_1) { - func = fbCompositeSrcScaleNearest; - /* Like the general path, fbCompositeSrcScaleNearest handles all the repeat types itself */ - srcRepeat = FALSE; - } - } else if ((src->type == BITS || pixman_image_can_get_solid (src)) && (!mask || mask->type == BITS) + if ((src->type == BITS || pixman_image_can_get_solid (src)) && (!mask || mask->type == BITS) && !srcTransform && !maskTransform && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap && (src->common.filter != PIXMAN_FILTER_CONVOLUTION) @@ -836,7 +623,7 @@ general_composite (pixman_implementation_t * imp, maskRepeat = FALSE; } - pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y, + _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height, srcRepeat, maskRepeat, func); } diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c index 05b0a9c..8f18b06 100644 --- a/pixman/pixman-mmx.c +++ b/pixman/pixman-mmx.c @@ -3143,7 +3143,7 @@ const FastPathInfo *const mmx_fast_paths = mmx_fast_path_array; pixman_implementation_t * _pixman_implementation_create_mmx (pixman_implementation_t *toplevel) { - pixman_implementation_t *general = _pixman_implementation_create_general (NULL); + pixman_implementation_t *general = _pixman_implementation_create_fast_path (NULL); pixman_implementation_t *imp = _pixman_implementation_create (toplevel, general); /* check if we have MMX support and initialize accordingly */ diff --git a/pixman/pixman-pict.c b/pixman/pixman-pict.c index a76ce21..18ec4f8 100644 --- a/pixman/pixman-pict.c +++ b/pixman/pixman-pict.c @@ -127,7 +127,7 @@ pixman_image_composite (pixman_op_t op, return; if (!imp) - imp = _pixman_implementation_create_general (NULL); + imp = _pixman_implementation_create_fast_path (NULL); _pixman_implementation_composite (imp, op, src, mask, dest, diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index e660be6..a8c6ce4 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -896,6 +896,24 @@ typedef void (* pixman_composite_func_t) (pixman_implementation_t * imp, int32_t width, int32_t height); +void +_pixman_walk_composite_region (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * pSrc, + pixman_image_t * pMask, + pixman_image_t * pDst, + int16_t xSrc, + int16_t ySrc, + int16_t xMask, + int16_t yMask, + int16_t xDst, + int16_t yDst, + uint16_t width, + uint16_t height, + pixman_bool_t srcRepeat, + pixman_bool_t maskRepeat, + pixman_composite_func_t compositeRect); + /* These "formats" both have depth 0, so they * will never clash with any real ones */ @@ -981,6 +999,8 @@ _pixman_implementation_composite (pixman_implementation_t * imp, /* Specific implementations */ pixman_implementation_t * _pixman_implementation_create_general (pixman_implementation_t *toplevel); +pixman_implementation_t * +_pixman_implementation_create_fast_path (pixman_implementation_t *toplevel); #ifdef USE_MMX pixman_implementation_t * _pixman_implementation_create_mmx (pixman_implementation_t *toplevel); diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c index cdf0220..e445c3c 100644 --- a/pixman/pixman-utils.c +++ b/pixman/pixman-utils.c @@ -593,3 +593,98 @@ pixman_format_supported_source (pixman_format_code_t format) return FALSE; } } + +void +_pixman_walk_composite_region (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * pSrc, + pixman_image_t * pMask, + pixman_image_t * pDst, + int16_t xSrc, + int16_t ySrc, + int16_t xMask, + int16_t yMask, + int16_t xDst, + int16_t yDst, + uint16_t width, + uint16_t height, + pixman_bool_t srcRepeat, + pixman_bool_t maskRepeat, + pixman_composite_func_t compositeRect) +{ + int n; + const pixman_box32_t *pbox; + int w, h, w_this, h_this; + int x_msk, y_msk, x_src, y_src, x_dst, y_dst; + pixman_region32_t reg; + pixman_region32_t *region; + + pixman_region32_init (®); + if (!pixman_compute_composite_region32 (®, pSrc, pMask, pDst, + xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) + { + return; + } + + region = ® + + pbox = pixman_region32_rectangles (region, &n); + while (n--) + { + h = pbox->y2 - pbox->y1; + y_src = pbox->y1 - yDst + ySrc; + y_msk = pbox->y1 - yDst + yMask; + y_dst = pbox->y1; + while (h) + { + h_this = h; + w = pbox->x2 - pbox->x1; + x_src = pbox->x1 - xDst + xSrc; + x_msk = pbox->x1 - xDst + xMask; + x_dst = pbox->x1; + if (maskRepeat) + { + y_msk = MOD (y_msk, pMask->bits.height); + if (h_this > pMask->bits.height - y_msk) + h_this = pMask->bits.height - y_msk; + } + if (srcRepeat) + { + y_src = MOD (y_src, pSrc->bits.height); + if (h_this > pSrc->bits.height - y_src) + h_this = pSrc->bits.height - y_src; + } + while (w) + { + w_this = w; + if (maskRepeat) + { + x_msk = MOD (x_msk, pMask->bits.width); + if (w_this > pMask->bits.width - x_msk) + w_this = pMask->bits.width - x_msk; + } + if (srcRepeat) + { + x_src = MOD (x_src, pSrc->bits.width); + if (w_this > pSrc->bits.width - x_src) + w_this = pSrc->bits.width - x_src; + } + (*compositeRect) (imp, + op, pSrc, pMask, pDst, + x_src, y_src, x_msk, y_msk, x_dst, y_dst, + w_this, h_this); + w -= w_this; + x_src += w_this; + x_msk += w_this; + x_dst += w_this; + } + h -= h_this; + y_src += h_this; + y_msk += h_this; + y_dst += h_this; + } + pbox++; + } + pixman_region32_fini (®); +} +