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_s3tc(enum pipe_format format)322 util_format_is_s3tc(enum pipe_format format)
323 {
324    const struct util_format_description *desc = util_format_description(format);
325 
326    assert(desc);
327    if (!desc) {
328       return FALSE;
329    }
330 
331    return desc->layout == UTIL_FORMAT_LAYOUT_S3TC ? TRUE : FALSE;
332 }
333 
334 static inline boolean
util_format_is_srgb(enum pipe_format format)335 util_format_is_srgb(enum pipe_format format)
336 {
337    const struct util_format_description *desc = util_format_description(format);
338    return desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB;
339 }
340 
341 static inline boolean
util_format_has_depth(const struct util_format_description * desc)342 util_format_has_depth(const struct util_format_description *desc)
343 {
344    return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
345           desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE;
346 }
347 
348 static inline boolean
util_format_has_stencil(const struct util_format_description * desc)349 util_format_has_stencil(const struct util_format_description *desc)
350 {
351    return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
352           desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE;
353 }
354 
355 static inline boolean
util_format_is_depth_or_stencil(enum pipe_format format)356 util_format_is_depth_or_stencil(enum pipe_format format)
357 {
358    const struct util_format_description *desc = util_format_description(format);
359 
360    assert(desc);
361    if (!desc) {
362       return FALSE;
363    }
364 
365    return util_format_has_depth(desc) ||
366           util_format_has_stencil(desc);
367 }
368 
369 static inline boolean
util_format_is_depth_and_stencil(enum pipe_format format)370 util_format_is_depth_and_stencil(enum pipe_format format)
371 {
372    const struct util_format_description *desc = util_format_description(format);
373 
374    assert(desc);
375    if (!desc) {
376       return FALSE;
377    }
378 
379    return util_format_has_depth(desc) &&
380           util_format_has_stencil(desc);
381 }
382 
383 
384 /**
385  * Calculates the depth format type based upon the incoming format description.
386  */
387 static inline unsigned
util_get_depth_format_type(const struct util_format_description * desc)388 util_get_depth_format_type(const struct util_format_description *desc)
389 {
390    unsigned depth_channel = desc->swizzle[0];
391    if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
392        depth_channel != UTIL_FORMAT_SWIZZLE_NONE) {
393       return desc->channel[depth_channel].type;
394    } else {
395       return UTIL_FORMAT_TYPE_VOID;
396    }
397 }
398 
399 
400 /**
401  * Calculates the MRD for the depth format. MRD is used in depth bias
402  * for UNORM and unbound depth buffers. When the depth buffer is floating
403  * point, the depth bias calculation does not use the MRD. However, the
404  * default MRD will be 1.0 / ((1 << 24) - 1).
405  */
406 double
407 util_get_depth_format_mrd(const struct util_format_description *desc);
408 
409 
410 /**
411  * Return whether this is an RGBA, Z, S, or combined ZS format.
412  * Useful for initializing pipe_blit_info::mask.
413  */
414 static inline unsigned
util_format_get_mask(enum pipe_format format)415 util_format_get_mask(enum pipe_format format)
416 {
417    const struct util_format_description *desc =
418       util_format_description(format);
419 
420    if (!desc)
421       return 0;
422 
423    if (util_format_has_depth(desc)) {
424       if (util_format_has_stencil(desc)) {
425          return PIPE_MASK_ZS;
426       } else {
427          return PIPE_MASK_Z;
428       }
429    } else {
430       if (util_format_has_stencil(desc)) {
431          return PIPE_MASK_S;
432       } else {
433          return PIPE_MASK_RGBA;
434       }
435    }
436 }
437 
438 /**
439  * Give the RGBA colormask of the channels that can be represented in this
440  * format.
441  *
442  * That is, the channels whose values are preserved.
443  */
444 static inline unsigned
util_format_colormask(const struct util_format_description * desc)445 util_format_colormask(const struct util_format_description *desc)
446 {
447    unsigned colormask;
448    unsigned chan;
449 
450    switch (desc->colorspace) {
451    case UTIL_FORMAT_COLORSPACE_RGB:
452    case UTIL_FORMAT_COLORSPACE_SRGB:
453    case UTIL_FORMAT_COLORSPACE_YUV:
454       colormask = 0;
455       for (chan = 0; chan < 4; ++chan) {
456          if (desc->swizzle[chan] < 4) {
457             colormask |= (1 << chan);
458          }
459       }
460       return colormask;
461    case UTIL_FORMAT_COLORSPACE_ZS:
462       return 0;
463    default:
464       assert(0);
465       return 0;
466    }
467 }
468 
469 
470 /**
471  * Checks if color mask covers every channel for the specified format
472  *
473  * @param desc       a format description to check colormask with
474  * @param colormask  a bit mask for channels, matches format of PIPE_MASK_RGBA
475  */
476 static inline boolean
util_format_colormask_full(const struct util_format_description * desc,unsigned colormask)477 util_format_colormask_full(const struct util_format_description *desc, unsigned colormask)
478 {
479    return (~colormask & util_format_colormask(desc)) == 0;
480 }
481 
482 
483 boolean
484 util_format_is_float(enum pipe_format format);
485 
486 
487 boolean
488 util_format_has_alpha(enum pipe_format format);
489 
490 
491 boolean
492 util_format_is_luminance(enum pipe_format format);
493 
494 boolean
495 util_format_is_alpha(enum pipe_format format);
496 
497 boolean
498 util_format_is_luminance_alpha(enum pipe_format format);
499 
500 
501 boolean
502 util_format_is_intensity(enum pipe_format format);
503 
504 boolean
505 util_format_is_subsampled_422(enum pipe_format format);
506 
507 boolean
508 util_format_is_pure_integer(enum pipe_format format);
509 
510 boolean
511 util_format_is_pure_sint(enum pipe_format format);
512 
513 boolean
514 util_format_is_pure_uint(enum pipe_format format);
515 
516 boolean
517 util_format_is_snorm(enum pipe_format format);
518 
519 /**
520  * Check if the src format can be blitted to the destination format with
521  * a simple memcpy.  For example, blitting from RGBA to RGBx is OK, but not
522  * the reverse.
523  */
524 boolean
525 util_is_format_compatible(const struct util_format_description *src_desc,
526                           const struct util_format_description *dst_desc);
527 
528 /**
529  * Whether the format is supported by Gallium for the given bindings.
530  * This covers S3TC textures and floating-point render targets.
531  */
532 boolean
533 util_format_is_supported(enum pipe_format format, unsigned bind);
534 
535 /**
536  * Whether this format is a rgab8 variant.
537  *
538  * That is, any format that matches the
539  *
540  *   PIPE_FORMAT_?8?8?8?8_UNORM
541  */
542 static inline boolean
util_format_is_rgba8_variant(const struct util_format_description * desc)543 util_format_is_rgba8_variant(const struct util_format_description *desc)
544 {
545    unsigned chan;
546 
547    if(desc->block.width != 1 ||
548       desc->block.height != 1 ||
549       desc->block.bits != 32)
550       return FALSE;
551 
552    for(chan = 0; chan < 4; ++chan) {
553       if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED &&
554          desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID)
555          return FALSE;
556       if(desc->channel[chan].type == UTIL_FORMAT_TYPE_UNSIGNED &&
557          !desc->channel[chan].normalized)
558          return FALSE;
559       if(desc->channel[chan].size != 8)
560          return FALSE;
561    }
562 
563    return TRUE;
564 }
565 
566 
567 /**
568  * Return total bits needed for the pixel format per block.
569  */
570 static inline uint
util_format_get_blocksizebits(enum pipe_format format)571 util_format_get_blocksizebits(enum pipe_format format)
572 {
573    const struct util_format_description *desc = util_format_description(format);
574 
575    assert(desc);
576    if (!desc) {
577       return 0;
578    }
579 
580    return desc->block.bits;
581 }
582 
583 /**
584  * Return bytes per block (not pixel) for the given format.
585  */
586 static inline uint
util_format_get_blocksize(enum pipe_format format)587 util_format_get_blocksize(enum pipe_format format)
588 {
589    uint bits = util_format_get_blocksizebits(format);
590    uint bytes = bits / 8;
591 
592    assert(bits % 8 == 0);
593    assert(bytes > 0);
594    if (bytes == 0) {
595       bytes = 1;
596    }
597 
598    return bytes;
599 }
600 
601 static inline uint
util_format_get_blockwidth(enum pipe_format format)602 util_format_get_blockwidth(enum pipe_format format)
603 {
604    const struct util_format_description *desc = util_format_description(format);
605 
606    assert(desc);
607    if (!desc) {
608       return 1;
609    }
610 
611    return desc->block.width;
612 }
613 
614 static inline uint
util_format_get_blockheight(enum pipe_format format)615 util_format_get_blockheight(enum pipe_format format)
616 {
617    const struct util_format_description *desc = util_format_description(format);
618 
619    assert(desc);
620    if (!desc) {
621       return 1;
622    }
623 
624    return desc->block.height;
625 }
626 
627 static inline unsigned
util_format_get_nblocksx(enum pipe_format format,unsigned x)628 util_format_get_nblocksx(enum pipe_format format,
629                          unsigned x)
630 {
631    unsigned blockwidth = util_format_get_blockwidth(format);
632    return (x + blockwidth - 1) / blockwidth;
633 }
634 
635 static inline unsigned
util_format_get_nblocksy(enum pipe_format format,unsigned y)636 util_format_get_nblocksy(enum pipe_format format,
637                          unsigned y)
638 {
639    unsigned blockheight = util_format_get_blockheight(format);
640    return (y + blockheight - 1) / blockheight;
641 }
642 
643 static inline unsigned
util_format_get_nblocks(enum pipe_format format,unsigned width,unsigned height)644 util_format_get_nblocks(enum pipe_format format,
645                         unsigned width,
646                         unsigned height)
647 {
648    return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height);
649 }
650 
651 static inline size_t
util_format_get_stride(enum pipe_format format,unsigned width)652 util_format_get_stride(enum pipe_format format,
653                        unsigned width)
654 {
655    return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format);
656 }
657 
658 static inline size_t
util_format_get_2d_size(enum pipe_format format,size_t stride,unsigned height)659 util_format_get_2d_size(enum pipe_format format,
660                         size_t stride,
661                         unsigned height)
662 {
663    return util_format_get_nblocksy(format, height) * stride;
664 }
665 
666 static inline uint
util_format_get_component_bits(enum pipe_format format,enum util_format_colorspace colorspace,uint component)667 util_format_get_component_bits(enum pipe_format format,
668                                enum util_format_colorspace colorspace,
669                                uint component)
670 {
671    const struct util_format_description *desc = util_format_description(format);
672    enum util_format_colorspace desc_colorspace;
673 
674    assert(format);
675    if (!format) {
676       return 0;
677    }
678 
679    assert(component < 4);
680 
681    /* Treat RGB and SRGB as equivalent. */
682    if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
683       colorspace = UTIL_FORMAT_COLORSPACE_RGB;
684    }
685    if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
686       desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB;
687    } else {
688       desc_colorspace = desc->colorspace;
689    }
690 
691    if (desc_colorspace != colorspace) {
692       return 0;
693    }
694 
695    switch (desc->swizzle[component]) {
696    case UTIL_FORMAT_SWIZZLE_X:
697       return desc->channel[0].size;
698    case UTIL_FORMAT_SWIZZLE_Y:
699       return desc->channel[1].size;
700    case UTIL_FORMAT_SWIZZLE_Z:
701       return desc->channel[2].size;
702    case UTIL_FORMAT_SWIZZLE_W:
703       return desc->channel[3].size;
704    default:
705       return 0;
706    }
707 }
708 
709 /**
710  * Given a linear RGB colorspace format, return the corresponding SRGB
711  * format, or PIPE_FORMAT_NONE if none.
712  */
713 static inline enum pipe_format
util_format_srgb(enum pipe_format format)714 util_format_srgb(enum pipe_format format)
715 {
716    if (util_format_is_srgb(format))
717       return format;
718 
719    switch (format) {
720    case PIPE_FORMAT_L8_UNORM:
721       return PIPE_FORMAT_L8_SRGB;
722    case PIPE_FORMAT_L8A8_UNORM:
723       return PIPE_FORMAT_L8A8_SRGB;
724    case PIPE_FORMAT_R8G8B8_UNORM:
725       return PIPE_FORMAT_R8G8B8_SRGB;
726    case PIPE_FORMAT_A8B8G8R8_UNORM:
727       return PIPE_FORMAT_A8B8G8R8_SRGB;
728    case PIPE_FORMAT_X8B8G8R8_UNORM:
729       return PIPE_FORMAT_X8B8G8R8_SRGB;
730    case PIPE_FORMAT_B8G8R8A8_UNORM:
731       return PIPE_FORMAT_B8G8R8A8_SRGB;
732    case PIPE_FORMAT_B8G8R8X8_UNORM:
733       return PIPE_FORMAT_B8G8R8X8_SRGB;
734    case PIPE_FORMAT_A8R8G8B8_UNORM:
735       return PIPE_FORMAT_A8R8G8B8_SRGB;
736    case PIPE_FORMAT_X8R8G8B8_UNORM:
737       return PIPE_FORMAT_X8R8G8B8_SRGB;
738    case PIPE_FORMAT_R8G8B8A8_UNORM:
739       return PIPE_FORMAT_R8G8B8A8_SRGB;
740    case PIPE_FORMAT_R8G8B8X8_UNORM:
741       return PIPE_FORMAT_R8G8B8X8_SRGB;
742    case PIPE_FORMAT_DXT1_RGB:
743       return PIPE_FORMAT_DXT1_SRGB;
744    case PIPE_FORMAT_DXT1_RGBA:
745       return PIPE_FORMAT_DXT1_SRGBA;
746    case PIPE_FORMAT_DXT3_RGBA:
747       return PIPE_FORMAT_DXT3_SRGBA;
748    case PIPE_FORMAT_DXT5_RGBA:
749       return PIPE_FORMAT_DXT5_SRGBA;
750    case PIPE_FORMAT_B5G6R5_UNORM:
751       return PIPE_FORMAT_B5G6R5_SRGB;
752    case PIPE_FORMAT_BPTC_RGBA_UNORM:
753       return PIPE_FORMAT_BPTC_SRGBA;
754    default:
755       return PIPE_FORMAT_NONE;
756    }
757 }
758 
759 /**
760  * Given an sRGB format, return the corresponding linear colorspace format.
761  * For non sRGB formats, return the format unchanged.
762  */
763 static inline enum pipe_format
util_format_linear(enum pipe_format format)764 util_format_linear(enum pipe_format format)
765 {
766    switch (format) {
767    case PIPE_FORMAT_L8_SRGB:
768       return PIPE_FORMAT_L8_UNORM;
769    case PIPE_FORMAT_L8A8_SRGB:
770       return PIPE_FORMAT_L8A8_UNORM;
771    case PIPE_FORMAT_R8G8B8_SRGB:
772       return PIPE_FORMAT_R8G8B8_UNORM;
773    case PIPE_FORMAT_A8B8G8R8_SRGB:
774       return PIPE_FORMAT_A8B8G8R8_UNORM;
775    case PIPE_FORMAT_X8B8G8R8_SRGB:
776       return PIPE_FORMAT_X8B8G8R8_UNORM;
777    case PIPE_FORMAT_B8G8R8A8_SRGB:
778       return PIPE_FORMAT_B8G8R8A8_UNORM;
779    case PIPE_FORMAT_B8G8R8X8_SRGB:
780       return PIPE_FORMAT_B8G8R8X8_UNORM;
781    case PIPE_FORMAT_A8R8G8B8_SRGB:
782       return PIPE_FORMAT_A8R8G8B8_UNORM;
783    case PIPE_FORMAT_X8R8G8B8_SRGB:
784       return PIPE_FORMAT_X8R8G8B8_UNORM;
785    case PIPE_FORMAT_R8G8B8A8_SRGB:
786       return PIPE_FORMAT_R8G8B8A8_UNORM;
787    case PIPE_FORMAT_R8G8B8X8_SRGB:
788       return PIPE_FORMAT_R8G8B8X8_UNORM;
789    case PIPE_FORMAT_DXT1_SRGB:
790       return PIPE_FORMAT_DXT1_RGB;
791    case PIPE_FORMAT_DXT1_SRGBA:
792       return PIPE_FORMAT_DXT1_RGBA;
793    case PIPE_FORMAT_DXT3_SRGBA:
794       return PIPE_FORMAT_DXT3_RGBA;
795    case PIPE_FORMAT_DXT5_SRGBA:
796       return PIPE_FORMAT_DXT5_RGBA;
797    case PIPE_FORMAT_B5G6R5_SRGB:
798       return PIPE_FORMAT_B5G6R5_UNORM;
799    case PIPE_FORMAT_BPTC_SRGBA:
800       return PIPE_FORMAT_BPTC_RGBA_UNORM;
801    default:
802       return format;
803    }
804 }
805 
806 /**
807  * Given a depth-stencil format, return the corresponding stencil-only format.
808  * For stencil-only formats, return the format unchanged.
809  */
810 static inline enum pipe_format
util_format_stencil_only(enum pipe_format format)811 util_format_stencil_only(enum pipe_format format)
812 {
813    switch (format) {
814    /* mask out the depth component */
815    case PIPE_FORMAT_Z24_UNORM_S8_UINT:
816       return PIPE_FORMAT_X24S8_UINT;
817    case PIPE_FORMAT_S8_UINT_Z24_UNORM:
818       return PIPE_FORMAT_S8X24_UINT;
819    case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
820       return PIPE_FORMAT_X32_S8X24_UINT;
821 
822    /* stencil only formats */
823    case PIPE_FORMAT_X24S8_UINT:
824    case PIPE_FORMAT_S8X24_UINT:
825    case PIPE_FORMAT_X32_S8X24_UINT:
826    case PIPE_FORMAT_S8_UINT:
827       return format;
828 
829    default:
830       assert(0);
831       return PIPE_FORMAT_NONE;
832    }
833 }
834 
835 /**
836  * Converts PIPE_FORMAT_*I* to PIPE_FORMAT_*R*.
837  * This is identity for non-intensity formats.
838  */
839 static inline enum pipe_format
util_format_intensity_to_red(enum pipe_format format)840 util_format_intensity_to_red(enum pipe_format format)
841 {
842    switch (format) {
843    case PIPE_FORMAT_I8_UNORM:
844       return PIPE_FORMAT_R8_UNORM;
845    case PIPE_FORMAT_I8_SNORM:
846       return PIPE_FORMAT_R8_SNORM;
847    case PIPE_FORMAT_I16_UNORM:
848       return PIPE_FORMAT_R16_UNORM;
849    case PIPE_FORMAT_I16_SNORM:
850       return PIPE_FORMAT_R16_SNORM;
851    case PIPE_FORMAT_I16_FLOAT:
852       return PIPE_FORMAT_R16_FLOAT;
853    case PIPE_FORMAT_I32_FLOAT:
854       return PIPE_FORMAT_R32_FLOAT;
855    case PIPE_FORMAT_I8_UINT:
856       return PIPE_FORMAT_R8_UINT;
857    case PIPE_FORMAT_I8_SINT:
858       return PIPE_FORMAT_R8_SINT;
859    case PIPE_FORMAT_I16_UINT:
860       return PIPE_FORMAT_R16_UINT;
861    case PIPE_FORMAT_I16_SINT:
862       return PIPE_FORMAT_R16_SINT;
863    case PIPE_FORMAT_I32_UINT:
864       return PIPE_FORMAT_R32_UINT;
865    case PIPE_FORMAT_I32_SINT:
866       return PIPE_FORMAT_R32_SINT;
867    default:
868       assert(!util_format_is_intensity(format));
869       return format;
870    }
871 }
872 
873 /**
874  * Converts PIPE_FORMAT_*L* to PIPE_FORMAT_*R*.
875  * This is identity for non-luminance formats.
876  */
877 static inline enum pipe_format
util_format_luminance_to_red(enum pipe_format format)878 util_format_luminance_to_red(enum pipe_format format)
879 {
880    switch (format) {
881    case PIPE_FORMAT_L8_UNORM:
882       return PIPE_FORMAT_R8_UNORM;
883    case PIPE_FORMAT_L8_SNORM:
884       return PIPE_FORMAT_R8_SNORM;
885    case PIPE_FORMAT_L16_UNORM:
886       return PIPE_FORMAT_R16_UNORM;
887    case PIPE_FORMAT_L16_SNORM:
888       return PIPE_FORMAT_R16_SNORM;
889    case PIPE_FORMAT_L16_FLOAT:
890       return PIPE_FORMAT_R16_FLOAT;
891    case PIPE_FORMAT_L32_FLOAT:
892       return PIPE_FORMAT_R32_FLOAT;
893    case PIPE_FORMAT_L8_UINT:
894       return PIPE_FORMAT_R8_UINT;
895    case PIPE_FORMAT_L8_SINT:
896       return PIPE_FORMAT_R8_SINT;
897    case PIPE_FORMAT_L16_UINT:
898       return PIPE_FORMAT_R16_UINT;
899    case PIPE_FORMAT_L16_SINT:
900       return PIPE_FORMAT_R16_SINT;
901    case PIPE_FORMAT_L32_UINT:
902       return PIPE_FORMAT_R32_UINT;
903    case PIPE_FORMAT_L32_SINT:
904       return PIPE_FORMAT_R32_SINT;
905 
906    case PIPE_FORMAT_LATC1_UNORM:
907       return PIPE_FORMAT_RGTC1_UNORM;
908    case PIPE_FORMAT_LATC1_SNORM:
909       return PIPE_FORMAT_RGTC1_SNORM;
910 
911    case PIPE_FORMAT_L4A4_UNORM:
912       return PIPE_FORMAT_R4A4_UNORM;
913 
914    case PIPE_FORMAT_L8A8_UNORM:
915       return PIPE_FORMAT_R8A8_UNORM;
916    case PIPE_FORMAT_L8A8_SNORM:
917       return PIPE_FORMAT_R8A8_SNORM;
918    case PIPE_FORMAT_L16A16_UNORM:
919       return PIPE_FORMAT_R16A16_UNORM;
920    case PIPE_FORMAT_L16A16_SNORM:
921       return PIPE_FORMAT_R16A16_SNORM;
922    case PIPE_FORMAT_L16A16_FLOAT:
923       return PIPE_FORMAT_R16A16_FLOAT;
924    case PIPE_FORMAT_L32A32_FLOAT:
925       return PIPE_FORMAT_R32A32_FLOAT;
926    case PIPE_FORMAT_L8A8_UINT:
927       return PIPE_FORMAT_R8A8_UINT;
928    case PIPE_FORMAT_L8A8_SINT:
929       return PIPE_FORMAT_R8A8_SINT;
930    case PIPE_FORMAT_L16A16_UINT:
931       return PIPE_FORMAT_R16A16_UINT;
932    case PIPE_FORMAT_L16A16_SINT:
933       return PIPE_FORMAT_R16A16_SINT;
934    case PIPE_FORMAT_L32A32_UINT:
935       return PIPE_FORMAT_R32A32_UINT;
936    case PIPE_FORMAT_L32A32_SINT:
937       return PIPE_FORMAT_R32A32_SINT;
938 
939    /* We don't have compressed red-alpha variants for these. */
940    case PIPE_FORMAT_LATC2_UNORM:
941    case PIPE_FORMAT_LATC2_SNORM:
942       return PIPE_FORMAT_NONE;
943 
944    default:
945       assert(!util_format_is_luminance(format) &&
946 	     !util_format_is_luminance_alpha(format));
947       return format;
948    }
949 }
950 
951 /**
952  * Return the number of components stored.
953  * Formats with block size != 1x1 will always have 1 component (the block).
954  */
955 static inline unsigned
util_format_get_nr_components(enum pipe_format format)956 util_format_get_nr_components(enum pipe_format format)
957 {
958    const struct util_format_description *desc = util_format_description(format);
959    return desc->nr_channels;
960 }
961 
962 /**
963  * Return the index of the first non-void channel
964  * -1 if no non-void channels
965  */
966 static inline int
util_format_get_first_non_void_channel(enum pipe_format format)967 util_format_get_first_non_void_channel(enum pipe_format format)
968 {
969    const struct util_format_description *desc = util_format_description(format);
970    int i;
971 
972    for (i = 0; i < 4; i++)
973       if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
974          break;
975 
976    if (i == 4)
977        return -1;
978 
979    return i;
980 }
981 
982 /*
983  * Generic format conversion;
984  */
985 
986 boolean
987 util_format_fits_8unorm(const struct util_format_description *format_desc);
988 
989 /*
990  * Swizzle operations.
991  */
992 
993 /* Compose two sets of swizzles.
994  * If V is a 4D vector and the function parameters represent functions that
995  * swizzle vector components, this holds:
996  *     swz2(swz1(V)) = dst(V)
997  */
998 void util_format_compose_swizzles(const unsigned char swz1[4],
999                                   const unsigned char swz2[4],
1000                                   unsigned char dst[4]);
1001 
1002 /* Apply the swizzle provided in \param swz (which is one of PIPE_SWIZZLE_x)
1003  * to \param src and store the result in \param dst.
1004  * \param is_integer determines the value written for PIPE_SWIZZLE_ONE.
1005  */
1006 void util_format_apply_color_swizzle(union pipe_color_union *dst,
1007                                      const union pipe_color_union *src,
1008                                      const unsigned char swz[4],
1009                                      const boolean is_integer);
1010 
1011 void util_format_swizzle_4f(float *dst, const float *src,
1012                             const unsigned char swz[4]);
1013 
1014 void util_format_unswizzle_4f(float *dst, const float *src,
1015                               const unsigned char swz[4]);
1016 
1017 #ifdef __cplusplus
1018 } // extern "C" {
1019 #endif
1020 
1021 #endif /* ! U_FORMAT_H */
1022