diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-04-13 09:38:57 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-04-13 09:43:07 +0100 |
commit | 9becfbbf89f2b170e50f705cabfc7bbf1dcf9846 (patch) | |
tree | 8e299cff7aa161532a75ab4fa1ba155f4bacd168 | |
parent | e269ed5d4e1b9d758aeb9a85ed0fa631f0aff0b1 (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.c | 136 |
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 |