summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv50
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2009-10-31 20:46:59 +0100
committerChristoph Bumiller <[email protected]>2009-10-31 20:51:09 +0100
commit1cc16e1b831cef8e1573cc998cee3e55179bb830 (patch)
tree631c2ee863ea4d896eb35740e5323d33c81f2003 /src/gallium/drivers/nv50
parent91232b7004d7a9fbf4f99bb9ec4e5eea8e1c6eef (diff)
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.
Diffstat (limited to 'src/gallium/drivers/nv50')
-rw-r--r--src/gallium/drivers/nv50/nv50_miptree.c35
-rw-r--r--src/gallium/drivers/nv50/nv50_transfer.c50
2 files changed, 48 insertions, 37 deletions
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index 93479a0314a..229a59cb743 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -26,6 +26,16 @@
#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;
diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c
index f1eb6723366..9c008090b8d 100644
--- a/src/gallium/drivers/nv50/nv50_transfer.c
+++ b/src/gallium/drivers/nv50/nv50_transfer.c
@@ -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);
}