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