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 <[email protected]>
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 bool
util_format_is_red_alpha(enum pipe_format format)303 util_format_is_red_alpha(enum pipe_format format)
304 {
305 const struct util_format_description *desc =
306 util_format_description(format);
307
308 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
309 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
310 desc->swizzle[0] == PIPE_SWIZZLE_X &&
311 desc->swizzle[1] == PIPE_SWIZZLE_0 &&
312 desc->swizzle[2] == PIPE_SWIZZLE_0 &&
313 desc->swizzle[3] == PIPE_SWIZZLE_Y) {
314 return true;
315 }
316 return false;
317 }
318
319 bool
util_format_is_red_green(enum pipe_format format)320 util_format_is_red_green(enum pipe_format format)
321 {
322 const struct util_format_description *desc =
323 util_format_description(format);
324
325 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
326 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
327 desc->swizzle[0] == PIPE_SWIZZLE_X &&
328 desc->swizzle[1] == PIPE_SWIZZLE_Y &&
329 desc->swizzle[2] == PIPE_SWIZZLE_0 &&
330 desc->swizzle[3] == PIPE_SWIZZLE_1) {
331 return true;
332 }
333 return false;
334 }
335
336 bool
util_format_is_intensity(enum pipe_format format)337 util_format_is_intensity(enum pipe_format format)
338 {
339 const struct util_format_description *desc =
340 util_format_description(format);
341
342 if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
343 desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
344 desc->swizzle[0] == PIPE_SWIZZLE_X &&
345 desc->swizzle[1] == PIPE_SWIZZLE_X &&
346 desc->swizzle[2] == PIPE_SWIZZLE_X &&
347 desc->swizzle[3] == PIPE_SWIZZLE_X) {
348 return true;
349 }
350 return false;
351 }
352
353 bool
util_format_is_subsampled_422(enum pipe_format format)354 util_format_is_subsampled_422(enum pipe_format format)
355 {
356 const struct util_format_description *desc =
357 util_format_description(format);
358
359 return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED &&
360 desc->block.width == 2 &&
361 desc->block.height == 1 &&
362 desc->block.bits == 32;
363 }
364
365 /**
366 * Calculates the MRD for the depth format. MRD is used in depth bias
367 * for UNORM and unbound depth buffers. When the depth buffer is floating
368 * point, the depth bias calculation does not use the MRD. However, the
369 * default MRD will be 1.0 / ((1 << 24) - 1).
370 */
371 double
util_get_depth_format_mrd(const struct util_format_description * desc)372 util_get_depth_format_mrd(const struct util_format_description *desc)
373 {
374 /*
375 * Depth buffer formats without a depth component OR scenarios
376 * without a bound depth buffer default to D24.
377 */
378 double mrd = 1.0 / ((1 << 24) - 1);
379 unsigned depth_channel;
380
381 /*
382 * Some depth formats do not store the depth component in the first
383 * channel, detect the format and adjust the depth channel. Get the
384 * swizzled depth component channel.
385 */
386 depth_channel = desc->swizzle[0];
387
388 if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
389 desc->channel[depth_channel].normalized) {
390 int depth_bits;
391
392 depth_bits = desc->channel[depth_channel].size;
393 mrd = 1.0 / ((1ULL << depth_bits) - 1);
394 }
395
396 return mrd;
397 }
398
399 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)400 util_format_unpack_rgba_rect(enum pipe_format format,
401 void *dst, unsigned dst_stride,
402 const void *src, unsigned src_stride,
403 unsigned w, unsigned h)
404 {
405 const struct util_format_unpack_description *unpack =
406 util_format_unpack_description(format);
407
408 /* Optimized function for block-compressed formats */
409 if (unpack->unpack_rgba_rect) {
410 unpack->unpack_rgba_rect(dst, dst_stride, src, src_stride, w, h);
411 } else {
412 for (unsigned y = 0; y < h; y++) {
413 unpack->unpack_rgba(dst, src, w);
414 src = (const char *)src + src_stride;
415 dst = (char *)dst + dst_stride;
416 }
417 }
418 }
419
420 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)421 util_format_unpack_rgba_8unorm_rect(enum pipe_format format,
422 void *dst, unsigned dst_stride,
423 const void *src, unsigned src_stride,
424 unsigned w, unsigned h)
425 {
426 const struct util_format_unpack_description *unpack =
427 util_format_unpack_description(format);
428
429 /* Optimized function for block-compressed formats */
430 if (unpack->unpack_rgba_8unorm_rect) {
431 unpack->unpack_rgba_8unorm_rect(dst, dst_stride, src, src_stride, w, h);
432 } else {
433 for (unsigned y = 0; y < h; y++) {
434 unpack->unpack_rgba_8unorm(dst, src, w);
435 src = (const char *)src + src_stride;
436 dst = (char *)dst + dst_stride;
437 }
438 }
439 }
440
441 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)442 util_format_read_4(enum pipe_format format,
443 void *dst, unsigned dst_stride,
444 const void *src, unsigned src_stride,
445 unsigned x, unsigned y, unsigned w, unsigned h)
446 {
447 const struct util_format_description *format_desc;
448 const uint8_t *src_row;
449
450 format_desc = util_format_description(format);
451
452 assert(x % format_desc->block.width == 0);
453 assert(y % format_desc->block.height == 0);
454
455 src_row = (const uint8_t *)src + (uint64_t)y*src_stride + x*(format_desc->block.bits/8);
456
457 util_format_unpack_rgba_rect(format, dst, dst_stride, src_row, src_stride, w, h);
458 }
459
460
461 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)462 util_format_write_4(enum pipe_format format,
463 const void *src, unsigned src_stride,
464 void *dst, unsigned dst_stride,
465 unsigned x, unsigned y, unsigned w, unsigned h)
466 {
467 const struct util_format_description *format_desc;
468 const struct util_format_pack_description *pack =
469 util_format_pack_description(format);
470 uint8_t *dst_row;
471
472 format_desc = util_format_description(format);
473
474 assert(x % format_desc->block.width == 0);
475 assert(y % format_desc->block.height == 0);
476
477 dst_row = (uint8_t *)dst + (uint64_t)y*dst_stride + x*(format_desc->block.bits/8);
478
479 if (util_format_is_pure_uint(format))
480 pack->pack_rgba_uint(dst_row, dst_stride, src, src_stride, w, h);
481 else if (util_format_is_pure_sint(format))
482 pack->pack_rgba_sint(dst_row, dst_stride, src, src_stride, w, h);
483 else
484 pack->pack_rgba_float(dst_row, dst_stride, src, src_stride, w, h);
485 }
486
487
488 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)489 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)
490 {
491 const struct util_format_description *format_desc;
492 const uint8_t *src_row;
493
494 format_desc = util_format_description(format);
495
496 assert(x % format_desc->block.width == 0);
497 assert(y % format_desc->block.height == 0);
498
499 src_row = (const uint8_t *)src + (uint64_t)y*src_stride + x*(format_desc->block.bits/8);
500
501 util_format_unpack_rgba_8unorm_rect(format, dst, dst_stride, src_row, src_stride, w, h);
502 }
503
504
505 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)506 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)
507 {
508 const struct util_format_description *format_desc;
509 const struct util_format_pack_description *pack =
510 util_format_pack_description(format);
511 uint8_t *dst_row;
512 const uint8_t *src_row;
513
514 format_desc = util_format_description(format);
515
516 assert(x % format_desc->block.width == 0);
517 assert(y % format_desc->block.height == 0);
518
519 dst_row = (uint8_t *)dst + (uint64_t)y*dst_stride + x*(format_desc->block.bits/8);
520 src_row = src;
521
522 pack->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
523 }
524
525 /**
526 * Check if we can safely memcopy from the source format to the dest format.
527 * This basically covers the cases of a "used" channel copied to a typeless
528 * channel, plus some 1-channel cases.
529 * Examples of compatible copy formats include:
530 * b8g8r8a8_unorm -> b8g8r8x8_unorm
531 * a8r8g8b8_unorm -> x8r8g8b8_unorm
532 * b5g5r5a1_unorm -> b5g5r5x1_unorm
533 * b4g4r4a4_unorm -> b4g4r4x4_unorm
534 * l8_unorm -> r8_unorm
535 * i8_unorm -> l8_unorm
536 * i8_unorm -> a8_unorm
537 * i8_unorm -> r8_unorm
538 * l16_unorm -> r16_unorm
539 * z24_unorm_s8_uint -> z24x8_unorm
540 * s8_uint_z24_unorm -> x8z24_unorm
541 * r8g8b8a8_unorm -> r8g8b8x8_unorm
542 * a8b8g8r8_srgb -> x8b8g8r8_srgb
543 * b8g8r8a8_srgb -> b8g8r8x8_srgb
544 * a8r8g8b8_srgb -> x8r8g8b8_srgb
545 * a8b8g8r8_unorm -> x8b8g8r8_unorm
546 * r10g10b10a2_uscaled -> r10g10b10x2_uscaled
547 * r10sg10sb10sa2u_norm -> r10g10b10x2_snorm
548 */
549 bool
util_is_format_compatible(const struct util_format_description * src_desc,const struct util_format_description * dst_desc)550 util_is_format_compatible(const struct util_format_description *src_desc,
551 const struct util_format_description *dst_desc)
552 {
553 unsigned chan;
554
555 if (src_desc->format == dst_desc->format) {
556 return true;
557 }
558
559 if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
560 dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
561 return false;
562 }
563
564 if (src_desc->block.bits != dst_desc->block.bits ||
565 src_desc->nr_channels != dst_desc->nr_channels ||
566 src_desc->colorspace != dst_desc->colorspace) {
567 return false;
568 }
569
570 for (chan = 0; chan < 4; ++chan) {
571 if (src_desc->channel[chan].size !=
572 dst_desc->channel[chan].size) {
573 return false;
574 }
575 }
576
577 for (chan = 0; chan < 4; ++chan) {
578 enum pipe_swizzle swizzle = dst_desc->swizzle[chan];
579
580 if (swizzle < 4) {
581 if (src_desc->swizzle[chan] != swizzle) {
582 return false;
583 }
584 if ((src_desc->channel[swizzle].type !=
585 dst_desc->channel[swizzle].type) ||
586 (src_desc->channel[swizzle].normalized !=
587 dst_desc->channel[swizzle].normalized)) {
588 return false;
589 }
590 }
591 }
592
593 return true;
594 }
595
596
597 bool
util_format_fits_8unorm(const struct util_format_description * format_desc)598 util_format_fits_8unorm(const struct util_format_description *format_desc)
599 {
600 unsigned chan;
601
602 /*
603 * After linearized sRGB values require more than 8bits.
604 */
605
606 if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
607 return false;
608 }
609
610 switch (format_desc->layout) {
611
612 case UTIL_FORMAT_LAYOUT_S3TC:
613 /*
614 * These are straight forward.
615 */
616 return true;
617 case UTIL_FORMAT_LAYOUT_RGTC:
618 if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
619 format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
620 format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
621 format_desc->format == PIPE_FORMAT_LATC2_SNORM)
622 return false;
623 return true;
624 case UTIL_FORMAT_LAYOUT_BPTC:
625 if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM)
626 return true;
627 return false;
628
629 case UTIL_FORMAT_LAYOUT_ETC:
630 if (format_desc->format == PIPE_FORMAT_ETC1_RGB8)
631 return true;
632 return false;
633
634 case UTIL_FORMAT_LAYOUT_PLAIN:
635 /*
636 * For these we can find a generic rule.
637 */
638
639 for (chan = 0; chan < format_desc->nr_channels; ++chan) {
640 switch (format_desc->channel[chan].type) {
641 case UTIL_FORMAT_TYPE_VOID:
642 break;
643 case UTIL_FORMAT_TYPE_UNSIGNED:
644 if (!format_desc->channel[chan].normalized ||
645 format_desc->channel[chan].size > 8) {
646 return false;
647 }
648 break;
649 default:
650 return false;
651 }
652 }
653 return true;
654
655 default:
656 /*
657 * Handle all others on a case by case basis.
658 */
659
660 switch (format_desc->format) {
661 case PIPE_FORMAT_R1_UNORM:
662 case PIPE_FORMAT_UYVY:
663 case PIPE_FORMAT_VYUY:
664 case PIPE_FORMAT_YUYV:
665 case PIPE_FORMAT_YVYU:
666 case PIPE_FORMAT_R8G8_B8G8_UNORM:
667 case PIPE_FORMAT_G8R8_G8B8_UNORM:
668 return true;
669
670 default:
671 return false;
672 }
673 }
674 }
675
676
677 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)678 util_format_translate(enum pipe_format dst_format,
679 void *dst, unsigned dst_stride,
680 unsigned dst_x, unsigned dst_y,
681 enum pipe_format src_format,
682 const void *src, unsigned src_stride,
683 unsigned src_x, unsigned src_y,
684 unsigned width, unsigned height)
685 {
686 const struct util_format_description *dst_format_desc;
687 const struct util_format_description *src_format_desc;
688 const struct util_format_pack_description *pack =
689 util_format_pack_description(dst_format);
690 const struct util_format_unpack_description *unpack =
691 util_format_unpack_description(src_format);
692 uint8_t *dst_row;
693 const uint8_t *src_row;
694 unsigned x_step, y_step;
695 unsigned dst_step;
696 unsigned src_step;
697
698 dst_format_desc = util_format_description(dst_format);
699 src_format_desc = util_format_description(src_format);
700
701 if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
702 /*
703 * Trivial case.
704 */
705
706 util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y,
707 width, height, src, (int)src_stride,
708 src_x, src_y);
709 return true;
710 }
711
712 assert(dst_x % dst_format_desc->block.width == 0);
713 assert(dst_y % dst_format_desc->block.height == 0);
714 assert(src_x % src_format_desc->block.width == 0);
715 assert(src_y % src_format_desc->block.height == 0);
716
717 dst_row = (uint8_t *)dst + (uint64_t)dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
718 src_row = (const uint8_t *)src + (uint64_t)src_y*src_stride + src_x*(src_format_desc->block.bits/8);
719
720 /*
721 * This works because all pixel formats have pixel blocks with power of two
722 * sizes.
723 */
724
725 y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
726 x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
727 assert(y_step % dst_format_desc->block.height == 0);
728 assert(y_step % src_format_desc->block.height == 0);
729
730 dst_step = y_step / dst_format_desc->block.height * dst_stride;
731 src_step = y_step / src_format_desc->block.height * src_stride;
732
733 /*
734 * TODO: double formats will loose precision
735 * TODO: Add a special case for formats that are mere swizzles of each other
736 */
737
738 if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
739 dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
740 float *tmp_z = NULL;
741 uint8_t *tmp_s = NULL;
742
743 assert(x_step == 1);
744 assert(y_step == 1);
745
746 if (unpack->unpack_z_float && pack->pack_z_float) {
747 tmp_z = malloc(width * sizeof *tmp_z);
748 }
749
750 if (unpack->unpack_s_8uint && pack->pack_s_8uint) {
751 tmp_s = malloc(width * sizeof *tmp_s);
752 }
753
754 while (height--) {
755 if (tmp_z) {
756 util_format_unpack_z_float(src_format, tmp_z, src_row, width);
757 util_format_pack_z_float(dst_format, dst_row, tmp_z, width);
758 }
759
760 if (tmp_s) {
761 util_format_unpack_s_8uint(src_format, tmp_s, src_row, width);
762 util_format_pack_s_8uint(dst_format, dst_row, tmp_s, width);
763 }
764
765 dst_row += dst_step;
766 src_row += src_step;
767 }
768
769 free(tmp_s);
770
771 free(tmp_z);
772
773 return true;
774 }
775
776 if (util_format_fits_8unorm(src_format_desc) ||
777 util_format_fits_8unorm(dst_format_desc)) {
778 unsigned tmp_stride;
779 uint8_t *tmp_row;
780
781 if ((!unpack->unpack_rgba_8unorm && !unpack->unpack_rgba_8unorm_rect) ||
782 !pack->pack_rgba_8unorm) {
783 return false;
784 }
785
786 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
787 tmp_row = malloc((uint64_t)y_step * tmp_stride);
788 if (!tmp_row)
789 return false;
790
791 while (height >= y_step) {
792 util_format_unpack_rgba_8unorm_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
793 pack->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
794
795 dst_row += dst_step;
796 src_row += src_step;
797 height -= y_step;
798 }
799
800 if (height) {
801 util_format_unpack_rgba_8unorm_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
802 pack->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
803 }
804
805 free(tmp_row);
806 }
807 else if (util_format_is_pure_sint(src_format) ||
808 util_format_is_pure_sint(dst_format)) {
809 unsigned tmp_stride;
810 int *tmp_row;
811
812 if (util_format_is_pure_sint(src_format) !=
813 util_format_is_pure_sint(dst_format)) {
814 return false;
815 }
816
817 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
818 tmp_row = malloc((uint64_t)y_step * tmp_stride);
819 if (!tmp_row)
820 return false;
821
822 while (height >= y_step) {
823 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
824 pack->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
825
826 dst_row += dst_step;
827 src_row += src_step;
828 height -= y_step;
829 }
830
831 if (height) {
832 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
833 pack->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
834 }
835
836 free(tmp_row);
837 }
838 else if (util_format_is_pure_uint(src_format) ||
839 util_format_is_pure_uint(dst_format)) {
840 unsigned tmp_stride;
841 unsigned int *tmp_row;
842
843 if ((!unpack->unpack_rgba && !unpack->unpack_rgba_rect) ||
844 !pack->pack_rgba_uint) {
845 return false;
846 }
847
848 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
849 tmp_row = malloc((uint64_t)y_step * tmp_stride);
850 if (!tmp_row)
851 return false;
852
853 while (height >= y_step) {
854 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
855 pack->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
856
857 dst_row += dst_step;
858 src_row += src_step;
859 height -= y_step;
860 }
861
862 if (height) {
863 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
864 pack->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
865 }
866
867 free(tmp_row);
868 }
869 else {
870 unsigned tmp_stride;
871 float *tmp_row;
872
873 if ((!unpack->unpack_rgba && !unpack->unpack_rgba_rect) ||
874 !pack->pack_rgba_float) {
875 return false;
876 }
877
878 tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
879 tmp_row = malloc((uint64_t)y_step * tmp_stride);
880 if (!tmp_row)
881 return false;
882
883 while (height >= y_step) {
884 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
885 pack->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
886
887 dst_row += dst_step;
888 src_row += src_step;
889 height -= y_step;
890 }
891
892 if (height) {
893 util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
894 pack->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
895 }
896
897 free(tmp_row);
898 }
899 return true;
900 }
901
902 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)903 util_format_translate_3d(enum pipe_format dst_format,
904 void *dst, unsigned dst_stride,
905 uint64_t dst_slice_stride,
906 unsigned dst_x, unsigned dst_y,
907 unsigned dst_z,
908 enum pipe_format src_format,
909 const void *src, unsigned src_stride,
910 uint64_t src_slice_stride,
911 unsigned src_x, unsigned src_y,
912 unsigned src_z, unsigned width,
913 unsigned height, unsigned depth)
914 {
915 uint8_t *dst_layer;
916 const uint8_t *src_layer;
917 unsigned z;
918 dst_layer = dst;
919 src_layer = src;
920 dst_layer += dst_z * dst_slice_stride;
921 src_layer += src_z * src_slice_stride;
922 for (z = 0; z < depth; ++z) {
923 if (!util_format_translate(dst_format, dst_layer, dst_stride,
924 dst_x, dst_y,
925 src_format, src_layer, src_stride,
926 src_x, src_y,
927 width, height))
928 return false;
929
930 dst_layer += dst_slice_stride;
931 src_layer += src_slice_stride;
932 }
933 return true;
934 }
935
util_format_compose_swizzles(const unsigned char swz1[4],const unsigned char swz2[4],unsigned char dst[4])936 void util_format_compose_swizzles(const unsigned char swz1[4],
937 const unsigned char swz2[4],
938 unsigned char dst[4])
939 {
940 unsigned i;
941
942 for (i = 0; i < 4; i++) {
943 dst[i] = swz2[i] <= PIPE_SWIZZLE_W ?
944 swz1[swz2[i]] : swz2[i];
945 }
946 }
947
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)948 void util_format_apply_color_swizzle(union pipe_color_union *dst,
949 const union pipe_color_union *src,
950 const unsigned char swz[4],
951 const bool is_integer)
952 {
953 unsigned c;
954
955 if (is_integer) {
956 for (c = 0; c < 4; ++c) {
957 switch (swz[c]) {
958 case PIPE_SWIZZLE_X: dst->ui[c] = src->ui[0]; break;
959 case PIPE_SWIZZLE_Y: dst->ui[c] = src->ui[1]; break;
960 case PIPE_SWIZZLE_Z: dst->ui[c] = src->ui[2]; break;
961 case PIPE_SWIZZLE_W: dst->ui[c] = src->ui[3]; break;
962 default:
963 dst->ui[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1 : 0;
964 break;
965 }
966 }
967 } else {
968 for (c = 0; c < 4; ++c) {
969 switch (swz[c]) {
970 case PIPE_SWIZZLE_X: dst->f[c] = src->f[0]; break;
971 case PIPE_SWIZZLE_Y: dst->f[c] = src->f[1]; break;
972 case PIPE_SWIZZLE_Z: dst->f[c] = src->f[2]; break;
973 case PIPE_SWIZZLE_W: dst->f[c] = src->f[3]; break;
974 default:
975 dst->f[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1.0f : 0.0f;
976 break;
977 }
978 }
979 }
980 }
981
pipe_swizzle_4f(float * dst,const float * src,const unsigned char swz[4])982 void pipe_swizzle_4f(float *dst, const float *src,
983 const unsigned char swz[4])
984 {
985 unsigned i;
986
987 for (i = 0; i < 4; i++) {
988 if (swz[i] <= PIPE_SWIZZLE_W)
989 dst[i] = src[swz[i]];
990 else if (swz[i] == PIPE_SWIZZLE_0)
991 dst[i] = 0;
992 else if (swz[i] == PIPE_SWIZZLE_1)
993 dst[i] = 1;
994 }
995 }
996
util_format_unswizzle_4f(float * dst,const float * src,const unsigned char swz[4])997 void util_format_unswizzle_4f(float *dst, const float *src,
998 const unsigned char swz[4])
999 {
1000 unsigned i;
1001
1002 for (i = 0; i < 4; i++) {
1003 switch (swz[i]) {
1004 case PIPE_SWIZZLE_X:
1005 dst[0] = src[i];
1006 break;
1007 case PIPE_SWIZZLE_Y:
1008 dst[1] = src[i];
1009 break;
1010 case PIPE_SWIZZLE_Z:
1011 dst[2] = src[i];
1012 break;
1013 case PIPE_SWIZZLE_W:
1014 dst[3] = src[i];
1015 break;
1016 }
1017 }
1018 }
1019
1020 enum pipe_format
util_format_snorm_to_sint(enum pipe_format format)1021 util_format_snorm_to_sint(enum pipe_format format)
1022 {
1023 switch (format) {
1024 case PIPE_FORMAT_R32_SNORM:
1025 return PIPE_FORMAT_R32_SINT;
1026 case PIPE_FORMAT_R32G32_SNORM:
1027 return PIPE_FORMAT_R32G32_SINT;
1028 case PIPE_FORMAT_R32G32B32_SNORM:
1029 return PIPE_FORMAT_R32G32B32_SINT;
1030 case PIPE_FORMAT_R32G32B32A32_SNORM:
1031 return PIPE_FORMAT_R32G32B32A32_SINT;
1032
1033 case PIPE_FORMAT_R16_SNORM:
1034 return PIPE_FORMAT_R16_SINT;
1035 case PIPE_FORMAT_R16G16_SNORM:
1036 return PIPE_FORMAT_R16G16_SINT;
1037 case PIPE_FORMAT_R16G16B16_SNORM:
1038 return PIPE_FORMAT_R16G16B16_SINT;
1039 case PIPE_FORMAT_R16G16B16A16_SNORM:
1040 return PIPE_FORMAT_R16G16B16A16_SINT;
1041
1042 case PIPE_FORMAT_R8_SNORM:
1043 return PIPE_FORMAT_R8_SINT;
1044 case PIPE_FORMAT_R8G8_SNORM:
1045 return PIPE_FORMAT_R8G8_SINT;
1046 case PIPE_FORMAT_R8G8B8_SNORM:
1047 return PIPE_FORMAT_R8G8B8_SINT;
1048 case PIPE_FORMAT_B8G8R8_SNORM:
1049 return PIPE_FORMAT_B8G8R8_SINT;
1050 case PIPE_FORMAT_R8G8B8A8_SNORM:
1051 return PIPE_FORMAT_R8G8B8A8_SINT;
1052 case PIPE_FORMAT_B8G8R8A8_SNORM:
1053 return PIPE_FORMAT_B8G8R8A8_SINT;
1054
1055 case PIPE_FORMAT_R10G10B10A2_SNORM:
1056 return PIPE_FORMAT_R10G10B10A2_SINT;
1057 case PIPE_FORMAT_B10G10R10A2_SNORM:
1058 return PIPE_FORMAT_B10G10R10A2_SINT;
1059
1060 case PIPE_FORMAT_R10G10B10X2_SNORM:
1061 return PIPE_FORMAT_R10G10B10X2_SINT;
1062
1063 case PIPE_FORMAT_A8_SNORM:
1064 return PIPE_FORMAT_A8_SINT;
1065 case PIPE_FORMAT_L8_SNORM:
1066 return PIPE_FORMAT_L8_SINT;
1067 case PIPE_FORMAT_L8A8_SNORM:
1068 return PIPE_FORMAT_L8A8_SINT;
1069 case PIPE_FORMAT_I8_SNORM:
1070 return PIPE_FORMAT_I8_SINT;
1071
1072 case PIPE_FORMAT_A16_SNORM:
1073 return PIPE_FORMAT_A16_SINT;
1074 case PIPE_FORMAT_L16_SNORM:
1075 return PIPE_FORMAT_L16_SINT;
1076 case PIPE_FORMAT_L16A16_SNORM:
1077 return PIPE_FORMAT_L16A16_SINT;
1078 case PIPE_FORMAT_I16_SNORM:
1079 return PIPE_FORMAT_I16_SINT;
1080
1081 case PIPE_FORMAT_R8G8B8X8_SNORM:
1082 return PIPE_FORMAT_R8G8B8X8_SINT;
1083 case PIPE_FORMAT_R16G16B16X16_SNORM:
1084 return PIPE_FORMAT_R16G16B16X16_SINT;
1085
1086 case PIPE_FORMAT_R8A8_SNORM:
1087 return PIPE_FORMAT_R8A8_SINT;
1088 case PIPE_FORMAT_R16A16_SNORM:
1089 return PIPE_FORMAT_R16A16_SINT;
1090
1091 case PIPE_FORMAT_G8R8_SNORM:
1092 return PIPE_FORMAT_G8R8_SINT;
1093 case PIPE_FORMAT_G16R16_SNORM:
1094 return PIPE_FORMAT_G16R16_SINT;
1095
1096 case PIPE_FORMAT_A8B8G8R8_SNORM:
1097 return PIPE_FORMAT_A8B8G8R8_SINT;
1098 case PIPE_FORMAT_X8B8G8R8_SNORM:
1099 return PIPE_FORMAT_X8B8G8R8_SINT;
1100
1101 case PIPE_FORMAT_B8G8R8X8_SNORM:
1102 return PIPE_FORMAT_B8G8R8X8_SINT;
1103 case PIPE_FORMAT_A8R8G8B8_SNORM:
1104 return PIPE_FORMAT_A8R8G8B8_SINT;
1105 case PIPE_FORMAT_X8R8G8B8_SNORM:
1106 return PIPE_FORMAT_X8R8G8B8_SINT;
1107 case PIPE_FORMAT_B10G10R10X2_SNORM:
1108 return PIPE_FORMAT_B10G10R10X2_SINT;
1109
1110 default:
1111 return format;
1112 }
1113 }
1114
1115 /**
1116 * If the format is RGB, return BGR. If the format is BGR, return RGB.
1117 * This may fail by returning PIPE_FORMAT_NONE.
1118 */
1119 enum pipe_format
util_format_rgb_to_bgr(enum pipe_format format)1120 util_format_rgb_to_bgr(enum pipe_format format)
1121 {
1122 #define REMAP_RGB_ONE(r, rs, g, gs, b, bs, type) \
1123 case PIPE_FORMAT_##r##rs##g##gs##b##bs##_##type: \
1124 return PIPE_FORMAT_##b##bs##g##gs##r##rs##_##type;
1125
1126 #define REMAP_RGB(rs, gs, bs, type) \
1127 REMAP_RGB_ONE(R, rs, G, gs, B, bs, type) \
1128 REMAP_RGB_ONE(B, bs, G, gs, R, rs, type) \
1129
1130 #define REMAP_RGBA_ONE(r, rs, g, gs, b, bs, a, as, type) \
1131 case PIPE_FORMAT_##r##rs##g##gs##b##bs##a##as##_##type: \
1132 return PIPE_FORMAT_##b##bs##g##gs##r##rs##a##as##_##type;
1133
1134 #define REMAP_ARGB_ONE(a, as, r, rs, g, gs, b, bs, type) \
1135 case PIPE_FORMAT_##a##as##r##rs##g##gs##b##bs##_##type: \
1136 return PIPE_FORMAT_##a##as##b##bs##g##gs##r##rs##_##type;
1137
1138 #define REMAP_RGB_AX(A, rs, gs, bs, as, type) \
1139 REMAP_RGBA_ONE(R, rs, G, gs, B, bs, A, as, type) \
1140 REMAP_RGBA_ONE(B, bs, G, gs, R, rs, A, as, type) \
1141
1142 #define REMAP_AX_RGB(A, rs, gs, bs, as, type) \
1143 REMAP_ARGB_ONE(A, as, R, rs, G, gs, B, bs, type) \
1144 REMAP_ARGB_ONE(A, as, B, bs, G, gs, R, rs, type) \
1145
1146 #define REMAP_RGBA(rs, gs, bs, as, type) REMAP_RGB_AX(A, rs, gs, bs, as, type)
1147 #define REMAP_RGBX(rs, gs, bs, as, type) REMAP_RGB_AX(X, rs, gs, bs, as, type)
1148 #define REMAP_ARGB(rs, gs, bs, as, type) REMAP_AX_RGB(A, rs, gs, bs, as, type)
1149 #define REMAP_XRGB(rs, gs, bs, as, type) REMAP_AX_RGB(X, rs, gs, bs, as, type)
1150
1151 #define REMAP_RGBA_ALL(rs, gs, bs, as, type) \
1152 REMAP_RGBA(rs, gs, bs, as, type) \
1153 REMAP_RGBX(rs, gs, bs, as, type) \
1154 REMAP_ARGB(rs, gs, bs, as, type) \
1155 REMAP_XRGB(rs, gs, bs, as, type)
1156
1157 switch (format) {
1158 REMAP_RGB(3, 3, 2, UNORM);
1159 REMAP_RGB(3, 3, 2, UINT);
1160 REMAP_RGB(5, 6, 5, SRGB);
1161 REMAP_RGB(5, 6, 5, UNORM);
1162 REMAP_RGB(5, 6, 5, UINT);
1163 REMAP_RGB(8, 8, 8, SRGB);
1164 REMAP_RGB(8, 8, 8, UNORM);
1165 REMAP_RGB(8, 8, 8, SNORM);
1166 REMAP_RGB(8, 8, 8, UINT);
1167 REMAP_RGB(8, 8, 8, SINT);
1168 REMAP_RGB(8, 8, 8, USCALED);
1169 REMAP_RGB(8, 8, 8, SSCALED);
1170
1171 /* Complete format sets. */
1172 REMAP_RGBA_ALL(5, 5, 5, 1, UNORM);
1173 REMAP_RGBA_ALL(8, 8, 8, 8, SRGB);
1174 REMAP_RGBA_ALL(8, 8, 8, 8, UNORM);
1175 REMAP_RGBA_ALL(8, 8, 8, 8, SNORM);
1176 REMAP_RGBA_ALL(8, 8, 8, 8, SINT);
1177
1178 /* Format sets missing XRGB/XBGR. */
1179 REMAP_RGBA(4, 4, 4, 4, UNORM);
1180 REMAP_RGBX(4, 4, 4, 4, UNORM);
1181 REMAP_ARGB(4, 4, 4, 4, UNORM);
1182
1183 REMAP_RGBA(8, 8, 8, 8, UINT);
1184 REMAP_RGBX(8, 8, 8, 8, UINT);
1185 REMAP_ARGB(8, 8, 8, 8, UINT);
1186
1187 REMAP_RGBA(10, 10, 10, 2, UNORM);
1188 REMAP_RGBX(10, 10, 10, 2, UNORM);
1189 REMAP_ARGB(10, 10, 10, 2, UNORM);
1190
1191 /* Format sets missing a half of combinations. */
1192 REMAP_RGBA(4, 4, 4, 4, UINT);
1193 REMAP_ARGB(4, 4, 4, 4, UINT);
1194
1195 REMAP_RGBA(5, 5, 5, 1, UINT);
1196 REMAP_ARGB(5, 5, 5, 1, UINT);
1197
1198 REMAP_RGBA(10, 10, 10, 2, SNORM);
1199 REMAP_RGBX(10, 10, 10, 2, SNORM);
1200
1201 REMAP_RGBA(10, 10, 10, 2, UINT);
1202 REMAP_ARGB(10, 10, 10, 2, UINT);
1203
1204 REMAP_RGBA(10, 10, 10, 2, SINT);
1205 REMAP_RGBX(10, 10, 10, 2, SINT);
1206
1207 /* Format sets having only RGBA/BGRA. */
1208 REMAP_RGBA(8, 8, 8, 8, USCALED);
1209 REMAP_RGBA(8, 8, 8, 8, SSCALED);
1210 REMAP_RGBA(10, 10, 10, 2, USCALED);
1211 REMAP_RGBA(10, 10, 10, 2, SSCALED);
1212
1213 default:
1214 return PIPE_FORMAT_NONE;
1215 }
1216 }
1217
1218 static const struct util_format_unpack_description *util_format_unpack_table[PIPE_FORMAT_COUNT];
1219
1220 static void
util_format_unpack_table_init(void)1221 util_format_unpack_table_init(void)
1222 {
1223 for (enum pipe_format format = PIPE_FORMAT_NONE; format < PIPE_FORMAT_COUNT; format++) {
1224 #if (DETECT_ARCH_AARCH64 || DETECT_ARCH_ARM) && !defined(NO_FORMAT_ASM) && !defined(__SOFTFP__)
1225 const struct util_format_unpack_description *unpack = util_format_unpack_description_neon(format);
1226 if (unpack) {
1227 util_format_unpack_table[format] = unpack;
1228 continue;
1229 }
1230 #endif
1231
1232 util_format_unpack_table[format] = util_format_unpack_description_generic(format);
1233 }
1234 }
1235
1236 const struct util_format_unpack_description *
util_format_unpack_description(enum pipe_format format)1237 util_format_unpack_description(enum pipe_format format)
1238 {
1239 static once_flag flag = ONCE_FLAG_INIT;
1240 call_once(&flag, util_format_unpack_table_init);
1241
1242 return util_format_unpack_table[format];
1243 }
1244
1245 enum pipe_format
util_format_snorm_to_unorm(enum pipe_format format)1246 util_format_snorm_to_unorm(enum pipe_format format)
1247 {
1248 #define CASE(x) case PIPE_FORMAT_##x##_SNORM: return PIPE_FORMAT_##x##_UNORM
1249
1250 switch (format) {
1251 CASE(R8G8B8A8);
1252 CASE(R8G8B8X8);
1253 CASE(B8G8R8A8);
1254 CASE(B8G8R8X8);
1255 CASE(A8R8G8B8);
1256 CASE(X8R8G8B8);
1257 CASE(A8B8G8R8);
1258 CASE(X8B8G8R8);
1259
1260 CASE(R10G10B10A2);
1261 CASE(R10G10B10X2);
1262 CASE(B10G10R10A2);
1263 CASE(B10G10R10X2);
1264
1265 CASE(R8);
1266 CASE(R8G8);
1267 CASE(G8R8);
1268 CASE(R8G8B8);
1269 CASE(B8G8R8);
1270
1271 CASE(R16);
1272 CASE(R16G16);
1273 CASE(G16R16);
1274 CASE(R16G16B16);
1275
1276 CASE(R16G16B16A16);
1277 CASE(R16G16B16X16);
1278
1279 CASE(R32);
1280 CASE(R32G32);
1281 CASE(R32G32B32);
1282 CASE(R32G32B32A32);
1283
1284 CASE(RGTC1);
1285 CASE(RGTC2);
1286 CASE(ETC2_R11);
1287 CASE(ETC2_RG11);
1288
1289 CASE(A8);
1290 CASE(A16);
1291 CASE(L8);
1292 CASE(L16);
1293 CASE(I8);
1294 CASE(I16);
1295
1296 CASE(L8A8);
1297 CASE(L16A16);
1298 CASE(R8A8);
1299 CASE(R16A16);
1300
1301 CASE(LATC1);
1302 CASE(LATC2);
1303
1304 default:
1305 return format;
1306 }
1307
1308 #undef CASE
1309 }
1310
1311 enum pipe_format
util_format_rgbx_to_rgba(enum pipe_format format)1312 util_format_rgbx_to_rgba(enum pipe_format format)
1313 {
1314 switch (format) {
1315 case PIPE_FORMAT_B8G8R8X8_UNORM:
1316 return PIPE_FORMAT_B8G8R8A8_UNORM;
1317 case PIPE_FORMAT_X8B8G8R8_UNORM:
1318 return PIPE_FORMAT_A8B8G8R8_UNORM;
1319 case PIPE_FORMAT_X8R8G8B8_UNORM:
1320 return PIPE_FORMAT_A8R8G8B8_UNORM;
1321 case PIPE_FORMAT_X8B8G8R8_SRGB:
1322 return PIPE_FORMAT_A8B8G8R8_SRGB;
1323 case PIPE_FORMAT_B8G8R8X8_SRGB:
1324 return PIPE_FORMAT_B8G8R8A8_SRGB;
1325 case PIPE_FORMAT_X8R8G8B8_SRGB:
1326 return PIPE_FORMAT_A8R8G8B8_SRGB;
1327 case PIPE_FORMAT_B5G5R5X1_UNORM:
1328 return PIPE_FORMAT_B5G5R5A1_UNORM;
1329 case PIPE_FORMAT_R10G10B10X2_USCALED:
1330 return PIPE_FORMAT_R10G10B10A2_USCALED;
1331 case PIPE_FORMAT_R10G10B10X2_SNORM:
1332 return PIPE_FORMAT_R10G10B10A2_SNORM;
1333 case PIPE_FORMAT_R8G8B8X8_UNORM:
1334 return PIPE_FORMAT_R8G8B8A8_UNORM;
1335 case PIPE_FORMAT_B4G4R4X4_UNORM:
1336 return PIPE_FORMAT_B4G4R4A4_UNORM;
1337 case PIPE_FORMAT_R8G8B8X8_SNORM:
1338 return PIPE_FORMAT_R8G8B8A8_SNORM;
1339 case PIPE_FORMAT_R8G8B8X8_SRGB:
1340 return PIPE_FORMAT_R8G8B8A8_SRGB;
1341 case PIPE_FORMAT_R8G8B8X8_UINT:
1342 return PIPE_FORMAT_R8G8B8A8_UINT;
1343 case PIPE_FORMAT_R8G8B8X8_SINT:
1344 return PIPE_FORMAT_R8G8B8A8_SINT;
1345 case PIPE_FORMAT_B10G10R10X2_UNORM:
1346 return PIPE_FORMAT_B10G10R10A2_UNORM;
1347 case PIPE_FORMAT_R16G16B16X16_UNORM:
1348 return PIPE_FORMAT_R16G16B16A16_UNORM;
1349 case PIPE_FORMAT_R16G16B16X16_SNORM:
1350 return PIPE_FORMAT_R16G16B16A16_SNORM;
1351 case PIPE_FORMAT_R16G16B16X16_FLOAT:
1352 return PIPE_FORMAT_R16G16B16A16_FLOAT;
1353 case PIPE_FORMAT_R16G16B16X16_UINT:
1354 return PIPE_FORMAT_R16G16B16A16_UINT;
1355 case PIPE_FORMAT_R16G16B16X16_SINT:
1356 return PIPE_FORMAT_R16G16B16A16_SINT;
1357 case PIPE_FORMAT_R32G32B32X32_FLOAT:
1358 return PIPE_FORMAT_R32G32B32A32_FLOAT;
1359 case PIPE_FORMAT_R32G32B32X32_UINT:
1360 return PIPE_FORMAT_R32G32B32A32_UINT;
1361 case PIPE_FORMAT_R32G32B32X32_SINT:
1362 return PIPE_FORMAT_R32G32B32A32_SINT;
1363 case PIPE_FORMAT_X8B8G8R8_SNORM:
1364 return PIPE_FORMAT_A8B8G8R8_SNORM;
1365 case PIPE_FORMAT_R10G10B10X2_UNORM:
1366 return PIPE_FORMAT_R10G10B10A2_UNORM;
1367 case PIPE_FORMAT_X1B5G5R5_UNORM:
1368 return PIPE_FORMAT_A1B5G5R5_UNORM;
1369 case PIPE_FORMAT_X8B8G8R8_SINT:
1370 return PIPE_FORMAT_A8B8G8R8_SINT;
1371 case PIPE_FORMAT_B8G8R8X8_SNORM:
1372 return PIPE_FORMAT_B8G8R8A8_SNORM;
1373 case PIPE_FORMAT_B8G8R8X8_UINT:
1374 return PIPE_FORMAT_B8G8R8A8_UINT;
1375 case PIPE_FORMAT_B8G8R8X8_SINT:
1376 return PIPE_FORMAT_B8G8R8A8_SINT;
1377 case PIPE_FORMAT_X8R8G8B8_SNORM:
1378 return PIPE_FORMAT_A8R8G8B8_SNORM;
1379 case PIPE_FORMAT_X8R8G8B8_SINT:
1380 return PIPE_FORMAT_A8R8G8B8_SINT;
1381 case PIPE_FORMAT_R5G5B5X1_UNORM:
1382 return PIPE_FORMAT_R5G5B5A1_UNORM;
1383 case PIPE_FORMAT_X1R5G5B5_UNORM:
1384 return PIPE_FORMAT_A1R5G5B5_UNORM;
1385 case PIPE_FORMAT_R4G4B4X4_UNORM:
1386 return PIPE_FORMAT_R4G4B4A4_UNORM;
1387 case PIPE_FORMAT_B10G10R10X2_SNORM:
1388 return PIPE_FORMAT_B10G10R10A2_SNORM;
1389 case PIPE_FORMAT_R10G10B10X2_SINT:
1390 return PIPE_FORMAT_R10G10B10A2_SINT;
1391 case PIPE_FORMAT_B10G10R10X2_SINT:
1392 return PIPE_FORMAT_B10G10R10A2_SINT;
1393 default: {
1394 ASSERTED const struct util_format_description *desc = util_format_description(format);
1395
1396 /* Assert that the format doesn't contain X instead of A. */
1397 assert(desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS ||
1398 (desc->channel[0].type != UTIL_FORMAT_TYPE_VOID &&
1399 desc->channel[desc->nr_channels - 1].type != UTIL_FORMAT_TYPE_VOID));
1400 return format;
1401 }
1402 }
1403 }
1404
1405 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)1406 util_format_get_array(const enum util_format_type type, const unsigned bits,
1407 const unsigned nr_components, const bool normalized,
1408 const bool pure_integer)
1409 {
1410 #define CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS, NR_VAR) \
1411 case BITS: \
1412 switch (NR_VAR) { \
1413 case 1: \
1414 return PIPE_FORMAT_R##BITS##_##TYPE; \
1415 case 2: \
1416 return PIPE_FORMAT_R##BITS##G##BITS##_##TYPE; \
1417 case 3: \
1418 return PIPE_FORMAT_R##BITS##G##BITS##B##BITS##_##TYPE; \
1419 case 4: \
1420 return PIPE_FORMAT_R##BITS##G##BITS##B##BITS##A##BITS##_##TYPE; \
1421 default: \
1422 return PIPE_FORMAT_NONE; \
1423 }
1424
1425 #define SWITCH_BY_BITS_CASEX3(TYPE, BITS_VAR, BITS1, BITS2, BITS3, NR_VAR) \
1426 switch (BITS_VAR) { \
1427 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS1, NR_VAR) \
1428 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS2, NR_VAR) \
1429 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS3, NR_VAR) \
1430 default: \
1431 return PIPE_FORMAT_NONE; \
1432 }
1433
1434 #define SWITCH_BY_BITS_CASEX4(TYPE, BITS_VAR, BITS1, BITS2, BITS3, BITS4, NR_VAR) \
1435 switch (BITS_VAR) { \
1436 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS1, NR_VAR) \
1437 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS2, NR_VAR) \
1438 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS3, NR_VAR) \
1439 CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4(TYPE, BITS4, NR_VAR) \
1440 default: \
1441 return PIPE_FORMAT_NONE; \
1442 }
1443
1444 switch (type) {
1445 case UTIL_FORMAT_TYPE_UNSIGNED:
1446 if (normalized)
1447 SWITCH_BY_BITS_CASEX3(UNORM, bits, 8, 16, 32, nr_components)
1448 else if (!pure_integer)
1449 SWITCH_BY_BITS_CASEX3(USCALED, bits, 8, 16, 32, nr_components)
1450 else
1451 SWITCH_BY_BITS_CASEX4(UINT, bits, 8, 16, 32, 64, nr_components)
1452 case UTIL_FORMAT_TYPE_SIGNED:
1453 if (normalized)
1454 SWITCH_BY_BITS_CASEX3(SNORM, bits, 8, 16, 32, nr_components)
1455 else if (!pure_integer)
1456 SWITCH_BY_BITS_CASEX3(SSCALED, bits, 8, 16, 32, nr_components)
1457 else
1458 SWITCH_BY_BITS_CASEX4(SINT, bits, 8, 16, 32, 64, nr_components)
1459 case UTIL_FORMAT_TYPE_FLOAT:
1460 SWITCH_BY_BITS_CASEX3(FLOAT, bits, 16, 32, 64, nr_components)
1461 default:
1462 return PIPE_FORMAT_NONE;
1463 }
1464
1465 #undef CASE_BY_BIT_SWITCH_BY_NR_COMPONENTS_1TO4
1466 #undef SWITCH_BY_BITS_CASEX3
1467 #undef SWITCH_BY_BITS_CASEX4
1468
1469 return PIPE_FORMAT_NONE;
1470 }
1471
1472 unsigned
util_format_get_last_component(enum pipe_format format)1473 util_format_get_last_component(enum pipe_format format)
1474 {
1475 const struct util_format_description *desc = util_format_description(format);
1476 unsigned num = 0;
1477
1478 for (unsigned i = 1; i < 4; i++) {
1479 if (desc->swizzle[i] <= PIPE_SWIZZLE_W)
1480 num = i;
1481 }
1482 return num;
1483 }
1484
1485 int
util_format_get_largest_non_void_channel(enum pipe_format format)1486 util_format_get_largest_non_void_channel(enum pipe_format format)
1487 {
1488 const struct util_format_description *desc = util_format_description(format);
1489 int chan = -1, max_size = 0;
1490
1491 for (int i = 0; i < 4; i++) {
1492 if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID &&
1493 desc->channel[i].size > max_size) {
1494 chan = i;
1495 max_size = desc->channel[i].size;
1496 }
1497 }
1498
1499 return chan;
1500 }
1501
1502 unsigned
util_format_get_max_channel_size(enum pipe_format format)1503 util_format_get_max_channel_size(enum pipe_format format)
1504 {
1505 const struct util_format_description *desc = util_format_description(format);
1506 int max_src_chan = util_format_get_largest_non_void_channel(format);
1507 assert(max_src_chan >= 0 || util_format_is_compressed(format));
1508
1509 switch (format) {
1510 case PIPE_FORMAT_BPTC_RGB_FLOAT:
1511 case PIPE_FORMAT_BPTC_RGB_UFLOAT:
1512 return 16;
1513 case PIPE_FORMAT_ETC2_R11_UNORM:
1514 case PIPE_FORMAT_ETC2_R11_SNORM:
1515 case PIPE_FORMAT_ETC2_RG11_UNORM:
1516 case PIPE_FORMAT_ETC2_RG11_SNORM:
1517 return 11;
1518 default:
1519 return util_format_is_compressed(format) ?
1520 8 : desc->channel[max_src_chan].size;
1521 }
1522 }
1523
1524 static uint32_t blocksizes_64kb[5][6][3] = {
1525 /* 3D 2D 1 sample 2D 2 samples 2D 4 samples 2D 8 samples 2D 16 samples) */
1526 { { 64, 32, 32 }, { 256, 256, 1 }, { 128, 256, 1 }, { 128, 128, 1 }, { 64, 128, 1 }, { 64, 64, 1 } }, /* 8 bits */
1527 { { 32, 32, 32 }, { 256, 128, 1 }, { 128, 128, 1 }, { 128, 64, 1 }, { 64, 64, 1 }, { 64, 32, 1 } }, /* 16 bits */
1528 { { 32, 32, 16 }, { 128, 128, 1 }, { 64, 128, 1 }, { 64, 64, 1 }, { 32, 64, 1 }, { 32, 32, 1 } }, /* 32 bits */
1529 { { 32, 16, 16 }, { 128, 64, 1 }, { 64, 64, 1 }, { 64, 32, 1 }, { 32, 32, 1 }, { 32, 16, 1 } }, /* 64 bits */
1530 { { 16, 16, 16 }, { 64, 64, 1 }, { 32, 64, 1 }, { 32, 32, 1 }, { 16, 32, 1 }, { 16, 16, 1 } }, /* 128 bits */
1531 };
1532
1533 uint32_t
util_format_get_tilesize(enum pipe_format format,uint32_t dimensions,uint32_t samples,uint32_t axis)1534 util_format_get_tilesize(enum pipe_format format, uint32_t dimensions, uint32_t samples, uint32_t axis)
1535 {
1536 if (dimensions == 1)
1537 return axis == 0 ? 64 * 1024 : 1;
1538
1539 uint32_t kind = 0;
1540 if (dimensions == 2)
1541 kind = util_logbase2(samples) + 1;
1542
1543 uint32_t block_size_log2 = util_logbase2_ceil(util_format_get_blocksize(format));
1544 return blocksizes_64kb[block_size_log2][kind][axis];
1545 }
1546