diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c index 1e91864..e868a82 100644 --- a/pixman/pixman-compose.c +++ b/pixman/pixman-compose.c @@ -90,7 +90,7 @@ SourcePictureClassify (source_image_t *pict, v.vector[0] = pixman_int_to_fixed ((i % 2) * (width - 1) + x); v.vector[1] = pixman_int_to_fixed ((i / 2) * (height - 1) + y); v.vector[2] = pixman_fixed_1; - + if (pict->common.transform) { if (!pixman_transform_point_3d (pict->common.transform, &v)) @@ -2866,7 +2866,7 @@ static void fbFetchSolid(bits_image_t * pict, int x, int y, int width, uint32_t uint32_t *end; fetchPixelProc fetch = fetchPixelProcForPicture(pict); const pixman_indexed_t * indexed = pict->indexed; - + bits = pict->bits; color = fetch((pixman_image_t *)pict, bits, 0, indexed); @@ -2877,16 +2877,22 @@ static void fbFetchSolid(bits_image_t * pict, int x, int y, int width, uint32_t fbFinishAccess (pict->pDrawable); } -static void fbFetch(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits) +static void fbFetch (bits_image_t *pict, + int x, + int y, + int width, + uint32_t *buffer, + uint32_t *mask, + uint32_t maskBits) { uint32_t *bits; uint32_t stride; fetchProc fetch = fetchProcForPicture(pict); const pixman_indexed_t * indexed = pict->indexed; - + bits = pict->bits; stride = pict->rowstride; - + bits += y*stride; fetch((pixman_image_t *)pict, bits, x, width, buffer, indexed); @@ -3139,7 +3145,7 @@ static void pixmanFetchSourcePict(source_image_t * pict, int x, int y, int width GradientWalker walker; uint32_t *end = buffer + width; gradient_t *gradient; - + if (pict->common.type == SOLID) { register uint32_t color = ((solid_fill_t *)pict)->color; @@ -3557,7 +3563,171 @@ static void pixmanFetchSourcePict(source_image_t * pict, int x, int y, int width } } -static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits) +static inline void +fbFetchTransformed_NearestNormalRegion1 (bits_image_t *pict, + int width, + pixman_vector_t v, + pixman_vector_t unit, + uint32_t *buffer, + pixman_bool_t affine, + fetchPixelProc fetch, + uint32_t *mask, + uint32_t maskBits) +{ + int i; + uint32_t *bits = pict->bits; + uint32_t stride = pict->rowstride; + + if (!mask) + { + if (affine) + { + pixman_fixed_t vec0 = v.vector[0]; + pixman_fixed_t vec1 = v.vector[1]; + pixman_fixed_t vec2 = v.vector[2]; + + const pixman_fixed_t uvec0 = unit.vector[0]; + const pixman_fixed_t uvec1 = unit.vector[1]; + const pixman_fixed_t uvec2 = unit.vector[2]; + + if (uvec0 && !uvec1 && !uvec2) + { + /* There is no rotation in this case. x is the only + component changing. */ + + /* Compute what the last x coordinate to fetch from + is. If it is smaller than pict->width, then we can + avoid the MOD operation because the image doesn't + wrap in the x-direction. */ + int last_x = (vec0 + (width - 1) * uvec0) >> 16; + uint32_t *bits_ofs = + bits + MOD (vec1 >> 16, pict->height) * stride; + + if (last_x < pict->width) + { + /* MOD avoided. */ + for (i = 0; i < width; i++) + { + int x = vec0 >> 16; + *(buffer + i) = fetch ((pixman_image_t *) pict, + bits_ofs, + x, + pict->indexed); + vec0 += uvec0; + } + } + else + { + /* MOD is needed. */ + for (i = 0; i < width; i++) + { + int x = vec0 >> 16; + x = MOD (x, pict->width); + + *(buffer + i) = fetch ((pixman_image_t *) pict, + bits_ofs, + x, + pict->indexed); + vec0 += uvec0; + } + } + } + else + { + /* There may be rotation. */ + for (i = 0; i < width; i++) + { + if (!v.vector[2]) + { + *(buffer + i) = 0; + } + else + { + int x = v.vector[0] >> 16; + int y = v.vector[1] >> 16; + x = MOD (x, pict->width); + y = MOD (y, pict->height); + *(buffer + i) = fetch ((pixman_image_t *) pict, + bits + y * stride, + x, + pict->indexed); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } + else + { + for (i = 0; i < width; i++) + { + if (!v.vector[2]) + { + *(buffer + i) = 0; + } + else + { + int x = DIV (v.vector[0], v.vector[2]); + int y = DIV (v.vector[1], v.vector[2]); + x = MOD (x, pict->width); + y = MOD (y, pict->height); + *(buffer + i) = fetch ((pixman_image_t *) pict, + bits + y * stride, + x, + pict->indexed); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } + } + else + { + for (i = 0; i < width; i++) + { + if (!(mask[i] & maskBits)) + continue; + if (!v.vector[2]) + { + *(buffer + i) = 0; + } + else + { + int x; + int y; + if (!affine) + { + x = DIV (v.vector[0], v.vector[2]); + y = DIV (v.vector[1], v.vector[2]); + } + else + { + x = v.vector[0] >> 16; + y = v.vector[1] >> 16; + } + x = MOD (x, pict->width); + y = MOD (y, pict->height); + *(buffer + i) = fetch((pixman_image_t *) pict, + bits + y * stride, + x, + pict->indexed); + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } + } +} + +static void fbFetchTransformed(bits_image_t * pict, + int x, + int y, + int width, + uint32_t *buffer, + uint32_t *mask, + uint32_t maskBits) { uint32_t *bits; uint32_t stride; @@ -3568,17 +3738,17 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin pixman_box16_t box; const pixman_indexed_t * indexed = pict->indexed; pixman_bool_t affine = TRUE; - + fetch = fetchPixelProcForPicture(pict); - + bits = pict->bits; stride = pict->rowstride; - + /* reference point is the center of the pixel */ v.vector[0] = pixman_int_to_fixed(x) + pixman_fixed_1 / 2; v.vector[1] = pixman_int_to_fixed(y) + pixman_fixed_1 / 2; v.vector[2] = pixman_fixed_1; - + /* when using convolution filters one might get here without a transform */ if (pict->common.transform) { @@ -3599,31 +3769,20 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin unit.vector[2] = 0; } - if (pict->common.filter == PIXMAN_FILTER_NEAREST || pict->common.filter == PIXMAN_FILTER_FAST) + if (pict->common.filter == PIXMAN_FILTER_NEAREST || + pict->common.filter == PIXMAN_FILTER_FAST) { if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) { if (pixman_region_n_rects (pict->common.src_clip) == 1) { - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits) - { - if (!v.vector[2]) { - *(buffer + i) = 0; - } else { - if (!affine) { - y = MOD(DIV(v.vector[1],v.vector[2]), pict->height); - x = MOD(DIV(v.vector[0],v.vector[2]), pict->width); - } else { - y = MOD(v.vector[1]>>16, pict->height); - x = MOD(v.vector[0]>>16, pict->width); - } - *(buffer + i) = fetch((pixman_image_t *)pict, bits + y * stride, x, indexed); - } - } - - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } + fbFetchTransformed_NearestNormalRegion1 (pict, + width, + v, + unit, + buffer, + affine, + fetch, + mask, + maskBits); } else { for (i = 0; i < width; ++i) { if (!mask || mask[i] & maskBits) @@ -4165,7 +4324,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, uint32_t *bits; uint32_t stride; int xoff, yoff; - + if (data->op == PIXMAN_OP_CLEAR) fetchSrc = NULL; else if (IS_SOURCE_IMAGE (data->src))