Mesa (master): nvfx: move 2D format selection logic to 2D code

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


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

Author: Luca Barbieri <luca at luca-barbieri.com>
Date:   Sat Sep  4 20:16:54 2010 +0200

nvfx: move 2D format selection logic to 2D code

---

 src/gallium/drivers/nvfx/nv04_2d.c      |   87 ++++++++++++++++++++++++-------
 src/gallium/drivers/nvfx/nv04_2d.h      |    2 +-
 src/gallium/drivers/nvfx/nvfx_surface.c |   53 +++----------------
 3 files changed, 75 insertions(+), 67 deletions(-)

diff --git a/src/gallium/drivers/nvfx/nv04_2d.c b/src/gallium/drivers/nvfx/nv04_2d.c
index bc6012f..407f435 100644
--- a/src/gallium/drivers/nvfx/nv04_2d.c
+++ b/src/gallium/drivers/nvfx/nv04_2d.c
@@ -725,15 +725,58 @@ ms:
 	nouveau_bo_unmap(dst->bo);
 }
 
+static inline int
+nv04_region_cs2d_format(struct nv04_region* rgn)
+{
+	switch(rgn->bpps) {
+	case 0:
+		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+	case 1:
+		if(rgn->one_bits >= 1)
+			return NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_X1R5G5B5;
+		else
+			return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+	case 2:
+		if(rgn->one_bits >= 8)
+			return NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_X8R8G8B8;
+		else
+			return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
+	default:
+		return -1;
+	}
+}
+
+static inline int
+nv04_region_sifm_format(struct nv04_region* rgn)
+{
+	switch(rgn->bpps) {
+	case 0:
+		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8;
+	case 1:
+		if(rgn->one_bits >= 1)
+			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X1R5G5B5;
+		else
+			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
+	case 2:
+		if(rgn->one_bits >= 8)
+			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
+		else
+			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
+	default:
+		return -1;
+	}
+}
 static void
 nv04_region_copy_swizzle(struct nv04_2d_context *ctx,
 			  struct nv04_region* dst,
 			  struct nv04_region* src,
-			  int w, int h, int cs2d_format, int sifm_format)
+			  int w, int h)
 {
 	struct nouveau_channel *chan = ctx->swzsurf->channel;
 	struct nouveau_grobj *swzsurf = ctx->swzsurf;
 	struct nouveau_grobj *sifm = ctx->sifm;
+	int cs2d_format = nv04_region_cs2d_format(dst);
+	int sifm_format = nv04_region_sifm_format(src);
 	/* Max width & height may not be the same on all HW, but must be POT */
 	unsigned max_shift = 10;
 	unsigned cw = 1 << max_shift;
@@ -951,11 +994,12 @@ nv04_region_copy_m2mf(struct nv04_2d_context *ctx, struct nv04_region *dst, stru
 }
 
 static inline void
-nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src, int w, int h, int format)
+nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src, int w, int h)
 {
 	struct nouveau_channel *chan = ctx->surf2d->channel;
 	struct nouveau_grobj *surf2d = ctx->surf2d;
 	struct nouveau_grobj *blit = ctx->blit;
+	int cs2d_format = nv04_region_cs2d_format(dst);
 
 #ifdef NV04_REGION_DEBUG
 	fprintf(stderr, "\tRGN_COPY_BLIT [%i, %i: %i] ", w, h, dst->bpps);
@@ -976,7 +1020,7 @@ nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, stru
 	OUT_RELOCo(chan, src->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
 	OUT_RELOCo(chan, dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
 	BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
-	OUT_RING  (chan, format);
+	OUT_RING  (chan, cs2d_format);
 	OUT_RING  (chan, (dst->pitch << 16) | src->pitch);
 	OUT_RELOCl(chan, src->bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
 	OUT_RELOCl(chan, dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
@@ -1003,12 +1047,12 @@ nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, stru
 // dst and src may be modified, and the possibly modified version should be passed to nv04_region_cpu if necessary
 int
 nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src,
-		int w, int h, int cs2d_format, int sifm_format, int dst_to_gpu, int src_on_gpu)
+		int w, int h, int dst_to_gpu, int src_on_gpu)
 {
 	assert(src->bpps == dst->bpps);
 
 #ifdef NV04_REGION_DEBUG
-	fprintf(stderr, "RGN_COPY%s [%i, %i: %i] ", (cs2d_format >= 0) ? "_2D" : "_NO2D", w, h, dst->bpps);
+	fprintf(stderr, "RGN_COPY [%i, %i: %i] ", w, h, dst->bpps);
 	for(int i = 0; i < 2; ++i)
 	{
 		int gpu = i ? src_on_gpu : dst_to_gpu;
@@ -1061,7 +1105,7 @@ nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct
 	{
 		if (!dst->pitch)
 		{
-			if(cs2d_format < 0 || sifm_format < 0 || !dst_to_gpu)
+			if(!dst_to_gpu)
 			{
 #ifdef NV04_REGION_DEBUG
 				fprintf(stderr, "\tCOPY_ENG3D\n");
@@ -1072,7 +1116,7 @@ nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct
 			{
 				assert(!nv04_region_align(dst, w, h, 6));
 
-				nv04_region_copy_swizzle(ctx, dst, src, w, h, cs2d_format, sifm_format);
+				nv04_region_copy_swizzle(ctx, dst, src, w, h);
 				return 0;
 			}
 		}
@@ -1081,16 +1125,20 @@ nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct
 			/* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
 			 * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
 			 * TODO: is this also true for the source? possibly not
+			 * TODO: should we just always use m2mf?
+			 * TODO: if not, add support for multiple operations to copy_blit
 			 */
 
-			if ((cs2d_format < 0)
-				|| !dst_to_gpu
+			if (!dst_to_gpu
+				|| w > 2047
+				|| h > 2047
+				|| (w & 1)
 				|| nv04_region_align(src, w, h, 6)
 				|| nv04_region_align(dst, w, h, 6)
 				)
 				nv04_region_copy_m2mf(ctx, dst, src, w, h);
 			else
-				nv04_region_copy_blit(ctx, dst, src, w, h, cs2d_format);
+				nv04_region_copy_blit(ctx, dst, src, w, h);
 
 			return 0;
 		}
@@ -1112,26 +1160,25 @@ nv04_region_fill_gdirect(struct nv04_2d_context *ctx, struct nv04_region* dst, i
 	assert(!(dst->pitch & 63) && dst->pitch);
 	nv04_region_assert(dst, w, h);
 
-	if(dst->bpps == 0)
+	switch(dst->bpps)
 	{
+	case 0:
 		gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
 		cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
-	}
-	else if(dst->bpps == 1)
-	{
+		break;
+	case 1:
 		gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
 		cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y16;
-	}
-	else if(dst->bpps == 2)
-	{
+		break;
+	case 2:
 		gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
 		cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
-	}
-	else
-	{
+		break;
+	default:
 		assert(0);
 		gdirect_format = 0;
 		cs2d_format = 0;
+		break;
 	}
 
 	MARK_RING (chan, 15, 4);
diff --git a/src/gallium/drivers/nvfx/nv04_2d.h b/src/gallium/drivers/nvfx/nv04_2d.h
index e7d872a..00ee5bc 100644
--- a/src/gallium/drivers/nvfx/nv04_2d.h
+++ b/src/gallium/drivers/nvfx/nv04_2d.h
@@ -43,6 +43,7 @@ struct nv04_region {
 	int offset;
 	unsigned pitch; // 0 -> swizzled
 	unsigned bpps; // bpp shift (0, 1, 2; 3, 4 for fp/compressed)
+	unsigned one_bits; // number of high bits read and written as ones (for "no-alpha" optimization)
 	unsigned x, y, z;
 	unsigned w, h, d;
 };
@@ -95,7 +96,6 @@ int
 nv04_region_copy_2d(struct nv04_2d_context *ctx,
 		struct nv04_region* dst, struct nv04_region* src,
 		int w, int h,
-		int cs2d_format, int sifm_format,
 		int dst_to_gpu, int src_on_gpu);
 
 int
diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c
index 0255e3f..e0c85cc 100644
--- a/src/gallium/drivers/nvfx/nvfx_surface.c
+++ b/src/gallium/drivers/nvfx/nvfx_surface.c
@@ -48,6 +48,8 @@ nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format)
 {
 	unsigned bits = util_format_get_blocksizebits(format);
 	unsigned shift = 0;
+	rgn->one_bits = 0;
+
 	switch(bits)
 	{
 	case 8:
@@ -55,9 +57,13 @@ nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format)
 		break;
 	case 16:
 		rgn->bpps = 1;
+		if(format == PIPE_FORMAT_B5G5R5X1_UNORM)
+			rgn->one_bits = 1;
 		break;
 	case 32:
 		rgn->bpps = 2;
+		if(format == PIPE_FORMAT_R8G8B8X8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM)
+			rgn->one_bits = 8;
 		break;
 	case 64:
 		rgn->bpps = 2;
@@ -149,48 +155,6 @@ nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource*
 		nv04_region_try_to_linearize(rgn);
 }
 
-// TODO: actually test this for all formats, it's probably wrong for some...
-
-static INLINE int
-nvfx_surface_format(enum pipe_format format)
-{
-	switch(util_format_get_blocksize(format)) {
-	case 1:
-		return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
-	case 2:
-		//return NV04_CONTEXT_SURFACES_2D_FORMAT_Y16;
-		return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
-	case 4:
-		//if(format == PIPE_FORMAT_B8G8R8X8_UNORM || format == PIPE_FORMAT_B8G8R8A8_UNORM)
-			return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
-		//else
-		//	return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
-	default:
-		return -1;
-	}
-}
-
-static INLINE int
-nv04_scaled_image_format(enum pipe_format format)
-{
-	switch(util_format_get_blocksize(format)) {
-	case 1:
-		return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8;
-	case 2:
-		//if(format == PIPE_FORMAT_B5G5R5A1_UNORM)
-		//	return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
-		//else
-			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
-	case 4:
-		if(format == PIPE_FORMAT_B8G8R8X8_UNORM)
-			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
-		else
-			return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
-	default:
-		return -1;
-	}
-}
-
 // don't save index buffer because blitter doesn't setit
 static struct blitter_context*
 nvfx_get_blitter(struct pipe_context* pipe, int copy)
@@ -284,10 +248,7 @@ nvfx_resource_copy_region(struct pipe_context *pipe,
 	if((!dst_to_gpu || !src_on_gpu) && small)
 		ret = -1; /* use the CPU */
 	else
-		ret = nv04_region_copy_2d(ctx, &dst, &src, w, h,
-			dstr->target == PIPE_BUFFER ? -1 : nvfx_surface_format(dstr->format),
-			dstr->target == PIPE_BUFFER ? -1 : nv04_scaled_image_format(dstr->format),
-			dst_to_gpu, src_on_gpu);
+		ret = nv04_region_copy_2d(ctx, &dst, &src, w, h, dst_to_gpu, src_on_gpu);
 	if(!ret)
 	{}
 	else if(ret > 0 && dstr->bind & PIPE_BIND_RENDER_TARGET && srcr->bind & PIPE_BIND_SAMPLER_VIEW)




More information about the mesa-commit mailing list