xf86-video-intel: 2 commits - src/sna/sna_accel.c src/sna/sna_blt.c src/sna/sna.h

Chris Wilson ickle at kemper.freedesktop.org
Mon Jan 23 07:43:42 PST 2012


 src/sna/sna.h       |    1 
 src/sna/sna_accel.c |  409 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/sna/sna_blt.c   |   14 -
 3 files changed, 408 insertions(+), 16 deletions(-)

New commits:
commit 41739ff9517ca158d9f7b7ac82e5bacef62a3d68
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jan 23 15:42:18 2012 +0000

    sna: Wrap gc->ops->FillPolygon
    
    The goal is to avoid the overhead of performing multiple region analysis
    when calling sna_fill_spans by doing it once at the top level and then
    choose the most appropriate drawing method.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 38ae404..cabf04c 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -192,6 +192,7 @@ static inline struct sna_pixmap *sna_pixmap_from_drawable(DrawablePtr drawable)
 struct sna_gc {
 	long changes;
 	long serial;
+	void *priv;
 };
 
 static inline struct sna_gc *sna_gc(GCPtr gc)
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 3f53e01..c258812 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -75,7 +75,7 @@
 #define ACCEL_POLY_SEGMENT 1
 #define ACCEL_POLY_RECTANGLE 1
 #define ACCEL_POLY_ARC 1
-//#define ACCEL_FILL_POLYGON 1
+#define ACCEL_POLY_FILL_POLYGON 1
 #define ACCEL_POLY_FILL_RECT 1
 //#define ACCEL_POLY_FILL_ARC 1
 #define ACCEL_POLY_TEXT8 1
@@ -3597,6 +3597,251 @@ find_clip_box_for_y(const BoxRec *begin, const BoxRec *end, int16_t y)
 	return find_clip_box_for_y(mid, end, y);
 }
 
