From 42a3a2d6fc8d3e521c6914ff8fb89f1fbc673e28 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Fri, 6 Jun 2008 15:45:17 -0700 Subject: [PATCH] Add wide fetch/store functions. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Use the narrow ones and expand/contract where necessary. Still need wide paths for fancy pictures, but this gets the basic stuff working. Signed-off-by: Søren Sandmann Pedersen --- pixman/pixman-access.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++ pixman/pixman-compose.c | 58 ++++++++++++-- pixman/pixman-utils.c | 2 + pixman/pixman.h | 4 +- 4 files changed, 254 insertions(+), 8 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 5609421..d5d3952 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -2,6 +2,7 @@ * * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. * 2005 Lars Knoll & Zack Rusin, Trolltech + * 2008 Aaron Plattner, NVIDIA Corporation * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -27,7 +28,9 @@ #include #endif +#include #include +#include #include "pixman-private.h" @@ -117,6 +120,52 @@ fbFetch_x8b8g8r8 (bits_image_t *pict, int x, int y, int width, uint32_t *buffer) } static FASTCALL void +fbFetch_a2b10g10r10 (bits_image_t *pict, int x, int y, int width, uint64_t *buffer) +{ + const uint32_t *bits = pict->bits + y*pict->rowstride; + const uint32_t *pixel = bits + x; + const uint32_t *end = pixel + width; + while (pixel < end) { + uint32_t p = READ(pict, pixel++); + uint64_t a = p >> 30; + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + a <<= 62; + a |= a >> 2; + a |= a >> 4; + a |= a >> 8; + + *buffer++ = a << 48 | r << 32 | g << 16 | b; + } +} + +static FASTCALL void +fbFetch_x2b10g10r10 (bits_image_t *pict, int x, int y, int width, uint64_t *buffer) +{ + const uint32_t *bits = pict->bits + y*pict->rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + while (pixel < end) { + uint32_t p = READ(pict, pixel++); + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + *buffer++ = 0xffffULL << 48 | r << 32 | g << 16 | b; + } +} + +static FASTCALL void fbFetch_r8g8b8 (bits_image_t *pict, int x, int y, int width, uint32_t *buffer) { const uint32_t *bits = pict->bits + y*pict->rowstride; @@ -644,6 +693,9 @@ fetchProc32 ACCESS(pixman_fetchProcForPicture32) (bits_image_t * pict) case PIXMAN_x8r8g8b8: return fbFetch_x8r8g8b8; case PIXMAN_a8b8g8r8: return fbFetch_a8b8g8r8; case PIXMAN_x8b8g8r8: return fbFetch_x8b8g8r8; + /* These two require wide compositing */ + case PIXMAN_a2b10g10r10: return NULL; + case PIXMAN_x2b10g10r10: return NULL; /* 24bpp formats */ case PIXMAN_r8g8b8: return fbFetch_r8g8b8; @@ -693,8 +745,66 @@ fetchProc32 ACCESS(pixman_fetchProcForPicture32) (bits_image_t * pict) return NULL; } +static FASTCALL void +fbFetch64_generic (bits_image_t *pict, int x, int y, int width, uint64_t *buffer) +{ + fetchProc32 fetch32 = ACCESS(pixman_fetchProcForPicture32) (pict); + + // Fetch the pixels into the first half of buffer and then expand them in + // place. + fetch32(pict, x, y, width, (uint32_t*)buffer); + pixman_expand(buffer, (uint32_t*)buffer, pict->format, width); +} + +fetchProc64 ACCESS(pixman_fetchProcForPicture64) (bits_image_t * pict) +{ + switch(pict->format) { + case PIXMAN_a2b10g10r10: return fbFetch_a2b10g10r10; + case PIXMAN_x2b10g10r10: return fbFetch_x2b10g10r10; + default: return fbFetch64_generic; + } +} + /**************************** Pixel wise fetching *****************************/ +static FASTCALL uint64_t +fbFetchPixel_a2b10g10r10 (bits_image_t *pict, int offset, int line) +{ + uint32_t *bits = pict->bits + line*pict->rowstride; + uint32_t p = READ(pict, bits + offset); + uint64_t a = p >> 30; + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + a <<= 62; + a |= a >> 2; + a |= a >> 4; + a |= a >> 8; + + return a << 48 | r << 32 | g << 16 | b; +} + +static FASTCALL uint64_t +fbFetchPixel_x2b10g10r10 (bits_image_t *pict, int offset, int line) +{ + uint32_t *bits = pict->bits + line*pict->rowstride; + uint32_t p = READ(pict, bits + offset); + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + r = r << 6 | r >> 4; + g = g << 6 | g >> 4; + b = b << 6 | b >> 4; + + return 0xffffULL << 48 | r << 32 | g << 16 | b; +} + static FASTCALL uint32_t fbFetchPixel_a8r8g8b8 (bits_image_t *pict, int offset, int line) { @@ -1155,6 +1265,9 @@ fetchPixelProc32 ACCESS(pixman_fetchPixelProcForPicture32) (bits_image_t * pict) case PIXMAN_x8r8g8b8: return fbFetchPixel_x8r8g8b8; case PIXMAN_a8b8g8r8: return fbFetchPixel_a8b8g8r8; case PIXMAN_x8b8g8r8: return fbFetchPixel_x8b8g8r8; + /* These two require wide compositing */ + case PIXMAN_a2b10g10r10: return NULL; + case PIXMAN_x2b10g10r10: return NULL; /* 24bpp formats */ case PIXMAN_r8g8b8: return fbFetchPixel_r8g8b8; @@ -1204,12 +1317,62 @@ fetchPixelProc32 ACCESS(pixman_fetchPixelProcForPicture32) (bits_image_t * pict) return NULL; } +static FASTCALL uint64_t +fbFetchPixel64_generic (bits_image_t *pict, int offset, int line) +{ + fetchPixelProc32 fetchPixel32 = ACCESS(pixman_fetchPixelProcForPicture32) (pict); + uint32_t argb8Pixel = fetchPixel32(pict, offset, line); + uint64_t argb16Pixel; + + pixman_expand(&argb16Pixel, &argb8Pixel, pict->format, 1); + + return argb16Pixel; +} + +fetchPixelProc64 ACCESS(pixman_fetchPixelProcForPicture64) (bits_image_t * pict) +{ + switch(pict->format) { + case PIXMAN_a2b10g10r10: return fbFetchPixel_a2b10g10r10; + case PIXMAN_x2b10g10r10: return fbFetchPixel_x2b10g10r10; + default: return fbFetchPixel64_generic; + } +} + /*********************************** Store ************************************/ #define Splita(v) uint32_t a = ((v) >> 24), r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff #define Split(v) uint32_t r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff static FASTCALL void +fbStore_a2b10g10r10 (pixman_image_t *image, + uint32_t *bits, const uint64_t *values, int x, int width, const pixman_indexed_t * indexed) +{ + int i; + uint32_t *pixel = bits + x; + for (i = 0; i < width; ++i) { + WRITE(image, pixel++, + ((values[i] >> 32) & 0xc0000000) | // A + ((values[i] >> 38) & 0x3ff) | // R + ((values[i] >> 12) & 0xffc00) | // G + ((values[i] << 14) & 0x3ff00000)); // B + } +} + +static FASTCALL void +fbStore_x2b10g10r10 (pixman_image_t *image, + uint32_t *bits, const uint64_t *values, int x, int width, const pixman_indexed_t * indexed) +{ + int i; + uint32_t *pixel = bits + x; + for (i = 0; i < width; ++i) { + WRITE(image, pixel++, + ((values[i] >> 38) & 0x3ff) | // R + ((values[i] >> 12) & 0xffc00) | // G + ((values[i] << 14) & 0x3ff00000)); // B + } +} + +static FASTCALL void fbStore_a8r8g8b8 (pixman_image_t *image, uint32_t *bits, const uint32_t *values, int x, int width, const pixman_indexed_t * indexed) { @@ -1679,6 +1842,41 @@ storeProc32 ACCESS(pixman_storeProcForPicture32) (bits_image_t * pict) } } +/* + * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit + * store proc. + */ +static FASTCALL void +fbStore64_generic (pixman_image_t *image, + uint32_t *bits, const uint64_t *values, int x, int width, const pixman_indexed_t * indexed) +{ + bits_image_t *pict = (bits_image_t*)image; + storeProc32 store32 = ACCESS(pixman_storeProcForPicture32) (pict); + uint32_t *argb8Pixels; + + assert(image->common.type == BITS); + assert(store32); + + argb8Pixels = malloc(sizeof(uint32_t) * width); + if (!argb8Pixels) return; + + // Contract the scanline. We could do this in place if values weren't + // const. + pixman_contract(argb8Pixels, values, width); + store32(image, bits, argb8Pixels, x, width, indexed); + + free(argb8Pixels); +} + +storeProc64 ACCESS(pixman_storeProcForPicture64) (bits_image_t * pict) +{ + switch(pict->format) { + case PIXMAN_a2b10g10r10: return fbStore_a2b10g10r10; + case PIXMAN_x2b10g10r10: return fbStore_x2b10g10r10; + default: return fbStore64_generic; + } +} + #ifndef PIXMAN_FB_ACCESSORS /* * This function expands images from ARGB8 format to ARGB16. To preserve diff --git a/pixman/pixman-compose.c b/pixman/pixman-compose.c index 616fbc4..c5773eb 100644 --- a/pixman/pixman-compose.c +++ b/pixman/pixman-compose.c @@ -2,6 +2,7 @@ * * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. * 2005 Lars Knoll & Zack Rusin, Trolltech + * 2008 Aaron Plattner, NVIDIA Corporation * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -114,6 +115,19 @@ static void fbFetchSolid(bits_image_t * pict, int x, int y, int width, uint32_t *(buffer++) = color; } +static void fbFetchSolid64(bits_image_t * pict, int x, int y, int width, uint64_t *buffer, void *unused, uint32_t unused2) +{ + uint64_t color; + uint64_t *end; + fetchPixelProc64 fetch = ACCESS(pixman_fetchPixelProcForPicture64)(pict); + + color = fetch(pict, 0, 0); + + end = buffer + width; + while (buffer < end) + *(buffer++) = color; +} + static void fbFetch(bits_image_t * pict, int x, int y, int width, uint32_t *buffer, uint32_t *mask, uint32_t maskBits) { fetchProc32 fetch = ACCESS(pixman_fetchProcForPicture32)(pict); @@ -121,6 +135,13 @@ static void fbFetch(bits_image_t * pict, int x, int y, int width, uint32_t *buff fetch(pict, x, y, width, buffer); } +static void fbFetch64(bits_image_t * pict, int x, int y, int width, uint64_t *buffer, void *unused, uint32_t unused2) +{ + fetchProc64 fetch = ACCESS(pixman_fetchProcForPicture64)(pict); + + fetch(pict, x, y, width, buffer); +} + static void fbStore(bits_image_t * pict, int x, int y, int width, uint32_t *buffer) { @@ -135,6 +156,20 @@ 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 +fbStore64(bits_image_t * pict, int x, int y, int width, uint64_t *buffer) +{ + uint32_t *bits; + int32_t stride; + storeProc64 store = ACCESS(pixman_storeProcForPicture64)(pict); + const pixman_indexed_t * indexed = pict->indexed; + + bits = pict->bits; + stride = pict->rowstride; + bits += y*stride; + store((pixman_image_t *)pict, bits, buffer, x, width, indexed); +} + 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); @@ -171,22 +206,24 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, if (bits->common.alpha_map) { + // TODO: Need wide external alpha routine. fetchSrc = (scanFetchProc)ACCESS(fbFetchExternalAlpha); } else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) && bits->width == 1 && bits->height == 1) { - fetchSrc = (scanFetchProc)fbFetchSolid; + fetchSrc = wide ? (scanFetchProc)fbFetchSolid64 : (scanFetchProc)fbFetchSolid; srcClass = SOURCE_IMAGE_CLASS_HORIZONTAL; } else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION && bits->common.repeat != PIXMAN_REPEAT_PAD) { - fetchSrc = (scanFetchProc)fbFetch; + fetchSrc = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch; } else { + // TODO: Need wide transformed fetch. fetchSrc = (scanFetchProc)ACCESS(fbFetchTransformed); } } @@ -210,24 +247,27 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, if (bits->common.alpha_map) { + // TODO: Need wide external alpha routine. fetchMask = (scanFetchProc)ACCESS(fbFetchExternalAlpha); } else if ((bits->common.repeat == PIXMAN_REPEAT_NORMAL || bits->common.repeat == PIXMAN_REPEAT_PAD) && bits->width == 1 && bits->height == 1) { - fetchMask = (scanFetchProc)fbFetchSolid; + fetchMask = wide ? (scanFetchProc)fbFetchSolid64 : (scanFetchProc)fbFetchSolid; maskClass = SOURCE_IMAGE_CLASS_HORIZONTAL; } else if (!bits->common.transform && bits->common.filter != PIXMAN_FILTER_CONVOLUTION && bits->common.repeat != PIXMAN_REPEAT_PAD) - fetchMask = (scanFetchProc)fbFetch; + fetchMask = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch; else + // TODO: Need wide transformed fetch. fetchMask = (scanFetchProc)ACCESS(fbFetchTransformed); } } if (data->dest->common.alpha_map) { + // TODO: Need wide external alpha routine. fetchDest = (scanFetchProc)ACCESS(fbFetchExternalAlpha); store = (scanStoreProc)ACCESS(fbStoreExternalAlpha); @@ -236,8 +276,8 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, } else { - fetchDest = (scanFetchProc)fbFetch; - store = (scanStoreProc)fbStore; + fetchDest = wide ? (scanFetchProc)fbFetch64 : (scanFetchProc)fbFetch; + store = wide ? (scanStoreProc)fbStore64 : (scanStoreProc)fbStore; switch (data->op) { @@ -251,7 +291,11 @@ PIXMAN_COMPOSITE_RECT_GENERAL (const FbComposeData *data, switch (data->dest->bits.format) { case PIXMAN_a8r8g8b8: case PIXMAN_x8r8g8b8: - store = NULL; + // Skip the store step and composite directly into the + // destination if the output format of the compose func matches + // the destination format. + if (!wide) + store = NULL; break; default: break; diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c index ed6c255..f013ae7 100644 --- a/pixman/pixman-utils.c +++ b/pixman/pixman-utils.c @@ -467,6 +467,8 @@ pixman_format_supported_destination (pixman_format_code_t format) { switch (format) { /* 32 bpp formats */ + case PIXMAN_a2b10g10r10: + case PIXMAN_x2b10g10r10: case PIXMAN_a8r8g8b8: case PIXMAN_x8r8g8b8: case PIXMAN_a8b8g8r8: diff --git a/pixman/pixman.h b/pixman/pixman.h index 78dee13..10871a3 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -517,7 +517,9 @@ typedef enum { PIXMAN_x8r8g8b8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB,0,8,8,8), PIXMAN_a8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,8,8,8,8), PIXMAN_x8b8g8r8 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,8,8,8), - + PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10), + PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10), + /* 24bpp formats */ PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8), PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8), -- 2.7.4