• 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    assert(desc);
104    if (!desc) {
105       return FALSE;
106    }
107 
108    i = util_format_get_first_non_void_channel(format);
109    if (i < 0) {
110       return FALSE;
111    }
112 
113    return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE;
114 }
115 
116 
117 /** Test if the format contains RGB, but not alpha */
118 boolean
util_format_has_alpha(enum pipe_format format)119 util_format_has_alpha(enum pipe_format format)
120 {
121    const struct util_format_description *desc =
122       util_format_description(format);
123 
124    return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
125            desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
126           desc->swizzle[3] != PIPE_SWIZZLE_1;
127 }
128 
129 /** Test if format has alpha as 1 (like RGBX) */
130 boolean
util_format_has_alpha1(enum pipe_format format)131 util_format_has_alpha1(enum pipe_format format)
132 {
133    const struct util_format_description *desc =
134       util_format_description(format);
135 
136    return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
137            desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
138            desc->nr_channels == 4 &&
139            desc->swizzle[3] == PIPE_SWIZZLE_1;
140 }
141 
142 boolean
util_format_is_luminance(enum pipe_format format)143 util_format_is_luminance(enum pipe_format format)
144 {
145    const struct util_format_description *desc =
146       util_format_description(format);
147 
148    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
149         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
150        desc->swizzle[0] == PIPE_SWIZZLE_X &&
151        desc->swizzle[1] == PIPE_SWIZZLE_X &&
152        desc->swizzle[2] == PIPE_SWIZZLE_X &&
153        desc->swizzle[3] == PIPE_SWIZZLE_1) {
154       return TRUE;
155    }
156    return FALSE;
157 }
158 
159 boolean
util_format_is_alpha(enum pipe_format format)160 util_format_is_alpha(enum pipe_format format)
161 {
162    const struct util_format_description *desc =
163       util_format_description(format);
164 
165    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
166         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
167        desc->swizzle[0] == PIPE_SWIZZLE_0 &&
168        desc->swizzle[1] == PIPE_SWIZZLE_0 &&
169        desc->swizzle[2] == PIPE_SWIZZLE_0 &&
170        desc->swizzle[3] == PIPE_SWIZZLE_X) {
171       return TRUE;
172    }
173    return FALSE;
174 }
175 
176 boolean
util_format_is_pure_integer(enum pipe_format format)177 util_format_is_pure_integer(enum pipe_format format)
178 {
179    const struct util_format_description *desc = util_format_description(format);
180    int i;
181 
182    /* Find the first non-void channel. */
183    i = util_format_get_first_non_void_channel(format);
184    if (i == -1)
185       return FALSE;
186 
187    return desc->channel[i].pure_integer ? TRUE : FALSE;
188 }
189 
190 boolean
util_format_is_pure_sint(enum pipe_format format)191 util_format_is_pure_sint(enum pipe_format format)
192 {
193    const struct util_format_description *desc = util_format_description(format);
194    int i;
195 
196    i = util_format_get_first_non_void_channel(format);
197    if (i == -1)
198       return FALSE;
199 
200    return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
201 }
202 
203 boolean
util_format_is_pure_uint(enum pipe_format format)204 util_format_is_pure_uint(enum pipe_format format)
205 {
206    const struct util_format_description *desc = util_format_description(format);
207    int i;
208 
209    i = util_format_get_first_non_void_channel(format);
210    if (i == -1)
211       return FALSE;
212 
213    return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
214 }
215 
216 /**
217  * Returns true if the format contains normalized signed channels.
218  */
219 boolean
util_format_is_snorm(enum pipe_format format)220 util_format_is_snorm(enum pipe_format format)
221 {
222    const struct util_format_description *desc = util_format_description(format);
223 
224    return desc->is_snorm;
225 }
226 
227 /**
228  * Returns true if the format contains normalized unsigned channels.
229  */
230 boolean
util_format_is_unorm(enum pipe_format format)231 util_format_is_unorm(enum pipe_format format)
232 {
233    const struct util_format_description *desc = util_format_description(format);
234 
235    return desc->is_unorm;
236 }
237 
238 /**
239  * Returns true if the format contains scaled integer format channels.
240  */
241 boolean
util_format_is_scaled(enum pipe_format format)242 util_format_is_scaled(enum pipe_format format)
243 {
244    const struct util_format_description *desc = util_format_description(format);
245    int i;
246 
247    /* format none is described as scaled but not for this check */
248    if (format == PIPE_FORMAT_NONE)
249       return FALSE;
250 
251    /* Find the first non-void channel. */
252    i = util_format_get_first_non_void_channel(format);
253    if (i == -1)
254       return FALSE;
255 
256    return !desc->channel[i].pure_integer && !desc->channel[i].normalized &&
257       (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED ||
258        desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
259 }
260 
261 boolean
util_format_is_snorm8(enum pipe_format format)262 util_format_is_snorm8(enum pipe_format format)
263 {
264    const struct util_format_description *desc = util_format_description(format);
265    int i;
266 
267    if (desc->is_mixed)
268       return FALSE;
269 
270    i = util_format_get_first_non_void_channel(format);
271    if (i == -1)
272       return FALSE;
273 
274    return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
275           !desc->channel[i].pure_integer &&
276           desc->channel[i].normalized &&
277           desc->channel[i].size == 8;
278 }
279 
280 boolean
util_format_is_luminance_alpha(enum pipe_format format)281 util_format_is_luminance_alpha(enum pipe_format format)
282 {
283    const struct util_format_description *desc =
284       util_format_description(format);
285 
286    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
287         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
288        desc->swizzle[0] == PIPE_SWIZZLE_X &&
289        desc->swizzle[1] == PIPE_SWIZZLE_X &&
290        desc->swizzle[2] == PIPE_SWIZZLE_X &&
291        desc->swizzle[3] == PIPE_SWIZZLE_Y) {
292       return TRUE;
293    }
294    return FALSE;
295 }
296 
297 
298 boolean
util_format_is_intensity(enum pipe_format format)299 util_format_is_intensity(enum pipe_format format)
300 {
301    const struct util_format_description *desc =
302       util_format_description(format);
303 
304    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
305         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
306        desc->swizzle[0] == PIPE_SWIZZLE_X &&
307        desc->swizzle[1] == PIPE_SWIZZLE_X &&
308        desc->swizzle[2] == PIPE_SWIZZLE_X &&
309        desc->swizzle[3] == PIPE_SWIZZLE_X) {
310       return TRUE;
311    }
312    return FALSE;
313 }
314 
315 boolean
util_format_is_subsampled_422(enum pipe_format format)316 util_format_is_subsampled_422(enum pipe_format format)
317 {
318    const struct util_format_description *desc =
319       util_format_description(format);
320 
321    return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED &&
322       desc->block.width == 2 &&
323       desc->block.height == 1 &&
324       desc->block.bits == 32;
325 }
326 
327 /**
328  * Calculates the MRD for the depth format. MRD is used in depth bias
329  * for UNORM and unbound depth buffers. When the depth buffer is floating
330  * point, the depth bias calculation does not use the MRD. However, the
331  * default MRD will be 1.0 / ((1 << 24) - 1).
332  */
333 double
util_get_depth_format_mrd(const struct util_format_description * desc)334 util_get_depth_format_mrd(const struct util_format_description *desc)
335 {
336    /*
337     * Depth buffer formats without a depth component OR scenarios
338     * without a bound depth buffer default to D24.
339     */
340    double mrd = 1.0 / ((1 << 24) - 1);
341    unsigned depth_channel;
342 
343    assert(desc);
344 
345    /*
346     * Some depth formats do not store the depth component in the first
347     * channel, detect the format and adjust the depth channel. Get the
348     * swizzled depth component channel.
349     */
350    depth_channel = desc->swizzle[0];
351 
352    if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
353        desc->channel[depth_channel].normalized) {
354       int depth_bits;
355 
356       depth_bits = desc->channel[depth_channel].size;
357       mrd = 1.0 / ((1ULL << depth_bits) - 1);
358    }
359 
360    return mrd;
361 }
362 
363 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)364 util_format_unpack_rgba_rect(enum pipe_format format,
365                    void *dst, unsigned dst_stride,
366                    const void *src, unsigned src_stride,
367                    unsigned w, unsigned h)
368 {
369    const struct util_format_unpack_description *unpack =
370       util_format_unpack_description(format);
371 
372    /* Optimized function for block-compressed formats */
373    if (unpack->unpack_rgba_rect) {
374       unpack->unpack_rgba_rect(dst, dst_stride, src, src_stride, w, h);
375    } else {
376      for (unsigned y = 0; y < h; y++) {
377         unpack->unpack_rgba(dst, src, w);
378         src = (const char *)src + src_stride;
379         dst = (char *)dst + dst_stride;
380      }
381   }
382 }
383 
384 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)385 util_format_unpack_rgba_8unorm_rect(enum pipe_format format,
386                    void *dst, unsigned dst_stride,
387                    const void *src, unsigned src_stride,
388                    unsigned w, unsigned h)
389 {
390    const struct util_format_unpack_description *unpack =
391       util_format_unpack_description(format);
392 
393    /* Optimized function for block-compressed formats */
394    if (unpack->unpack_rgba_8unorm_rect) {
395       unpack->unpack_rgba_8unorm_rect(dst, dst_stride, src, src_stride, w, h);
396    } else {
397      for (unsigned y = 0; y < h; y++) {
398         unpack->unpack_rgba_8unorm(dst, src, w);
399         src = (const char *)src + src_stride;
400         dst = (char *)dst + dst_stride;
401      }
402   }
403 }
404 
405 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)406 util_format_read_4(enum pipe_format format,
407                    void *dst, unsigned dst_stride,
408                    const void *src, unsigned src_stride,
409                    unsigned x, unsigned y, unsigned w, unsigned h)
410 {
411    const struct util_format_description *format_desc;
412    const uint8_t *src_row;
413 
414    format_desc = util_format_description(format);
415 
416    assert(x % format_desc->block.width == 0);
417    assert(y % format_desc->block.height == 0);
418 
419    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
420 
421    util_format_unpack_rgba_rect(format, dst, dst_stride, src_row, src_stride, w, h);
422 }
423 
424 
425 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)426 util_format_write_4(enum pipe_format format,
427                      const void *src, unsigned src_stride,
428                      void *dst, unsigned dst_stride,
429                      unsigned x, unsigned y, unsigned w, unsigned h)
430 {
431    const struct util_format_description *format_desc;
432    const struct util_format_pack_description *pack =
433       util_format_pack_description(format);
434    uint8_t *dst_row;
435 
436    format_desc = util_format_description(format);
437 
438    assert(x % format_desc->block.width == 0);
439    assert(y % format_desc->block.height == 0);
440 
441    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
442 
443    if (util_format_is_pure_uint(format))
444       pack->pack_rgba_uint(dst_row, dst_stride, src, src_stride, w, h);
445    else if (util_format_is_pure_sint(format))
446       pack->pack_rgba_sint(dst_row, dst_stride, src, src_stride, w, h);
447    else
448       pack->pack_rgba_float(dst_row, dst_stride, src, src_stride, w, h);
449 }
450 
451 
452 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)453 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 {
455    const struct util_format_description *format_desc;
456    const uint8_t *src_row;
457 
458    format_desc = util_format_description(format);
459 
460    assert(x % format_desc->block.width == 0);
461    assert(y % format_desc->block.height == 0);
462 
463    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
464 
465    util_format_unpack_rgba_8unorm_rect(format, dst, dst_stride, src_row, src_stride, w, h);
466 }
467 
468 
469 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)470 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 {
472    const struct util_format_description *format_desc;
473    const struct util_format_pack_description *pack =
474       util_format_pack_description(format);
475    uint8_t *dst_row;
476    const uint8_t *src_row;
477 
478    format_desc = util_format_description(format);
479 
480    assert(x % format_desc->block.width == 0);
481    assert(y % format_desc->block.height == 0);
482 
483    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
484    src_row = src;
485 
486    pack->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
487 }
488 
489 /**
490  * Check if we can safely memcopy from the source format to the dest format.
491  * This basically covers the cases of a "used" channel copied to a typeless
492  * channel, plus some 1-channel cases.
493  * Examples of compatible copy formats include:
494  *    b8g8r8a8_unorm -> b8g8r8x8_unorm
495  *    a8r8g8b8_unorm -> x8r8g8b8_unorm
496  *    b5g5r5a1_unorm -> b5g5r5x1_unorm
497  *    b4g4r4a4_unorm -> b4g4r4x4_unorm
498  *    l8_unorm -> r8_unorm
499  *    i8_unorm -> l8_unorm
500  *    i8_unorm -> a8_unorm
501  *    i8_unorm -> r8_unorm
502  *    l16_unorm -> r16_unorm
503  *    z24_unorm_s8_uint -> z24x8_unorm
504  *    s8_uint_z24_unorm -> x8z24_unorm
505  *    r8g8b8a8_unorm -> r8g8b8x8_unorm
506  *    a8b8g8r8_srgb -> x8b8g8r8_srgb
507  *    b8g8r8a8_srgb -> b8g8r8x8_srgb
508  *    a8r8g8b8_srgb -> x8r8g8b8_srgb
509  *    a8b8g8r8_unorm -> x8b8g8r8_unorm
510  *    r10g10b10a2_uscaled -> r10g10b10x2_uscaled
511  *    r10sg10sb10sa2u_norm -> r10g10b10x2_snorm
512  */
513 boolean
util_is_format_compatible(const struct util_format_description * src_desc,const struct util_format_description * dst_desc)514 util_is_format_compatible(const struct util_format_description *src_desc,
515                           const struct util_format_description *dst_desc)
516 {
517    unsigned chan;
518 
519    if (src_desc->format == dst_desc->format) {
520       return TRUE;
521    }
522 
523    if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
524        dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
525       return FALSE;
526    }
527 
528    if (src_desc->block.bits != dst_desc->block.bits ||
529        src_desc->nr_channels != dst_desc->nr_channels ||
530        src_desc->colorspace != dst_desc->colorspace) {
531       return FALSE;
532    }
533 
534    for (chan = 0; chan < 4; ++chan) {
535       if (src_desc->channel[chan].size !=
536           dst_desc->channel[chan].size) {
537          return FALSE;
538       }
539    }
540 
541    for (chan = 0; chan < 4; ++chan) {
542       enum pipe_swizzle swizzle = dst_desc->swizzle[chan];
543 
544       if (swizzle < 4) {
545          if (src_desc->swizzle[chan] != swizzle) {
546             return FALSE;
547          }
548          if ((src_desc->channel[swizzle].type !=
549               dst_desc->channel[swizzle].type) ||
550              (src_desc->channel[swizzle].normalized !=
551               dst_desc->channel[swizzle].normalized)) {
552             return FALSE;
553          }
554       }
555    }
556 
557    return TRUE;
558 }
559 
560 
561 boolean
util_format_fits_8unorm(const struct util_format_description * format_desc)562 util_format_fits_8unorm(const struct util_format_description *format_desc)
563 {
564    unsigned chan;
565 
566    /*
567     * After linearized sRGB values require more than 8bits.
568     */
569 
570    if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
571       return FALSE;
572    }
573 
574    switch (format_desc->layout) {
575 
576    case UTIL_FORMAT_LAYOUT_S3TC:
577       /*
578        * These are straight forward.
579        */
580       return TRUE;
581    case UTIL_FORMAT_LAYOUT_RGTC:
582       if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
583           format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
584           format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
585           format_desc->format == PIPE_FORMAT_LATC2_SNORM)
586          return FALSE;
587       return TRUE;
588    case UTIL_FORMAT_LAYOUT_BPTC:
589       if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM)
590          return TRUE;
591       return FALSE;
592 
593    case UTIL_FORMAT_LAYOUT_ETC:
594       if (format_desc->format == PIPE_FORMAT_ETC1_RGB8)
595          return TRUE;
596       return FALSE;
597 
598    case UTIL_FORMAT_LAYOUT_PLAIN:
599       /*
600        * For these we can find a generic rule.
601        */
602 
603       for (chan = 0; chan < format_desc->nr_channels; ++chan) {
604          switch (format_desc->channel[chan].type) {
605          case UTIL_FORMAT_TYPE_VOID:
606             break;
607          case UTIL_FORMAT_TYPE_UNSIGNED:
608             if (!format_desc->channel[chan].normalized ||
609                 format_desc->channel[chan].size > 8) {
610                return FALSE;
611             }
612             break;
613          default:
614             return FALSE;
615          }
616       }
617       return TRUE;
618 
619    default:
620       /*
621        * Handle all others on a case by case basis.
622        */
623 
624       switch (format_desc->format) {
625       case PIPE_FORMAT_R1_UNORM:
626       case PIPE_FORMAT_UYVY:
627       case PIPE_FORMAT_YUYV:
628       case PIPE_FORMAT_R8G8_B8G8_UNORM:
629       case PIPE_FORMAT_G8R8_G8B8_UNORM:
630          return TRUE;
631 
632       default:
633          return FALSE;
634       }
635    }
636 }
637 
638 
639 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)640 util_format_translate(enum pipe_format dst_format,
641                       void *dst, unsigned dst_stride,
642                       unsigned dst_x, unsigned dst_y,
643                       enum pipe_format src_format,
644                       const void *src, unsigned src_stride,
645                       unsigned src_x, unsigned src_y,
646                       unsigned width, unsigned height)
647 {
648    const struct util_format_description *dst_format_desc;
649    const struct util_format_description *src_format_desc;
650    const struct util_format_pack_description *pack =
651       util_format_pack_description(dst_format);
652    const struct util_format_unpack_description *unpack =
653       util_format_unpack_description(src_format);
654    uint8_t *dst_row;
655    const uint8_t *src_row;
656    unsigned x_step, y_step;
657    unsigned dst_step;
658    unsigned src_step;
659 
660    dst_format_desc = util_format_description(dst_format);
661    src_format_desc = util_format_description(src_format);
662 
663    if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
664       /*
665        * Trivial case.
666        */
667 
668       util_copy_rect(dst, dst_format, dst_stride,  dst_x, dst_y,
669                      width, height, src, (int)src_stride,
670                      src_x, src_y);
671       return TRUE;
672    }
673 
674    assert(dst_x % dst_format_desc->block.width == 0);
675    assert(dst_y % dst_format_desc->block.height == 0);
676    assert(src_x % src_format_desc->block.width == 0);
677    assert(src_y % src_format_desc->block.height == 0);
678 
679    dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
680    src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8);
681 
682    /*
683     * This works because all pixel formats have pixel blocks with power of two
684     * sizes.
685     */
686 
687    y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
688    x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
689    assert(y_step % dst_format_desc->block.height == 0);
690    assert(y_step % src_format_desc->block.height == 0);
691 
692    dst_step = y_step / dst_format_desc->block.height * dst_stride;
693    src_step = y_step / src_format_desc->block.height * src_stride;
694 
695    /*
696     * TODO: double formats will loose precision
697     * TODO: Add a special case for formats that are mere swizzles of each other
698     */
699 
700    if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
701        dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
702       float *tmp_z = NULL;
703       uint8_t *tmp_s = NULL;
704 
705       assert(x_step == 1);
706       assert(y_step == 1);
707 
708       if (unpack->unpack_z_float && pack->pack_z_float) {
709          tmp_z = malloc(width * sizeof *tmp_z);
710       }
711 
712       if (unpack->unpack_s_8uint && pack->pack_s_8uint) {
713          tmp_s = malloc(width * sizeof *tmp_s);
714       }
715 
716       while (height--) {
717          if (tmp_z) {
718             util_format_unpack_z_float(src_format, tmp_z, src_row, width);
719             util_format_pack_z_float(dst_format, dst_row, tmp_z, width);
720          }
721 
722          if (tmp_s) {
723             util_format_unpack_s_8uint(src_format, tmp_s, src_row, width);
724             util_format_pack_s_8uint(dst_format, dst_row, tmp_s, width);
725          }
726 
727          dst_row += dst_step;
728          src_row += src_step;
729       }
730 
731       free(tmp_s);
732 
733       free(tmp_z);
734 
735       return TRUE;
736    }
737 
738    if (util_format_fits_8unorm(src_format_desc) ||
739        util_format_fits_8unorm(dst_format_desc)) {
740       unsigned tmp_stride;
741       uint8_t *tmp_row;
742 
743       if ((!unpack->unpack_rgba_8unorm && !unpack->unpack_rgba_8unorm_rect) ||
744           !pack->pack_rgba_8unorm) {
745          return FALSE;
746       }
747 
748       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
749       tmp_row = malloc(y_step * tmp_stride);
750       if (!tmp_row)
751          return FALSE;
752 
753       while (height >= y_step) {
754          util_format_unpack_rgba_8unorm_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
755          pack->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
756 
757          dst_row += dst_step;
758          src_row += src_step;
759          height -= y_step;
760       }
761 
762       if (height) {
763          util_format_unpack_rgba_8unorm_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
764          pack->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
765       }
766 
767       free(tmp_row);
768    }
769    else if (util_format_is_pure_sint(src_format) ||
770             util_format_is_pure_sint(dst_format)) {
771       unsigned tmp_stride;
772       int *tmp_row;
773 
774       if (util_format_is_pure_sint(src_format) !=
775           util_format_is_pure_sint(dst_format)) {
776          return FALSE;
777       }
778 
779       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
780       tmp_row = malloc(y_step * tmp_stride);
781       if (!tmp_row)
782          return FALSE;
783 
784       while (height >= y_step) {
785          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
786          pack->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
787 
788          dst_row += dst_step;
789          src_row += src_step;
790          height -= y_step;
791       }
792 
793       if (height) {
794          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
795          pack->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
796       }
797 
798       free(tmp_row);
799    }
800    else if (util_format_is_pure_uint(src_format) ||
801             util_format_is_pure_uint(dst_format)) {
802       unsigned tmp_stride;
803       unsigned int *tmp_row;
804 
805       if ((!unpack->unpack_rgba && !unpack->unpack_rgba_rect) ||
806           !pack->pack_rgba_uint) {
807          return FALSE;
808       }
809 
810       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
811       tmp_row = malloc(y_step * tmp_stride);
812       if (!tmp_row)
813          return FALSE;
814 
815       while (height >= y_step) {
816          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
817          pack->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
818 
819          dst_row += dst_step;
820          src_row += src_step;
821          height -= y_step;
822       }
823 
824       if (height) {
825          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
826          pack->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
827       }
828 
829       free(tmp_row);
830    }
831    else {
832       unsigned tmp_stride;
833       float *tmp_row;
834 
835       if ((!unpack->unpack_rgba && !unpack->unpack_rgba_rect) ||
836           !pack->pack_rgba_float) {
837          return FALSE;
838       }
839 
840       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
841       tmp_row = malloc(y_step * tmp_stride);
842       if (!tmp_row)
843          return FALSE;
844 
845       while (height >= y_step) {
846          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, y_step);
847          pack->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
848 
849          dst_row += dst_step;
850          src_row += src_step;
851          height -= y_step;
852       }
853 
854       if (height) {
855          util_format_unpack_rgba_rect(src_format, tmp_row, tmp_stride, src_row, src_stride, width, height);
856          pack->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
857       }
858 
859       free(tmp_row);
860    }
861    return TRUE;
862 }
863 
864 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)865 util_format_translate_3d(enum pipe_format dst_format,
866                          void *dst, unsigned dst_stride,
867                          unsigned dst_slice_stride,
868                          unsigned dst_x, unsigned dst_y,
869                          unsigned dst_z,
870                          enum pipe_format src_format,
871                          const void *src, unsigned src_stride,
872                          unsigned src_slice_stride,
873                          unsigned src_x, unsigned src_y,
874                          unsigned src_z, unsigned width,
875                          unsigned height, unsigned depth)
876 {
877    uint8_t *dst_layer;
878    const uint8_t *src_layer;
879    unsigned z;
880    dst_layer = dst;
881    src_layer = src;
882    dst_layer += dst_z * dst_slice_stride;
883    src_layer += src_z * src_slice_stride;
884    for (z = 0; z < depth; ++z) {
885       if (!util_format_translate(dst_format, dst_layer, dst_stride,
886                                  dst_x, dst_y,
887                                  src_format, src_layer, src_stride,
888                                  src_x, src_y,
889                                  width, height))
890           return FALSE;
891 
892       dst_layer += dst_slice_stride;
893       src_layer += src_slice_stride;
894    }
895    return TRUE;
896 }
897 
util_format_compose_swizzles(const unsigned char swz1[4],const unsigned char swz2[4],unsigned char dst[4])898 void util_format_compose_swizzles(const unsigned char swz1[4],
899                                   const unsigned char swz2[4],
900                                   unsigned char dst[4])
901 {
902    unsigned i;
903 
904    for (i = 0; i < 4; i++) {
905       dst[i] = swz2[i] <= PIPE_SWIZZLE_W ?
906                swz1[swz2[i]] : swz2[i];
907    }
908 }
909 
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)910 void util_format_apply_color_swizzle(union pipe_color_union *dst,
911                                      const union pipe_color_union *src,
912                                      const unsigned char swz[4],
913                                      const boolean is_integer)
914 {
915    unsigned c;
916 
917    if (is_integer) {
918       for (c = 0; c < 4; ++c) {
919          switch (swz[c]) {
920          case PIPE_SWIZZLE_X:   dst->ui[c] = src->ui[0]; break;
921          case PIPE_SWIZZLE_Y: dst->ui[c] = src->ui[1]; break;
922          case PIPE_SWIZZLE_Z:  dst->ui[c] = src->ui[2]; break;
923          case PIPE_SWIZZLE_W: dst->ui[c] = src->ui[3]; break;
924          default:
925             dst->ui[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1 : 0;
926             break;
927          }
928       }
929    } else {
930       for (c = 0; c < 4; ++c) {
931          switch (swz[c]) {
932          case PIPE_SWIZZLE_X:   dst->f[c] = src->f[0]; break;
933          case PIPE_SWIZZLE_Y: dst->f[c] = src->f[1]; break;
934          case PIPE_SWIZZLE_Z:  dst->f[c] = src->f[2]; break;
935          case PIPE_SWIZZLE_W: dst->f[c] = src->f[3]; break;
936          default:
937             dst->f[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1.0f : 0.0f;
938             break;
939          }
940       }
941    }
942 }
943 
pipe_swizzle_4f(float * dst,const float * src,const unsigned char swz[4])944 void pipe_swizzle_4f(float *dst, const float *src,
945                             const unsigned char swz[4])
946 {
947    unsigned i;
948 
949    for (i = 0; i < 4; i++) {
950       if (swz[i] <= PIPE_SWIZZLE_W)
951          dst[i] = src[swz[i]];
952       else if (swz[i] == PIPE_SWIZZLE_0)
953          dst[i] = 0;
954       else if (swz[i] == PIPE_SWIZZLE_1)
955          dst[i] = 1;
956    }
957 }
958 
util_format_unswizzle_4f(float * dst,const float * src,const unsigned char swz[4])959 void util_format_unswizzle_4f(float *dst, const float *src,
960                               const unsigned char swz[4])
961 {
962    unsigned i;
963 
964    for (i = 0; i < 4; i++) {
965       switch (swz[i]) {
966       case PIPE_SWIZZLE_X:
967          dst[0] = src[i];
968          break;
969       case PIPE_SWIZZLE_Y:
970          dst[1] = src[i];
971          break;
972       case PIPE_SWIZZLE_Z:
973          dst[2] = src[i];
974          break;
975       case PIPE_SWIZZLE_W:
976          dst[3] = src[i];
977          break;
978       }
979    }
980 }
981 
982 enum pipe_format
util_format_snorm8_to_sint8(enum pipe_format format)983 util_format_snorm8_to_sint8(enum pipe_format format)
984 {
985    switch (format) {
986    case PIPE_FORMAT_R8_SNORM:
987       return PIPE_FORMAT_R8_SINT;
988    case PIPE_FORMAT_R8G8_SNORM:
989       return PIPE_FORMAT_R8G8_SINT;
990    case PIPE_FORMAT_R8G8B8_SNORM:
991       return PIPE_FORMAT_R8G8B8_SINT;
992    case PIPE_FORMAT_R8G8B8A8_SNORM:
993       return PIPE_FORMAT_R8G8B8A8_SINT;
994 
995    case PIPE_FORMAT_A8_SNORM:
996       return PIPE_FORMAT_A8_SINT;
997    case PIPE_FORMAT_L8_SNORM:
998       return PIPE_FORMAT_L8_SINT;
999    case PIPE_FORMAT_L8A8_SNORM:
1000       return PIPE_FORMAT_L8A8_SINT;
1001    case PIPE_FORMAT_I8_SNORM:
1002       return PIPE_FORMAT_I8_SINT;
1003 
1004    case PIPE_FORMAT_R8G8B8X8_SNORM:
1005       return PIPE_FORMAT_R8G8B8X8_SINT;
1006    case PIPE_FORMAT_B8G8R8X8_SNORM:
1007       return PIPE_FORMAT_B8G8R8X8_SINT;
1008 
1009    case PIPE_FORMAT_R8A8_SNORM:
1010       return PIPE_FORMAT_R8A8_SINT;
1011    case PIPE_FORMAT_G8R8_SNORM:
1012       return PIPE_FORMAT_G8R8_SINT;
1013 
1014    case PIPE_FORMAT_A8R8G8B8_SNORM:
1015       return PIPE_FORMAT_A8R8G8B8_SINT;
1016    case PIPE_FORMAT_X8R8G8B8_SNORM:
1017       return PIPE_FORMAT_X8R8G8B8_SINT;
1018 
1019    case PIPE_FORMAT_A8B8G8R8_SNORM:
1020       return PIPE_FORMAT_A8B8G8R8_SINT;
1021    case PIPE_FORMAT_X8B8G8R8_SNORM:
1022       return PIPE_FORMAT_X8B8G8R8_SINT;
1023 
1024    case PIPE_FORMAT_R10G10B10A2_SNORM:
1025       return PIPE_FORMAT_R10G10B10A2_SINT;
1026    case PIPE_FORMAT_B10G10R10A2_SNORM:
1027       return PIPE_FORMAT_B10G10R10A2_SINT;
1028 
1029    default:
1030       return format;
1031    }
1032 }
1033 
1034 /**
1035  * If the format is RGB, return BGR. If the format is BGR, return RGB.
1036  * This may fail by returning PIPE_FORMAT_NONE.
1037  */
1038 enum pipe_format
util_format_rgb_to_bgr(enum pipe_format format)1039 util_format_rgb_to_bgr(enum pipe_format format)
1040 {
1041 #define REMAP_RGB_ONE(r, rs, g, gs, b, bs, type) \
1042    case PIPE_FORMAT_##r##rs##g##gs##b##bs##_##type: \
1043       return PIPE_FORMAT_##b##bs##g##gs##r##rs##_##type;
1044 
1045 #define REMAP_RGB(rs, gs, bs, type) \
1046    REMAP_RGB_ONE(R, rs, G, gs, B, bs, type) \
1047    REMAP_RGB_ONE(B, bs, G, gs, R, rs, type) \
1048 
1049 #define REMAP_RGBA_ONE(r, rs, g, gs, b, bs, a, as, type) \
1050    case PIPE_FORMAT_##r##rs##g##gs##b##bs##a##as##_##type: \
1051       return PIPE_FORMAT_##b##bs##g##gs##r##rs##a##as##_##type;
1052 
1053 #define REMAP_ARGB_ONE(a, as, r, rs, g, gs, b, bs, type) \
1054    case PIPE_FORMAT_##a##as##r##rs##g##gs##b##bs##_##type: \
1055       return PIPE_FORMAT_##a##as##b##bs##g##gs##r##rs##_##type;
1056 
1057 #define REMAP_RGB_AX(A, rs, gs, bs, as, type) \
1058    REMAP_RGBA_ONE(R, rs, G, gs, B, bs, A, as, type) \
1059    REMAP_RGBA_ONE(B, bs, G, gs, R, rs, A, as, type) \
1060 
1061 #define REMAP_AX_RGB(A, rs, gs, bs, as, type) \
1062    REMAP_ARGB_ONE(A, as, R, rs, G, gs, B, bs, type) \
1063    REMAP_ARGB_ONE(A, as, B, bs, G, gs, R, rs, type) \
1064 
1065 #define REMAP_RGBA(rs, gs, bs, as, type) REMAP_RGB_AX(A, rs, gs, bs, as, type)
1066 #define REMAP_RGBX(rs, gs, bs, as, type) REMAP_RGB_AX(X, rs, gs, bs, as, type)
1067 #define REMAP_ARGB(rs, gs, bs, as, type) REMAP_AX_RGB(A, rs, gs, bs, as, type)
1068 #define REMAP_XRGB(rs, gs, bs, as, type) REMAP_AX_RGB(X, rs, gs, bs, as, type)
1069 
1070 #define REMAP_RGBA_ALL(rs, gs, bs, as, type) \
1071    REMAP_RGBA(rs, gs, bs, as, type) \
1072    REMAP_RGBX(rs, gs, bs, as, type) \
1073    REMAP_ARGB(rs, gs, bs, as, type) \
1074    REMAP_XRGB(rs, gs, bs, as, type)
1075 
1076    switch (format) {
1077    REMAP_RGB(3, 3, 2, UNORM);
1078    REMAP_RGB(3, 3, 2, UINT);
1079    REMAP_RGB(5, 6, 5, SRGB);
1080    REMAP_RGB(5, 6, 5, UNORM);
1081    REMAP_RGB(5, 6, 5, UINT);
1082    REMAP_RGB(8, 8, 8, SRGB);
1083    REMAP_RGB(8, 8, 8, UNORM);
1084    REMAP_RGB(8, 8, 8, SNORM);
1085    REMAP_RGB(8, 8, 8, UINT);
1086    REMAP_RGB(8, 8, 8, SINT);
1087    REMAP_RGB(8, 8, 8, USCALED);
1088    REMAP_RGB(8, 8, 8, SSCALED);
1089 
1090    /* Complete format sets. */
1091    REMAP_RGBA_ALL(5, 5, 5, 1, UNORM);
1092    REMAP_RGBA_ALL(8, 8, 8, 8, SRGB);
1093    REMAP_RGBA_ALL(8, 8, 8, 8, UNORM);
1094    REMAP_RGBA_ALL(8, 8, 8, 8, SNORM);
1095    REMAP_RGBA_ALL(8, 8, 8, 8, SINT);
1096 
1097    /* Format sets missing XRGB/XBGR. */
1098    REMAP_RGBA(4, 4, 4, 4, UNORM);
1099    REMAP_RGBX(4, 4, 4, 4, UNORM);
1100    REMAP_ARGB(4, 4, 4, 4, UNORM);
1101 
1102    REMAP_RGBA(8, 8, 8, 8, UINT);
1103    REMAP_RGBX(8, 8, 8, 8, UINT);
1104    REMAP_ARGB(8, 8, 8, 8, UINT);
1105 
1106    REMAP_RGBA(10, 10, 10, 2, UNORM);
1107    REMAP_RGBX(10, 10, 10, 2, UNORM);
1108    REMAP_ARGB(10, 10, 10, 2, UNORM);
1109 
1110    /* Format sets missing a half of combinations. */
1111    REMAP_RGBA(4, 4, 4, 4, UINT);
1112    REMAP_ARGB(4, 4, 4, 4, UINT);
1113 
1114    REMAP_RGBA(5, 5, 5, 1, UINT);
1115    REMAP_ARGB(5, 5, 5, 1, UINT);
1116 
1117    REMAP_RGBA(10, 10, 10, 2, SNORM);
1118    REMAP_RGBX(10, 10, 10, 2, SNORM);
1119 
1120    REMAP_RGBA(10, 10, 10, 2, UINT);
1121    REMAP_ARGB(10, 10, 10, 2, UINT);
1122 
1123    /* Format sets having only RGBA/BGRA. */
1124    REMAP_RGBA(8, 8, 8, 8, USCALED);
1125    REMAP_RGBA(8, 8, 8, 8, SSCALED);
1126    REMAP_RGBA(10, 10, 10, 2, SINT);
1127    REMAP_RGBA(10, 10, 10, 2, USCALED);
1128    REMAP_RGBA(10, 10, 10, 2, SSCALED);
1129 
1130    default:
1131       return PIPE_FORMAT_NONE;
1132    }
1133 }
1134 
1135 static const struct util_format_unpack_description *util_format_unpack_table[PIPE_FORMAT_COUNT];
1136 
1137 static void
util_format_unpack_table_init(void)1138 util_format_unpack_table_init(void)
1139 {
1140    for (enum pipe_format format = PIPE_FORMAT_NONE; format < PIPE_FORMAT_COUNT; format++) {
1141 #if (defined(PIPE_ARCH_AARCH64) || defined(PIPE_ARCH_ARM)) && !defined(NO_FORMAT_ASM) && !defined(__SOFTFP__)
1142       const struct util_format_unpack_description *unpack = util_format_unpack_description_neon(format);
1143       if (unpack) {
1144          util_format_unpack_table[format] = unpack;
1145          continue;
1146       }
1147 #endif
1148 
1149       util_format_unpack_table[format] = util_format_unpack_description_generic(format);
1150    }
1151 }
1152 
1153 const struct util_format_unpack_description *
util_format_unpack_description(enum pipe_format format)1154 util_format_unpack_description(enum pipe_format format)
1155 {
1156    static once_flag flag = ONCE_FLAG_INIT;
1157    call_once(&flag, util_format_unpack_table_init);
1158 
1159    return util_format_unpack_table[format];
1160 }
1161