• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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