Mesa (master): r300g: added support for 3D textures

Joakim Sindholt jsindholt at kemper.freedesktop.org
Sun Oct 25 07:08:47 UTC 2009


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

Author: Marek Olšák <maraeo at gmail.com>
Date:   Sun Oct 25 05:05:27 2009 +0100

r300g: added support for 3D textures

Mipmaps not tested. Also, I am not sure why piglit/texturing/tex3d needs
to have color tolerance +-1 to pass. The classic Mesa driver doesn't
need that.

---

 src/gallium/drivers/r300/r300_context.h |    3 ++
 src/gallium/drivers/r300/r300_screen.c  |   59 +++++++++----------------------
 src/gallium/drivers/r300/r300_texture.c |   39 ++++++++++++++------
 src/gallium/drivers/r300/r300_texture.h |    3 ++
 4 files changed, 51 insertions(+), 53 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 30b80fa..4d73567 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -181,6 +181,9 @@ struct r300_texture {
     /* Offsets into the buffer. */
     unsigned offset[PIPE_MAX_TEXTURE_LEVELS];
 
+    /* Size of one zslice or face based on the texture target */
+    unsigned layer_size[PIPE_MAX_TEXTURE_LEVELS];
+
     /**
      * If non-zero, override the natural texture layout with
      * a custom stride (in bytes).
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index 1d9f91d..f581f0c 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -119,32 +119,13 @@ static int r300_get_param(struct pipe_screen* pscreen, int param)
         case PIPE_CAP_TEXTURE_SHADOW_MAP:
             return 1;
         case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
-            if (r300screen->caps->is_r500) {
-                /* 13 == 4096x4096 */
-                return 13;
-            } else {
-                /* 12 == 2048x2048 */
-                return 12;
-            }
         case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
-            /* So, technically, the limit is the same as above, but some math
-             * shows why this is silly. Assuming RGBA, 4cpp, we can see that
-             * 4096*4096*4096 = 64.0 GiB exactly, so it's not exactly
-             * practical. However, if at some point a game really wants this,
-             * then we can remove or raise this limit. */
-            if (r300screen->caps->is_r500) {
-                /* 9 == 256x256x256 */
-                return 9;
-            } else {
-                /* 8 == 128*128*128 */
-                return 8;
-            }
         case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
             if (r300screen->caps->is_r500) {
-                /* 13 == 4096x4096 */
+                /* 13 == 4096 */
                 return 13;
             } else {
-                /* 12 == 2048x2048 */
+                /* 12 == 2048 */
                 return 12;
             }
         case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
@@ -191,8 +172,8 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param)
     }
 }
 
-static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage,
-                                   boolean is_r500)
+static boolean check_tex_format(enum pipe_format format, uint32_t usage,
+                                boolean is_r500)
 {
     uint32_t retval = 0;
 
@@ -286,7 +267,6 @@ static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage,
     return (retval >= usage);
 }
 
