summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-03-16 09:28:24 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-03-16 09:53:15 +0000
commitcb04cf9f4395c258987faead80de5c3a2c93082e (patch)
tree22101fd22711736917706e57c9244ba22df92a3c
parentd55bbdf42c75eb0fdb634e963ce81953583964b9 (diff)
sna/traps: Make the inline u8 arithmetic more robust
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_trapezoids.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index dca9d1f4..c1d42a70 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -3553,6 +3553,19 @@ struct inplace {
uint8_t opacity;
};
+static inline uint8_t
+mul_8_8(uint8_t a, uint8_t b)
+{
+ uint16_t t = a * (uint16_t)b + 0x7f;
+ return ((t >> 8) + t) >> 8;
+}
+
+static uint8_t coverage_opacity(int coverage, uint8_t opacity)
+{
+ coverage = coverage * 256 / FAST_SAMPLES_XY;
+ return mul_8_8(coverage - (coverage >> 8), opacity);
+}
+
static void
tor_blt_src(struct sna *sna,
struct sna_composite_spans_op *op,
@@ -3564,7 +3577,7 @@ tor_blt_src(struct sna *sna,
uint8_t *ptr = in->ptr;
int h, w;
- coverage = coverage * in->opacity / FAST_SAMPLES_XY;
+ coverage = coverage_opacity(coverage, in->opacity);
ptr += box->y1 * in->stride + box->x1;
@@ -3613,19 +3626,22 @@ tor_blt_in(struct sna *sna,
uint8_t *ptr = in->ptr;
int h, w, i;
- coverage = coverage * in->opacity / FAST_SAMPLES_XY;
if (coverage == 0) {
tor_blt_src(sna, op, clip, box, 0);
return;
}
+ coverage = coverage_opacity(coverage, in->opacity);
+ if (coverage == 0xff)
+ return;
+
ptr += box->y1 * in->stride + box->x1;
h = box->y2 - box->y1;
w = box->x2 - box->x1;
do {
for (i = 0; i < w; i++)
- ptr[i] = (ptr[i] * coverage) >> 8;
+ ptr[i] = mul_8_8(ptr[i], coverage);
ptr += in->stride;
} while (--h);
}
@@ -3660,10 +3676,15 @@ tor_blt_add(struct sna *sna,
uint8_t *ptr = in->ptr;
int h, w, v, i;
- coverage = coverage * in->opacity / FAST_SAMPLES_XY;
if (coverage == 0)
return;
+ coverage = coverage_opacity(coverage, in->opacity);
+ if (coverage == 0xff) {
+ tor_blt_src(sna, op, clip, box, 0xff);
+ return;
+ }
+
ptr += box->y1 * in->stride + box->x1;
h = box->y2 - box->y1;
@@ -4057,10 +4078,14 @@ trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
case PictOpAdd:
if (priv->clear && priv->clear_color == 0)
op = PictOpSrc;
+ if ((color >> 24) == 0)
+ return true;
break;
case PictOpIn:
if (priv->clear && priv->clear_color == 0)
return true;
+ if ((color >> 24) == 0)
+ return true;
case PictOpSrc:
break;
default: