From 23639dc046435716042b68359ac6208d99be82f4 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Tue, 3 Aug 2010 21:32:42 +0200 Subject: [PATCH] nvfx: new 2D: rewrite transfer code to use staging transfers This greatly simplifies the code, and avoids ad-hoc copy code. Also, these new transfers work for buffers too, even though they are still used for miptrees only. --- src/gallium/drivers/nvfx/nvfx_miptree.c | 9 +- src/gallium/drivers/nvfx/nvfx_transfer.c | 215 ++++++----------------- src/gallium/drivers/nvfx/nvfx_transfer.h | 10 +- 3 files changed, 61 insertions(+), 173 deletions(-) diff --git a/src/gallium/drivers/nvfx/nvfx_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c index 0b08f888849..27bfa24b282 100644 --- a/src/gallium/drivers/nvfx/nvfx_miptree.c +++ b/src/gallium/drivers/nvfx/nvfx_miptree.c @@ -4,6 +4,7 @@ #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_staging.h" #include "state_tracker/drm_driver.h" #include "nouveau/nouveau_winsys.h" #include "nouveau/nouveau_screen.h" @@ -142,11 +143,11 @@ struct u_resource_vtbl nvfx_miptree_vtbl = nvfx_miptree_get_handle, /* get_handle */ nvfx_miptree_destroy, /* resource_destroy */ NULL, /* is_resource_referenced */ - nvfx_miptree_transfer_new, /* get_transfer */ - nvfx_miptree_transfer_del, /* transfer_destroy */ - nvfx_miptree_transfer_map, /* transfer_map */ + nvfx_transfer_new, /* get_transfer */ + util_staging_transfer_destroy, /* transfer_destroy */ + nvfx_transfer_map, /* transfer_map */ u_default_transfer_flush_region, /* transfer_flush_region */ - nvfx_miptree_transfer_unmap, /* transfer_unmap */ + nvfx_transfer_unmap, /* transfer_unmap */ u_default_transfer_inline_write /* transfer_inline_write */ }; diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c index 957e586f81d..e9c3dd7e551 100644 --- a/src/gallium/drivers/nvfx/nvfx_transfer.c +++ b/src/gallium/drivers/nvfx/nvfx_transfer.c @@ -4,199 +4,88 @@ #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_math.h" -#include "nouveau/nouveau_winsys.h" +#include "util/u_staging.h" #include "nvfx_context.h" #include "nvfx_screen.h" #include "nvfx_state.h" #include "nvfx_resource.h" #include "nvfx_transfer.h" -struct nvfx_transfer { - struct pipe_transfer base; - struct pipe_surface *surface; - boolean direct; -}; - -static void -nvfx_compatible_transfer_tex(struct pipe_resource *pt, unsigned width, unsigned height, - unsigned bind, - struct pipe_resource *template) -{ - memset(template, 0, sizeof(struct pipe_resource)); - template->target = pt->target; - template->format = pt->format; - template->width0 = width; - template->height0 = height; - template->depth0 = 1; - template->last_level = 0; - template->nr_samples = pt->nr_samples; - template->bind = bind; - template->usage = PIPE_USAGE_DYNAMIC; - template->flags = NVFX_RESOURCE_FLAG_LINEAR; -} - - -static unsigned nvfx_transfer_bind_flags( unsigned transfer_usage ) +struct nvfx_staging_transfer { - unsigned bind = 0; + struct util_staging_transfer base; -#if 0 - if (transfer_usage & PIPE_TRANSFER_WRITE) - bind |= PIPE_BIND_BLIT_SOURCE; - - if (transfer_usage & PIPE_TRANSFER_READ) - bind |= PIPE_BIND_BLIT_DESTINATION; -#endif - - return bind; -} + unsigned offset; + unsigned map_count; +}; struct pipe_transfer * -nvfx_miptree_transfer_new(struct pipe_context *pipe, +nvfx_transfer_new(struct pipe_context *pipe, struct pipe_resource *pt, struct pipe_subresource sr, unsigned usage, const struct pipe_box *box) { - struct pipe_screen *pscreen = pipe->screen; - struct nvfx_transfer *tx; - struct pipe_resource tx_tex_template, *tx_tex; - unsigned bind = nvfx_transfer_bind_flags(usage); + struct nvfx_staging_transfer* tx; + bool direct = !nvfx_resource_on_gpu(pt) && pt->flags & NVFX_RESOURCE_FLAG_LINEAR; - tx = CALLOC_STRUCT(nvfx_transfer); - if (!tx) + tx = CALLOC_STRUCT(nvfx_staging_transfer); + if(!tx) return NULL; - /* Don't handle 3D transfers yet. - */ - assert(box->depth == 1); - - 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; + util_staging_transfer_init(pipe, pt, sr, usage, box, direct, tx); - /* Direct access to texture */ - if ((util_format_is_s3tc(pt->format) || pt->usage & PIPE_USAGE_DYNAMIC) && - pt->flags & NVFX_RESOURCE_FLAG_LINEAR) + if(pt->target == PIPE_BUFFER) { - tx->direct = true; - - /* XXX: just call the internal nvfx function. - */ - tx->surface = pscreen->get_tex_surface(pscreen, pt, - sr.face, sr.level, - box->z, - bind); - return &tx->base; + tx->base.base.slice_stride = tx->base.base.stride = ((struct nvfx_resource*)tx->base.staging_resource)->bo->size; + if(direct) + tx->offset = util_format_get_stride(pt->format, box->x); + else + tx->offset = 0; } - - tx->direct = false; - - nvfx_compatible_transfer_tex(pt, box->width, box->height, bind, &tx_tex_template); - - tx_tex = pscreen->resource_create(pscreen, &tx_tex_template); - if (!tx_tex) + else { - FREE(tx); - return NULL; + if(direct) + { + tx->base.base.stride = nvfx_subresource_pitch(pt, sr.level); + tx->base.base.slice_stride = tx->base.base.stride * u_minify(pt->height0, sr.level); + tx->offset = nvfx_subresource_offset(pt, sr.face, sr.level, box->z) + + util_format_get_2d_size(pt->format, tx->base.base.stride, box->y) + + util_format_get_stride(pt->format, box->x); + } + else + { + tx->base.base.stride = nvfx_subresource_pitch(tx->base.staging_resource, 0); + tx->base.base.slice_stride = tx->base.base.stride * tx->base.staging_resource->height0; + tx->offset = 0; + } + + assert(tx->base.base.stride); + + return &tx->base.base; } - - 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, - bind); - - pipe_resource_reference(&tx_tex, NULL); - - if (!tx->surface) - { - pipe_surface_reference(&tx->surface, NULL); - FREE(tx); - return NULL; - } - - if (usage & PIPE_TRANSFER_READ) { - struct nvfx_screen *nvscreen = nvfx_screen(pscreen); - struct pipe_surface *src; - - src = pscreen->get_tex_surface(pscreen, pt, - sr.face, sr.level, box->z, - 0 /*PIPE_BIND_BLIT_SOURCE*/); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - /* TODO: Check if SIFM can un-swizzle */ - nvscreen->eng2d->copy(nvscreen->eng2d, - tx->surface, 0, 0, - src, - box->x, box->y, - box->width, box->height); - - pipe_surface_reference(&src, NULL); - } - - return &tx->base; -} - -void -nvfx_miptree_transfer_del(struct pipe_context *pipe, - struct pipe_transfer *ptx) -{ - struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx; - - if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = pipe->screen; - struct nvfx_screen *nvscreen = nvfx_screen(pscreen); - struct pipe_surface *dst; - - dst = pscreen->get_tex_surface(pscreen, - ptx->resource, - ptx->sr.face, - ptx->sr.level, - ptx->box.z, - 0 /*PIPE_BIND_BLIT_DESTINATION*/); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - nvscreen->eng2d->copy(nvscreen->eng2d, - dst, ptx->box.x, ptx->box.y, - tx->surface, 0, 0, - ptx->box.width, ptx->box.height); - - pipe_surface_reference(&dst, NULL); - } - - pipe_surface_reference(&tx->surface, NULL); - pipe_resource_reference(&ptx->resource, NULL); - FREE(ptx); } void * -nvfx_miptree_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx) +nvfx_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx) { - 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(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 - + util_format_get_2d_size(ns->base.format, ns->pitch, ptx->box.y) - + util_format_get_stride(ptx->resource->format, ptx->box.x); + struct nvfx_staging_transfer *tx = (struct nvfx_staging_transfer *)ptx; + if(!ptx->data) + { + struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->base.staging_resource; + uint8_t *map = nouveau_screen_bo_map(pipe->screen, mt->base.bo, nouveau_screen_transfer_flags(ptx->usage)); + ptx->data = map + tx->offset; + } + ++tx->map_count; + return ptx->data; } void -nvfx_miptree_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx) +nvfx_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx) { - struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx; - struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture; + struct nvfx_staging_transfer *tx = (struct nvfx_staging_transfer *)ptx; + struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->base.staging_resource; - nouveau_screen_bo_unmap(pipe->screen, mt->base.bo); + if(!--tx->map_count) + nouveau_screen_bo_unmap(pipe->screen, mt->base.bo); } diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.h b/src/gallium/drivers/nvfx/nvfx_transfer.h index 3e3317b2c7b..20f20d5b0b8 100644 --- a/src/gallium/drivers/nvfx/nvfx_transfer.h +++ b/src/gallium/drivers/nvfx/nvfx_transfer.h @@ -7,19 +7,17 @@ struct pipe_transfer * -nvfx_miptree_transfer_new(struct pipe_context *pcontext, +nvfx_transfer_new(struct pipe_context *pcontext, struct pipe_resource *pt, struct pipe_subresource sr, unsigned usage, const struct pipe_box *box); -void -nvfx_miptree_transfer_del(struct pipe_context *pcontext, - struct pipe_transfer *ptx); + void * -nvfx_miptree_transfer_map(struct pipe_context *pcontext, +nvfx_transfer_map(struct pipe_context *pcontext, struct pipe_transfer *ptx); void -nvfx_miptree_transfer_unmap(struct pipe_context *pcontext, +nvfx_transfer_unmap(struct pipe_context *pcontext, struct pipe_transfer *ptx); -- 2.30.2