nv50: fix mipmap offsets and tiling
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Fri, 14 Aug 2009 16:23:55 +0000 (18:23 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Fri, 14 Aug 2009 16:23:55 +0000 (18:23 +0200)
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
src/gallium/drivers/nv50/nv50_miptree.c
src/gallium/drivers/nv50/nv50_transfer.c

index 9b8cc4d37d03397087b175bea37e17ebb055b608..5cbc2c8f823415d90032ed26f68cb441d269ac53 100644 (file)
@@ -71,6 +71,7 @@ struct nv50_sampler_stateobj {
 struct nv50_miptree_level {
        int *image_offset;
        unsigned pitch;
+       unsigned tile_mode;
 };
 
 struct nv50_miptree {
index c8392799ed8111cb156bde4038f5268c28f02f6f..7493ef3af2a670df6ae8977d23e0dbfe9c20889d 100644 (file)
@@ -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;
index 6ff375951e4f8de6b2b9cb26b5e6a27861dbb63b..1c47c30968ea27313991bb25246462475d086c00 100644 (file)
@@ -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);
        }