| /* |
| * |
| * 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 <config.h> |
| #endif |
| |
| #include <stdlib.h> |
| |
| #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); |
| } |
| |