Mesa (master): nv50: fix mipmap offsets and tiling

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Fri Aug 14 16:31:36 UTC 2009


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

Author: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
Date:   Fri Aug 14 18:23:55 2009 +0200

nv50: fix mipmap offsets and tiling

The hardware expects a texture's tile mode to change with
the mipmap level.
Also, only multiply by block size once to obtain size.

---

 src/gallium/drivers/nv50/nv50_context.h  |    1 +
 src/gallium/drivers/nv50/nv50_miptree.c  |   11 +++++++-
 src/gallium/drivers/nv50/nv50_transfer.c |   39 ++++++++++++++++++-----------
 3 files changed, 34 insertions(+), 17 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index 9b8cc4d..5cbc2c8 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -71,6 +71,7 @@ struct nv50_sampler_stateobj {
 struct nv50_miptree_level {
 	int *image_offset;
 	unsigned pitch;
+	unsigned tile_mode;
 };
 
 struct nv50_miptree {
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index c839279..7493ef3 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -87,20 +87,27 @@ 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->width[l] * pt->block.size, 64);
+		lvl->tile_mode = tile_mode;
 
 		width = MAX2(1, width >> 1);
 		height = MAX2(1, height >> 1);
 		depth = MAX2(1, depth >> 1);
+
+		if (tile_mode && height <= (tile_h >> 1)) {
+			tile_mode--;
+			tile_h >>= 1;
+		}
 	}
 
 	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;
+			tile_h = 1 << (lvl->tile_mode + 2);
 
 			size  = align(pt->width[l], 8) * pt->block.size;
 			size  = align(size, 64);
-			size *= align(pt->height[l], tile_h) * pt->block.size;
+			size *= align(pt->height[l], tile_h);
 
 			lvl->image_offset[i] = mt->total_size;
 
@@ -109,7 +116,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
 	}
 
 	ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size,
-				  tile_mode, tile_flags, &mt->bo);
+				  mt->level[0].tile_mode, tile_flags, &mt->bo);
 	if (ret) {
 		FREE(mt);
 		return NULL;
diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
index 6ff3759..1c47c30 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -8,6 +8,7 @@ struct nv50_transfer {
 	struct pipe_transfer base;
 	struct nouveau_bo *bo;
 	unsigned level_offset;
+	unsigned level_tiling;
 	int level_pitch;
 	int level_width;
 	int level_height;
@@ -16,11 +17,14 @@ struct nv50_transfer {
 };
 
 static void
-nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct nouveau_bo *src_bo,
-			unsigned src_offset, int src_pitch, int sx, int sy,
-			int sw, int sh, struct nouveau_bo *dst_bo,
-			unsigned dst_offset, int dst_pitch, int dx, int dy,
-			int dw, int dh, int cpp, int width, int height,
+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,
+			struct nouveau_bo *dst_bo, unsigned dst_offset,
+			int dst_pitch, unsigned dst_tile_mode,
+			int dx, int dy, int dw, int dh,
+			int cpp, int width, int height,
 			unsigned src_reloc, unsigned dst_reloc)
 {
 	struct nv50_screen *screen = nv50_screen(pscreen);
@@ -41,7 +45,7 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct nouveau_bo *src_bo,
 	} else {
 		BEGIN_RING(chan, m2mf, 0x0200, 6);
 		OUT_RING  (chan, 0);
-		OUT_RING  (chan, src_bo->tile_mode << 4);
+		OUT_RING  (chan, src_tile_mode << 4);
 		OUT_RING  (chan, sw * cpp);
 		OUT_RING  (chan, sh);
 		OUT_RING  (chan, 1);
@@ -57,7 +61,7 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct nouveau_bo *src_bo,
 	} else {
 		BEGIN_RING(chan, m2mf, 0x021c, 6);
 		OUT_RING  (chan, 0);
-		OUT_RING  (chan, dst_bo->tile_mode << 4);
+		OUT_RING  (chan, dst_tile_mode << 4);
 		OUT_RING  (chan, dw * cpp);
 		OUT_RING  (chan, dh);
 		OUT_RING  (chan, 1);
@@ -136,6 +140,7 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
 	tx->level_width = mt->base.width[level];
 	tx->level_height = mt->base.height[level];
 	tx->level_offset = lvl->image_offset[image];
+	tx->level_tiling = lvl->tile_mode;
 	tx->level_x = x;
 	tx->level_y = y;
 	ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
@@ -147,9 +152,11 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
 
 	if (usage != PIPE_TRANSFER_WRITE) {
 		nv50_transfer_rect_m2mf(pscreen, mt->bo, tx->level_offset,
-					tx->level_pitch, x, y, tx->level_width,
-					tx->level_height, tx->bo, 0,
-					tx->base.stride, 0, 0,
+					tx->level_pitch, tx->level_tiling,
+					x, y,
+					tx->level_width, tx->level_height,
+					tx->bo, 0, tx->base.stride,
+					tx->bo->tile_mode, 0, 0,
 					tx->base.width, tx->base.height,
 					tx->base.block.size, w, h,
 					NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
@@ -168,12 +175,14 @@ nv50_transfer_del(struct pipe_transfer *ptx)
 	if (ptx->usage != PIPE_TRANSFER_READ) {
 		struct pipe_screen *pscreen = ptx->texture->screen;
 		nv50_transfer_rect_m2mf(pscreen, tx->bo, 0, tx->base.stride,
-					0, 0, tx->base.width, tx->base.height,
-					mt->bo, tx->level_offset,
-					tx->level_pitch, tx->level_x,
-					tx->level_y, tx->level_width,
-					tx->level_height, tx->base.block.size,
+					tx->bo->tile_mode, 0, 0,
 					tx->base.width, tx->base.height,
+					mt->bo, tx->level_offset,
+					tx->level_pitch, tx->level_tiling,
+					tx->level_x, tx->level_y,
+					tx->level_width, tx->level_height,
+					tx->base.block.size, tx->base.width,
+					tx->base.height,
 					NOUVEAU_BO_GART, NOUVEAU_BO_VRAM |
 					NOUVEAU_BO_GART);
 	}




More information about the mesa-commit mailing list