diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-11-14 13:39:34 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-11-14 13:39:34 +0000 |
commit | e861e816f53989ce3ab3ec89dd1d9a35155f999a (patch) | |
tree | cfc3c8fbb7ae121e653463b3a754e5905e6d83a1 | |
parent | 6fc2928f578ae1e278c968d5c778d99d56bd667a (diff) |
sna: Convert non-FillSolid rectilinear segments to boxes
And render using the tiled/stippled rect routines instead.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_accel.c | 72 |
1 files changed, 68 insertions, 4 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index ac76525f..c3c08a5d 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -4879,10 +4879,11 @@ sna_poly_segment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg) gc->lineWidth, gc->planemask, PM_IS_SOLID(drawable, gc->planemask), flags & 4)); - if (gc->fillStyle == FillSolid && - gc->lineStyle == LineSolid && - gc->lineWidth <= 1 && - PM_IS_SOLID(drawable, gc->planemask)) { + if (!PM_IS_SOLID(drawable, gc->planemask)) + goto fallback; + if (gc->lineStyle != LineSolid || gc->lineWidth > 1) + goto spans_fallback; + if (gc->fillStyle == FillSolid) { struct sna_pixmap *priv = sna_pixmap(pixmap); struct sna_damage **damage; @@ -4917,9 +4918,72 @@ sna_poly_segment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg) gc, n, seg, ®ion.extents, flags & 2)) return; } + } else if (flags &4) { + struct sna_pixmap *priv = sna_pixmap(pixmap); + struct sna_damage **damage; + + /* Try converting these to a set of rectangles instead */ + if (sna_drawable_use_gpu_bo(drawable, ®ion.extents, &damage)) { + xRectangle *rect; + int i; + + DBG(("%s: converting to rectagnles\n", __FUNCTION__)); + + rect = malloc (n * sizeof (xRectangle)); + if (rect == NULL) + return; + + for (i = 0; i < n; i++) { + if (seg[i].x1 < seg[i].x2) { + rect[i].x = seg[i].x1; + rect[i].width = seg[i].x2 - seg[i].x1; + } else if (seg[i].x1 > seg[i].x2) { + rect[i].x = seg[i].x2; + rect[i].width = seg[i].x1 - seg[i].x2; + } else { + rect[i].x = seg[i].x1; + rect[i].width = 1; + } + if (seg[i].y1 < seg[i].y2) { + rect[i].y = seg[i].y1; + rect[i].height = seg[i].y2 - seg[i].y1; + } else if (seg[i].x1 > seg[i].y2) { + rect[i].y = seg[i].y2; + rect[i].height = seg[i].y1 - seg[i].y2; + } else { + rect[i].y = seg[i].y1; + rect[i].height = 1; + } + + /* don't paint last pixel */ + if (gc->capStyle == CapNotLast) { + if (seg->x1 == seg->x2) + rect[i].height--; + else + rect[i].width--; + } + } + + if (gc->fillStyle == FillTiled) { + i = sna_poly_fill_rect_tiled_blt(drawable, + priv->gpu_bo, damage, + gc, n, rect, + ®ion.extents, flags & 2); + } else { + i = sna_poly_fill_rect_stippled_blt(drawable, + priv->gpu_bo, damage, + gc, n, rect, + ®ion.extents, flags & 2); + } + free (rect); + + if (i) + return; + } } /* XXX Do we really want to base this decision on the amalgam ? */ +spans_fallback: if (USE_SPANS && can_fill_spans(drawable, gc) && sna_drawable_use_gpu_bo(drawable, ®ion.extents, NULL)) { |