Mesa (master): nvfx: fix swizzling of high bpp surfaces

Luca Barbieri lb at kemper.freedesktop.org
Sat Sep 4 21:01:23 UTC 2010


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

Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Sat Sep  4 17:12:02 2010 +0200

nvfx: fix swizzling of high bpp surfaces

---

 src/gallium/drivers/nvfx/nv04_2d.h      |   20 ++++++++
 src/gallium/drivers/nvfx/nvfx_surface.c |   82 ++++++++++++++++---------------
 2 files changed, 63 insertions(+), 39 deletions(-)

diff --git a/src/gallium/drivers/nvfx/nv04_2d.h b/src/gallium/drivers/nvfx/nv04_2d.h
index e638b8c..e7d872a 100644
--- a/src/gallium/drivers/nvfx/nv04_2d.h
+++ b/src/gallium/drivers/nvfx/nv04_2d.h
@@ -47,6 +47,26 @@ struct nv04_region {
 	unsigned w, h, d;
 };
 
+static inline void
+nv04_region_try_to_linearize(struct nv04_region* rgn)
+{
+	assert(!rgn->pitch);
+
+	if(rgn->d <= 1)
+	{
+		if(rgn->h <= 1 || rgn->w <= 2)
+			rgn->pitch = rgn->w << rgn->bpps;
+	}
+	else
+	{
+		if(rgn->h <= 2 && rgn->w <= 2)
+		{
+			rgn->pitch = rgn->w << rgn->bpps;
+			rgn->offset += rgn->z * rgn->h * rgn->pitch;
+		}
+	}
+}
+
 void
 nv04_memcpy(struct nv04_2d_context *ctx,
 		struct nouveau_bo* dstbo, int dstoff,
diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c
index 34fd4c4..0255e3f 100644
--- a/src/gallium/drivers/nvfx/nvfx_surface.c
+++ b/src/gallium/drivers/nvfx/nvfx_surface.c
@@ -47,6 +47,7 @@ static INLINE void
 nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format)
 {
 	unsigned bits = util_format_get_blocksizebits(format);
+	unsigned shift = 0;
 	switch(bits)
 	{
 	case 8:
@@ -58,39 +59,20 @@ nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format)
 	case 32:
 		rgn->bpps = 2;
 		break;
-	default:
-		{
-			int shift;
-			assert(util_is_power_of_two(bits));
-			shift = util_logbase2(bits) - 3;
-			assert(shift >= 2);
-			rgn->bpps = 2;
-			shift -= 2;
-
-			rgn->x = util_format_get_nblocksx(format, rgn->x) << shift;
-			rgn->y = util_format_get_nblocksy(format, rgn->y);
-		}
+	case 64:
+		rgn->bpps = 2;
+		shift = 1;
+		break;
+	case 128:
+		rgn->bpps = 2;
+		shift = 2;
+		break;
 	}
-}
 
-static INLINE void
-nvfx_region_fixup_swizzled(struct nv04_region* rgn, unsigned zslice, unsigned width, unsigned height, unsigned depth)
-{
-	// TODO: move this code to surface creation?
-	if((depth <= 1) && (height <= 1 || width <= 2))
-		rgn->pitch = width << rgn->bpps;
-	else if(depth > 1 && height <= 2 && width <= 2)
-	{
-		rgn->pitch = width << rgn->bpps;
-		rgn->offset += (zslice * width * height) << rgn->bpps;
-	}
-	else
-	{
-		rgn->pitch = 0;
-		rgn->z = zslice;
-		rgn->w = width;
-		rgn->h = height;
-		rgn->d = depth;
+	if(shift) {
+		rgn->x = util_format_get_nblocksx(format, rgn->x) << shift;
+		rgn->y = util_format_get_nblocksy(format, rgn->y);
+		rgn->w <<= shift;
 	}
 }
 
@@ -100,7 +82,6 @@ nvfx_region_init_for_surface(struct nv04_region* rgn, struct nvfx_surface* surf,
 	rgn->x = x;
 	rgn->y = y;
 	rgn->z = 0;
-	nvfx_region_set_format(rgn, surf->base.base.format);
 
 	if(surf->temp)
 	{
@@ -113,11 +94,22 @@ nvfx_region_init_for_surface(struct nv04_region* rgn, struct nvfx_surface* surf,
 	} else {
 		rgn->bo = ((struct nvfx_resource*)surf->base.base.texture)->bo;
 		rgn->offset = surf->base.base.offset;
-		rgn->pitch = surf->pitch;
 
-	        if(!(surf->base.base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR))
-		        nvfx_region_fixup_swizzled(rgn, surf->base.base.zslice, surf->base.base.width, surf->base.base.height, u_minify(surf->base.base.texture->depth0, surf->base.base.level));
+		if(surf->base.base.texture->flags & NVFX_RESOURCE_FLAG_LINEAR)
+			rgn->pitch = surf->pitch;
+	        else
+	        {
+		        rgn->pitch = 0;
+		        rgn->z = surf->base.base.zslice;
+		        rgn->w = surf->base.base.width;
+		        rgn->h = surf->base.base.height;
+		        rgn->d = u_minify(surf->base.base.texture->depth0, surf->base.base.level);
+	        }
 	}
+
+	nvfx_region_set_format(rgn, surf->base.base.format);
+	if(!rgn->pitch)
+		nv04_region_try_to_linearize(rgn);
 }
 
 static INLINE void
@@ -135,14 +127,26 @@ nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource*
 
 	rgn->bo = ((struct nvfx_resource*)pt)->bo;
 	rgn->offset = nvfx_subresource_offset(pt, sub.face, sub.level, z);
-	rgn->pitch = nvfx_subresource_pitch(pt, sub.level);
 	rgn->x = x;
 	rgn->y = y;
-	rgn->z = 0;
+
+	if(pt->flags & NVFX_RESOURCE_FLAG_LINEAR)
+	{
+		rgn->pitch = nvfx_subresource_pitch(pt, sub.level);
+		rgn->z = 0;
+	}
+	else
+	{
+		rgn->pitch = 0;
+		rgn->z = z;
+		rgn->w = u_minify(pt->width0, sub.level);
+		rgn->h = u_minify(pt->height0, sub.level);
+		rgn->d = u_minify(pt->depth0, sub.level);
+	}
 
 	nvfx_region_set_format(rgn, pt->format);
-	if(!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR))
-		nvfx_region_fixup_swizzled(rgn, z, u_minify(pt->width0, sub.level), u_minify(pt->height0, sub.level), u_minify(pt->depth0, sub.level));
+	if(!rgn->pitch)
+		nv04_region_try_to_linearize(rgn);
 }
 
 // TODO: actually test this for all formats, it's probably wrong for some...




More information about the mesa-commit mailing list