From bb0a38d8197e1480dc5aedb3520741c840d01e91 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Fri, 5 Jul 2019 14:22:16 +0300 Subject: [PATCH] virgl: Introduce virgl_resource_transfer_map Normal mapping of buffers and textures uses almost identical logic. This commit extracts the this logic in the form of the virgl_resource_transfer_map() helper function. Signed-off-by: Alexandros Frantzis Reviewed-by: Chia-I Wu --- src/gallium/drivers/virgl/virgl_resource.c | 84 ++++++++++++++++++++++ src/gallium/drivers/virgl/virgl_resource.h | 8 +++ 2 files changed, 92 insertions(+) diff --git a/src/gallium/drivers/virgl/virgl_resource.c b/src/gallium/drivers/virgl/virgl_resource.c index c47a154f400..953ec9824c3 100644 --- a/src/gallium/drivers/virgl/virgl_resource.c +++ b/src/gallium/drivers/virgl/virgl_resource.c @@ -213,6 +213,90 @@ virgl_resource_transfer_prepare(struct virgl_context *vctx, return map_type; } +void * +virgl_resource_transfer_map(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **transfer) +{ + struct virgl_context *vctx = virgl_context(ctx); + struct virgl_winsys *vws = virgl_screen(ctx->screen)->vws; + struct virgl_resource *vres = virgl_resource(resource); + struct virgl_transfer *trans; + enum virgl_transfer_map_type map_type; + void *map_addr; + + /* Multisampled resources require resolve before mapping. */ + assert(resource->nr_samples <= 1); + + trans = virgl_resource_create_transfer(vctx, resource, + &vres->metadata, level, usage, box); + + map_type = virgl_resource_transfer_prepare(vctx, trans); + switch (map_type) { + case VIRGL_TRANSFER_MAP_REALLOC: + if (!virgl_resource_realloc(vctx, vres)) { + map_addr = NULL; + break; + } + vws->resource_reference(vws, &trans->hw_res, vres->hw_res); + /* fall through */ + case VIRGL_TRANSFER_MAP_HW_RES: + trans->hw_res_map = vws->resource_map(vws, vres->hw_res); + if (trans->hw_res_map) + map_addr = trans->hw_res_map + trans->offset; + else + map_addr = NULL; + break; + case VIRGL_TRANSFER_MAP_STAGING: + map_addr = virgl_staging_map(vctx, trans); + /* Copy transfers don't make use of hw_res_map at the moment. */ + trans->hw_res_map = NULL; + break; + case VIRGL_TRANSFER_MAP_ERROR: + default: + trans->hw_res_map = NULL; + map_addr = NULL; + break; + } + + if (!map_addr) { + virgl_resource_destroy_transfer(vctx, trans); + return NULL; + } + + if (vres->u.b.target == PIPE_BUFFER) { + /* For the checks below to be able to use 'usage', we assume that + * transfer preparation doesn't affect the usage. + */ + assert(usage == trans->base.usage); + + /* If we are doing a whole resource discard with a hw_res map, the buffer + * storage can now be considered unused and we don't care about previous + * contents. We can thus mark the storage as uninitialized, but only if + * the buffer is not host writable (in which case we can't clear the + * valid range, since that would result in missed readbacks in future + * transfers). We only do this for VIRGL_TRANSFER_MAP_HW_RES, since for + * VIRGL_TRANSFER_MAP_REALLOC we already take care of the buffer range + * when reallocating and rebinding, and VIRGL_TRANSFER_MAP_STAGING is not + * currently used for whole resource discards. + */ + if (map_type == VIRGL_TRANSFER_MAP_HW_RES && + (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) && + (vres->clean_mask & 1)) { + util_range_set_empty(&vres->valid_buffer_range); + } + + if (usage & PIPE_TRANSFER_WRITE) + util_range_add(&vres->valid_buffer_range, box->x, box->x + box->width); + } + + *transfer = &trans->base; + return map_addr; +} + static struct pipe_resource *virgl_resource_create(struct pipe_screen *screen, const struct pipe_resource *templ) { diff --git a/src/gallium/drivers/virgl/virgl_resource.h b/src/gallium/drivers/virgl/virgl_resource.h index f41c1ce98b3..1e8eb4068b9 100644 --- a/src/gallium/drivers/virgl/virgl_resource.h +++ b/src/gallium/drivers/virgl/virgl_resource.h @@ -164,6 +164,14 @@ enum virgl_transfer_map_type virgl_resource_transfer_prepare(struct virgl_context *vctx, struct virgl_transfer *xfer); +void * +virgl_resource_transfer_map(struct pipe_context *ctx, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **transfer); + void virgl_resource_layout(struct pipe_resource *pt, struct virgl_resource_metadata *metadata);