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