+static void
+sna_fill_spans__cpu(DrawablePtr drawable,
+		    GCPtr gc, int n,
+		    DDXPointPtr pt, int *width, int sorted)
+{
+	BoxRec extents;
+
+	DBG(("%s x %d\n", __FUNCTION__, n));
+
+	extents = gc->pCompositeClip->extents;
+	while (n--) {
+		BoxRec b;
+
+		DBG(("%s: (%d, %d) + %d\n",
+		     __FUNCTION__, pt->x, pt->y, *width));
+
+		*(DDXPointRec *)&b = *pt++;
+		b.x2 = b.x1 + *width++;
+		b.y2 = b.y1 + 1;
+
+		if (!box_intersect(&b, &extents))
+			continue;
+
+		if (region_is_singular(gc->pCompositeClip)) {
+			fbFill(drawable, gc, b.x1, b.y1, b.x2 - b.x1, 1);
+		} else {
+			const BoxRec * const clip_start = RegionBoxptr(gc->pCompositeClip);
+			const BoxRec * const clip_end = clip_start + gc->pCompositeClip->data->numRects;
+			const BoxRec *c;
+
+			c = find_clip_box_for_y(clip_start,
+						clip_end,
+						b.y1);
+			while (c != clip_end) {
+				int16_t x1, x2;
+
+				if (b.y2 <= c->y1)
+					break;
+
+				if (b.x1 >= c->x2)
+					break;
+				if (b.x2 <= c->x1) {
+					c++;
+					continue;
+				}
+
+				x1 = c->x1;
+				x2 = c->x2;
+				c++;
+
+				if (x1 < b.x1)
+					x1 = b.x1;
+				if (x2 > b.x2)
+					x2 = b.x2;
+				if (x2 > x1)
+					fbFill(drawable, gc,
+					       x1, b.y1, x2 - x1, 1);
+			}
+		}
+	}
+}
+
+struct sna_fill_spans {
+	struct sna *sna;
+	PixmapPtr pixmap;
+	RegionRec region;
+	unsigned flags;
+	struct sna_damage **damage;
+	int16_t dx, dy;
+	void *op;
+};
+
+static void
+sna_fill_spans__fill(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;
+	BoxRec box[512];
+
+	DBG(("%s: alu=%d, fg=%08lx, count=%d\n",
+	     __FUNCTION__, gc->alu, gc->fgPixel, n));
+
+	assert(n);
+	do {
+		BoxRec *b = box;
+		int nbox = n;
+		if (nbox > ARRAY_SIZE(box))
+			nbox = ARRAY_SIZE(box);
+		n -= nbox;
+		do {
+			*(DDXPointRec *)b = *pt++;
+			b->x2 = b->x1 + (int)*width++;
+			b->y2 = b->y1 + 1;
+			DBG(("%s: (%d, %d), (%d, %d)\n",
+			     __FUNCTION__, b->x1, b->y1, b->x2, b->y2));
+			if (b->x2 > b->x1)
+				b++;
+		} while (--nbox);
+		if (b != box)
+			op->boxes(data->sna, op, box, b - box);
+	} while (n);
+}
+
+static void
+sna_fill_spans__fill_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;
+	BoxRec box[512];
+
+	DBG(("%s: alu=%d, fg=%08lx\n", __FUNCTION__, gc->alu, gc->fgPixel));
+
+	do {
+		BoxRec *b = box;
+		int nbox = n;
+		if (nbox > ARRAY_SIZE(box))
+			nbox = ARRAY_SIZE(box);
+		n -= nbox;
+		do {
+			*(DDXPointRec *)b = *pt++;
+			b->x1 += data->dx;
+			b->y1 += data->dy;
+			b->x2 = b->x1 + (int)*width++;
+			b->y2 = b->y1 + 1;
+			if (b->x2 > b->x1)
+				b++;
+		} while (--nbox);
+		if (b != box)
+			op->boxes(data->sna, op, box, b - box);
+	} while (n);
+}
+
+static void
+sna_fill_spans__fill_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;
+	const BoxRec *extents = &data->region.extents;
+	BoxRec box[512], *b = box, *const last_box = box + ARRAY_SIZE(box);
+
+	DBG(("%s: alu=%d, fg=%08lx, count=%d, extents=(%d, %d), (%d, %d)\n",
+	     __FUNCTION__, gc->alu, gc->fgPixel, n,
+	     extents->x1, extents->y1,
+	     extents->x2, extents->y2));
+
+	assert(n);
+	do {
+		*(DDXPointRec *)b = *pt++;
+		b->x2 = b->x1 + (int)*width++;
+		b->y2 = b->y1 + 1;
+		if (box_intersect(b, extents)) {
+			b->x1 += data->dx;
+			b->x2 += data->dx;
+			b->y1 += data->dy;
+			b->y2 += data->dy;
+			if (++b == last_box) {
+				op->boxes(data->sna, op, box, last_box - box);
+				b = box;
+			}
+		}
+	} while (--n);
+	if (b != box)
+		op->boxes(data->sna, op, box, b - box);
+}
+
+static void
+sna_fill_spans__fill_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;
+	BoxRec box[512], *b = box, *const last_box = box + ARRAY_SIZE(box);
+	const BoxRec * const clip_start = RegionBoxptr(&data->region);
+	const BoxRec * const clip_end = clip_start + data->region.data->numRects;
+
+	DBG(("%s: alu=%d, fg=%08lx, count=%d, extents=(%d, %d), (%d, %d)\n",
+	     __FUNCTION__, gc->alu, gc->fgPixel, n,
+	     data->region.extents.x1, data->region.extents.y1,
+	     data->region.extents.x2, data->region.extents.y2));
+
+	assert(n);
+	do {
+		int16_t X1 = pt->x;
+		int16_t y = pt->y;
+		int16_t X2 = X1 + (int)*width;
+		const BoxRec *c;
+
+		pt++;
+		width++;
+
+		if (y < data->region.extents.y1 || data->region.extents.y2 <= y)
+			continue;
+
+		if (X1 < data->region.extents.x1)
+			X1 = data->region.extents.x1;
+
+		if (X2 > data->region.extents.x2)
+			X2 = data->region.extents.x2;
+
+		if (X1 >= X2)
+			continue;
+
+		c = find_clip_box_for_y(clip_start, clip_end, y);
+		while (c != clip_end) {
+			if (y + 1 <= c->y1)
+				break;
+
+			if (X1 >= c->x2)
+				break;
+			if (X2 <= c->x1) {
+				c++;
+				continue;
+			}
+
+			b->x1 = c->x1;
+			b->x2 = c->x2;
+			c++;
+
+			if (b->x1 < X1)
+				b->x1 = X1;
+			if (b->x2 > X2)
+				b->x2 = X2;
+			if (b->x2 <= b->x1)
+				continue;
+
+			b->x1 += data->dx;
+			b->x2 += data->dx;
+			b->y1 = y + data->dy;
+			b->y2 = b->y1 + 1;
+			if (++b == last_box) {
+				op->boxes(data->sna, op, box, last_box - box);
+				b = box;
+			}
+		}
+	} while (--n);
+	if (b != box)
+		op->boxes(data->sna, op, box, b - box);
+}
 
 static Bool
 sna_fill_spans_blt(DrawablePtr drawable,
@@ -4061,7 +4306,7 @@ fallback:
 		goto out;
 	if (!sna_drawable_move_region_to_cpu(drawable, &region,
 					     drawable_gc_flags(drawable,
-							       gc, true)))
+							       gc, n > 1)))
 		goto out;
 
 	fbFillSpans(drawable, gc, n, pt, width, sorted);
