xref: /third_party/mesa3d/src/util/format/u_format.c (revision bf215546)
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 */
49void
50util_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
97boolean
98util_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 */
113boolean
114util_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) */
125boolean
126util_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
137boolean
138util_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
154boolean
155util_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
171boolean
172util_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
193boolean
194util_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
206boolean
207util_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 */
222boolean
223util_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 */
233boolean
234util_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 */
244boolean
245util_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
264boolean
265util_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
283boolean
284util_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
301boolean
302util_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
318boolean
319util_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 */
336double
337util_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
364void
365util_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
385void
386util_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
406void
407util_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
426void
427util_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
453void
454util_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
470void
471util_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 */
514boolean
515util_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
562boolean
563util_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
640boolean
641util_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
865boolean
866util_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
899void 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
911void 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
945void 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
960void 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
983enum pipe_format
984util_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 */
1082enum pipe_format
1083util_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
1181static const struct util_format_unpack_description *util_format_unpack_table[PIPE_FORMAT_COUNT];
1182
1183static void
1184util_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
1199const struct util_format_unpack_description *
1200util_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
1208enum pipe_format
1209util_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
1274enum pipe_format
1275util_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