Mesa (main): gallium: add hook on getting canonical format

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Apr 19 08:48:38 UTC 2022


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

Author: Juan A. Suarez Romero <jasuarez at igalia.com>
Date:   Wed Apr 13 20:06:21 2022 +0200

gallium: add hook on getting canonical format

On swizzled copies canonical formats are used to reduce the formats to a
simpler subset.

Nevertheless, it is possible that some of the canonical formats defined
in Gallium are actually not supported by the drivers themselves.

This provides a driver-defined hook that can be used to provide an
alternative canonical format in case the canonical one defined by
Gallium is not supported by the driver.

Signed-off-by: Juan A. Suarez Romero <jasuarez at igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15693>

---

 src/gallium/include/pipe/p_context.h     | 10 ++++++
 src/mesa/state_tracker/st_cb_copyimage.c | 53 +++++++++++++++++++-------------
 2 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 75e30da09f9..c5b20f4cd23 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -999,6 +999,16 @@ struct pipe_context {
                        bool to_device, bool migrate_content);
    /*@}*/
 
+   /**
+    * Return an equivalent canonical format which has the same component sizes
+    * and swizzles as the original, and it is supported by the driver. Gallium
+    * already does a first canonicalization step (see get_canonical_format()
+    * on st_cb_copyimage.c) and it calls this function (if defined) to get an
+    * alternative format if the picked is not supported by the driver.
+    */
+   enum pipe_format (*get_canonical_format)(struct pipe_context *context,
+                                            enum pipe_format format);
+
    /**
     * Get the default sample position for an individual sample point.
     *
diff --git a/src/mesa/state_tracker/st_cb_copyimage.c b/src/mesa/state_tracker/st_cb_copyimage.c
index 25ae78045b2..72c7bcda0c5 100644
--- a/src/mesa/state_tracker/st_cb_copyimage.c
+++ b/src/mesa/state_tracker/st_cb_copyimage.c
@@ -54,7 +54,8 @@
  * formats are not supported. (same as ARB_copy_image)
  */
 static enum pipe_format
