Mesa (master): dri/nouveau: Swizzle using the CPU when we hit a limitation of SIFM.

Francisco Jerez currojerez at kemper.freedesktop.org
Thu Feb 25 18:33:38 UTC 2010


Module: Mesa
Branch: master
Commit: 44602bb23ca7b67d4db586d9194c75cfe4a60962
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=44602bb23ca7b67d4db586d9194c75cfe4a60962

Author: Francisco Jerez <currojerez at riseup.net>
Date:   Mon Feb 22 01:53:23 2010 +0100

dri/nouveau: Swizzle using the CPU when we hit a limitation of SIFM.

---

 src/mesa/drivers/dri/nouveau/nv04_surface.c |   96 +++++++++++++++++++++++++--
 1 files changed, 89 insertions(+), 7 deletions(-)

diff --git a/src/mesa/drivers/dri/nouveau/nv04_surface.c b/src/mesa/drivers/dri/nouveau/nv04_surface.c
index e8a5409..e3febf7 100644
--- a/src/mesa/drivers/dri/nouveau/nv04_surface.c
+++ b/src/mesa/drivers/dri/nouveau/nv04_surface.c
@@ -321,6 +321,82 @@ nv04_surface_copy_m2mf(GLcontext *ctx,
 		FIRE_RING(chan);
 }
 
+typedef unsigned (*get_offset_t)(struct nouveau_surface *s,
+				 unsigned x, unsigned y);
+
+static unsigned
+get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y)
+{
+	return x * s->cpp + y * s->pitch;
+}
+
+static unsigned
+get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y)
+{
+	unsigned k = log2i(MIN2(s->width, s->height));
+
+	unsigned u = (x & 0x001) << 0 |
+		(x & 0x002) << 1 |
+		(x & 0x004) << 2 |
+		(x & 0x008) << 3 |
+		(x & 0x010) << 4 |
+		(x & 0x020) << 5 |
+		(x & 0x040) << 6 |
+		(x & 0x080) << 7 |
+		(x & 0x100) << 8 |
+		(x & 0x200) << 9 |
+		(x & 0x400) << 10 |
+		(x & 0x800) << 11;
+
+	unsigned v = (y & 0x001) << 1 |
+		(y & 0x002) << 2 |
+		(y & 0x004) << 3 |
+		(y & 0x008) << 4 |
+		(y & 0x010) << 5 |
+		(y & 0x020) << 6 |
+		(y & 0x040) << 7 |
+		(y & 0x080) << 8 |
+		(y & 0x100) << 9 |
+		(y & 0x200) << 10 |
+		(y & 0x400) << 11 |
+		(y & 0x800) << 12;
+
+	return s->cpp * (((u | v) & ~(~0 << 2*k)) |
+			 (x & (~0 << k)) << k |
+			 (y & (~0 << k)) << k);
+}
+
+static void
+nv04_surface_copy_cpu(GLcontext *ctx,
+		      struct nouveau_surface *dst,
+		      struct nouveau_surface *src,
+		      int dx, int dy, int sx, int sy,
+		      int w, int h)
+{
+	int x, y;
+	get_offset_t get_dst = (dst->layout == SWIZZLED ?
+				get_swizzled_offset : get_linear_offset);
+	get_offset_t get_src = (src->layout == SWIZZLED ?
+				get_swizzled_offset : get_linear_offset);
+	void *dp, *sp;
+
+	nouveau_bo_map(dst->bo, NOUVEAU_BO_WR);
+	nouveau_bo_map(src->bo, NOUVEAU_BO_RD);
+
+	dp = dst->bo->map + dst->offset;
+	sp = src->bo->map + src->offset;
+
+	for (y = 0; y < h; y++) {
+		for (x = 0; x < w; x++) {
+			memcpy(dp + get_dst(dst, dx + x, dy + y),
+			       sp + get_src(src, sx + x, sy + y), dst->cpp);
+		}
+	}
+
+	nouveau_bo_unmap(src->bo);
+	nouveau_bo_unmap(dst->bo);
+}
+
 void
 nv04_surface_copy(GLcontext *ctx,
 		  struct nouveau_surface *dst,
@@ -328,16 +404,22 @@ nv04_surface_copy(GLcontext *ctx,
 		  int dx, int dy, int sx, int sy,
 		  int w, int h)
 {
-	/* Setup transfer to swizzle the texture to vram if needed */
-        if (src->layout != SWIZZLED &&
-	    dst->layout == SWIZZLED &&
-	    dst->width > 2 && dst->height > 1) {
-		nv04_surface_copy_swizzle(ctx, dst, src,
-					  dx, dy, sx, sy, w, h);
+	/* Linear texture copy. */
+	if ((src->layout == LINEAR && dst->layout == LINEAR) ||
+	    dst->width <= 2 || dst->height <= 1) {
+		nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
+		return;
+	}
+
+	/* Swizzle using sifm+swzsurf. */
+        if (src->layout == LINEAR && dst->layout == SWIZZLED &&
+	    dst->cpp != 1 && !(dst->offset & 63)) {
+		nv04_surface_copy_swizzle(ctx, dst, src, dx, dy, sx, sy, w, h);
 		return;
 	}
 
-	nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
+	/* Fallback to CPU copy. */
+	nv04_surface_copy_cpu(ctx, dst, src, dx, dy, sx, sy, w, h);
 }
 
 void




More information about the mesa-commit mailing list