};
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;
+}
#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,
}
}
- 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)
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);
}
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 */
return;
if (!imp)
- imp = _pixman_implementation_create_general (NULL);
+ imp = _pixman_implementation_create_fast_path (NULL);
_pixman_implementation_composite (imp, op,
src, mask, dest,
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
*/
/* 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);
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 (®);
+}
+