summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-04-13 09:38:57 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-04-13 09:43:07 +0100
commit9becfbbf89f2b170e50f705cabfc7bbf1dcf9846 (patch)
tree8e299cff7aa161532a75ab4fa1ba155f4bacd168
parente269ed5d4e1b9d758aeb9a85ed0fa631f0aff0b1 (diff)
sna: Draw dashed PolyLines twice, once for the fgPixel, once for the bgPixel
As the fast paths only setup state upfront, we were missing the state changes required between dash-on/off. Take advantage of that each pixel is only drawn once to batch the state changes and run the miZeroDashLines twice. A future task would be to use a custom line drawing routine... Fixes regression from ec1267df746512c2e262ef0bd9e9527bc5efe6f4. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_accel.c136
1 files changed, 109 insertions, 27 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 590cc11b..b3507ad5 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -4275,6 +4275,18 @@ sna_fill_spans__fill(DrawablePtr drawable,
}
static void
+sna_fill_spans__dash(DrawablePtr drawable,
+ GCPtr gc, int n,
+ DDXPointPtr pt, int *width, int sorted)
+{
+ struct sna_fill_spans *data = sna_gc(gc)->priv;
+ struct sna_fill_op *op = data->op;
+
+ if (op->base.u.blt.pixel == gc->fgPixel)
+ sna_fill_spans__fill(drawable, gc, n, pt, width, sorted);
+}
+
+static void
sna_fill_spans__fill_offset(DrawablePtr drawable,
GCPtr gc, int n,
DDXPointPtr pt, int *width, int sorted)
@@ -4306,6 +4318,18 @@ sna_fill_spans__fill_offset(DrawablePtr drawable,
}
static void
+sna_fill_spans__dash_offset(DrawablePtr drawable,
+ GCPtr gc, int n,
+ DDXPointPtr pt, int *width, int sorted)
+{
+ struct sna_fill_spans *data = sna_gc(gc)->priv;
+ struct sna_fill_op *op = data->op;
+
+ if (op->base.u.blt.pixel == gc->fgPixel)
+ sna_fill_spans__fill_offset(drawable, gc, n, pt, width, sorted);
+}
+
+static void
sna_fill_spans__fill_clip_extents(DrawablePtr drawable,
GCPtr gc, int n,
DDXPointPtr pt, int *width, int sorted)
@@ -4349,6 +4373,18 @@ sna_fill_spans__fill_clip_extents(DrawablePtr drawable,
}
static void
+sna_fill_spans__dash_clip_extents(DrawablePtr drawable,
+ GCPtr gc, int n,
+ DDXPointPtr pt, int *width, int sorted)
+{
+ struct sna_fill_spans *data = sna_gc(gc)->priv;
+ struct sna_fill_op *op = data->op;
+
+ if (op->base.u.blt.pixel == gc->fgPixel)
+ sna_fill_spans__fill_clip_extents(drawable, gc, n, pt, width, sorted);
+}
+
+static void
sna_fill_spans__fill_clip_boxes(DrawablePtr drawable,
GCPtr gc, int n,
DDXPointPtr pt, int *width, int sorted)
@@ -4422,6 +4458,18 @@ sna_fill_spans__fill_clip_boxes(DrawablePtr drawable,
op->boxes(data->sna, op, box, b - box);
}
+static void
+sna_fill_spans__dash_clip_boxes(DrawablePtr drawable,
+ GCPtr gc, int n,
+ DDXPointPtr pt, int *width, int sorted)
+{
+ struct sna_fill_spans *data = sna_gc(gc)->priv;
+ struct sna_fill_op *op = data->op;
+
+ if (op->base.u.blt.pixel == gc->fgPixel)
+ sna_fill_spans__fill_clip_boxes(drawable, gc, n, pt, width, sorted);
+}
+
static Bool
sna_fill_spans_blt(DrawablePtr drawable,
struct kgem_bo *bo, struct sna_damage **damage,
@@ -6646,44 +6694,78 @@ spans_fallback:
get_drawable_deltas(drawable, data.pixmap, &data.dx, &data.dy);
sna_gc(gc)->priv = &data;
- if (gc->lineWidth == 0 &&
- gc_is_solid(gc, &color)) {
+ if (gc->lineWidth == 0 && gc_is_solid(gc, &color)) {
struct sna_fill_op fill;
- if (!sna_fill_init_blt(&fill,
- data.sna, data.pixmap,
- data.bo, gc->alu, color))
- goto fallback;
+ if (gc->lineStyle == LineSolid) {
+ if (!sna_fill_init_blt(&fill,
+ data.sna, data.pixmap,
+ data.bo, gc->alu, color))
+ goto fallback;
- data.op = &fill;
+ data.op = &fill;
- if ((data.flags & 2) == 0) {
- if (data.dx | data.dy)
- sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset;
- else
- sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill;
- } else {
- region_maybe_clip(&data.region,
- gc->pCompositeClip);
- if (!RegionNotEmpty(&data.region))
- return;
+ if ((data.flags & 2) == 0) {
+ if (data.dx | data.dy)
+ sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset;
+ else
+ sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill;
+ } else {
+ region_maybe_clip(&data.region,
+ gc->pCompositeClip);
+ if (!RegionNotEmpty(&data.region))
+ return;
- if (region_is_singular(&data.region))
- sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents;
- else
- sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes;
- }
- assert(gc->miTranslate);
+ if (region_is_singular(&data.region))
+ sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents;
+ else
+ sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes;
+ }
+ assert(gc->miTranslate);
- gc->ops = &sna_gc_ops__tmp;
- if (gc->lineStyle == LineSolid) {
+ gc->ops = &sna_gc_ops__tmp;
DBG(("%s: miZeroLine (solid fill)\n", __FUNCTION__));
miZeroLine(drawable, gc, mode, n, pt);
+ fill.done(data.sna, &fill);
} else {
- DBG(("%s: miZeroDashLine (solid fill)\n", __FUNCTION__));
+ data.op = &fill;
+
+ if ((data.flags & 2) == 0) {
+ if (data.dx | data.dy)
+ sna_gc_ops__tmp.FillSpans = sna_fill_spans__dash_offset;
+ else
+ sna_gc_ops__tmp.FillSpans = sna_fill_spans__dash;
+ } else {
+ region_maybe_clip(&data.region,
+ gc->pCompositeClip);
+ if (!RegionNotEmpty(&data.region))
+ return;
+
+ if (region_is_singular(&data.region))
+ sna_gc_ops__tmp.FillSpans = sna_fill_spans__dash_clip_extents;
+ else
+ sna_gc_ops__tmp.FillSpans = sna_fill_spans__dash_clip_boxes;
+ }
+ assert(gc->miTranslate);
+
+ gc->ops = &sna_gc_ops__tmp;
+ DBG(("%s: miZeroLine (solid dash)\n", __FUNCTION__));
+ if (!sna_fill_init_blt(&fill,
+ data.sna, data.pixmap,
+ data.bo, gc->alu, color))
+ goto fallback;
+
miZeroDashLine(drawable, gc, mode, n, pt);
+ fill.done(data.sna, &fill);
+
+ if (sna_fill_init_blt(&fill,
+ data.sna, data.pixmap,
+ data.bo, gc->alu,
+ gc->bgPixel)) {
+ miZeroDashLine(drawable, gc, mode, n, pt);
+ fill.done(data.sna, &fill);
+ }
}
- fill.done(data.sna, &fill);
} else {
/* Note that the WideDash functions alternate
* between filling using fgPixel and bgPixel