llvmpipe: add multisample resource copy region support.
authorDave Airlie <airlied@redhat.com>
Tue, 10 Mar 2020 03:36:36 +0000 (13:36 +1000)
committerMarge Bot <eric+marge@anholt.net>
Wed, 6 May 2020 06:20:37 +0000 (06:20 +0000)
This allows direct copies of all samples between two resources.

Reviewed-by: Roland Scheidegger <sroland@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4122>

src/gallium/drivers/llvmpipe/lp_surface.c

index e9d7e50020e76253525b9e72cad23daf76dd8645..879cfc7793cc84997d20f3a7d28cd8c4ec137037 100644 (file)
 #include "lp_query.h"
 #include "lp_rast.h"
 
+static void
+lp_resource_copy_ms(struct pipe_context *pipe,
+                    struct pipe_resource *dst, unsigned dst_level,
+                    unsigned dstx, unsigned dsty, unsigned dstz,
+                    struct pipe_resource *src, unsigned src_level,
+                    const struct pipe_box *src_box)
+{
+   struct pipe_box dst_box = *src_box;
+   enum pipe_format src_format;
+   dst_box.x = dstx;
+   dst_box.y = dsty;
+   dst_box.z = dstz;
+
+   src_format = src->format;
+
+   for (unsigned i = 0; i < src->nr_samples; i++) {
+      struct pipe_transfer *src_trans, *dst_trans;
+      const uint8_t *src_map = llvmpipe_transfer_map_ms(pipe,
+                                                        src, 0, PIPE_TRANSFER_READ, i,
+                                                        src_box,
+                                                        &src_trans);
+      if (!src_map)
+         return;
+
+      uint8_t *dst_map = llvmpipe_transfer_map_ms(pipe,
+                                                  dst, 0, PIPE_TRANSFER_WRITE, i,
+                                                  &dst_box,
+                                                  &dst_trans);
+      if (!dst_map) {
+         pipe->transfer_unmap(pipe, src_trans);
+         return;
+      }
+
+      util_copy_box(dst_map,
+                    src_format,
+                    dst_trans->stride, dst_trans->layer_stride,
+                    0, 0, 0,
+                    src_box->width, src_box->height, src_box->depth,
+                    src_map,
+                    src_trans->stride, src_trans->layer_stride,
+                    0, 0, 0);
+      pipe->transfer_unmap(pipe, dst_trans);
+      pipe->transfer_unmap(pipe, src_trans);
+   }
+}
 static void
 lp_resource_copy(struct pipe_context *pipe,
                  struct pipe_resource *dst, unsigned dst_level,
@@ -56,6 +101,12 @@ lp_resource_copy(struct pipe_context *pipe,
                            FALSE, /* do_not_block */
                            "blit src");
 
+   if (dst->nr_samples > 1 &&
+       dst->nr_samples == src->nr_samples) {
+      lp_resource_copy_ms(pipe, dst, dst_level, dstx, dsty, dstz,
+                          src, src_level, src_box);
+      return;
+   }
    util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
                              src, src_level, src_box);
 }