diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/nvfx/nv30_fragtex.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nv40_fragtex.c | 12 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_miptree.c | 332 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_resource.h | 48 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_state_fb.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_transfer.c | 27 |
6 files changed, 207 insertions, 224 deletions
diff --git a/src/gallium/drivers/nvfx/nv30_fragtex.c b/src/gallium/drivers/nvfx/nv30_fragtex.c index 0cd70ca1042..85489eab287 100644 --- a/src/gallium/drivers/nvfx/nv30_fragtex.c +++ b/src/gallium/drivers/nvfx/nv30_fragtex.c @@ -92,9 +92,9 @@ void nv30_fragtex_set(struct nvfx_context *nvfx, int unit) { struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; - struct nvfx_miptree *nv30mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture; - struct pipe_resource *pt = &nv30mt->base.base; - struct nouveau_bo *bo = nv30mt->base.bo; + struct nvfx_miptree *mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture; + struct pipe_resource *pt = &mt->base.base; + struct nouveau_bo *bo = mt->base.bo; struct nv30_texture_format *tf; struct nouveau_channel* chan = nvfx->screen->base.channel; uint32_t txf, txs; diff --git a/src/gallium/drivers/nvfx/nv40_fragtex.c b/src/gallium/drivers/nvfx/nv40_fragtex.c index 0d3e90dcb05..45c34c7ffd5 100644 --- a/src/gallium/drivers/nvfx/nv40_fragtex.c +++ b/src/gallium/drivers/nvfx/nv40_fragtex.c @@ -111,9 +111,9 @@ nv40_fragtex_set(struct nvfx_context *nvfx, int unit) { struct nouveau_channel* chan = nvfx->screen->base.channel; struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; - struct nvfx_miptree *nv40mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture; - struct nouveau_bo *bo = nv40mt->base.bo; - struct pipe_resource *pt = &nv40mt->base.base; + struct nvfx_miptree *mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture; + struct nouveau_bo *bo = mt->base.bo; + struct pipe_resource *pt = &mt->base.base; struct nv40_texture_format *tf; uint32_t txf, txs, txp; @@ -149,10 +149,10 @@ nv40_fragtex_set(struct nvfx_context *nvfx, int unit) return; } - if (!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR)) { + if (!mt->linear_pitch) txp = 0; - } else { - txp = nv40mt->level[0].pitch; + else { + txp = mt->linear_pitch; txf |= NV40TCL_TEX_FORMAT_LINEAR; } diff --git a/src/gallium/drivers/nvfx/nvfx_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c index 1fec1ffa42d..0b08f888849 100644 --- a/src/gallium/drivers/nvfx/nvfx_miptree.c +++ b/src/gallium/drivers/nvfx/nvfx_miptree.c @@ -2,69 +2,111 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_format.h" +#include "util/u_memory.h" #include "util/u_math.h" - +#include "state_tracker/drm_driver.h" +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_screen.h" +#include "nv04_surface_2d.h" #include "nvfx_context.h" #include "nvfx_resource.h" #include "nvfx_transfer.h" -#include "nv04_surface_2d.h" - -/* Currently using separate implementations for buffers and textures, - * even though gallium has a unified abstraction of these objects. - * Eventually these should be combined, and mechanisms like transfers - * be adapted to work for both buffer and texture uploads. - */ static void -nvfx_miptree_layout(struct nvfx_miptree *mt) +nvfx_miptree_choose_format(struct nvfx_miptree *mt) { struct pipe_resource *pt = &mt->base.base; - uint width = pt->width0; - uint offset = 0; - int nr_faces, l, f; - uint wide_pitch = pt->bind & (PIPE_BIND_SAMPLER_VIEW | - PIPE_BIND_DEPTH_STENCIL | - PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SCANOUT); - - if (pt->target == PIPE_TEXTURE_CUBE) { - nr_faces = 6; - } else - if (pt->target == PIPE_TEXTURE_3D) { - nr_faces = pt->depth0; - } else { - nr_faces = 1; + unsigned uniform_pitch = 0; + static int no_swizzle = -1; + if(no_swizzle < 0) + no_swizzle = debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE); + + /* Non-uniform pitch textures must be POT */ + if (pt->width0 & (pt->width0 - 1) || + pt->height0 & (pt->height0 - 1) || + pt->depth0 & (pt->depth0 - 1) + ) + uniform_pitch = 1; + + /* All texture formats except compressed ones can be swizzled + * Unsure about depth, let's prevent swizzling for now + */ + if ( + (pt->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET)) + || (pt->usage & PIPE_USAGE_DYNAMIC) || (pt->usage & PIPE_USAGE_STAGING) + || util_format_is_depth_or_stencil(pt->format) + || util_format_is_compressed(pt->format) + // disable swizzled textures on NV04-NV20 as our current drivers don't fully support that + // TODO: hardware should support them, fix the drivers and reenable + || nouveau_screen(pt->screen)->device->chipset < 0x30 + || no_swizzle + + // disable swizzling for non-RGBA 2D because our current 2D code can't handle anything + // else correctly, and even that is semi-broken + || pt->target != PIPE_TEXTURE_2D + || (pt->format != PIPE_FORMAT_B8G8R8A8_UNORM && pt->format != PIPE_FORMAT_B8G8R8X8_UNORM) + ) + mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; + + /* non compressed formats with uniform pitch must be linear, and vice versa */ + if(!util_format_is_s3tc(pt->format) + && (uniform_pitch || mt->base.base.flags & NVFX_RESOURCE_FLAG_LINEAR)) + { + mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; + uniform_pitch = 1; } - for (l = 0; l <= pt->last_level; l++) { - if (wide_pitch && (pt->flags & NVFX_RESOURCE_FLAG_LINEAR)) - mt->level[l].pitch = align(util_format_get_stride(pt->format, pt->width0), 64); - else - mt->level[l].pitch = util_format_get_stride(pt->format, width); + if(uniform_pitch) + { + mt->linear_pitch = util_format_get_stride(pt->format, pt->width0); + + // TODO: this is only a constraint for rendering and not sampling, apparently + // we may also want this unconditionally + if(pt->bind & (PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DEPTH_STENCIL | + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT)) + mt->linear_pitch = align(mt->linear_pitch, 64); + } + else + mt->linear_pitch = 0; +} - mt->level[l].image_offset = - CALLOC(nr_faces, sizeof(unsigned)); +static unsigned +nvfx_miptree_layout(struct nvfx_miptree *mt) +{ + struct pipe_resource* pt = &mt->base.base; + uint offset = 0; - width = u_minify(width, 1); + if(!nvfx_screen(pt->screen)->is_nv4x) + { + assert(pt->target == PIPE_TEXTURE_RECT + || (util_is_pot(pt->width0) && util_is_pot(pt->height0))); } - for (f = 0; f < nr_faces; f++) { - for (l = 0; l < pt->last_level; l++) { - mt->level[l].image_offset[f] = offset; + for (unsigned l = 0; l <= pt->last_level; l++) + { + unsigned size; + mt->level_offset[l] = offset; + + if(mt->linear_pitch) + size = mt->linear_pitch; + else + size = util_format_get_stride(pt->format, u_minify(pt->width0, l)); + size = util_format_get_2d_size(pt->format, size, u_minify(pt->height0, l)); - if (!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR) && - u_minify(pt->width0, l + 1) > 1 && u_minify(pt->height0, l + 1) > 1) - offset += align(mt->level[l].pitch * u_minify(pt->height0, l), 64); - else - offset += mt->level[l].pitch * u_minify(pt->height0, l); - } + if(pt->target == PIPE_TEXTURE_3D) + size *= u_minify(pt->depth0, l); - mt->level[l].image_offset[f] = offset; - offset += mt->level[l].pitch * u_minify(pt->height0, l); + offset += size; } - mt->total_size = offset; + offset = align(offset, 128); + mt->face_size = offset; + if(mt->base.base.target == PIPE_TEXTURE_CUBE) + offset += 5 * mt->face_size; + return offset; } static boolean @@ -79,7 +121,7 @@ nvfx_miptree_get_handle(struct pipe_screen *pscreen, return nouveau_screen_bo_get_handle(pscreen, mt->base.bo, - mt->level[0].pitch, + mt->linear_pitch, whandle); } @@ -88,15 +130,7 @@ static void nvfx_miptree_destroy(struct pipe_screen *screen, struct pipe_resource *pt) { struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; - int l; - nouveau_screen_bo_release(screen, mt->base.bo); - - for (l = 0; l <= pt->last_level; l++) { - if (mt->level[l].image_offset) - FREE(mt->level[l].image_offset); - } - FREE(mt); } @@ -116,76 +150,50 @@ struct u_resource_vtbl nvfx_miptree_vtbl = u_default_transfer_inline_write /* transfer_inline_write */ }; +static struct nvfx_miptree* +nvfx_miptree_create_skeleton(struct pipe_screen *pscreen, const struct pipe_resource *pt) +{ + struct nvfx_miptree *mt; + + if(pt->width0 > 4096 || pt->height0 > 4096) + return NULL; + + mt = CALLOC_STRUCT(nvfx_miptree); + if (!mt) + return NULL; + + mt->base.base = *pt; + mt->base.vtbl = &nvfx_miptree_vtbl; + pipe_reference_init(&mt->base.base.reference, 1); + mt->base.base.screen = pscreen; + + // set this to the actual capabilities, we use it to decide whether to use the 3D engine for copies + // TODO: is this the correct way to use Gallium? + mt->base.base.bind = pt->bind | PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL; + + // on our current driver (and the driver too), format support does not depend on geometry, so don't bother computing it + // TODO: may want to revisit this + if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_RENDER_TARGET, 0)) + mt->base.base.bind &=~ PIPE_BIND_RENDER_TARGET; + if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_SAMPLER_VIEW, 0)) + mt->base.base.bind &=~ PIPE_BIND_SAMPLER_VIEW; + if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_DEPTH_STENCIL, 0)) + mt->base.base.bind &=~ PIPE_BIND_DEPTH_STENCIL; + + return mt; +} struct pipe_resource * nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt) { - struct nvfx_miptree *mt; - static int no_swizzle = -1; - if(no_swizzle < 0) - no_swizzle = debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE); - - mt = CALLOC_STRUCT(nvfx_miptree); - if (!mt) - return NULL; - - mt->base.base = *pt; - mt->base.vtbl = &nvfx_miptree_vtbl; - pipe_reference_init(&mt->base.base.reference, 1); - mt->base.base.screen = pscreen; - - /* Swizzled textures must be POT */ - if (pt->width0 & (pt->width0 - 1) || - pt->height0 & (pt->height0 - 1)) - mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; - else - if (pt->bind & (PIPE_BIND_SCANOUT | - PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_DEPTH_STENCIL)) - mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; - else - if (pt->usage == PIPE_USAGE_DYNAMIC) - mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; - else { - switch (pt->format) { - case PIPE_FORMAT_B5G6R5_UNORM: - case PIPE_FORMAT_L8A8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_I8_UNORM: - /* TODO: we can actually swizzle these formats on nv40, we - are just preserving the pre-unification behavior. - The whole 2D code is going to be rewritten anyway. */ - if(nvfx_screen(pscreen)->is_nv4x) { - mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; - break; - } - /* TODO: Figure out which formats can be swizzled */ - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_R16_SNORM: - { - if (no_swizzle) - mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; - break; - } - default: - mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; - } - } + struct nvfx_miptree* mt = nvfx_miptree_create_skeleton(pscreen, pt); + nvfx_miptree_choose_format(mt); - /* apparently we can't render to swizzled surfaces smaller than 64 bytes, so make them linear. - * If the user did not ask for a render target, they can still render to it, but it will cost them an extra copy. - * This also happens for small mipmaps of large textures. */ - if (pt->bind & PIPE_BIND_RENDER_TARGET && - util_format_get_stride(pt->format, pt->width0) < 64) - mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; + unsigned size = nvfx_miptree_layout(mt); - nvfx_miptree_layout(mt); + mt->base.bo = nouveau_screen_bo_new(pscreen, 256, pt->usage, pt->bind, size); - mt->base.bo = nouveau_screen_bo_new(pscreen, 256, - pt->usage, pt->bind, mt->total_size); if (!mt->base.bo) { FREE(mt); return NULL; @@ -193,54 +201,28 @@ nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt) return &mt->base.base; } - - - +// TODO: redo this, just calling miptree_layout struct pipe_resource * -nvfx_miptree_from_handle(struct pipe_screen *pscreen, - const struct pipe_resource *template, - struct winsys_handle *whandle) +nvfx_miptree_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *template, struct winsys_handle *whandle) { - struct nvfx_miptree *mt; - unsigned stride; - - /* Only supports 2D, non-mipmapped textures for the moment */ - if ((template->target != PIPE_TEXTURE_2D && - template->target != PIPE_TEXTURE_RECT) || - template->last_level != 0 || - template->depth0 != 1) - return NULL; - - mt = CALLOC_STRUCT(nvfx_miptree); - if (!mt) - return NULL; - - mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride); - if (mt->base.bo == NULL) { - FREE(mt); - return NULL; - } - - mt->base.base = *template; - mt->base.vtbl = &nvfx_miptree_vtbl; - pipe_reference_init(&mt->base.base.reference, 1); - mt->base.base.screen = pscreen; - mt->level[0].pitch = stride; - mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); - - /* Assume whoever created this buffer expects it to be linear for now */ - mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; - - /* XXX: Need to adjust bo refcount?? - */ - /* nouveau_bo_ref(bo, &mt->base.bo); */ - return &mt->base.base; + struct nvfx_miptree* mt = nvfx_miptree_create_skeleton(pscreen, template); + if(whandle->stride) { + mt->linear_pitch = whandle->stride; + mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR; + } else + nvfx_miptree_choose_format(mt); + + nvfx_miptree_layout(mt); + + unsigned stride; + mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride); + if (mt->base.bo == NULL) { + FREE(mt); + return NULL; + } + return &mt->base.base; } - - - - /* Surface helpers, not strictly required to implement the resource vtbl: */ struct pipe_surface * @@ -248,7 +230,6 @@ nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) { - struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; struct nv04_surface *ns; ns = CALLOC_STRUCT(nv04_surface); @@ -263,33 +244,8 @@ nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, ns->base.face = face; ns->base.level = level; ns->base.zslice = zslice; - ns->pitch = mt->level[level].pitch; - - if (pt->target == PIPE_TEXTURE_CUBE) { - ns->base.offset = mt->level[level].image_offset[face]; - } else - if (pt->target == PIPE_TEXTURE_3D) { - ns->base.offset = mt->level[level].image_offset[zslice]; - } else { - ns->base.offset = mt->level[level].image_offset[0]; - } - - /* create a linear temporary that we can render into if - * necessary. - * - * Note that ns->pitch is always a multiple of 64 for linear - * surfaces and swizzled surfaces are POT, so ns->pitch & 63 - * is equivalent to (ns->pitch < 64 && swizzled) - */ - - if ((ns->pitch & 63) && - (ns->base.usage & PIPE_BIND_RENDER_TARGET)) - { - struct nv04_surface_2d* eng2d = - ((struct nvfx_screen*)pscreen)->eng2d; - - ns = nv04_surface_wrap_for_render(pscreen, eng2d, ns); - } + ns->pitch = nvfx_subresource_pitch(pt, level); + ns->base.offset = nvfx_subresource_offset(pt, face, level, zslice); return &ns->base; } diff --git a/src/gallium/drivers/nvfx/nvfx_resource.h b/src/gallium/drivers/nvfx/nvfx_resource.h index bdbf3dd3d89..0e24ec2f1f9 100644 --- a/src/gallium/drivers/nvfx/nvfx_resource.h +++ b/src/gallium/drivers/nvfx/nvfx_resource.h @@ -39,15 +39,11 @@ nvfx_resource_on_gpu(struct pipe_resource* pr) #define NVFX_MAX_TEXTURE_LEVELS 16 struct nvfx_miptree { - struct nvfx_resource base; - uint total_size; + struct nvfx_resource base; - struct { - uint pitch; - uint *image_offset; - } level[NVFX_MAX_TEXTURE_LEVELS]; - - unsigned image_nr; + unsigned linear_pitch; /* for linear textures, 0 for swizzled and compressed textures with level-dependent minimal pitch */ + unsigned face_size; /* 128-byte aligned face/total size */ + unsigned level_offset[NVFX_MAX_TEXTURE_LEVELS]; }; static INLINE @@ -103,5 +99,41 @@ nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags); +/* only for miptrees, don't use for buffers */ + +/* NOTE: for swizzled 3D textures, this just returns the offset of the mipmap level */ +static inline unsigned +nvfx_subresource_offset(struct pipe_resource* pt, unsigned face, unsigned level, unsigned zslice) +{ + if(pt->target == PIPE_BUFFER) + return 0; + else + { + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; + + unsigned offset = mt->level_offset[level]; + if (pt->target == PIPE_TEXTURE_CUBE) + offset += mt->face_size * face; + else if (pt->target == PIPE_TEXTURE_3D && mt->linear_pitch) + offset += zslice * util_format_get_2d_size(pt->format, (mt->linear_pitch ? mt->linear_pitch : util_format_get_stride(pt->format, u_minify(pt->width0, level))), u_minify(pt->height0, level)); + return offset; + } +} + +static inline unsigned +nvfx_subresource_pitch(struct pipe_resource* pt, unsigned level) +{ + if(pt->target == PIPE_BUFFER) + return ((struct nvfx_resource*)pt)->bo->size; + else + { + struct nvfx_miptree *mt = (struct nvfx_miptree *)pt; + + if(mt->linear_pitch) + return mt->linear_pitch; + else + return util_format_get_stride(pt->format, u_minify(pt->width0, level)); + } +} #endif diff --git a/src/gallium/drivers/nvfx/nvfx_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c index 360e569f77c..657e315f067 100644 --- a/src/gallium/drivers/nvfx/nvfx_state_fb.c +++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c @@ -29,7 +29,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx) colour_format = fb->cbufs[i]->format; rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i); - nvfx->hw_rt[i].bo = nvfx_surface_buffer(fb->cbufs[i]); + nvfx->hw_rt[i].bo = ((struct nvfx_miptree*)fb->cbufs[i]->texture)->base.bo; nvfx->hw_rt[i].offset = fb->cbufs[i]->offset; nvfx->hw_rt[i].pitch = ((struct nv04_surface *)fb->cbufs[i])->pitch; } @@ -42,7 +42,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx) if (fb->zsbuf) { zeta_format = fb->zsbuf->format; - nvfx->hw_zeta.bo = nvfx_surface_buffer(fb->zsbuf); + nvfx->hw_zeta.bo = ((struct nvfx_miptree*)fb->zsbuf->texture)->base.bo; nvfx->hw_zeta.offset = fb->zsbuf->offset; nvfx->hw_zeta.pitch = ((struct nv04_surface *)fb->zsbuf)->pitch; } @@ -67,7 +67,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx) depth_only = 1; /* Render to depth buffer only */ - if (!(fb->zsbuf->texture->usage & NVFX_RESOURCE_FLAG_LINEAR)) { + if (!(fb->zsbuf->texture->flags & NVFX_RESOURCE_FLAG_LINEAR)) { assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1))); rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED | 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); } |