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 #include "c99_compat.h"
38
39 union pipe_color_union;
40 struct pipe_screen;
41
42
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46
47
48 /**
49 * Describe how to pack/unpack pixels into/from the prescribed format.
50 *
51 * XXX: This could be renamed to something like util_format_pack, or broke down
52 * in flags inside util_format_block that said exactly what we want.
53 */
54 enum util_format_layout {
55 /**
56 * Formats with util_format_block::width == util_format_block::height == 1
57 * that can be described as an ordinary data structure.
58 */
59 UTIL_FORMAT_LAYOUT_PLAIN,
60
61 /**
62 * Formats with sub-sampled channels.
63 *
64 * This is for formats like YVYU where there is less than one sample per
65 * pixel.
66 */
67 UTIL_FORMAT_LAYOUT_SUBSAMPLED,
68
69 /**
70 * S3 Texture Compression formats.
71 */
72 UTIL_FORMAT_LAYOUT_S3TC,
73
74 /**
75 * Red-Green Texture Compression formats.
76 */
77 UTIL_FORMAT_LAYOUT_RGTC,
78
79 /**
80 * Ericsson Texture Compression
81 */
82 UTIL_FORMAT_LAYOUT_ETC,
83
84 /**
85 * BC6/7 Texture Compression
86 */
87 UTIL_FORMAT_LAYOUT_BPTC,
88
89 UTIL_FORMAT_LAYOUT_ASTC,
90
91 UTIL_FORMAT_LAYOUT_ATC,
92
93 /** Formats with 2 or more planes. */
94 UTIL_FORMAT_LAYOUT_PLANAR2,
95 UTIL_FORMAT_LAYOUT_PLANAR3,
96
97 UTIL_FORMAT_LAYOUT_FXT1 = 10,
98
99 /**
100 * Everything else that doesn't fit in any of the above layouts.
101 */
102 UTIL_FORMAT_LAYOUT_OTHER,
103 };
104
105
106 struct util_format_block
107 {
108 /** Block width in pixels */
109 unsigned width;
110
111 /** Block height in pixels */
112 unsigned height;
113
114 /** Block depth in pixels */
115 unsigned depth;
116
117 /** Block size in bits */
118 unsigned bits;
119 };
120
121
122 enum util_format_type {
123 UTIL_FORMAT_TYPE_VOID = 0,
124 UTIL_FORMAT_TYPE_UNSIGNED = 1,
125 UTIL_FORMAT_TYPE_SIGNED = 2,
126 UTIL_FORMAT_TYPE_FIXED = 3,
127 UTIL_FORMAT_TYPE_FLOAT = 4
128 };
129
130
131 enum util_format_colorspace {
132 UTIL_FORMAT_COLORSPACE_RGB = 0,
133 UTIL_FORMAT_COLORSPACE_SRGB = 1,
134 UTIL_FORMAT_COLORSPACE_YUV = 2,
135 UTIL_FORMAT_COLORSPACE_ZS = 3
136 };
137
138
139 struct util_format_channel_description
140 {
141 unsigned type:5; /**< UTIL_FORMAT_TYPE_x */
142 unsigned normalized:1;
143 unsigned pure_integer:1;
144 unsigned size:9; /**< bits per channel */
145 unsigned shift:16; /** number of bits from lsb */
146 };
147
148
149 struct util_format_description
150 {
151 enum pipe_format format;
152
153 const char *name;
154
155 /**
156 * Short name, striped of the prefix, lower case.
157 */
158 const char *short_name;
159
160 /**
161 * Pixel block dimensions.
162 */
163 struct util_format_block block;
164
165 enum util_format_layout layout;
166
167 /**
168 * The number of channels.
169 */
170 unsigned nr_channels:3;
171
172 /**
173 * Whether all channels have the same number of (whole) bytes and type.
174 */
175 unsigned is_array:1;
176
177 /**
178 * Whether the pixel format can be described as a bitfield structure.
179 *
180 * In particular:
181 * - pixel depth must be 8, 16, or 32 bits;
182 * - all channels must be unsigned, signed, or void
183 */
184 unsigned is_bitmask:1;
185
186 /**
187 * Whether channels have mixed types (ignoring UTIL_FORMAT_TYPE_VOID).
188 */
189 unsigned is_mixed:1;
190
191 /**
192 * Whether the format contains UNORM channels
193 */
194 unsigned is_unorm:1;
195
196 /**
197 * Whether the format contains SNORM channels
198 */
199 unsigned is_snorm:1;
200
201 /**
202 * Input channel description, in the order XYZW.
203 *
204 * Only valid for UTIL_FORMAT_LAYOUT_PLAIN formats.
205 *
206 * If each channel is accessed as an individual N-byte value, X is always
207 * at the lowest address in memory, Y is always next, and so on. For all
208 * currently-defined formats, the N-byte value has native endianness.
209 *
210 * If instead a group of channels is accessed as a single N-byte value,
211 * the order of the channels within that value depends on endianness.
212 * For big-endian targets, X is the most significant subvalue,
213 * otherwise it is the least significant one.
214 *
215 * For example, if X is 8 bits and Y is 24 bits, the memory order is:
216 *
217 * 0 1 2 3
218 * little-endian: X Yl Ym Yu (l = lower, m = middle, u = upper)
219 * big-endian: X Yu Ym Yl
220 *
221 * If X is 5 bits, Y is 5 bits, Z is 5 bits and W is 1 bit, the layout is:
222 *
223 * 0 1
224 * msb lsb msb lsb
225 * little-endian: YYYXXXXX WZZZZZYY
226 * big-endian: XXXXXYYY YYZZZZZW
227 */
228 struct util_format_channel_description channel[4];
229
230 /**
231 * Output channel swizzle.
232 *
233 * The order is either:
234 * - RGBA
235 * - YUV(A)
236 * - ZS
237 * depending on the colorspace.
238 */
239 unsigned char swizzle[4];
240
241 /**
242 * Colorspace transformation.
243 */
244 enum util_format_colorspace colorspace;
245 };
246
247 struct util_format_pack_description {
248 /**
249 * Pack pixel blocks from R8G8B8A8_UNORM.
250 * Note: strides are in bytes.
251 *
252 * Only defined for non-depth-stencil formats.
253 */
254 void
255 (*pack_rgba_8unorm)(uint8_t *restrict dst, unsigned dst_stride,
256 const uint8_t *restrict src, unsigned src_stride,
257 unsigned width, unsigned height);
258
259 /**
260 * Pack pixel blocks from R32G32B32A32_FLOAT.
261 * Note: strides are in bytes.
262 *
263 * Only defined for non-depth-stencil formats.
264 */
265 void
266 (*pack_rgba_float)(uint8_t *restrict dst, unsigned dst_stride,
267 const float *restrict src, unsigned src_stride,
268 unsigned width, unsigned height);
269
270 /**
271 * Pack pixels from Z32_FLOAT.
272 * Note: strides are in bytes.
273 *
274 * Only defined for depth formats.
275 */
276 void
277 (*pack_z_32unorm)(uint8_t *restrict dst, unsigned dst_stride,
278 const uint32_t *restrict src, unsigned src_stride,
279 unsigned width, unsigned height);
280
281 /**
282 * Pack pixels from Z32_FLOAT.
283 * Note: strides are in bytes.
284 *
285 * Only defined for depth formats.
286 */
287 void
288 (*pack_z_float)(uint8_t *restrict dst, unsigned dst_stride,
289 const float *restrict src, unsigned src_stride,
290 unsigned width, unsigned height);
291
292 /**
293 * Pack pixels from S8_UINT.
294 * Note: strides are in bytes.
295 *
296 * Only defined for stencil formats.
297 */
298 void
299 (*pack_s_8uint)(uint8_t *restrict dst, unsigned dst_stride,
300 const uint8_t *restrict src, unsigned src_stride,
301 unsigned width, unsigned height);
302
303 void
304 (*pack_rgba_uint)(uint8_t *restrict dst, unsigned dst_stride,
305 const uint32_t *restrict src, unsigned src_stride,
306 unsigned width, unsigned height);
307
308 void
309 (*pack_rgba_sint)(uint8_t *restrict dst, unsigned dst_stride,
310 const int32_t *restrict src, unsigned src_stride,
311 unsigned width, unsigned height);
312 };
313
314
315 struct util_format_unpack_description {
316 /**
317 * Unpack pixel blocks to R8G8B8A8_UNORM.
318 * Note: strides are in bytes.
319 *
320 * Only defined for non-block non-depth-stencil formats.
321 */
322 void
323 (*unpack_rgba_8unorm)(uint8_t *restrict dst, const uint8_t *restrict src,
324 unsigned width);
325
326 /**
327 * Unpack pixel blocks to R8G8B8A8_UNORM.
328 * Note: strides are in bytes.
329 *
330 * Only defined for block non-depth-stencil formats.
331 */
332 void
333 (*unpack_rgba_8unorm_rect)(uint8_t *restrict dst, unsigned dst_stride,
334 const uint8_t *restrict src, unsigned src_stride,
335 unsigned width, unsigned height);
336
337 /**
338 * Fetch a single pixel (i, j) from a block.
339 *
340 * XXX: Only defined for a very few select formats.
341 */
342 void
343 (*fetch_rgba_8unorm)(uint8_t *restrict dst,
344 const uint8_t *restrict src,
345 unsigned i, unsigned j);
346
347 /**
348 * Unpack pixel blocks to R32G32B32A32_UINT/_INT_FLOAT based on whether the
349 * type is pure uint, int, or other.
350 *
351 * Note: strides are in bytes.
352 *
353 * Only defined for non-block non-depth-stencil formats.
354 */
355 void
356 (*unpack_rgba)(void *restrict dst, const uint8_t *restrict src,
357 unsigned width);
358
359 /**
360 * Unpack pixel blocks to R32G32B32A32_UINT/_INT_FLOAT based on whether the
361 * type is pure uint, int, or other.
362 *
363 * Note: strides are in bytes.
364 *
365 * Only defined for block non-depth-stencil formats.
366 */
367 void
368 (*unpack_rgba_rect)(void *restrict dst, unsigned dst_stride,
369 const uint8_t *restrict src, unsigned src_stride,
370 unsigned width, unsigned height);
371
372 /**
373 * Unpack pixels to Z32_UNORM.
374 * Note: strides are in bytes.
375 *
376 * Only defined for depth formats.
377 */
378 void
379 (*unpack_z_32unorm)(uint32_t *restrict dst, unsigned dst_stride,
380 const uint8_t *restrict src, unsigned src_stride,
381 unsigned width, unsigned height);
382
383 /**
384 * Unpack pixels to Z32_FLOAT.
385 * Note: strides are in bytes.
386 *
387 * Only defined for depth formats.
388 */
389 void
390 (*unpack_z_float)(float *restrict dst, unsigned dst_stride,
391 const uint8_t *restrict src, unsigned src_stride,
392 unsigned width, unsigned height);
393
394 /**
395 * Unpack pixels to S8_UINT.
396 * Note: strides are in bytes.
397 *
398 * Only defined for stencil formats.
399 */
400 void
401 (*unpack_s_8uint)(uint8_t *restrict dst, unsigned dst_stride,
402 const uint8_t *restrict src, unsigned src_stride,
403 unsigned width, unsigned height);
404 };
405
406 typedef void (*util_format_fetch_rgba_func_ptr)(void *restrict dst, const uint8_t *restrict src,
407 unsigned i, unsigned j);
408
409 /* Silence warnings triggered by sharing function/struct names */
410 #ifdef __GNUC__
411 #pragma GCC diagnostic push
412 #pragma GCC diagnostic ignored "-Wshadow"
413 #endif
414 const struct util_format_description *
415 util_format_description(enum pipe_format format) ATTRIBUTE_CONST;
416
417 const struct util_format_pack_description *
418 util_format_pack_description(enum pipe_format format) ATTRIBUTE_CONST;
419
420 /* Lookup with CPU detection for choosing optimized paths. */
421 const struct util_format_unpack_description *
422 util_format_unpack_description(enum pipe_format format) ATTRIBUTE_CONST;
423
424 /* Codegenned table of CPU-agnostic unpack code. */
425 const struct util_format_unpack_description *
426 util_format_unpack_description_generic(enum pipe_format format) ATTRIBUTE_CONST;
427
428 const struct util_format_unpack_description *
429 util_format_unpack_description_neon(enum pipe_format format) ATTRIBUTE_CONST;
430
431 #ifdef __GNUC__
432 #pragma GCC diagnostic pop
433 #endif
434
435 /**
436 * Returns a function to fetch a single pixel (i, j) from a block.
437 *
438 * Only defined for non-depth-stencil and non-integer formats.
439 */
440 util_format_fetch_rgba_func_ptr
441 util_format_fetch_rgba_func(enum pipe_format format) ATTRIBUTE_CONST;
442
443 /*
444 * Format query functions.
445 */
446
447 static inline const char *
util_format_name(enum pipe_format format)448 util_format_name(enum pipe_format format)
449 {
450 const struct util_format_description *desc = util_format_description(format);
451
452 assert(desc);
453 if (!desc) {
454 return "PIPE_FORMAT_???";
455 }
456
457 return desc->name;
458 }
459
460 static inline const char *
util_format_short_name(enum pipe_format format)461 util_format_short_name(enum pipe_format format)
462 {
463 const struct util_format_description *desc = util_format_description(format);
464
465 assert(desc);
466 if (!desc) {
467 return "???";
468 }
469
470 return desc->short_name;
471 }
472
473 /**
474 * Whether this format is plain, see UTIL_FORMAT_LAYOUT_PLAIN for more info.
475 */
476 static inline boolean
util_format_is_plain(enum pipe_format format)477 util_format_is_plain(enum pipe_format format)
478 {
479 const struct util_format_description *desc = util_format_description(format);
480
481 if (!format) {
482 return FALSE;
483 }
484
485 return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ? TRUE : FALSE;
486 }
487
488 static inline boolean
util_format_is_compressed(enum pipe_format format)489 util_format_is_compressed(enum pipe_format format)
490 {
491 const struct util_format_description *desc = util_format_description(format);
492
493 assert(desc);
494 if (!desc) {
495 return FALSE;
496 }
497
498 switch (desc->layout) {
499 case UTIL_FORMAT_LAYOUT_S3TC:
500 case UTIL_FORMAT_LAYOUT_RGTC:
501 case UTIL_FORMAT_LAYOUT_ETC:
502 case UTIL_FORMAT_LAYOUT_BPTC:
503 case UTIL_FORMAT_LAYOUT_ASTC:
504 case UTIL_FORMAT_LAYOUT_ATC:
505 case UTIL_FORMAT_LAYOUT_FXT1:
506 /* XXX add other formats in the future */
507 return TRUE;
508 default:
509 return FALSE;
510 }
511 }
512
513 static inline boolean
util_format_is_s3tc(enum pipe_format format)514 util_format_is_s3tc(enum pipe_format format)
515 {
516 const struct util_format_description *desc = util_format_description(format);
517
518 assert(desc);
519 if (!desc) {
520 return FALSE;
521 }
522
523 return desc->layout == UTIL_FORMAT_LAYOUT_S3TC ? TRUE : FALSE;
524 }
525
526 static inline boolean
util_format_is_etc(enum pipe_format format)527 util_format_is_etc(enum pipe_format format)
528 {
529 const struct util_format_description *desc = util_format_description(format);
530
531 assert(desc);
532 if (!desc) {
533 return FALSE;
534 }
535
536 return desc->layout == UTIL_FORMAT_LAYOUT_ETC ? TRUE : FALSE;
537 }
538
539 static inline boolean
util_format_is_srgb(enum pipe_format format)540 util_format_is_srgb(enum pipe_format format)
541 {
542 const struct util_format_description *desc = util_format_description(format);
543 return desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB;
544 }
545
546 static inline boolean
util_format_has_depth(const struct util_format_description * desc)547 util_format_has_depth(const struct util_format_description *desc)
548 {
549 return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
550 desc->swizzle[0] != PIPE_SWIZZLE_NONE;
551 }
552
553 static inline boolean
util_format_has_stencil(const struct util_format_description * desc)554 util_format_has_stencil(const struct util_format_description *desc)
555 {
556 return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
557 desc->swizzle[1] != PIPE_SWIZZLE_NONE;
558 }
559
560 static inline boolean
util_format_is_depth_or_stencil(enum pipe_format format)561 util_format_is_depth_or_stencil(enum pipe_format format)
562 {
563 const struct util_format_description *desc = util_format_description(format);
564
565 assert(desc);
566 if (!desc) {
567 return FALSE;
568 }
569
570 return util_format_has_depth(desc) ||
571 util_format_has_stencil(desc);
572 }
573
574 static inline boolean
util_format_is_depth_and_stencil(enum pipe_format format)575 util_format_is_depth_and_stencil(enum pipe_format format)
576 {
577 const struct util_format_description *desc = util_format_description(format);
578
579 assert(desc);
580 if (!desc) {
581 return FALSE;
582 }
583
584 return util_format_has_depth(desc) &&
585 util_format_has_stencil(desc);
586 }
587
588 /**
589 * For depth-stencil formats, return the equivalent depth-only format.
590 */
591 static inline enum pipe_format
util_format_get_depth_only(enum pipe_format format)592 util_format_get_depth_only(enum pipe_format format)
593 {
594 switch (format) {
595 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
596 return PIPE_FORMAT_Z24X8_UNORM;
597
598 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
599 return PIPE_FORMAT_X8Z24_UNORM;
600
601 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
602 return PIPE_FORMAT_Z32_FLOAT;
603
604 default:
605 return format;
606 }
607 }
608
609 static inline boolean
util_format_is_yuv(enum pipe_format format)610 util_format_is_yuv(enum pipe_format format)
611 {
612 const struct util_format_description *desc = util_format_description(format);
613
614 assert(desc);
615 if (!desc) {
616 return FALSE;
617 }
618
619 return desc->colorspace == UTIL_FORMAT_COLORSPACE_YUV;
620 }
621
622 /**
623 * Calculates the depth format type based upon the incoming format description.
624 */
625 static inline unsigned
util_get_depth_format_type(const struct util_format_description * desc)626 util_get_depth_format_type(const struct util_format_description *desc)
627 {
628 unsigned depth_channel = desc->swizzle[0];
629 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
630 depth_channel != PIPE_SWIZZLE_NONE) {
631 return desc->channel[depth_channel].type;
632 } else {
633 return UTIL_FORMAT_TYPE_VOID;
634 }
635 }
636
637
638 /**
639 * Calculates the MRD for the depth format. MRD is used in depth bias
640 * for UNORM and unbound depth buffers. When the depth buffer is floating
641 * point, the depth bias calculation does not use the MRD. However, the
642 * default MRD will be 1.0 / ((1 << 24) - 1).
643 */
644 double
645 util_get_depth_format_mrd(const struct util_format_description *desc);
646
647
648 /**
649 * Return whether this is an RGBA, Z, S, or combined ZS format.
650 * Useful for initializing pipe_blit_info::mask.
651 */
652 static inline unsigned
util_format_get_mask(enum pipe_format format)653 util_format_get_mask(enum pipe_format format)
654 {
655 const struct util_format_description *desc =
656 util_format_description(format);
657
658 if (!desc)
659 return 0;
660
661 if (util_format_has_depth(desc)) {
662 if (util_format_has_stencil(desc)) {
663 return PIPE_MASK_ZS;
664 } else {
665 return PIPE_MASK_Z;
666 }
667 } else {
668 if (util_format_has_stencil(desc)) {
669 return PIPE_MASK_S;
670 } else {
671 return PIPE_MASK_RGBA;
672 }
673 }
674 }
675
676 /**
677 * Give the RGBA colormask of the channels that can be represented in this
678 * format.
679 *
680 * That is, the channels whose values are preserved.
681 */
682 static inline unsigned
util_format_colormask(const struct util_format_description * desc)683 util_format_colormask(const struct util_format_description *desc)
684 {
685 unsigned colormask;
686 unsigned chan;
687
688 switch (desc->colorspace) {
689 case UTIL_FORMAT_COLORSPACE_RGB:
690 case UTIL_FORMAT_COLORSPACE_SRGB:
691 case UTIL_FORMAT_COLORSPACE_YUV:
692 colormask = 0;
693 for (chan = 0; chan < 4; ++chan) {
694 if (desc->swizzle[chan] < 4) {
695 colormask |= (1 << chan);
696 }
697 }
698 return colormask;
699 case UTIL_FORMAT_COLORSPACE_ZS:
700 return 0;
701 default:
702 assert(0);
703 return 0;
704 }
705 }
706
707
708 /**
709 * Checks if color mask covers every channel for the specified format
710 *
711 * @param desc a format description to check colormask with
712 * @param colormask a bit mask for channels, matches format of PIPE_MASK_RGBA
713 */
714 static inline boolean
util_format_colormask_full(const struct util_format_description * desc,unsigned colormask)715 util_format_colormask_full(const struct util_format_description *desc, unsigned colormask)
716 {
717 return (~colormask & util_format_colormask(desc)) == 0;
718 }
719
720
721 boolean
722 util_format_is_float(enum pipe_format format) ATTRIBUTE_CONST;
723
724
725 boolean
726 util_format_has_alpha(enum pipe_format format) ATTRIBUTE_CONST;
727
728 boolean
729 util_format_has_alpha1(enum pipe_format format) ATTRIBUTE_CONST;
730
731 boolean
732 util_format_is_luminance(enum pipe_format format) ATTRIBUTE_CONST;
733
734 boolean
735 util_format_is_alpha(enum pipe_format format) ATTRIBUTE_CONST;
736
737 boolean
738 util_format_is_luminance_alpha(enum pipe_format format) ATTRIBUTE_CONST;
739
740
741 boolean
742 util_format_is_intensity(enum pipe_format format) ATTRIBUTE_CONST;
743
744 boolean
745 util_format_is_subsampled_422(enum pipe_format format) ATTRIBUTE_CONST;
746
747 boolean
748 util_format_is_pure_integer(enum pipe_format format) ATTRIBUTE_CONST;
749
750 boolean
751 util_format_is_pure_sint(enum pipe_format format) ATTRIBUTE_CONST;
752
753 boolean
754 util_format_is_pure_uint(enum pipe_format format) ATTRIBUTE_CONST;
755
756 boolean
757 util_format_is_snorm(enum pipe_format format) ATTRIBUTE_CONST;
758
759 boolean
760 util_format_is_unorm(enum pipe_format format) ATTRIBUTE_CONST;
761
762 boolean
763 util_format_is_snorm8(enum pipe_format format) ATTRIBUTE_CONST;
764
765 boolean
766 util_format_is_scaled(enum pipe_format format) ATTRIBUTE_CONST;
767 /**
768 * Check if the src format can be blitted to the destination format with
769 * a simple memcpy. For example, blitting from RGBA to RGBx is OK, but not
770 * the reverse.
771 */
772 boolean
773 util_is_format_compatible(const struct util_format_description *src_desc,
774 const struct util_format_description *dst_desc) ATTRIBUTE_CONST;
775
776 /**
777 * Whether this format is a rgab8 variant.
778 *
779 * That is, any format that matches the
780 *
781 * PIPE_FORMAT_?8?8?8?8_UNORM
782 */
783 static inline boolean
util_format_is_rgba8_variant(const struct util_format_description * desc)784 util_format_is_rgba8_variant(const struct util_format_description *desc)
785 {
786 unsigned chan;
787
788 if(desc->block.width != 1 ||
789 desc->block.height != 1 ||
790 desc->block.bits != 32)
791 return FALSE;
792
793 for(chan = 0; chan < 4; ++chan) {
794 if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED &&
795 desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID)
796 return FALSE;
797 if(desc->channel[chan].type == UTIL_FORMAT_TYPE_UNSIGNED &&
798 !desc->channel[chan].normalized)
799 return FALSE;
800 if(desc->channel[chan].size != 8)
801 return FALSE;
802 }
803
804 return TRUE;
805 }
806
807
808 static inline bool
util_format_is_rgbx_or_bgrx(enum pipe_format format)809 util_format_is_rgbx_or_bgrx(enum pipe_format format)
810 {
811 const struct util_format_description *desc = util_format_description(format);
812 return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
813 desc->nr_channels == 4 &&
814 (desc->swizzle[0] == PIPE_SWIZZLE_X || desc->swizzle[0] == PIPE_SWIZZLE_Z) &&
815 desc->swizzle[1] == PIPE_SWIZZLE_Y &&
816 (desc->swizzle[2] == PIPE_SWIZZLE_Z || desc->swizzle[2] == PIPE_SWIZZLE_X) &&
817 desc->swizzle[3] == PIPE_SWIZZLE_1;
818 }
819
820 /**
821 * Return total bits needed for the pixel format per block.
822 */
823 static inline uint
util_format_get_blocksizebits(enum pipe_format format)824 util_format_get_blocksizebits(enum pipe_format format)
825 {
826 const struct util_format_description *desc = util_format_description(format);
827
828 assert(desc);
829 if (!desc) {
830 return 0;
831 }
832
833 return desc->block.bits;
834 }
835
836 /**
837 * Return bytes per block (not pixel) for the given format.
838 */
839 static inline uint
util_format_get_blocksize(enum pipe_format format)840 util_format_get_blocksize(enum pipe_format format)
841 {
842 uint bits = util_format_get_blocksizebits(format);
843 uint bytes = bits / 8;
844
845 assert(bits % 8 == 0);
846 /* Some formats have bits set to 0, let's default to 1.*/
847 if (bytes == 0) {
848 bytes = 1;
849 }
850
851 return bytes;
852 }
853
854 static inline uint
util_format_get_blockwidth(enum pipe_format format)855 util_format_get_blockwidth(enum pipe_format format)
856 {
857 const struct util_format_description *desc = util_format_description(format);
858
859 assert(desc);
860 if (!desc) {
861 return 1;
862 }
863
864 return desc->block.width;
865 }
866
867 static inline uint
util_format_get_blockheight(enum pipe_format format)868 util_format_get_blockheight(enum pipe_format format)
869 {
870 const struct util_format_description *desc = util_format_description(format);
871
872 assert(desc);
873 if (!desc) {
874 return 1;
875 }
876
877 return desc->block.height;
878 }
879
880 static inline uint
util_format_get_blockdepth(enum pipe_format format)881 util_format_get_blockdepth(enum pipe_format format)
882 {
883 const struct util_format_description *desc = util_format_description(format);
884
885 assert(desc);
886 if (!desc) {
887 return 1;
888 }
889
890 return desc->block.depth;
891 }
892
893 static inline unsigned
util_format_get_nblocksx(enum pipe_format format,unsigned x)894 util_format_get_nblocksx(enum pipe_format format,
895 unsigned x)
896 {
897 unsigned blockwidth = util_format_get_blockwidth(format);
898 return (x + blockwidth - 1) / blockwidth;
899 }
900
901 static inline unsigned
util_format_get_nblocksy(enum pipe_format format,unsigned y)902 util_format_get_nblocksy(enum pipe_format format,
903 unsigned y)
904 {
905 unsigned blockheight = util_format_get_blockheight(format);
906 return (y + blockheight - 1) / blockheight;
907 }
908
909 static inline unsigned
util_format_get_nblocksz(enum pipe_format format,unsigned z)910 util_format_get_nblocksz(enum pipe_format format,
911 unsigned z)
912 {
913 unsigned blockdepth = util_format_get_blockdepth(format);
914 return (z + blockdepth - 1) / blockdepth;
915 }
916
917 static inline unsigned
util_format_get_nblocks(enum pipe_format format,unsigned width,unsigned height)918 util_format_get_nblocks(enum pipe_format format,
919 unsigned width,
920 unsigned height)
921 {
922 assert(util_format_get_blockdepth(format) == 1);
923 return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height);
924 }
925
926 static inline size_t
util_format_get_stride(enum pipe_format format,unsigned width)927 util_format_get_stride(enum pipe_format format,
928 unsigned width)
929 {
930 return (size_t)util_format_get_nblocksx(format, width) * util_format_get_blocksize(format);
931 }
932
933 static inline size_t
util_format_get_2d_size(enum pipe_format format,size_t stride,unsigned height)934 util_format_get_2d_size(enum pipe_format format,
935 size_t stride,
936 unsigned height)
937 {
938 return util_format_get_nblocksy(format, height) * stride;
939 }
940
941 static inline uint
util_format_get_component_bits(enum pipe_format format,enum util_format_colorspace colorspace,uint component)942 util_format_get_component_bits(enum pipe_format format,
943 enum util_format_colorspace colorspace,
944 uint component)
945 {
946 const struct util_format_description *desc = util_format_description(format);
947 enum util_format_colorspace desc_colorspace;
948
949 assert(format);
950 if (!format) {
951 return 0;
952 }
953
954 assert(component < 4);
955
956 /* Treat RGB and SRGB as equivalent. */
957 if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
958 colorspace = UTIL_FORMAT_COLORSPACE_RGB;
959 }
960 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
961 desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB;
962 } else {
963 desc_colorspace = desc->colorspace;
964 }
965
966 if (desc_colorspace != colorspace) {
967 return 0;
968 }
969
970 switch (desc->swizzle[component]) {
971 case PIPE_SWIZZLE_X:
972 return desc->channel[0].size;
973 case PIPE_SWIZZLE_Y:
974 return desc->channel[1].size;
975 case PIPE_SWIZZLE_Z:
976 return desc->channel[2].size;
977 case PIPE_SWIZZLE_W:
978 return desc->channel[3].size;
979 default:
980 return 0;
981 }
982 }
983
984 /**
985 * Given a linear RGB colorspace format, return the corresponding SRGB
986 * format, or PIPE_FORMAT_NONE if none.
987 */
988 static inline enum pipe_format
util_format_srgb(enum pipe_format format)989 util_format_srgb(enum pipe_format format)
990 {
991 if (util_format_is_srgb(format))
992 return format;
993
994 switch (format) {
995 case PIPE_FORMAT_L8_UNORM:
996 return PIPE_FORMAT_L8_SRGB;
997 case PIPE_FORMAT_R8_UNORM:
998 return PIPE_FORMAT_R8_SRGB;
999 case PIPE_FORMAT_L8A8_UNORM:
1000 return PIPE_FORMAT_L8A8_SRGB;
1001 case PIPE_FORMAT_R8G8_UNORM:
1002 return PIPE_FORMAT_R8G8_SRGB;
1003 case PIPE_FORMAT_R8G8B8_UNORM:
1004 return PIPE_FORMAT_R8G8B8_SRGB;
1005 case PIPE_FORMAT_B8G8R8_UNORM:
1006 return PIPE_FORMAT_B8G8R8_SRGB;
1007 case PIPE_FORMAT_A8B8G8R8_UNORM:
1008 return PIPE_FORMAT_A8B8G8R8_SRGB;
1009 case PIPE_FORMAT_X8B8G8R8_UNORM:
1010 return PIPE_FORMAT_X8B8G8R8_SRGB;
1011 case PIPE_FORMAT_B8G8R8A8_UNORM:
1012 return PIPE_FORMAT_B8G8R8A8_SRGB;
1013 case PIPE_FORMAT_B8G8R8X8_UNORM:
1014 return PIPE_FORMAT_B8G8R8X8_SRGB;
1015 case PIPE_FORMAT_A8R8G8B8_UNORM:
1016 return PIPE_FORMAT_A8R8G8B8_SRGB;
1017 case PIPE_FORMAT_X8R8G8B8_UNORM:
1018 return PIPE_FORMAT_X8R8G8B8_SRGB;
1019 case PIPE_FORMAT_R8G8B8A8_UNORM:
1020 return PIPE_FORMAT_R8G8B8A8_SRGB;
1021 case PIPE_FORMAT_R8G8B8X8_UNORM:
1022 return PIPE_FORMAT_R8G8B8X8_SRGB;
1023 case PIPE_FORMAT_DXT1_RGB:
1024 return PIPE_FORMAT_DXT1_SRGB;
1025 case PIPE_FORMAT_DXT1_RGBA:
1026 return PIPE_FORMAT_DXT1_SRGBA;
1027 case PIPE_FORMAT_DXT3_RGBA:
1028 return PIPE_FORMAT_DXT3_SRGBA;
1029 case PIPE_FORMAT_DXT5_RGBA:
1030 return PIPE_FORMAT_DXT5_SRGBA;
1031 case PIPE_FORMAT_R5G6B5_UNORM:
1032 return PIPE_FORMAT_R5G6B5_SRGB;
1033 case PIPE_FORMAT_B5G6R5_UNORM:
1034 return PIPE_FORMAT_B5G6R5_SRGB;
1035 case PIPE_FORMAT_BPTC_RGBA_UNORM:
1036 return PIPE_FORMAT_BPTC_SRGBA;
1037 case PIPE_FORMAT_ETC2_RGB8:
1038 return PIPE_FORMAT_ETC2_SRGB8;
1039 case PIPE_FORMAT_ETC2_RGB8A1:
1040 return PIPE_FORMAT_ETC2_SRGB8A1;
1041 case PIPE_FORMAT_ETC2_RGBA8:
1042 return PIPE_FORMAT_ETC2_SRGBA8;
1043 case PIPE_FORMAT_ASTC_4x4:
1044 return PIPE_FORMAT_ASTC_4x4_SRGB;
1045 case PIPE_FORMAT_ASTC_5x4:
1046 return PIPE_FORMAT_ASTC_5x4_SRGB;
1047 case PIPE_FORMAT_ASTC_5x5:
1048 return PIPE_FORMAT_ASTC_5x5_SRGB;
1049 case PIPE_FORMAT_ASTC_6x5:
1050 return PIPE_FORMAT_ASTC_6x5_SRGB;
1051 case PIPE_FORMAT_ASTC_6x6:
1052 return PIPE_FORMAT_ASTC_6x6_SRGB;
1053 case PIPE_FORMAT_ASTC_8x5:
1054 return PIPE_FORMAT_ASTC_8x5_SRGB;
1055 case PIPE_FORMAT_ASTC_8x6:
1056 return PIPE_FORMAT_ASTC_8x6_SRGB;
1057 case PIPE_FORMAT_ASTC_8x8:
1058 return PIPE_FORMAT_ASTC_8x8_SRGB;
1059 case PIPE_FORMAT_ASTC_10x5:
1060 return PIPE_FORMAT_ASTC_10x5_SRGB;
1061 case PIPE_FORMAT_ASTC_10x6:
1062 return PIPE_FORMAT_ASTC_10x6_SRGB;
1063 case PIPE_FORMAT_ASTC_10x8:
1064 return PIPE_FORMAT_ASTC_10x8_SRGB;
1065 case PIPE_FORMAT_ASTC_10x10:
1066 return PIPE_FORMAT_ASTC_10x10_SRGB;
1067 case PIPE_FORMAT_ASTC_12x10:
1068 return PIPE_FORMAT_ASTC_12x10_SRGB;
1069 case PIPE_FORMAT_ASTC_12x12:
1070 return PIPE_FORMAT_ASTC_12x12_SRGB;
1071 case PIPE_FORMAT_ASTC_3x3x3:
1072 return PIPE_FORMAT_ASTC_3x3x3_SRGB;
1073 case PIPE_FORMAT_ASTC_4x3x3:
1074 return PIPE_FORMAT_ASTC_4x3x3_SRGB;
1075 case PIPE_FORMAT_ASTC_4x4x3:
1076 return PIPE_FORMAT_ASTC_4x4x3_SRGB;
1077 case PIPE_FORMAT_ASTC_4x4x4:
1078 return PIPE_FORMAT_ASTC_4x4x4_SRGB;
1079 case PIPE_FORMAT_ASTC_5x4x4:
1080 return PIPE_FORMAT_ASTC_5x4x4_SRGB;
1081 case PIPE_FORMAT_ASTC_5x5x4:
1082 return PIPE_FORMAT_ASTC_5x5x4_SRGB;
1083 case PIPE_FORMAT_ASTC_5x5x5:
1084 return PIPE_FORMAT_ASTC_5x5x5_SRGB;
1085 case PIPE_FORMAT_ASTC_6x5x5:
1086 return PIPE_FORMAT_ASTC_6x5x5_SRGB;
1087 case PIPE_FORMAT_ASTC_6x6x5:
1088 return PIPE_FORMAT_ASTC_6x6x5_SRGB;
1089 case PIPE_FORMAT_ASTC_6x6x6:
1090 return PIPE_FORMAT_ASTC_6x6x6_SRGB;
1091
1092 default:
1093 return PIPE_FORMAT_NONE;
1094 }
1095 }
1096
1097 /**
1098 * Given an sRGB format, return the corresponding linear colorspace format.
1099 * For non sRGB formats, return the format unchanged.
1100 */
1101 static inline enum pipe_format
util_format_linear(enum pipe_format format)1102 util_format_linear(enum pipe_format format)
1103 {
1104 switch (format) {
1105 case PIPE_FORMAT_L8_SRGB:
1106 return PIPE_FORMAT_L8_UNORM;
1107 case PIPE_FORMAT_R8_SRGB:
1108 return PIPE_FORMAT_R8_UNORM;
1109 case PIPE_FORMAT_L8A8_SRGB:
1110 return PIPE_FORMAT_L8A8_UNORM;
1111 case PIPE_FORMAT_R8G8_SRGB:
1112 return PIPE_FORMAT_R8G8_UNORM;
1113 case PIPE_FORMAT_R8G8B8_SRGB:
1114 return PIPE_FORMAT_R8G8B8_UNORM;
1115 case PIPE_FORMAT_B8G8R8_SRGB:
1116 return PIPE_FORMAT_B8G8R8_UNORM;
1117 case PIPE_FORMAT_A8B8G8R8_SRGB:
1118 return PIPE_FORMAT_A8B8G8R8_UNORM;
1119 case PIPE_FORMAT_X8B8G8R8_SRGB:
1120 return PIPE_FORMAT_X8B8G8R8_UNORM;
1121 case PIPE_FORMAT_B8G8R8A8_SRGB:
1122 return PIPE_FORMAT_B8G8R8A8_UNORM;
1123 case PIPE_FORMAT_B8G8R8X8_SRGB:
1124 return PIPE_FORMAT_B8G8R8X8_UNORM;
1125 case PIPE_FORMAT_A8R8G8B8_SRGB:
1126 return PIPE_FORMAT_A8R8G8B8_UNORM;
1127 case PIPE_FORMAT_X8R8G8B8_SRGB:
1128 return PIPE_FORMAT_X8R8G8B8_UNORM;
1129 case PIPE_FORMAT_R8G8B8A8_SRGB:
1130 return PIPE_FORMAT_R8G8B8A8_UNORM;
1131 case PIPE_FORMAT_R8G8B8X8_SRGB:
1132 return PIPE_FORMAT_R8G8B8X8_UNORM;
1133 case PIPE_FORMAT_DXT1_SRGB:
1134 return PIPE_FORMAT_DXT1_RGB;
1135 case PIPE_FORMAT_DXT1_SRGBA:
1136 return PIPE_FORMAT_DXT1_RGBA;
1137 case PIPE_FORMAT_DXT3_SRGBA:
1138 return PIPE_FORMAT_DXT3_RGBA;
1139 case PIPE_FORMAT_DXT5_SRGBA:
1140 return PIPE_FORMAT_DXT5_RGBA;
1141 case PIPE_FORMAT_R5G6B5_SRGB:
1142 return PIPE_FORMAT_R5G6B5_UNORM;
1143 case PIPE_FORMAT_B5G6R5_SRGB:
1144 return PIPE_FORMAT_B5G6R5_UNORM;
1145 case PIPE_FORMAT_BPTC_SRGBA:
1146 return PIPE_FORMAT_BPTC_RGBA_UNORM;
1147 case PIPE_FORMAT_ETC2_SRGB8:
1148 return PIPE_FORMAT_ETC2_RGB8;
1149 case PIPE_FORMAT_ETC2_SRGB8A1:
1150 return PIPE_FORMAT_ETC2_RGB8A1;
1151 case PIPE_FORMAT_ETC2_SRGBA8:
1152 return PIPE_FORMAT_ETC2_RGBA8;
1153 case PIPE_FORMAT_ASTC_4x4_SRGB:
1154 return PIPE_FORMAT_ASTC_4x4;
1155 case PIPE_FORMAT_ASTC_5x4_SRGB:
1156 return PIPE_FORMAT_ASTC_5x4;
1157 case PIPE_FORMAT_ASTC_5x5_SRGB:
1158 return PIPE_FORMAT_ASTC_5x5;
1159 case PIPE_FORMAT_ASTC_6x5_SRGB:
1160 return PIPE_FORMAT_ASTC_6x5;
1161 case PIPE_FORMAT_ASTC_6x6_SRGB:
1162 return PIPE_FORMAT_ASTC_6x6;
1163 case PIPE_FORMAT_ASTC_8x5_SRGB:
1164 return PIPE_FORMAT_ASTC_8x5;
1165 case PIPE_FORMAT_ASTC_8x6_SRGB:
1166 return PIPE_FORMAT_ASTC_8x6;
1167 case PIPE_FORMAT_ASTC_8x8_SRGB:
1168 return PIPE_FORMAT_ASTC_8x8;
1169 case PIPE_FORMAT_ASTC_10x5_SRGB:
1170 return PIPE_FORMAT_ASTC_10x5;
1171 case PIPE_FORMAT_ASTC_10x6_SRGB:
1172 return PIPE_FORMAT_ASTC_10x6;
1173 case PIPE_FORMAT_ASTC_10x8_SRGB:
1174 return PIPE_FORMAT_ASTC_10x8;
1175 case PIPE_FORMAT_ASTC_10x10_SRGB:
1176 return PIPE_FORMAT_ASTC_10x10;
1177 case PIPE_FORMAT_ASTC_12x10_SRGB:
1178 return PIPE_FORMAT_ASTC_12x10;
1179 case PIPE_FORMAT_ASTC_12x12_SRGB:
1180 return PIPE_FORMAT_ASTC_12x12;
1181 case PIPE_FORMAT_ASTC_3x3x3_SRGB:
1182 return PIPE_FORMAT_ASTC_3x3x3;
1183 case PIPE_FORMAT_ASTC_4x3x3_SRGB:
1184 return PIPE_FORMAT_ASTC_4x3x3;
1185 case PIPE_FORMAT_ASTC_4x4x3_SRGB:
1186 return PIPE_FORMAT_ASTC_4x4x3;
1187 case PIPE_FORMAT_ASTC_4x4x4_SRGB:
1188 return PIPE_FORMAT_ASTC_4x4x4;
1189 case PIPE_FORMAT_ASTC_5x4x4_SRGB:
1190 return PIPE_FORMAT_ASTC_5x4x4;
1191 case PIPE_FORMAT_ASTC_5x5x4_SRGB:
1192 return PIPE_FORMAT_ASTC_5x5x4;
1193 case PIPE_FORMAT_ASTC_5x5x5_SRGB:
1194 return PIPE_FORMAT_ASTC_5x5x5;
1195 case PIPE_FORMAT_ASTC_6x5x5_SRGB:
1196 return PIPE_FORMAT_ASTC_6x5x5;
1197 case PIPE_FORMAT_ASTC_6x6x5_SRGB:
1198 return PIPE_FORMAT_ASTC_6x6x5;
1199 case PIPE_FORMAT_ASTC_6x6x6_SRGB:
1200 return PIPE_FORMAT_ASTC_6x6x6;
1201 default:
1202 assert(!util_format_is_srgb(format));
1203 return format;
1204 }
1205 }
1206
1207 /**
1208 * Given a depth-stencil format, return the corresponding stencil-only format.
1209 * For stencil-only formats, return the format unchanged.
1210 */
1211 static inline enum pipe_format
util_format_stencil_only(enum pipe_format format)1212 util_format_stencil_only(enum pipe_format format)
1213 {
1214 switch (format) {
1215 /* mask out the depth component */
1216 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
1217 return PIPE_FORMAT_X24S8_UINT;
1218 case PIPE_FORMAT_S8_UINT_Z24_UNORM:
1219 return PIPE_FORMAT_S8X24_UINT;
1220 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
1221 return PIPE_FORMAT_X32_S8X24_UINT;
1222
1223 /* stencil only formats */
1224 case PIPE_FORMAT_X24S8_UINT:
1225 case PIPE_FORMAT_S8X24_UINT:
1226 case PIPE_FORMAT_X32_S8X24_UINT:
1227 case PIPE_FORMAT_S8_UINT:
1228 return format;
1229
1230 default:
1231 assert(0);
1232 return PIPE_FORMAT_NONE;
1233 }
1234 }
1235
1236 /**
1237 * Converts PIPE_FORMAT_*I* to PIPE_FORMAT_*R*.
1238 * This is identity for non-intensity formats.
1239 */
1240 static inline enum pipe_format
util_format_intensity_to_red(enum pipe_format format)1241 util_format_intensity_to_red(enum pipe_format format)
1242 {
1243 switch (format) {
1244 case PIPE_FORMAT_I8_UNORM:
1245 return PIPE_FORMAT_R8_UNORM;
1246 case PIPE_FORMAT_I8_SNORM:
1247 return PIPE_FORMAT_R8_SNORM;
1248 case PIPE_FORMAT_I16_UNORM:
1249 return PIPE_FORMAT_R16_UNORM;
1250 case PIPE_FORMAT_I16_SNORM:
1251 return PIPE_FORMAT_R16_SNORM;
1252 case PIPE_FORMAT_I16_FLOAT:
1253 return PIPE_FORMAT_R16_FLOAT;
1254 case PIPE_FORMAT_I32_FLOAT:
1255 return PIPE_FORMAT_R32_FLOAT;
1256 case PIPE_FORMAT_I8_UINT:
1257 return PIPE_FORMAT_R8_UINT;
1258 case PIPE_FORMAT_I8_SINT:
1259 return PIPE_FORMAT_R8_SINT;
1260 case PIPE_FORMAT_I16_UINT:
1261 return PIPE_FORMAT_R16_UINT;
1262 case PIPE_FORMAT_I16_SINT:
1263 return PIPE_FORMAT_R16_SINT;
1264 case PIPE_FORMAT_I32_UINT:
1265 return PIPE_FORMAT_R32_UINT;
1266 case PIPE_FORMAT_I32_SINT:
1267 return PIPE_FORMAT_R32_SINT;
1268 default:
1269 assert(!util_format_is_intensity(format));
1270 return format;
1271 }
1272 }
1273
1274 /**
1275 * Converts PIPE_FORMAT_*L* to PIPE_FORMAT_*R*.
1276 * This is identity for non-luminance formats.
1277 */
1278 static inline enum pipe_format
util_format_luminance_to_red(enum pipe_format format)1279 util_format_luminance_to_red(enum pipe_format format)
1280 {
1281 switch (format) {
1282 case PIPE_FORMAT_L8_UNORM:
1283 return PIPE_FORMAT_R8_UNORM;
1284 case PIPE_FORMAT_L8_SNORM:
1285 return PIPE_FORMAT_R8_SNORM;
1286 case PIPE_FORMAT_L16_UNORM:
1287 return PIPE_FORMAT_R16_UNORM;
1288 case PIPE_FORMAT_L16_SNORM:
1289 return PIPE_FORMAT_R16_SNORM;
1290 case PIPE_FORMAT_L16_FLOAT:
1291 return PIPE_FORMAT_R16_FLOAT;
1292 case PIPE_FORMAT_L32_FLOAT:
1293 return PIPE_FORMAT_R32_FLOAT;
1294 case PIPE_FORMAT_L8_UINT:
1295 return PIPE_FORMAT_R8_UINT;
1296 case PIPE_FORMAT_L8_SINT:
1297 return PIPE_FORMAT_R8_SINT;
1298 case PIPE_FORMAT_L16_UINT:
1299 return PIPE_FORMAT_R16_UINT;
1300 case PIPE_FORMAT_L16_SINT:
1301 return PIPE_FORMAT_R16_SINT;
1302 case PIPE_FORMAT_L32_UINT:
1303 return PIPE_FORMAT_R32_UINT;
1304 case PIPE_FORMAT_L32_SINT:
1305 return PIPE_FORMAT_R32_SINT;
1306
1307 case PIPE_FORMAT_LATC1_UNORM:
1308 return PIPE_FORMAT_RGTC1_UNORM;
1309 case PIPE_FORMAT_LATC1_SNORM:
1310 return PIPE_FORMAT_RGTC1_SNORM;
1311
1312 case PIPE_FORMAT_L4A4_UNORM:
1313 return PIPE_FORMAT_R4A4_UNORM;
1314
1315 case PIPE_FORMAT_L8A8_UNORM:
1316 return PIPE_FORMAT_R8A8_UNORM;
1317 case PIPE_FORMAT_L8A8_SNORM:
1318 return PIPE_FORMAT_R8A8_SNORM;
1319 case PIPE_FORMAT_L16A16_UNORM:
1320 return PIPE_FORMAT_R16A16_UNORM;
1321 case PIPE_FORMAT_L16A16_SNORM:
1322 return PIPE_FORMAT_R16A16_SNORM;
1323 case PIPE_FORMAT_L16A16_FLOAT:
1324 return PIPE_FORMAT_R16A16_FLOAT;
1325 case PIPE_FORMAT_L32A32_FLOAT:
1326 return PIPE_FORMAT_R32A32_FLOAT;
1327 case PIPE_FORMAT_L8A8_UINT:
1328 return PIPE_FORMAT_R8A8_UINT;
1329 case PIPE_FORMAT_L8A8_SINT:
1330 return PIPE_FORMAT_R8A8_SINT;
1331 case PIPE_FORMAT_L16A16_UINT:
1332 return PIPE_FORMAT_R16A16_UINT;
1333 case PIPE_FORMAT_L16A16_SINT:
1334 return PIPE_FORMAT_R16A16_SINT;
1335 case PIPE_FORMAT_L32A32_UINT:
1336 return PIPE_FORMAT_R32A32_UINT;
1337 case PIPE_FORMAT_L32A32_SINT:
1338 return PIPE_FORMAT_R32A32_SINT;
1339
1340 /* We don't have compressed red-alpha variants for these. */
1341 case PIPE_FORMAT_LATC2_UNORM:
1342 case PIPE_FORMAT_LATC2_SNORM:
1343 return PIPE_FORMAT_NONE;
1344
1345 default:
1346 assert(!util_format_is_luminance(format) &&
1347 !util_format_is_luminance_alpha(format));
1348 return format;
1349 }
1350 }
1351
1352 static inline unsigned
util_format_get_num_planes(enum pipe_format format)1353 util_format_get_num_planes(enum pipe_format format)
1354 {
1355 switch (util_format_description(format)->layout) {
1356 case UTIL_FORMAT_LAYOUT_PLANAR3:
1357 return 3;
1358 case UTIL_FORMAT_LAYOUT_PLANAR2:
1359 return 2;
1360 default:
1361 return 1;
1362 }
1363 }
1364
1365 static inline enum pipe_format
util_format_get_plane_format(enum pipe_format format,unsigned plane)1366 util_format_get_plane_format(enum pipe_format format, unsigned plane)
1367 {
1368 switch (format) {
1369 case PIPE_FORMAT_YV12:
1370 case PIPE_FORMAT_YV16:
1371 case PIPE_FORMAT_IYUV:
1372 case PIPE_FORMAT_Y8_U8_V8_422_UNORM:
1373 case PIPE_FORMAT_Y8_U8_V8_444_UNORM:
1374 return PIPE_FORMAT_R8_UNORM;
1375 case PIPE_FORMAT_NV12:
1376 case PIPE_FORMAT_Y8_U8V8_422_UNORM:
1377 return !plane ? PIPE_FORMAT_R8_UNORM : PIPE_FORMAT_RG88_UNORM;
1378 case PIPE_FORMAT_NV21:
1379 return !plane ? PIPE_FORMAT_R8_UNORM : PIPE_FORMAT_GR88_UNORM;
1380 case PIPE_FORMAT_Y16_U16_V16_420_UNORM:
1381 case PIPE_FORMAT_Y16_U16_V16_422_UNORM:
1382 case PIPE_FORMAT_Y16_U16_V16_444_UNORM:
1383 return PIPE_FORMAT_R16_UNORM;
1384 case PIPE_FORMAT_P010:
1385 case PIPE_FORMAT_P012:
1386 case PIPE_FORMAT_P016:
1387 case PIPE_FORMAT_Y16_U16V16_422_UNORM:
1388 return !plane ? PIPE_FORMAT_R16_UNORM : PIPE_FORMAT_R16G16_UNORM;
1389 default:
1390 return format;
1391 }
1392 }
1393
1394 static inline unsigned
util_format_get_plane_width(enum pipe_format format,unsigned plane,unsigned width)1395 util_format_get_plane_width(enum pipe_format format, unsigned plane,
1396 unsigned width)
1397 {
1398 switch (format) {
1399 case PIPE_FORMAT_YV12:
1400 case PIPE_FORMAT_YV16:
1401 case PIPE_FORMAT_IYUV:
1402 case PIPE_FORMAT_NV12:
1403 case PIPE_FORMAT_NV21:
1404 case PIPE_FORMAT_P010:
1405 case PIPE_FORMAT_P012:
1406 case PIPE_FORMAT_P016:
1407 case PIPE_FORMAT_Y8_U8_V8_422_UNORM:
1408 case PIPE_FORMAT_Y8_U8V8_422_UNORM:
1409 case PIPE_FORMAT_Y16_U16_V16_420_UNORM:
1410 case PIPE_FORMAT_Y16_U16_V16_422_UNORM:
1411 case PIPE_FORMAT_Y16_U16V16_422_UNORM:
1412 return !plane ? width : (width + 1) / 2;
1413 default:
1414 return width;
1415 }
1416 }
1417
1418 static inline unsigned
util_format_get_plane_height(enum pipe_format format,unsigned plane,unsigned height)1419 util_format_get_plane_height(enum pipe_format format, unsigned plane,
1420 unsigned height)
1421 {
1422 switch (format) {
1423 case PIPE_FORMAT_YV12:
1424 case PIPE_FORMAT_IYUV:
1425 case PIPE_FORMAT_NV12:
1426 case PIPE_FORMAT_NV21:
1427 case PIPE_FORMAT_P010:
1428 case PIPE_FORMAT_P012:
1429 case PIPE_FORMAT_P016:
1430 case PIPE_FORMAT_Y16_U16_V16_420_UNORM:
1431 return !plane ? height : (height + 1) / 2;
1432 case PIPE_FORMAT_YV16:
1433 default:
1434 return height;
1435 }
1436 }
1437
1438 /**
1439 * Return the number of components stored.
1440 * Formats with block size != 1x1 will always have 1 component (the block).
1441 */
1442 static inline unsigned
util_format_get_nr_components(enum pipe_format format)1443 util_format_get_nr_components(enum pipe_format format)
1444 {
1445 const struct util_format_description *desc = util_format_description(format);
1446 return desc->nr_channels;
1447 }
1448
1449 /**
1450 * Return the index of the first non-void channel
1451 * -1 if no non-void channels
1452 */
1453 static inline int
util_format_get_first_non_void_channel(enum pipe_format format)1454 util_format_get_first_non_void_channel(enum pipe_format format)
1455 {
1456 const struct util_format_description *desc = util_format_description(format);
1457 int i;
1458
1459 for (i = 0; i < 4; i++)
1460 if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
1461 break;
1462
1463 if (i == 4)
1464 return -1;
1465
1466 return i;
1467 }
1468
1469 /**
1470 * Whether this format is any 8-bit UNORM variant. Looser than
1471 * util_is_rgba8_variant (also includes alpha textures, for instance).
1472 */
1473
1474 static inline bool
util_format_is_unorm8(const struct util_format_description * desc)1475 util_format_is_unorm8(const struct util_format_description *desc)
1476 {
1477 int c = util_format_get_first_non_void_channel(desc->format);
1478
1479 if (c == -1)
1480 return false;
1481
1482 return desc->is_unorm && desc->is_array && desc->channel[c].size == 8;
1483 }
1484
1485 static inline void
util_format_unpack_z_float(enum pipe_format format,float * dst,const void * src,unsigned w)1486 util_format_unpack_z_float(enum pipe_format format, float *dst,
1487 const void *src, unsigned w)
1488 {
1489 const struct util_format_unpack_description *desc =
1490 util_format_unpack_description(format);
1491
1492 desc->unpack_z_float(dst, 0, (const uint8_t *)src, 0, w, 1);
1493 }
1494
1495 static inline void
util_format_unpack_z_32unorm(enum pipe_format format,uint32_t * dst,const void * src,unsigned w)1496 util_format_unpack_z_32unorm(enum pipe_format format, uint32_t *dst,
1497 const void *src, unsigned w)
1498 {
1499 const struct util_format_unpack_description *desc =
1500 util_format_unpack_description(format);
1501
1502 desc->unpack_z_32unorm(dst, 0, (const uint8_t *)src, 0, w, 1);
1503 }
1504
1505 static inline void
util_format_unpack_s_8uint(enum pipe_format format,uint8_t * dst,const void * src,unsigned w)1506 util_format_unpack_s_8uint(enum pipe_format format, uint8_t *dst,
1507 const void *src, unsigned w)
1508 {
1509 const struct util_format_unpack_description *desc =
1510 util_format_unpack_description(format);
1511
1512 desc->unpack_s_8uint(dst, 0, (const uint8_t *)src, 0, w, 1);
1513 }
1514
1515 /**
1516 * Unpacks a row of color data to 32-bit RGBA, either integers for pure
1517 * integer formats (sign-extended for signed data), or 32-bit floats.
1518 */
1519 static inline void
util_format_unpack_rgba(enum pipe_format format,void * dst,const void * src,unsigned w)1520 util_format_unpack_rgba(enum pipe_format format, void *dst,
1521 const void *src, unsigned w)
1522 {
1523 const struct util_format_unpack_description *desc =
1524 util_format_unpack_description(format);
1525
1526 desc->unpack_rgba(dst, (const uint8_t *)src, w);
1527 }
1528
1529 static inline void
util_format_pack_z_float(enum pipe_format format,void * dst,const float * src,unsigned w)1530 util_format_pack_z_float(enum pipe_format format, void *dst,
1531 const float *src, unsigned w)
1532 {
1533 const struct util_format_pack_description *desc =
1534 util_format_pack_description(format);
1535
1536 desc->pack_z_float((uint8_t *)dst, 0, src, 0, w, 1);
1537 }
1538
1539 static inline void
util_format_pack_z_32unorm(enum pipe_format format,void * dst,const uint32_t * src,unsigned w)1540 util_format_pack_z_32unorm(enum pipe_format format, void *dst,
1541 const uint32_t *src, unsigned w)
1542 {
1543 const struct util_format_pack_description *desc =
1544 util_format_pack_description(format);
1545
1546 desc->pack_z_32unorm((uint8_t *)dst, 0, src, 0, w, 1);
1547 }
1548
1549 static inline void
util_format_pack_s_8uint(enum pipe_format format,void * dst,const uint8_t * src,unsigned w)1550 util_format_pack_s_8uint(enum pipe_format format, void *dst,
1551 const uint8_t *src, unsigned w)
1552 {
1553 const struct util_format_pack_description *desc =
1554 util_format_pack_description(format);
1555
1556 desc->pack_s_8uint((uint8_t *)dst, 0, src, 0, w, 1);
1557 }
1558
1559 /**
1560 * Packs a row of color data from 32-bit RGBA, either integers for pure
1561 * integer formats, or 32-bit floats. Values are clamped to the packed
1562 * representation's range.
1563 */
1564 static inline void
util_format_pack_rgba(enum pipe_format format,void * dst,const void * src,unsigned w)1565 util_format_pack_rgba(enum pipe_format format, void *dst,
1566 const void *src, unsigned w)
1567 {
1568 const struct util_format_pack_description *desc =
1569 util_format_pack_description(format);
1570
1571 if (util_format_is_pure_uint(format))
1572 desc->pack_rgba_uint((uint8_t *)dst, 0, (const uint32_t *)src, 0, w, 1);
1573 else if (util_format_is_pure_sint(format))
1574 desc->pack_rgba_sint((uint8_t *)dst, 0, (const int32_t *)src, 0, w, 1);
1575 else
1576 desc->pack_rgba_float((uint8_t *)dst, 0, (const float *)src, 0, w, 1);
1577 }
1578
1579 /*
1580 * Format access functions for subrectangles
1581 */
1582
1583 void
1584 util_format_read_4(enum pipe_format format,
1585 void *dst, unsigned dst_stride,
1586 const void *src, unsigned src_stride,
1587 unsigned x, unsigned y, unsigned w, unsigned h);
1588
1589 void
1590 util_format_write_4(enum pipe_format format,
1591 const void *src, unsigned src_stride,
1592 void *dst, unsigned dst_stride,
1593 unsigned x, unsigned y, unsigned w, unsigned h);
1594
1595 void
1596 util_format_read_4ub(enum pipe_format format,
1597 uint8_t *dst, unsigned dst_stride,
1598 const void *src, unsigned src_stride,
1599 unsigned x, unsigned y, unsigned w, unsigned h);
1600
1601 void
1602 util_format_write_4ub(enum pipe_format format,
1603 const uint8_t *src, unsigned src_stride,
1604 void *dst, unsigned dst_stride,
1605 unsigned x, unsigned y, unsigned w, unsigned h);
1606
1607 void
1608 util_format_unpack_rgba_rect(enum pipe_format format,
1609 void *dst, unsigned dst_stride,
1610 const void *src, unsigned src_stride,
1611 unsigned w, unsigned h);
1612
1613 void
1614 util_format_unpack_rgba_8unorm_rect(enum pipe_format format,
1615 void *dst, unsigned dst_stride,
1616 const void *src, unsigned src_stride,
1617 unsigned w, unsigned h);
1618
1619 /*
1620 * Generic format conversion;
1621 */
1622
1623 boolean
1624 util_format_fits_8unorm(const struct util_format_description *format_desc) ATTRIBUTE_CONST;
1625
1626 boolean
1627 util_format_translate(enum pipe_format dst_format,
1628 void *dst, unsigned dst_stride,
1629 unsigned dst_x, unsigned dst_y,
1630 enum pipe_format src_format,
1631 const void *src, unsigned src_stride,
1632 unsigned src_x, unsigned src_y,
1633 unsigned width, unsigned height);
1634
1635 boolean
1636 util_format_translate_3d(enum pipe_format dst_format,
1637 void *dst, unsigned dst_stride,
1638 unsigned dst_slice_stride,
1639 unsigned dst_x, unsigned dst_y,
1640 unsigned dst_z,
1641 enum pipe_format src_format,
1642 const void *src, unsigned src_stride,
1643 unsigned src_slice_stride,
1644 unsigned src_x, unsigned src_y,
1645 unsigned src_z, unsigned width,
1646 unsigned height, unsigned depth);
1647
1648 /*
1649 * Swizzle operations.
1650 */
1651
1652 /* Compose two sets of swizzles.
1653 * If V is a 4D vector and the function parameters represent functions that
1654 * swizzle vector components, this holds:
1655 * swz2(swz1(V)) = dst(V)
1656 */
1657 void util_format_compose_swizzles(const unsigned char swz1[4],
1658 const unsigned char swz2[4],
1659 unsigned char dst[4]);
1660
1661 /* Apply the swizzle provided in \param swz (which is one of PIPE_SWIZZLE_x)
1662 * to \param src and store the result in \param dst.
1663 * \param is_integer determines the value written for PIPE_SWIZZLE_1.
1664 */
1665 void util_format_apply_color_swizzle(union pipe_color_union *dst,
1666 const union pipe_color_union *src,
1667 const unsigned char swz[4],
1668 const boolean is_integer);
1669
1670 void pipe_swizzle_4f(float *dst, const float *src,
1671 const unsigned char swz[4]);
1672
1673 void util_format_unswizzle_4f(float *dst, const float *src,
1674 const unsigned char swz[4]);
1675
1676 enum pipe_format
1677 util_format_snorm_to_sint(enum pipe_format format) ATTRIBUTE_CONST;
1678
1679 extern void
1680 util_copy_rect(ubyte * dst, enum pipe_format format,
1681 unsigned dst_stride, unsigned dst_x, unsigned dst_y,
1682 unsigned width, unsigned height, const ubyte * src,
1683 int src_stride, unsigned src_x, unsigned src_y);
1684
1685 /**
1686 * If the format is RGB, return BGR. If the format is BGR, return RGB.
1687 * This may fail by returning PIPE_FORMAT_NONE.
1688 */
1689 enum pipe_format
1690 util_format_rgb_to_bgr(enum pipe_format format);
1691
1692 /* Returns the pipe format with SNORM formats cast to UNORM, otherwise the original pipe format. */
1693 enum pipe_format
1694 util_format_snorm_to_unorm(enum pipe_format format);
1695
1696 enum pipe_format
1697 util_format_rgbx_to_rgba(enum pipe_format format);
1698
1699 #ifdef __cplusplus
1700 } // extern "C" {
1701 #endif
1702
1703 #endif /* ! U_FORMAT_H */
1704