summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-11-14 13:39:34 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-11-14 13:39:34 +0000
commite861e816f53989ce3ab3ec89dd1d9a35155f999a (patch)
treecfc3c8fbb7ae121e653463b3a754e5905e6d83a1
parent6fc2928f578ae1e278c968d5c778d99d56bd667a (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.c72
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, &region.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, &region.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,
+ &region.extents, flags & 2);
+ } else {
+ i = sna_poly_fill_rect_stippled_blt(drawable,
+ priv->gpu_bo, damage,
+ gc, n, rect,
+ &region.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, &region.extents, NULL)) {