diff options
| author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-24 16:32:40 +0000 |
|---|---|---|
| committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-24 18:54:07 +0000 |
| commit | b8b49ae70b3aadf4423bd6830c446c040f87a2f1 (patch) | |
| tree | 2d1906a6ace4506d14b173f318a1c74852d4a9b7 | |
| parent | 1a116a15a5d978a1edf413a439f6ef6d3205a7aa (diff) | |
sna: Mutate a temporary copy of the GC->ops so we don't alter new GCs
In order to avoid using the wrong function for a scratch GC created
during the course of a MI function whilst we have a specialised GC in
use, we need to avoid modifying the original function table.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
| -rw-r--r-- | src/sna/sna_accel.c | 160 |
1 files changed, 110 insertions, 50 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index fea51671..531140e7 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -125,6 +125,10 @@ static const uint8_t fill_ROP[] = { ROP_1 }; +static const GCOps sna_gc_ops; +static const GCOps sna_gc_ops__cpu; +static GCOps sna_gc_ops__tmp; + static inline void region_set(RegionRec *r, const BoxRec *b) { r->extents = *b; @@ -6209,9 +6213,9 @@ spans_fallback: if ((data.flags & 2) == 0) { if (data.dx | data.dy) - gc->ops->FillSpans = sna_fill_spans__fill_offset; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset; else - gc->ops->FillSpans = sna_fill_spans__fill; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill; } else { region_maybe_clip(&data.region, gc->pCompositeClip); @@ -6219,12 +6223,13 @@ spans_fallback: return; if (region_is_singular(&data.region)) - gc->ops->FillSpans = sna_fill_spans__fill_clip_extents; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents; else - gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes; } assert(gc->miTranslate); + gc->ops = &sna_gc_ops__tmp; miZeroLine(drawable, gc, mode, n, pt); fill.done(data.sna, &fill); } else { @@ -6233,7 +6238,8 @@ spans_fallback: * FillSpans. */ data.bo = priv->gpu_bo; - gc->ops->FillSpans = sna_fill_spans__gpu; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu; + gc->ops = &sna_gc_ops__tmp; switch (gc->lineStyle) { default: @@ -6260,7 +6266,7 @@ spans_fallback: } } - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; if (data.damage) sna_damage_add(data.damage, &data.region); RegionUninit(&data.region); @@ -6282,12 +6288,13 @@ fallback: /* Install FillSpans in case we hit a fallback path in fbPolyLine */ sna_gc(gc)->priv = &data.region; - gc->ops->FillSpans = sna_fill_spans__cpu; + assert(gc->ops == (GCOps *)&sna_gc_ops); + gc->ops = (GCOps *)&sna_gc_ops__cpu; DBG(("%s: fbPolyLine\n", __FUNCTION__)); fbPolyLine(drawable, gc, mode, n, pt); - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; out: RegionUninit(&data.region); } @@ -7144,9 +7151,9 @@ spans_fallback: if ((data.flags & 2) == 0) { if (data.dx | data.dy) - gc->ops->FillSpans = sna_fill_spans__fill_offset; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset; else - gc->ops->FillSpans = sna_fill_spans__fill; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill; } else { region_maybe_clip(&data.region, gc->pCompositeClip); @@ -7154,11 +7161,12 @@ spans_fallback: return; if (region_is_singular(&data.region)) - gc->ops->FillSpans = sna_fill_spans__fill_clip_extents; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents; else - gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes; } assert(gc->miTranslate); + gc->ops = &sna_gc_ops__tmp; for (i = 0; i < n; i++) line(drawable, gc, CoordModeOrigin, 2, (DDXPointPtr)&seg[i]); @@ -7166,14 +7174,15 @@ spans_fallback: fill.done(data.sna, &fill); } else { data.bo = priv->gpu_bo; - gc->ops->FillSpans = sna_fill_spans__gpu; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu; + gc->ops = &sna_gc_ops__tmp; for (i = 0; i < n; i++) line(drawable, gc, CoordModeOrigin, 2, (DDXPointPtr)&seg[i]); } - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; if (data.damage) sna_damage_add(data.damage, &data.region); RegionUninit(&data.region); @@ -7195,12 +7204,13 @@ fallback: /* Install FillSpans in case we hit a fallback path in fbPolySegment */ sna_gc(gc)->priv = &data.region; - gc->ops->FillSpans = sna_fill_spans__cpu; + assert(gc->ops == (GCOps *)&sna_gc_ops); + gc->ops = (GCOps *)&sna_gc_ops__cpu; DBG(("%s: fbPolySegment\n", __FUNCTION__)); fbPolySegment(drawable, gc, n, seg); - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; out: RegionUninit(&data.region); } @@ -7871,10 +7881,10 @@ sna_poly_arc(DrawablePtr drawable, GCPtr gc, int n, xArc *arc) if ((data.flags & 2) == 0) { if (data.dx | data.dy) - gc->ops->FillSpans = sna_fill_spans__fill_offset; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset; else - gc->ops->FillSpans = sna_fill_spans__fill; - gc->ops->PolyPoint = sna_poly_point__fill; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill; + sna_gc_ops__tmp.PolyPoint = sna_poly_point__fill; } else { region_maybe_clip(&data.region, gc->pCompositeClip); @@ -7882,21 +7892,20 @@ sna_poly_arc(DrawablePtr drawable, GCPtr gc, int n, xArc *arc) return; if (region_is_singular(&data.region)) { - gc->ops->FillSpans = sna_fill_spans__fill_clip_extents; - gc->ops->PolyPoint = sna_poly_point__fill_clip_extents; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents; + sna_gc_ops__tmp.PolyPoint = sna_poly_point__fill_clip_extents; } else { - gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes; - gc->ops->PolyPoint = sna_poly_point__fill_clip_boxes; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes; + sna_gc_ops__tmp.PolyPoint = sna_poly_point__fill_clip_boxes; } } assert(gc->miTranslate); + gc->ops = &sna_gc_ops__tmp; if (gc->lineWidth == 0) miZeroPolyArc(drawable, gc, n, arc); else miPolyArc(drawable, gc, n, arc); - - gc->ops->PolyPoint = sna_poly_point; - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; fill.done(data.sna, &fill); if (data.damage) @@ -7928,14 +7937,13 @@ fallback: /* Install FillSpans in case we hit a fallback path in fbPolyArc */ sna_gc(gc)->priv = &data.region; - gc->ops->FillSpans = sna_fill_spans__cpu; - gc->ops->PolyPoint = sna_poly_point__cpu; + assert(gc->ops == (GCOps *)&sna_gc_ops); + gc->ops = (GCOps *)&sna_gc_ops__cpu; DBG(("%s -- fbPolyArc\n", __FUNCTION__)); fbPolyArc(drawable, gc, n, arc); - gc->ops->PolyPoint = sna_poly_point; - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; out: RegionUninit(&data.region); } @@ -8218,9 +8226,9 @@ sna_poly_fill_polygon(DrawablePtr draw, GCPtr gc, if ((data.flags & 2) == 0) { if (data.dx | data.dy) - gc->ops->FillSpans = sna_fill_spans__fill_offset; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset; else - gc->ops->FillSpans = sna_fill_spans__fill; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill; } else { region_maybe_clip(&data.region, gc->pCompositeClip); @@ -8228,22 +8236,24 @@ sna_poly_fill_polygon(DrawablePtr draw, GCPtr gc, return; if (region_is_singular(&data.region)) - gc->ops->FillSpans = sna_fill_spans__fill_clip_extents; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents; else - gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes; } assert(gc->miTranslate); + gc->ops = &sna_gc_ops__tmp; miFillPolygon(draw, gc, shape, mode, n, pt); fill.done(data.sna, &fill); } else { data.bo = priv->gpu_bo; - gc->ops->FillSpans = sna_fill_spans__gpu; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu; + gc->ops = &sna_gc_ops__tmp; miFillPolygon(draw, gc, shape, mode, n, pt); } - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; if (data.damage) sna_damage_add(data.damage, &data.region); RegionUninit(&data.region); @@ -8270,10 +8280,11 @@ fallback: DBG(("%s: fallback -- miFillPolygon -> sna_fill_spans__cpu\n", __FUNCTION__)); sna_gc(gc)->priv = &data.region; - gc->ops->FillSpans = sna_fill_spans__cpu; + assert(gc->ops == (GCOps *)&sna_gc_ops); + gc->ops = (GCOps *)&sna_gc_ops__cpu; miFillPolygon(draw, gc, shape, mode, n, pt); - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; out: RegionUninit(&data.region); } @@ -9745,9 +9756,9 @@ sna_poly_fill_arc(DrawablePtr draw, GCPtr gc, int n, xArc *arc) if ((data.flags & 2) == 0) { if (data.dx | data.dy) - gc->ops->FillSpans = sna_fill_spans__fill_offset; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset; else - gc->ops->FillSpans = sna_fill_spans__fill; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill; } else { region_maybe_clip(&data.region, gc->pCompositeClip); @@ -9755,22 +9766,24 @@ sna_poly_fill_arc(DrawablePtr draw, GCPtr gc, int n, xArc *arc) return; if (region_is_singular(&data.region)) - gc->ops->FillSpans = sna_fill_spans__fill_clip_extents; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents; else - gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes; } assert(gc->miTranslate); + gc->ops = &sna_gc_ops__tmp; miPolyFillArc(draw, gc, n, arc); fill.done(data.sna, &fill); } else { data.bo = priv->gpu_bo; - gc->ops->FillSpans = sna_fill_spans__gpu; + sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu; + gc->ops = &sna_gc_ops__tmp; miPolyFillArc(draw, gc, n, arc); } - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; if (data.damage) sna_damage_add(data.damage, &data.region); RegionUninit(&data.region); @@ -9797,10 +9810,11 @@ fallback: DBG(("%s: fallback -- miFillPolygon -> sna_fill_spans__cpu\n", __FUNCTION__)); sna_gc(gc)->priv = &data.region; - gc->ops->FillSpans = sna_fill_spans__cpu; + assert(gc->ops == (GCOps *)&sna_gc_ops); + gc->ops = (GCOps *)&sna_gc_ops__cpu; miPolyFillArc(draw, gc, n, arc); - gc->ops->FillSpans = sna_fill_spans; + gc->ops = (GCOps *)&sna_gc_ops; out: RegionUninit(&data.region); } @@ -10929,7 +10943,53 @@ out: RegionUninit(®ion); } -static GCOps sna_gc_ops = { +static const GCOps sna_gc_ops = { + sna_fill_spans, + sna_set_spans, + sna_put_image, + sna_copy_area, + sna_copy_plane, + sna_poly_point, + sna_poly_line, + sna_poly_segment, + sna_poly_rectangle, + sna_poly_arc, + sna_poly_fill_polygon, + sna_poly_fill_rect, + sna_poly_fill_arc, + sna_poly_text8, + sna_poly_text16, + sna_image_text8, + sna_image_text16, + sna_image_glyph, + sna_poly_glyph, + sna_push_pixels, +}; + +static const GCOps sna_gc_ops__cpu = { + sna_fill_spans__cpu, + sna_set_spans, + sna_put_image, + sna_copy_area, + sna_copy_plane, + sna_poly_point__cpu, + sna_poly_line, + sna_poly_segment, + sna_poly_rectangle, + sna_poly_arc, + sna_poly_fill_polygon, + sna_poly_fill_rect, + sna_poly_fill_arc, + sna_poly_text8, + sna_poly_text16, + sna_image_text8, + sna_image_text16, + sna_image_glyph, + sna_poly_glyph, + sna_push_pixels, +}; + +static GCOps sna_gc_ops__tmp = { sna_fill_spans, sna_set_spans, sna_put_image, @@ -10965,7 +11025,7 @@ sna_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable) sna_gc(gc)->changes |= changes; } -static GCFuncs sna_gc_funcs = { +static const GCFuncs sna_gc_funcs = { sna_validate_gc, miChangeGC, miCopyGC, @@ -10980,8 +11040,8 @@ static int sna_create_gc(GCPtr gc) if (!fbCreateGC(gc)) return FALSE; - gc->funcs = &sna_gc_funcs; - gc->ops = &sna_gc_ops; + gc->funcs = (GCFuncs *)&sna_gc_funcs; + gc->ops = (GCOps *)&sna_gc_ops; return TRUE; } |
