Module: Mesa
Branch: main
Commit: 673d241f36907839c78b0382d9c3af6112d0c626
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=673d241f36907839c78b0382d9c3af6112d0c626

Author: Erik Faye-Lund <[email protected]>
Date:   Thu Aug 11 11:07:52 2022 +0200

mesa/st: avoid double-mapping if both images are the same

If both src_image and dst_image are pointing to the same image, we'll
end up double mapping the image, which throws an assert in
st_texture_image_map.

So let's check if these images are the same, and avoid the extra mapping
in that case.

Acked-by: Marek Olšák <[email protected]>
Acked-by: Soroush Kashani <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18012>

---

 src/mesa/state_tracker/st_cb_copyimage.c | 66 ++++++++++++++++++++++----------
 1 file changed, 45 insertions(+), 21 deletions(-)

diff --git a/src/mesa/state_tracker/st_cb_copyimage.c 
b/src/mesa/state_tracker/st_cb_copyimage.c
index 1a1f3536ad4..633182dffd4 100644
--- a/src/mesa/state_tracker/st_cb_copyimage.c
+++ b/src/mesa/state_tracker/st_cb_copyimage.c
@@ -589,30 +589,53 @@ fallback_copy_image(struct st_context *st,
    else
       line_bytes = _mesa_format_row_stride(dst_image->TexFormat, dst_w);
 
-   if (dst_image) {
+   if (src_image == dst_image && src_z == dst_z) {
+      assert(dst_image != NULL);
+
+      /* calculate bounding-box of the two rectangles */
+      int min_x = MIN2(src_x, dst_x);
+      int min_y = MIN2(src_y, dst_y);
+      int max_x = MAX2(src_x + src_w, dst_x + dst_w);
+      int max_y = MAX2(src_y + src_h, dst_y + dst_h);
       st_MapTextureImage(
             st->ctx, dst_image, dst_z,
-            dst_x, dst_y, dst_w, dst_h,
-            GL_MAP_WRITE_BIT, &dst, &dst_stride);
+            min_x, min_y, max_x - min_x, max_y - min_y,
+            GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &dst, &dst_stride);
+      src = dst;
+      src_stride = dst_stride;
+
+      /* adjust pointers */
+      int format_bytes = _mesa_get_format_bytes(dst_image->TexFormat);
+      src += ((src_y - min_y) / src_blk_h) * src_stride;
+      src += ((src_x - min_x) / src_blk_w) * format_bytes;
+      dst += ((dst_y - min_y) / src_blk_h) * dst_stride;
+      dst += ((dst_x - min_x) / dst_blk_w) * format_bytes;
    } else {
-      dst = pipe_texture_map(st->pipe, dst_res, 0, dst_z,
-                              PIPE_MAP_WRITE,
-                              dst_x, dst_y, dst_w, dst_h,
-                              &dst_transfer);
-      dst_stride = dst_transfer->stride;
-   }
+      if (dst_image) {
+         st_MapTextureImage(
+               st->ctx, dst_image, dst_z,
+               dst_x, dst_y, dst_w, dst_h,
+               GL_MAP_WRITE_BIT, &dst, &dst_stride);
+      } else {
+         dst = pipe_texture_map(st->pipe, dst_res, 0, dst_z,
+                                 PIPE_MAP_WRITE,
+                                 dst_x, dst_y, dst_w, dst_h,
+                                 &dst_transfer);
+         dst_stride = dst_transfer->stride;
+      }
 
-   if (src_image) {
-      st_MapTextureImage(
-            st->ctx, src_image, src_z,
-            src_x, src_y, src_w, src_h,
-            GL_MAP_READ_BIT, &src, &src_stride);
-   } else {
-      src = pipe_texture_map(st->pipe, src_res, 0, src_z,
-                              PIPE_MAP_READ,
-                              src_x, src_y, src_w, src_h,
-                              &src_transfer);
-      src_stride = src_transfer->stride;
+      if (src_image) {
+         st_MapTextureImage(
+               st->ctx, src_image, src_z,
+               src_x, src_y, src_w, src_h,
+               GL_MAP_READ_BIT, &src, &src_stride);
+      } else {
+         src = pipe_texture_map(st->pipe, src_res, 0, src_z,
+                                 PIPE_MAP_READ,
+                                 src_x, src_y, src_w, src_h,
+                                 &src_transfer);
+         src_stride = src_transfer->stride;
+      }
    }
 
    for (int y = 0; y < lines; y++) {
@@ -628,7 +651,8 @@ fallback_copy_image(struct st_context *st,
    }
 
    if (src_image) {
-      st_UnmapTextureImage(st->ctx, src_image, src_z);
+      if (src_image != dst_image || src_z != dst_z)
+         st_UnmapTextureImage(st->ctx, src_image, src_z);
    } else {
       pipe_texture_unmap(st->pipe, src_transfer);
    }

Reply via email to