From 1d0be402c7a3e8b6de7fcf7faf20537f2ffd09a3 Mon Sep 17 00:00:00 2001 From: Neha Bhende Date: Tue, 28 Jun 2016 17:20:43 -0600 Subject: [PATCH] svga: use vgpu10 CopyRegion command when possible Do texture->texture copies host-side with this command when possible. Use the previous software fallback otherwise. Reviewed-by: Brian Paul Acked-by: Roland Scheidegger Reviewed-by: Charmaine Lee --- src/gallium/drivers/svga/svga_pipe_blit.c | 149 +++++++++++++++++++++++++++++- 1 file changed, 147 insertions(+), 2 deletions(-) diff --git a/src/gallium/drivers/svga/svga_pipe_blit.c b/src/gallium/drivers/svga/svga_pipe_blit.c index 4eec927..564af51 100644 --- a/src/gallium/drivers/svga/svga_pipe_blit.c +++ b/src/gallium/drivers/svga/svga_pipe_blit.c @@ -36,12 +36,76 @@ #define FILE_DEBUG_FLAG DEBUG_BLIT +/** + * Copy an image between textures with the vgpu10 CopyRegion command. + */ +static void +copy_region_vgpu10(struct svga_context *svga, struct pipe_resource *src_tex, + unsigned src_x, unsigned src_y, unsigned src_z, + unsigned src_level, unsigned src_face, + struct pipe_resource *dst_tex, + unsigned dst_x, unsigned dst_y, unsigned dst_z, + unsigned dst_level, unsigned dst_face, + unsigned width, unsigned height, unsigned depth) +{ + enum pipe_error ret; + uint32 srcSubResource, dstSubResource; + struct svga_texture *dtex, *stex; + SVGA3dCopyBox box; + int i, num_layers = 1; + + stex = svga_texture(src_tex); + dtex = svga_texture(dst_tex); + + box.x = dst_x; + box.y = dst_y; + box.z = dst_z; + box.w = width; + box.h = height; + box.d = depth; + box.srcx = src_x; + box.srcy = src_y; + box.srcz = src_z; + + if (src_tex->target == PIPE_TEXTURE_1D_ARRAY || + src_tex->target == PIPE_TEXTURE_2D_ARRAY) { + /* copy layer by layer */ + box.z = 0; + box.d = 1; + box.srcz = 0; + + num_layers = depth; + src_face = src_z; + dst_face = dst_z; + } + + /* loop over array layers */ + for (i = 0; i < num_layers; i++) { + srcSubResource = (src_face + i) * (src_tex->last_level + 1) + src_level; + dstSubResource = (dst_face + i) * (dst_tex->last_level + 1) + dst_level; + + ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc, + dtex->handle, dstSubResource, + stex->handle, srcSubResource, &box); + if (ret != PIPE_OK) { + svga_context_flush(svga, NULL); + ret = SVGA3D_vgpu10_PredCopyRegion(svga->swc, + dtex->handle, dstSubResource, + stex->handle, srcSubResource, &box); + assert(ret == PIPE_OK); + } + + svga_define_texture_level(dtex, dst_face + i, dst_level); + } +} + + static void svga_resource_copy_region(struct pipe_context *pipe, - struct pipe_resource* dst_tex, + struct pipe_resource *dst_tex, unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, - struct pipe_resource* src_tex, + struct pipe_resource *src_tex, unsigned src_level, const struct pipe_box *src_box) { @@ -100,6 +164,52 @@ svga_resource_copy_region(struct pipe_context *pipe, } +/** + * The state tracker implements some resource copies with blits (for + * GL_ARB_copy_image). This function checks if we should really do the blit + * with a VGPU10 CopyRegion command or software fallback (for incompatible + * src/dst formats). + */ +static bool +can_blit_via_copy_region_vgpu10(struct svga_context *svga, + const struct pipe_blit_info *blit_info) +{ + struct svga_texture *dtex, *stex; + + if (!svga_have_vgpu10(svga)) + return false; + + stex = svga_texture(blit_info->src.resource); + dtex = svga_texture(blit_info->src.resource); + + // can't copy within one resource + if (stex->handle == dtex->handle) + return false; + + // can't copy between different resource types + if (blit_info->src.resource->target != blit_info->dst.resource->target) + return false; + + // check that the blit src/dst regions are same size, no flipping, etc. + if (blit_info->src.box.width != blit_info->dst.box.width || + blit_info->src.box.height != blit_info->dst.box.height) + return false; + + // depth/stencil copies not supported at this time + if (blit_info->mask != PIPE_MASK_RGBA) + return false; + + if (blit_info->alpha_blend || blit_info->render_condition_enable || + blit_info->scissor_enable) + return false; + + // check that src/dst surface formats are compatible for the VGPU device. + return util_is_format_compatible( + util_format_description(blit_info->src.resource->format), + util_format_description(blit_info->dst.resource->format)); +} + + static void svga_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) @@ -115,6 +225,41 @@ svga_blit(struct pipe_context *pipe, return; } + if (can_blit_via_copy_region_vgpu10(svga, blit_info)) { + unsigned src_face, src_z, dst_face, dst_z; + + if (blit_info->src.resource->target == PIPE_TEXTURE_CUBE) { + src_face = blit_info->src.box.z; + src_z = 0; + assert(blit_info->src.box.depth == 1); + } + else { + src_face = 0; + src_z = blit_info->src.box.z; + } + + if (blit_info->dst.resource->target == PIPE_TEXTURE_CUBE) { + dst_face = blit_info->dst.box.z; + dst_z = 0; + assert(blit_info->src.box.depth == 1); + } + else { + dst_face = 0; + dst_z = blit_info->dst.box.z; + } + + copy_region_vgpu10(svga, + blit_info->src.resource, + blit_info->src.box.x, blit_info->src.box.y, src_z, + blit_info->src.level, src_face, + blit_info->dst.resource, + blit_info->dst.box.x, blit_info->dst.box.y, dst_z, + blit_info->dst.level, dst_face, + blit_info->src.box.width, blit_info->src.box.height, + blit_info->src.box.depth); + return; + } + if (util_try_blit_via_copy_region(pipe, blit_info)) { return; /* done */ } -- 2.7.4