-/* XXX moar targets */
 static boolean r300_is_format_supported(struct pipe_screen* pscreen,
                                         enum pipe_format format,
                                         enum pipe_texture_target target,
@@ -294,15 +274,17 @@ static boolean r300_is_format_supported(struct pipe_screen* pscreen,
                                         unsigned geom_flags)
 {
     switch (target) {
+        case PIPE_TEXTURE_1D:   /* handle 1D textures as 2D ones */
         case PIPE_TEXTURE_2D:
-            return check_tex_2d_format(format, tex_usage,
-                r300_screen(pscreen)->caps->is_r500);
-        case PIPE_TEXTURE_1D:
         case PIPE_TEXTURE_3D:
+            return check_tex_format(format, tex_usage,
+                r300_screen(pscreen)->caps->is_r500);
+
         case PIPE_TEXTURE_CUBE:
             debug_printf("r300: Implementation error: Unsupported format "
                     "target: %d\n", target);
             break;
+
         default:
             debug_printf("r300: Fatal: This is not a format target: %d\n",
                 target);
@@ -322,22 +304,9 @@ r300_get_tex_transfer(struct pipe_screen *screen,
 {
     struct r300_texture *tex = (struct r300_texture *)texture;
     struct r300_transfer *trans;
-    unsigned offset = 0;  /* in bytes */
+    unsigned offset;
 
-    /* XXX Add support for these things */
-    if (texture->target == PIPE_TEXTURE_CUBE) {
-        debug_printf("PIPE_TEXTURE_CUBE is not yet supported.\n");
-        /* offset = tex->image_offset[level][face]; */
-    }
-    else if (texture->target == PIPE_TEXTURE_3D) {
-        debug_printf("PIPE_TEXTURE_3D is not yet supported.\n");
-        /* offset = tex->image_offset[level][zslice]; */
-    }
-    else {
-        offset = tex->offset[level];
-        assert(face == 0);
-        assert(zslice == 0);
-    }
+    offset = r300_texture_get_offset(tex, level, zslice, face);  /* in bytes */
 
     trans = CALLOC_STRUCT(r300_transfer);
     if (trans) {
@@ -352,6 +321,12 @@ r300_get_tex_transfer(struct pipe_screen *screen,
         trans->transfer.nblocksy = texture->nblocksy[level];
         trans->transfer.stride = r300_texture_get_stride(tex, level);
         trans->transfer.usage = usage;
+
+        /* XXX not sure whether it's required to set these two,
+               the driver doesn't use them */
+        trans->transfer.zslice = zslice;
+        trans->transfer.face = face;
+
         trans->offset = offset;
     }
     return &trans->transfer;
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 3c8ff24..37c7910 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -36,7 +36,7 @@ static void r300_setup_texture_state(struct r300_texture* tex)
     state->format0 = R300_TX_WIDTH((pt->width[0] - 1) & 0x7ff) |
         R300_TX_HEIGHT((pt->height[0] - 1) & 0x7ff) |
         R300_TX_DEPTH(util_logbase2(pt->depth[0]) & 0xf) |
-        R300_TX_NUM_LEVELS(pt->last_level) |
+        R300_TX_NUM_LEVELS(pt->last_level & 0xf) |
         R300_TX_PITCH_EN;
 
     /* XXX */
@@ -48,7 +48,8 @@ static void r300_setup_texture_state(struct r300_texture* tex)
         state->format1 |= R300_TX_FORMAT_3D;
     }
 
-    state->format2 = (r300_texture_get_stride(tex, 0) / pt->block.size) - 1;
+    state->format2 = ((r300_texture_get_stride(tex, 0) / pt->block.size) - 1)
+                     & 0x1fff;
 
     /* Don't worry about accidentally setting this bit on non-r500;
      * the kernel should catch it. */
@@ -63,6 +64,26 @@ static void r300_setup_texture_state(struct r300_texture* tex)
 		 pt->width[0], pt->height[0], pt->last_level);
 }
 
+unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
+                                 unsigned zslice, unsigned face)
+{
+    unsigned offset = tex->offset[level];
+
+    switch (tex->tex.target) {
+        case PIPE_TEXTURE_3D:
+            assert(face == 0);
+            return offset + zslice * tex->layer_size[level];
+
+        case PIPE_TEXTURE_CUBE:
+            assert(zslice == 0);
+            return offset + face * tex->layer_size[level];
+
+        default:
+            assert(zslice == 0 && face == 0);
+            return offset;
+    }
+}
+
 /**
  * Return the stride, in bytes, of the texture images of the given texture
  * at the given level.
@@ -84,7 +105,7 @@ unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level)
 static void r300_setup_miptree(struct r300_texture* tex)
 {
     struct pipe_texture* base = &tex->tex;
-    int stride, size;
+    int stride, size, layer_size;
     int i;
 
     for (i = 0; i <= base->last_level; i++) {
@@ -98,10 +119,12 @@ static void r300_setup_miptree(struct r300_texture* tex)
         base->nblocksy[i] = pf_get_nblocksy(&base->block, base->height[i]);
 
         stride = r300_texture_get_stride(tex, i);
-        size = stride * base->nblocksy[i] * base->depth[i];
+        layer_size = stride * base->nblocksy[i];
+        size = layer_size * base->depth[i];
 
         tex->offset[i] = align(tex->size, 32);
         tex->size = tex->offset[i] + size;
+        tex->layer_size[i] = layer_size;
 
         debug_printf("r300: Texture miptree: Level %d "
                 "(%dx%dx%d px, pitch %d bytes)\n",
@@ -161,8 +184,7 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
     struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface);
     unsigned offset;
 
-    /* XXX this is certainly dependent on tex target */
-    offset = tex->offset[level];
+    offset = r300_texture_get_offset(tex, level, zslice, face);
 
     if (surface) {
         pipe_reference_init(&surface->reference, 1);
@@ -191,11 +213,6 @@ static struct pipe_texture*
 {
     struct r300_texture* tex;
 
-    if (base->target != PIPE_TEXTURE_2D ||
-        base->depth[0] != 1) {
-        return NULL;
-    }
-
     tex = CALLOC_STRUCT(r300_texture);
     if (!tex) {
         return NULL;
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index 55d1a0a..35e06a9 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -33,6 +33,9 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen);
 
 unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level);
 
+unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
+                                 unsigned zslice, unsigned face);
+
 /* Note the signature of R300_EASY_TX_FORMAT(A, R, G, B, FORMAT)... */
 static INLINE uint32_t r300_translate_texformat(enum pipe_format format)
 {




More information about the mesa-commit mailing list