diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-03-16 09:28:24 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-03-16 09:53:15 +0000 |
commit | cb04cf9f4395c258987faead80de5c3a2c93082e (patch) | |
tree | 22101fd22711736917706e57c9244ba22df92a3c | |
parent | d55bbdf42c75eb0fdb634e963ce81953583964b9 (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.c | 33 |
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: |