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.
This commit is contained in:
@@ -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 */
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
struct nvfx_staging_transfer
|
||||
{
|
||||
struct util_staging_transfer base;
|
||||
|
||||
unsigned offset;
|
||||
unsigned map_count;
|
||||
};
|
||||
|
||||
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 )
|
||||
{
|
||||
unsigned bind = 0;
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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);
|
||||
util_staging_transfer_init(pipe, pt, sr, usage, box, direct, tx);
|
||||
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user