summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-12-31 13:27:13 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-12-31 15:36:18 +0000
commit511146d2e40e267f74e18c0dd06b65f5d6a69f5d (patch)
treea4293048b1b889307980efc778916ddc637b47e1
parenta1f585a3d0ae72e896684f62960a9ae96dc259f5 (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.c111
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(&region, box, 1);
+ RegionIntersect(&region, &region, clip);
+ n = REGION_NUM_RECTS(&region);
+ box = REGION_RECTS(&region);
+ while (n--)
+ tor_blt_add(sna, op, NULL, box++, coverage);
+ pixman_region_fini(&region);
+}
+
+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;