X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Futil%2Fu_format.h;h=f1aa116fe3a118ac756fee9ede276b6257ec92f6;hb=6196259d957cc7c3ea355b74649623ef7e582854;hp=03b73c0e98f5fa08adddfec177b3b6b329aa501a;hpb=695cc370a280a637f411f5ff3877b3fd1c05e424;p=mesa.git diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h index 03b73c0e98f..f1aa116fe3a 100644 --- a/src/gallium/auxiliary/util/u_format.h +++ b/src/gallium/auxiliary/util/u_format.h @@ -31,8 +31,13 @@ #include "pipe/p_format.h" +#include "pipe/p_defines.h" #include "util/u_debug.h" +union pipe_color_union; +struct pipe_screen; + + #ifdef __cplusplus extern "C" { #endif @@ -49,30 +54,50 @@ enum util_format_layout { * Formats with util_format_block::width == util_format_block::height == 1 * that can be described as an ordinary data structure. */ - UTIL_FORMAT_LAYOUT_PLAIN = 0, + UTIL_FORMAT_LAYOUT_PLAIN, /** * Formats with sub-sampled channels. * - * This is for formats like YV12 where there is less than one sample per + * This is for formats like YVYU where there is less than one sample per * pixel. */ - UTIL_FORMAT_LAYOUT_SUBSAMPLED = 3, + UTIL_FORMAT_LAYOUT_SUBSAMPLED, /** * S3 Texture Compression formats. */ - UTIL_FORMAT_LAYOUT_S3TC = 4, + UTIL_FORMAT_LAYOUT_S3TC, /** * Red-Green Texture Compression formats. */ - UTIL_FORMAT_LAYOUT_RGTC = 5, + UTIL_FORMAT_LAYOUT_RGTC, + + /** + * Ericsson Texture Compression + */ + UTIL_FORMAT_LAYOUT_ETC, + + /** + * BC6/7 Texture Compression + */ + UTIL_FORMAT_LAYOUT_BPTC, + + UTIL_FORMAT_LAYOUT_ASTC, + + UTIL_FORMAT_LAYOUT_ATC, + + /** Formats with 2 or more planes. */ + UTIL_FORMAT_LAYOUT_PLANAR2, + UTIL_FORMAT_LAYOUT_PLANAR3, + + UTIL_FORMAT_LAYOUT_FXT1 = 10, /** * Everything else that doesn't fit in any of the above layouts. */ - UTIL_FORMAT_LAYOUT_OTHER = 6 + UTIL_FORMAT_LAYOUT_OTHER, }; @@ -84,6 +109,9 @@ struct util_format_block /** Block height in pixels */ unsigned height; + /** Block depth in pixels */ + unsigned depth; + /** Block size in bits */ unsigned bits; }; @@ -98,17 +126,6 @@ enum util_format_type { }; -enum util_format_swizzle { - UTIL_FORMAT_SWIZZLE_X = 0, - UTIL_FORMAT_SWIZZLE_Y = 1, - UTIL_FORMAT_SWIZZLE_Z = 2, - UTIL_FORMAT_SWIZZLE_W = 3, - UTIL_FORMAT_SWIZZLE_0 = 4, - UTIL_FORMAT_SWIZZLE_1 = 5, - UTIL_FORMAT_SWIZZLE_NONE = 6 -}; - - enum util_format_colorspace { UTIL_FORMAT_COLORSPACE_RGB = 0, UTIL_FORMAT_COLORSPACE_SRGB = 1, @@ -119,9 +136,11 @@ enum util_format_colorspace { struct util_format_channel_description { - unsigned type:6; + unsigned type:5; /**< UTIL_FORMAT_TYPE_x */ unsigned normalized:1; - unsigned size:9; + unsigned pure_integer:1; + unsigned size:9; /**< bits per channel */ + unsigned shift:16; /** number of bits from lsb */ }; @@ -149,7 +168,7 @@ struct util_format_description unsigned nr_channels:3; /** - * Whether all channels have the same number of (whole) bytes. + * Whether all channels have the same number of (whole) bytes and type. */ unsigned is_array:1; @@ -168,9 +187,41 @@ struct util_format_description unsigned is_mixed:1; /** - * Input channel description. + * Whether the format contains UNORM channels + */ + unsigned is_unorm:1; + + /** + * Whether the format contains SNORM channels + */ + unsigned is_snorm:1; + + /** + * Input channel description, in the order XYZW. * * Only valid for UTIL_FORMAT_LAYOUT_PLAIN formats. + * + * If each channel is accessed as an individual N-byte value, X is always + * at the lowest address in memory, Y is always next, and so on. For all + * currently-defined formats, the N-byte value has native endianness. + * + * If instead a group of channels is accessed as a single N-byte value, + * the order of the channels within that value depends on endianness. + * For big-endian targets, X is the most significant subvalue, + * otherwise it is the least significant one. + * + * For example, if X is 8 bits and Y is 24 bits, the memory order is: + * + * 0 1 2 3 + * little-endian: X Yl Ym Yu (l = lower, m = middle, u = upper) + * big-endian: X Yu Ym Yl + * + * If X is 5 bits, Y is 5 bits, Z is 5 bits and W is 1 bit, the layout is: + * + * 0 1 + * msb lsb msb lsb + * little-endian: YYYXXXXX WZZZZZYY + * big-endian: XXXXXYYY YYZZZZZW */ struct util_format_channel_description channel[4]; @@ -247,7 +298,7 @@ struct util_format_description /** * Fetch a single pixel (i, j) from a block. * - * Only defined for non-depth-stencil formats. + * Only defined for non-depth-stencil and non-integer formats. */ void (*fetch_rgba_float)(float *dst, @@ -299,27 +350,78 @@ struct util_format_description unsigned width, unsigned height); /** - * Unpack pixels to S8_USCALED. + * Unpack pixels to S8_UINT. * Note: strides are in bytes. * * Only defined for stencil formats. */ void - (*unpack_s_8uscaled)(uint8_t *dst, unsigned dst_stride, - const uint8_t *src, unsigned src_stride, - unsigned width, unsigned height); + (*unpack_s_8uint)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); /** - * Pack pixels from S8_USCALED. + * Pack pixels from S8_UINT. * Note: strides are in bytes. * * Only defined for stencil formats. */ void - (*pack_s_8uscaled)(uint8_t *dst, unsigned dst_stride, - const uint8_t *src, unsigned src_stride, - unsigned width, unsigned height); + (*pack_s_8uint)(uint8_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + /** + * Unpack pixel blocks to R32G32B32A32_UINT. + * Note: strides are in bytes. + * + * Only defined for INT formats. + */ + void + (*unpack_rgba_uint)(uint32_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + void + (*pack_rgba_uint)(uint8_t *dst, unsigned dst_stride, + const uint32_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Unpack pixel blocks to R32G32B32A32_SINT. + * Note: strides are in bytes. + * + * Only defined for INT formats. + */ + void + (*unpack_rgba_sint)(int32_t *dst, unsigned dst_stride, + const uint8_t *src, unsigned src_stride, + unsigned width, unsigned height); + + void + (*pack_rgba_sint)(uint8_t *dst, unsigned dst_stride, + const int32_t *src, unsigned src_stride, + unsigned width, unsigned height); + + /** + * Fetch a single pixel (i, j) from a block. + * + * Only defined for unsigned (pure) integer formats. + */ + void + (*fetch_rgba_uint)(uint32_t *dst, + const uint8_t *src, + unsigned i, unsigned j); + + /** + * Fetch a single pixel (i, j) from a block. + * + * Only defined for signed (pure) integer formats. + */ + void + (*fetch_rgba_sint)(int32_t *dst, + const uint8_t *src, + unsigned i, unsigned j); }; @@ -335,7 +437,7 @@ util_format_description(enum pipe_format format); * Format query functions. */ -static INLINE const char * +static inline const char * util_format_name(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -348,7 +450,7 @@ util_format_name(enum pipe_format format) return desc->name; } -static INLINE const char * +static inline const char * util_format_short_name(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -364,7 +466,7 @@ util_format_short_name(enum pipe_format format) /** * Whether this format is plain, see UTIL_FORMAT_LAYOUT_PLAIN for more info. */ -static INLINE boolean +static inline boolean util_format_is_plain(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -376,7 +478,7 @@ util_format_is_plain(enum pipe_format format) return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ? TRUE : FALSE; } -static INLINE boolean +static inline boolean util_format_is_compressed(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -389,6 +491,10 @@ util_format_is_compressed(enum pipe_format format) switch (desc->layout) { case UTIL_FORMAT_LAYOUT_S3TC: case UTIL_FORMAT_LAYOUT_RGTC: + case UTIL_FORMAT_LAYOUT_ETC: + case UTIL_FORMAT_LAYOUT_BPTC: + case UTIL_FORMAT_LAYOUT_ASTC: + case UTIL_FORMAT_LAYOUT_ATC: /* XXX add other formats in the future */ return TRUE; default: @@ -396,7 +502,7 @@ util_format_is_compressed(enum pipe_format format) } } -static INLINE boolean +static inline boolean util_format_is_s3tc(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -409,7 +515,41 @@ util_format_is_s3tc(enum pipe_format format) return desc->layout == UTIL_FORMAT_LAYOUT_S3TC ? TRUE : FALSE; } -static INLINE boolean +static inline boolean +util_format_is_etc(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return FALSE; + } + + return desc->layout == UTIL_FORMAT_LAYOUT_ETC ? TRUE : FALSE; +} + +static inline boolean +util_format_is_srgb(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + return desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB; +} + +static inline boolean +util_format_has_depth(const struct util_format_description *desc) +{ + return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS && + desc->swizzle[0] != PIPE_SWIZZLE_NONE; +} + +static inline boolean +util_format_has_stencil(const struct util_format_description *desc) +{ + return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS && + desc->swizzle[1] != PIPE_SWIZZLE_NONE; +} + +static inline boolean util_format_is_depth_or_stencil(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -419,10 +559,11 @@ util_format_is_depth_or_stencil(enum pipe_format format) return FALSE; } - return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ? TRUE : FALSE; + return util_format_has_depth(desc) || + util_format_has_stencil(desc); } -static INLINE boolean +static inline boolean util_format_is_depth_and_stencil(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -432,14 +573,97 @@ util_format_is_depth_and_stencil(enum pipe_format format) return FALSE; } - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) { + return util_format_has_depth(desc) && + util_format_has_stencil(desc); +} + +/** + * For depth-stencil formats, return the equivalent depth-only format. + */ +static inline enum pipe_format +util_format_get_depth_only(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return PIPE_FORMAT_Z24X8_UNORM; + + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + return PIPE_FORMAT_X8Z24_UNORM; + + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + return PIPE_FORMAT_Z32_FLOAT; + + default: + return format; + } +} + +static inline boolean +util_format_is_yuv(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { return FALSE; } - return (desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE && - desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE) ? TRUE : FALSE; + return desc->colorspace == UTIL_FORMAT_COLORSPACE_YUV; } +/** + * Calculates the depth format type based upon the incoming format description. + */ +static inline unsigned +util_get_depth_format_type(const struct util_format_description *desc) +{ + unsigned depth_channel = desc->swizzle[0]; + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS && + depth_channel != PIPE_SWIZZLE_NONE) { + return desc->channel[depth_channel].type; + } else { + return UTIL_FORMAT_TYPE_VOID; + } +} + + +/** + * Calculates the MRD for the depth format. MRD is used in depth bias + * for UNORM and unbound depth buffers. When the depth buffer is floating + * point, the depth bias calculation does not use the MRD. However, the + * default MRD will be 1.0 / ((1 << 24) - 1). + */ +double +util_get_depth_format_mrd(const struct util_format_description *desc); + + +/** + * Return whether this is an RGBA, Z, S, or combined ZS format. + * Useful for initializing pipe_blit_info::mask. + */ +static inline unsigned +util_format_get_mask(enum pipe_format format) +{ + const struct util_format_description *desc = + util_format_description(format); + + if (!desc) + return 0; + + if (util_format_has_depth(desc)) { + if (util_format_has_stencil(desc)) { + return PIPE_MASK_ZS; + } else { + return PIPE_MASK_Z; + } + } else { + if (util_format_has_stencil(desc)) { + return PIPE_MASK_S; + } else { + return PIPE_MASK_RGBA; + } + } +} /** * Give the RGBA colormask of the channels that can be represented in this @@ -447,7 +671,7 @@ util_format_is_depth_and_stencil(enum pipe_format format) * * That is, the channels whose values are preserved. */ -static INLINE unsigned +static inline unsigned util_format_colormask(const struct util_format_description *desc) { unsigned colormask; @@ -474,14 +698,69 @@ util_format_colormask(const struct util_format_description *desc) /** - * Whether the src format can be blitted to destation format with a simple - * memcpy. + * Checks if color mask covers every channel for the specified format + * + * @param desc a format description to check colormask with + * @param colormask a bit mask for channels, matches format of PIPE_MASK_RGBA + */ +static inline boolean +util_format_colormask_full(const struct util_format_description *desc, unsigned colormask) +{ + return (~colormask & util_format_colormask(desc)) == 0; +} + + +boolean +util_format_is_float(enum pipe_format format); + + +boolean +util_format_has_alpha(enum pipe_format format); + + +boolean +util_format_is_luminance(enum pipe_format format); + +boolean +util_format_is_alpha(enum pipe_format format); + +boolean +util_format_is_luminance_alpha(enum pipe_format format); + + +boolean +util_format_is_intensity(enum pipe_format format); + +boolean +util_format_is_subsampled_422(enum pipe_format format); + +boolean +util_format_is_pure_integer(enum pipe_format format); + +boolean +util_format_is_pure_sint(enum pipe_format format); + +boolean +util_format_is_pure_uint(enum pipe_format format); + +boolean +util_format_is_snorm(enum pipe_format format); + +boolean +util_format_is_unorm(enum pipe_format format); + +boolean +util_format_is_snorm8(enum pipe_format format); + +/** + * Check if the src format can be blitted to the destination format with + * a simple memcpy. For example, blitting from RGBA to RGBx is OK, but not + * the reverse. */ boolean util_is_format_compatible(const struct util_format_description *src_desc, const struct util_format_description *dst_desc); - /** * Whether this format is a rgab8 variant. * @@ -489,7 +768,7 @@ util_is_format_compatible(const struct util_format_description *src_desc, * * PIPE_FORMAT_?8?8?8?8_UNORM */ -static INLINE boolean +static inline boolean util_format_is_rgba8_variant(const struct util_format_description *desc) { unsigned chan; @@ -503,6 +782,9 @@ util_format_is_rgba8_variant(const struct util_format_description *desc) if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID) return FALSE; + if(desc->channel[chan].type == UTIL_FORMAT_TYPE_UNSIGNED && + !desc->channel[chan].normalized) + return FALSE; if(desc->channel[chan].size != 8) return FALSE; } @@ -510,11 +792,10 @@ util_format_is_rgba8_variant(const struct util_format_description *desc) return TRUE; } - /** * Return total bits needed for the pixel format per block. */ -static INLINE uint +static inline uint util_format_get_blocksizebits(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -530,17 +811,22 @@ util_format_get_blocksizebits(enum pipe_format format) /** * Return bytes per block (not pixel) for the given format. */ -static INLINE uint +static inline uint util_format_get_blocksize(enum pipe_format format) { uint bits = util_format_get_blocksizebits(format); + uint bytes = bits / 8; assert(bits % 8 == 0); + assert(bytes > 0); + if (bytes == 0) { + bytes = 1; + } - return bits / 8; + return bytes; } -static INLINE uint +static inline uint util_format_get_blockwidth(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -553,7 +839,7 @@ util_format_get_blockwidth(enum pipe_format format) return desc->block.width; } -static INLINE uint +static inline uint util_format_get_blockheight(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); @@ -566,7 +852,20 @@ util_format_get_blockheight(enum pipe_format format) return desc->block.height; } -static INLINE unsigned +static inline uint +util_format_get_blockdepth(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + if (!desc) { + return 1; + } + + return desc->block.depth; +} + +static inline unsigned util_format_get_nblocksx(enum pipe_format format, unsigned x) { @@ -574,7 +873,7 @@ util_format_get_nblocksx(enum pipe_format format, return (x + blockwidth - 1) / blockwidth; } -static INLINE unsigned +static inline unsigned util_format_get_nblocksy(enum pipe_format format, unsigned y) { @@ -582,22 +881,31 @@ util_format_get_nblocksy(enum pipe_format format, return (y + blockheight - 1) / blockheight; } -static INLINE unsigned +static inline unsigned +util_format_get_nblocksz(enum pipe_format format, + unsigned z) +{ + unsigned blockdepth = util_format_get_blockdepth(format); + return (z + blockdepth - 1) / blockdepth; +} + +static inline unsigned util_format_get_nblocks(enum pipe_format format, unsigned width, unsigned height) { + assert(util_format_get_blockdepth(format) == 1); return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height); } -static INLINE size_t +static inline size_t util_format_get_stride(enum pipe_format format, unsigned width) { - return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format); + return (size_t)util_format_get_nblocksx(format, width) * util_format_get_blocksize(format); } -static INLINE size_t +static inline size_t util_format_get_2d_size(enum pipe_format format, size_t stride, unsigned height) @@ -605,7 +913,7 @@ util_format_get_2d_size(enum pipe_format format, return util_format_get_nblocksy(format, height) * stride; } -static INLINE uint +static inline uint util_format_get_component_bits(enum pipe_format format, enum util_format_colorspace colorspace, uint component) @@ -635,52 +943,34 @@ util_format_get_component_bits(enum pipe_format format, } switch (desc->swizzle[component]) { - case UTIL_FORMAT_SWIZZLE_X: + case PIPE_SWIZZLE_X: return desc->channel[0].size; - case UTIL_FORMAT_SWIZZLE_Y: + case PIPE_SWIZZLE_Y: return desc->channel[1].size; - case UTIL_FORMAT_SWIZZLE_Z: + case PIPE_SWIZZLE_Z: return desc->channel[2].size; - case UTIL_FORMAT_SWIZZLE_W: + case PIPE_SWIZZLE_W: return desc->channel[3].size; default: return 0; } } -static INLINE boolean -util_format_has_alpha(enum pipe_format format) -{ - const struct util_format_description *desc = util_format_description(format); - - assert(format); - if (!format) { - return FALSE; - } - - switch (desc->colorspace) { - case UTIL_FORMAT_COLORSPACE_RGB: - case UTIL_FORMAT_COLORSPACE_SRGB: - return desc->swizzle[3] != UTIL_FORMAT_SWIZZLE_1; - case UTIL_FORMAT_COLORSPACE_YUV: - return FALSE; - case UTIL_FORMAT_COLORSPACE_ZS: - return FALSE; - default: - assert(0); - return FALSE; - } -} - /** - * Return the matching SRGB format, or PIPE_FORMAT_NONE if none. + * Given a linear RGB colorspace format, return the corresponding SRGB + * format, or PIPE_FORMAT_NONE if none. */ -static INLINE enum pipe_format +static inline enum pipe_format util_format_srgb(enum pipe_format format) { + if (util_format_is_srgb(format)) + return format; + switch (format) { case PIPE_FORMAT_L8_UNORM: return PIPE_FORMAT_L8_SRGB; + case PIPE_FORMAT_R8_UNORM: + return PIPE_FORMAT_R8_SRGB; case PIPE_FORMAT_L8A8_UNORM: return PIPE_FORMAT_L8A8_SRGB; case PIPE_FORMAT_R8G8B8_UNORM: @@ -697,6 +987,10 @@ util_format_srgb(enum pipe_format format) return PIPE_FORMAT_A8R8G8B8_SRGB; case PIPE_FORMAT_X8R8G8B8_UNORM: return PIPE_FORMAT_X8R8G8B8_SRGB; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return PIPE_FORMAT_R8G8B8A8_SRGB; + case PIPE_FORMAT_R8G8B8X8_UNORM: + return PIPE_FORMAT_R8G8B8X8_SRGB; case PIPE_FORMAT_DXT1_RGB: return PIPE_FORMAT_DXT1_SRGB; case PIPE_FORMAT_DXT1_RGBA: @@ -705,22 +999,398 @@ util_format_srgb(enum pipe_format format) return PIPE_FORMAT_DXT3_SRGBA; case PIPE_FORMAT_DXT5_RGBA: return PIPE_FORMAT_DXT5_SRGBA; + case PIPE_FORMAT_B5G6R5_UNORM: + return PIPE_FORMAT_B5G6R5_SRGB; + case PIPE_FORMAT_BPTC_RGBA_UNORM: + return PIPE_FORMAT_BPTC_SRGBA; + case PIPE_FORMAT_ETC2_RGB8: + return PIPE_FORMAT_ETC2_SRGB8; + case PIPE_FORMAT_ETC2_RGB8A1: + return PIPE_FORMAT_ETC2_SRGB8A1; + case PIPE_FORMAT_ETC2_RGBA8: + return PIPE_FORMAT_ETC2_SRGBA8; + case PIPE_FORMAT_ASTC_4x4: + return PIPE_FORMAT_ASTC_4x4_SRGB; + case PIPE_FORMAT_ASTC_5x4: + return PIPE_FORMAT_ASTC_5x4_SRGB; + case PIPE_FORMAT_ASTC_5x5: + return PIPE_FORMAT_ASTC_5x5_SRGB; + case PIPE_FORMAT_ASTC_6x5: + return PIPE_FORMAT_ASTC_6x5_SRGB; + case PIPE_FORMAT_ASTC_6x6: + return PIPE_FORMAT_ASTC_6x6_SRGB; + case PIPE_FORMAT_ASTC_8x5: + return PIPE_FORMAT_ASTC_8x5_SRGB; + case PIPE_FORMAT_ASTC_8x6: + return PIPE_FORMAT_ASTC_8x6_SRGB; + case PIPE_FORMAT_ASTC_8x8: + return PIPE_FORMAT_ASTC_8x8_SRGB; + case PIPE_FORMAT_ASTC_10x5: + return PIPE_FORMAT_ASTC_10x5_SRGB; + case PIPE_FORMAT_ASTC_10x6: + return PIPE_FORMAT_ASTC_10x6_SRGB; + case PIPE_FORMAT_ASTC_10x8: + return PIPE_FORMAT_ASTC_10x8_SRGB; + case PIPE_FORMAT_ASTC_10x10: + return PIPE_FORMAT_ASTC_10x10_SRGB; + case PIPE_FORMAT_ASTC_12x10: + return PIPE_FORMAT_ASTC_12x10_SRGB; + case PIPE_FORMAT_ASTC_12x12: + return PIPE_FORMAT_ASTC_12x12_SRGB; + + default: + return PIPE_FORMAT_NONE; + } +} + +/** + * Given an sRGB format, return the corresponding linear colorspace format. + * For non sRGB formats, return the format unchanged. + */ +static inline enum pipe_format +util_format_linear(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_L8_SRGB: + return PIPE_FORMAT_L8_UNORM; + case PIPE_FORMAT_R8_SRGB: + return PIPE_FORMAT_R8_UNORM; + case PIPE_FORMAT_L8A8_SRGB: + return PIPE_FORMAT_L8A8_UNORM; + case PIPE_FORMAT_R8G8B8_SRGB: + return PIPE_FORMAT_R8G8B8_UNORM; + case PIPE_FORMAT_A8B8G8R8_SRGB: + return PIPE_FORMAT_A8B8G8R8_UNORM; + case PIPE_FORMAT_X8B8G8R8_SRGB: + return PIPE_FORMAT_X8B8G8R8_UNORM; + case PIPE_FORMAT_B8G8R8A8_SRGB: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case PIPE_FORMAT_B8G8R8X8_SRGB: + return PIPE_FORMAT_B8G8R8X8_UNORM; + case PIPE_FORMAT_A8R8G8B8_SRGB: + return PIPE_FORMAT_A8R8G8B8_UNORM; + case PIPE_FORMAT_X8R8G8B8_SRGB: + return PIPE_FORMAT_X8R8G8B8_UNORM; + case PIPE_FORMAT_R8G8B8A8_SRGB: + return PIPE_FORMAT_R8G8B8A8_UNORM; + case PIPE_FORMAT_R8G8B8X8_SRGB: + return PIPE_FORMAT_R8G8B8X8_UNORM; + case PIPE_FORMAT_DXT1_SRGB: + return PIPE_FORMAT_DXT1_RGB; + case PIPE_FORMAT_DXT1_SRGBA: + return PIPE_FORMAT_DXT1_RGBA; + case PIPE_FORMAT_DXT3_SRGBA: + return PIPE_FORMAT_DXT3_RGBA; + case PIPE_FORMAT_DXT5_SRGBA: + return PIPE_FORMAT_DXT5_RGBA; + case PIPE_FORMAT_B5G6R5_SRGB: + return PIPE_FORMAT_B5G6R5_UNORM; + case PIPE_FORMAT_BPTC_SRGBA: + return PIPE_FORMAT_BPTC_RGBA_UNORM; + case PIPE_FORMAT_ETC2_SRGB8: + return PIPE_FORMAT_ETC2_RGB8; + case PIPE_FORMAT_ETC2_SRGB8A1: + return PIPE_FORMAT_ETC2_RGB8A1; + case PIPE_FORMAT_ETC2_SRGBA8: + return PIPE_FORMAT_ETC2_RGBA8; + case PIPE_FORMAT_ASTC_4x4_SRGB: + return PIPE_FORMAT_ASTC_4x4; + case PIPE_FORMAT_ASTC_5x4_SRGB: + return PIPE_FORMAT_ASTC_5x4; + case PIPE_FORMAT_ASTC_5x5_SRGB: + return PIPE_FORMAT_ASTC_5x5; + case PIPE_FORMAT_ASTC_6x5_SRGB: + return PIPE_FORMAT_ASTC_6x5; + case PIPE_FORMAT_ASTC_6x6_SRGB: + return PIPE_FORMAT_ASTC_6x6; + case PIPE_FORMAT_ASTC_8x5_SRGB: + return PIPE_FORMAT_ASTC_8x5; + case PIPE_FORMAT_ASTC_8x6_SRGB: + return PIPE_FORMAT_ASTC_8x6; + case PIPE_FORMAT_ASTC_8x8_SRGB: + return PIPE_FORMAT_ASTC_8x8; + case PIPE_FORMAT_ASTC_10x5_SRGB: + return PIPE_FORMAT_ASTC_10x5; + case PIPE_FORMAT_ASTC_10x6_SRGB: + return PIPE_FORMAT_ASTC_10x6; + case PIPE_FORMAT_ASTC_10x8_SRGB: + return PIPE_FORMAT_ASTC_10x8; + case PIPE_FORMAT_ASTC_10x10_SRGB: + return PIPE_FORMAT_ASTC_10x10; + case PIPE_FORMAT_ASTC_12x10_SRGB: + return PIPE_FORMAT_ASTC_12x10; + case PIPE_FORMAT_ASTC_12x12_SRGB: + return PIPE_FORMAT_ASTC_12x12; default: + return format; + } +} + +/** + * Given a depth-stencil format, return the corresponding stencil-only format. + * For stencil-only formats, return the format unchanged. + */ +static inline enum pipe_format +util_format_stencil_only(enum pipe_format format) +{ + switch (format) { + /* mask out the depth component */ + case PIPE_FORMAT_Z24_UNORM_S8_UINT: + return PIPE_FORMAT_X24S8_UINT; + case PIPE_FORMAT_S8_UINT_Z24_UNORM: + return PIPE_FORMAT_S8X24_UINT; + case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: + return PIPE_FORMAT_X32_S8X24_UINT; + + /* stencil only formats */ + case PIPE_FORMAT_X24S8_UINT: + case PIPE_FORMAT_S8X24_UINT: + case PIPE_FORMAT_X32_S8X24_UINT: + case PIPE_FORMAT_S8_UINT: + return format; + + default: + assert(0); + return PIPE_FORMAT_NONE; + } +} + +/** + * Converts PIPE_FORMAT_*I* to PIPE_FORMAT_*R*. + * This is identity for non-intensity formats. + */ +static inline enum pipe_format +util_format_intensity_to_red(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_I8_UNORM: + return PIPE_FORMAT_R8_UNORM; + case PIPE_FORMAT_I8_SNORM: + return PIPE_FORMAT_R8_SNORM; + case PIPE_FORMAT_I16_UNORM: + return PIPE_FORMAT_R16_UNORM; + case PIPE_FORMAT_I16_SNORM: + return PIPE_FORMAT_R16_SNORM; + case PIPE_FORMAT_I16_FLOAT: + return PIPE_FORMAT_R16_FLOAT; + case PIPE_FORMAT_I32_FLOAT: + return PIPE_FORMAT_R32_FLOAT; + case PIPE_FORMAT_I8_UINT: + return PIPE_FORMAT_R8_UINT; + case PIPE_FORMAT_I8_SINT: + return PIPE_FORMAT_R8_SINT; + case PIPE_FORMAT_I16_UINT: + return PIPE_FORMAT_R16_UINT; + case PIPE_FORMAT_I16_SINT: + return PIPE_FORMAT_R16_SINT; + case PIPE_FORMAT_I32_UINT: + return PIPE_FORMAT_R32_UINT; + case PIPE_FORMAT_I32_SINT: + return PIPE_FORMAT_R32_SINT; + default: + assert(!util_format_is_intensity(format)); + return format; + } +} + +/** + * Converts PIPE_FORMAT_*L* to PIPE_FORMAT_*R*. + * This is identity for non-luminance formats. + */ +static inline enum pipe_format +util_format_luminance_to_red(enum pipe_format format) +{ + switch (format) { + case PIPE_FORMAT_L8_UNORM: + return PIPE_FORMAT_R8_UNORM; + case PIPE_FORMAT_L8_SNORM: + return PIPE_FORMAT_R8_SNORM; + case PIPE_FORMAT_L16_UNORM: + return PIPE_FORMAT_R16_UNORM; + case PIPE_FORMAT_L16_SNORM: + return PIPE_FORMAT_R16_SNORM; + case PIPE_FORMAT_L16_FLOAT: + return PIPE_FORMAT_R16_FLOAT; + case PIPE_FORMAT_L32_FLOAT: + return PIPE_FORMAT_R32_FLOAT; + case PIPE_FORMAT_L8_UINT: + return PIPE_FORMAT_R8_UINT; + case PIPE_FORMAT_L8_SINT: + return PIPE_FORMAT_R8_SINT; + case PIPE_FORMAT_L16_UINT: + return PIPE_FORMAT_R16_UINT; + case PIPE_FORMAT_L16_SINT: + return PIPE_FORMAT_R16_SINT; + case PIPE_FORMAT_L32_UINT: + return PIPE_FORMAT_R32_UINT; + case PIPE_FORMAT_L32_SINT: + return PIPE_FORMAT_R32_SINT; + + case PIPE_FORMAT_LATC1_UNORM: + return PIPE_FORMAT_RGTC1_UNORM; + case PIPE_FORMAT_LATC1_SNORM: + return PIPE_FORMAT_RGTC1_SNORM; + + case PIPE_FORMAT_L4A4_UNORM: + return PIPE_FORMAT_R4A4_UNORM; + + case PIPE_FORMAT_L8A8_UNORM: + return PIPE_FORMAT_R8A8_UNORM; + case PIPE_FORMAT_L8A8_SNORM: + return PIPE_FORMAT_R8A8_SNORM; + case PIPE_FORMAT_L16A16_UNORM: + return PIPE_FORMAT_R16A16_UNORM; + case PIPE_FORMAT_L16A16_SNORM: + return PIPE_FORMAT_R16A16_SNORM; + case PIPE_FORMAT_L16A16_FLOAT: + return PIPE_FORMAT_R16A16_FLOAT; + case PIPE_FORMAT_L32A32_FLOAT: + return PIPE_FORMAT_R32A32_FLOAT; + case PIPE_FORMAT_L8A8_UINT: + return PIPE_FORMAT_R8A8_UINT; + case PIPE_FORMAT_L8A8_SINT: + return PIPE_FORMAT_R8A8_SINT; + case PIPE_FORMAT_L16A16_UINT: + return PIPE_FORMAT_R16A16_UINT; + case PIPE_FORMAT_L16A16_SINT: + return PIPE_FORMAT_R16A16_SINT; + case PIPE_FORMAT_L32A32_UINT: + return PIPE_FORMAT_R32A32_UINT; + case PIPE_FORMAT_L32A32_SINT: + return PIPE_FORMAT_R32A32_SINT; + + /* We don't have compressed red-alpha variants for these. */ + case PIPE_FORMAT_LATC2_UNORM: + case PIPE_FORMAT_LATC2_SNORM: return PIPE_FORMAT_NONE; + + default: + assert(!util_format_is_luminance(format) && + !util_format_is_luminance_alpha(format)); + return format; + } +} + +static inline unsigned +util_format_get_num_planes(enum pipe_format format) +{ + switch (util_format_description(format)->layout) { + case UTIL_FORMAT_LAYOUT_PLANAR3: + return 3; + case UTIL_FORMAT_LAYOUT_PLANAR2: + return 2; + default: + return 1; } } +static inline enum pipe_format +util_format_get_plane_format(enum pipe_format format, unsigned plane) +{ + switch (format) { + case PIPE_FORMAT_YV12: + case PIPE_FORMAT_YV16: + case PIPE_FORMAT_IYUV: + return PIPE_FORMAT_R8_UNORM; + case PIPE_FORMAT_NV12: + return !plane ? PIPE_FORMAT_R8_UNORM : PIPE_FORMAT_RG88_UNORM; + case PIPE_FORMAT_NV21: + return !plane ? PIPE_FORMAT_R8_UNORM : PIPE_FORMAT_GR88_UNORM; + case PIPE_FORMAT_P016: + return !plane ? PIPE_FORMAT_R16_UNORM : PIPE_FORMAT_R16G16_UNORM; + default: + return format; + } +} + +static inline unsigned +util_format_get_plane_width(enum pipe_format format, unsigned plane, + unsigned width) +{ + switch (format) { + case PIPE_FORMAT_YV12: + case PIPE_FORMAT_YV16: + case PIPE_FORMAT_IYUV: + case PIPE_FORMAT_NV12: + case PIPE_FORMAT_NV21: + case PIPE_FORMAT_P016: + return !plane ? width : (width + 1) / 2; + default: + return width; + } +} + +static inline unsigned +util_format_get_plane_height(enum pipe_format format, unsigned plane, + unsigned height) +{ + switch (format) { + case PIPE_FORMAT_YV12: + case PIPE_FORMAT_IYUV: + case PIPE_FORMAT_NV12: + case PIPE_FORMAT_NV21: + case PIPE_FORMAT_P016: + return !plane ? height : (height + 1) / 2; + case PIPE_FORMAT_YV16: + default: + return height; + } +} + +bool util_format_planar_is_supported(struct pipe_screen *screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned sample_count, + unsigned storage_sample_count, + unsigned bind); + /** * Return the number of components stored. * Formats with block size != 1x1 will always have 1 component (the block). */ -static INLINE unsigned +static inline unsigned util_format_get_nr_components(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); return desc->nr_channels; } +/** + * Return the index of the first non-void channel + * -1 if no non-void channels + */ +static inline int +util_format_get_first_non_void_channel(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + int i; + + for (i = 0; i < 4; i++) + if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) + break; + + if (i == 4) + return -1; + + return i; +} + +/** + * Whether this format is any 8-bit UNORM variant. Looser than + * util_is_rgba8_variant (also includes alpha textures, for instance). + */ + +static inline bool +util_format_is_unorm8(const struct util_format_description *desc) +{ + int c = util_format_get_first_non_void_channel(desc->format); + + if (c == -1) + return false; + + return desc->is_unorm && desc->is_array && desc->channel[c].size == 8; +} + /* * Format access functions. */ @@ -749,6 +1419,30 @@ util_format_write_4ub(enum pipe_format format, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h); +void +util_format_read_4ui(enum pipe_format format, + unsigned *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4ui(enum pipe_format format, + const unsigned int *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_read_4i(enum pipe_format format, + int *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4i(enum pipe_format format, + const int *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + /* * Generic format conversion; */ @@ -756,7 +1450,7 @@ util_format_write_4ub(enum pipe_format format, boolean util_format_fits_8unorm(const struct util_format_description *format_desc); -void +boolean util_format_translate(enum pipe_format dst_format, void *dst, unsigned dst_stride, unsigned dst_x, unsigned dst_y, @@ -765,6 +1459,50 @@ util_format_translate(enum pipe_format dst_format, unsigned src_x, unsigned src_y, unsigned width, unsigned height); +boolean +util_format_translate_3d(enum pipe_format dst_format, + void *dst, unsigned dst_stride, + unsigned dst_slice_stride, + unsigned dst_x, unsigned dst_y, + unsigned dst_z, + enum pipe_format src_format, + const void *src, unsigned src_stride, + unsigned src_slice_stride, + unsigned src_x, unsigned src_y, + unsigned src_z, unsigned width, + unsigned height, unsigned depth); + +/* + * Swizzle operations. + */ + +/* Compose two sets of swizzles. + * If V is a 4D vector and the function parameters represent functions that + * swizzle vector components, this holds: + * swz2(swz1(V)) = dst(V) + */ +void util_format_compose_swizzles(const unsigned char swz1[4], + const unsigned char swz2[4], + unsigned char dst[4]); + +/* Apply the swizzle provided in \param swz (which is one of PIPE_SWIZZLE_x) + * to \param src and store the result in \param dst. + * \param is_integer determines the value written for PIPE_SWIZZLE_1. + */ +void util_format_apply_color_swizzle(union pipe_color_union *dst, + const union pipe_color_union *src, + const unsigned char swz[4], + const boolean is_integer); + +void pipe_swizzle_4f(float *dst, const float *src, + const unsigned char swz[4]); + +void util_format_unswizzle_4f(float *dst, const float *src, + const unsigned char swz[4]); + +enum pipe_format +util_format_snorm8_to_sint8(enum pipe_format format); + #ifdef __cplusplus } // extern "C" { #endif