• Home
  • History
  • Annotate
  • 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 "u_math.h"
36  #include "u_memory.h"
37  #include "u_rect.h"
38  #include "u_format.h"
39  #include "u_format_s3tc.h"
40  
41  #include "pipe/p_defines.h"
42  
43  
44  boolean
util_format_is_float(enum pipe_format format)45  util_format_is_float(enum pipe_format format)
46  {
47     const struct util_format_description *desc = util_format_description(format);
48     unsigned 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 == -1) {
57        return FALSE;
58     }
59  
60     return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE;
61  }
62  
63  
64  /**
65   * Return the number of logical channels in the given format by
66   * examining swizzles.
67   * XXX this could be made into a public function if useful elsewhere.
68   */
69  static unsigned
nr_logical_channels(const struct util_format_description * desc)70  nr_logical_channels(const struct util_format_description *desc)
71  {
72     boolean swizzle_used[UTIL_FORMAT_SWIZZLE_MAX];
73  
74     memset(swizzle_used, 0, sizeof(swizzle_used));
75  
76     swizzle_used[desc->swizzle[0]] = TRUE;
77     swizzle_used[desc->swizzle[1]] = TRUE;
78     swizzle_used[desc->swizzle[2]] = TRUE;
79     swizzle_used[desc->swizzle[3]] = TRUE;
80  
81     return (swizzle_used[UTIL_FORMAT_SWIZZLE_X] +
82             swizzle_used[UTIL_FORMAT_SWIZZLE_Y] +
83             swizzle_used[UTIL_FORMAT_SWIZZLE_Z] +
84             swizzle_used[UTIL_FORMAT_SWIZZLE_W]);
85  }
86  
87  
88  /** Test if the format contains RGB, but not alpha */
89  boolean
util_format_is_rgb_no_alpha(enum pipe_format format)90  util_format_is_rgb_no_alpha(enum pipe_format format)
91  {
92     const struct util_format_description *desc =
93        util_format_description(format);
94  
95     if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
96          desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
97         nr_logical_channels(desc) == 3) {
98        return TRUE;
99     }
100     return FALSE;
101  }
102  
103  
104  boolean
util_format_is_luminance(enum pipe_format format)105  util_format_is_luminance(enum pipe_format format)
106  {
107     const struct util_format_description *desc =
108        util_format_description(format);
109  
110     if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
111          desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
112         desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
113         desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
114         desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
115         desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1) {
116        return TRUE;
117     }
118     return FALSE;
119  }
120  
121  boolean
util_format_is_pure_integer(enum pipe_format format)122  util_format_is_pure_integer(enum pipe_format format)
123  {
124     const struct util_format_description *desc = util_format_description(format);
125     int i;
126  
127     /* Find the first non-void channel. */
128     i = util_format_get_first_non_void_channel(format);
129     if (i == -1)
130        return FALSE;
131  
132     return desc->channel[i].pure_integer ? TRUE : FALSE;
133  }
134  
135  boolean
util_format_is_pure_sint(enum pipe_format format)136  util_format_is_pure_sint(enum pipe_format format)
137  {
138     const struct util_format_description *desc = util_format_description(format);
139     int i;
140  
141     i = util_format_get_first_non_void_channel(format);
142     if (i == -1)
143        return FALSE;
144  
145     return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
146  }
147  
148  boolean
util_format_is_pure_uint(enum pipe_format format)149  util_format_is_pure_uint(enum pipe_format format)
150  {
151     const struct util_format_description *desc = util_format_description(format);
152     int i;
153  
154     i = util_format_get_first_non_void_channel(format);
155     if (i == -1)
156        return FALSE;
157  
158     return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
159  }
160  
161  boolean
util_format_is_array(const struct util_format_description * desc)162  util_format_is_array(const struct util_format_description *desc)
163  {
164     unsigned chan;
165  
166     if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
167         desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB ||
168         desc->block.width != 1 ||
169         desc->block.height != 1) {
170        return FALSE;
171     }
172  
173     for (chan = 0; chan < desc->nr_channels; ++chan) {
174        if (desc->swizzle[chan] != chan)
175           return FALSE;
176  
177        if (desc->channel[chan].type != desc->channel[0].type)
178           return FALSE;
179  
180        if (desc->channel[chan].normalized != desc->channel[0].normalized)
181           return FALSE;
182  
183        if (desc->channel[chan].pure_integer != desc->channel[0].pure_integer)
184           return FALSE;
185  
186        if (desc->channel[chan].size != desc->channel[0].size)
187           return FALSE;
188     }
189  
190     return TRUE;
191  }
192  
193  boolean
util_format_is_luminance_alpha(enum pipe_format format)194  util_format_is_luminance_alpha(enum pipe_format format)
195  {
196     const struct util_format_description *desc =
197        util_format_description(format);
198  
199     if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
200          desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
201         desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
202         desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
203         desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
204         desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_Y) {
205        return TRUE;
206     }
207     return FALSE;
208  }
209  
210  
211  boolean
util_format_is_intensity(enum pipe_format format)212  util_format_is_intensity(enum pipe_format format)
213  {
214     const struct util_format_description *desc =
215        util_format_description(format);
216  
217     if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
218          desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
219         desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
220         desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
221         desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
222         desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_X) {
223        return TRUE;
224     }
225     return FALSE;
226  }
227  
228  
229  boolean
util_format_is_supported(enum pipe_format format,unsigned bind)230  util_format_is_supported(enum pipe_format format, unsigned bind)
231  {
232     if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) {
233        return FALSE;
234     }
235  
236  #ifndef TEXTURE_FLOAT_ENABLED
237     if ((bind & PIPE_BIND_RENDER_TARGET) &&
238         format != PIPE_FORMAT_R9G9B9E5_FLOAT &&
239         format != PIPE_FORMAT_R11G11B10_FLOAT &&
240         util_format_is_float(format)) {
241        return FALSE;
242     }
243  #endif
244  
245     return TRUE;
246  }
247  
248  
249  void
util_format_read_4f(enum pipe_format format,float * dst,unsigned dst_stride,const void * src,unsigned src_stride,unsigned x,unsigned y,unsigned w,unsigned h)250  util_format_read_4f(enum pipe_format format,
251                      float *dst, unsigned dst_stride,
252                      const void *src, unsigned src_stride,
253                      unsigned x, unsigned y, unsigned w, unsigned h)
254  {
255     const struct util_format_description *format_desc;
256     const uint8_t *src_row;
257     float *dst_row;
258  
259     format_desc = util_format_description(format);
260  
261     assert(x % format_desc->block.width == 0);
262     assert(y % format_desc->block.height == 0);
263  
264     src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
265     dst_row = dst;
266  
267     format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
268  }
269  
270  
271  void
util_format_write_4f(enum pipe_format format,const float * src,unsigned src_stride,void * dst,unsigned dst_stride,unsigned x,unsigned y,unsigned w,unsigned h)272  util_format_write_4f(enum pipe_format format,
273                       const float *src, unsigned src_stride,
274                       void *dst, unsigned dst_stride,
275                       unsigned x, unsigned y, unsigned w, unsigned h)
276  {
277     const struct util_format_description *format_desc;
278     uint8_t *dst_row;
279     const float *src_row;
280  
281     format_desc = util_format_description(format);
282  
283     assert(x % format_desc->block.width == 0);
284     assert(y % format_desc->block.height == 0);
285  
286     dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
287     src_row = src;
288  
289     format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
290  }
291  
292  
293  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)294  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)
295  {
296     const struct util_format_description *format_desc;
297     const uint8_t *src_row;
298     uint8_t *dst_row;
299  
300     format_desc = util_format_description(format);
301  
302     assert(x % format_desc->block.width == 0);
303     assert(y % format_desc->block.height == 0);
304  
305     src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
306     dst_row = dst;
307  
308     format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
309  }
310  
311  
312  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)313  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)
314  {
315     const struct util_format_description *format_desc;
316     uint8_t *dst_row;
317     const uint8_t *src_row;
318  
319     format_desc = util_format_description(format);
320  
321     assert(x % format_desc->block.width == 0);
322     assert(y % format_desc->block.height == 0);
323  
324     dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
325     src_row = src;
326  
327     format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
328  }
329  
330  void
util_format_read_4ui(enum pipe_format format,unsigned * dst,unsigned dst_stride,const void * src,unsigned src_stride,unsigned x,unsigned y,unsigned w,unsigned h)331  util_format_read_4ui(enum pipe_format format,
332                       unsigned *dst, unsigned dst_stride,
333                       const void *src, unsigned src_stride,
334                       unsigned x, unsigned y, unsigned w, unsigned h)
335  {
336     const struct util_format_description *format_desc;
337     const uint8_t *src_row;
338     unsigned *dst_row;
339  
340     format_desc = util_format_description(format);
341  
342     assert(x % format_desc->block.width == 0);
343     assert(y % format_desc->block.height == 0);
344  
345     src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
346     dst_row = dst;
347  
348     format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
349  }
350  
351  void
util_format_write_4ui(enum pipe_format format,const unsigned int * src,unsigned src_stride,void * dst,unsigned dst_stride,unsigned x,unsigned y,unsigned w,unsigned h)352  util_format_write_4ui(enum pipe_format format,
353                        const unsigned int *src, unsigned src_stride,
354                        void *dst, unsigned dst_stride,
355                        unsigned x, unsigned y, unsigned w, unsigned h)
356  {
357     const struct util_format_description *format_desc;
358     uint8_t *dst_row;
359     const unsigned *src_row;
360  
361     format_desc = util_format_description(format);
362  
363     assert(x % format_desc->block.width == 0);
364     assert(y % format_desc->block.height == 0);
365  
366     dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
367     src_row = src;
368  
369     format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
370  }
371  
372  void
util_format_read_4i(enum pipe_format format,int * dst,unsigned dst_stride,const void * src,unsigned src_stride,unsigned x,unsigned y,unsigned w,unsigned h)373  util_format_read_4i(enum pipe_format format,
374                      int *dst, unsigned dst_stride,
375                      const void *src, unsigned src_stride,
376                      unsigned x, unsigned y, unsigned w, unsigned h)
377  {
378     const struct util_format_description *format_desc;
379     const uint8_t *src_row;
380     int *dst_row;
381  
382     format_desc = util_format_description(format);
383  
384     assert(x % format_desc->block.width == 0);
385     assert(y % format_desc->block.height == 0);
386  
387     src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
388     dst_row = dst;
389  
390     format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
391  }
392  
393  void
util_format_write_4i(enum pipe_format format,const int * src,unsigned src_stride,void * dst,unsigned dst_stride,unsigned x,unsigned y,unsigned w,unsigned h)394  util_format_write_4i(enum pipe_format format,
395                        const int *src, unsigned src_stride,
396                        void *dst, unsigned dst_stride,
397                        unsigned x, unsigned y, unsigned w, unsigned h)
398  {
399     const struct util_format_description *format_desc;
400     uint8_t *dst_row;
401     const int *src_row;
402  
403     format_desc = util_format_description(format);
404  
405     assert(x % format_desc->block.width == 0);
406     assert(y % format_desc->block.height == 0);
407  
408     dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
409     src_row = src;
410  
411     format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
412  }
413  
414  boolean
util_is_format_compatible(const struct util_format_description * src_desc,const struct util_format_description * dst_desc)415  util_is_format_compatible(const struct util_format_description *src_desc,
416                            const struct util_format_description *dst_desc)
417  {
418     unsigned chan;
419  
420     if (src_desc->format == dst_desc->format) {
421        return TRUE;
422     }
423  
424     if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
425         dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
426        return FALSE;
427     }
428  
429     if (src_desc->block.bits != dst_desc->block.bits ||
430         src_desc->nr_channels != dst_desc->nr_channels ||
431         src_desc->colorspace != dst_desc->colorspace) {
432        return FALSE;
433     }
434  
435     for (chan = 0; chan < 4; ++chan) {
436        if (src_desc->channel[chan].size !=
437            dst_desc->channel[chan].size) {
438           return FALSE;
439        }
440     }
441  
442     for (chan = 0; chan < 4; ++chan) {
443        enum util_format_swizzle swizzle = dst_desc->swizzle[chan];
444  
445        if (swizzle < 4) {
446           if (src_desc->swizzle[chan] != swizzle) {
447              return FALSE;
448           }
449           if ((src_desc->channel[swizzle].type !=
450                dst_desc->channel[swizzle].type) ||
451               (src_desc->channel[swizzle].normalized !=
452                dst_desc->channel[swizzle].normalized)) {
453              return FALSE;
454           }
455        }
456     }
457  
458     return TRUE;
459  }
460  
461  
462  boolean
util_format_fits_8unorm(const struct util_format_description * format_desc)463  util_format_fits_8unorm(const struct util_format_description *format_desc)
464  {
465     unsigned chan;
466  
467     /*
468      * After linearized sRGB values require more than 8bits.
469      */
470  
471     if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
472        return FALSE;
473     }
474  
475     switch (format_desc->layout) {
476  
477     case UTIL_FORMAT_LAYOUT_S3TC:
478        /*
479         * These are straight forward.
480         */
481        return TRUE;
482     case UTIL_FORMAT_LAYOUT_RGTC:
483        if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
484            format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
485            format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
486            format_desc->format == PIPE_FORMAT_LATC2_SNORM)
487           return FALSE;
488        return TRUE;
489  
490     case UTIL_FORMAT_LAYOUT_PLAIN:
491        /*
492         * For these we can find a generic rule.
493         */
494  
495        for (chan = 0; chan < format_desc->nr_channels; ++chan) {
496           switch (format_desc->channel[chan].type) {
497           case UTIL_FORMAT_TYPE_VOID:
498              break;
499           case UTIL_FORMAT_TYPE_UNSIGNED:
500              if (!format_desc->channel[chan].normalized ||
501                  format_desc->channel[chan].size > 8) {
502                 return FALSE;
503              }
504              break;
505           default:
506              return FALSE;
507           }
508        }
509        return TRUE;
510  
511     default:
512        /*
513         * Handle all others on a case by case basis.
514         */
515  
516        switch (format_desc->format) {
517        case PIPE_FORMAT_R1_UNORM:
518        case PIPE_FORMAT_UYVY:
519        case PIPE_FORMAT_YUYV:
520        case PIPE_FORMAT_R8G8_B8G8_UNORM:
521        case PIPE_FORMAT_G8R8_G8B8_UNORM:
522           return TRUE;
523  
524        default:
525           return FALSE;
526        }
527     }
528  }
529  
530  
531  void
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)532  util_format_translate(enum pipe_format dst_format,
533                        void *dst, unsigned dst_stride,
534                        unsigned dst_x, unsigned dst_y,
535                        enum pipe_format src_format,
536                        const void *src, unsigned src_stride,
537                        unsigned src_x, unsigned src_y,
538                        unsigned width, unsigned height)
539  {
540     const struct util_format_description *dst_format_desc;
541     const struct util_format_description *src_format_desc;
542     uint8_t *dst_row;
543     const uint8_t *src_row;
544     unsigned x_step, y_step;
545     unsigned dst_step;
546     unsigned src_step;
547  
548     dst_format_desc = util_format_description(dst_format);
549     src_format_desc = util_format_description(src_format);
550  
551     if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
552        /*
553         * Trivial case.
554         */
555  
556        util_copy_rect(dst, dst_format, dst_stride,  dst_x, dst_y,
557                       width, height, src, (int)src_stride,
558                       src_x, src_y);
559        return;
560     }
561  
562     assert(dst_x % dst_format_desc->block.width == 0);
563     assert(dst_y % dst_format_desc->block.height == 0);
564     assert(src_x % src_format_desc->block.width == 0);
565     assert(src_y % src_format_desc->block.height == 0);
566  
567     dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
568     src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8);
569  
570     /*
571      * This works because all pixel formats have pixel blocks with power of two
572      * sizes.
573      */
574  
575     y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
576     x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
577     assert(y_step % dst_format_desc->block.height == 0);
578     assert(y_step % src_format_desc->block.height == 0);
579  
580     dst_step = y_step / dst_format_desc->block.height * dst_stride;
581     src_step = y_step / src_format_desc->block.height * src_stride;
582  
583     /*
584      * TODO: double formats will loose precision
585      * TODO: Add a special case for formats that are mere swizzles of each other
586      */
587  
588     if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
589         dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
590        float *tmp_z = NULL;
591        uint8_t *tmp_s = NULL;
592  
593        assert(x_step == 1);
594        assert(y_step == 1);
595  
596        if (src_format_desc->unpack_z_float &&
597            dst_format_desc->pack_z_float) {
598           tmp_z = MALLOC(width * sizeof *tmp_z);
599        }
600  
601        if (src_format_desc->unpack_s_8uint &&
602            dst_format_desc->pack_s_8uint) {
603           tmp_s = MALLOC(width * sizeof *tmp_s);
604        }
605  
606        while (height--) {
607           if (tmp_z) {
608              src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1);
609              dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1);
610           }
611  
612           if (tmp_s) {
613              src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1);
614              dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1);
615           }
616  
617           dst_row += dst_step;
618           src_row += src_step;
619        }
620  
621        if (tmp_s) {
622           FREE(tmp_s);
623        }
624  
625        if (tmp_z) {
626           FREE(tmp_z);
627        }
628  
629        return;
630     }
631  
632     if (util_format_fits_8unorm(src_format_desc) ||
633         util_format_fits_8unorm(dst_format_desc)) {
634        unsigned tmp_stride;
635        uint8_t *tmp_row;
636  
637        tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
638        tmp_row = MALLOC(y_step * tmp_stride);
639        if (!tmp_row)
640           return;
641  
642        while (height >= y_step) {
643           src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
644           dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
645  
646           dst_row += dst_step;
647           src_row += src_step;
648           height -= y_step;
649        }
650  
651        if (height) {
652           src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height);
653           dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
654        }
655  
656        FREE(tmp_row);
657     }
658     else {
659        unsigned tmp_stride;
660        float *tmp_row;
661  
662        tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
663        tmp_row = MALLOC(y_step * tmp_stride);
664        if (!tmp_row)
665           return;
666  
667        while (height >= y_step) {
668           src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
669           dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
670  
671           dst_row += dst_step;
672           src_row += src_step;
673           height -= y_step;
674        }
675  
676        if (height) {
677           src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height);
678           dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
679        }
680  
681        FREE(tmp_row);
682     }
683  }
684  
util_format_compose_swizzles(const unsigned char swz1[4],const unsigned char swz2[4],unsigned char dst[4])685  void util_format_compose_swizzles(const unsigned char swz1[4],
686                                    const unsigned char swz2[4],
687                                    unsigned char dst[4])
688  {
689     unsigned i;
690  
691     for (i = 0; i < 4; i++) {
692        dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ?
693                 swz1[swz2[i]] : swz2[i];
694     }
695  }
696  
util_format_swizzle_4f(float * dst,const float * src,const unsigned char swz[4])697  void util_format_swizzle_4f(float *dst, const float *src,
698                              const unsigned char swz[4])
699  {
700     unsigned i;
701  
702     for (i = 0; i < 4; i++) {
703        if (swz[i] <= UTIL_FORMAT_SWIZZLE_W)
704           dst[i] = src[swz[i]];
705        else if (swz[i] == UTIL_FORMAT_SWIZZLE_0)
706           dst[i] = 0;
707        else if (swz[i] == UTIL_FORMAT_SWIZZLE_1)
708           dst[i] = 1;
709     }
710  }
711  
util_format_unswizzle_4f(float * dst,const float * src,const unsigned char swz[4])712  void util_format_unswizzle_4f(float *dst, const float *src,
713                                const unsigned char swz[4])
714  {
715     unsigned i;
716  
717     for (i = 0; i < 4; i++) {
718        switch (swz[i]) {
719        case UTIL_FORMAT_SWIZZLE_X:
720           dst[0] = src[i];
721           break;
722        case UTIL_FORMAT_SWIZZLE_Y:
723           dst[1] = src[i];
724           break;
725        case UTIL_FORMAT_SWIZZLE_Z:
726           dst[2] = src[i];
727           break;
728        case UTIL_FORMAT_SWIZZLE_W:
729           dst[3] = src[i];
730           break;
731        }
732     }
733  }
734