1/**************************************************************************
2 *
3 * Copyright 2010 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28/**
29 * @file
30 * Pixel format accessor functions.
31 *
32 * @author Jose Fonseca <jfonseca@vmware.com>
33 */
34
35#include "util/format/u_format.h"
36#include "util/format/u_format_s3tc.h"
37#include "util/u_cpu_detect.h"
38#include "util/u_math.h"
39
40#include "pipe/p_defines.h"
41#include "pipe/p_screen.h"
42
43
44/**
45 * Copy 2D rect from one place to another.
46 * Position and sizes are in pixels.
47 * src_stride may be negative to do vertical flip of pixels from source.
48 */
49void
50util_copy_rect(ubyte * dst,
51               enum pipe_format format,
52               unsigned dst_stride,
53               unsigned dst_x,
54               unsigned dst_y,
55               unsigned width,
56               unsigned height,
57               const ubyte * src,
58               int src_stride,
59               unsigned src_x,
60               unsigned src_y)
61{
62   unsigned i;
63   int src_stride_pos = src_stride < 0 ? -src_stride : src_stride;
64   int blocksize = util_format_get_blocksize(format);
65   int blockwidth = util_format_get_blockwidth(format);
66   int blockheight = util_format_get_blockheight(format);
67
68   assert(blocksize > 0);
69   assert(blockwidth > 0);
70   assert(blockheight > 0);
71
72   dst_x /= blockwidth;
73   dst_y /= blockheight;
74   width = (width + blockwidth - 1)/blockwidth;
75   height = (height + blockheight - 1)/blockheight;
76   src_x /= blockwidth;
77   src_y /= blockheight;
78
79   dst += dst_x * blocksize;
80   src += src_x * blocksize;
81   dst += dst_y * dst_stride;
82   src += src_y * src_stride_pos;
83   width *= blocksize;
84
85   if (width == dst_stride && width == (unsigned)src_stride)
86      memcpy(dst, src, height * width);
87   else {
88      for (i = 0; i < height; i++) {
89         memcpy(dst, src, width);
90         dst += dst_stride;
91         src += src_stride;
92      }
93   }
94}
95
96
97boolean
98util_format_is_float(enum pipe_format format)
99{
100   const struct util_format_description *desc = util_format_description(format);
101   int i;
102
103   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 */
118boolean
119util_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) */
130boolean
131util_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
142boolean
143util_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
159boolean
160util_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
176boolean
177util_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
190boolean
191util_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
203boolean
204util_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 */
219boolean
220util_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 */
230boolean
231util_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 */
241boolean
242util_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
261boolean
262util_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
280boolean
281util_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
298boolean
299util_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
315boolean
316util_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 */
333double
334util_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
363void
364util_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
384void
385util_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
405void
406util_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
425void
426util_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
452void
453util_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
469void
470util_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 */
513boolean
514util_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
561boolean
562util_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
639boolean
640util_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
864boolean
865util_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
898void 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
910void 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
944void 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
959void 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
982enum pipe_format
983util_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 */
1038enum pipe_format
1039util_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
1135static const struct util_format_unpack_description *util_format_unpack_table[PIPE_FORMAT_COUNT];
1136
1137static void
1138util_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
1153const struct util_format_unpack_description *
1154util_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