nv50: fix textures with block size != cpp
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 31 Oct 2009 19:46:59 +0000 (20:46 +0100)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Sat, 31 Oct 2009 19:51:09 +0000 (20:51 +0100)
First, using width * block size as pitch is evidently
wrong if a block contains more than 1 texel.

For tiled textures, since a block occupies a contiguous
area of memory, y addressing in m2mf has to be done by
block index, not the y coordinate itself.

This should fix compressed textures.

src/gallium/drivers/nv50/nv50_miptree.c
src/gallium/drivers/nv50/nv50_transfer.c

index 93479a0314a2c2279ead0ea25183d44166fad27b..229a59cb743781a23513375a567fa6ab5f7ffcfa 100644 (file)
 
 #include "nv50_context.h"
 
+static INLINE uint32_t
+get_tile_mode(unsigned ny)
+{
+       if (ny > 32) return 4;
+       if (ny > 16) return 3;
+       if (ny >  8) return 2;
+       if (ny >  4) return 1;
+       return 0;
+}
+
 static struct pipe_texture *
 nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
 {
@@ -34,7 +44,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
        struct pipe_texture *pt = &mt->base.base;
        unsigned width = tmp->width[0], height = tmp->height[0];
        unsigned depth = tmp->depth[0];
-       uint32_t tile_mode, tile_flags, tile_h;
+       uint32_t tile_flags;
        int ret, i, l;
 
        *pt = *tmp;
@@ -57,13 +67,6 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
                break;
        }
 
-       if      (pt->height[0] > 32) tile_mode = 4;
-       else if (pt->height[0] > 16) tile_mode = 3;
-       else if (pt->height[0] >  8) tile_mode = 2;
-       else if (pt->height[0] >  4) tile_mode = 1;
-       else                         tile_mode = 0;
-       tile_h = 1 << (tile_mode + 2);
-
        switch (pt->target) {
        case PIPE_TEXTURE_3D:
                mt->image_nr = pt->depth[0];
@@ -86,28 +89,22 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
                pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);
 
                lvl->image_offset = CALLOC(mt->image_nr, sizeof(int));
-               lvl->pitch = align(pt->width[l] * pt->block.size, 64);
-               lvl->tile_mode = tile_mode;
+               lvl->pitch = align(pt->nblocksx[l] * pt->block.size, 64);
+               lvl->tile_mode = get_tile_mode(pt->nblocksy[l]);
 
                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);
+                       unsigned tile_ny = 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);
+                       size  = align(pt->nblocksx[l] * pt->block.size, 64);
+                       size *= align(pt->nblocksy[l], tile_ny);
 
                        lvl->image_offset[i] = mt->total_size;
 
index f1eb672336688649a6126634f3937071123f3ac2..9c008090b8df733d5a9b7b258a5bea747405eeba 100644 (file)
@@ -124,7 +124,7 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
        struct nv50_miptree *mt = nv50_miptree(pt);
        struct nv50_miptree_level *lvl = &mt->level[level];
        struct nv50_transfer *tx;
-       unsigned image = 0;
+       unsigned nx, ny, image = 0;
        int ret;
 
        if (pt->target == PIPE_TEXTURE_CUBE)
@@ -142,9 +142,16 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
        tx->base.width = w;
        tx->base.height = h;
        tx->base.block = pt->block;
-       tx->base.nblocksx = pt->nblocksx[level];
-       tx->base.nblocksy = pt->nblocksy[level];
-       tx->base.stride = (w * pt->block.size);
+       if (!pt->nblocksx[level]) {
+               tx->base.nblocksx = pf_get_nblocksx(&pt->block,
+                                                   pt->width[level]);
+               tx->base.nblocksy = pf_get_nblocksy(&pt->block,
+                                                   pt->height[level]);
+       } else {
+               tx->base.nblocksx = pt->nblocksx[level];
+               tx->base.nblocksy = pt->nblocksy[level];
+       }
+       tx->base.stride = tx->base.nblocksx * pt->block.size;
        tx->base.usage = usage;
 
        tx->level_pitch = lvl->pitch;
@@ -152,24 +159,28 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt,
        tx->level_height = mt->base.base.height[level];
        tx->level_offset = lvl->image_offset[image];
        tx->level_tiling = lvl->tile_mode;
-       tx->level_x = x;
-       tx->level_y = y;
+       tx->level_x = pf_get_nblocksx(&tx->base.block, x);
+       tx->level_y = pf_get_nblocksy(&tx->base.block, y);
        ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
-                            w * pt->block.size * h, &tx->bo);
+                            tx->base.nblocksy * tx->base.stride, &tx->bo);
        if (ret) {
                FREE(tx);
                return NULL;
        }
 
        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);
+
                nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset,
                                        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,
+                                       tx->base.nblocksx, tx->base.nblocksy,
+                                       tx->bo, 0,
+                                       tx->base.stride, tx->bo->tile_mode,
+                                       0, 0,
+                                       tx->base.nblocksx, tx->base.nblocksy,
+                                       tx->base.block.size, nx, ny,
                                        NOUVEAU_BO_VRAM | NOUVEAU_BO_GART,
                                        NOUVEAU_BO_GART);
        }
@@ -183,17 +194,20 @@ nv50_transfer_del(struct pipe_transfer *ptx)
        struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
        struct nv50_miptree *mt = nv50_miptree(ptx->texture);
 
+       unsigned nx = pf_get_nblocksx(&tx->base.block, tx->base.width);
+       unsigned ny = pf_get_nblocksy(&tx->base.block, tx->base.height);
+
        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.width, tx->base.height,
+               nv50_transfer_rect_m2mf(pscreen, tx->bo, 0,
+                                       tx->base.stride, tx->bo->tile_mode,
+                                       0, 0,
+                                       tx->base.nblocksx, tx->base.nblocksy,
                                        mt->base.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,
+                                       tx->base.nblocksx, tx->base.nblocksy,
+                                       tx->base.block.size, nx, ny,
                                        NOUVEAU_BO_GART, NOUVEAU_BO_VRAM |
                                        NOUVEAU_BO_GART);
        }