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