xref: /aosp_15_r20/external/virglrenderer/src/gallium/auxiliary/util/u_format.h (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1 /**************************************************************************
2  *
3  * Copyright 2009-2010 Vmware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 
29 #ifndef U_FORMAT_H
30 #define U_FORMAT_H
31 
32 
33 #include "pipe/p_format.h"
34 #include "pipe/p_defines.h"
35 #include "util/u_debug.h"
36 
37 union pipe_color_union;
38 
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 
45 /**
46  * Describe how to pack/unpack pixels into/from the prescribed format.
47  *
48  * XXX: This could be renamed to something like util_format_pack, or broke down
49  * in flags inside util_format_block that said exactly what we want.
50  */
51 enum util_format_layout {
52    /**
53     * Formats with util_format_block::width == util_format_block::height == 1
54     * that can be described as an ordinary data structure.
55     */
56    UTIL_FORMAT_LAYOUT_PLAIN = 0,
57 
58    /**
59     * Formats with sub-sampled channels.
60     *
61     * This is for formats like YVYU where there is less than one sample per
62     * pixel.
63     */
64    UTIL_FORMAT_LAYOUT_SUBSAMPLED = 3,
65 
66    /**
67     * S3 Texture Compression formats.
68     */
69    UTIL_FORMAT_LAYOUT_S3TC = 4,
70 
71    /**
72     * Red-Green Texture Compression formats.
73     */
74    UTIL_FORMAT_LAYOUT_RGTC = 5,
75 
76    /**
77     * Ericsson Texture Compression
78     */
79    UTIL_FORMAT_LAYOUT_ETC = 6,
80 
81    /**
82     * BC6/7 Texture Compression
83     */
84    UTIL_FORMAT_LAYOUT_BPTC = 7,
85 
86    UTIL_FORMAT_LAYOUT_ASTC = 8,
87 
88    UTIL_FORMAT_LAYOUT_ATC = 9,
89 
90    /** Formats with 2 or more planes. */
91    UTIL_FORMAT_LAYOUT_PLANAR2 = 10,
92    UTIL_FORMAT_LAYOUT_PLANAR3 = 11,
93 
94    UTIL_FORMAT_LAYOUT_FXT1 = 12,
95    /**
96     * Everything else that doesn't fit in any of the above layouts.
97     */
98    UTIL_FORMAT_LAYOUT_OTHER = 13,
99 };
100 
101 
102 struct util_format_block
103 {
104    /** Block width in pixels */
105    unsigned width;
106 
107    /** Block height in pixels */
108    unsigned height;
109 
110    /** Block size in bits */
111    unsigned bits;
112 };
113 
114 
115 enum util_format_type {
116    UTIL_FORMAT_TYPE_VOID = 0,
117    UTIL_FORMAT_TYPE_UNSIGNED = 1,
118    UTIL_FORMAT_TYPE_SIGNED = 2,
119    UTIL_FORMAT_TYPE_FIXED = 3,
120    UTIL_FORMAT_TYPE_FLOAT = 4
121 };
122 
123 
124 enum util_format_swizzle {
125    UTIL_FORMAT_SWIZZLE_X = 0,
126    UTIL_FORMAT_SWIZZLE_Y = 1,
127    UTIL_FORMAT_SWIZZLE_Z = 2,
128    UTIL_FORMAT_SWIZZLE_W = 3,
129    UTIL_FORMAT_SWIZZLE_0 = 4,
130    UTIL_FORMAT_SWIZZLE_1 = 5,
131    UTIL_FORMAT_SWIZZLE_NONE = 6,
132    UTIL_FORMAT_SWIZZLE_MAX = 7  /**< Number of enums counter (must be last) */
133 };
134 
135 
136 enum util_format_colorspace {
137    UTIL_FORMAT_COLORSPACE_RGB = 0,
138    UTIL_FORMAT_COLORSPACE_SRGB = 1,
139    UTIL_FORMAT_COLORSPACE_YUV = 2,
140    UTIL_FORMAT_COLORSPACE_ZS = 3
141 };
142 
143 
144 struct util_format_channel_description
145 {
146    unsigned type:5;        /**< UTIL_FORMAT_TYPE_x */
147    unsigned normalized:1;
148    unsigned pure_integer:1;
149    unsigned size:9;        /**< bits per channel */
150    unsigned shift:16;      /** number of bits from lsb */
151 };
152 
153 
154 struct util_format_description
155 {
156    enum pipe_format format;
157 
158    const char *name;
159 
160    /**
161     * Short name, striped of the prefix, lower case.
162     */
163    const char *short_name;
164 
165    /**
166     * Pixel block dimensions.
167     */
168    struct util_format_block block;
169 
170    enum util_format_layout layout;
171 
172    /**
173     * The number of channels.
174     */
175    unsigned nr_channels:3;
176 
177    /**
178     * Whether all channels have the same number of (whole) bytes and type.
179     */
180    unsigned is_array:1;
181 
182    /**
183     * Whether the pixel format can be described as a bitfield structure.
184     *
185     * In particular:
186     * - pixel depth must be 8, 16, or 32 bits;
187     * - all channels must be unsigned, signed, or void
188     */
189    unsigned is_bitmask:1;
190 
191    /**
192     * Whether channels have mixed types (ignoring UTIL_FORMAT_TYPE_VOID).
193     */
194    unsigned is_mixed:1;
195 
196    /**
197     * Input channel description, in the order XYZW.
198     *
199     * Only valid for UTIL_FORMAT_LAYOUT_PLAIN formats.
200     *
201     * If each channel is accessed as an individual N-byte value, X is always
202     * at the lowest address in memory, Y is always next, and so on.  For all
203     * currently-defined formats, the N-byte value has native endianness.
204     *
205     * If instead a group of channels is accessed as a single N-byte value,
206     * the order of the channels within that value depends on endianness.
207     * For big-endian targets, X is the most significant subvalue,
208     * otherwise it is the least significant one.
209     *
210     * For example, if X is 8 bits and Y is 24 bits, the memory order is:
211     *
212     *                 0  1  2  3
213     *  little-endian: X  Yl Ym Yu    (l = lower, m = middle, u = upper)
214     *  big-endian:    X  Yu Ym Yl
215     *
216     * If X is 5 bits, Y is 5 bits, Z is 5 bits and W is 1 bit, the layout is:
217     *
218     *                        0        1
219     *                 msb  lsb msb  lsb
220     *  little-endian: YYYXXXXX WZZZZZYY
221     *  big-endian:    XXXXXYYY YYZZZZZW
222     */
223    struct util_format_channel_description channel[4];
224 
225    /**
226     * Output channel swizzle.
227     *
228     * The order is either:
229     * - RGBA
230     * - YUV(A)
231     * - ZS
232     * depending on the colorspace.
233     */
234    unsigned char swizzle[4];
235 
236    /**
237     * Colorspace transformation.
238     */
239    enum util_format_colorspace colorspace;
240 };
241 
242 
243 extern const struct util_format_description
244 util_format_description_table[];
245 
246 
247 const struct util_format_description *
248 util_format_description(enum pipe_format format);
249 
250 
251 /*
252  * Format query functions.
253  */
254 
255 static inline const char *
util_format_name(enum pipe_format format)256 util_format_name(enum pipe_format format)
257 {
258    const struct util_format_description *desc = util_format_description(format);
259 
260    assert(desc);
261    if (!desc) {
262       return "PIPE_FORMAT_???";
263    }
264 
265    return desc->name;
266 }
267 
268 static inline const char *
util_format_short_name(enum pipe_format format)269 util_format_short_name(enum pipe_format format)
270 {
271    const struct util_format_description *desc = util_format_description(format);
272 
273    assert(desc);
274    if (!desc) {
275       return "???";
276    }
277 
278    return desc->short_name;
279 }
280 
281 /**
282  * Whether this format is plain, see UTIL_FORMAT_LAYOUT_PLAIN for more info.
283  */
284 static inline boolean
util_format_is_plain(enum pipe_format format)285 util_format_is_plain(enum pipe_format format)
286 {
287    const struct util_format_description *desc = util_format_description(format);
288 
289    if (!format) {
290       return FALSE;
291    }
292 
293    return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ? TRUE : FALSE;
294 }
295 
296 static inline boolean
util_format_is_compressed(enum pipe_format format)297 util_format_is_compressed(enum pipe_format format)
298 {
299    const struct util_format_description *desc = util_format_description(format);
300 
301    assert(desc);
302    if (!desc) {
303       return FALSE;
304    }
305 
306    switch (desc->layout) {
307    case UTIL_FORMAT_LAYOUT_S3TC:
308    case UTIL_FORMAT_LAYOUT_RGTC:
309    case UTIL_FORMAT_LAYOUT_ETC:
310    case UTIL_FORMAT_LAYOUT_BPTC:
311    case UTIL_FORMAT_LAYOUT_ASTC:
312    case UTIL_FORMAT_LAYOUT_ATC:
313    case UTIL_FORMAT_LAYOUT_FXT1:
314       /* XXX add other formats in the future */
315       return TRUE;
316    default:
317       return FALSE;
318    }
319 }
320 
321 static inline boolean
util_format_is_srgb(enum pipe_format format)322 util_format_is_srgb(enum pipe_format format)
323 {
324    const struct util_format_description *desc = util_format_description(format);
325    return desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB;
326 }
327 
328 static inline boolean
util_format_has_depth(const struct util_format_description * desc)329 util_format_has_depth(const struct util_format_description *desc)
330 {
331    return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
332           desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE;
333 }
334 
335 static inline boolean
util_format_has_stencil(const struct util_format_description * desc)336 util_format_has_stencil(const struct util_format_description *desc)
337 {
338    return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
339           desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE;
340 }
341 
342 static inline boolean
util_format_is_depth_or_stencil(enum pipe_format format)343 util_format_is_depth_or_stencil(enum pipe_format format)
344 {
345    const struct util_format_description *desc = util_format_description(format);
346 
347    assert(desc);
348    if (!desc) {
349       return FALSE;
350    }
351 
352    return util_format_has_depth(desc) ||
353           util_format_has_stencil(desc);
354 }
355 
356 static inline boolean
util_format_is_depth_and_stencil(enum pipe_format format)357 util_format_is_depth_and_stencil(enum pipe_format format)
358 {
359    const struct util_format_description *desc = util_format_description(format);
360 
361    assert(desc);
362    if (!desc) {
363       return FALSE;
364    }
365 
366    return util_format_has_depth(desc) &&
367           util_format_has_stencil(desc);
368 }
369 
370 
371 /**
372  * Calculates the depth format type based upon the incoming format description.
373  */
374 static inline unsigned
util_get_depth_format_type(const struct util_format_description * desc)375 util_get_depth_format_type(const struct util_format_description *desc)
376 {
377    unsigned depth_channel = desc->swizzle[0];
378    if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
379        depth_channel != UTIL_FORMAT_SWIZZLE_NONE) {
380       return desc->channel[depth_channel].type;
381    } else {
382       return UTIL_FORMAT_TYPE_VOID;
383    }
384 }
385 
386 
387 /**
388  * Calculates the MRD for the depth format. MRD is used in depth bias
389  * for UNORM and unbound depth buffers. When the depth buffer is floating
390  * point, the depth bias calculation does not use the MRD. However, the
391  * default MRD will be 1.0 / ((1 << 24) - 1).
392  */
393 double
394 util_get_depth_format_mrd(const struct util_format_description *desc);
395 
396 
397 /**
398  * Return whether this is an RGBA, Z, S, or combined ZS format.
399  * Useful for initializing pipe_blit_info::mask.
400  */
401 static inline unsigned
util_format_get_mask(enum pipe_format format)402 util_format_get_mask(enum pipe_format format)
403 {
404    const struct util_format_description *desc =
405       util_format_description(format);
406 
407    if (!desc)
408       return 0;
409 
410    if (util_format_has_depth(desc)) {
411       if (util_format_has_stencil(desc)) {
412          return PIPE_MASK_ZS;
413       } else {
414          return PIPE_MASK_Z;
415       }
416    } else {
417       if (util_format_has_stencil(desc)) {
418          return PIPE_MASK_S;
419       } else {
420          return PIPE_MASK_RGBA;
421       }
422    }
423 }
424 
425 boolean
426 util_format_has_alpha(enum pipe_format format);
427 
428 
429 boolean
430 util_format_is_luminance(enum pipe_format format);
431 
432 boolean
433 util_format_is_alpha(enum pipe_format format);
434 
435 boolean
436 util_format_is_luminance_alpha(enum pipe_format format);
437 
438 
439 boolean
440 util_format_is_intensity(enum pipe_format format);
441 
442 boolean
443 util_format_is_pure_integer(enum pipe_format format);
444 
445 boolean
446 util_format_is_pure_sint(enum pipe_format format);
447 
448 boolean
449 util_format_is_pure_uint(enum pipe_format format);
450 
451 boolean
452 util_format_is_snorm(enum pipe_format format);
453 
454 /**
455  * Check if the src format can be blitted to the destination format with
456  * a simple memcpy.  For example, blitting from RGBA to RGBx is OK, but not
457  * the reverse.
458  */
459 boolean
460 util_is_format_compatible(const struct util_format_description *src_desc,
461                           const struct util_format_description *dst_desc);
462 
463 /**
464  * Whether this format is a rgab8 variant.
465  *
466  * That is, any format that matches the
467  *
468  *   PIPE_FORMAT_?8?8?8?8_UNORM
469  */
470 static inline boolean
util_format_is_rgba8_variant(const struct util_format_description * desc)471 util_format_is_rgba8_variant(const struct util_format_description *desc)
472 {
473    unsigned chan;
474 
475    if(desc->block.width != 1 ||
476       desc->block.height != 1 ||
477       desc->block.bits != 32)
478       return FALSE;
479 
480    for(chan = 0; chan < 4; ++chan) {
481       if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED &&
482          desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID)
483          return FALSE;
484       if(desc->channel[chan].type == UTIL_FORMAT_TYPE_UNSIGNED &&
485          !desc->channel[chan].normalized)
486          return FALSE;
487       if(desc->channel[chan].size != 8)
488          return FALSE;
489    }
490 
491    return TRUE;
492 }
493 
494 
495 /**
496  * Return total bits needed for the pixel format per block.
497  */
498 static inline uint
util_format_get_blocksizebits(enum pipe_format format)499 util_format_get_blocksizebits(enum pipe_format format)
500 {
501    const struct util_format_description *desc = util_format_description(format);
502 
503    assert(desc);
504    if (!desc) {
505       return 0;
506    }
507 
508    return desc->block.bits;
509 }
510 
511 /**
512  * Return bytes per block (not pixel) for the given format.
513  */
514 static inline uint
util_format_get_blocksize(enum pipe_format format)515 util_format_get_blocksize(enum pipe_format format)
516 {
517    uint bits = util_format_get_blocksizebits(format);
518    uint bytes = bits / 8;
519 
520    assert(bits % 8 == 0);
521    assert(bytes > 0);
522    if (bytes == 0) {
523       bytes = 1;
524    }
525 
526    return bytes;
527 }
528 
529 static inline uint
util_format_get_blockwidth(enum pipe_format format)530 util_format_get_blockwidth(enum pipe_format format)
531 {
532    const struct util_format_description *desc = util_format_description(format);
533 
534    assert(desc);
535    if (!desc) {
536       return 1;
537    }
538 
539    return desc->block.width;
540 }
541 
542 static inline uint
util_format_get_blockheight(enum pipe_format format)543 util_format_get_blockheight(enum pipe_format format)
544 {
545    const struct util_format_description *desc = util_format_description(format);
546 
547    assert(desc);
548    if (!desc) {
549       return 1;
550    }
551 
552    return desc->block.height;
553 }
554 
555 static inline unsigned
util_format_get_nblocksx(enum pipe_format format,unsigned x)556 util_format_get_nblocksx(enum pipe_format format,
557                          unsigned x)
558 {
559    unsigned blockwidth = util_format_get_blockwidth(format);
560    return (x + blockwidth - 1) / blockwidth;
561 }
562 
563 static inline unsigned
util_format_get_nblocksy(enum pipe_format format,unsigned y)564 util_format_get_nblocksy(enum pipe_format format,
565                          unsigned y)
566 {
567    unsigned blockheight = util_format_get_blockheight(format);
568    return (y + blockheight - 1) / blockheight;
569 }
570 
571 static inline unsigned
util_format_get_nblocks(enum pipe_format format,unsigned width,unsigned height)572 util_format_get_nblocks(enum pipe_format format,
573                         unsigned width,
574                         unsigned height)
575 {
576    return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height);
577 }
578 
579 static inline size_t
util_format_get_stride(enum pipe_format format,unsigned width)580 util_format_get_stride(enum pipe_format format,
581                        unsigned width)
582 {
583    return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format);
584 }
585 
586 static inline size_t
util_format_get_2d_size(enum pipe_format format,size_t stride,unsigned height)587 util_format_get_2d_size(enum pipe_format format,
588                         size_t stride,
589                         unsigned height)
590 {
591    return util_format_get_nblocksy(format, height) * stride;
592 }
593 
594 static inline uint
util_format_get_component_bits(enum pipe_format format,enum util_format_colorspace colorspace,uint component)595 util_format_get_component_bits(enum pipe_format format,
596                                enum util_format_colorspace colorspace,
597                                uint component)
598 {
599    const struct util_format_description *desc = util_format_description(format);
600    enum util_format_colorspace desc_colorspace;
601 
602    assert(format);
603    if (!format) {
604       return 0;
605    }
606 
607    assert(component < 4);
608 
609    /* Treat RGB and SRGB as equivalent. */
610    if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
611       colorspace = UTIL_FORMAT_COLORSPACE_RGB;
612    }
613    if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
614       desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB;
615    } else {
616       desc_colorspace = desc->colorspace;
617    }
618 
619    if (desc_colorspace != colorspace) {
620       return 0;
621    }
622 
623    switch (desc->swizzle[component]) {
624    case UTIL_FORMAT_SWIZZLE_X:
625       return desc->channel[0].size;
626    case UTIL_FORMAT_SWIZZLE_Y:
627       return desc->channel[1].size;
628    case UTIL_FORMAT_SWIZZLE_Z:
629       return desc->channel[2].size;
630    case UTIL_FORMAT_SWIZZLE_W:
631       return desc->channel[3].size;
632    default:
633       return 0;
634    }
635 }
636 
637 /**
638  * Given a linear RGB colorspace format, return the corresponding SRGB
639  * format, or PIPE_FORMAT_NONE if none.
640  */
641 static inline enum pipe_format
util_format_srgb(enum pipe_format format)642 util_format_srgb(enum pipe_format format)
643 {
644    if (util_format_is_srgb(format))
645       return format;
646 
647    switch (format) {
648    case PIPE_FORMAT_L8_UNORM:
649       return PIPE_FORMAT_L8_SRGB;
650    case PIPE_FORMAT_L8A8_UNORM:
651       return PIPE_FORMAT_L8A8_SRGB;
652    case PIPE_FORMAT_R8G8B8_UNORM:
653       return PIPE_FORMAT_R8G8B8_SRGB;
654    case PIPE_FORMAT_A8B8G8R8_UNORM:
655       return PIPE_FORMAT_A8B8G8R8_SRGB;
656    case PIPE_FORMAT_X8B8G8R8_UNORM:
657       return PIPE_FORMAT_X8B8G8R8_SRGB;
658    case PIPE_FORMAT_B8G8R8A8_UNORM:
659       return PIPE_FORMAT_B8G8R8A8_SRGB;
660    case PIPE_FORMAT_B8G8R8X8_UNORM:
661       return PIPE_FORMAT_B8G8R8X8_SRGB;
662    case PIPE_FORMAT_A8R8G8B8_UNORM:
663       return PIPE_FORMAT_A8R8G8B8_SRGB;
664    case PIPE_FORMAT_X8R8G8B8_UNORM:
665       return PIPE_FORMAT_X8R8G8B8_SRGB;
666    case PIPE_FORMAT_R8G8B8A8_UNORM:
667       return PIPE_FORMAT_R8G8B8A8_SRGB;
668    case PIPE_FORMAT_R8G8B8X8_UNORM:
669       return PIPE_FORMAT_R8G8B8X8_SRGB;
670    case PIPE_FORMAT_DXT1_RGB:
671       return PIPE_FORMAT_DXT1_SRGB;
672    case PIPE_FORMAT_DXT1_RGBA:
673       return PIPE_FORMAT_DXT1_SRGBA;
674    case PIPE_FORMAT_DXT3_RGBA:
675       return PIPE_FORMAT_DXT3_SRGBA;
676    case PIPE_FORMAT_DXT5_RGBA:
677       return PIPE_FORMAT_DXT5_SRGBA;
678    case PIPE_FORMAT_B5G6R5_UNORM:
679       return PIPE_FORMAT_B5G6R5_SRGB;
680    case PIPE_FORMAT_BPTC_RGBA_UNORM:
681       return PIPE_FORMAT_BPTC_SRGBA;
682    default:
683       return PIPE_FORMAT_NONE;
684    }
685 }
686 
687 /**
688  * Given an sRGB format, return the corresponding linear colorspace format.
689  * For non sRGB formats, return the format unchanged.
690  */
691 static inline enum pipe_format
util_format_linear(enum pipe_format format)692 util_format_linear(enum pipe_format format)
693 {
694    switch (format) {
695    case PIPE_FORMAT_L8_SRGB:
696       return PIPE_FORMAT_L8_UNORM;
697    case PIPE_FORMAT_L8A8_SRGB:
698       return PIPE_FORMAT_L8A8_UNORM;
699    case PIPE_FORMAT_R8G8B8_SRGB:
700       return PIPE_FORMAT_R8G8B8_UNORM;
701    case PIPE_FORMAT_A8B8G8R8_SRGB:
702       return PIPE_FORMAT_A8B8G8R8_UNORM;
703    case PIPE_FORMAT_X8B8G8R8_SRGB:
704       return PIPE_FORMAT_X8B8G8R8_UNORM;
705    case PIPE_FORMAT_B8G8R8A8_SRGB:
706       return PIPE_FORMAT_B8G8R8A8_UNORM;
707    case PIPE_FORMAT_B8G8R8X8_SRGB:
708       return PIPE_FORMAT_B8G8R8X8_UNORM;
709    case PIPE_FORMAT_A8R8G8B8_SRGB:
710       return PIPE_FORMAT_A8R8G8B8_UNORM;
711    case PIPE_FORMAT_X8R8G8B8_SRGB:
712       return PIPE_FORMAT_X8R8G8B8_UNORM;
713    case PIPE_FORMAT_R8G8B8A8_SRGB:
714       return PIPE_FORMAT_R8G8B8A8_UNORM;
715    case PIPE_FORMAT_R8G8B8X8_SRGB:
716       return PIPE_FORMAT_R8G8B8X8_UNORM;
717    case PIPE_FORMAT_DXT1_SRGB:
718       return PIPE_FORMAT_DXT1_RGB;
719    case PIPE_FORMAT_DXT1_SRGBA:
720       return PIPE_FORMAT_DXT1_RGBA;
721    case PIPE_FORMAT_DXT3_SRGBA:
722       return PIPE_FORMAT_DXT3_RGBA;
723    case PIPE_FORMAT_DXT5_SRGBA:
724       return PIPE_FORMAT_DXT5_RGBA;
725    case PIPE_FORMAT_B5G6R5_SRGB:
726       return PIPE_FORMAT_B5G6R5_UNORM;
727    case PIPE_FORMAT_BPTC_SRGBA:
728       return PIPE_FORMAT_BPTC_RGBA_UNORM;
729    default:
730       return format;
731    }
732 }
733 
734 /**
735  * Given a depth-stencil format, return the corresponding stencil-only format.
736  * For stencil-only formats, return the format unchanged.
737  */
738 static inline enum pipe_format
util_format_stencil_only(enum pipe_format format)739 util_format_stencil_only(enum pipe_format format)
740 {
741    switch (format) {
742    /* mask out the depth component */
743    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
744       return PIPE_FORMAT_X24S8_UINT;
745    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
746       return PIPE_FORMAT_S8X24_UINT;
747    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
748       return PIPE_FORMAT_X32_S8X24_UINT;
749 
750    /* stencil only formats */
751    case PIPE_FORMAT_X24S8_UINT:
752    case PIPE_FORMAT_S8X24_UINT:
753    case PIPE_FORMAT_X32_S8X24_UINT:
754    case PIPE_FORMAT_S8_UINT:
755       return format;
756 
757    default:
758       assert(0);
759       return PIPE_FORMAT_NONE;
760    }
761 }
762 
763 /**
764  * Converts PIPE_FORMAT_*I* to PIPE_FORMAT_*R*.
765  * This is identity for non-intensity formats.
766  */
767 static inline enum pipe_format
util_format_intensity_to_red(enum pipe_format format)768 util_format_intensity_to_red(enum pipe_format format)
769 {
770    switch (format) {
771    case PIPE_FORMAT_I8_UNORM:
772       return PIPE_FORMAT_R8_UNORM;
773    case PIPE_FORMAT_I8_SNORM:
774       return PIPE_FORMAT_R8_SNORM;
775    case PIPE_FORMAT_I16_UNORM:
776       return PIPE_FORMAT_R16_UNORM;
777    case PIPE_FORMAT_I16_SNORM:
778       return PIPE_FORMAT_R16_SNORM;
779    case PIPE_FORMAT_I16_FLOAT:
780       return PIPE_FORMAT_R16_FLOAT;
781    case PIPE_FORMAT_I32_FLOAT:
782       return PIPE_FORMAT_R32_FLOAT;
783    case PIPE_FORMAT_I8_UINT:
784       return PIPE_FORMAT_R8_UINT;
785    case PIPE_FORMAT_I8_SINT:
786       return PIPE_FORMAT_R8_SINT;
787    case PIPE_FORMAT_I16_UINT:
788       return PIPE_FORMAT_R16_UINT;
789    case PIPE_FORMAT_I16_SINT:
790       return PIPE_FORMAT_R16_SINT;
791    case PIPE_FORMAT_I32_UINT:
792       return PIPE_FORMAT_R32_UINT;
793    case PIPE_FORMAT_I32_SINT:
794       return PIPE_FORMAT_R32_SINT;
795    default:
796       assert(!util_format_is_intensity(format));
797       return format;
798    }
799 }
800 
801 /**
802  * Converts PIPE_FORMAT_*L* to PIPE_FORMAT_*R*.
803  * This is identity for non-luminance formats.
804  */
805 static inline enum pipe_format
util_format_luminance_to_red(enum pipe_format format)806 util_format_luminance_to_red(enum pipe_format format)
807 {
808    switch (format) {
809    case PIPE_FORMAT_L8_UNORM:
810       return PIPE_FORMAT_R8_UNORM;
811    case PIPE_FORMAT_L8_SNORM:
812       return PIPE_FORMAT_R8_SNORM;
813    case PIPE_FORMAT_L16_UNORM:
814       return PIPE_FORMAT_R16_UNORM;
815    case PIPE_FORMAT_L16_SNORM:
816       return PIPE_FORMAT_R16_SNORM;
817    case PIPE_FORMAT_L16_FLOAT:
818       return PIPE_FORMAT_R16_FLOAT;
819    case PIPE_FORMAT_L32_FLOAT:
820       return PIPE_FORMAT_R32_FLOAT;
821    case PIPE_FORMAT_L8_UINT:
822       return PIPE_FORMAT_R8_UINT;
823    case PIPE_FORMAT_L8_SINT:
824       return PIPE_FORMAT_R8_SINT;
825    case PIPE_FORMAT_L16_UINT:
826       return PIPE_FORMAT_R16_UINT;
827    case PIPE_FORMAT_L16_SINT:
828       return PIPE_FORMAT_R16_SINT;
829    case PIPE_FORMAT_L32_UINT:
830       return PIPE_FORMAT_R32_UINT;
831    case PIPE_FORMAT_L32_SINT:
832       return PIPE_FORMAT_R32_SINT;
833 
834    case PIPE_FORMAT_LATC1_UNORM:
835       return PIPE_FORMAT_RGTC1_UNORM;
836    case PIPE_FORMAT_LATC1_SNORM:
837       return PIPE_FORMAT_RGTC1_SNORM;
838 
839    case PIPE_FORMAT_L4A4_UNORM:
840       return PIPE_FORMAT_R4A4_UNORM;
841 
842    case PIPE_FORMAT_L8A8_UNORM:
843       return PIPE_FORMAT_R8A8_UNORM;
844    case PIPE_FORMAT_L8A8_SNORM:
845       return PIPE_FORMAT_R8A8_SNORM;
846    case PIPE_FORMAT_L16A16_UNORM:
847       return PIPE_FORMAT_R16A16_UNORM;
848    case PIPE_FORMAT_L16A16_SNORM:
849       return PIPE_FORMAT_R16A16_SNORM;
850    case PIPE_FORMAT_L16A16_FLOAT:
851       return PIPE_FORMAT_R16A16_FLOAT;
852    case PIPE_FORMAT_L32A32_FLOAT:
853       return PIPE_FORMAT_R32A32_FLOAT;
854    case PIPE_FORMAT_L8A8_UINT:
855       return PIPE_FORMAT_R8A8_UINT;
856    case PIPE_FORMAT_L8A8_SINT:
857       return PIPE_FORMAT_R8A8_SINT;
858    case PIPE_FORMAT_L16A16_UINT:
859       return PIPE_FORMAT_R16A16_UINT;
860    case PIPE_FORMAT_L16A16_SINT:
861       return PIPE_FORMAT_R16A16_SINT;
862    case PIPE_FORMAT_L32A32_UINT:
863       return PIPE_FORMAT_R32A32_UINT;
864    case PIPE_FORMAT_L32A32_SINT:
865       return PIPE_FORMAT_R32A32_SINT;
866 
867    /* We don't have compressed red-alpha variants for these. */
868    case PIPE_FORMAT_LATC2_UNORM:
869    case PIPE_FORMAT_LATC2_SNORM:
870       return PIPE_FORMAT_NONE;
871 
872    default:
873       assert(!util_format_is_luminance(format) &&
874 	     !util_format_is_luminance_alpha(format));
875       return format;
876    }
877 }
878 
879 /**
880  * Return the number of components stored.
881  * Formats with block size != 1x1 will always have 1 component (the block).
882  */
883 static inline unsigned
util_format_get_nr_components(enum pipe_format format)884 util_format_get_nr_components(enum pipe_format format)
885 {
886    const struct util_format_description *desc = util_format_description(format);
887    return desc->nr_channels;
888 }
889 
890 /**
891  * Return the index of the first non-void channel
892  * -1 if no non-void channels
893  */
894 static inline int
util_format_get_first_non_void_channel(enum pipe_format format)895 util_format_get_first_non_void_channel(enum pipe_format format)
896 {
897    const struct util_format_description *desc = util_format_description(format);
898    int i;
899 
900    for (i = 0; i < 4; i++)
901       if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
902          break;
903 
904    if (i == 4)
905        return -1;
906 
907    return i;
908 }
909 
910 /*
911  * Generic format conversion;
912  */
913 
914 boolean
915 util_format_fits_8unorm(const struct util_format_description *format_desc);
916 
917 /*
918  * Swizzle operations.
919  */
920 
921 /* Compose two sets of swizzles.
922  * If V is a 4D vector and the function parameters represent functions that
923  * swizzle vector components, this holds:
924  *     swz2(swz1(V)) = dst(V)
925  */
926 void util_format_compose_swizzles(const unsigned char swz1[4],
927                                   const unsigned char swz2[4],
928                                   unsigned char dst[4]);
929 
930 /* Apply the swizzle provided in \param swz (which is one of PIPE_SWIZZLE_x)
931  * to \param src and store the result in \param dst.
932  * \param is_integer determines the value written for PIPE_SWIZZLE_ONE.
933  */
934 void util_format_apply_color_swizzle(union pipe_color_union *dst,
935                                      const union pipe_color_union *src,
936                                      const unsigned char swz[4],
937                                      const boolean is_integer);
938 
939 void util_format_swizzle_4f(float *dst, const float *src,
940                             const unsigned char swz[4]);
941 
942 void util_format_unswizzle_4f(float *dst, const float *src,
943                               const unsigned char swz[4]);
944 
945 #ifdef __cplusplus
946 } // extern "C" {
947 #endif
948 
949 #endif /* ! U_FORMAT_H */
950