[virglrenderer-devel] [PATCH] vrend: Copy from iovec to avoid needing glGetTexImage

Tomeu Vizoso tomeu.vizoso at collabora.com
Fri May 25 06:58:01 UTC 2018


GLES doesn't have glGetTexImage, so this is a way to get around that.

We rely on the existing assumption that a resource's backing iovec is
always in sync with the texture data if it isn't renderable.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso at collabora.com>
---
 src/vrend_renderer.c | 92 +++++++++++++++++++++++++++-----------------
 1 file changed, 57 insertions(+), 35 deletions(-)

diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 862a873cd812..1fccccbc28de 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -5809,13 +5809,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;
 
@@ -5824,6 +5826,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);
@@ -5839,42 +5847,51 @@ 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);
+   if (!vrend_format_can_render(src_res->base.format)) {
+      /*
+       * If the src resource isn't renderable, we can rely on its backing
+       * iovec having the data we need.
+       */
+      read_transfer_data(&src_res->base, src_res->iov, src_res->num_iovs,
+                         tptr, src_stride, &box, src_level, 0, false);
+   } 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 ? 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 = 0;
+      for (i = 0; i < cube_slice; i++) {
+         GLenum ctarget = src_res->target == GL_TEXTURE_CUBE_MAP ? 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);
@@ -5925,6 +5942,11 @@ static void vrend_resource_copy_fallback(struct vrend_context *ctx,
    }
 
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+   /* Sync the iov that backs the dst resource */
+   write_transfer_data(&dst_res->base, dst_res->iov, dst_res->num_iovs, tptr,
+                       dst_stride, &box, src_level, 0, false);
+
    free(tptr);
 }
 
-- 
2.17.0



More information about the virglrenderer-devel mailing list