From 8267d8d38f794c51e09f440c470f1c23c59e11aa Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Sandmann=20Pedersen?= Date: Sat, 2 May 2009 23:26:30 -0400 Subject: [PATCH] Add a generic 64 bit fetcher and use it for gradients and transformed images --- pixman/pixman-bits-image.c | 4 +-- pixman/pixman-compose.c | 2 +- pixman/pixman-conical-gradient.c | 2 +- pixman/pixman-image.c | 32 ++++++++++++++++++++ pixman/pixman-linear-gradient.c | 2 +- pixman/pixman-private.h | 15 ++-------- pixman/pixman-radial-gradient.c | 2 +- pixman/pixman-solid-fill.c | 2 +- pixman/pixman-source.c | 27 ----------------- pixman/pixman-transformed.c | 63 ---------------------------------------- 10 files changed, 41 insertions(+), 110 deletions(-) diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 1437406..2dcf34b 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -90,7 +90,7 @@ bits_image_property_changed (pixman_image_t *image) if (bits->common.alpha_map) { image->common.get_scanline_64 = - (scanFetchProc)READ_ACCESS(fbFetchExternalAlpha64); + (scanFetchProc)_pixman_image_get_scanline_64_generic; image->common.get_scanline_32 = (scanFetchProc)READ_ACCESS(fbFetchExternalAlpha); } @@ -112,7 +112,7 @@ bits_image_property_changed (pixman_image_t *image) else { image->common.get_scanline_64 = - (scanFetchProc)READ_ACCESS(fbFetchTransformed64); + (scanFetchProc)_pixman_image_get_scanline_64_generic; image->common.get_scanline_32 = (scanFetchProc)READ_ACCESS(fbFetchTransformed); } diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c index d13d87c..23bfe5d 100644 --- a/pixman/pixman-compose.c +++ b/pixman/pixman-compose.c @@ -216,7 +216,7 @@ pixman_composite_rect_general (const FbComposeData *data) const int Bpp = wide ? 8 : 4; uint8_t *scanline_buffer = stack_scanline_buffer; uint8_t *src_buffer, *mask_buffer, *dest_buffer; - + if (data->width * Bpp > SCANLINE_BUFFER_LENGTH) { scanline_buffer = pixman_malloc_abc (data->width, 3, Bpp); diff --git a/pixman/pixman-conical-gradient.c b/pixman/pixman-conical-gradient.c index cd8d36c..d5c4e23 100644 --- a/pixman/pixman-conical-gradient.c +++ b/pixman/pixman-conical-gradient.c @@ -27,8 +27,8 @@ static void conical_gradient_property_changed (pixman_image_t *image) { - image->common.get_scanline_64 = (scanFetchProc)pixmanFetchSourcePict64; image->common.get_scanline_32 = (scanFetchProc)pixmanFetchSourcePict; + image->common.get_scanline_64 = (scanFetchProc)_pixman_image_get_scanline_64_generic; } PIXMAN_EXPORT pixman_image_t * diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 0553a5a..9d62f4a 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -56,6 +56,38 @@ _pixman_init_gradient (gradient_t *gradient, return TRUE; } +/* + * By default, just evaluate the image at 32bpp and expand. Individual image + * types can plug in a better scanline getter if they want to. For example + * we could produce smoother gradients by evaluating them at higher color depth, but + * that's a project for the future. + */ +void +_pixman_image_get_scanline_64_generic (pixman_image_t * pict, int x, int y, int width, + uint64_t *buffer, uint64_t *mask, uint32_t maskBits) +{ + uint32_t *mask8 = NULL; + + // Contract the mask image, if one exists, so that the 32-bit fetch function + // can use it. + if (mask) { + mask8 = pixman_malloc_ab(width, sizeof(uint32_t)); + if (!mask8) + return; + + pixman_contract(mask8, mask, width); + } + + // Fetch the source image into the first half of buffer. + _pixman_image_get_scanline_32 (pict, x, y, width, (uint32_t*)buffer, mask8, + maskBits); + + // Expand from 32bpp to 64bpp in place. + pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width); + + free(mask8); +} + pixman_image_t * _pixman_image_allocate (void) { diff --git a/pixman/pixman-linear-gradient.c b/pixman/pixman-linear-gradient.c index 46217a0..c6c662a 100644 --- a/pixman/pixman-linear-gradient.c +++ b/pixman/pixman-linear-gradient.c @@ -86,8 +86,8 @@ linear_gradient_classify (pixman_image_t *image, static void linear_gradient_property_changed (pixman_image_t *image) { - image->common.get_scanline_64 = (scanFetchProc)pixmanFetchSourcePict64; image->common.get_scanline_32 = (scanFetchProc)pixmanFetchSourcePict; + image->common.get_scanline_64 = (scanFetchProc)_pixman_image_get_scanline_64_generic; } PIXMAN_EXPORT pixman_image_t * diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index fedbbb3..ff1bfa6 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -222,9 +222,8 @@ void pixman_contract(uint32_t *dst, const uint64_t *src, int width); void pixmanFetchSourcePict(source_image_t *, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits); -void pixmanFetchSourcePict64(source_image_t *, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, uint32_t maskBits); - +void _pixman_image_get_scanline_64_generic (pixman_image_t * pict, int x, int y, int width, + uint64_t *buffer, uint64_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, @@ -241,21 +240,11 @@ void fbFetchExternalAlpha_accessors(bits_image_t *, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits); -void fbFetchTransformed64(bits_image_t *, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, uint32_t maskBits); void fbStoreExternalAlpha64(bits_image_t *, int x, int y, int width, uint64_t *buffer); -void fbFetchExternalAlpha64(bits_image_t *, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, uint32_t maskBits); -void fbFetchTransformed64_accessors(bits_image_t *, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, - uint32_t maskBits); void fbStoreExternalAlpha64_accessors(bits_image_t *, int x, int y, int width, uint64_t *buffer); -void fbFetchExternalAlpha64_accessors(bits_image_t *, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, - uint32_t maskBits); /* end */ diff --git a/pixman/pixman-radial-gradient.c b/pixman/pixman-radial-gradient.c index 62f8f27..e05299c 100644 --- a/pixman/pixman-radial-gradient.c +++ b/pixman/pixman-radial-gradient.c @@ -27,8 +27,8 @@ static void radial_gradient_property_changed (pixman_image_t *image) { - image->common.get_scanline_64 = (scanFetchProc)pixmanFetchSourcePict64; image->common.get_scanline_32 = (scanFetchProc)pixmanFetchSourcePict; + image->common.get_scanline_64 = (scanFetchProc)_pixman_image_get_scanline_64_generic; } PIXMAN_EXPORT pixman_image_t * diff --git a/pixman/pixman-solid-fill.c b/pixman/pixman-solid-fill.c index b6e8ebb..af383b5 100644 --- a/pixman/pixman-solid-fill.c +++ b/pixman/pixman-solid-fill.c @@ -37,8 +37,8 @@ solid_fill_classify (pixman_image_t *image, static void solid_fill_property_changed (pixman_image_t *image) { - image->common.get_scanline_64 = (scanFetchProc)pixmanFetchSourcePict64; image->common.get_scanline_32 = (scanFetchProc)pixmanFetchSourcePict; + image->common.get_scanline_64 = (scanFetchProc)_pixman_image_get_scanline_64_generic; } static uint32_t diff --git a/pixman/pixman-source.c b/pixman/pixman-source.c index c405f49..0b2569e 100644 --- a/pixman/pixman-source.c +++ b/pixman/pixman-source.c @@ -458,30 +458,3 @@ void pixmanFetchSourcePict(source_image_t * pict, int x, int y, int width, } } } - -/* - * For now, just evaluate the source picture at 32bpp and expand. We could - * produce smoother gradients by evaluating them at higher color depth, but - * that's a project for the future. - */ -void pixmanFetchSourcePict64(source_image_t * pict, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, uint32_t maskBits) -{ - uint32_t *mask8 = NULL; - - // Contract the mask image, if one exists, so that the 32-bit fetch function - // can use it. - if (mask) { - mask8 = pixman_malloc_ab(width, sizeof(uint32_t)); - pixman_contract(mask8, mask, width); - } - - // Fetch the source image into the first half of buffer. - pixmanFetchSourcePict(pict, x, y, width, (uint32_t*)buffer, mask8, - maskBits); - - // Expand from 32bpp to 64bpp in place. - pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width); - - free(mask8); -} diff --git a/pixman/pixman-transformed.c b/pixman/pixman-transformed.c index 6d695c5..997d24e 100644 --- a/pixman/pixman-transformed.c +++ b/pixman/pixman-transformed.c @@ -472,30 +472,6 @@ ACCESS(fbFetchTransformed)(bits_image_t * pict, int x, int y, int width, } } -void -ACCESS(fbFetchTransformed64)(bits_image_t * pict, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, uint32_t maskBits) -{ - // TODO: Don't lose precision for wide pictures! - uint32_t *mask8 = NULL; - - // Contract the mask image, if one exists, so that the 32-bit fetch function - // can use it. - if (mask) { - mask8 = pixman_malloc_ab(width, sizeof(uint32_t)); - pixman_contract(mask8, mask, width); - } - - // Fetch the image into the first half of buffer. - ACCESS(fbFetchTransformed)(pict, x, y, width, (uint32_t*)buffer, mask8, - maskBits); - - // Expand from 32bpp to 64bpp in place. - pixman_expand(buffer, (uint32_t*)buffer, PIXMAN_a8r8g8b8, width); - - free(mask8); -} - #define SCANLINE_BUFFER_LENGTH 2048 void @@ -534,45 +510,6 @@ ACCESS(fbFetchExternalAlpha)(bits_image_t * pict, int x, int y, int width, } void -ACCESS(fbFetchExternalAlpha64)(bits_image_t * pict, int x, int y, int width, - uint64_t *buffer, uint64_t *mask, - uint32_t maskBits) -{ - int i; - uint64_t _alpha_buffer[SCANLINE_BUFFER_LENGTH]; - uint64_t *alpha_buffer = _alpha_buffer; - uint64_t maskBits64; - - if (!pict->common.alpha_map) { - ACCESS(fbFetchTransformed64) (pict, x, y, width, buffer, mask, maskBits); - return; - } - if (width > SCANLINE_BUFFER_LENGTH) - alpha_buffer = (uint64_t *) pixman_malloc_ab (width, sizeof(uint64_t)); - - ACCESS(fbFetchTransformed64)(pict, x, y, width, buffer, mask, maskBits); - ACCESS(fbFetchTransformed64)((bits_image_t *)pict->common.alpha_map, x - pict->common.alpha_origin.x, - y - pict->common.alpha_origin.y, width, - alpha_buffer, mask, maskBits); - - pixman_expand(&maskBits64, &maskBits, PIXMAN_a8r8g8b8, 1); - - for (i = 0; i < width; ++i) { - if (!mask || mask[i] & maskBits64) - { - int64_t a = alpha_buffer[i]>>48; - *(buffer + i) = (a << 48) - | (div_65535(Red64(*(buffer + i)) * a) << 32) - | (div_65535(Green64(*(buffer + i)) * a) << 16) - | (div_65535(Blue64(*(buffer + i)) * a)); - } - } - - if (alpha_buffer != _alpha_buffer) - free(alpha_buffer); -} - -void ACCESS(fbStoreExternalAlpha)(bits_image_t * pict, int x, int y, int width, uint32_t *buffer) { -- 2.7.4