From: Bas Nieuwenhuizen <ba...@chromium.org>

In vulkan linear images can have a stride that is larger than the
width, which impacts the utility functions from cru_image.
---
 include/tapi/t_image.h       | 12 ++++++++++++
 include/util/cru_image.h     |  8 ++++++++
 src/framework/test/t_image.c | 15 +++++++++++++++
 src/util/cru_image.c         | 22 ++++++++--------------
 src/util/cru_image.h         |  5 ++++-
 src/util/cru_pixel_image.c   | 30 +++++++++++++++++++++++++++++-
 src/util/cru_png_image.c     |  9 +++------
 src/util/cru_vk_image.c      |  2 +-
 8 files changed, 80 insertions(+), 23 deletions(-)

diff --git a/include/tapi/t_image.h b/include/tapi/t_image.h
index 77a6ed6..71a22d4 100644
--- a/include/tapi/t_image.h
+++ b/include/tapi/t_image.h
@@ -64,3 +64,15 @@ t_new_cru_image_from_vk_image(VkDevice dev, VkQueue queue, 
VkImage image,
 malloclike cru_image_t *
 t_new_cru_image_from_pixels(void *restrict pixels, VkFormat format,
                             uint32_t width, uint32_t height);
+
+/// \brief Create a Crucible image from an array of pixels.
+///
+/// This is a wrapper around cru_image_from_pixels_with_stride(). On success,
+/// the new image is pushed onto the test thread's cleanup stack.  On failure,
+/// the test fails.
+///
+/// \see cru_image_from_from_pixels_with_stride()
+malloclike cru_image_t *
+t_new_cru_image_from_pixels_with_stride(void *restrict pixels, VkFormat format,
+                                        uint32_t width, uint32_t height,
+                                        uint32_t stride);
diff --git a/include/util/cru_image.h b/include/util/cru_image.h
index 48db399..ef63008 100644
--- a/include/util/cru_image.h
+++ b/include/util/cru_image.h
@@ -66,6 +66,14 @@ malloclike cru_image_t *
 cru_image_from_pixels(void *restrict pixels, VkFormat format,
                       uint32_t width, uint32_t height);
 
+/// \brief Create a Crucible image from an array of pixels.
+///
+/// If writing a test, consider using 
t_new_cru_image_from_pixels_with_stride(),
+/// which has a simpler interface.
+malloclike cru_image_t *
+cru_image_from_pixels_with_stride(void *restrict pixels, VkFormat format,
+                                  uint32_t width, uint32_t height,
+                                  uint32_t stride);
 
 /// \brief Create a Crucible image from a file.
 ///
diff --git a/src/framework/test/t_image.c b/src/framework/test/t_image.c
index 266ce6d..01cb91e 100644
--- a/src/framework/test/t_image.c
+++ b/src/framework/test/t_image.c
@@ -70,3 +70,18 @@ t_new_cru_image_from_pixels(void *restrict pixels, VkFormat 
format,
 
     return cimg;
 }
+
+malloclike cru_image_t *
+t_new_cru_image_from_pixels_with_stride(void *restrict pixels, VkFormat format,
+                                        uint32_t width, uint32_t height, 
uint32_t stride)
+{
+    t_thread_yield();
+
+    cru_image_t *cimg = cru_image_from_pixels_with_stride(pixels, format, 
width, height, stride);
+    if (!cimg)
+        t_failf("%s: failed to create image", __func__);
+
+    t_cleanup_push_cru_image(cimg);
+
+    return cimg;
+}
diff --git a/src/util/cru_image.c b/src/util/cru_image.c
index 7860ad3..1e9bd98 100644
--- a/src/util/cru_image.c
+++ b/src/util/cru_image.c
@@ -90,7 +90,7 @@ cru_image_get_format(cru_image_t *image)
 bool
 cru_image_init(cru_image_t *image, enum cru_image_type type,
                VkFormat format, uint32_t width, uint32_t height,
-               bool read_only)
+               bool read_only, uint32_t stride)
 {
     cru_refcount_init(&image->refcount);
 
@@ -115,6 +115,8 @@ cru_image_init(cru_image_t *image, enum cru_image_type type,
     image->type = type;
     image->read_only = read_only;
 
+    image->stride = stride ? stride : image->format_info->cpp * width;
+
     return true;
 }
 
@@ -299,12 +301,6 @@ cru_image_copy_pixels_to_pixels(cru_image_t *dest, 
cru_image_t *src)
     const uint32_t width = src->width;
     const uint32_t height = src->height;
 
-    const uint32_t src_cpp = src->format_info->cpp;
-    const uint32_t src_stride = src_cpp * width;
-
-    const uint32_t dest_cpp = dest->format_info->cpp;
-    const uint32_t dest_stride = dest_cpp * width;
-
     assert(!dest->read_only);
 
     // Extent equality is enforced by cru_image_check_compatible().
@@ -320,7 +316,7 @@ cru_image_copy_pixels_to_pixels(cru_image_t *dest, 
cru_image_t *src)
         goto fail_map_dest_pixels;
 
     if (src->format_info == dest->format_info
-        && src_stride == dest_stride) {
+        && src->stride == dest->stride) {
         copy_func = copy_oneshot_memcpy;
     } else if (src_format == VK_FORMAT_R8_UNORM &&
                dest_format == VK_FORMAT_D32_SFLOAT) {
@@ -340,8 +336,8 @@ cru_image_copy_pixels_to_pixels(cru_image_t *dest, 
cru_image_t *src)
     }
 
     result = copy_func(width, height,
-                       src_pixels, 0, 0, src_stride,
-                       dest_pixels, 0, 0, dest_stride);
+                       src_pixels, 0, 0, src->stride,
+                       dest_pixels, 0, 0, dest->stride);
 
 fail_no_copy_func:
 