@@ -7505,6 +7750,146 @@ get_pixel(PixmapPtr pixmap)
 	}
 }
 
+static bool
+gc_is_solid(GCPtr gc, uint32_t *color)
+{
+	if (gc->fillStyle == FillSolid ||
+	    (gc->fillStyle == FillTiled && gc->tileIsPixel) ||
+	    (gc->fillStyle == FillOpaqueStippled && gc->bgPixel == gc->fgPixel)) {
+		*color = gc->fillStyle == FillTiled ? gc->tile.pixel : gc->fgPixel;
+		return true;
+	}
+
+	return false;
+}
+
+static void
+sna_poly_fill_polygon(DrawablePtr draw, GCPtr gc,
+		      int shape, int mode,
+		      int n, DDXPointPtr pt)
+{
+	struct sna_fill_spans data;
+	struct sna_pixmap *priv;
+
+	DBG(("%s(n=%d, PlaneMask: %lx (solid %d), solid fill: %d [style=%d, tileIsPixel=%d], alu=%d)\n", __FUNCTION__,
+	     n, gc->planemask, !!PM_IS_SOLID(draw, gc->planemask),
+	     (gc->fillStyle == FillSolid ||
+	      (gc->fillStyle == FillTiled && gc->tileIsPixel)),
+	     gc->fillStyle, gc->tileIsPixel,
+	     gc->alu));
+
+	data.flags = sna_poly_point_extents(draw, gc, mode, n, pt,
+					    &data.region.extents);
+	if (data.flags == 0) {
+		DBG(("%s, nothing to do\n", __FUNCTION__));
+		return;
+	}
+
+	DBG(("%s: extents(%d, %d), (%d, %d), flags=%x\n", __FUNCTION__,
+	     data.region.extents.x1, data.region.extents.y1,
+	     data.region.extents.x2, data.region.extents.y2,
+	     data.flags));
+
+	data.region.data = NULL;
+
+	if (FORCE_FALLBACK)
+		goto fallback;
+
+	if (!ACCEL_POLY_FILL_POLYGON)
+		goto fallback;
+
+	data.pixmap = get_drawable_pixmap(draw);
+	data.sna = to_sna_from_pixmap(data.pixmap);
+	priv = sna_pixmap(data.pixmap);
+	if (priv == NULL) {
+		DBG(("%s: fallback -- unattached\n", __FUNCTION__));
+		goto fallback;
+	}
+
+	if (wedged(data.sna)) {
+		DBG(("%s: fallback -- wedged\n", __FUNCTION__));
+		goto fallback;
+	}
+
+	if (!PM_IS_SOLID(draw, gc->planemask))
+		goto fallback;
+
+	if (sna_drawable_use_gpu_bo(draw,
+				    &data.region.extents,
+				    &data.damage)) {
+		uint32_t color;
+
+		get_drawable_deltas(draw, data.pixmap, &data.dx, &data.dy);
+
+		if (gc_is_solid(gc, &color)) {
+			struct sna_fill_op fill;
+
+			if (!sna_fill_init_blt(&fill,
+					       data.sna, data.pixmap,
+					       priv->gpu_bo, gc->alu, color))
+				goto fallback;
+
+			data.op = &fill;
+			sna_gc(gc)->priv = &data;
+
+			if ((data.flags & 2) == 0) {
+				if (data.dx | data.dy)
+					gc->ops->FillSpans = sna_fill_spans__fill_offset;
+				else
+					gc->ops->FillSpans = sna_fill_spans__fill;
+			} else {
+				region_maybe_clip(&data.region,
+						  gc->pCompositeClip);
+				if (!RegionNotEmpty(&data.region))
+					return;
+
+				if (region_is_singular(&data.region))
+					gc->ops->FillSpans = sna_fill_spans__fill_clip_extents;
+				else
+					gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes;
+			}
+			assert(gc->miTranslate);
+			miFillPolygon(draw, gc, shape, mode, n, pt);
+			gc->ops->FillSpans = sna_fill_spans;
+
+			fill.done(data.sna, &fill);
+			if (data.damage)
+				sna_damage_add(data.damage, &data.region);
+			RegionUninit(&data.region);
+			return;
+		}
+
+		/* XXX */
+		miFillPolygon(draw, gc, shape, mode, n, pt);
+		return;
+	}
+
+fallback:
+	DBG(("%s: fallback (%d, %d), (%d, %d)\n", __FUNCTION__,
+	     data.region.extents.x1, data.region.extents.y1,
+	     data.region.extents.x2, data.region.extents.y2));
+	region_maybe_clip(&data.region, gc->pCompositeClip);
+	if (!RegionNotEmpty(&data.region)) {
+		DBG(("%s: nothing to do, all clipped\n", __FUNCTION__));
+		return;
+	}
+
+	if (!sna_gc_move_to_cpu(gc, draw))
+		goto out;
+
+	if (!sna_drawable_move_region_to_cpu(draw, &data.region,
+					     drawable_gc_flags(draw, gc,
+							       true)))
+		goto out;
+
+	DBG(("%s: fallback -- miFillPolygon -> sna_fill_spans__cpu\n", __FUNCTION__));
+	gc->ops->FillSpans = sna_fill_spans__cpu;
+	miFillPolygon(draw, gc, shape, mode, n, pt);
+	gc->ops->FillSpans = sna_fill_spans;
+out:
+	RegionUninit(&data.region);
+}
+
 static Bool
 sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
 			     struct kgem_bo *bo,
