Browse Source

nv50: fix textures with block size != cpp

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.
tags/mesa_7_7_rc1
Christoph Bumiller 16 years ago
parent
commit
1cc16e1b83
2 changed files with 48 additions and 37 deletions
  1. 16
    19
      src/gallium/drivers/nv50/nv50_miptree.c
  2. 32
    18
      src/gallium/drivers/nv50/nv50_transfer.c

+ 16
- 19
src/gallium/drivers/nv50/nv50_miptree.c View File



#include "nv50_context.h" #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 * static struct pipe_texture *
nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp)
{ {
struct pipe_texture *pt = &mt->base.base; struct pipe_texture *pt = &mt->base.base;
unsigned width = tmp->width[0], height = tmp->height[0]; unsigned width = tmp->width[0], height = tmp->height[0];
unsigned depth = tmp->depth[0]; unsigned depth = tmp->depth[0];
uint32_t tile_mode, tile_flags, tile_h;
uint32_t tile_flags;
int ret, i, l; int ret, i, l;


*pt = *tmp; *pt = *tmp;
break; 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) { switch (pt->target) {
case PIPE_TEXTURE_3D: case PIPE_TEXTURE_3D:
mt->image_nr = pt->depth[0]; mt->image_nr = pt->depth[0];
pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height);


lvl->image_offset = CALLOC(mt->image_nr, sizeof(int)); 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); width = MAX2(1, width >> 1);
height = MAX2(1, height >> 1); height = MAX2(1, height >> 1);
depth = MAX2(1, depth >> 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 (i = 0; i < mt->image_nr; i++) {
for (l = 0; l <= pt->last_level; l++) { for (l = 0; l <= pt->last_level; l++) {
struct nv50_miptree_level *lvl = &mt->level[l]; struct nv50_miptree_level *lvl = &mt->level[l];
int size; 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; lvl->image_offset[i] = mt->total_size;



+ 32
- 18
src/gallium/drivers/nv50/nv50_transfer.c View File

struct nv50_miptree *mt = nv50_miptree(pt); struct nv50_miptree *mt = nv50_miptree(pt);
struct nv50_miptree_level *lvl = &mt->level[level]; struct nv50_miptree_level *lvl = &mt->level[level];
struct nv50_transfer *tx; struct nv50_transfer *tx;
unsigned image = 0;
unsigned nx, ny, image = 0;
int ret; int ret;


if (pt->target == PIPE_TEXTURE_CUBE) if (pt->target == PIPE_TEXTURE_CUBE)
tx->base.width = w; tx->base.width = w;
tx->base.height = h; tx->base.height = h;
tx->base.block = pt->block; 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->base.usage = usage;


tx->level_pitch = lvl->pitch; tx->level_pitch = lvl->pitch;
tx->level_height = mt->base.base.height[level]; tx->level_height = mt->base.base.height[level];
tx->level_offset = lvl->image_offset[image]; tx->level_offset = lvl->image_offset[image];
tx->level_tiling = lvl->tile_mode; 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, 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) { if (ret) {
FREE(tx); FREE(tx);
return NULL; return NULL;
} }


if (usage & PIPE_TRANSFER_READ) { 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, nv50_transfer_rect_m2mf(pscreen, mt->base.bo, tx->level_offset,
tx->level_pitch, tx->level_tiling, tx->level_pitch, tx->level_tiling,
x, y, 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_VRAM | NOUVEAU_BO_GART,
NOUVEAU_BO_GART); NOUVEAU_BO_GART);
} }
struct nv50_transfer *tx = (struct nv50_transfer *)ptx; struct nv50_transfer *tx = (struct nv50_transfer *)ptx;
struct nv50_miptree *mt = nv50_miptree(ptx->texture); 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) { if (ptx->usage & PIPE_TRANSFER_WRITE) {
struct pipe_screen *pscreen = ptx->texture->screen; 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, mt->base.bo, tx->level_offset,
tx->level_pitch, tx->level_tiling, tx->level_pitch, tx->level_tiling,
tx->level_x, tx->level_y, 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, NOUVEAU_BO_VRAM |
NOUVEAU_BO_GART); NOUVEAU_BO_GART);
} }

Loading…
Cancel
Save