@@ -422,8 +418,6 @@ cru_image_compare_rect(cru_image_t *a, uint32_t a_x, 
uint32_t a_y,
 
     const uint32_t cpp = a->format_info->cpp;
     const uint32_t row_size = cpp * width;
-    const uint32_t a_stride = cpp * a->width;
-    const uint32_t b_stride = cpp * b->width;
 
     a_map = a->map_pixels(a, CRU_IMAGE_MAP_ACCESS_READ);
     if (!a_map)
@@ -436,8 +430,8 @@ cru_image_compare_rect(cru_image_t *a, uint32_t a_x, 
uint32_t a_y,
     // FINISHME: Support a configurable tolerance.
     // FINISHME: Support dumping the diff to file.
     for (uint32_t y = 0; y < height; ++y) {
-        const void *a_row = a_map + ((a_y + y) * a_stride + a_x * cpp);
-        const void *b_row = b_map + ((b_y + y) * b_stride + b_x * cpp);
+        const void *a_row = a_map + ((a_y + y) * a->stride + a_x * cpp);
+        const void *b_row = b_map + ((b_y + y) * b->stride + b_x * cpp);
 
         if (memcmp(a_row, b_row, row_size) != 0) {
             loge("%s: diff found in row %u of rect", __func__, y);
diff --git a/src/util/cru_image.h b/src/util/cru_image.h
index fae72d0..2d74125 100644
--- a/src/util/cru_image.h
+++ b/src/util/cru_image.h
@@ -39,6 +39,9 @@ struct cru_image {
     uint32_t height;
     bool read_only;
 
+    /* stride in bytes */
+    uint32_t stride;
+
     cru_refcount_t refcount;
     enum cru_image_type type;
 
@@ -54,7 +57,7 @@ struct cru_image {
 // file: cru_image.c
 bool
 cru_image_init(cru_image_t *image, enum cru_image_type type, VkFormat format,
-               uint32_t width, uint32_t height, bool read_only);
+               uint32_t width, uint32_t height, bool read_only, uint32_t 
stride);
 char *cru_image_get_abspath(const char *filename);
 
 // file: cru_png_image.c
diff --git a/src/util/cru_pixel_image.c b/src/util/cru_pixel_image.c
index d9ed531..2034f09 100644
--- a/src/util/cru_pixel_image.c
+++ b/src/util/cru_pixel_image.c
@@ -79,7 +79,35 @@ cru_image_from_pixels(void *restrict pixels,
 
     if (!cru_image_init(&kpix_image->image, CRU_IMAGE_TYPE_PIXELS,
                         format, width, height,
-                        /*read_only*/ false)) {
+                        /*read_only*/ false, 0)) {
+        goto fail;
+    }
+
+    kpix_image->pixels = pixels;
+    kpix_image->map_access = 0;
+
+    kpix_image->image.destroy = cru_pixel_image_destroy;
+    kpix_image->image.map_pixels = cru_pixel_image_map_pixels;
+    kpix_image->image.unmap_pixels = cru_pixel_image_unmap_pixels;
+
+    return &kpix_image->image;
+
+fail:
+    cru_pixel_image_destroy((cru_image_t *) kpix_image);
+    return NULL;
+}
+
+cru_image_t *
+cru_image_from_pixels_with_stride(void *restrict pixels,
+                                  VkFormat format,
+                                  uint32_t width, uint32_t height,
+                                  uint32_t stride)
+{
+    cru_pixel_image_t *kpix_image = xmalloc(sizeof(*kpix_image));
+
+    if (!cru_image_init(&kpix_image->image, CRU_IMAGE_TYPE_PIXELS,
+                        format, width, height,
+                        /*read_only*/ false, stride)) {
         goto fail;
     }
 
diff --git a/src/util/cru_png_image.c b/src/util/cru_png_image.c
index 9a3ffb1..316cfbd 100644
--- a/src/util/cru_png_image.c
+++ b/src/util/cru_png_image.c
@@ -138,9 +138,7 @@ copy_direct_from_png(cru_image_t *src, cru_image_t *dest)
     png_structp png_reader = NULL;
     png_infop png_info = NULL;
 
-    const uint32_t width = src->width;
     const uint32_t height = src->height;
-    const uint32_t stride = width * src->format_info->cpp;
     uint8_t *dest_pixels = NULL;
     uint8_t *dest_rows[height];
 
@@ -157,7 +155,7 @@ copy_direct_from_png(cru_image_t *src, cru_image_t *dest)
         return false;
 
     for (uint32_t y = 0; y < height; ++y) {
-        dest_rows[y] = dest_pixels + y * stride;
+        dest_rows[y] = dest_pixels + y * src->stride;
     }
 
     // FINISHME: Error callbacks for libpng
@@ -368,7 +366,7 @@ cru_png_image_load_file(const char *filename)
     if (!cru_image_init(&png_image->image,
                         CRU_IMAGE_TYPE_PNG,
                         format, width, height,
-                        /*read_only*/ true)) {
+                        /*read_only*/ true, 0)) {
         goto fail_image_init;
     }
 
@@ -402,7 +400,6 @@ write_direct_to_png(cru_image_t *image, const string_t 
*filename)
     char *abspath = NULL;
     const uint32_t src_width = image->width;
     const uint32_t src_height = image->height;
-    const uint32_t src_stride = image->format_info->cpp * src_width;
     uint8_t *src_pixels = NULL;
     uint8_t *src_rows[src_height];
 
@@ -442,7 +439,7 @@ write_direct_to_png(cru_image_t *image, const string_t 
*filename)
         goto fail_map_pixels;
 
     for (uint32_t y = 0; y < src_height; ++y) {
-        src_rows[y] = src_pixels + y * src_stride;
+        src_rows[y] = src_pixels + y * image->stride;
     }
 
     f = fopen(abspath, "wb");
diff --git a/src/util/cru_vk_image.c b/src/util/cru_vk_image.c
index aea540e..8c7118e 100644
--- a/src/util/cru_vk_image.c
+++ b/src/util/cru_vk_image.c
@@ -300,7 +300,7 @@ cru_image_from_vk_image(VkDevice dev, VkQueue queue, 
VkImage image,
     if (!cru_image_init(&self->cru_image, CRU_IMAGE_TYPE_VULKAN, format,
                         cru_minify(level0_width, miplevel),
                         cru_minify(level0_height, miplevel),
-                        /*read_only*/ false)) {
+                        /*read_only*/ false, 0)) {
         goto fail;
     }
 
-- 
2.16.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to