@@ -10015,7 +10400,7 @@ out:
 	RegionUninit(&region);
 }
 
-static const GCOps sna_gc_ops = {
+static GCOps sna_gc_ops = {
 	sna_fill_spans,
 	sna_set_spans,
 	sna_put_image,
@@ -10026,7 +10411,7 @@ static const GCOps sna_gc_ops = {
 	sna_poly_segment,
 	sna_poly_rectangle,
 	sna_poly_arc,
-	miFillPolygon,
+	sna_poly_fill_polygon,
 	sna_poly_fill_rect,
 	miPolyFillArc,
 	sna_poly_text8,
@@ -10051,7 +10436,7 @@ sna_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
 	sna_gc(gc)->changes |= changes;
 }
 
-static const GCFuncs sna_gc_funcs = {
+static GCFuncs sna_gc_funcs = {
 	sna_validate_gc,
 	miChangeGC,
 	miCopyGC,
@@ -10066,8 +10451,8 @@ static int sna_create_gc(GCPtr gc)
 	if (!fbCreateGC(gc))
 		return FALSE;
 
-	gc->funcs = (GCFuncs *)&sna_gc_funcs;
-	gc->ops = (GCOps *)&sna_gc_ops;
+	gc->funcs = &sna_gc_funcs;
+	gc->ops = &sna_gc_ops;
 	return TRUE;
 }
 
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index 86cc311..535628c 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -117,17 +117,17 @@ static bool sna_blt_fill_init(struct sna *sna,
 			      uint32_t pixel)
 {
 	struct kgem *kgem = &sna->kgem;
-	int pitch;
 
+	assert(bo->tiling != I915_TILING_Y);
 	blt->bo[0] = bo;
 
-	pitch = bo->pitch;
+	blt->br13 = bo->pitch;
 	blt->cmd = XY_SCANLINE_BLT;
-	if (kgem->gen >= 40 && blt->bo[0]->tiling) {
-		blt->cmd |= 1 << 11;
-		pitch >>= 2;
+	if (kgem->gen >= 40 && bo->tiling) {
+		blt->cmd |= BLT_DST_TILED;
+		blt->br13 >>= 2;
 	}
-	assert(pitch < MAXSHORT);
+	assert(blt->br13 < MAXSHORT);
 
 	if (alu == GXclear)
 		pixel = 0;
@@ -138,7 +138,7 @@ static bool sna_blt_fill_init(struct sna *sna,
 			alu = GXset;
 	}
 
-	blt->br13 = 1<<31 | (fill_ROP[alu] << 16) | pitch;
+	blt->br13 |= 1<<31 | (fill_ROP[alu] << 16);
 	switch (bpp) {
 	default: assert(0);
 	case 32: blt->br13 |= 1 << 25; /* RGB8888 */
commit aef56b194d4de9bd71ab71e3d93d81e1750262c5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jan 23 15:38:30 2012 +0000

    sna: Mark GPU bo as busy when drawing to an all-damaged pixmap for core
    
    The fast path to decide whether to use the GPU bo for the core drawaing
    operations forgot to update the active status of the pixmap. This
    included forgetting to clear the is-cleared flag.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index c195dc1..3f53e01 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -727,8 +727,10 @@ static Bool sna_destroy_pixmap(PixmapPtr pixmap)
 
 static inline void list_move(struct list *list, struct list *head)
 {
-	__list_del(list->prev, list->next);
-	list_add(list, head);
+	if (list->prev != head) {
+		__list_del(list->prev, list->next);
+		list_add(list, head);
+	}
 }
 
 static inline bool pixmap_inplace(struct sna *sna,
@@ -1630,6 +1632,10 @@ _sna_drawable_use_gpu_bo(DrawablePtr drawable,
 
 	if (DAMAGE_IS_ALL(priv->gpu_damage)) {
 		*damage = NULL;
+		if (!priv->pinned)
+			list_move(&priv->inactive,
+				  &to_sna_from_pixmap(pixmap)->active_pixmaps);
+		priv->clear = false;
 		return TRUE;
 	}
 


More information about the xorg-commit mailing list