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/u_memory.h"
36#include "u_format.h"
37#include "u_format_s3tc.h"
38#include "u_surface.h"
39#include "util/u_math.h"
40
41#include "pipe/p_defines.h"
42
43
44boolean
45util_format_is_float(enum pipe_format format)
46{
47   const struct util_format_description *desc = util_format_description(format);
48   int i;
49
50   assert(desc);
51   if (!desc) {
52      return FALSE;
53   }
54
55   i = util_format_get_first_non_void_channel(format);
56   if (i < 0) {
57      return FALSE;
58   }
59
60   return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE;
61}
62
63
64/** Test if the format contains RGB, but not alpha */
65boolean
66util_format_has_alpha(enum pipe_format format)
67{
68   const struct util_format_description *desc =
69      util_format_description(format);
70
71   return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
72           desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
73          desc->swizzle[3] != PIPE_SWIZZLE_1;
74}
75
76
77boolean
78util_format_is_luminance(enum pipe_format format)
79{
80   const struct util_format_description *desc =
81      util_format_description(format);
82
83   if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
84        desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
85       desc->swizzle[0] == PIPE_SWIZZLE_X &&
86       desc->swizzle[1] == PIPE_SWIZZLE_X &&
87       desc->swizzle[2] == PIPE_SWIZZLE_X &&
88       desc->swizzle[3] == PIPE_SWIZZLE_1) {
89      return TRUE;
90   }
91   return FALSE;
92}
93
94boolean
95util_format_is_alpha(enum pipe_format format)
96{
97   const struct util_format_description *desc =
98      util_format_description(format);
99
100   if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
101        desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
102       desc->swizzle[0] == PIPE_SWIZZLE_0 &&
103       desc->swizzle[1] == PIPE_SWIZZLE_0 &&
104       desc->swizzle[2] == PIPE_SWIZZLE_0 &&
105       desc->swizzle[3] == PIPE_SWIZZLE_X) {
106      return TRUE;
107   }
108   return FALSE;
109}
110
111boolean
112util_format_is_pure_integer(enum pipe_format format)
113{
114   const struct util_format_description *desc = util_format_description(format);
115   int i;
116
117   /* Find the first non-void channel. */
118   i = util_format_get_first_non_void_channel(format);
119   if (i == -1)
120      return FALSE;
121
122   return desc->channel[i].pure_integer ? TRUE : FALSE;
123}
124
125boolean
126util_format_is_pure_sint(enum pipe_format format)
127{
128   const struct util_format_description *desc = util_format_description(format);
129   int i;
130
131   i = util_format_get_first_non_void_channel(format);
132   if (i == -1)
133      return FALSE;
134
135   return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
136}
137
138boolean
139util_format_is_pure_uint(enum pipe_format format)
140{
141   const struct util_format_description *desc = util_format_description(format);
142   int i;
143
144   i = util_format_get_first_non_void_channel(format);
145   if (i == -1)
146      return FALSE;
147
148   return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
149}
150
151/**
152 * Returns true if the format contains normalized signed channels.
153 */
154boolean
155util_format_is_snorm(enum pipe_format format)
156{
157   const struct util_format_description *desc = util_format_description(format);
158
159   return desc->is_snorm;
160}
161
162/**
163 * Returns true if the format contains normalized unsigned channels.
164 */
165boolean
166util_format_is_unorm(enum pipe_format format)
167{
168   const struct util_format_description *desc = util_format_description(format);
169
170   return desc->is_unorm;
171}
172
173boolean
174util_format_is_snorm8(enum pipe_format format)
175{
176   const struct util_format_description *desc = util_format_description(format);
177   int i;
178
179   if (desc->is_mixed)
180      return FALSE;
181
182   i = util_format_get_first_non_void_channel(format);
183   if (i == -1)
184      return FALSE;
185
186   return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
187          !desc->channel[i].pure_integer &&
188          desc->channel[i].normalized &&
189          desc->channel[i].size == 8;
190}
191
192boolean
193util_format_is_luminance_alpha(enum pipe_format format)
194{
195   const struct util_format_description *desc =
196      util_format_description(format);
197
198   if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
199        desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
200       desc->swizzle[0] == PIPE_SWIZZLE_X &&
201       desc->swizzle[1] == PIPE_SWIZZLE_X &&
202       desc->swizzle[2] == PIPE_SWIZZLE_X &&
203       desc->swizzle[3] == PIPE_SWIZZLE_Y) {
204      return TRUE;
205   }
206   return FALSE;
207}
208
209
210boolean
211util_format_is_intensity(enum pipe_format format)
212{
213   const struct util_format_description *desc =
214      util_format_description(format);
215
216   if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
217        desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
218       desc->swizzle[0] == PIPE_SWIZZLE_X &&
219       desc->swizzle[1] == PIPE_SWIZZLE_X &&
220       desc->swizzle[2] == PIPE_SWIZZLE_X &&
221       desc->swizzle[3] == PIPE_SWIZZLE_X) {
222      return TRUE;
223   }
224   return FALSE;
225}
226
227boolean
228util_format_is_subsampled_422(enum pipe_format format)
229{
230   const struct util_format_description *desc =
231      util_format_description(format);
232
233   return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED &&
234      desc->block.width == 2 &&
235      desc->block.height == 1 &&
236      desc->block.bits == 32;
237}
238
239/**
240 * Calculates the MRD for the depth format. MRD is used in depth bias
241 * for UNORM and unbound depth buffers. When the depth buffer is floating
242 * point, the depth bias calculation does not use the MRD. However, the
243 * default MRD will be 1.0 / ((1 << 24) - 1).
244 */
245double
246util_get_depth_format_mrd(const struct util_format_description *desc)
247{
248   /*
249    * Depth buffer formats without a depth component OR scenarios
250    * without a bound depth buffer default to D24.
251    */
252   double mrd = 1.0 / ((1 << 24) - 1);
253   unsigned depth_channel;
254
255   assert(desc);
256
257   /*
258    * Some depth formats do not store the depth component in the first
259    * channel, detect the format and adjust the depth channel. Get the
260    * swizzled depth component channel.
261    */
262   depth_channel = desc->swizzle[0];
263
264   if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
265       desc->channel[depth_channel].normalized) {
266      int depth_bits;
267
268      depth_bits = desc->channel[depth_channel].size;
269      mrd = 1.0 / ((1ULL << depth_bits) - 1);
270   }
271
272   return mrd;
273}
274
275
276void
277util_format_read_4f(enum pipe_format format,
278                    float *dst, unsigned dst_stride,
279                    const void *src, unsigned src_stride,
280                    unsigned x, unsigned y, unsigned w, unsigned h)
281{
282   const struct util_format_description *format_desc;
283   const uint8_t *src_row;
284   float *dst_row;
285
286   format_desc = util_format_description(format);
287
288   assert(x % format_desc->block.width == 0);
289   assert(y % format_desc->block.height == 0);
290
291   src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
292   dst_row = dst;
293
294   format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
295}
296
297
298void
299util_format_write_4f(enum pipe_format format,
300                     const float *src, unsigned src_stride,
301                     void *dst, unsigned dst_stride,
302                     unsigned x, unsigned y, unsigned w, unsigned h)
303{
304   const struct util_format_description *format_desc;
305   uint8_t *dst_row;
306   const float *src_row;
307
308   format_desc = util_format_description(format);
309
310   assert(x % format_desc->block.width == 0);
311   assert(y % format_desc->block.height == 0);
312
313   dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
314   src_row = src;
315
316   format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
317}
318
319
320void
321util_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)
322{
323   const struct util_format_description *format_desc;
324   const uint8_t *src_row;
325   uint8_t *dst_row;
326
327   format_desc = util_format_description(format);
328
329   assert(x % format_desc->block.width == 0);
330   assert(y % format_desc->block.height == 0);
331
332   src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
333   dst_row = dst;
334
335   format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
336}
337
338
339void
340util_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)
341{
342   const struct util_format_description *format_desc;
343   uint8_t *dst_row;
344   const uint8_t *src_row;
345
346   format_desc = util_format_description(format);
347
348   assert(x % format_desc->block.width == 0);
349   assert(y % format_desc->block.height == 0);
350
351   dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
352   src_row = src;
353
354   format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
355}
356
357void
358util_format_read_4ui(enum pipe_format format,
359                     unsigned *dst, unsigned dst_stride,
360                     const void *src, unsigned src_stride,
361                     unsigned x, unsigned y, unsigned w, unsigned h)
362{
363   const struct util_format_description *format_desc;
364   const uint8_t *src_row;
365   uint32_t *dst_row;
366
367   format_desc = util_format_description(format);
368
369   assert(x % format_desc->block.width == 0);
370   assert(y % format_desc->block.height == 0);
371
372   src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
373   dst_row = dst;
374
375   format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
376}
377
378void
379util_format_write_4ui(enum pipe_format format,
380                      const unsigned int *src, unsigned src_stride,
381                      void *dst, unsigned dst_stride,
382                      unsigned x, unsigned y, unsigned w, unsigned h)
383{
384   const struct util_format_description *format_desc;
385   uint8_t *dst_row;
386   const uint32_t *src_row;
387
388   format_desc = util_format_description(format);
389
390   assert(x % format_desc->block.width == 0);
391   assert(y % format_desc->block.height == 0);
392
393   dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
394   src_row = src;
395
396   format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
397}
398
399void
400util_format_read_4i(enum pipe_format format,
401                    int *dst, unsigned dst_stride,
402                    const void *src, unsigned src_stride,
403                    unsigned x, unsigned y, unsigned w, unsigned h)
404{
405   const struct util_format_description *format_desc;
406   const uint8_t *src_row;
407   int32_t *dst_row;
408
409   format_desc = util_format_description(format);
410
411   assert(x % format_desc->block.width == 0);
412   assert(y % format_desc->block.height == 0);
413
414   src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
415   dst_row = dst;
416
417   format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
418}
419
420void
421util_format_write_4i(enum pipe_format format,
422                      const int *src, unsigned src_stride,
423                      void *dst, unsigned dst_stride,
424                      unsigned x, unsigned y, unsigned w, unsigned h)
425{
426   const struct util_format_description *format_desc;
427   uint8_t *dst_row;
428   const int32_t *src_row;
429
430   format_desc = util_format_description(format);
431
432   assert(x % format_desc->block.width == 0);
433   assert(y % format_desc->block.height == 0);
434
435   dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
436   src_row = src;
437
438   format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
439}
440
441/**
442 * Check if we can safely memcopy from the source format to the dest format.
443 * This basically covers the cases of a "used" channel copied to a typeless
444 * channel, plus some 1-channel cases.
445 * Examples of compatible copy formats include:
446 *    b8g8r8a8_unorm -> b8g8r8x8_unorm
447 *    a8r8g8b8_unorm -> x8r8g8b8_unorm
448 *    b5g5r5a1_unorm -> b5g5r5x1_unorm
449 *    b4g4r4a4_unorm -> b4g4r4x4_unorm
450 *    l8_unorm -> r8_unorm
451 *    i8_unorm -> l8_unorm
452 *    i8_unorm -> a8_unorm
453 *    i8_unorm -> r8_unorm
454 *    l16_unorm -> r16_unorm
455 *    z24_unorm_s8_uint -> z24x8_unorm
456 *    s8_uint_z24_unorm -> x8z24_unorm
457 *    r8g8b8a8_unorm -> r8g8b8x8_unorm
458 *    a8b8g8r8_srgb -> x8b8g8r8_srgb
459 *    b8g8r8a8_srgb -> b8g8r8x8_srgb
460 *    a8r8g8b8_srgb -> x8r8g8b8_srgb
461 *    a8b8g8r8_unorm -> x8b8g8r8_unorm
462 *    r10g10b10a2_uscaled -> r10g10b10x2_uscaled
463 *    r10sg10sb10sa2u_norm -> r10g10b10x2_snorm
464 */
465boolean
466util_is_format_compatible(const struct util_format_description *src_desc,
467                          const struct util_format_description *dst_desc)
468{
469   unsigned chan;
470
471   if (src_desc->format == dst_desc->format) {
472      return TRUE;
473   }
474
475   if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
476       dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
477      return FALSE;
478   }
479
480   if (src_desc->block.bits != dst_desc->block.bits ||
481       src_desc->nr_channels != dst_desc->nr_channels ||
482       src_desc->colorspace != dst_desc->colorspace) {
483      return FALSE;
484   }
485
486   for (chan = 0; chan < 4; ++chan) {
487      if (src_desc->channel[chan].size !=
488          dst_desc->channel[chan].size) {
489         return FALSE;
490      }
491   }
492
493   for (chan = 0; chan < 4; ++chan) {
494      enum pipe_swizzle swizzle = dst_desc->swizzle[chan];
495
496      if (swizzle < 4) {
497         if (src_desc->swizzle[chan] != swizzle) {
498            return FALSE;
499         }
500         if ((src_desc->channel[swizzle].type !=
501              dst_desc->channel[swizzle].type) ||
502             (src_desc->channel[swizzle].normalized !=
503              dst_desc->channel[swizzle].normalized)) {
504            return FALSE;
505         }
506      }
507   }
508
509   return TRUE;
510}
511
512
513boolean
514util_format_fits_8unorm(const struct util_format_description *format_desc)
515{
516   unsigned chan;
517
518   /*
519    * After linearized sRGB values require more than 8bits.
520    */
521
522   if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
523      return FALSE;
524   }
525
526   switch (format_desc->layout) {
527
528   case UTIL_FORMAT_LAYOUT_S3TC:
529      /*
530       * These are straight forward.
531       */
532      return TRUE;
533   case UTIL_FORMAT_LAYOUT_RGTC:
534      if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
535          format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
536          format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
537          format_desc->format == PIPE_FORMAT_LATC2_SNORM)
538         return FALSE;
539      return TRUE;
540   case UTIL_FORMAT_LAYOUT_BPTC:
541      if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM)
542         return TRUE;
543      return FALSE;
544
545   case UTIL_FORMAT_LAYOUT_ETC:
546      if (format_desc->format == PIPE_FORMAT_ETC1_RGB8)
547         return TRUE;
548      return FALSE;
549
550   case UTIL_FORMAT_LAYOUT_PLAIN:
551      /*
552       * For these we can find a generic rule.
553       */
554
555      for (chan = 0; chan < format_desc->nr_channels; ++chan) {
556         switch (format_desc->channel[chan].type) {
557         case UTIL_FORMAT_TYPE_VOID:
558            break;
559         case UTIL_FORMAT_TYPE_UNSIGNED:
560            if (!format_desc->channel[chan].normalized ||
561                format_desc->channel[chan].size > 8) {
562               return FALSE;
563            }
564            break;
565         default:
566            return FALSE;
567         }
568      }
569      return TRUE;
570
571   default:
572      /*
573       * Handle all others on a case by case basis.
574       */
575
576      switch (format_desc->format) {
577      case PIPE_FORMAT_R1_UNORM:
578      case PIPE_FORMAT_UYVY:
579      case PIPE_FORMAT_YUYV:
580      case PIPE_FORMAT_R8G8_B8G8_UNORM:
581      case PIPE_FORMAT_G8R8_G8B8_UNORM:
582         return TRUE;
583
584      default:
585         return FALSE;
586      }
587   }
588}
589
590
591boolean
592util_format_translate(enum pipe_format dst_format,
593                      void *dst, unsigned dst_stride,
594                      unsigned dst_x, unsigned dst_y,
595                      enum pipe_format src_format,
596                      const void *src, unsigned src_stride,
597                      unsigned src_x, unsigned src_y,
598                      unsigned width, unsigned height)
599{
600   const struct util_format_description *dst_format_desc;
601   const struct util_format_description *src_format_desc;
602   uint8_t *dst_row;
603   const uint8_t *src_row;
604   unsigned x_step, y_step;
605   unsigned dst_step;
606   unsigned src_step;
607
608   dst_format_desc = util_format_description(dst_format);
609   src_format_desc = util_format_description(src_format);
610
611   if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
612      /*
613       * Trivial case.
614       */
615
616      util_copy_rect(dst, dst_format, dst_stride,  dst_x, dst_y,
617                     width, height, src, (int)src_stride,
618                     src_x, src_y);
619      return TRUE;
620   }
621
622   assert(dst_x % dst_format_desc->block.width == 0);
623   assert(dst_y % dst_format_desc->block.height == 0);
624   assert(src_x % src_format_desc->block.width == 0);
625   assert(src_y % src_format_desc->block.height == 0);
626
627   dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
628   src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8);
629
630   /*
631    * This works because all pixel formats have pixel blocks with power of two
632    * sizes.
633    */
634
635   y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
636   x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
637   assert(y_step % dst_format_desc->block.height == 0);
638   assert(y_step % src_format_desc->block.height == 0);
639
640   dst_step = y_step / dst_format_desc->block.height * dst_stride;
641   src_step = y_step / src_format_desc->block.height * src_stride;
642
643   /*
644    * TODO: double formats will loose precision
645    * TODO: Add a special case for formats that are mere swizzles of each other
646    */
647
648   if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
649       dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
650      float *tmp_z = NULL;
651      uint8_t *tmp_s = NULL;
652
653      assert(x_step == 1);
654      assert(y_step == 1);
655
656      if (src_format_desc->unpack_z_float &&
657          dst_format_desc->pack_z_float) {
658         tmp_z = MALLOC(width * sizeof *tmp_z);
659      }
660
661      if (src_format_desc->unpack_s_8uint &&
662          dst_format_desc->pack_s_8uint) {
663         tmp_s = MALLOC(width * sizeof *tmp_s);
664      }
665
666      while (height--) {
667         if (tmp_z) {
668            src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1);
669            dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1);
670         }
671
672         if (tmp_s) {
673            src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1);
674            dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1);
675         }
676
677         dst_row += dst_step;
678         src_row += src_step;
679      }
680
681      FREE(tmp_s);
682
683      FREE(tmp_z);
684
685      return TRUE;
686   }
687
688   if (util_format_fits_8unorm(src_format_desc) ||
689       util_format_fits_8unorm(dst_format_desc)) {
690      unsigned tmp_stride;
691      uint8_t *tmp_row;
692
693      if (!src_format_desc->unpack_rgba_8unorm ||
694          !dst_format_desc->pack_rgba_8unorm) {
695         return FALSE;
696      }
697
698      tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
699      tmp_row = MALLOC(y_step * tmp_stride);
700      if (!tmp_row)
701         return FALSE;
702
703      while (height >= y_step) {
704         src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
705         dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
706
707         dst_row += dst_step;
708         src_row += src_step;
709         height -= y_step;
710      }
711
712      if (height) {
713         src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height);
714         dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
715      }
716
717      FREE(tmp_row);
718   }
719   else if (util_format_is_pure_sint(src_format) ||
720            util_format_is_pure_sint(dst_format)) {
721      unsigned tmp_stride;
722      int *tmp_row;
723
724      if (!src_format_desc->unpack_rgba_sint ||
725          !dst_format_desc->pack_rgba_sint) {
726         return FALSE;
727      }
728
729      tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
730      tmp_row = MALLOC(y_step * tmp_stride);
731      if (!tmp_row)
732         return FALSE;
733
734      while (height >= y_step) {
735         src_format_desc->unpack_rgba_sint(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
736         dst_format_desc->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
737
738         dst_row += dst_step;
739         src_row += src_step;
740         height -= y_step;
741      }
742
743      if (height) {
744         src_format_desc->unpack_rgba_sint(tmp_row, tmp_stride, src_row, src_stride, width, height);
745         dst_format_desc->pack_rgba_sint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
746      }
747
748      FREE(tmp_row);
749   }
750   else if (util_format_is_pure_uint(src_format) ||
751            util_format_is_pure_uint(dst_format)) {
752      unsigned tmp_stride;
753      unsigned int *tmp_row;
754
755      if (!src_format_desc->unpack_rgba_uint ||
756          !dst_format_desc->pack_rgba_uint) {
757         return FALSE;
758      }
759
760      tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
761      tmp_row = MALLOC(y_step * tmp_stride);
762      if (!tmp_row)
763         return FALSE;
764
765      while (height >= y_step) {
766         src_format_desc->unpack_rgba_uint(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
767         dst_format_desc->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
768
769         dst_row += dst_step;
770         src_row += src_step;
771         height -= y_step;
772      }
773
774      if (height) {
775         src_format_desc->unpack_rgba_uint(tmp_row, tmp_stride, src_row, src_stride, width, height);
776         dst_format_desc->pack_rgba_uint(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
777      }
778
779      FREE(tmp_row);
780   }
781   else {
782      unsigned tmp_stride;
783      float *tmp_row;
784
785      if (!src_format_desc->unpack_rgba_float ||
786          !dst_format_desc->pack_rgba_float) {
787         return FALSE;
788      }
789
790      tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
791      tmp_row = MALLOC(y_step * tmp_stride);
792      if (!tmp_row)
793         return FALSE;
794
795      while (height >= y_step) {
796         src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
797         dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
798
799         dst_row += dst_step;
800         src_row += src_step;
801         height -= y_step;
802      }
803
804      if (height) {
805         src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height);
806         dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
807      }
808
809      FREE(tmp_row);
810   }
811   return TRUE;
812}
813
814boolean
815util_format_translate_3d(enum pipe_format dst_format,
816                         void *dst, unsigned dst_stride,
817                         unsigned dst_slice_stride,
818                         unsigned dst_x, unsigned dst_y,
819                         unsigned dst_z,
820                         enum pipe_format src_format,
821                         const void *src, unsigned src_stride,
822                         unsigned src_slice_stride,
823                         unsigned src_x, unsigned src_y,
824                         unsigned src_z, unsigned width,
825                         unsigned height, unsigned depth)
826{
827   uint8_t *dst_layer;
828   const uint8_t *src_layer;
829   unsigned z;
830   dst_layer = dst;
831   src_layer = src;
832   dst_layer += dst_z * dst_slice_stride;
833   src_layer += src_z * src_slice_stride;
834   for (z = 0; z < depth; ++z) {
835      if (!util_format_translate(dst_format, dst_layer, dst_stride,
836                                 dst_x, dst_y,
837                                 src_format, src_layer, src_stride,
838                                 src_x, src_y,
839                                 width, height))
840          return FALSE;
841
842      dst_layer += dst_slice_stride;
843      src_layer += src_slice_stride;
844   }
845   return TRUE;
846}
847
848void util_format_compose_swizzles(const unsigned char swz1[4],
849                                  const unsigned char swz2[4],
850                                  unsigned char dst[4])
851{
852   unsigned i;
853
854   for (i = 0; i < 4; i++) {
855      dst[i] = swz2[i] <= PIPE_SWIZZLE_W ?
856               swz1[swz2[i]] : swz2[i];
857   }
858}
859
860void util_format_apply_color_swizzle(union pipe_color_union *dst,
861                                     const union pipe_color_union *src,
862                                     const unsigned char swz[4],
863                                     const boolean is_integer)
864{
865   unsigned c;
866
867   if (is_integer) {
868      for (c = 0; c < 4; ++c) {
869         switch (swz[c]) {
870         case PIPE_SWIZZLE_X:   dst->ui[c] = src->ui[0]; break;
871         case PIPE_SWIZZLE_Y: dst->ui[c] = src->ui[1]; break;
872         case PIPE_SWIZZLE_Z:  dst->ui[c] = src->ui[2]; break;
873         case PIPE_SWIZZLE_W: dst->ui[c] = src->ui[3]; break;
874         default:
875            dst->ui[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1 : 0;
876            break;
877         }
878      }
879   } else {
880      for (c = 0; c < 4; ++c) {
881         switch (swz[c]) {
882         case PIPE_SWIZZLE_X:   dst->f[c] = src->f[0]; break;
883         case PIPE_SWIZZLE_Y: dst->f[c] = src->f[1]; break;
884         case PIPE_SWIZZLE_Z:  dst->f[c] = src->f[2]; break;
885         case PIPE_SWIZZLE_W: dst->f[c] = src->f[3]; break;
886         default:
887            dst->f[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1.0f : 0.0f;
888            break;
889         }
890      }
891   }
892}
893
894void pipe_swizzle_4f(float *dst, const float *src,
895                            const unsigned char swz[4])
896{
897   unsigned i;
898
899   for (i = 0; i < 4; i++) {
900      if (swz[i] <= PIPE_SWIZZLE_W)
901         dst[i] = src[swz[i]];
902      else if (swz[i] == PIPE_SWIZZLE_0)
903         dst[i] = 0;
904      else if (swz[i] == PIPE_SWIZZLE_1)
905         dst[i] = 1;
906   }
907}
908
909void util_format_unswizzle_4f(float *dst, const float *src,
910                              const unsigned char swz[4])
911{
912   unsigned i;
913
914   for (i = 0; i < 4; i++) {
915      switch (swz[i]) {
916      case PIPE_SWIZZLE_X:
917         dst[0] = src[i];
918         break;
919      case PIPE_SWIZZLE_Y:
920         dst[1] = src[i];
921         break;
922      case PIPE_SWIZZLE_Z:
923         dst[2] = src[i];
924         break;
925      case PIPE_SWIZZLE_W:
926         dst[3] = src[i];
927         break;
928      }
929   }
930}
931
932enum pipe_format
933util_format_snorm8_to_sint8(enum pipe_format format)
934{
935   switch (format) {
936   case PIPE_FORMAT_R8_SNORM:
937      return PIPE_FORMAT_R8_SINT;
938   case PIPE_FORMAT_R8G8_SNORM:
939      return PIPE_FORMAT_R8G8_SINT;
940   case PIPE_FORMAT_R8G8B8_SNORM:
941      return PIPE_FORMAT_R8G8B8_SINT;
942   case PIPE_FORMAT_R8G8B8A8_SNORM:
943      return PIPE_FORMAT_R8G8B8A8_SINT;
944
945   case PIPE_FORMAT_A8_SNORM:
946      return PIPE_FORMAT_A8_SINT;
947   case PIPE_FORMAT_L8_SNORM:
948      return PIPE_FORMAT_L8_SINT;
949   case PIPE_FORMAT_L8A8_SNORM:
950      return PIPE_FORMAT_L8A8_SINT;
951   case PIPE_FORMAT_I8_SNORM:
952      return PIPE_FORMAT_I8_SINT;
953
954   case PIPE_FORMAT_R8G8B8X8_SNORM:
955      return PIPE_FORMAT_R8G8B8X8_SINT;
956   case PIPE_FORMAT_R8A8_SNORM:
957      return PIPE_FORMAT_R8A8_SINT;
958   case PIPE_FORMAT_A8L8_SNORM:
959      return PIPE_FORMAT_A8L8_SINT;
960   case PIPE_FORMAT_G8R8_SNORM:
961      return PIPE_FORMAT_G8R8_SINT;
962   case PIPE_FORMAT_A8B8G8R8_SNORM:
963      return PIPE_FORMAT_A8B8G8R8_SINT;
964   case PIPE_FORMAT_X8B8G8R8_SNORM:
965      return PIPE_FORMAT_X8B8G8R8_SINT;
966
967   default:
968      return format;
969   }
970}
971