aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv50/nv50_transfer.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_transfer.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_transfer.c')
-rw-r--r--src/gallium/drivers/nv50/nv50_transfer.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
index 9c008090b8d..ea61357aaa6 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -12,6 +12,7 @@ struct nv50_transfer {
int level_pitch;
int level_width;
int level_height;
+ int level_depth;
int level_x;
int level_y;
};
@@ -20,10 +21,10 @@ static void
nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
struct nouveau_bo *src_bo, unsigned src_offset,
int src_pitch, unsigned src_tile_mode,
- int sx, int sy, int sw, int sh,
+ int sx, int sy, int sw, int sh, int sd,
struct nouveau_bo *dst_bo, unsigned dst_offset,
int dst_pitch, unsigned dst_tile_mode,
- int dx, int dy, int dw, int dh,
+ int dx, int dy, int dw, int dh, int dd,
int cpp, int width, int height,
unsigned src_reloc, unsigned dst_reloc)
{
@@ -51,7 +52,7 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
OUT_RING (chan, src_tile_mode << 4);
OUT_RING (chan, sw * cpp);
OUT_RING (chan, sh);
- OUT_RING (chan, 1);
+ OUT_RING (chan, sd);
OUT_RING (chan, 0);
}
@@ -70,7 +71,7 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
OUT_RING (chan, dst_tile_mode << 4);
OUT_RING (chan, dw * cpp);
OUT_RING (chan, dh);
- OUT_RING (chan, 1);
+ OUT_RING (chan, dd);
OUT_RING (chan, 0);
}
@@ -114,6 +115,20 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen,
}
}
+static INLINE unsigned
+get_zslice_offset(unsigned tile_mode, unsigned z, unsigned pitch, unsigned ny)
+{
+ unsigned tile_h = get_tile_height(tile_mode);
+ unsigned tile_d = get_tile_depth(tile_mode);
+
+ /* pitch_2d == to next slice within this volume-tile */
+ /* pitch_3d == to next slice in next 2D array of blocks */
+ unsigned pitch_2d = tile_h * 64;
+ unsigned pitch_3d = tile_d * align(ny, tile_h) * pitch;
+
+ return (z % tile_d) * pitch_2d + (z / tile_d) * pitch_3d;
+}
+
static struct pipe_transfer *
nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
unsigned face, unsigned level, unsigned zslice,
@@ -129,9 +144,6 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
if (pt->target == PIPE_TEXTURE_CUBE)
image = face;
- else
- if (pt->target == PIPE_TEXTURE_3D)
- image = zslice;
tx = CALLOC_STRUCT(nv50_transfer);
if (!tx)
@@ -157,6 +169,7 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
tx->level_pitch = lvl->pitch;
tx->level_width = mt->base.base.width[level];
tx->level_height = mt->base.base.height[level];
+ tx->level_depth = mt->base.base.depth[level];
tx->level_offset = lvl->image_offset[image];
tx->level_tiling = lvl->tile_mode;
tx->level_x = pf_get_nblocksx(&tx->base.block, x);
@@ -168,6 +181,11 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
return NULL;
}
+ if (pt->target == PIPE_TEXTURE_3D)
+ tx->level_offset += get_zslice_offset(lvl->tile_mode, zslice,
+ lvl->pitch,
+ tx->base.nblocksy);
+
if (usage & PIPE_TRANSFER_READ) {
nx = pf_get_nblocksx(&tx->base.block, tx->base.width);
ny = pf_get_nblocksy(&tx->base.block, tx->base.height);
@@ -176,10 +194,11 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
tx->level_pitch, tx->level_tiling,
x, y,
tx->base.nblocksx, tx->base.nblocksy,
+ tx->level_depth,
tx->bo, 0,
tx->base.stride, tx->bo->tile_mode,
0, 0,
- tx->base.nblocksx, tx->base.nblocksy,
+ tx->base.nblocksx, tx->base.nblocksy, 1,
tx->base.block.size, nx, ny,
NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
NOUVEAU_BO_GART);
@@ -199,14 +218,16 @@ nv50_transfer_del(struct pipe_transfer *ptx)
if (ptx->usage & PIPE_TRANSFER_WRITE) {
struct pipe_screen *pscreen = ptx->texture->screen;
+
nv50_transfer_rect_m2mf(pscreen, tx->bo, 0,
tx->base.stride, tx->bo->tile_mode,
0, 0,
- tx->base.nblocksx, tx->base.nblocksy,
+ tx->base.nblocksx, tx->base.nblocksy, 1,
mt->base.bo, tx->level_offset,
tx->level_pitch, tx->level_tiling,
tx->level_x, tx->level_y,
tx->base.nblocksx, tx->base.nblocksy,
+ tx->level_depth,
tx->base.block.size, nx, ny,
NOUVEAU_BO_GART, NOUVEAU_BO_VRAM |
NOUVEAU_BO_GART);