Mesa (master): r600g: add support for s3tc formats.

Dave Airlie airlied at kemper.freedesktop.org
Tue Feb 15 04:39:25 UTC 2011


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

Author: Dave Airlie <airlied at redhat.com>
Date:   Fri Feb 11 13:42:52 2011 +1000

r600g: add support for s3tc formats.

On r600, s3tc formats require a 1D tiled texture format,
so we have to do uploads using a blit, via the 64-bit and 128-bit formats

Based on the r600c code we use a 64 and 128-bit type to do the
blits.

Still requires R600_ENABLE_S3TC until the kernel fixes are in,
this has only been tested on evergreen where the kernel doesn't
yet get in the way.

---

 src/gallium/drivers/r600/r600_blit.c    |   60 +++++++++++++++++++++++++++++++
 src/gallium/drivers/r600/r600_pipe.c    |    2 +
 src/gallium/drivers/r600/r600_texture.c |   13 +++++++
 3 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index fbade99..6687d09 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -219,6 +219,47 @@ static void r600_hw_copy_region(struct pipe_context *ctx,
 	r600_blitter_end(ctx);
 }
 
+struct texture_orig_info {
+	unsigned format;
+	unsigned width0;
+	unsigned height0;
+};
+
+static void r600_s3tc_to_blittable(struct pipe_resource *tex,
+				   unsigned level,
+				   struct texture_orig_info *orig)
+{
+	unsigned pixsize = util_format_get_blocksize(tex->format);
+	int new_format;
+	int new_height, new_width;
+
+	orig->format = tex->format;
+	orig->width0 = tex->width0;
+	orig->height0 = tex->height0;
+
+	if (pixsize == 8)
+		new_format = PIPE_FORMAT_R16G16B16A16_UNORM; /* 64-bit block */
+	else
+		new_format = PIPE_FORMAT_R32G32B32A32_UNORM; /* 128-bit block */
+
+	new_width = util_format_get_nblocksx(tex->format, orig->width0);
+	new_height = util_format_get_nblocksy(tex->format, orig->height0);
+
+	tex->width0 = new_width;
+	tex->height0 = new_height;
+	tex->format = new_format;
+
+}
+
+static void r600_reset_blittable_to_s3tc(struct pipe_resource *tex,
+					 unsigned level,
+					 struct texture_orig_info *orig)
+{
+	tex->format = orig->format;
+	tex->width0 = orig->width0;
+	tex->height0 = orig->height0;
+}
+
 static void r600_resource_copy_region(struct pipe_context *ctx,
 				      struct pipe_resource *dst,
 				      unsigned dst_level,
@@ -228,13 +269,32 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
 				      const struct pipe_box *src_box)
 {
 	struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src;
+	struct texture_orig_info orig_info[2];
+	boolean restore_orig[2];
 
 	if (rsrc->depth && !rsrc->is_flushing_texture)
 		r600_texture_depth_flush(ctx, src, FALSE);
 
+	restore_orig[0] = restore_orig[1] = FALSE;
+
+	if (util_format_is_s3tc(src->format)) {
+		r600_s3tc_to_blittable(src, src_level, &orig_info[0]);
+		restore_orig[0] = TRUE;
+	}
+
+	if (util_format_is_s3tc(dst->format)) {
+		r600_s3tc_to_blittable(dst, dst_level, &orig_info[1]);
+		restore_orig[1] = TRUE;
+	}
+
 	r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
 			    src, src_level, src_box);
 
+	if (restore_orig[0])
+		r600_reset_blittable_to_s3tc(src, src_level, &orig_info[0]);
+
+	if (restore_orig[1])
+		r600_reset_blittable_to_s3tc(dst, dst_level, &orig_info[1]);
 }
 
 void r600_init_blit_functions(struct r600_pipe_context *rctx)
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index f9e8e76..9d6c9bd 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -30,6 +30,7 @@
 #include <tgsi/tgsi_util.h>
 #include <util/u_blitter.h>
 #include <util/u_double_list.h>
+#include <util/u_format_s3tc.h>
 #include <util/u_transfer.h>
 #include <util/u_surface.h>
 #include <util/u_pack_color.h>
@@ -502,6 +503,7 @@ struct pipe_screen *r600_screen_create(struct radeon *radeon)
 	r600_init_screen_resource_functions(&rscreen->screen);
 
 	rscreen->tiling_info = r600_get_tiling_info(radeon);
+	util_format_s3tc_init();
 
 	util_slab_create(&rscreen->pool_buffers,
 			 sizeof(struct r600_resource_buffer), 64,
diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c
index db39383..dd14143 100644
--- a/src/gallium/drivers/r600/r600_texture.c
+++ b/src/gallium/drivers/r600/r600_texture.c
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <pipe/p_screen.h>
 #include <util/u_format.h>
+#include <util/u_format_s3tc.h>
 #include <util/u_math.h>
 #include <util/u_inlines.h>
 #include <util/u_memory.h>
@@ -289,6 +290,10 @@ static boolean permit_hardware_blit(struct pipe_screen *screen,
 	else
 		bind = PIPE_BIND_RENDER_TARGET;
 
+	/* hackaround for S3TC */
+	if (util_format_is_s3tc(res->format))
+		return TRUE;
+	    
 	if (!screen->is_format_supported(screen,
 				res->format,
 				res->target,
@@ -417,6 +422,10 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
 		}
 	}
 
+	if (!(templ->flags & R600_RESOURCE_FLAG_TRANSFER) &&
+	    util_format_is_s3tc(templ->format))
+		array_mode = V_038000_ARRAY_1D_TILED_THIN1;
+
 	return (struct pipe_resource *)r600_texture_create_object(screen, templ, array_mode,
 								  0, 0, NULL);
 
@@ -869,6 +878,10 @@ uint32_t r600_translate_texformat(enum pipe_format format,
 		if (!r600_enable_s3tc)
 			goto out_unknown;
 
+		if (!util_format_s3tc_enabled) {
+			goto out_unknown;
+		}
+
 		switch (format) {
 		case PIPE_FORMAT_DXT1_RGB:
 		case PIPE_FORMAT_DXT1_RGBA:




More information about the mesa-commit mailing list