diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-12-31 13:27:13 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-12-31 15:36:18 +0000 |
commit | 511146d2e40e267f74e18c0dd06b65f5d6a69f5d (patch) | |
tree | a4293048b1b889307980efc778916ddc637b47e1 | |
parent | a1f585a3d0ae72e896684f62960a9ae96dc259f5 (diff) |
sna: Implement inplace trapezoidal addition (for clipmasks)
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_trapezoids.c | 111 |
1 files changed, 103 insertions, 8 deletions
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c index 9222f2fb..f7fbdb2d 100644 --- a/src/sna/sna_trapezoids.c +++ b/src/sna/sna_trapezoids.c @@ -3138,6 +3138,80 @@ tor_blt_in_clipped_mono(struct sna *sna, coverage < FAST_SAMPLES_XY/2 ? 0 : FAST_SAMPLES_XY); } +static void +tor_blt_add(struct sna *sna, + struct sna_composite_spans_op *op, + pixman_region16_t *clip, + const BoxRec *box, + int coverage) +{ + struct inplace *in = (struct inplace *)op; + uint8_t *ptr = in->ptr; + int h, w, v, i; + + coverage = coverage * in->opacity / FAST_SAMPLES_XY; + if (coverage == 0) + return; + + ptr += box->y1 * in->stride + box->x1; + + h = box->y2 - box->y1; + w = box->x2 - box->x1; + if ((w | h) == 1) { + v = coverage + *ptr; + *ptr = v >= 255 ? 255 : v; + } else { + do { + for (i = 0; i < w; i++) { + v = coverage + ptr[i]; + ptr[i] = v >= 255 ? 255 : v; + } + ptr += in->stride; + } while (--h); + } +} + +static void +tor_blt_add_clipped(struct sna *sna, + struct sna_composite_spans_op *op, + pixman_region16_t *clip, + const BoxRec *box, + int coverage) +{ + pixman_region16_t region; + int n; + + pixman_region_init_rects(®ion, box, 1); + RegionIntersect(®ion, ®ion, clip); + n = REGION_NUM_RECTS(®ion); + box = REGION_RECTS(®ion); + while (n--) + tor_blt_add(sna, op, NULL, box++, coverage); + pixman_region_fini(®ion); +} + +static void +tor_blt_add_mono(struct sna *sna, + struct sna_composite_spans_op *op, + pixman_region16_t *clip, + const BoxRec *box, + int coverage) +{ + if (coverage >= FAST_SAMPLES_XY/2) + tor_blt_add(sna, op, clip, box, FAST_SAMPLES_XY); +} + +static void +tor_blt_add_clipped_mono(struct sna *sna, + struct sna_composite_spans_op *op, + pixman_region16_t *clip, + const BoxRec *box, + int coverage) +{ + if (coverage >= FAST_SAMPLES_XY/2) + tor_blt_add_clipped(sna, op, clip, box, FAST_SAMPLES_XY); +} + static bool trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst, PictFormatPtr maskFormat, INT16 src_x, INT16 src_y, @@ -3167,17 +3241,26 @@ trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst, return false; } - DBG(("%s: format=%x, op=%d, color=%x\n", - __FUNCTION__, dst->format, op, color)); + if (dst->format != PICT_a8 || !sna_picture_is_solid(src, &color)) { + DBG(("%s: fallback -- can not perform operation in place, format=%x\n", + __FUNCTION__, dst->format)); + return false; + } - if (dst->format != PICT_a8 || - !(op == PictOpSrc || op == PictOpIn) || - !sna_picture_is_solid(src, &color)) { - DBG(("%s: fallback -- can not perform operation in place\n", - __FUNCTION__)); + switch (op) { + case PictOpSrc: + case PictOpIn: + case PictOpAdd: + break; + default: + DBG(("%s: fallback -- can not perform op [%d] in place\n", + __FUNCTION__, op)); return false; } + DBG(("%s: format=%x, op=%d, color=%x\n", + __FUNCTION__, dst->format, op, color)); + if (maskFormat == NULL && ntrap > 1) { DBG(("%s: individual rasterisation requested\n", __FUNCTION__)); @@ -3246,7 +3329,7 @@ trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst, else span = tor_blt_src; } - } else { + } else if (op == PictOpIn) { if (dst->pCompositeClip->data) { if (maskFormat ? maskFormat->depth < 8 : dst->polyEdge == PolyEdgeSharp) span = tor_blt_in_clipped_mono; @@ -3258,6 +3341,18 @@ trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst, else span = tor_blt_in; } + } else { + if (dst->pCompositeClip->data) { + if (maskFormat ? maskFormat->depth < 8 : dst->polyEdge == PolyEdgeSharp) + span = tor_blt_add_clipped_mono; + else + span = tor_blt_add_clipped; + } else { + if (maskFormat ? maskFormat->depth < 8 : dst->polyEdge == PolyEdgeSharp) + span = tor_blt_add_mono; + else + span = tor_blt_add; + } } region.data = NULL; |