mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-23 23:48:18 +02:00
In the C23 standard unreachable() is now a predefined function-like macro in <stddef.h> See https://android.googlesource.com/platform/bionic/+/HEAD/docs/c23.md#is-now-a-predefined-function_like-macro-in And this causes build errors when building for C23: ----------------------------------------------------------------------- In file included from ../src/util/log.h:30, from ../src/util/log.c:30: ../src/util/macros.h:123:9: warning: "unreachable" redefined 123 | #define unreachable(str) \ | ^~~~~~~~~~~ In file included from ../src/util/macros.h:31: /usr/lib/gcc/x86_64-linux-gnu/14/include/stddef.h:456:9: note: this is the location of the previous definition 456 | #define unreachable() (__builtin_unreachable ()) | ^~~~~~~~~~~ ----------------------------------------------------------------------- So don't redefine it with the same name, but use the name UNREACHABLE() to also signify it's a macro. Using a different name also makes sense because the behavior of the macro was extending the one of __builtin_unreachable() anyway, and it also had a different signature, accepting one argument, compared to the standard unreachable() with no arguments. This change improves the chances of building mesa with the C23 standard, which for instance is the default in recent AOSP versions. All the instances of the macro, including the definition, were updated with the following command line: git grep -l '[^_]unreachable(' -- "src/**" | sort | uniq | \ while read file; \ do \ sed -e 's/\([^_]\)unreachable(/\1UNREACHABLE(/g' -i "$file"; \ done && \ sed -e 's/#undef unreachable/#undef UNREACHABLE/g' -i src/intel/isl/isl_aux_info.c Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36437>
177 lines
5.5 KiB
C
177 lines
5.5 KiB
C
/*
|
|
* Copyright 2022 Alyssa Rosenzweig
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "util/format/format_utils.h"
|
|
#include "util/format/u_format.h"
|
|
#include "util/half_float.h"
|
|
#include "agx_helpers.h"
|
|
#include "agx_pack.h"
|
|
|
|
/*
|
|
* AGX allows the sampler descriptor to specify a custom border colour. The
|
|
* packing depends on the texture format (i.e. no
|
|
* customBorderColorWithoutFormat).
|
|
*
|
|
* Each channel is packed separately into 32-bit words. Pure integers are stored
|
|
* as-is. Pure floats are extended to 16-bit/32-bit as appropriate. Normalized
|
|
* formats are encoded as usual, except sRGB gets 4 extra bits.
|
|
*
|
|
* The texture descriptor swizzle is applied to the border colour. That swizzle
|
|
* includes the format swizzle. In effect, we want to encode the border colour
|
|
* like it would be encoded in memory, and then the swizzles work out
|
|
* for Vulkan.
|
|
*/
|
|
|
|
struct channel {
|
|
enum util_format_type type;
|
|
bool normalized;
|
|
unsigned size;
|
|
};
|
|
|
|
static struct channel
|
|
get_channel_info(enum pipe_format format, unsigned channel)
|
|
{
|
|
/* Compressed formats may have packing with no PIPE equivalent, handle
|
|
* specially.
|
|
*/
|
|
switch (format) {
|
|
case PIPE_FORMAT_ETC2_R11_UNORM:
|
|
case PIPE_FORMAT_ETC2_RG11_UNORM:
|
|
return (struct channel){UTIL_FORMAT_TYPE_UNSIGNED, true, 11};
|
|
|
|
case PIPE_FORMAT_ETC2_R11_SNORM:
|
|
case PIPE_FORMAT_ETC2_RG11_SNORM:
|
|
return (struct channel){UTIL_FORMAT_TYPE_SIGNED, true, 11};
|
|
|
|
case PIPE_FORMAT_RGTC1_UNORM:
|
|
case PIPE_FORMAT_RGTC2_UNORM:
|
|
return (struct channel){UTIL_FORMAT_TYPE_UNSIGNED, true, 14};
|
|
case PIPE_FORMAT_RGTC1_SNORM:
|
|
case PIPE_FORMAT_RGTC2_SNORM:
|
|
return (struct channel){UTIL_FORMAT_TYPE_SIGNED, true, 14};
|
|
|
|
case PIPE_FORMAT_ETC1_RGB8:
|
|
case PIPE_FORMAT_ETC2_RGB8:
|
|
case PIPE_FORMAT_ETC2_RGBA8:
|
|
case PIPE_FORMAT_ETC2_RGB8A1:
|
|
case PIPE_FORMAT_BPTC_RGBA_UNORM:
|
|
case PIPE_FORMAT_DXT1_RGB:
|
|
case PIPE_FORMAT_DXT1_RGBA:
|
|
case PIPE_FORMAT_DXT3_RGBA:
|
|
case PIPE_FORMAT_DXT5_RGBA:
|
|
return (struct channel){UTIL_FORMAT_TYPE_UNSIGNED, true, 8};
|
|
|
|
case PIPE_FORMAT_ETC2_SRGB8:
|
|
case PIPE_FORMAT_ETC2_SRGBA8:
|
|
case PIPE_FORMAT_ETC2_SRGB8A1:
|
|
case PIPE_FORMAT_BPTC_SRGBA:
|
|
case PIPE_FORMAT_DXT1_SRGB:
|
|
case PIPE_FORMAT_DXT1_SRGBA:
|
|
case PIPE_FORMAT_DXT3_SRGBA:
|
|
case PIPE_FORMAT_DXT5_SRGBA:
|
|
return (struct channel){
|
|
UTIL_FORMAT_TYPE_UNSIGNED,
|
|
true,
|
|
channel == 3 ? 8 : 12,
|
|
};
|
|
|
|
case PIPE_FORMAT_BPTC_RGB_FLOAT:
|
|
case PIPE_FORMAT_BPTC_RGB_UFLOAT:
|
|
return (struct channel){UTIL_FORMAT_TYPE_FLOAT, false, 16};
|
|
|
|
default:
|
|
assert(
|
|
!util_format_is_compressed(format) &&
|
|
"Other compressed formats must be special cased for border colours."
|
|
"Add more cases if we have a use case");
|
|
|
|
break;
|
|
}
|
|
|
|
const struct util_format_description *desc = util_format_description(format);
|
|
struct util_format_channel_description chan_desc = desc->channel[channel];
|
|
bool srgb = (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
|
|
(desc->swizzle[channel] <= PIPE_SWIZZLE_Z);
|
|
|
|
if (chan_desc.type == UTIL_FORMAT_TYPE_UNSIGNED ||
|
|
chan_desc.type == UTIL_FORMAT_TYPE_SIGNED) {
|
|
|
|
assert((chan_desc.normalized ^ chan_desc.pure_integer) &&
|
|
"no SCALED formats supported for texturing");
|
|
}
|
|
|
|
if (srgb && chan_desc.type != UTIL_FORMAT_TYPE_VOID) {
|
|
assert(chan_desc.normalized && chan_desc.size == 8 &&
|
|
chan_desc.type == UTIL_FORMAT_TYPE_UNSIGNED &&
|
|
"only 8-bit unorm supported with sRGB");
|
|
}
|
|
|
|
return (struct channel){
|
|
.type = chan_desc.type,
|
|
.normalized = chan_desc.normalized,
|
|
.size = srgb ? 12 : chan_desc.size,
|
|
};
|
|
}
|
|
|
|
static uint32_t
|
|
pack_channel(uint32_t value, enum pipe_format format, unsigned channel)
|
|
{
|
|
struct channel chan = get_channel_info(format, channel);
|
|
|
|
switch (chan.type) {
|
|
case UTIL_FORMAT_TYPE_VOID:
|
|
return 0;
|
|
|
|
case UTIL_FORMAT_TYPE_UNSIGNED:
|
|
if (chan.normalized)
|
|
return _mesa_float_to_unorm(uif(value), chan.size);
|
|
else
|
|
return _mesa_unsigned_to_unsigned(value, chan.size);
|
|
|
|
case UTIL_FORMAT_TYPE_SIGNED:
|
|
if (chan.normalized)
|
|
return _mesa_float_to_snorm(uif(value), chan.size);
|
|
else
|
|
return _mesa_signed_to_signed(value, chan.size);
|
|
|
|
case UTIL_FORMAT_TYPE_FLOAT:
|
|
assert(chan.size == 32 || chan.size <= 16);
|
|
return chan.size == 32 ? value : _mesa_float_to_half(uif(value));
|
|
|
|
case UTIL_FORMAT_TYPE_FIXED:
|
|
UNREACHABLE("no FIXED textures");
|
|
}
|
|
|
|
UNREACHABLE("invalid format type");
|
|
}
|
|
|
|
void
|
|
agx_pack_border(struct agx_border_packed *out, const uint32_t in[4],
|
|
enum pipe_format format)
|
|
{
|
|
assert(format != PIPE_FORMAT_NONE);
|
|
|
|
const struct util_format_description *desc = util_format_description(format);
|
|
uint8_t channel_map[4] = {0};
|
|
|
|
/* Determine the in-memory order of the format. That is the inverse of the
|
|
* format swizzle. If a component is replicated, we use the first component,
|
|
* by looping backwards and overwriting.
|
|
*/
|
|
for (int i = 3; i >= 0; --i) {
|
|
static_assert(PIPE_SWIZZLE_X == 0, "known ordering");
|
|
static_assert(PIPE_SWIZZLE_W == 3, "known ordering");
|
|
|
|
if (desc->swizzle[i] <= PIPE_SWIZZLE_W)
|
|
channel_map[i] = desc->swizzle[i];
|
|
}
|
|
|
|
agx_pack(out, BORDER, cfg) {
|
|
cfg.channel_0 = pack_channel(in[channel_map[0]], format, 0);
|
|
cfg.channel_1 = pack_channel(in[channel_map[1]], format, 1);
|
|
cfg.channel_2 = pack_channel(in[channel_map[2]], format, 2);
|
|
cfg.channel_3 = pack_channel(in[channel_map[3]], format, 3);
|
|
}
|
|
}
|