1 /**************************************************************************
2 *
3 * Copyright 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 * @file
30 * Pixel format accessor functions.
31 *
32 * @author Jose Fonseca <jfonseca@vmware.com>
33 */
34
35 #include "c11/threads.h"
36 #include "util/detect_arch.h"
37 #include "util/format/u_format.h"
38 #include "util/format/u_format_s3tc.h"
39 #include "util/u_math.h"
40
41 /**
42 * Copy 2D rect from one place to another.
43 * Position and sizes are in pixels.
44 * src_stride may be negative to do vertical flip of pixels from source.
45 */
46 void
util_copy_rect(void * dst_in,enum pipe_format format,unsigned dst_stride,unsigned dst_x,unsigned dst_y,unsigned width,unsigned height,const void * src_in,int src_stride,unsigned src_x,unsigned src_y)47 util_copy_rect(void * dst_in,
48 enum pipe_format format,
49 unsigned dst_stride,
50 unsigned dst_x,
51 unsigned dst_y,
52 unsigned width,
53 unsigned height,
54 const void * src_in,
55 int src_stride,
56 unsigned src_x,
57 unsigned src_y)
58 {
59 uint8_t *dst = dst_in;
60 const uint8_t *src = src_in;
61 unsigned i;
62 int src_stride_pos = src_stride < 0 ? -src_stride : src_stride;
63 int blocksize = util_format_get_blocksize(format);
64 int blockwidth = util_format_get_blockwidth(format);
65 int blockheight = util_format_get_blockheight(format);
66
67 assert(blocksize > 0);
68 assert(blockwidth > 0);
69 assert(blockheight > 0);
70
71 dst_x /= blockwidth;
72 dst_y /= blockheight;
73 width = (width + blockwidth - 1)/blockwidth;
74 height = (height + blockheight - 1)/blockheight;
75 src_x /= blockwidth;
76 src_y /= blockheight;
77
78 dst += dst_x * blocksize;
79 src += src_x * blocksize;
80 dst += dst_y * dst_stride;
81 src += src_y * src_stride_pos;
82 width *= blocksize;
83
84 if (width == dst_stride && width == (unsigned)src_stride) {
85 uint64_t size = (uint64_t)height * width;
86
87 assert(size <= SIZE_MAX);
88 memcpy(dst, src, size);
89 } else {
90 for (i = 0; i < height; i++) {
91 memcpy(dst, src, width);
92 dst += dst_stride;
93 src += src_stride;
94 }
95 }
96 }
97
98
99 bool
util_format_is_float(enum pipe_format format)100 util_format_is_float(enum pipe_format format)
101 {
102 const struct util_format_description *desc = util_format_description(format);
103 int i;
104
105 i = util_format_get_first_non_void_channel(format);
106 if (i < 0) {
107 return false;
108 }
109
110 return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? true : false;
111 }
112
113
114 /** Test if the format contains RGB, but not alpha */
115 bool
util_format_has_alpha(enum pipe_format format)116 util_format_has_alpha(enum pipe_format format)
117 {
118 const struct util_format_description *desc =
119 util_format_description(format);
120
121 return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
122 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
123 desc->swizzle[3] != PIPE_SWIZZLE_1;
124 }
125
126 /** Test if format has alpha as 1 (like RGBX) */
127 bool
util_format_has_alpha1(enum pipe_format format)128 util_format_has_alpha1(enum pipe_format format)
129 {
130 const struct util_format_description *desc =
131 util_format_description(format);
132
133 return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
134 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
135 desc->nr_channels == 4 &&
136 desc->swizzle[3] == PIPE_SWIZZLE_1;
137 }
138
139 bool
util_format_is_luminance(enum pipe_format format)140 util_format_is_luminance(enum pipe_format format)
141 {
142 const struct util_format_description *desc =
143 util_format_description(format);
144
145 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
146 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
147 desc->swizzle[0] == PIPE_SWIZZLE_X &&
148 desc->swizzle[1] == PIPE_SWIZZLE_X &&
149 desc->swizzle[2] == PIPE_SWIZZLE_X &&
150 desc->swizzle[3] == PIPE_SWIZZLE_1) {
151 return true;
152 }
153 return false;
154 }
155
156 bool
util_format_is_alpha(enum pipe_format format)157 util_format_is_alpha(enum pipe_format format)
158 {
159 const struct util_format_description *desc =
160 util_format_description(format);
161
162 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
163 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
164 desc->swizzle[0] == PIPE_SWIZZLE_0 &&
165 desc->swizzle[1] == PIPE_SWIZZLE_0 &&
166 desc->swizzle[2] == PIPE_SWIZZLE_0 &&
167 desc->swizzle[3] == PIPE_SWIZZLE_X) {
168 return true;
169 }
170 return false;
171 }
172
173 bool
util_format_is_pure_integer(enum pipe_format format)174 util_format_is_pure_integer(enum pipe_format format)
175 {
176 const struct util_format_description *desc = util_format_description(format);
177 int i;
178
179 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
180 if (util_format_has_depth(desc))
181 return false;
182
183 assert(util_format_has_stencil(desc));
184 return true;
185 }
186
187 /* Find the first non-void channel. */
188 i = util_format_get_first_non_void_channel(format);
189 if (i == -1)
190 return false;
191
192 return desc->channel[i].pure_integer ? true : false;
193 }
194
195 bool
util_format_is_pure_sint(enum pipe_format format)196 util_format_is_pure_sint(enum pipe_format format)
197 {
198 const struct util_format_description *desc = util_format_description(format);
199 int i;
200
201 i = util_format_get_first_non_void_channel(format);
202 if (i == -1)
203 return false;
204
205 return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? true : false;
206 }
207
208 bool
util_format_is_pure_uint(enum pipe_format format)209 util_format_is_pure_uint(enum pipe_format format)
210 {
211 const struct util_format_description *desc = util_format_description(format);
212 int i;
213
214 i = util_format_get_first_non_void_channel(format);
215 if (i == -1)
216 return false;
217
218 return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? true : false;
219 }
220
221 /**
222 * Returns true if the format contains normalized signed channels.
223 */
224 bool
util_format_is_snorm(enum pipe_format format)225 util_format_is_snorm(enum pipe_format format)
226 {
227 const struct util_format_description *desc = util_format_description(format);
228
229 return desc->is_snorm;
230 }
231
232 /**
233 * Returns true if the format contains normalized unsigned channels.
234 */
235 bool
util_format_is_unorm(enum pipe_format format)236 util_format_is_unorm(enum pipe_format format)
237 {
238 const struct util_format_description *desc = util_format_description(format);
239
240 return desc->is_unorm;
241 }
242
243 /**
244 * Returns true if the format contains scaled integer format channels.
245 */
246 bool
util_format_is_scaled(enum pipe_format format)247 util_format_is_scaled(enum pipe_format format)
248 {
249 const struct util_format_description *desc = util_format_description(format);
250 int i;
251
252 /* format none is described as scaled but not for this check */
253 if (format == PIPE_FORMAT_NONE)
254 return false;
255
256 /* Find the first non-void channel. */
257 i = util_format_get_first_non_void_channel(format);
258 if (i == -1)
259 return false;
260
261 return !desc->channel[i].pure_integer && !desc->channel[i].normalized &&
262 (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED ||
263 desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
264 }
265
266 bool
util_format_is_snorm8(enum pipe_format format)267 util_format_is_snorm8(enum pipe_format format)
268 {
269 const struct util_format_description *desc = util_format_description(format);
270 int i;
271
272 if (desc->is_mixed)
273 return false;
274
275 i = util_format_get_first_non_void_channel(format);
276 if (i == -1)
277 return false;
278
279 return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
280 !desc->channel[i].pure_integer &&
281 desc->channel[i].normalized &&
282 desc->channel[i].size == 8;
283 }
284
285 bool
util_format_is_luminance_alpha(enum pipe_format format)286 util_format_is_luminance_alpha(enum pipe_format format)
287 {
288 const struct util_format_description *desc =
289 util_format_description(format);
290
291 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
292 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
293 desc->swizzle[0] == PIPE_SWIZZLE_X &&
294 desc->swizzle[1] == PIPE_SWIZZLE_X &&
295 desc->swizzle[2] == PIPE_SWIZZLE_X &&
296 desc->swizzle[3] == PIPE_SWIZZLE_Y) {
297 return true;
298 }
299 return false;
300 }
301
302
303 bool
util_format_is_intensity(enum pipe_format format)304 util_format_is_intensity(enum pipe_format format)
305 {
306 const struct util_format_description *desc =
307 util_format_description(format);
308
309 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
310 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
311 desc->swizzle[0] == PIPE_SWIZZLE_X &&
312 desc->swizzle[1] == PIPE_SWIZZLE_X &&
313 desc->swizzle[2] == PIPE_SWIZZLE_X &&
314 desc->swizzle[3] == PIPE_SWIZZLE_X) {
315 return true;
316 }
317 return false;
318 }
319
320 bool
util_format_is_subsampled_422(enum pipe_format format)321 util_format_is_subsampled_422(enum pipe_format format)
322 {
323 const struct util_format_description *desc =
324 util_format_description(format);
325
326 return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED &&
327 desc->block.width == 2 &&
328 desc->block.height == 1 &&
329 desc->block.bits == 32;
330 }
331
332 /**
333 * Calculates the MRD for the depth format. MRD is used in depth bias
334 * for UNORM and unbound depth buffers. When the depth buffer is floating
335 * point, the depth bias calculation does not use the MRD. However, the
336 * default MRD will be 1.0 / ((1 << 24) - 1).
337 */
338 double
util_get_depth_format_mrd(const struct util_format_description * desc)339 util_get_depth_format_mrd(const struct util_format_description *desc)
340 {
341 /*
342 * Depth buffer formats without a depth component OR scenarios
343 * without a bound depth buffer default to D24.
344 */
345 double mrd = 1.0 / ((1 << 24) - 1);
346 unsigned depth_channel;
347
348 /*
349 * Some depth formats do not store the depth component in the first
350 * channel, detect the format and adjust the depth channel. Get the
351 * swizzled depth component channel.
352 */
353 depth_channel = desc->swizzle[0];
354
355 if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
356 desc->channel[depth_channel].normalized) {
357 int depth_bits;
358
359 depth_bits = desc->channel[depth_channel].size;
360 mrd = 1.0 / ((1ULL << depth_bits) - 1);
361 }
362
363 return mrd;
364 }
365
366 void
util_format_unpack_rgba_rect(enum pipe_format format,void * dst,unsigned dst_stride,const void * src,unsigned src_stride,unsigned w,unsigned h)367 util_format_unpack_rgba_rect(enum pipe_format format,
368 void *dst, unsigned dst_stride,
369 const void *src, unsigned src_stride,
370 unsigned w, unsigned h)
371 {
372 const struct util_format_unpack_description *unpack =
373 util_format_unpack_description(format);
374
375 /* Optimized function for block-compressed formats */
376 if (unpack->unpack_rgba_rect) {
377 unpack->unpack_rgba_rect(dst, dst_stride, src, src_stride, w, h);
378 } else {
379 for (unsigned y = 0; y < h; y++) {
380 unpack->unpack_rgba(dst, src, w);
381 src = (const char *)src + src_stride;
382 dst = (char *)dst + dst_stride;
383 }
384 }
385 }
386
387 void
util_format_unpack_rgba_8unorm_rect(enum pipe_format format,void * dst,unsigned dst_stride,const void * src,unsigned src_stride,unsigned w,unsigned h)388 util_format_unpack_rgba_8unorm_rect(enum pipe_format format,
389 void *dst, unsigned dst_stride,
390 const void *src, unsigned src_stride,
391 unsigned w, unsigned h)
392 {
393 const struct util_format_unpack_description *unpack =
394 util_format_unpack_description(format);
395
396 /* Optimized function for block-compressed formats */
397 if (unpack->unpack_rgba_8unorm_rect) {
398 unpack->unpack_rgba_8unorm_rect(dst, dst_stride, src, src_stride, w, h);
399 } else {
400 for (unsigned y = 0; y < h; y++) {
401 unpack->unpack_rgba_8unorm(dst, src, w);
402 src = (const char *)src + src_stride;
403 dst = (char *)dst + dst_stride;
404 }
405 }
406 }
407
408 void
util_format_read_4(enum pipe_format format,void * dst,unsigned dst_stride,const void * src,unsigned src_stride,unsigned x,unsigned y,unsigned w,unsigned h)409 util_format_read_4(enum pipe_format format,
410 void *dst, unsigned dst_stride,
411 const void *src, unsigned src_stride,
412 unsigned x, unsigned y, unsigned w, unsigned h)
413 {
414 const struct util_format_description *format_desc;
415 const uint8_t *src_row;
416
417 format_desc = util_format_description(format);
418
419 assert(x % format_desc->block.width == 0);
420 assert(y % format_desc->block.height == 0);
421
422 src_row = (const uint8_t *)src + (uint64_t)y*src_stride + x*(format_desc->block.bits/8);
423
424 util_format_unpack_rgba_rect(format, dst, dst_stride, src_row, src_stride, w, h);
425 }
426
427
428 void
util_format_write_4(enum pipe_format format,const void * src,unsigned src_stride,void * dst,unsigned dst_stride,unsigned x,unsigned y,unsigned w,unsigned h)429 util_format_write_4(enum pipe_format format,
430 const void *src, unsigned src_stride,
431 void *dst, unsigned dst_stride,
432 unsigned x, unsigned y, unsigned w, unsigned h)
433 {
434 const struct util_format_description *format_desc;
435 const struct util_format_pack_description *pack =
436 util_format_pack_description(format);
437 uint8_t *dst_row;
438
439 format_desc = util_format_description(format);
440
441 assert(x % format_desc->block.width == 0);
442 assert(y % format_desc->block.height == 0);
443
444 dst_row = (uint8_t *)dst + (uint64_t)y*dst_stride + x*(format_desc->block.bits/8);
445
446 if (util_format_is_pure_uint(format))
447 pack->pack_rgba_uint(dst_row, dst_stride, src, src_stride, w, h);
448 else if (util_format_is_pure_sint(format))
449 pack->pack_rgba_sint(dst_row, dst_stride, src, src_stride, w, h);
450 else
451 pack->pack_rgba_float(dst_row, dst_stride, src, src_stride, w, h);
452 }
453
454
455 void
util_format_read_4ub(enum pipe_format format,uint8_t * dst,unsigned dst_stride,const void * src,unsigned src_stride,unsigned x,unsigned y,unsigned w,unsigned h)456 util_format_read_4ub(enum pipe_format format, uint8_t *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)
457 {
458 const struct util_format_description *format_desc;
459 const uint8_t *src_row;
460
461 format_desc = util_format_description(format);
462
463 assert(x % format_desc->block.width == 0);
464 assert(y % format_desc->block.height == 0);
465
466 src_row = (const uint8_t *)src + (uint64_t)y*src_stride + x*(format_desc->block.bits/8);
467
468 util_format_unpack_rgba_8unorm_rect(format, dst, dst_stride, src_row, src_stride, w, h);
469 }
470
471
472 void
util_format_write_4ub(enum pipe_format format,const uint8_t * src,unsigned src_stride,void * dst,unsigned dst_stride,unsigned x,unsigned y,unsigned w,unsigned h)473 util_format_write_4ub(enum pipe_format format, const uint8_t *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)
474 {
475 const struct util_format_description *format_desc;
476 const struct util_format_pack_description *pack =
477 util_format_pack_description(format);
478 uint8_t *dst_row;
479 const uint8_t *src_row;
480
481 format_desc = util_format_description(format);
482
483 assert(x % format_desc->block.width == 0);
484 assert(y % format_desc->block.height == 0);
485
486 dst_row = (uint8_t *)dst + (uint64_t)y*dst_stride + x*(format_desc->block.bits/8);
487 src_row = src;
488
489 pack->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
490 }
491
492 /**
493 * Check if we can safely memcopy from the source format to the dest format.
494 * This basically covers the cases of a "used" channel copied to a typeless
495 * channel, plus some 1-channel cases.
496 * Examples of compatible copy formats include:
497 * b8g8r8a8_unorm -> b8g8r8x8_unorm
498 * a8r8g8b8_unorm -> x8r8g8b8_unorm
499 * b5g5r5a1_unorm -> b5g5r5x1_unorm
500 * b4g4r4a4_unorm -> b4g4r4x4_unorm
501 * l8_unorm -> r8_unorm
502 * i8_unorm -> l8_unorm
503 * i8_unorm -> a8_unorm
504 * i8_unorm -> r8_unorm
505 * l16_unorm -> r16_unorm
506 * z24_unorm_s8_uint -> z24x8_unorm
507 * s8_uint_z24_unorm -> x8z24_unorm
508 * r8g8b8a8_unorm -> r8g8b8x8_unorm
509 * a8b8g8r8_srgb -> x8b8g8r8_srgb
510 * b8g8r8a8_srgb -> b8g8r8x8_srgb
511 * a8r8g8b8_srgb -> x8r8g8b8_srgb
512 * a8b8g8r8_unorm -> x8b8g8r8_unorm
513 * r10g10b10a2_uscaled -> r10g10b10x2_uscaled
514 * r10sg10sb10sa2u_norm -> r10g10b10x2_snorm
515 */
516 bool
util_is_format_compatible(const struct util_format_description * src_desc,const struct util_format_description * dst_desc)517 util_is_format_compatible(const struct util_format_description *src_desc,
518 const struct util_format_description *dst_desc)
519 {
520 unsigned chan;
521
522 if (src_desc->format == dst_desc->format) {
523 return true;
524 }
525
526 if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
527 dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
528 return false;
529 }
530
531 if (src_desc->block.bits != dst_desc->block.bits ||
532 src_desc->nr_channels != dst_desc->nr_channels ||
533 src_desc->colorspace != dst_desc->colorspace) {
534 return false;
535 }
536
537 for (chan = 0; chan < 4; ++chan) {
538 if (src_desc->channel[chan].size !=
539 dst_desc->channel[chan].size) {
540 return false;
541 }
542 }
543
544 for (chan = 0; chan < 4; ++chan) {
545 enum pipe_swizzle swizzle = dst_desc->swizzle[chan];
546
547 if (swizzle < 4) {
548 if (src_desc->swizzle[chan] != swizzle) {
549 return false;
550 }
551 if ((src_desc->channel[swizzle].type !=
552 dst_desc->channel[swizzle].type) ||
553 (src_desc->channel[swizzle].normalized !=
554 dst_desc->channel[swizzle].normalized)) {
555 return false;
556 }
557 }
558 }
559
560 return true;
561 }
562
563
564 bool
util_format_fits_8unorm(const struct util_format_description * format_desc)565 util_format_fits_8unorm(const struct util_format_description *format_desc)
566 {
567 unsigned chan;
568
569 /*
570 * After linearized sRGB values require more than 8bits.
571 */
572
573 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
574 return false;
575 }
576
577 switch (format_desc->layout) {
578
579 case UTIL_FORMAT_LAYOUT_S3TC:
580 /*
581 * These are straight forward.
582 */
583 return true;
584 case UTIL_FORMAT_LAYOUT_RGTC:
585 if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
586 format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
587 format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
588 format_desc->format == PIPE_FORMAT_LATC2_SNORM)
589 return false;
590 return true;
591 case UTIL_FORMAT_LAYOUT_BPTC:
592 if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM)
593 return true;
594 return false;
595
596 case UTIL_FORMAT_LAYOUT_ETC:
597 if (format_desc->format == PIPE_FORMAT_ETC1_RGB8)
598 return true;
599 return false;
600
601 case UTIL_FORMAT_LAYOUT_PLAIN:
602 /*
603 * For these we can find a generic rule.
604 */
605
606 for (chan = 0; chan < format_desc->nr_channels; ++chan) {
607 switch (format_desc->channel[chan].type) {
608 case UTIL_FORMAT_TYPE_VOID:
609 break;
610 case UTIL_FORMAT_TYPE_UNSIGNED:
611 if (!format_desc->channel[chan].normalized ||
612 format_desc->channel[chan].size > 8) {
613 return false;
614 }
615 break;
616 default:
617 return false;
618 }
619 }
620 return true;
621
622 default:
623 /*
624 * Handle all others on a case by case basis.
625 */
626
627 switch (format_desc->format) {
628 case PIPE_FORMAT_R1_UNORM:
629 case PIPE_FORMAT_UYVY:
630 case PIPE_FORMAT_VYUY:
631 case PIPE_FORMAT_YUYV:
632 case PIPE_FORMAT_YVYU:
633 case PIPE_FORMAT_R8G8_B8G8_UNORM:
634 case PIPE_FORMAT_G8R8_G8B8_UNORM:
635 return true;
636
637 default:
638 return false;
639 }
640 }
641 }
642
643
644 bool
util_format_translate(enum pipe_format dst_format,void * dst,unsigned dst_stride,unsigned dst_x,unsigned dst_y,enum pipe_format src_format,const void * src,unsigned src_stride,unsigned src_x,unsigned src_y,unsigned width,unsigned height)645 util_format_translate(enum pipe_format dst_format,
646 void *dst, unsigned dst_stride,
647 unsigned dst_x, unsigned dst_y,
648 enum pipe_format src_format,
649 const void *src, unsigned src_stride,
650 unsigned src_x, unsigned src_y,
651 unsigned width, unsigned height)
652 {
653 const struct util_format_description *dst_format_desc;
654 const struct util_format_description *src_format_desc;
655 const struct util_format_pack_description *pack =
656 util_format_pack_description(dst_format);
657 const struct util_format_unpack_description *unpack =
658 util_format_unpack_description(src_format);
659 uint8_t *dst_row;
660 const uint8_t *src_row;
661 unsigned x_step, y_step;
662 unsigned dst_step;
663 unsigned src_step;
664
665 dst_format_desc = util_format_description(dst_format);
666 src_format_desc = util_format_description(src_format);
667
668 if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
669 /*
670 * Trivial case.
671 */
672
673 util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y,
674 width, height, src, (int)src_stride,
675 src_x, src_y);
676 return true;
677 }
678
679 assert(dst_x % dst_format_desc->block.width == 0);
680 assert(dst_y % dst_format_desc->block.height == 0);
681 assert(src_x % src_format_desc->block.width == 0);
682 assert(src_y % src_format_desc->block.height == 0);
683
684 dst_row = (uint8_t *)dst + (uint64_t)dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
685 src_row = (const uint8_t *)src + (uint64_t)src_y*src_stride + src_x*(src_format_desc->block.bits/8);
686
687 /*
688 * This works because all pixel formats have pixel blocks with power of two
689 * sizes.
690 */
691
692 y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
693 x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
694 assert(y_step % dst_format_desc->block.height == 0);
695 assert(y_step % src_format_desc->block.height == 0);
696
697 dst_step = y_step / dst_format_desc->block.height * dst_stride;
698 src_step = y_step / src_format_desc->block.height * src_stride;
699
700 /*
701 * TODO: double formats will loose precision
702 * TODO: Add a special case for formats that are mere swizzles of each other
703 */
704
705 if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
706 dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
707 float *tmp_z = NULL;
708 uint8_t *tmp_s = NULL;
709
710 assert(x_step == 1);
711 assert(y_step == 1);
712
713 if (unpack->unpack_z_float && pack->pack_z_float) {
714 tmp_z = malloc(width * sizeof *tmp_z);
715 }
716
717 if (unpack->unpack_s_8uint && pack->pack_s_8uint) {
718 tmp_s = malloc(width * sizeof *tmp_s);
719 }
720
721 while (height--) {
722 if (tmp_z) {
723 util_format_unpack_z_float(src_format, tmp_z, src_row, width);
724 util_format_pack_z_float(dst_format, dst_row, tmp_z, width);
725 }
726
727 if (tmp_s) {
728 util_format_unpack_s_8uint(src_format, tmp_s, src_row, width);
729 util_format_pack_s_8uint(dst_format, dst_row, tmp_s, width);
730 }
731
732 dst_row += dst_step;
733 src_row += src_step;
734 }
735
736 free(tmp_s);
737
738 free(tmp_z);
739
740 return true;
741 }
742
743 if (util_format_fits_8unorm(src_format_desc) ||
744 util_format_fits_8unorm(dst_format_desc)) {
745 unsigned tmp_stride;
746 uint8_t *tmp_row;
747
748 if ((!unpack->unpack_rgba_8unorm && !unpack->unpack_rgba_8unorm_rect) ||
749 !pack->pack_rgba_8unorm) {
750 return false;
751 }
752
753 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
754 tmp_row = malloc((uint64_t)y_step * tmp_stride);
755 if (!tmp_row)
756 return false;
757
758 while (height >= y_step) {
759 util_format_unpack_rgba_8unorm_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
760 pack->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
761
762 dst_row += dst_step;
763 src_row += src_step;
764 height -= y_step;
765 }
766
767 if (height) {
768 util_format_unpack_rgba_8unorm_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
769 pack->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
770 }
771
772 free(tmp_row);
773 }
774 else if (util_format_is_pure_sint(src_format) ||
775 util_format_is_pure_sint(dst_format)) {
776 unsigned tmp_stride;
777 int *tmp_row;
778
779 if (util_format_is_pure_sint(src_format) !=
780 util_format_is_pure_sint(dst_format)) {
781 return false;
782 }
783
784 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
785 tmp_row = malloc((uint64_t)y_step * tmp_stride);
786 if (!tmp_row)
787 return false;
788
789 while (height >= y_step) {
790 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
791 pack->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
792
793 dst_row += dst_step;
794 src_row += src_step;
795 height -= y_step;
796 }
797
798 if (height) {
799 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
800 pack->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
801 }
802
803 free(tmp_row);
804 }
805 else if (util_format_is_pure_uint(src_format) ||
806 util_format_is_pure_uint(dst_format)) {
807 unsigned tmp_stride;
808 unsigned int *tmp_row;
809
810 if ((!unpack->unpack_rgba && !unpack->unpack_rgba_rect) ||
811 !pack->pack_rgba_uint) {
812 return false;
813 }
814
815 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
816 tmp_row = malloc((uint64_t)y_step * tmp_stride);
817 if (!tmp_row)
818 return false;
819
820 while (height >= y_step) {
821 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
822 pack->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
823
824 dst_row += dst_step;
825 src_row += src_step;
826 height -= y_step;
827 }
828
829 if (height) {
830 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
831 pack->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
832 }
833
834 free(tmp_row);
835 }
836 else {
837 unsigned tmp_stride;
838 float *tmp_row;
839
840 if ((!unpack->unpack_rgba && !unpack->unpack_rgba_rect) ||
841 !pack->pack_rgba_float) {
842 return false;
843 }
844
845 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
846 tmp_row = malloc((uint64_t)y_step * tmp_stride);
847 if (!tmp_row)
848 return false;
849
850 while (height >= y_step) {
851 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
852 pack->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
853
854 dst_row += dst_step;
855 src_row += src_step;
856 height -= y_step;
857 }
858
859 if (height) {
860 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
861 pack->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
862 }
863
864 free(tmp_row);
865 }
866 return true;
867 }
868
869 bool
util_format_translate_3d(enum pipe_format dst_format,void * dst,unsigned dst_stride,uint64_t dst_slice_stride,unsigned dst_x,unsigned dst_y,unsigned dst_z,enum pipe_format src_format,const void * src,unsigned src_stride,uint64_t src_slice_stride,unsigned src_x,unsigned src_y,unsigned src_z,unsigned width,unsigned height,unsigned depth)870 util_format_translate_3d(enum pipe_format dst_format,
871 void *dst, unsigned dst_stride,
872 uint64_t dst_slice_stride,
873 unsigned dst_x, unsigned dst_y,
874 unsigned dst_z,
875 enum pipe_format src_format,
876 const void *src, unsigned src_stride,
877 uint64_t src_slice_stride,
878 unsigned src_x, unsigned src_y,
879 unsigned src_z, unsigned width,
880 unsigned height, unsigned depth)
881 {
882 uint8_t *dst_layer;
883 const uint8_t *src_layer;
884 unsigned z;
885 dst_layer = dst;
886 src_layer = src;
887 dst_layer += dst_z * dst_slice_stride;
888 src_layer += src_z * src_slice_stride;
889 for (z = 0; z < depth; ++z) {
890 if (!util_format_translate(dst_format, dst_layer, dst_stride,
891 dst_x, dst_y,
892 src_format, src_layer, src_stride,
893 src_x, src_y,
894 width, height))
895 return false;
896
897 dst_layer += dst_slice_stride;
898 src_layer += src_slice_stride;
899 }
900 return true;
901 }
902
util_format_compose_swizzles(const unsigned char swz1[4],const unsigned char swz2[4],unsigned char dst[4])903 void util_format_compose_swizzles(const unsigned char swz1[4],
904 const unsigned char swz2[4],
905 unsigned char dst[4])
906 {
907 unsigned i;
908
909 for (i = 0; i < 4; i++) {
910 dst[i] = swz2[i] <= PIPE_SWIZZLE_W ?
911 swz1[swz2[i]] : swz2[i];
912 }
913 }
914
util_format_apply_color_swizzle(union pipe_color_union * dst,const union pipe_color_union * src,const unsigned char swz[4],const bool is_integer)915 void util_format_apply_color_swizzle(union pipe_color_union *dst,
916 const union pipe_color_union *src,
917 const unsigned char swz[4],
918 const bool is_integer)
919 {
920 unsigned c;
921
922 if (is_integer) {
923 for (c = 0; c < 4; ++c) {
924 switch (swz[c]) {
925 case PIPE_SWIZZLE_X: dst->ui[c] = src->ui[0]; break;
926 case PIPE_SWIZZLE_Y: dst->ui[c] = src->ui[1]; break;
927 case PIPE_SWIZZLE_Z: dst->ui[c] = src->ui[2]; break;
928 case PIPE_SWIZZLE_W: dst->ui[c] = src->ui[3]; break;
929 default:
930 dst->ui[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1 : 0;
931 break;
932 }
933 }
934 } else {
935 for (c = 0; c < 4; ++c) {
936 switch (swz[c]) {
937 case PIPE_SWIZZLE_X: dst->f[c] = src->f[0]; break;
938 case PIPE_SWIZZLE_Y: dst->f[c] = src->f[1]; break;
939 case PIPE_SWIZZLE_Z: dst->f[c] = src->f[2]; break;
940 case PIPE_SWIZZLE_W: dst->f[c] = src->f[3]; break;
941 default:
942 dst->f[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1.0f : 0.0f;
943 break;
944 }
945 }
946 }
947 }
948
pipe_swizzle_4f(float * dst,const float * src,const unsigned char swz[4])949 void pipe_swizzle_4f(float *dst, const float *src,
950 const unsigned char swz[4])
951 {
952 unsigned i;
953
954 for (i = 0; i < 4; i++) {
955 if (swz[i] <= PIPE_SWIZZLE_W)
956 dst[i] = src[swz[i]];
957 else if (swz[i] == PIPE_SWIZZLE_0)
958 dst[i] = 0;
959 else if (swz[i] == PIPE_SWIZZLE_1)
960 dst[i] = 1;
961 }
962 }
963
util_format_unswizzle_4f(float * dst,const float * src,const unsigned char swz[4])964 void util_format_unswizzle_4f(float *dst, const float *src,
965 const unsigned char swz[4])
966 {
967 unsigned i;
968
969 for (i = 0; i < 4; i++) {
970 switch (swz[i]) {
971 case PIPE_SWIZZLE_X:
972 dst[0] = src[i];
973 break;
974 case PIPE_SWIZZLE_Y:
975 dst[1] = src[i];
976 break;
977 case PIPE_SWIZZLE_Z:
978 dst[2] = src[i];
979 break;
980 case PIPE_SWIZZLE_W:
981 dst[3] = src[i];
982 break;
983 }
984 }
985 }
986
987 enum pipe_format
util_format_snorm_to_sint(enum pipe_format format)988 util_format_snorm_to_sint(enum pipe_format format)
989 {
990 switch (format) {
991 case PIPE_FORMAT_R32_SNORM:
992 return PIPE_FORMAT_R32_SINT;
993 case PIPE_FORMAT_R32G32_SNORM:
994 return PIPE_FORMAT_R32G32_SINT;
995 case PIPE_FORMAT_R32G32B32_SNORM:
996 return PIPE_FORMAT_R32G32B32_SINT;
997 case PIPE_FORMAT_R32G32B32A32_SNORM:
998 return PIPE_FORMAT_R32G32B32A32_SINT;
999
1000 case PIPE_FORMAT_R16_SNORM:
1001 return PIPE_FORMAT_R16_SINT;
1002 case PIPE_FORMAT_R16G16_SNORM:
1003 return PIPE_FORMAT_R16G16_SINT;
1004 case PIPE_FORMAT_R16G16B16_SNORM:
1005 return PIPE_FORMAT_R16G16B16_SINT;
1006 case PIPE_FORMAT_R16G16B16A16_SNORM:
1007 return PIPE_FORMAT_R16G16B16A16_SINT;
1008
1009 case PIPE_FORMAT_R8_SNORM:
1010 return PIPE_FORMAT_R8_SINT;
1011 case PIPE_FORMAT_R8G8_SNORM:
1012 return PIPE_FORMAT_R8G8_SINT;
1013 case PIPE_FORMAT_R8G8B8_SNORM:
1014 return PIPE_FORMAT_R8G8B8_SINT;
1015 case PIPE_FORMAT_B8G8R8_SNORM:
1016 return PIPE_FORMAT_B8G8R8_SINT;
1017 case PIPE_FORMAT_R8G8B8A8_SNORM:
1018 return PIPE_FORMAT_R8G8B8A8_SINT;
1019 case PIPE_FORMAT_B8G8R8A8_SNORM:
1020 return PIPE_FORMAT_B8G8R8A8_SINT;
1021
1022 case PIPE_FORMAT_R10G10B10A2_SNORM:
1023 return PIPE_FORMAT_R10G10B10A2_SINT;
1024 case PIPE_FORMAT_B10G10R10A2_SNORM:
1025 return PIPE_FORMAT_B10G10R10A2_SINT;
1026
1027 case PIPE_FORMAT_R10G10B10X2_SNORM:
1028 return PIPE_FORMAT_R10G10B10X2_SINT;
1029
1030 case PIPE_FORMAT_A8_SNORM:
1031 return PIPE_FORMAT_A8_SINT;
1032 case PIPE_FORMAT_L8_SNORM:
1033 return PIPE_FORMAT_L8_SINT;
1034 case PIPE_FORMAT_L8A8_SNORM:
1035 return PIPE_FORMAT_L8A8_SINT;
1036 case PIPE_FORMAT_I8_SNORM:
1037 return PIPE_FORMAT_I8_SINT;
1038
1039 case PIPE_FORMAT_A16_SNORM:
1040 return PIPE_FORMAT_A16_SINT;
1041 case PIPE_FORMAT_L16_SNORM:
1042 return PIPE_FORMAT_L16_SINT;
1043 case PIPE_FORMAT_L16A16_SNORM:
1044 return PIPE_FORMAT_L16A16_SINT;
1045 case PIPE_FORMAT_I16_SNORM:
1046 return PIPE_FORMAT_I16_SINT;
1047
1048 case PIPE_FORMAT_R8G8B8X8_SNORM:
1049 return PIPE_FORMAT_R8G8B8X8_SINT;
1050 case PIPE_FORMAT_R16G16B16X16_SNORM:
1051 return PIPE_FORMAT_R16G16B16X16_SINT;
1052
1053 case PIPE_FORMAT_R8A8_SNORM:
1054 return PIPE_FORMAT_R8A8_SINT;
1055 case PIPE_FORMAT_R16A16_SNORM:
1056 return PIPE_FORMAT_R16A16_SINT;
1057
1058 case PIPE_FORMAT_G8R8_SNORM:
1059 return PIPE_FORMAT_G8R8_SINT;
1060 case PIPE_FORMAT_G16R16_SNORM:
1061 return PIPE_FORMAT_G16R16_SINT;
1062
1063 case PIPE_FORMAT_A8B8G8R8_SNORM:
1064 return PIPE_FORMAT_A8B8G8R8_SINT;
1065 case PIPE_FORMAT_X8B8G8R8_SNORM:
1066 return PIPE_FORMAT_X8B8G8R8_SINT;
1067
1068 case PIPE_FORMAT_B8G8R8X8_SNORM:
1069 return PIPE_FORMAT_B8G8R8X8_SINT;
1070 case PIPE_FORMAT_A8R8G8B8_SNORM:
1071 return PIPE_FORMAT_A8R8G8B8_SINT;
1072 case PIPE_FORMAT_X8R8G8B8_SNORM:
1073 return PIPE_FORMAT_X8R8G8B8_SINT;
1074 case PIPE_FORMAT_B10G10R10X2_SNORM:
1075 return PIPE_FORMAT_B10G10R10X2_SINT;
1076
1077 default:
1078 return format;
1079 }
1080 }
1081
1082 /**
1083 * If the format is RGB, return BGR. If the format is BGR, return RGB.
1084 * This may fail by returning PIPE_FORMAT_NONE.
1085 */
1086 enum pipe_format
util_format_rgb_to_bgr(enum pipe_format format)1087 util_format_rgb_to_bgr(enum pipe_format format)
1088 {
1089 #define REMAP_RGB_ONE(r, rs, g, gs, b, bs, type) \
1090 case PIPE_FORMAT_##r##rs##g##gs##b##bs##_##type: \
1091 return PIPE_FORMAT_##b##bs##g##gs##r##rs##_##type;
1092
1093 #define REMAP_RGB(rs, gs, bs, type) \
1094 REMAP_RGB_ONE(R, rs, G, gs, B, bs, type) \
1095 REMAP_RGB_ONE(B, bs, G, gs, R, rs, type) \
1096
1097 #define REMAP_RGBA_ONE(r, rs, g, gs, b, bs, a, as, type) \
1098 case PIPE_FORMAT_##r##rs##g##gs##b##bs##a##as##_##type: \
1099 return PIPE_FORMAT_##b##bs##g##gs##r##rs##a##as##_##type;
1100
1101 #define REMAP_ARGB_ONE(a, as, r, rs, g, gs, b, bs, type) \
1102 case PIPE_FORMAT_##a##as##r##rs##g##gs##b##bs##_##type: \
1103 return PIPE_FORMAT_##a##as##b##bs##g##gs##r##rs##_##type;
1104
1105 #define REMAP_RGB_AX(A, rs, gs, bs, as, type) \
1106 REMAP_RGBA_ONE(R, rs, G, gs, B, bs, A, as, type) \
1107 REMAP_RGBA_ONE(B, bs, G, gs, R, rs, A, as, type) \
1108
1109 #define REMAP_AX_RGB(A, rs, gs, bs, as, type) \
1110 REMAP_ARGB_ONE(A, as, R, rs, G, gs, B, bs, type) \
1111 REMAP_ARGB_ONE(A, as, B, bs, G, gs, R, rs, type) \
1112
1113 #define REMAP_RGBA(rs, gs, bs, as, type) REMAP_RGB_AX(A, rs, gs, bs, as, type)
1114 #define REMAP_RGBX(rs, gs, bs, as, type) REMAP_RGB_AX(X, rs, gs, bs, as, type)
1115 #define REMAP_ARGB(rs, gs, bs, as, type) REMAP_AX_RGB(A, rs, gs, bs, as, type)
1116 #define REMAP_XRGB(rs, gs, bs, as, type) REMAP_AX_RGB(X, rs, gs, bs, as, type)
1117
1118 #define REMAP_RGBA_ALL(rs, gs, bs, as, type) \
1119 REMAP_RGBA(rs, gs, bs, as, type) \
1120 REMAP_RGBX(rs, gs, bs, as, type) \
1121 REMAP_ARGB(rs, gs, bs, as, type) \
1122 REMAP_XRGB(rs, gs, bs, as, type)
1123
1124 switch (format) {
1125 REMAP_RGB(3, 3, 2, UNORM);
1126 REMAP_RGB(3, 3, 2, UINT);
1127 REMAP_RGB(5, 6, 5, SRGB);
1128 REMAP_RGB(5, 6, 5, UNORM);
1129 REMAP_RGB(5, 6, 5, UINT);
1130 REMAP_RGB(8, 8, 8, SRGB);
1131 REMAP_RGB(8, 8, 8, UNORM);
1132 REMAP_RGB(8, 8, 8, SNORM);
1133 REMAP_RGB(8, 8, 8, UINT);
1134 REMAP_RGB(8, 8, 8, SINT);
1135 REMAP_RGB(8, 8, 8, USCALED);
1136 REMAP_RGB(8, 8, 8, SSCALED);
1137
1138 /* Complete format sets. */
1139 REMAP_RGBA_ALL(5, 5, 5, 1, UNORM);
1140 REMAP_RGBA_ALL(8, 8, 8, 8, SRGB);
1141 REMAP_RGBA_ALL(8, 8, 8, 8, UNORM);
1142 REMAP_RGBA_ALL(8, 8, 8, 8, SNORM);
1143 REMAP_RGBA_ALL(8, 8, 8, 8, SINT);
1144
1145 /* Format sets missing XRGB/XBGR. */
1146 REMAP_RGBA(4, 4, 4, 4, UNORM);
1147 REMAP_RGBX(4, 4, 4, 4, UNORM);
1148 REMAP_ARGB(4, 4, 4, 4, UNORM);
1149
1150 REMAP_RGBA(8, 8, 8, 8, UINT);
1151 REMAP_RGBX(8, 8, 8, 8, UINT);
1152 REMAP_ARGB(8, 8, 8, 8, UINT);
1153
1154 REMAP_RGBA(10, 10, 10, 2, UNORM);
1155 REMAP_RGBX(10, 10, 10, 2, UNORM);
1156 REMAP_ARGB(10, 10, 10, 2, UNORM);
1157
1158 /* Format sets missing a half of combinations. */
1159 REMAP_RGBA(4, 4, 4, 4, UINT);
1160 REMAP_ARGB(4, 4, 4, 4, UINT);
1161
1162 REMAP_RGBA(5, 5, 5, 1, UINT);
1163 REMAP_ARGB(5, 5, 5, 1, UINT);
1164
1165 REMAP_RGBA(10, 10, 10, 2, SNORM);
1166 REMAP_RGBX(10, 10, 10, 2, SNORM);
1167
1168 REMAP_RGBA(10, 10, 10, 2, UINT);
1169 REMAP_ARGB(10, 10, 10, 2, UINT);
1170
1171 REMAP_RGBA(10, 10, 10, 2, SINT);
1172 REMAP_RGBX(10, 10, 10, 2, SINT);
1173
1174 /* Format sets having only RGBA/BGRA. */
1175 REMAP_RGBA(8, 8, 8, 8, USCALED);
1176 REMAP_RGBA(8, 8, 8, 8, SSCALED);
1177 REMAP_RGBA(10, 10, 10, 2, USCALED);
1178 REMAP_RGBA(10, 10, 10, 2, SSCALED);
1179
1180 default:
1181 return PIPE_FORMAT_NONE;
1182 }
1183 }
1184
1185 static const struct util_format_unpack_description *util_format_unpack_table[PIPE_FORMAT_COUNT];
1186
1187 static void
util_format_unpack_table_init(void)1188 util_format_unpack_table_init(void)
1189 {
1190 for (enum pipe_format format = PIPE_FORMAT_NONE; format < PIPE_FORMAT_COUNT; format++) {
1191 #if (DETECT_ARCH_AARCH64 || DETECT_ARCH_ARM) && !defined(NO_FORMAT_ASM) && !defined(__SOFTFP__)
1192 const struct util_format_unpack_description *unpack = util_format_unpack_description_neon(format);
1193 if (unpack) {
1194 util_format_unpack_table[format] = unpack;
1195 continue;
1196 }
1197 #endif
1198
1199 util_format_unpack_table[format] = util_format_unpack_description_generic(format);
1200 }
1201 }
1202
1203 const struct util_format_unpack_description *
util_format_unpack_description(enum pipe_format format)1204 util_format_unpack_description(enum pipe_format format)
1205 {
1206 static once_flag flag = ONCE_FLAG_INIT;
1207 call_once(&flag, util_format_unpack_table_init);
1208
1209 return util_format_unpack_table[format];
1210 }
1211
1212 enum pipe_format
util_format_snorm_to_unorm(enum pipe_format format)1213 util_format_snorm_to_unorm(enum pipe_format format)
1214 {
1215 #define CASE(x) case PIPE_FORMAT_##x##_SNORM: return PIPE_FORMAT_##x##_UNORM
1216
1217 switch (format) {
1218 CASE(R8G8B8A8);
1219 CASE(R8G8B8X8);
1220 CASE(B8G8R8A8);
1221 CASE(B8G8R8X8);
1222 CASE(A8R8G8B8);
1223 CASE(X8R8G8B8);
1224 CASE(A8B8G8R8);
1225 CASE(X8B8G8R8);
1226
1227 CASE(R10G10B10A2);
1228 CASE(R10G10B10X2);
1229 CASE(B10G10R10A2);
1230 CASE(B10G10R10X2);
1231
1232 CASE(R8);
1233 CASE(R8G8);
1234 CASE(G8R8);
1235 CASE(R8G8B8);
1236 CASE(B8G8R8);
1237
1238 CASE(R16);
1239 CASE(R16G16);
1240 CASE(G16R16);
1241 CASE(R16G16B16);
1242
1243 CASE(R16G16B16A16);
1244 CASE(R16G16B16X16);
1245
1246 CASE(R32);
1247 CASE(R32G32);
1248 CASE(R32G32B32);
1249 CASE(R32G32B32A32);
1250
1251 CASE(RGTC1);
1252 CASE(RGTC2);
1253 CASE(ETC2_R11);
1254 CASE(ETC2_RG11);
1255
1256 CASE(A8);
1257 CASE(A16);
1258 CASE(L8);
1259 CASE(L16);
1260 CASE(I8);
1261 CASE(I16);
1262
1263 CASE(L8A8);
1264 CASE(L16A16);
1265 CASE(R8A8);
1266 CASE(R16A16);
1267
1268 CASE(LATC1);
1269 CASE(LATC2);
1270
1271 default:
1272 return format;
1273 }
1274
1275 #undef CASE
1276 }
1277
1278 enum pipe_format
util_format_rgbx_to_rgba(enum pipe_format format)1279 util_format_rgbx_to_rgba(enum pipe_format format)
1280 {
1281 switch (format) {
1282 case PIPE_FORMAT_B8G8R8X8_UNORM:
1283 return PIPE_FORMAT_B8G8R8A8_UNORM;
1284 case PIPE_FORMAT_X8B8G8R8_UNORM:
1285 return PIPE_FORMAT_A8B8G8R8_UNORM;
1286 case PIPE_FORMAT_X8R8G8B8_UNORM:
1287 return PIPE_FORMAT_A8R8G8B8_UNORM;
1288 case PIPE_FORMAT_X8B8G8R8_SRGB:
1289 return PIPE_FORMAT_A8B8G8R8_SRGB;
1290 case PIPE_FORMAT_B8G8R8X8_SRGB:
1291 return PIPE_FORMAT_B8G8R8A8_SRGB;
1292 case PIPE_FORMAT_X8R8G8B8_SRGB:
1293 return PIPE_FORMAT_A8R8G8B8_SRGB;
1294 case PIPE_FORMAT_B5G5R5X1_UNORM:
1295 return PIPE_FORMAT_B5G5R5A1_UNORM;
1296 case PIPE_FORMAT_R10G10B10X2_USCALED:
1297 return PIPE_FORMAT_R10G10B10A2_USCALED;
1298 case PIPE_FORMAT_R10G10B10X2_SNORM:
1299 return PIPE_FORMAT_R10G10B10A2_SNORM;
1300 case PIPE_FORMAT_R8G8B8X8_UNORM:
1301 return PIPE_FORMAT_R8G8B8A8_UNORM;
1302 case PIPE_FORMAT_B4G4R4X4_UNORM:
1303 return PIPE_FORMAT_B4G4R4A4_UNORM;
1304 case PIPE_FORMAT_R8G8B8X8_SNORM:
1305 return PIPE_FORMAT_R8G8B8A8_SNORM;
1306 case PIPE_FORMAT_R8G8B8X8_SRGB:
1307 return PIPE_FORMAT_R8G8B8A8_SRGB;
1308 case PIPE_FORMAT_R8G8B8X8_UINT:
1309 return PIPE_FORMAT_R8G8B8A8_UINT;
1310 case PIPE_FORMAT_R8G8B8X8_SINT:
1311 return PIPE_FORMAT_R8G8B8A8_SINT;
1312 case PIPE_FORMAT_B10G10R10X2_UNORM:
1313 return PIPE_FORMAT_B10G10R10A2_UNORM;
1314 case PIPE_FORMAT_R16G16B16X16_UNORM:
1315 return PIPE_FORMAT_R16G16B16A16_UNORM;
1316 case PIPE_FORMAT_R16G16B16X16_SNORM:
1317 return PIPE_FORMAT_R16G16B16A16_SNORM;
1318 case PIPE_FORMAT_R16G16B16X16_FLOAT:
1319 return PIPE_FORMAT_R16G16B16A16_FLOAT;
1320 case PIPE_FORMAT_R16G16B16X16_UINT:
1321 return PIPE_FORMAT_R16G16B16A16_UINT;
1322 case PIPE_FORMAT_R16G16B16X16_SINT:
1323 return PIPE_FORMAT_R16G16B16A16_SINT;
1324 case PIPE_FORMAT_R32G32B32X32_FLOAT:
1325 return PIPE_FORMAT_R32G32B32A32_FLOAT;
1326 case PIPE_FORMAT_R32G32B32X32_UINT:
1327 return PIPE_FORMAT_R32G32B32A32_UINT;
1328 case PIPE_FORMAT_R32G32B32X32_SINT:
1329 return PIPE_FORMAT_R32G32B32A32_SINT;
1330 case PIPE_FORMAT_X8B8G8R8_SNORM:
1331 return PIPE_FORMAT_A8B8G8R8_SNORM;
1332 case PIPE_FORMAT_R10G10B10X2_UNORM:
1333 return PIPE_FORMAT_R10G10B10A2_UNORM;
1334 case PIPE_FORMAT_X1B5G5R5_UNORM:
1335 return PIPE_FORMAT_A1B5G5R5_UNORM;
1336 case PIPE_FORMAT_X8B8G8R8_SINT:
1337 return PIPE_FORMAT_A8B8G8R8_SINT;
1338 case PIPE_FORMAT_B8G8R8X8_SNORM:
1339 return PIPE_FORMAT_B8G8R8A8_SNORM;
1340 case PIPE_FORMAT_B8G8R8X8_UINT:
1341 return PIPE_FORMAT_B8G8R8A8_UINT;
1342 case PIPE_FORMAT_B8G8R8X8_SINT:
1343 return PIPE_FORMAT_B8G8R8A8_SINT;
1344 case PIPE_FORMAT_X8R8G8B8_SNORM:
1345 return PIPE_FORMAT_A8R8G8B8_SNORM;
1346 case PIPE_FORMAT_X8R8G8B8_SINT:
1347 return PIPE_FORMAT_A8R8G8B8_SINT;
1348 case PIPE_FORMAT_R5G5B5X1_UNORM:
1349 return PIPE_FORMAT_R5G5B5A1_UNORM;
1350 case PIPE_FORMAT_X1R5G5B5_UNORM:
1351 return PIPE_FORMAT_A1R5G5B5_UNORM;
1352 case PIPE_FORMAT_R4G4B4X4_UNORM:
1353 return PIPE_FORMAT_R4G4B4A4_UNORM;
1354 case PIPE_FORMAT_B10G10R10X2_SNORM:
1355 return PIPE_FORMAT_B10G10R10A2_SNORM;
1356 case PIPE_FORMAT_R10G10B10X2_SINT:
1357 return PIPE_FORMAT_R10G10B10A2_SINT;
1358 case PIPE_FORMAT_B10G10R10X2_SINT:
1359 return PIPE_FORMAT_B10G10R10A2_SINT;
1360 default: {
1361 ASSERTED const struct util_format_description *desc = util_format_description(format);
1362
1363 /* Assert that the format doesn't contain X instead of A. */
1364 assert(desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS ||
1365 (desc->channel[0].type != UTIL_FORMAT_TYPE_VOID &&
1366 desc->channel[desc->nr_channels - 1].type != UTIL_FORMAT_TYPE_VOID));
1367 return format;
1368 }
1369 }
1370 }
1371
1372 enum pipe_format
util_format_get_array(const enum util_format_type type,const unsigned bits,const unsigned nr_components,const bool normalized,const bool pure_integer)1373 util_format_get_array(const enum util_format_type type, const unsigned bits,
1374 const unsigned nr_components, const bool normalized,
1375 const bool pure_integer)
1376 {
1377 #define CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS, NR_VAR) \
1378 case BITS: \
1379 switch (NR_VAR) { \
1380 case 1: \
1381 return PIPE_FORMAT_R##BITS##_##TYPE; \
1382 case 2: \
1383 return PIPE_FORMAT_R##BITS##G##BITS##_##TYPE; \
1384 case 3: \
1385 return PIPE_FORMAT_R##BITS##G##BITS##B##BITS##_##TYPE; \
1386 case 4: \
1387 return PIPE_FORMAT_R##BITS##G##BITS##B##BITS##A##BITS##_##TYPE; \
1388 default: \
1389 return PIPE_FORMAT_NONE; \
1390 }
1391
1392 #define SWITCH_BY_BITS_CASEX3(TYPE, BITS_VAR, BITS1, BITS2, BITS3, NR_VAR) \
1393 switch (BITS_VAR) { \
1394 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS1, NR_VAR) \
1395 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS2, NR_VAR) \
1396 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS3, NR_VAR) \
1397 default: \
1398 return PIPE_FORMAT_NONE; \
1399 }
1400
1401 #define SWITCH_BY_BITS_CASEX4(TYPE, BITS_VAR, BITS1, BITS2, BITS3, BITS4, NR_VAR) \
1402 switch (BITS_VAR) { \
1403 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS1, NR_VAR) \
1404 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS2, NR_VAR) \
1405 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS3, NR_VAR) \
1406 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS4, NR_VAR) \
1407 default: \
1408 return PIPE_FORMAT_NONE; \
1409 }
1410
1411 switch (type) {
1412 case UTIL_FORMAT_TYPE_UNSIGNED:
1413 if (normalized)
1414 SWITCH_BY_BITS_CASEX3(UNORM, bits, 8, 16, 32, nr_components)
1415 else if (!pure_integer)
1416 SWITCH_BY_BITS_CASEX3(USCALED, bits, 8, 16, 32, nr_components)
1417 else
1418 SWITCH_BY_BITS_CASEX4(UINT, bits, 8, 16, 32, 64, nr_components)
1419 case UTIL_FORMAT_TYPE_SIGNED:
1420 if (normalized)
1421 SWITCH_BY_BITS_CASEX3(SNORM, bits, 8, 16, 32, nr_components)
1422 else if (!pure_integer)
1423 SWITCH_BY_BITS_CASEX3(SSCALED, bits, 8, 16, 32, nr_components)
1424 else
1425 SWITCH_BY_BITS_CASEX4(SINT, bits, 8, 16, 32, 64, nr_components)
1426 case UTIL_FORMAT_TYPE_FLOAT:
1427 SWITCH_BY_BITS_CASEX3(FLOAT, bits, 16, 32, 64, nr_components)
1428 default:
1429 return PIPE_FORMAT_NONE;
1430 }
1431
1432 #undef CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4
1433 #undef SWITCH_BY_BITS_CASEX3
1434 #undef SWITCH_BY_BITS_CASEX4
1435
1436 return PIPE_FORMAT_NONE;
1437 }
1438