summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nvfx/nvfx_transfer.c
diff options
context:
space:
mode:
authorLuca Barbieri <[email protected]>2010-01-15 10:11:11 +0100
committerLuca Barbieri <[email protected]>2010-08-21 20:42:14 +0200
commited2930e7e2c064458da33089cff902574008bf30 (patch)
tree34f3e56774f1bf861fca7c3d589f09801061c78b /src/gallium/drivers/nvfx/nvfx_transfer.c
parentac97e8dba654b9b3c5a9459953ce27056bcbb021 (diff)
nvfx: new 2D: rewrite miptree code, adapt transfers
Changes: - Disable swizzling on non-RGBA 2D textures, since the current 2D code is mostly broken in those cases. A later patch will fix this. Thanks to Andrew Randrianasulu who reported this. - Fix compressed texture transfers and hack around the current 2D code inability to copy compressed textures by using direct access. Thanks to Andrew Randrianasulu who reported this. This patch rewrites all the miptree layout and transfer code in the nvfx driver. The current code is broken in several ways: 1. 3D textures are laid out first by face, then by level, which is incorrect 2. Cube maps should have 128-byte aligned faces 3. Swizzled textures have a strange alignment test that seems unnecessary 4. We store the image_offsets for each face/slice but they can be easily computed instead 5. "Swizzling" is not supported for compressed formats. They can be "swizzled" but swizzling only means that there are no gaps (pitch is level-dependant) and the layout is still linear 6. Swizzling is not supported for non-RGBA formats. All formats (except possibly depth) can be swizzled according to my testing. The miptree layout is rewritten based on my empirical testing, which I posted in the "miptree findings" mail. The image_offset array is removed, since it can be calculated with a simple multiplication; the only array in the miptree structure is now the one for mipmap level starts, which it seems cannot be easily computed in constant time. Also, we now directly store a nouveau_bo instead of a pipe_buffer in the miptree structure, like nv50 does. Support for render temporaries is removed, and will be readded in a later patch. Note that the current temporary code is broken, because it does not copy the temporary back on render cache flushes.
Diffstat (limited to 'src/gallium/drivers/nvfx/nvfx_transfer.c')
-rw-r--r--src/gallium/drivers/nvfx/nvfx_transfer.c27
1 files changed, 11 insertions, 16 deletions
diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c
index 9ff0a93d307..957e586f81d 100644
--- a/src/gallium/drivers/nvfx/nvfx_transfer.c
+++ b/src/gallium/drivers/nvfx/nvfx_transfer.c
@@ -59,14 +59,9 @@ nvfx_miptree_transfer_new(struct pipe_context *pipe,
const struct pipe_box *box)
{
struct pipe_screen *pscreen = pipe->screen;
- struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
struct nvfx_transfer *tx;
struct pipe_resource tx_tex_template, *tx_tex;
- static int no_transfer = -1;
unsigned bind = nvfx_transfer_bind_flags(usage);
- if(no_transfer < 0)
- no_transfer = debug_get_bool_option("NOUVEAU_NO_TRANSFER", FALSE);
-
tx = CALLOC_STRUCT(nvfx_transfer);
if (!tx)
@@ -78,13 +73,13 @@ nvfx_miptree_transfer_new(struct pipe_context *pipe,
pipe_resource_reference(&tx->base.resource, pt);
tx->base.sr = sr;
+ tx->base.stride = nvfx_subresource_pitch(pt, sr.level);
+ tx->base.slice_stride = tx->base.stride * u_minify(pt->height0, sr.level);
tx->base.usage = usage;
tx->base.box = *box;
- tx->base.stride = mt->level[sr.level].pitch;
/* Direct access to texture */
- if ((pt->usage == PIPE_USAGE_DYNAMIC ||
- no_transfer) &&
+ if ((util_format_is_s3tc(pt->format) || pt->usage & PIPE_USAGE_DYNAMIC) &&
pt->flags & NVFX_RESOURCE_FLAG_LINEAR)
{
tx->direct = true;
@@ -109,7 +104,8 @@ nvfx_miptree_transfer_new(struct pipe_context *pipe,
return NULL;
}
- tx->base.stride = ((struct nvfx_miptree*)tx_tex)->level[0].pitch;
+ tx->base.stride = ((struct nvfx_miptree*)tx_tex)->linear_pitch;
+ tx->base.slice_stride = tx->base.stride * box->height;
tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
0, 0, 0,
@@ -181,27 +177,26 @@ nvfx_miptree_transfer_del(struct pipe_context *pipe,
void *
nvfx_miptree_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
{
- struct pipe_screen *pscreen = pipe->screen;
struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
- uint8_t *map = nouveau_screen_bo_map(pscreen, mt->base.bo,
+
+ uint8_t *map = nouveau_screen_bo_map(pipe->screen, mt->base.bo,
nouveau_screen_transfer_flags(ptx->usage));
if(!tx->direct)
return map + ns->base.offset;
else
- return (map + ns->base.offset +
- ptx->box.y * ns->pitch +
- ptx->box.x * util_format_get_blocksize(ptx->resource->format));
+ return map + ns->base.offset
+ + util_format_get_2d_size(ns->base.format, ns->pitch, ptx->box.y)
+ + util_format_get_stride(ptx->resource->format, ptx->box.x);
}
void
nvfx_miptree_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
{
- struct pipe_screen *pscreen = pipe->screen;
struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
- nouveau_screen_bo_unmap(pscreen, mt->base.bo);
+ nouveau_screen_bo_unmap(pipe->screen, mt->base.bo);
}