From 4f33f454c6dbaf356d20cee8d35fdf02f9a0317d Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Fri, 21 Mar 2008 18:59:45 -0700 Subject: [PATCH] Move fbFetchTransformed and friends into pixman-transformed.c. --- pixman/Makefile.am | 2 + pixman/Makefile.win32 | 2 + pixman/pixman-compose.c | 694 +------------------------------- pixman/pixman-private.h | 16 + pixman/pixman-transformed-accessors.c | 3 + pixman/pixman-transformed.c | 726 ++++++++++++++++++++++++++++++++++ 6 files changed, 768 insertions(+), 675 deletions(-) create mode 100644 pixman/pixman-transformed-accessors.c create mode 100644 pixman/pixman-transformed.c diff --git a/pixman/Makefile.am b/pixman/Makefile.am index 79c6788..37d892b 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -13,6 +13,8 @@ libpixman_1_la_SOURCES = \ pixman-compose-accessors.c \ pixman-pict.c \ pixman-source.c \ + pixman-transformed.c \ + pixman-transformed-accessors.c \ pixman-utils.c \ pixman-edge.c \ pixman-edge-accessors.c \ diff --git a/pixman/Makefile.win32 b/pixman/Makefile.win32 index b4096f2..bee8289 100644 --- a/pixman/Makefile.win32 +++ b/pixman/Makefile.win32 @@ -31,6 +31,8 @@ SOURCES = \ pixman-compose-accessors.c \ pixman-pict.c \ pixman-source.c \ + pixman-transformed.c \ + pixman-transformed-accessors.c \ pixman-utils.c \ pixman-edge.c \ pixman-edge-accessors.c \ diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c index 00d0171..6f524d6 100644 --- a/pixman/pixman-compose.c +++ b/pixman/pixman-compose.c @@ -38,15 +38,28 @@ #ifdef PIXMAN_FB_ACCESSORS #define PIXMAN_COMPOSITE_RECT_GENERAL pixman_composite_rect_general_accessors #define PIXMAN_COMPOSE_FUNCTIONS pixman_composeFunctions_accessors + #define FETCH_PROC_FOR_PICTURE pixman_fetchProcForPicture_accessors #define FETCH_PIXEL_PROC_FOR_PICTURE pixman_fetchPixelProcForPicture_accessors #define STORE_PROC_FOR_PICTURE pixman_storeProcForPicture_accessors + +#define FB_FETCH_TRANSFORMED fbFetchTransformed_accessors +#define FB_FETCH_EXTERNAL_ALPHA fbFetchExternalAlpha_accessors +#define FB_STORE_EXTERNAL_ALPHA fbStoreExternalAlpha_accessors + #else + #define PIXMAN_COMPOSITE_RECT_GENERAL pixman_composite_rect_general_no_accessors #define PIXMAN_COMPOSE_FUNCTIONS pixman_composeFunctions + #define FETCH_PROC_FOR_PICTURE pixman_fetchProcForPicture #define FETCH_PIXEL_PROC_FOR_PICTURE pixman_fetchPixelProcForPicture #define STORE_PROC_FOR_PICTURE pixman_storeProcForPicture + +#define FB_FETCH_TRANSFORMED fbFetchTransformed +#define FB_FETCH_EXTERNAL_ALPHA fbFetchExternalAlpha +#define FB_STORE_EXTERNAL_ALPHA fbStoreExternalAlpha + #endif static unsigned int @@ -109,8 +122,6 @@ SourcePictureClassify (source_image_t *pict, return pict->class; } -#define SCANLINE_BUFFER_LENGTH 2048 - static void fbFetchSolid(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits) { uint32_t color; @@ -140,635 +151,6 @@ FbComposeFunctions PIXMAN_COMPOSE_FUNCTIONS = { pixman_fbCombineMaskU }; -/* - * Fetch from region strategies - */ -typedef FASTCALL uint32_t (*fetchFromRegionProc)(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box); - -static inline uint32_t -fbFetchFromNoRegion(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box) -{ - return fetch (pict, x, y); -} - -static uint32_t -fbFetchFromNRectangles(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box) -{ - pixman_box16_t box2; - if (pixman_region_contains_point (pict->common.src_clip, x, y, &box2)) - return fbFetchFromNoRegion(pict, x, y, buffer, fetch, box); - else - return 0; -} - -static uint32_t -fbFetchFromOneRectangle(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box) -{ - pixman_box16_t box2 = *box; - return ((x < box2.x1) | (x >= box2.x2) | (y < box2.y1) | (y >= box2.y2)) ? - 0 : fbFetchFromNoRegion(pict, x, y, buffer, fetch, box); -} - -/* - * Fetching Algorithms - */ -static void -fbFetchTransformed_Nearest_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) -{ - pixman_box16_t* box = NULL; - fetchPixelProc fetch; - fetchFromRegionProc fetchFromRegion; - int x, y, i; - - /* initialize the two function pointers */ - fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); - - if(pixman_region_n_rects (pict->common.src_clip) == 1) - fetchFromRegion = fbFetchFromNoRegion; - else - fetchFromRegion = fbFetchFromNRectangles; - - 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) = fetchFromRegion(pict, x, y, buffer, fetch, box); - } - } - - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } -} - -static void -fbFetchTransformed_Nearest_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) -{ - pixman_box16_t *box = NULL; - fetchPixelProc fetch; - fetchFromRegionProc fetchFromRegion; - int x, y, i; - - /* initialize the two function pointers */ - fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); - - if(pixman_region_n_rects (pict->common.src_clip) == 1) - fetchFromRegion = fbFetchFromNoRegion; - else - fetchFromRegion = fbFetchFromNRectangles; - - for (i = 0; i < width; ++i) - { - if (!mask || mask[i] & maskBits) - { - if (!v.vector[2]) - { - *(buffer + i) = 0; - } - else - { - if (!affine) - { - y = CLIP(DIV(v.vector[1], v.vector[2]), 0, pict->height-1); - x = CLIP(DIV(v.vector[0], v.vector[2]), 0, pict->width-1); - } - else - { - y = CLIP(v.vector[1]>>16, 0, pict->height-1); - x = CLIP(v.vector[0]>>16, 0, pict->width-1); - } - - *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box); - } - } - - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } -} - -static void -fbFetchTransformed_Nearest_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) -{ - pixman_box16_t *box = NULL; - fetchPixelProc fetch; - fetchFromRegionProc fetchFromRegion; - int x, y, i; - - /* initialize the two function pointers */ - fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); - - if(pixman_region_n_rects (pict->common.src_clip) == 1) - { - box = &(pict->common.src_clip->extents); - fetchFromRegion = fbFetchFromOneRectangle; - } - else - { - fetchFromRegion = fbFetchFromNRectangles; - } - - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits) - { - if (!v.vector[2]) { - *(buffer + i) = 0; - } else { - if (!affine) { - y = DIV(v.vector[1],v.vector[2]); - x = DIV(v.vector[0],v.vector[2]); - } else { - y = v.vector[1]>>16; - x = v.vector[0]>>16; - } - *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box); - } - } - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } -} - -static void -fbFetchTransformed_Bilinear_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) -{ - pixman_box16_t *box = NULL; - fetchPixelProc fetch; - fetchFromRegionProc fetchFromRegion; - int i; - - /* initialize the two function pointers */ - fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); - - if(pixman_region_n_rects (pict->common.src_clip) == 1) - fetchFromRegion = fbFetchFromNoRegion; - else - fetchFromRegion = fbFetchFromNRectangles; - - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits) - { - if (!v.vector[2]) { - *(buffer + i) = 0; - } else { - int x1, x2, y1, y2, distx, idistx, disty, idisty; - uint32_t tl, tr, bl, br, r; - uint32_t ft, fb; - - if (!affine) { - pixman_fixed_48_16_t div; - div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2]; - x1 = div >> 16; - distx = ((pixman_fixed_t)div >> 8) & 0xff; - div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2]; - y1 = div >> 16; - disty = ((pixman_fixed_t)div >> 8) & 0xff; - } else { - x1 = v.vector[0] >> 16; - distx = (v.vector[0] >> 8) & 0xff; - y1 = v.vector[1] >> 16; - disty = (v.vector[1] >> 8) & 0xff; - } - x2 = x1 + 1; - y2 = y1 + 1; - - idistx = 256 - distx; - idisty = 256 - disty; - - x1 = MOD (x1, pict->width); - x2 = MOD (x2, pict->width); - y1 = MOD (y1, pict->height); - y2 = MOD (y2, pict->height); - - tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box); - tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box); - bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box); - br = fetchFromRegion(pict, x2, y2, buffer, fetch, box); - - ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; - fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; - r = (((ft * idisty + fb * disty) >> 16) & 0xff); - ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; - fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; - r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); - ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; - fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; - r |= (((ft * idisty + fb * disty)) & 0xff0000); - ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; - fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; - r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); - *(buffer + i) = r; - } - } - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } -} - -static void -fbFetchTransformed_Bilinear_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) -{ - pixman_box16_t *box = NULL; - fetchPixelProc fetch; - fetchFromRegionProc fetchFromRegion; - int i; - - /* initialize the two function pointers */ - fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); - - if(pixman_region_n_rects (pict->common.src_clip) == 1) - fetchFromRegion = fbFetchFromNoRegion; - else - fetchFromRegion = fbFetchFromNRectangles; - - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits) - { - if (!v.vector[2]) { - *(buffer + i) = 0; - } else { - int x1, x2, y1, y2, distx, idistx, disty, idisty; - uint32_t tl, tr, bl, br, r; - uint32_t ft, fb; - - if (!affine) { - pixman_fixed_48_16_t div; - div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2]; - x1 = div >> 16; - distx = ((pixman_fixed_t)div >> 8) & 0xff; - div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2]; - y1 = div >> 16; - disty = ((pixman_fixed_t)div >> 8) & 0xff; - } else { - x1 = v.vector[0] >> 16; - distx = (v.vector[0] >> 8) & 0xff; - y1 = v.vector[1] >> 16; - disty = (v.vector[1] >> 8) & 0xff; - } - x2 = x1 + 1; - y2 = y1 + 1; - - idistx = 256 - distx; - idisty = 256 - disty; - - x1 = CLIP (x1, 0, pict->width-1); - x2 = CLIP (x2, 0, pict->width-1); - y1 = CLIP (y1, 0, pict->height-1); - y2 = CLIP (y2, 0, pict->height-1); - - tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box); - tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box); - bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box); - br = fetchFromRegion(pict, x2, y2, buffer, fetch, box); - - ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; - fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; - r = (((ft * idisty + fb * disty) >> 16) & 0xff); - ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; - fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; - r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); - ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; - fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; - r |= (((ft * idisty + fb * disty)) & 0xff0000); - ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; - fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; - r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); - *(buffer + i) = r; - } - } - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } -} - -static void -fbFetchTransformed_Bilinear_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) -{ - pixman_box16_t *box = NULL; - fetchPixelProc fetch; - fetchFromRegionProc fetchFromRegion; - int i; - - /* initialize the two function pointers */ - fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); - - if(pixman_region_n_rects (pict->common.src_clip) == 1) - { - box = &(pict->common.src_clip->extents); - fetchFromRegion = fbFetchFromOneRectangle; - } - else - { - fetchFromRegion = fbFetchFromNRectangles; - } - - for (i = 0; i < width; ++i) - { - if (!mask || mask[i] & maskBits) - { - if (!v.vector[2]) { - *(buffer + i) = 0; - } else { - int x1, x2, y1, y2, distx, idistx, disty, idisty; - uint32_t tl, tr, bl, br, r; - uint32_t ft, fb; - - if (!affine) { - pixman_fixed_48_16_t div; - div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2]; - x1 = div >> 16; - distx = ((pixman_fixed_t)div >> 8) & 0xff; - div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2]; - y1 = div >> 16; - disty = ((pixman_fixed_t)div >> 8) & 0xff; - } else { - x1 = v.vector[0] >> 16; - distx = (v.vector[0] >> 8) & 0xff; - y1 = v.vector[1] >> 16; - disty = (v.vector[1] >> 8) & 0xff; - } - x2 = x1 + 1; - y2 = y1 + 1; - - idistx = 256 - distx; - idisty = 256 - disty; - - tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box); - tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box); - bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box); - br = fetchFromRegion(pict, x2, y2, buffer, fetch, box); - - ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; - fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; - r = (((ft * idisty + fb * disty) >> 16) & 0xff); - ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; - fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; - r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); - ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; - fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; - r |= (((ft * idisty + fb * disty)) & 0xff0000); - ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; - fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; - r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); - *(buffer + i) = r; - } - } - - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } -} - -static void -fbFetchTransformed_Convolution(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) -{ - pixman_box16_t dummy; - fetchPixelProc fetch; - int i; - - pixman_fixed_t *params = pict->common.filter_params; - int32_t cwidth = pixman_fixed_to_int(params[0]); - int32_t cheight = pixman_fixed_to_int(params[1]); - int xoff = (params[0] - pixman_fixed_1) >> 1; - int yoff = (params[1] - pixman_fixed_1) >> 1; - fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); - - params += 2; - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits) - { - if (!v.vector[2]) { - *(buffer + i) = 0; - } else { - int x1, x2, y1, y2, x, y; - int32_t srtot, sgtot, sbtot, satot; - pixman_fixed_t *p = params; - - if (!affine) { - pixman_fixed_48_16_t tmp; - tmp = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2] - xoff; - x1 = pixman_fixed_to_int(tmp); - tmp = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2] - yoff; - y1 = pixman_fixed_to_int(tmp); - } else { - x1 = pixman_fixed_to_int(v.vector[0] - xoff); - y1 = pixman_fixed_to_int(v.vector[1] - yoff); - } - x2 = x1 + cwidth; - y2 = y1 + cheight; - - srtot = sgtot = sbtot = satot = 0; - - for (y = y1; y < y2; y++) { - int ty; - switch (pict->common.repeat) { - case PIXMAN_REPEAT_NORMAL: - ty = MOD (y, pict->height); - break; - case PIXMAN_REPEAT_PAD: - ty = CLIP (y, 0, pict->height-1); - break; - default: - ty = y; - } - for (x = x1; x < x2; x++) { - if (*p) { - int tx; - switch (pict->common.repeat) { - case PIXMAN_REPEAT_NORMAL: - tx = MOD (x, pict->width); - break; - case PIXMAN_REPEAT_PAD: - tx = CLIP (x, 0, pict->width-1); - break; - default: - tx = x; - } - if (pixman_region_contains_point (pict->common.src_clip, tx, ty, &dummy)) { - uint32_t c = fetch(pict, tx, ty); - - srtot += Red(c) * *p; - sgtot += Green(c) * *p; - sbtot += Blue(c) * *p; - satot += Alpha(c) * *p; - } - } - p++; - } - } - - satot >>= 16; - srtot >>= 16; - sgtot >>= 16; - sbtot >>= 16; - - if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff; - if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff; - if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff; - if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff; - - *(buffer + i) = ((satot << 24) | - (srtot << 16) | - (sgtot << 8) | - (sbtot )); - } - } - v.vector[0] += unit.vector[0]; - v.vector[1] += unit.vector[1]; - v.vector[2] += unit.vector[2]; - } -} - -static void -adjust (pixman_vector_t *v, pixman_vector_t *u, pixman_fixed_t adjustment) -{ - int delta_v = (adjustment * v->vector[2]) >> 16; - int delta_u = (adjustment * u->vector[2]) >> 16; - - v->vector[0] += delta_v; - v->vector[1] += delta_v; - - u->vector[0] += delta_u; - u->vector[1] += delta_u; -} - -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; - int32_t stride; - pixman_vector_t v; - pixman_vector_t unit; - pixman_bool_t affine = TRUE; - - 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 or PIXMAN_REPEAT_PAD one might get here without a transform */ - if (pict->common.transform) - { - if (!pixman_transform_point_3d (pict->common.transform, &v)) - return; - unit.vector[0] = pict->common.transform->matrix[0][0]; - unit.vector[1] = pict->common.transform->matrix[1][0]; - unit.vector[2] = pict->common.transform->matrix[2][0]; - affine = v.vector[2] == pixman_fixed_1 && unit.vector[2] == 0; - } - else - { - unit.vector[0] = pixman_fixed_1; - unit.vector[1] = 0; - unit.vector[2] = 0; - } - - /* This allows filtering code to pretend that pixels are located at integer coordinates */ - adjust (&v, &unit, -(pixman_fixed_1 / 2)); - - if (pict->common.filter == PIXMAN_FILTER_NEAREST || pict->common.filter == PIXMAN_FILTER_FAST) - { - /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ - adjust (&v, &unit, pixman_fixed_1 / 2 - pixman_fixed_e); - - if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) - { - fbFetchTransformed_Nearest_Normal(pict, width, buffer, mask, maskBits, affine, v, unit); - - } - else if (pict->common.repeat == PIXMAN_REPEAT_PAD) - { - fbFetchTransformed_Nearest_Pad(pict, width, buffer, mask, maskBits, affine, v, unit); - } - else - { - fbFetchTransformed_Nearest_General(pict, width, buffer, mask, maskBits, affine, v, unit); - } - } else if (pict->common.filter == PIXMAN_FILTER_BILINEAR || - pict->common.filter == PIXMAN_FILTER_GOOD || - pict->common.filter == PIXMAN_FILTER_BEST) - { - if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) - { - fbFetchTransformed_Bilinear_Normal(pict, width, buffer, mask, maskBits, affine, v, unit); - } - else if (pict->common.repeat == PIXMAN_REPEAT_PAD) - { - fbFetchTransformed_Bilinear_Pad(pict, width, buffer, mask, maskBits, affine, v, unit); - } - else - { - fbFetchTransformed_Bilinear_General(pict, width, buffer, mask, maskBits, affine, v, unit); - } - } - else if (pict->common.filter == PIXMAN_FILTER_CONVOLUTION) - { - /* Round to closest integer, ensuring that 0.5 rounds to 0, not 1 */ - adjust (&v, &unit, pixman_fixed_1 / 2 - pixman_fixed_e); - - fbFetchTransformed_Convolution(pict, width, buffer, mask, maskBits, affine, v, unit); - } -} - - -static void -fbFetchExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits) -{ - int i; - uint32_t _alpha_buffer[SCANLINE_BUFFER_LENGTH]; - uint32_t *alpha_buffer = _alpha_buffer; - - if (!pict->common.alpha_map) { - fbFetchTransformed (pict, x, y, width, buffer, mask, maskBits); - return; - } - if (width > SCANLINE_BUFFER_LENGTH) - alpha_buffer = (uint32_t *) pixman_malloc_ab (width, sizeof(uint32_t)); - - fbFetchTransformed(pict, x, y, width, buffer, mask, maskBits); - fbFetchTransformed((bits_image_t *)pict->common.alpha_map, x - pict->common.alpha_origin.x, - y - pict->common.alpha_origin.y, width, alpha_buffer, - mask, maskBits); - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits) - { - int a = alpha_buffer[i]>>24; - *(buffer + i) = (a << 24) - | (div_255(Red(*(buffer + i)) * a) << 16) - | (div_255(Green(*(buffer + i)) * a) << 8) - | (div_255(Blue(*(buffer + i)) * a)); - } - } - - if (alpha_buffer != _alpha_buffer) - free(alpha_buffer); -} - static void fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer) { @@ -783,44 +165,6 @@ fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer) store((pixman_image_t *)pict, bits, buffer, x, width, indexed); } -static void -fbStoreExternalAlpha(bits_image_t * pict, int x, int y, int width, uint32_t *buffer) -{ - uint32_t *bits, *alpha_bits; - int32_t stride, astride; - int ax, ay; - storeProc store; - storeProc astore; - const pixman_indexed_t * indexed = pict->indexed; - const pixman_indexed_t * aindexed; - - if (!pict->common.alpha_map) { - fbStore(pict, x, y, width, buffer); - return; - } - - store = STORE_PROC_FOR_PICTURE(pict); - astore = STORE_PROC_FOR_PICTURE(pict->common.alpha_map); - aindexed = pict->common.alpha_map->indexed; - - ax = x; - ay = y; - - bits = pict->bits; - stride = pict->rowstride; - - alpha_bits = pict->common.alpha_map->bits; - astride = pict->common.alpha_map->rowstride; - - bits += y*stride; - alpha_bits += (ay - pict->common.alpha_origin.y)*astride; - - - store((pixman_image_t *)pict, bits, buffer, x, width, indexed); - astore((pixman_image_t *)pict->common.alpha_map, - alpha_bits, buffer, ax - pict->common.alpha_origin.x, width, aindexed); -} - typedef void (*scanStoreProc)(pixman_image_t *, int, int, int, uint32_t *); typedef void (*scanFetchProc)(pixman_image_t *, int, int, int, uint32_t *, uint32_t *, uint32_t); @@ -858,7 +202,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, if (bits->common.alpha_map) { - fetchSrc = (scanFetchProc)fbFetchExternalAlpha; + fetchSrc = (scanFetchProc)FB_FETCH_EXTERNAL_ALPHA; } else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) && bits->width == 1 && @@ -874,7 +218,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, } else { - fetchSrc = (scanFetchProc)fbFetchTransformed; + fetchSrc = (scanFetchProc)FB_FETCH_TRANSFORMED; } } @@ -897,7 +241,7 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, if (bits->common.alpha_map) { - fetchMask = (scanFetchProc)fbFetchExternalAlpha; + fetchMask = (scanFetchProc)FB_FETCH_EXTERNAL_ALPHA; } else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) && bits->width == 1 && bits->height == 1) @@ -909,14 +253,14 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, && bits->common.repeat != PIXMAN_REPEAT_PAD) fetchMask = (scanFetchProc)fbFetch; else - fetchMask = (scanFetchProc)fbFetchTransformed; + fetchMask = (scanFetchProc)FB_FETCH_TRANSFORMED; } } if (data->dest->common.alpha_map) { - fetchDest = (scanFetchProc)fbFetchExternalAlpha; - store = (scanStoreProc)fbStoreExternalAlpha; + fetchDest = (scanFetchProc)FB_FETCH_EXTERNAL_ALPHA; + store = (scanStoreProc)FB_STORE_EXTERNAL_ALPHA; if (data->op == PIXMAN_OP_CLEAR || data->op == PIXMAN_OP_SRC) fetchDest = NULL; diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 3d67572..5767c10 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -191,6 +191,22 @@ storeProc pixman_storeProcForPicture_accessors (bits_image_t *); void pixmanFetchSourcePict(source_image_t *, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits); +void fbFetchTransformed(bits_image_t *, int x, int y, int width, + uint32_t *buffer, uint32_t *mask, uint32_t maskBits); +void fbStoreExternalAlpha(bits_image_t *, int x, int y, int width, + uint32_t *buffer); +void fbFetchExternalAlpha(bits_image_t *, int x, int y, int width, + uint32_t *buffer, uint32_t *mask, uint32_t maskBits); + +void fbFetchTransformed_accessors(bits_image_t *, int x, int y, int width, + uint32_t *buffer, uint32_t *mask, + uint32_t maskBits); +void fbStoreExternalAlpha_accessors(bits_image_t *, int x, int y, int width, + uint32_t *buffer); +void fbFetchExternalAlpha_accessors(bits_image_t *, int x, int y, int width, + uint32_t *buffer, uint32_t *mask, + uint32_t maskBits); + /* end */ typedef enum diff --git a/pixman/pixman-transformed-accessors.c b/pixman/pixman-transformed-accessors.c new file mode 100644 index 0000000..442ca24 --- /dev/null +++ b/pixman/pixman-transformed-accessors.c @@ -0,0 +1,3 @@ +#define PIXMAN_FB_ACCESSORS + +#include "pixman-transformed.c" diff --git a/pixman/pixman-transformed.c b/pixman/pixman-transformed.c new file mode 100644 index 0000000..19085ca --- /dev/null +++ b/pixman/pixman-transformed.c @@ -0,0 +1,726 @@ +/* + * + * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. + * 2005 Lars Knoll & Zack Rusin, Trolltech + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "pixman-private.h" + +#ifdef PIXMAN_FB_ACCESSORS +#define FETCH_PROC_FOR_PICTURE pixman_fetchProcForPicture_accessors +#define FETCH_PIXEL_PROC_FOR_PICTURE pixman_fetchPixelProcForPicture_accessors +#define STORE_PROC_FOR_PICTURE pixman_storeProcForPicture_accessors + +#define FB_FETCH_TRANSFORMED fbFetchTransformed_accessors +#define FB_FETCH_EXTERNAL_ALPHA fbFetchExternalAlpha_accessors +#define FB_STORE_EXTERNAL_ALPHA fbStoreExternalAlpha_accessors + +#else + +#define FETCH_PROC_FOR_PICTURE pixman_fetchProcForPicture +#define FETCH_PIXEL_PROC_FOR_PICTURE pixman_fetchPixelProcForPicture +#define STORE_PROC_FOR_PICTURE pixman_storeProcForPicture + +#define FB_FETCH_TRANSFORMED fbFetchTransformed +#define FB_FETCH_EXTERNAL_ALPHA fbFetchExternalAlpha +#define FB_STORE_EXTERNAL_ALPHA fbStoreExternalAlpha + +#endif + +/* + * Fetch from region strategies + */ +typedef FASTCALL uint32_t (*fetchFromRegionProc)(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box); + +static inline uint32_t +fbFetchFromNoRegion(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box) +{ + return fetch (pict, x, y); +} + +static uint32_t +fbFetchFromNRectangles(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box) +{ + pixman_box16_t box2; + if (pixman_region_contains_point (pict->common.src_clip, x, y, &box2)) + return fbFetchFromNoRegion(pict, x, y, buffer, fetch, box); + else + return 0; +} + +static uint32_t +fbFetchFromOneRectangle(bits_image_t *pict, int x, int y, uint32_t *buffer, fetchPixelProc fetch, pixman_box16_t *box) +{ + pixman_box16_t box2 = *box; + return ((x < box2.x1) | (x >= box2.x2) | (y < box2.y1) | (y >= box2.y2)) ? + 0 : fbFetchFromNoRegion(pict, x, y, buffer, fetch, box); +} + +/* + * Fetching Algorithms + */ +static void +fbFetchTransformed_Nearest_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) +{ + pixman_box16_t* box = NULL; + fetchPixelProc fetch; + fetchFromRegionProc fetchFromRegion; + int x, y, i; + + /* initialize the two function pointers */ + fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); + + if(pixman_region_n_rects (pict->common.src_clip) == 1) + fetchFromRegion = fbFetchFromNoRegion; + else + fetchFromRegion = fbFetchFromNRectangles; + + 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) = fetchFromRegion(pict, x, y, buffer, fetch, box); + } + } + + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } +} + +static void +fbFetchTransformed_Nearest_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) +{ + pixman_box16_t *box = NULL; + fetchPixelProc fetch; + fetchFromRegionProc fetchFromRegion; + int x, y, i; + + /* initialize the two function pointers */ + fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); + + if(pixman_region_n_rects (pict->common.src_clip) == 1) + fetchFromRegion = fbFetchFromNoRegion; + else + fetchFromRegion = fbFetchFromNRectangles; + + for (i = 0; i < width; ++i) + { + if (!mask || mask[i] & maskBits) + { + if (!v.vector[2]) + { + *(buffer + i) = 0; + } + else + { + if (!affine) + { + y = CLIP(DIV(v.vector[1], v.vector[2]), 0, pict->height-1); + x = CLIP(DIV(v.vector[0], v.vector[2]), 0, pict->width-1); + } + else + { + y = CLIP(v.vector[1]>>16, 0, pict->height-1); + x = CLIP(v.vector[0]>>16, 0, pict->width-1); + } + + *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box); + } + } + + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } +} + +static void +fbFetchTransformed_Nearest_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) +{ + pixman_box16_t *box = NULL; + fetchPixelProc fetch; + fetchFromRegionProc fetchFromRegion; + int x, y, i; + + /* initialize the two function pointers */ + fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); + + if(pixman_region_n_rects (pict->common.src_clip) == 1) + { + box = &(pict->common.src_clip->extents); + fetchFromRegion = fbFetchFromOneRectangle; + } + else + { + fetchFromRegion = fbFetchFromNRectangles; + } + + for (i = 0; i < width; ++i) { + if (!mask || mask[i] & maskBits) + { + if (!v.vector[2]) { + *(buffer + i) = 0; + } else { + if (!affine) { + y = DIV(v.vector[1],v.vector[2]); + x = DIV(v.vector[0],v.vector[2]); + } else { + y = v.vector[1]>>16; + x = v.vector[0]>>16; + } + *(buffer + i) = fetchFromRegion(pict, x, y, buffer, fetch, box); + } + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } +} + +static void +fbFetchTransformed_Bilinear_Normal(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) +{ + pixman_box16_t *box = NULL; + fetchPixelProc fetch; + fetchFromRegionProc fetchFromRegion; + int i; + + /* initialize the two function pointers */ + fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); + + if(pixman_region_n_rects (pict->common.src_clip) == 1) + fetchFromRegion = fbFetchFromNoRegion; + else + fetchFromRegion = fbFetchFromNRectangles; + + for (i = 0; i < width; ++i) { + if (!mask || mask[i] & maskBits) + { + if (!v.vector[2]) { + *(buffer + i) = 0; + } else { + int x1, x2, y1, y2, distx, idistx, disty, idisty; + uint32_t tl, tr, bl, br, r; + uint32_t ft, fb; + + if (!affine) { + pixman_fixed_48_16_t div; + div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((pixman_fixed_t)div >> 8) & 0xff; + div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + disty = ((pixman_fixed_t)div >> 8) & 0xff; + } else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } + x2 = x1 + 1; + y2 = y1 + 1; + + idistx = 256 - distx; + idisty = 256 - disty; + + x1 = MOD (x1, pict->width); + x2 = MOD (x2, pict->width); + y1 = MOD (y1, pict->height); + y2 = MOD (y2, pict->height); + + tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box); + tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box); + bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box); + br = fetchFromRegion(pict, x2, y2, buffer, fetch, box); + + ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; + fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; + fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; + fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; + fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); + *(buffer + i) = r; + } + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } +} + +static void +fbFetchTransformed_Bilinear_Pad(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) +{ + pixman_box16_t *box = NULL; + fetchPixelProc fetch; + fetchFromRegionProc fetchFromRegion; + int i; + + /* initialize the two function pointers */ + fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); + + if(pixman_region_n_rects (pict->common.src_clip) == 1) + fetchFromRegion = fbFetchFromNoRegion; + else + fetchFromRegion = fbFetchFromNRectangles; + + for (i = 0; i < width; ++i) { + if (!mask || mask[i] & maskBits) + { + if (!v.vector[2]) { + *(buffer + i) = 0; + } else { + int x1, x2, y1, y2, distx, idistx, disty, idisty; + uint32_t tl, tr, bl, br, r; + uint32_t ft, fb; + + if (!affine) { + pixman_fixed_48_16_t div; + div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((pixman_fixed_t)div >> 8) & 0xff; + div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + disty = ((pixman_fixed_t)div >> 8) & 0xff; + } else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } + x2 = x1 + 1; + y2 = y1 + 1; + + idistx = 256 - distx; + idisty = 256 - disty; + + x1 = CLIP (x1, 0, pict->width-1); + x2 = CLIP (x2, 0, pict->width-1); + y1 = CLIP (y1, 0, pict->height-1); + y2 = CLIP (y2, 0, pict->height-1); + + tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box); + tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box); + bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box); + br = fetchFromRegion(pict, x2, y2, buffer, fetch, box); + + ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; + fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; + fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; + fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; + fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); + *(buffer + i) = r; + } + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } +} + +static void +fbFetchTransformed_Bilinear_General(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) +{ + pixman_box16_t *box = NULL; + fetchPixelProc fetch; + fetchFromRegionProc fetchFromRegion; + int i; + + /* initialize the two function pointers */ + fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); + + if(pixman_region_n_rects (pict->common.src_clip) == 1) + { + box = &(pict->common.src_clip->extents); + fetchFromRegion = fbFetchFromOneRectangle; + } + else + { + fetchFromRegion = fbFetchFromNRectangles; + } + + for (i = 0; i < width; ++i) + { + if (!mask || mask[i] & maskBits) + { + if (!v.vector[2]) { + *(buffer + i) = 0; + } else { + int x1, x2, y1, y2, distx, idistx, disty, idisty; + uint32_t tl, tr, bl, br, r; + uint32_t ft, fb; + + if (!affine) { + pixman_fixed_48_16_t div; + div = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((pixman_fixed_t)div >> 8) & 0xff; + div = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + disty = ((pixman_fixed_t)div >> 8) & 0xff; + } else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } + x2 = x1 + 1; + y2 = y1 + 1; + + idistx = 256 - distx; + idisty = 256 - disty; + + tl = fetchFromRegion(pict, x1, y1, buffer, fetch, box); + tr = fetchFromRegion(pict, x2, y1, buffer, fetch, box); + bl = fetchFromRegion(pict, x1, y2, buffer, fetch, box); + br = fetchFromRegion(pict, x2, y2, buffer, fetch, box); + + ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; + fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; + fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; + fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; + fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); + *(buffer + i) = r; + } + } + + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } +} + +static void +fbFetchTransformed_Convolution(bits_image_t * pict, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits, pixman_bool_t affine, pixman_vector_t v, pixman_vector_t unit) +{ + pixman_box16_t dummy; + fetchPixelProc fetch; + int i; + + pixman_fixed_t *params = pict->common.filter_params; + int32_t cwidth = pixman_fixed_to_int(params[0]); + int32_t cheight = pixman_fixed_to_int(params[1]); + int xoff = (params[0] - pixman_fixed_1) >> 1; + int yoff = (params[1] - pixman_fixed_1) >> 1; + fetch = FETCH_PIXEL_PROC_FOR_PICTURE(pict); + + params += 2; + for (i = 0; i < width; ++i) { + if (!mask || mask[i] & maskBits) + { + if (!v.vector[2]) { + *(buffer + i) = 0; + } else { + int x1, x2, y1, y2, x, y; + int32_t srtot, sgtot, sbtot, satot; + pixman_fixed_t *p = params; + + if (!affine) { + pixman_fixed_48_16_t tmp; + tmp = ((pixman_fixed_48_16_t)v.vector[0] << 16)/v.vector[2] - xoff; + x1 = pixman_fixed_to_int(tmp); + tmp = ((pixman_fixed_48_16_t)v.vector[1] << 16)/v.vector[2] - yoff; + y1 = pixman_fixed_to_int(tmp); + } else { + x1 = pixman_fixed_to_int(v.vector[0] - xoff); + y1 = pixman_fixed_to_int(v.vector[1] - yoff); + } + x2 = x1 + cwidth; + y2 = y1 + cheight; + + srtot = sgtot = sbtot = satot = 0; + + for (y = y1; y < y2; y++) { + int ty; + switch (pict->common.repeat) { + case PIXMAN_REPEAT_NORMAL: + ty = MOD (y, pict->height); + break; + case PIXMAN_REPEAT_PAD: + ty = CLIP (y, 0, pict->height-1); + break; + default: + ty = y; + } + for (x = x1; x < x2; x++) { + if (*p) { + int tx; + switch (pict->common.repeat) { + case PIXMAN_REPEAT_NORMAL: + tx = MOD (x, pict->width); + break; + case PIXMAN_REPEAT_PAD: + tx = CLIP (x, 0, pict->width-1); + break; + default: + tx = x; + } + if (pixman_region_contains_point (pict->common.src_clip, tx, ty, &dummy)) { + uint32_t c = fetch(pict, tx, ty); + + srtot += Red(c) * *p; + sgtot += Green(c) * *p; + sbtot += Blue(c) * *p; + satot += Alpha(c) * *p; + } + } + p++; + } + } + + satot >>= 16; + srtot >>= 16; + sgtot >>= 16; + sbtot >>= 16; + + if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff; + if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff; + if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff; + if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff; + + *(buffer + i) = ((satot << 24) | + (srtot << 16) | + (sgtot << 8) | + (sbtot )); + } + } + v.vector[0] += unit.vector[0]; + v.vector[1] += unit.vector[1]; + v.vector[2] += unit.vector[2]; + } +} + +static void +adjust (pixman_vector_t *v, pixman_vector_t *u, pixman_fixed_t adjustment) +{ + int delta_v = (adjustment * v->vector[2]) >> 16; + int delta_u = (adjustment * u->vector[2]) >> 16; + + v->vector[0] += delta_v; + v->vector[1] += delta_v; + + u->vector[0] += delta_u; + u->vector[1] += delta_u; +} + +void +FB_FETCH_TRANSFORMED(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits) +{ + uint32_t *bits; + int32_t stride; + pixman_vector_t v; + pixman_vector_t unit; + pixman_bool_t affine = TRUE; + + 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 or PIXMAN_REPEAT_PAD one might get here without a transform */ + if (pict->common.transform) + { + if (!pixman_transform_point_3d (pict->common.transform, &v)) + return; + unit.vector[0] = pict->common.transform->matrix[0][0]; + unit.vector[1] = pict->common.transform->matrix[1][0]; + unit.vector[2] = pict->common.transform->matrix[2][0]; + affine = v.vector[2] == pixman_fixed_1 && unit.vector[2] == 0; + } + else + { + unit.vector[0] = pixman_fixed_1; + unit.vector[1] = 0; + unit.vector[2] = 0; + } + + /* This allows filtering code to pretend that pixels are located at integer coordinates */ + adjust (&v, &unit, -(pixman_fixed_1 / 2)); + + if (pict->common.filter == PIXMAN_FILTER_NEAREST || pict->common.filter == PIXMAN_FILTER_FAST) + { + /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ + adjust (&v, &unit, pixman_fixed_1 / 2 - pixman_fixed_e); + + if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) + { + fbFetchTransformed_Nearest_Normal(pict, width, buffer, mask, maskBits, affine, v, unit); + + } + else if (pict->common.repeat == PIXMAN_REPEAT_PAD) + { + fbFetchTransformed_Nearest_Pad(pict, width, buffer, mask, maskBits, affine, v, unit); + } + else + { + fbFetchTransformed_Nearest_General(pict, width, buffer, mask, maskBits, affine, v, unit); + } + } else if (pict->common.filter == PIXMAN_FILTER_BILINEAR || + pict->common.filter == PIXMAN_FILTER_GOOD || + pict->common.filter == PIXMAN_FILTER_BEST) + { + if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) + { + fbFetchTransformed_Bilinear_Normal(pict, width, buffer, mask, maskBits, affine, v, unit); + } + else if (pict->common.repeat == PIXMAN_REPEAT_PAD) + { + fbFetchTransformed_Bilinear_Pad(pict, width, buffer, mask, maskBits, affine, v, unit); + } + else + { + fbFetchTransformed_Bilinear_General(pict, width, buffer, mask, maskBits, affine, v, unit); + } + } + else if (pict->common.filter == PIXMAN_FILTER_CONVOLUTION) + { + /* Round to closest integer, ensuring that 0.5 rounds to 0, not 1 */ + adjust (&v, &unit, pixman_fixed_1 / 2 - pixman_fixed_e); + + fbFetchTransformed_Convolution(pict, width, buffer, mask, maskBits, affine, v, unit); + } +} + +#define SCANLINE_BUFFER_LENGTH 2048 + +void +FB_FETCH_EXTERNAL_ALPHA(bits_image_t * pict, int x, int y, int width, + uint32_t *buffer, uint32_t *mask, uint32_t maskBits) +{ + int i; + uint32_t _alpha_buffer[SCANLINE_BUFFER_LENGTH]; + uint32_t *alpha_buffer = _alpha_buffer; + + if (!pict->common.alpha_map) { + FB_FETCH_TRANSFORMED (pict, x, y, width, buffer, mask, maskBits); + return; + } + if (width > SCANLINE_BUFFER_LENGTH) + alpha_buffer = (uint32_t *) pixman_malloc_ab (width, sizeof(uint32_t)); + + FB_FETCH_TRANSFORMED(pict, x, y, width, buffer, mask, maskBits); + FB_FETCH_TRANSFORMED((bits_image_t *)pict->common.alpha_map, x - pict->common.alpha_origin.x, + y - pict->common.alpha_origin.y, width, alpha_buffer, + mask, maskBits); + for (i = 0; i < width; ++i) { + if (!mask || mask[i] & maskBits) + { + int a = alpha_buffer[i]>>24; + *(buffer + i) = (a << 24) + | (div_255(Red(*(buffer + i)) * a) << 16) + | (div_255(Green(*(buffer + i)) * a) << 8) + | (div_255(Blue(*(buffer + i)) * a)); + } + } + + if (alpha_buffer != _alpha_buffer) + free(alpha_buffer); +} + +void +FB_STORE_EXTERNAL_ALPHA(bits_image_t * pict, int x, int y, int width, + uint32_t *buffer) +{ + uint32_t *bits, *alpha_bits; + int32_t stride, astride; + int ax, ay; + storeProc store; + storeProc astore; + const pixman_indexed_t * indexed = pict->indexed; + const pixman_indexed_t * aindexed; + + if (!pict->common.alpha_map) { + // XXX[AGP]: This should never happen! + // fbStore(pict, x, y, width, buffer); + abort(); + return; + } + + store = STORE_PROC_FOR_PICTURE(pict); + astore = STORE_PROC_FOR_PICTURE(pict->common.alpha_map); + aindexed = pict->common.alpha_map->indexed; + + ax = x; + ay = y; + + bits = pict->bits; + stride = pict->rowstride; + + alpha_bits = pict->common.alpha_map->bits; + astride = pict->common.alpha_map->rowstride; + + bits += y*stride; + alpha_bits += (ay - pict->common.alpha_origin.y)*astride; + + + store((pixman_image_t *)pict, bits, buffer, x, width, indexed); + astore((pixman_image_t *)pict->common.alpha_map, + alpha_bits, buffer, ax - pict->common.alpha_origin.x, width, aindexed); +} + -- 2.7.4