diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 67abc25..ec49b45 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -6079,13 +6079,15 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx, const struct pipe_box *src_box) { char *tptr; - uint32_t transfer_size; + uint32_t transfer_size, src_stride, dst_stride; GLenum glformat, gltype; int elsize = util_format_get_blocksize(dst_res->base.format); int compressed = util_format_is_compressed(dst_res->base.format); int cube_slice = 1; uint32_t slice_size, slice_offset; int i; + struct pipe_box box; + if (src_res->target == GL_TEXTURE_CUBE_MAP) cube_slice = 6; @@ -6094,6 +6096,12 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx, return; } + box = *src_box; + box.depth = vrend_get_texture_depth(src_res, src_level); + + src_stride = util_format_get_stride(src_res->base.format, src_res->base.width0); + dst_stride = util_format_get_stride(dst_res->base.format, dst_res->base.width0); + /* this is ugly need to do a full GetTexImage */ slice_size = util_format_get_nblocks(src_res->base.format, u_minify(src_res->base.width0, src_level), u_minify(src_res->base.height0, src_level)) * util_format_get_blocksize(src_res->base.format); @@ -6109,43 +6117,61 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx, if (compressed) glformat = tex_conv_table[src_res->base.format].internalformat; - switch (elsize) { - case 1: - glPixelStorei(GL_PACK_ALIGNMENT, 1); - break; - case 2: - glPixelStorei(GL_PACK_ALIGNMENT, 2); - break; - case 4: - default: - glPixelStorei(GL_PACK_ALIGNMENT, 4); - break; - case 8: - glPixelStorei(GL_PACK_ALIGNMENT, 8); - break; - } - glBindTexture(src_res->target, src_res->id); - - slice_offset = 0; - for (i = 0; i < cube_slice; i++) { - GLenum ctarget = src_res->target == GL_TEXTURE_CUBE_MAP ? - (GLenum)(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i) : src_res->target; - if (compressed) { - if (vrend_state.have_arb_robustness) - glGetnCompressedTexImageARB(ctarget, src_level, transfer_size, tptr + slice_offset); - else if (vrend_state.use_gles) - report_gles_missing_func(ctx, "glGetCompressedTexImage"); - else - glGetCompressedTexImage(ctarget, src_level, tptr + slice_offset); - } else { - if (vrend_state.have_arb_robustness) - glGetnTexImageARB(ctarget, src_level, glformat, gltype, transfer_size, tptr + slice_offset); - else if (vrend_state.use_gles) - report_gles_missing_func(ctx, "glGetTexImage"); - else - glGetTexImage(ctarget, src_level, glformat, gltype, tptr + slice_offset); + /* If we are on gles we need to rely on the textures backing + * iovec to have the data we need, otherwise we can use glGetTexture + */ + if (vrend_state.use_gles) { + read_transfer_data(&src_res->base, src_res->iov, src_res->num_iovs, + tptr, src_stride, &box, src_level, 0, false); + /* Sync the dst iovec backing store because + * we might need it in a chain copy A->B, B->C */ + write_transfer_data(&dst_res->base, dst_res->iov, dst_res->num_iovs, tptr, + dst_stride, &box, src_level, 0, false); + /* we get values from the guest as 24-bit scaled integers + but we give them to the host GL and it interprets them + as 32-bit scaled integers, so we need to scale them here */ + if (dst_res->base.format == (enum pipe_format)VIRGL_FORMAT_Z24X8_UNORM) { + float depth_scale = 256.0; + vrend_scale_depth(tptr, transfer_size, depth_scale); + } + } else { + switch (elsize) { + case 1: + glPixelStorei(GL_PACK_ALIGNMENT, 1); + break; + case 2: + glPixelStorei(GL_PACK_ALIGNMENT, 2); + break; + case 4: + default: + glPixelStorei(GL_PACK_ALIGNMENT, 4); + break; + case 8: + glPixelStorei(GL_PACK_ALIGNMENT, 8); + break; + } + glBindTexture(src_res->target, src_res->id); + slice_offset = 0; + for (i = 0; i < cube_slice; i++) { + GLenum ctarget = src_res->target == GL_TEXTURE_CUBE_MAP ? + (GLenum)(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i) : src_res->target; + if (compressed) { + if (vrend_state.have_arb_robustness) + glGetnCompressedTexImageARB(ctarget, src_level, transfer_size, tptr + slice_offset); + else if (vrend_state.use_gles) + report_gles_missing_func(ctx, "glGetCompressedTexImage"); + else + glGetCompressedTexImage(ctarget, src_level, tptr + slice_offset); + } else { + if (vrend_state.have_arb_robustness) + glGetnTexImageARB(ctarget, src_level, glformat, gltype, transfer_size, tptr + slice_offset); + else if (vrend_state.use_gles) + report_gles_missing_func(ctx, "glGetTexImage"); + else + glGetTexImage(ctarget, src_level, glformat, gltype, tptr + slice_offset); + } + slice_offset += slice_size; } - slice_offset += slice_size; } glPixelStorei(GL_PACK_ALIGNMENT, 4);