summaryrefslogtreecommitdiffstats
path: root/src/vivante_accel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vivante_accel.c')
-rw-r--r--src/vivante_accel.c91
1 files changed, 73 insertions, 18 deletions
diff --git a/src/vivante_accel.c b/src/vivante_accel.c
index 1e4a96d..83f4915 100644
--- a/src/vivante_accel.c
+++ b/src/vivante_accel.c
@@ -31,6 +31,16 @@
#include <gc_hal_enum.h>
#include <gc_hal.h>
+static inline uint32_t scale16(uint32_t val, int bits)
+{
+ val <<= (16 - bits);
+ while (bits < 16) {
+ val |= val >> bits;
+ bits <<= 1;
+ }
+ return val >> 8;
+}
+
static CARD32 get_first_pixel(DrawablePtr pDraw)
{
union { CARD32 c32; CARD16 c16; CARD8 c8; char c; } pixel;
@@ -1226,6 +1236,63 @@ static Bool vivante_picture_is_solid(PicturePtr pict, CARD32 *colour)
return FALSE;
}
+static Bool vivante_pict_solid_argb(PicturePtr pict, uint32_t *col)
+{
+ unsigned r, g, b, a, rbits, gbits, bbits, abits;
+ PictFormatPtr pFormat;
+ xRenderColor colour;
+ CARD32 pixel;
+ uint32_t argb;
+
+ if (!vivante_picture_is_solid(pict, &pixel))
+ return FALSE;
+
+ pFormat = pict->pFormat;
+ /* If no format (eg, source-only) assume it's the correct format */
+ if (!pFormat || pict->format == PICT_a8r8g8b8) {
+ *col = pixel;
+ return TRUE;
+ }
+
+ switch (pFormat->type) {
+ case PictTypeDirect:
+ r = (pixel >> pFormat->direct.red) & pFormat->direct.redMask;
+ g = (pixel >> pFormat->direct.green) & pFormat->direct.greenMask;
+ b = (pixel >> pFormat->direct.blue) & pFormat->direct.blueMask;
+ a = (pixel >> pFormat->direct.alpha) & pFormat->direct.alphaMask;
+ rbits = Ones(pFormat->direct.redMask);
+ gbits = Ones(pFormat->direct.greenMask);
+ bbits = Ones(pFormat->direct.blueMask);
+ abits = Ones(pFormat->direct.alphaMask);
+ if (abits)
+ argb = scale16(a, abits) << 24;
+ else
+ argb = 0xff000000;
+ if (rbits)
+ argb |= scale16(r, rbits) << 16;
+ if (gbits)
+ argb |= scale16(g, gbits) << 8;
+ if (bbits)
+ argb |= scale16(b, bbits);
+ break;
+ case PictTypeIndexed:
+ miRenderPixelToColor(pFormat, pixel, &colour);
+ argb = (colour.alpha >> 8) << 24;
+ argb |= (colour.red >> 8) << 16;
+ argb |= (colour.green >> 8) << 8;
+ argb |= (colour.blue >> 8);
+ break;
+ default:
+ /* unknown type, just assume pixel value */
+ argb = pixel;
+ break;
+ }
+
+ *col = argb;
+
+ return TRUE;
+}
+
/*
* If we're filling a solid
* surface, force it to have alpha; it may be used in combination
@@ -1240,14 +1307,12 @@ static struct vivante_pixmap *vivante_acquire_src(struct vivante *vivante,
PixmapPtr pPixmap;
struct vivante_pixmap *vSrc;
DrawablePtr drawable = pict->pDrawable;
- CARD32 colour;
+ uint32_t colour;
int tx, ty, ox, oy;
- if (vivante_picture_is_solid(pict, &colour)) {
+ if (vivante_pict_solid_argb(pict, &colour)) {
*xout = 0;
*yout = 0;
- if (PICT_FORMAT_A(pict->format) == 0)
- colour |= 0xff000000;
if (!vivante_fill_single(vivante, vTemp, clip, colour))
return NULL;
vivante_flush(vivante);
@@ -1405,7 +1470,7 @@ fprintf(stderr, "%s: i: op 0x%02x src=%p,%d,%d mask=%p,%d,%d dst=%p,%d,%d %ux%u\
/* Remove repeat on source or mask if useless */
adjust_repeat(pSrc, xSrc, ySrc, width, height);
if (pMask) {
- CARD32 colour;
+ uint32_t colour;
/*
* A PictOpOver with a mask looks like this:
@@ -1436,19 +1501,9 @@ fprintf(stderr, "%s: i: op 0x%02x src=%p,%d,%d mask=%p,%d,%d dst=%p,%d,%d %ux%u\
* format must not have an alpha channel.
*/
if (op == PictOpOver && !PICT_FORMAT_A(pDst->format) &&
- vivante_picture_is_solid(pMask, &colour)) {
- switch (pMask->format) {
- case PICT_a8:
- break;
- case PICT_a4:
- colour *= 0x11;
- break;
- case PICT_a1:
- colour *= 0xff;
- break;
- default:
- goto fallback;
- }
+ vivante_pict_solid_argb(pMask, &colour)) {
+ /* Convert the colour to A8 */
+ colour >>= 24;
special = vivante_composite_op[PictOpAtop];