From 59064c6520a0658406cec8a0d5b1cf013d99439e Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Tue, 14 May 2019 17:48:19 +0300 Subject: [PATCH] vrend: Support copy transfers Support the copy_transfer3d command, which transfers data to a host resource by copying from another staging resource. This is used by the guest to avoid waiting in case it needs to write to a busy resource. Signed-off-by: Alexandros Frantzis Reviewed-by: Chia-I Wu Reviewed-by: Gurchetan Singh --- src/vrend_decode.c | 23 +++++++++++++++++++++++ src/vrend_renderer.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/vrend_renderer.h | 4 ++++ 3 files changed, 67 insertions(+) diff --git a/src/vrend_decode.c b/src/vrend_decode.c index 7dd901e..ad49098 100644 --- a/src/vrend_decode.c +++ b/src/vrend_decode.c @@ -1344,6 +1344,26 @@ static int vrend_decode_transfer3d(struct vrend_decode_ctx *ctx, int length, uin return vrend_renderer_transfer_iov(&info, transfer_mode); } +static int vrend_decode_copy_transfer3d(struct vrend_decode_ctx *ctx, int length) +{ + struct pipe_box box; + struct vrend_transfer_info info; + uint32_t src_handle; + + if (length != VIRGL_COPY_TRANSFER3D_SIZE) + return EINVAL; + + memset(&info, 0, sizeof(info)); + info.box = &box; + vrend_decode_transfer_common(ctx, &info); + info.offset = get_buf_entry(ctx, VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET); + info.synchronized = (get_buf_entry(ctx, VIRGL_COPY_TRANSFER3D_SYNCHRONIZED) != 0); + + src_handle = get_buf_entry(ctx, VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE); + + return vrend_renderer_copy_transfer3d(ctx->grctx, &info, src_handle); +} + void vrend_renderer_context_create_internal(uint32_t handle, uint32_t nlen, const char *debug_name) { @@ -1584,6 +1604,9 @@ int vrend_decode_block(uint32_t ctx_id, uint32_t *block, int ndw) case VIRGL_CCMD_TRANSFER3D: ret = vrend_decode_transfer3d(gdctx, len, ctx_id); break; + case VIRGL_CCMD_COPY_TRANSFER3D: + ret = vrend_decode_copy_transfer3d(gdctx, len); + break; case VIRGL_CCMD_END_TRANSFERS: ret = 0; break; diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index dc09587..d977ef4 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -7140,6 +7140,44 @@ int vrend_transfer_inline_write(struct vrend_context *ctx, } +int vrend_renderer_copy_transfer3d(struct vrend_context *ctx, + struct vrend_transfer_info *info, + uint32_t src_handle) +{ + struct vrend_resource *src_res, *dst_res; + + src_res = vrend_renderer_ctx_res_lookup(ctx, src_handle); + dst_res = vrend_renderer_ctx_res_lookup(ctx, info->handle); + + if (!src_res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, src_handle); + return EINVAL; + } + + if (!dst_res) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, info->handle); + return EINVAL; + } + + if (!src_res->iov) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, info->handle); + return EINVAL; + } + + if (!check_transfer_bounds(dst_res, info)) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, info->handle); + return EINVAL; + } + + if (!check_iov_bounds(dst_res, info, src_res->iov, src_res->num_iovs)) { + report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, info->handle); + return EINVAL; + } + + return vrend_renderer_transfer_write_iov(ctx, dst_res, src_res->iov, + src_res->num_iovs, info); +} + void vrend_set_stencil_ref(struct vrend_context *ctx, struct pipe_stencil_ref *ref) { @@ -9045,6 +9083,8 @@ static void vrend_renderer_fill_caps_v2(int gl_ver, int gles_ver, union virgl_c caps->v2.capability_bits |= VIRGL_CAP_3D_ASTC; caps->v2.capability_bits |= VIRGL_CAP_INDIRECT_INPUT_ADDR; + + caps->v2.capability_bits |= VIRGL_CAP_COPY_TRANSFER; } void vrend_renderer_fill_caps(uint32_t set, UNUSED uint32_t version, diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h index ce9704f..9ea7cd8 100644 --- a/src/vrend_renderer.h +++ b/src/vrend_renderer.h @@ -225,6 +225,10 @@ void vrend_set_num_vbo(struct vrend_context *ctx, int vrend_transfer_inline_write(struct vrend_context *ctx, struct vrend_transfer_info *info); +int vrend_renderer_copy_transfer3d(struct vrend_context *ctx, + struct vrend_transfer_info *info, + uint32_t src_handle); + void vrend_set_viewport_states(struct vrend_context *ctx, uint32_t start_slot, uint32_t num_viewports, const struct pipe_viewport_state *state);