From 23ccf5c1a9b81552ff4f1b9e43694a3805944ec4 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Mon, 27 May 2019 14:19:41 +0300 Subject: [PATCH] vrend: Use the transfer layer stride for transfers to the host This is required to be able to properly handle transfers with data layouts that are different from the resource layout. Signed-off-by: Alexandros Frantzis Reviewed-by: Chia-I Wu --- src/vrend_renderer.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 2533f63..21a0ddb 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -6284,22 +6284,22 @@ static void vrend_scale_depth(void *ptr, int size, float scale_val) } } -static void read_transfer_data(struct pipe_resource *res, - struct iovec *iov, +static void read_transfer_data(struct iovec *iov, unsigned int num_iovs, char *data, + enum pipe_format format, + uint64_t offset, uint32_t src_stride, + uint32_t src_layer_stride, struct pipe_box *box, - uint32_t level, - uint64_t offset, bool invert) { - int blsize = util_format_get_blocksize(res->format); + int blsize = util_format_get_blocksize(format); uint32_t size = vrend_get_iovec_size(iov, num_iovs); - uint32_t send_size = util_format_get_nblocks(res->format, box->width, + uint32_t send_size = util_format_get_nblocks(format, box->width, box->height) * blsize * box->depth; - uint32_t bwx = util_format_get_nblocksx(res->format, box->width) * blsize; - int32_t bh = util_format_get_nblocksy(res->format, box->height); + uint32_t bwx = util_format_get_nblocksx(format, box->width) * blsize; + int32_t bh = util_format_get_nblocksy(format, box->height); int d, h; if ((send_size == size || bh == 1) && !invert && box->depth == 1) @@ -6307,7 +6307,7 @@ static void read_transfer_data(struct pipe_resource *res, else { if (invert) { for (d = 0; d < box->depth; d++) { - uint32_t myoffset = offset + d * src_stride * u_minify(res->height0, level); + uint32_t myoffset = offset + d * src_layer_stride; for (h = bh - 1; h >= 0; h--) { void *ptr = data + (h * bwx) + d * (bh * bwx); vrend_read_from_iovec(iov, num_iovs, myoffset, ptr, bwx); @@ -6316,7 +6316,7 @@ static void read_transfer_data(struct pipe_resource *res, } } else { for (d = 0; d < box->depth; d++) { - uint32_t myoffset = offset + d * src_stride * u_minify(res->height0, level); + uint32_t myoffset = offset + d * src_layer_stride; for (h = 0; h < bh; h++) { void *ptr = data + (h * bwx) + d * (bh * bwx); vrend_read_from_iovec(iov, num_iovs, myoffset, ptr, bwx); @@ -6561,6 +6561,7 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx, float depth_scale; GLuint send_size = 0; uint32_t stride = info->stride; + uint32_t layer_stride = info->layer_stride; if (ctx) vrend_use_program(ctx, 0); @@ -6570,6 +6571,10 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx, if (!stride) stride = util_format_get_nblocksx(res->base.format, u_minify(res->base.width0, info->level)) * elsize; + if (!layer_stride) + layer_stride = util_format_get_2d_size(res->base.format, stride, + u_minify(res->base.height0, info->level)); + compressed = util_format_is_compressed(res->base.format); if (num_iovs > 1 || compressed) { need_temp = true; @@ -6587,15 +6592,15 @@ static int vrend_renderer_transfer_write_iov(struct vrend_context *ctx, data = malloc(send_size); if (!data) return ENOMEM; - read_transfer_data(&res->base, iov, num_iovs, data, stride, - info->box, info->level, info->offset, invert); + read_transfer_data(iov, num_iovs, data, res->base.format, info->offset, + stride, layer_stride, info->box, invert); } else { data = (char*)iov[0].iov_base + info->offset; } if (stride && !need_temp) { glPixelStorei(GL_UNPACK_ROW_LENGTH, stride / elsize); - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, u_minify(res->base.height0, info->level)); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, layer_stride / stride); } else glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); @@ -7434,7 +7439,7 @@ static void vrend_resource_copy_fallback(struct vrend_resource *src_res, const struct pipe_box *src_box) { char *tptr; - uint32_t total_size, src_stride, dst_stride; + uint32_t total_size, src_stride, dst_stride, src_layer_stride; GLenum glformat, gltype; int elsize = util_format_get_blocksize(dst_res->base.format); int compressed = util_format_is_compressed(dst_res->base.format); @@ -7483,8 +7488,12 @@ static void vrend_resource_copy_fallback(struct vrend_resource *src_res, src_stride = util_format_get_nblocksx(src_res->base.format, u_minify(src_res->base.width0, src_level)) * elsize; - read_transfer_data(&src_res->base, src_res->iov, src_res->num_iovs, tptr, - src_stride, &box, src_level, src_offset, false); + src_layer_stride = util_format_get_2d_size(src_res->base.format, + src_stride, + u_minify(src_res->base.height0, src_level)); + read_transfer_data(src_res->iov, src_res->num_iovs, tptr, + src_res->base.format, src_offset, + src_stride, src_layer_stride, &box, false); /* When on GLES sync the iov that backs the dst resource 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,