From: Nicolai Hähnle <nicolai.haeh...@amd.com> Allow callers to prescribe a desired stride for a transfer. Drivers are free to ignore this new parameter.
There is no new capability because it's unclear how strict requirements on this feature should be expressed. --- src/gallium/auxiliary/driver_ddebug/dd_draw.c | 3 ++- src/gallium/auxiliary/driver_noop/noop_pipe.c | 1 + src/gallium/auxiliary/driver_rbug/rbug_context.c | 5 ++++- src/gallium/auxiliary/driver_trace/tr_context.c | 3 ++- src/gallium/auxiliary/util/u_inlines.h | 8 ++++---- src/gallium/auxiliary/util/u_threaded_context.c | 5 +++-- src/gallium/auxiliary/util/u_transfer.c | 3 ++- src/gallium/auxiliary/util/u_transfer.h | 2 ++ src/gallium/auxiliary/util/u_transfer_helper.c | 1 + src/gallium/auxiliary/util/u_transfer_helper.h | 1 + src/gallium/drivers/etnaviv/etnaviv_transfer.c | 1 + src/gallium/drivers/i915/i915_resource_buffer.c | 1 + src/gallium/drivers/i915/i915_resource_texture.c | 1 + src/gallium/drivers/llvmpipe/lp_texture.c | 1 + src/gallium/drivers/nouveau/nouveau_buffer.c | 1 + src/gallium/drivers/nouveau/nv30/nv30_miptree.c | 1 + src/gallium/drivers/nouveau/nv50/nv50_transfer.c | 1 + src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c | 1 + src/gallium/drivers/r300/r300_screen_buffer.c | 1 + src/gallium/drivers/r300/r300_transfer.c | 1 + src/gallium/drivers/r300/r300_transfer.h | 1 + src/gallium/drivers/r600/evergreen_compute.c | 1 + src/gallium/drivers/r600/r600_buffer_common.c | 3 ++- src/gallium/drivers/r600/r600_texture.c | 1 + src/gallium/drivers/radeonsi/si_buffer.c | 3 ++- src/gallium/drivers/radeonsi/si_texture.c | 1 + src/gallium/drivers/softpipe/sp_texture.c | 1 + src/gallium/drivers/svga/svga_resource_buffer.c | 1 + src/gallium/drivers/svga/svga_resource_texture.c | 1 + src/gallium/drivers/vc4/vc4_resource.c | 1 + src/gallium/drivers/virgl/virgl_buffer.c | 1 + src/gallium/drivers/virgl/virgl_texture.c | 1 + src/gallium/include/pipe/p_context.h | 7 +++++++ 33 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/gallium/auxiliary/driver_ddebug/dd_draw.c b/src/gallium/auxiliary/driver_ddebug/dd_draw.c index cb5db8ab83b..125f6041324 100644 --- a/src/gallium/auxiliary/driver_ddebug/dd_draw.c +++ b/src/gallium/auxiliary/driver_ddebug/dd_draw.c @@ -1478,33 +1478,34 @@ dd_context_clear_texture(struct pipe_context *_pipe, } /******************************************************************** * transfer */ static void * dd_context_transfer_map(struct pipe_context *_pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct dd_context *dctx = dd_context(_pipe); struct pipe_context *pipe = dctx->pipe; struct dd_draw_record *record = dd_screen(dctx->base.screen)->transfers ? dd_create_record(dctx) : NULL; if (record) { record->call.type = CALL_TRANSFER_MAP; dd_before_draw(dctx, record); } - void *ptr = pipe->transfer_map(pipe, resource, level, usage, box, transfer); + void *ptr = pipe->transfer_map(pipe, resource, level, usage, box, user_stride, transfer); if (record) { record->call.info.transfer_map.transfer_ptr = *transfer; record->call.info.transfer_map.ptr = ptr; if (*transfer) { record->call.info.transfer_map.transfer = **transfer; record->call.info.transfer_map.transfer.resource = NULL; pipe_resource_reference(&record->call.info.transfer_map.transfer.resource, (*transfer)->resource); } else { memset(&record->call.info.transfer_map.transfer, 0, sizeof(struct pipe_transfer)); diff --git a/src/gallium/auxiliary/driver_noop/noop_pipe.c b/src/gallium/auxiliary/driver_noop/noop_pipe.c index d1e795dab16..cc74fcbd5df 100644 --- a/src/gallium/auxiliary/driver_noop/noop_pipe.c +++ b/src/gallium/auxiliary/driver_noop/noop_pipe.c @@ -167,20 +167,21 @@ static void noop_resource_destroy(struct pipe_screen *screen, /* * transfer */ static void *noop_transfer_map(struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, enum pipe_transfer_usage usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct pipe_transfer *transfer; struct noop_resource *nresource = (struct noop_resource *)resource; transfer = CALLOC_STRUCT(pipe_transfer); if (!transfer) return NULL; pipe_resource_reference(&transfer->resource, resource); transfer->level = level; diff --git a/src/gallium/auxiliary/driver_rbug/rbug_context.c b/src/gallium/auxiliary/driver_rbug/rbug_context.c index e1f3c4f2844..a03f4a79b46 100644 --- a/src/gallium/auxiliary/driver_rbug/rbug_context.c +++ b/src/gallium/auxiliary/driver_rbug/rbug_context.c @@ -1065,35 +1065,38 @@ rbug_context_surface_destroy(struct pipe_context *_pipe, } static void * rbug_context_transfer_map(struct pipe_context *_context, struct pipe_resource *_resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct rbug_context *rb_pipe = rbug_context(_context); struct rbug_resource *rb_resource = rbug_resource(_resource); struct pipe_context *context = rb_pipe->pipe; struct pipe_resource *resource = rb_resource->resource; struct pipe_transfer *result; void *map; mtx_lock(&rb_pipe->call_mutex); map = context->transfer_map(context, resource, level, usage, - box, &result); + box, + user_stride, + &result); mtx_unlock(&rb_pipe->call_mutex); *transfer = rbug_transfer_create(rb_pipe, rb_resource, result); return *transfer ? map : NULL; } static void rbug_context_transfer_flush_region(struct pipe_context *_context, struct pipe_transfer *_transfer, const struct pipe_box *box) diff --git a/src/gallium/auxiliary/driver_trace/tr_context.c b/src/gallium/auxiliary/driver_trace/tr_context.c index 6d918d42a38..ff8b556b596 100644 --- a/src/gallium/auxiliary/driver_trace/tr_context.c +++ b/src/gallium/auxiliary/driver_trace/tr_context.c @@ -1368,33 +1368,34 @@ trace_context_destroy(struct pipe_context *_pipe) * transfer */ static void * trace_context_transfer_map(struct pipe_context *_context, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct trace_context *tr_context = trace_context(_context); struct pipe_context *context = tr_context->pipe; struct pipe_transfer *result = NULL; void *map; /* * Map and transfers can't be serialized so we convert all write transfers * to texture/buffer_subdata and ignore read transfers. */ - map = context->transfer_map(context, resource, level, usage, box, &result); + map = context->transfer_map(context, resource, level, usage, box, user_stride, &result); if (!map) return NULL; *transfer = trace_transfer_create(tr_context, resource, result); if (map) { if (usage & PIPE_TRANSFER_WRITE) { trace_transfer(*transfer)->map = map; } } diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h index b7a28568807..3baa00f518d 100644 --- a/src/gallium/auxiliary/util/u_inlines.h +++ b/src/gallium/auxiliary/util/u_inlines.h @@ -322,21 +322,21 @@ pipe_buffer_map_range(struct pipe_context *pipe, { struct pipe_box box; void *map; assert(offset < buffer->width0); assert(offset + length <= buffer->width0); assert(length); u_box_1d(offset, length, &box); - map = pipe->transfer_map(pipe, buffer, 0, access, &box, transfer); + map = pipe->transfer_map(pipe, buffer, 0, access, &box, 0, transfer); if (!map) { return NULL; } return map; } /** * Map whole resource. @@ -459,21 +459,21 @@ pipe_buffer_read(struct pipe_context *pipe, * Map a resource for reading/writing. */ static inline void * pipe_transfer_map_box(struct pipe_context *context, struct pipe_resource *resource, unsigned level, enum pipe_transfer_usage usage, const struct pipe_box *box, struct pipe_transfer **out_transfer) { - return context->transfer_map(context, resource, level, usage, box, + return context->transfer_map(context, resource, level, usage, box, 0, out_transfer); } /** * Map a resource for reading/writing. * \param access bitmask of PIPE_TRANSFER_x flags */ static inline void * pipe_transfer_map(struct pipe_context *context, @@ -483,21 +483,21 @@ pipe_transfer_map(struct pipe_context *context, unsigned x, unsigned y, unsigned w, unsigned h, struct pipe_transfer **transfer) { struct pipe_box box; u_box_2d_zslice(x, y, layer, w, h, &box); return context->transfer_map(context, resource, level, access, - &box, transfer); + &box, 0, transfer); } /** * Map a 3D (texture) resource for reading/writing. * \param access bitmask of PIPE_TRANSFER_x flags */ static inline void * pipe_transfer_map_3d(struct pipe_context *context, struct pipe_resource *resource, @@ -506,21 +506,21 @@ pipe_transfer_map_3d(struct pipe_context *context, unsigned x, unsigned y, unsigned z, unsigned w, unsigned h, unsigned d, struct pipe_transfer **transfer) { struct pipe_box box; u_box_3d(x, y, z, w, h, d, &box); return context->transfer_map(context, resource, level, access, - &box, transfer); + &box, 0, transfer); } static inline void pipe_transfer_unmap( struct pipe_context *context, struct pipe_transfer *transfer ) { context->transfer_unmap( context, transfer ); } static inline void diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c index 1c647a3efd0..0c41f5582a9 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.c +++ b/src/gallium/auxiliary/util/u_threaded_context.c @@ -1429,20 +1429,21 @@ tc_improve_map_buffer_flags(struct threaded_context *tc, usage |= TC_TRANSFER_MAP_THREADED_UNSYNC; /* notify the driver */ } return usage; } static void * tc_transfer_map(struct pipe_context *_pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct threaded_context *tc = threaded_context(_pipe); struct threaded_resource *tres = threaded_resource(resource); struct pipe_context *pipe = tc->pipe; if (resource->target == PIPE_BUFFER) { usage = tc_improve_map_buffer_flags(tc, tres, usage, box->x, box->width); /* Do a staging transfer within the threaded context. The driver should @@ -1473,21 +1474,21 @@ tc_transfer_map(struct pipe_context *_pipe, } } /* Unsychronized buffer mappings don't have to synchronize the thread. */ if (!(usage & TC_TRANSFER_MAP_THREADED_UNSYNC)) tc_sync_msg(tc, resource->target != PIPE_BUFFER ? " texture" : usage & PIPE_TRANSFER_DISCARD_RANGE ? " discard_range" : usage & PIPE_TRANSFER_READ ? " read" : " ??"); return pipe->transfer_map(pipe, tres->latest ? tres->latest : resource, - level, usage, box, transfer); + level, usage, box, user_stride, transfer); } struct tc_transfer_flush_region { struct pipe_transfer *transfer; struct pipe_box box; }; static void tc_call_transfer_flush_region(struct pipe_context *pipe, union tc_payload *payload) @@ -1634,21 +1635,21 @@ tc_buffer_subdata(struct pipe_context *_pipe, */ if (usage & (PIPE_TRANSFER_UNSYNCHRONIZED | PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) || size > TC_MAX_SUBDATA_BYTES) { struct pipe_transfer *transfer; struct pipe_box box; uint8_t *map = NULL; u_box_1d(offset, size, &box); - map = tc_transfer_map(_pipe, resource, 0, usage, &box, &transfer); + map = tc_transfer_map(_pipe, resource, 0, usage, &box, 0, &transfer); if (map) { memcpy(map, data, size); tc_transfer_unmap(_pipe, transfer); } return; } util_range_add(&tres->valid_buffer_range, offset, offset + size); /* The upload is small. Enqueue it. */ diff --git a/src/gallium/auxiliary/util/u_transfer.c b/src/gallium/auxiliary/util/u_transfer.c index 0e0c4cc91cd..5f07ea067fd 100644 --- a/src/gallium/auxiliary/util/u_transfer.c +++ b/src/gallium/auxiliary/util/u_transfer.c @@ -125,25 +125,26 @@ void u_resource_destroy_vtbl(struct pipe_screen *screen, { struct u_resource *ur = u_resource(resource); ur->vtbl->resource_destroy(screen, resource); } void *u_transfer_map_vtbl(struct pipe_context *context, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct u_resource *ur = u_resource(resource); return ur->vtbl->transfer_map(context, resource, level, usage, box, - transfer); + user_stride, transfer); } void u_transfer_flush_region_vtbl( struct pipe_context *pipe, struct pipe_transfer *transfer, const struct pipe_box *box) { struct u_resource *ur = u_resource(transfer->resource); ur->vtbl->transfer_flush_region(pipe, transfer, box); } diff --git a/src/gallium/auxiliary/util/u_transfer.h b/src/gallium/auxiliary/util/u_transfer.h index 14084983daf..9f1fcb626f3 100644 --- a/src/gallium/auxiliary/util/u_transfer.h +++ b/src/gallium/auxiliary/util/u_transfer.h @@ -51,20 +51,21 @@ struct u_resource_vtbl { struct winsys_handle *handle); void (*resource_destroy)(struct pipe_screen *, struct pipe_resource *pt); void *(*transfer_map)(struct pipe_context *, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *, + unsigned user_stride, struct pipe_transfer **); void (*transfer_flush_region)( struct pipe_context *, struct pipe_transfer *transfer, const struct pipe_box *); void (*transfer_unmap)( struct pipe_context *, struct pipe_transfer *transfer ); }; @@ -83,20 +84,21 @@ boolean u_resource_get_handle_vtbl(struct pipe_screen *screen, unsigned usage); void u_resource_destroy_vtbl(struct pipe_screen *screen, struct pipe_resource *resource); void *u_transfer_map_vtbl(struct pipe_context *context, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer); void u_transfer_flush_region_vtbl( struct pipe_context *pipe, struct pipe_transfer *transfer, const struct pipe_box *box); void u_transfer_unmap_vtbl( struct pipe_context *rm_ctx, struct pipe_transfer *transfer ); #ifdef __cplusplus diff --git a/src/gallium/auxiliary/util/u_transfer_helper.c b/src/gallium/auxiliary/util/u_transfer_helper.c index f69015af519..b5ad30c522d 100644 --- a/src/gallium/auxiliary/util/u_transfer_helper.c +++ b/src/gallium/auxiliary/util/u_transfer_helper.c @@ -217,20 +217,21 @@ transfer_map_msaa(struct pipe_context *pctx, *pptrans = ptrans; return ss_map; } void * u_transfer_helper_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **pptrans) { struct u_transfer_helper *helper = pctx->screen->transfer_helper; struct u_transfer *trans; struct pipe_transfer *ptrans; enum pipe_format format = prsc->format; unsigned width = box->width; unsigned height = box->height; if (!handle_transfer(prsc)) diff --git a/src/gallium/auxiliary/util/u_transfer_helper.h b/src/gallium/auxiliary/util/u_transfer_helper.h index b13a1ec06c1..351efa894da 100644 --- a/src/gallium/auxiliary/util/u_transfer_helper.h +++ b/src/gallium/auxiliary/util/u_transfer_helper.h @@ -102,20 +102,21 @@ struct pipe_resource *u_transfer_helper_resource_create( struct pipe_screen *pscreen, const struct pipe_resource *templ); void u_transfer_helper_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc); void *u_transfer_helper_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **pptrans); void u_transfer_helper_transfer_flush_region(struct pipe_context *pctx, struct pipe_transfer *ptrans, const struct pipe_box *box); void u_transfer_helper_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans); diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c index 30ae3bfc39d..8d079ad4e29 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c @@ -131,20 +131,21 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) pipe_resource_reference(&trans->rsc, NULL); pipe_resource_reference(&ptrans->resource, NULL); slab_free(&ctx->transfer_pool, trans); } static void * etna_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **out_transfer) { struct etna_context *ctx = etna_context(pctx); struct etna_resource *rsc = etna_resource(prsc); struct etna_transfer *trans; struct pipe_transfer *ptrans; enum pipe_format format = prsc->format; trans = slab_alloc(&ctx->transfer_pool); if (!trans) diff --git a/src/gallium/drivers/i915/i915_resource_buffer.c b/src/gallium/drivers/i915/i915_resource_buffer.c index 2572fc40b2c..88a3181ee68 100644 --- a/src/gallium/drivers/i915/i915_resource_buffer.c +++ b/src/gallium/drivers/i915/i915_resource_buffer.c @@ -59,20 +59,21 @@ i915_buffer_destroy(struct pipe_screen *screen, FREE(buffer); } static void * i915_buffer_transfer_map(struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct i915_context *i915 = i915_context(pipe); struct i915_buffer *buffer = i915_buffer(resource); struct pipe_transfer *transfer = slab_alloc_st(&i915->transfer_pool); if (!transfer) return NULL; transfer->resource = resource; diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c index 4ade04f223c..fbf83624275 100644 --- a/src/gallium/drivers/i915/i915_resource_texture.c +++ b/src/gallium/drivers/i915/i915_resource_texture.c @@ -710,20 +710,21 @@ i915_texture_destroy(struct pipe_screen *screen, FREE(tex); } static void * i915_texture_transfer_map(struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct i915_context *i915 = i915_context(pipe); struct i915_texture *tex = i915_texture(resource); struct i915_transfer *transfer = slab_alloc_st(&i915->texture_transfer_pool); boolean use_staging_texture = FALSE; struct i915_winsys *iws = i915_screen(pipe->screen)->iws; enum pipe_format format = resource->format; unsigned offset; char *map; diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 89852cc95c3..8d2ec6dc0e6 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -503,20 +503,21 @@ llvmpipe_resource_get_handle(struct pipe_screen *screen, return winsys->displaytarget_get_handle(winsys, lpr->dt, whandle); } static void * llvmpipe_transfer_map( struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer ) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); struct llvmpipe_resource *lpr = llvmpipe_resource(resource); struct llvmpipe_transfer *lpt; struct pipe_transfer *pt; ubyte *map; enum pipe_format format; enum lp_texture_usage tex_usage; diff --git a/src/gallium/drivers/nouveau/nouveau_buffer.c b/src/gallium/drivers/nouveau/nouveau_buffer.c index 2c604419ce0..c5be45cadbd 100644 --- a/src/gallium/drivers/nouveau/nouveau_buffer.c +++ b/src/gallium/drivers/nouveau/nouveau_buffer.c @@ -370,20 +370,21 @@ nouveau_buffer_should_discard(struct nv04_resource *buf, unsigned usage) * be overwritten. * * The strategy for determining what kind of memory area to return is complex, * see comments inside of the function. */ static void * nouveau_buffer_transfer_map(struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct nouveau_context *nv = nouveau_context(pipe); struct nv04_resource *buf = nv04_resource(resource); struct nouveau_transfer *tx = MALLOC_STRUCT(nouveau_transfer); uint8_t *map; int ret; if (!tx) return NULL; diff --git a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c index 4f991776323..6832289e2cb 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_miptree.c @@ -254,20 +254,21 @@ nv30_blit(struct pipe_context *pipe, void nv30_flush_resource(struct pipe_context *pipe, struct pipe_resource *resource) { } static void * nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct nv30_context *nv30 = nv30_context(pipe); struct nouveau_device *dev = nv30->screen->base.device; struct nv30_transfer *tx; unsigned access = 0; int ret; tx = CALLOC_STRUCT(nv30_transfer); if (!tx) diff --git a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c index 8209f1f1e82..debc01e8fba 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c @@ -240,20 +240,21 @@ nv50_m2mf_copy_linear(struct nouveau_context *nv, nouveau_bufctx_reset(bctx, 0); } void * nv50_miptree_transfer_map(struct pipe_context *pctx, struct pipe_resource *res, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct nv50_screen *screen = nv50_screen(pctx->screen); struct nv50_context *nv50 = nv50_context(pctx); struct nouveau_device *dev = nv50->screen->base.device; const struct nv50_miptree *mt = nv50_miptree(res); struct nv50_transfer *tx; uint32_t size; int ret; unsigned flags = 0; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c index 225b8947171..69a031a46f0 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_transfer.c @@ -365,20 +365,21 @@ nvc0_mt_sync(struct nvc0_context *nvc0, struct nv50_miptree *mt, unsigned usage) return !mt->base.fence || nouveau_fence_wait(mt->base.fence, &nvc0->base.debug); return !mt->base.fence_wr || nouveau_fence_wait(mt->base.fence_wr, &nvc0->base.debug); } void * nvc0_miptree_transfer_map(struct pipe_context *pctx, struct pipe_resource *res, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct nvc0_context *nvc0 = nvc0_context(pctx); struct nouveau_device *dev = nvc0->screen->base.device; struct nv50_miptree *mt = nv50_miptree(res); struct nvc0_transfer *tx; uint32_t size; int ret; unsigned flags = 0; diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index 4af1c46856e..5b761fdd5b9 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -62,20 +62,21 @@ static void r300_buffer_destroy(struct pipe_screen *screen, FREE(rbuf); } static void * r300_buffer_transfer_map( struct pipe_context *context, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer ) { struct r300_context *r300 = r300_context(context); struct radeon_winsys *rws = r300->screen->rws; struct r300_resource *rbuf = r300_resource(resource); struct pipe_transfer *transfer; uint8_t *map; transfer = slab_alloc(&r300->pool_transfers); transfer->resource = resource; diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 9d00f4d9373..35361b5b7b4 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -98,20 +98,21 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, /* XXX remove this. */ r300_flush(ctx, 0, NULL); } void * r300_texture_transfer_map(struct pipe_context *ctx, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct r300_context *r300 = r300_context(ctx); struct r300_resource *tex = r300_resource(texture); struct r300_transfer *trans; boolean referenced_cs, referenced_hw; enum pipe_format format = tex->b.b.format; char *map; referenced_cs = diff --git a/src/gallium/drivers/r300/r300_transfer.h b/src/gallium/drivers/r300/r300_transfer.h index 45477ae6d0d..54cc5aa7042 100644 --- a/src/gallium/drivers/r300/r300_transfer.h +++ b/src/gallium/drivers/r300/r300_transfer.h @@ -27,18 +27,19 @@ #include "pipe/p_context.h" struct r300_context; void * r300_texture_transfer_map(struct pipe_context *ctx, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer); void r300_texture_transfer_unmap(struct pipe_context *ctx, struct pipe_transfer *transfer); #endif diff --git a/src/gallium/drivers/r600/evergreen_compute.c b/src/gallium/drivers/r600/evergreen_compute.c index 866837dfa6e..0338f25b881 100644 --- a/src/gallium/drivers/r600/evergreen_compute.c +++ b/src/gallium/drivers/r600/evergreen_compute.c @@ -1189,20 +1189,21 @@ void evergreen_init_compute_state_functions(struct r600_context *rctx) rctx->b.b.set_global_binding = evergreen_set_global_binding; rctx->b.b.launch_grid = evergreen_launch_grid; } static void *r600_compute_global_transfer_map(struct pipe_context *ctx, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct r600_context *rctx = (struct r600_context*)ctx; struct compute_memory_pool *pool = rctx->screen->global_pool; struct r600_resource_global* buffer = (struct r600_resource_global*)resource; struct compute_memory_item *item = buffer->chunk; struct pipe_resource *dst = NULL; unsigned offset = box->x; diff --git a/src/gallium/drivers/r600/r600_buffer_common.c b/src/gallium/drivers/r600/r600_buffer_common.c index 17a8c3a596f..b460bdb05f1 100644 --- a/src/gallium/drivers/r600/r600_buffer_common.c +++ b/src/gallium/drivers/r600/r600_buffer_common.c @@ -339,20 +339,21 @@ static bool r600_can_dma_copy_buffer(struct r600_common_context *rctx, (dword_aligned && (rctx->dma.cs || rctx->screen->has_streamout)); } static void *r600_buffer_transfer_map(struct pipe_context *ctx, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct r600_common_context *rctx = (struct r600_common_context*)ctx; struct r600_common_screen *rscreen = (struct r600_common_screen*)ctx->screen; struct r600_resource *rbuffer = r600_resource(resource); uint8_t *data; assert(box->x + box->width <= resource->width0); /* From GL_AMD_pinned_memory issues: @@ -545,21 +546,21 @@ void r600_buffer_subdata(struct pipe_context *ctx, { struct pipe_transfer *transfer = NULL; struct pipe_box box; uint8_t *map = NULL; u_box_1d(offset, size, &box); map = r600_buffer_transfer_map(ctx, buffer, 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE | usage, - &box, &transfer); + &box, 0, &transfer); if (!map) return; memcpy(map, data, size); r600_buffer_transfer_unmap(ctx, transfer); } static const struct u_resource_vtbl r600_buffer_vtbl = { NULL, /* get_handle */ diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index c39c00c2e3e..b889e27b5dd 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -1268,20 +1268,21 @@ static void r600_texture_invalidate_storage(struct r600_common_context *rctx, p_atomic_inc(&rscreen->dirty_tex_counter); rctx->num_alloc_tex_transfer_bytes += rtex->size; } static void *r600_texture_transfer_map(struct pipe_context *ctx, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct r600_common_context *rctx = (struct r600_common_context*)ctx; struct r600_texture *rtex = (struct r600_texture*)texture; struct r600_transfer *trans; struct r600_resource *buf; unsigned offset = 0; char *map; bool use_staging_texture = false; diff --git a/src/gallium/drivers/radeonsi/si_buffer.c b/src/gallium/drivers/radeonsi/si_buffer.c index d17b2c6a831..2cfc3c7ca4e 100644 --- a/src/gallium/drivers/radeonsi/si_buffer.c +++ b/src/gallium/drivers/radeonsi/si_buffer.c @@ -358,20 +358,21 @@ static void *si_buffer_get_transfer(struct pipe_context *ctx, transfer->staging = staging; *ptransfer = &transfer->b.b; return data; } static void *si_buffer_transfer_map(struct pipe_context *ctx, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct si_context *sctx = (struct si_context*)ctx; struct r600_resource *rbuffer = r600_resource(resource); uint8_t *data; assert(box->x + box->width <= resource->width0); /* From GL_AMD_pinned_memory issues: * @@ -578,21 +579,21 @@ static void si_buffer_subdata(struct pipe_context *ctx, { struct pipe_transfer *transfer = NULL; struct pipe_box box; uint8_t *map = NULL; u_box_1d(offset, size, &box); map = si_buffer_transfer_map(ctx, buffer, 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE | usage, - &box, &transfer); + &box, 0, &transfer); if (!map) return; memcpy(map, data, size); si_buffer_transfer_unmap(ctx, transfer); } static const struct u_resource_vtbl si_buffer_vtbl = { NULL, /* get_handle */ diff --git a/src/gallium/drivers/radeonsi/si_texture.c b/src/gallium/drivers/radeonsi/si_texture.c index 0a2939bdd16..43f1560ec3e 100644 --- a/src/gallium/drivers/radeonsi/si_texture.c +++ b/src/gallium/drivers/radeonsi/si_texture.c @@ -1644,20 +1644,21 @@ static void si_texture_invalidate_storage(struct si_context *sctx, p_atomic_inc(&sscreen->dirty_tex_counter); sctx->num_alloc_tex_transfer_bytes += rtex->size; } static void *si_texture_transfer_map(struct pipe_context *ctx, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct si_context *sctx = (struct si_context*)ctx; struct r600_texture *rtex = (struct r600_texture*)texture; struct r600_transfer *trans; struct r600_resource *buf; unsigned offset = 0; char *map; bool use_staging_texture = false; diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index c49bfcaba55..8ab85dff8d8 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -350,20 +350,21 @@ softpipe_surface_destroy(struct pipe_context *pipe, * \param level which mipmap level * \param usage bitmask of PIPE_TRANSFER_x flags * \param box the 1D/2D/3D region of interest */ static void * softpipe_transfer_map(struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; struct softpipe_resource *spr = softpipe_resource(resource); struct softpipe_transfer *spt; struct pipe_transfer *pt; enum pipe_format format = resource->format; uint8_t *map; assert(resource); diff --git a/src/gallium/drivers/svga/svga_resource_buffer.c b/src/gallium/drivers/svga/svga_resource_buffer.c index e9d31de6166..dc706cccced 100644 --- a/src/gallium/drivers/svga/svga_resource_buffer.c +++ b/src/gallium/drivers/svga/svga_resource_buffer.c @@ -63,20 +63,21 @@ svga_buffer_needs_hw_storage(unsigned usage) * processing. This means we need to exercise extra care here to ensure that * the end result is exactly the same as if one DMA was used for every mapped * range. */ static void * svga_buffer_transfer_map(struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct svga_context *svga = svga_context(pipe); struct svga_screen *ss = svga_screen(pipe->screen); struct svga_buffer *sbuf = svga_buffer(resource); struct pipe_transfer *transfer; uint8_t *map = NULL; int64_t begin = svga_get_time(svga); SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_BUFFERTRANSFERMAP); diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c index 71b8ebe7d42..5a0141316b1 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.c +++ b/src/gallium/drivers/svga/svga_resource_texture.c @@ -533,20 +533,21 @@ svga_texture_transfer_map_direct(struct svga_context *svga, /** * Request a transfer map to the texture resource */ static void * svga_texture_transfer_map(struct pipe_context *pipe, struct pipe_resource *texture, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **ptransfer) { struct svga_context *svga = svga_context(pipe); struct svga_winsys_screen *sws = svga_screen(pipe->screen)->sws; struct svga_texture *tex = svga_texture(texture); struct svga_transfer *st; struct svga_winsys_surface *surf = tex->handle; boolean use_direct_map = svga_have_gb_objects(svga) && !svga_have_gb_dma(svga); void *map = NULL; diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c index a86bd814d20..12f0c433972 100644 --- a/src/gallium/drivers/vc4/vc4_resource.c +++ b/src/gallium/drivers/vc4/vc4_resource.c @@ -140,20 +140,21 @@ vc4_get_temp_resource(struct pipe_context *pctx, temp_setup.array_size = 1; return pctx->screen->resource_create(pctx->screen, &temp_setup); } static void * vc4_resource_transfer_map(struct pipe_context *pctx, struct pipe_resource *prsc, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **pptrans) { struct vc4_context *vc4 = vc4_context(pctx); struct vc4_resource *rsc = vc4_resource(prsc); struct vc4_transfer *trans; struct pipe_transfer *ptrans; enum pipe_format format = prsc->format; char *buf; /* Upgrade DISCARD_RANGE to WHOLE_RESOURCE if the whole resource is diff --git a/src/gallium/drivers/virgl/virgl_buffer.c b/src/gallium/drivers/virgl/virgl_buffer.c index 2e63aebc72c..d6af398b101 100644 --- a/src/gallium/drivers/virgl/virgl_buffer.c +++ b/src/gallium/drivers/virgl/virgl_buffer.c @@ -36,20 +36,21 @@ static void virgl_buffer_destroy(struct pipe_screen *screen, util_range_destroy(&vbuf->valid_buffer_range); vs->vws->resource_unref(vs->vws, vbuf->base.hw_res); FREE(vbuf); } static void *virgl_buffer_transfer_map(struct pipe_context *ctx, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct virgl_context *vctx = virgl_context(ctx); struct virgl_screen *vs = virgl_screen(ctx->screen); struct virgl_buffer *vbuf = virgl_buffer(resource); struct virgl_transfer *trans; void *ptr; bool readback; uint32_t offset; bool doflushwait = false; diff --git a/src/gallium/drivers/virgl/virgl_texture.c b/src/gallium/drivers/virgl/virgl_texture.c index 150a5ebd8c7..903418f97a6 100644 --- a/src/gallium/drivers/virgl/virgl_texture.c +++ b/src/gallium/drivers/virgl/virgl_texture.c @@ -117,20 +117,21 @@ vrend_get_tex_image_offset(const struct virgl_texture *res, } return offset; } static void *virgl_texture_transfer_map(struct pipe_context *ctx, struct pipe_resource *resource, unsigned level, unsigned usage, const struct pipe_box *box, + unsigned user_stride, struct pipe_transfer **transfer) { struct virgl_context *vctx = virgl_context(ctx); struct virgl_screen *vs = virgl_screen(ctx->screen); struct virgl_texture *vtex = virgl_texture(resource); enum pipe_format format = resource->format; struct virgl_transfer *trans; void *ptr; boolean readback = TRUE; uint32_t offset; diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index c3dc5edf57d..6d99479e4b7 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -566,26 +566,33 @@ struct pipe_context { /** * Map a resource. * * Transfers are (by default) context-private and allow uploads to be * interleaved with rendering. * * out_transfer will contain the transfer object that must be passed * to all the other transfer functions. It also contains useful * information (like texture strides). + * + * If \p user_stride is non-zero, the driver should attempt to provide + * a transfer with stride == user_stride. However, the resulting stride + * may be different, e.g. if user_stride is not sufficiently aligned. + * The map may also fail if user_stride is insufficiently aligned or too + * large, and the behavior is undefined if user_stride is too small. */ void *(*transfer_map)(struct pipe_context *, struct pipe_resource *resource, unsigned level, unsigned usage, /* a combination of PIPE_TRANSFER_x */ const struct pipe_box *, + unsigned user_stride, struct pipe_transfer **out_transfer); /* If transfer was created with WRITE|FLUSH_EXPLICIT, only the * regions specified with this call are guaranteed to be written to * the resource. */ void (*transfer_flush_region)( struct pipe_context *, struct pipe_transfer *transfer, const struct pipe_box *); -- 2.17.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev