summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv50/nv50_miptree.c
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2009-11-03 23:19:56 +0100
committerChristoph Bumiller <[email protected]>2009-11-04 00:53:51 +0100
commit040e1d008f8f8258f1b0ee0fcdf4906e0979fb66 (patch)
tree0d4348bf43d94dfe423f1df2fb97377a47fed6b4 /src/gallium/drivers/nv50/nv50_miptree.c
parentc475079ef2d901ba4506ebd53e19419cd46793ab (diff)
nv50: add 3d texture tiling and mip-mapping
Mip-mapped 3D textures are not arrays of 2D layers with a mip-map layout like 2D textures, therefore we cannot use image_nr == depth for them. Making use of "volume tiling" modes now, the allowed modes are 0xZY where Z <= 5 and y <= 5.
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_miptree.c')
-rw-r--r--src/gallium/drivers/nv50/nv50_miptree.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index 229a59cb743..9c20c5cc282 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -26,14 +26,33 @@
#include "nv50_context.h"
+/* The restrictions in tile mode selection probably aren't necessary. */
static INLINE uint32_t
-get_tile_mode(unsigned ny)
+get_tile_mode(unsigned ny, unsigned d)
{
- if (ny > 32) return 4;
- if (ny > 16) return 3;
- if (ny > 8) return 2;
- if (ny > 4) return 1;
- return 0;
+ uint32_t tile_mode = 0x00;
+
+ if (ny > 32) tile_mode = 0x04; /* height 64 tiles */
+ else
+ if (ny > 16) tile_mode = 0x03; /* height 32 tiles */
+ else
+ if (ny > 8) tile_mode = 0x02; /* height 16 tiles */
+ else
+ if (ny > 4) tile_mode = 0x01; /* height 8 tiles */
+
+ if (d == 1)
+ return tile_mode;
+ else
+ if (tile_mode > 0x02)
+ tile_mode = 0x02;
+
+ if (d > 16 && tile_mode < 0x02)
+ return tile_mode | 0x50; /* depth 32 tiles */
+ if (d > 8) return tile_mode | 0x40; /* depth 16 tiles */
+ if (d > 4) return tile_mode | 0x30; /* depth 8 tiles */
+ if (d > 2) return tile_mode | 0x20; /* depth 4 tiles */
+
+ return tile_mode | 0x10;
}
static struct pipe_texture *
@@ -43,7 +62,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
struct pipe_texture *pt = &mt->base.base;
unsigned width = tmp->width[0], height = tmp->height[0];
- unsigned depth = tmp->depth[0];
+ unsigned depth = tmp->depth[0], image_alignment;
uint32_t tile_flags;
int ret, i, l;
@@ -67,17 +86,8 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
break;
}
- switch (pt->target) {
- case PIPE_TEXTURE_3D:
- mt->image_nr = pt->depth[0];
- break;
- case PIPE_TEXTURE_CUBE:
- mt->image_nr = 6;
- break;
- default:
- mt->image_nr = 1;
- break;
- }
+ /* XXX: texture arrays */
+ mt->image_nr = (pt->target == PIPE_TEXTURE_CUBE) ? 6 : 1;
for (l = 0; l <= pt->last_level; l++) {
struct nv50_miptree_level *lvl = &mt->level[l];
@@ -90,26 +100,35 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
lvl->image_offset = CALLOC(mt->image_nr, sizeof(int));
lvl->pitch = align(pt->nblocksx[l] * pt->block.size, 64);
- lvl->tile_mode = get_tile_mode(pt->nblocksy[l]);
+ lvl->tile_mode = get_tile_mode(pt->nblocksy[l], depth);
width = MAX2(1, width >> 1);
height = MAX2(1, height >> 1);
depth = MAX2(1, depth >> 1);
}
+ image_alignment = get_tile_height(mt->level[0].tile_mode) * 64;
+ image_alignment *= get_tile_depth(mt->level[0].tile_mode);
+
+ /* NOTE the distinction between arrays of mip-mapped 2D textures and
+ * mip-mapped 3D textures. We can't use image_nr == depth for 3D mip.
+ */
for (i = 0; i < mt->image_nr; i++) {
for (l = 0; l <= pt->last_level; l++) {
struct nv50_miptree_level *lvl = &mt->level[l];
int size;
- unsigned tile_ny = 1 << (lvl->tile_mode + 2);
+ unsigned tile_h = get_tile_height(lvl->tile_mode);
+ unsigned tile_d = get_tile_depth(lvl->tile_mode);
- size = align(pt->nblocksx[l] * pt->block.size, 64);
- size *= align(pt->nblocksy[l], tile_ny);
+ size = lvl->pitch;
+ size *= align(pt->nblocksy[l], tile_h);
+ size *= align(pt->depth[l], tile_d);
lvl->image_offset[i] = mt->total_size;
mt->total_size += size;
}
+ mt->total_size = align(mt->total_size, image_alignment);
}
ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size,