-get_canonical_format(enum pipe_format format)
+get_canonical_format(struct pipe_context *pipe,
+                     enum pipe_format format)
 {
    const struct util_format_description *desc =
       util_format_description(format);
@@ -62,7 +63,7 @@ get_canonical_format(enum pipe_format format)
    /* Packed formats. Return the equivalent array format. */
    if (format == PIPE_FORMAT_R11G11B10_FLOAT ||
        format == PIPE_FORMAT_R9G9B9E5_FLOAT)
-      return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT);
+      return get_canonical_format(pipe, PIPE_FORMAT_R8G8B8A8_UINT);
 
    if (desc->nr_channels == 4 &&
        desc->channel[0].size == 10 &&
@@ -72,32 +73,40 @@ get_canonical_format(enum pipe_format format)
       if (desc->swizzle[0] == PIPE_SWIZZLE_X &&
           desc->swizzle[1] == PIPE_SWIZZLE_Y &&
           desc->swizzle[2] == PIPE_SWIZZLE_Z)
-         return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R8G8B8A8_UINT);
 
       return PIPE_FORMAT_NONE;
    }
 
 #define RETURN_FOR_SWIZZLE1(x, format) \
    if (desc->swizzle[0] == PIPE_SWIZZLE_##x) \
-      return format
+      return (pipe->get_canonical_format ? \
+              pipe->get_canonical_format(pipe, format) : \
+              format)
 
 #define RETURN_FOR_SWIZZLE2(x, y, format) \
    if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
        desc->swizzle[1] == PIPE_SWIZZLE_##y) \
-      return format
+      return (pipe->get_canonical_format ? \
+              pipe->get_canonical_format(pipe, format) : \
+              format)
 
 #define RETURN_FOR_SWIZZLE3(x, y, z, format) \
    if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
        desc->swizzle[1] == PIPE_SWIZZLE_##y && \
        desc->swizzle[2] == PIPE_SWIZZLE_##z) \
-      return format
+      return (pipe->get_canonical_format ? \
+              pipe->get_canonical_format(pipe, format) : \
+              format)
 
 #define RETURN_FOR_SWIZZLE4(x, y, z, w, format) \
    if (desc->swizzle[0] == PIPE_SWIZZLE_##x && \
        desc->swizzle[1] == PIPE_SWIZZLE_##y && \
        desc->swizzle[2] == PIPE_SWIZZLE_##z && \
        desc->swizzle[3] == PIPE_SWIZZLE_##w) \
-      return format
+      return (pipe->get_canonical_format ? \
+              pipe->get_canonical_format(pipe, format) : \
+              format)
 
    /* Array formats. */
    if (desc->is_array) {
@@ -208,40 +217,42 @@ has_identity_swizzle(const struct util_format_description *desc)
  * Return a canonical format for the given bits and channel size.
  */
 static enum pipe_format
-canonical_format_from_bits(unsigned bits, unsigned channel_size)
+canonical_format_from_bits(struct pipe_context *pipe,
+                           unsigned bits,
+                           unsigned channel_size)
 {
    switch (bits) {
    case 8:
       if (channel_size == 8)
-         return get_canonical_format(PIPE_FORMAT_R8_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R8_UINT);
       break;
 
    case 16:
       if (channel_size == 8)
-         return get_canonical_format(PIPE_FORMAT_R8G8_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R8G8_UINT);
       if (channel_size == 16)
-         return get_canonical_format(PIPE_FORMAT_R16_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R16_UINT);
       break;
 
    case 32:
       if (channel_size == 8)
-         return get_canonical_format(PIPE_FORMAT_R8G8B8A8_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R8G8B8A8_UINT);
       if (channel_size == 16)
-         return get_canonical_format(PIPE_FORMAT_R16G16_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R16G16_UINT);
       if (channel_size == 32)
-         return get_canonical_format(PIPE_FORMAT_R32_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R32_UINT);
       break;
 
    case 64:
       if (channel_size == 16)
-         return get_canonical_format(PIPE_FORMAT_R16G16B16A16_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R16G16B16A16_UINT);
       if (channel_size == 32)
-         return get_canonical_format(PIPE_FORMAT_R32G32_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R32G32_UINT);
       break;
 
    case 128:
       if (channel_size == 32)
-         return get_canonical_format(PIPE_FORMAT_R32G32B32A32_UINT);
+         return get_canonical_format(pipe, PIPE_FORMAT_R32G32B32A32_UINT);
       break;
    }
 
@@ -296,8 +307,8 @@ swizzled_copy(struct pipe_context *pipe,
     * about the channel type from this point on.
     * Only the swizzle and channel size.
     */
-   blit_src_format = get_canonical_format(src->format);
-   blit_dst_format = get_canonical_format(dst->format);
+   blit_src_format = get_canonical_format(pipe, src->format);
+   blit_dst_format = get_canonical_format(pipe, dst->format);
 
    assert(blit_src_format != PIPE_FORMAT_NONE);
    assert(blit_dst_format != PIPE_FORMAT_NONE);
@@ -318,14 +329,14 @@ swizzled_copy(struct pipe_context *pipe,
        * e.g. R32 -> BGRA8 is realized as RGBA8 -> BGRA8
        */
       blit_src_format =
-         canonical_format_from_bits(bits, dst_desc->channel[0].size);
+         canonical_format_from_bits(pipe, bits, dst_desc->channel[0].size);
    } else if (has_identity_swizzle(dst_desc)) {
       /* Dst is unswizzled and src can be swizzled, so dst is typecast
        * to an equivalent src-compatible format.
        * e.g. BGRA8 -> R32 is realized as BGRA8 -> RGBA8
        */
       blit_dst_format =
-         canonical_format_from_bits(bits, src_desc->channel[0].size);
+         canonical_format_from_bits(pipe, bits, src_desc->channel[0].size);
    } else {
       assert(!"This should have been handled by handle_complex_copy.");
       return;



More information about the mesa-commit mailing list