diff options
author | Juan A. Suarez Romero <jasuarez@igalia.com> | 2022-04-13 20:06:21 +0200 |
---|---|---|
committer | Marge Bot <emma+marge@anholt.net> | 2022-04-19 08:03:42 +0000 |
commit | 606e42027e61aa759eb7ac69403e13816f8ccde1 (patch) | |
tree | 4783c5068684f73425509ad4f733423de5a72b4e | |
parent | 21bfbc74eea000b9768371a12f5edc20bed715ae (diff) |
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@igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15693>
-rw-r--r-- | src/gallium/include/pipe/p_context.h | 10 | ||||
-rw-r--r-- | 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 @@ -1000,6 +1000,16 @@ struct pipe_context { /*@}*/ /** + * 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. * * \param sample_count - total number of samples 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; |