• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright 2010 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 /**
29  * @file
30  * Pixel format accessor functions.
31  *
32  * @author Jose Fonseca <jfonseca@vmware.com>
33  */
34 
35 #include "u_math.h"
36 #include "u_memory.h"
37 #include "u_format.h"
38 #include "u_format_s3tc.h"
39 #include "u_surface.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    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 */
65 boolean
util_format_has_alpha(enum pipe_format format)66 util_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 
77 boolean
util_format_is_luminance(enum pipe_format format)78 util_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 
94 boolean
util_format_is_alpha(enum pipe_format format)95 util_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 
111 boolean
util_format_is_pure_integer(enum pipe_format format)112 util_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 
125 boolean
util_format_is_pure_sint(enum pipe_format format)126 util_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 
138 boolean
util_format_is_pure_uint(enum pipe_format format)139 util_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 all non-void channels are normalized signed.
153  */
154 boolean
util_format_is_snorm(enum pipe_format format)155 util_format_is_snorm(enum pipe_format format)
156 {
157    const struct util_format_description *desc = util_format_description(format);
158    int i;
159 
160    if (desc->is_mixed)
161       return FALSE;
162 
163    i = util_format_get_first_non_void_channel(format);
164    if (i == -1)
165       return FALSE;
166 
167    return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
168           !desc->channel[i].pure_integer &&
169           desc->channel[i].normalized;
170 }
171 
172 boolean
util_format_is_snorm8(enum pipe_format format)173 util_format_is_snorm8(enum pipe_format format)
174 {
175    const struct util_format_description *desc = util_format_description(format);
176    int i;
177 
178    if (desc->is_mixed)
179       return FALSE;
180 
181    i = util_format_get_first_non_void_channel(format);
182    if (i == -1)
183       return FALSE;
184 
185    return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
186           !desc->channel[i].pure_integer &&
187           desc->channel[i].normalized &&
188           desc->channel[i].size == 8;
189 }
190 
191 boolean
util_format_is_luminance_alpha(enum pipe_format format)192 util_format_is_luminance_alpha(enum pipe_format format)
193 {
194    const struct util_format_description *desc =
195       util_format_description(format);
196 
197    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
198         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
199        desc->swizzle[0] == PIPE_SWIZZLE_X &&
200        desc->swizzle[1] == PIPE_SWIZZLE_X &&
201        desc->swizzle[2] == PIPE_SWIZZLE_X &&
202        desc->swizzle[3] == PIPE_SWIZZLE_Y) {
203       return TRUE;
204    }
205    return FALSE;
206 }
207 
208 
209 boolean
util_format_is_intensity(enum pipe_format format)210 util_format_is_intensity(enum pipe_format format)
211 {
212    const struct util_format_description *desc =
213       util_format_description(format);
214 
215    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
216         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
217        desc->swizzle[0] == PIPE_SWIZZLE_X &&
218        desc->swizzle[1] == PIPE_SWIZZLE_X &&
219        desc->swizzle[2] == PIPE_SWIZZLE_X &&
220        desc->swizzle[3] == PIPE_SWIZZLE_X) {
221       return TRUE;
222    }
223    return FALSE;
224 }
225 
226 boolean
util_format_is_subsampled_422(enum pipe_format format)227 util_format_is_subsampled_422(enum pipe_format format)
228 {
229    const struct util_format_description *desc =
230       util_format_description(format);
231 
232    return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED &&
233       desc->block.width == 2 &&
234       desc->block.height == 1 &&
235       desc->block.bits == 32;
236 }
237 
238 boolean
util_format_is_supported(enum pipe_format format,unsigned bind)239 util_format_is_supported(enum pipe_format format, unsigned bind)
240 {
241    if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) {
242       return FALSE;
243    }
244 
245 #ifndef TEXTURE_FLOAT_ENABLED
246    if ((bind & PIPE_BIND_RENDER_TARGET) &&
247        format != PIPE_FORMAT_R9G9B9E5_FLOAT &&
248        format != PIPE_FORMAT_R11G11B10_FLOAT &&
249        util_format_is_float(format)) {
250       return FALSE;
251    }
252 #endif
253 
254    return TRUE;
255 }
256 
257 
258 /**
259  * Calculates the MRD for the depth format. MRD is used in depth bias
260  * for UNORM and unbound depth buffers. When the depth buffer is floating
261  * point, the depth bias calculation does not use the MRD. However, the
262  * default MRD will be 1.0 / ((1 << 24) - 1).
263  */
264 double
util_get_depth_format_mrd(const struct util_format_description * desc)265 util_get_depth_format_mrd(const struct util_format_description *desc)
266 {
267    /*
268     * Depth buffer formats without a depth component OR scenarios
269     * without a bound depth buffer default to D24.
270     */
271    double mrd = 1.0 / ((1 << 24) - 1);
272    unsigned depth_channel;
273 
274    assert(desc);
275 
276    /*
277     * Some depth formats do not store the depth component in the first
278     * channel, detect the format and adjust the depth channel. Get the
279     * swizzled depth component channel.
280     */
281    depth_channel = desc->swizzle[0];
282 
283    if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
284        desc->channel[depth_channel].normalized) {
285       int depth_bits;
286 
287       depth_bits = desc->channel[depth_channel].size;
288       mrd = 1.0 / ((1ULL << depth_bits) - 1);
289    }
290 
291    return mrd;
292 }
293 
294 
295 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)296 util_format_read_4f(enum pipe_format format,
297                     float *dst, unsigned dst_stride,
298                     const void *src, unsigned src_stride,
299                     unsigned x, unsigned y, unsigned w, unsigned h)
300 {
301    const struct util_format_description *format_desc;
302    const uint8_t *src_row;
303    float *dst_row;
304 
305    format_desc = util_format_description(format);
306 
307    assert(x % format_desc->block.width == 0);
308    assert(y % format_desc->block.height == 0);
309 
310    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
311    dst_row = dst;
312 
313    format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
314 }
315 
316 
317 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)318 util_format_write_4f(enum pipe_format format,
319                      const float *src, unsigned src_stride,
320                      void *dst, unsigned dst_stride,
321                      unsigned x, unsigned y, unsigned w, unsigned h)
322 {
323    const struct util_format_description *format_desc;
324    uint8_t *dst_row;
325    const float *src_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    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
333    src_row = src;
334 
335    format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
336 }
337 
338 
339 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)340 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)
341 {
342    const struct util_format_description *format_desc;
343    const uint8_t *src_row;
344    uint8_t *dst_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    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
352    dst_row = dst;
353 
354    format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
355 }
356 
357 
358 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)359 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)
360 {
361    const struct util_format_description *format_desc;
362    uint8_t *dst_row;
363    const uint8_t *src_row;
364 
365    format_desc = util_format_description(format);
366 
367    assert(x % format_desc->block.width == 0);
368    assert(y % format_desc->block.height == 0);
369 
370    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
371    src_row = src;
372 
373    format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
374 }
375 
376 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)377 util_format_read_4ui(enum pipe_format format,
378                      unsigned *dst, unsigned dst_stride,
379                      const void *src, unsigned src_stride,
380                      unsigned x, unsigned y, unsigned w, unsigned h)
381 {
382    const struct util_format_description *format_desc;
383    const uint8_t *src_row;
384    uint32_t *dst_row;
385 
386    format_desc = util_format_description(format);
387 
388    assert(x % format_desc->block.width == 0);
389    assert(y % format_desc->block.height == 0);
390 
391    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
392    dst_row = dst;
393 
394    format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
395 }
396 
397 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)398 util_format_write_4ui(enum pipe_format format,
399                       const unsigned int *src, unsigned src_stride,
400                       void *dst, unsigned dst_stride,
401                       unsigned x, unsigned y, unsigned w, unsigned h)
402 {
403    const struct util_format_description *format_desc;
404    uint8_t *dst_row;
405    const uint32_t *src_row;
406 
407    format_desc = util_format_description(format);
408 
409    assert(x % format_desc->block.width == 0);
410    assert(y % format_desc->block.height == 0);
411 
412    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
413    src_row = src;
414 
415    format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
416 }
417 
418 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)419 util_format_read_4i(enum pipe_format format,
420                     int *dst, unsigned dst_stride,
421                     const void *src, unsigned src_stride,
422                     unsigned x, unsigned y, unsigned w, unsigned h)
423 {
424    const struct util_format_description *format_desc;
425    const uint8_t *src_row;
426    int32_t *dst_row;
427 
428    format_desc = util_format_description(format);
429 
430    assert(x % format_desc->block.width == 0);
431    assert(y % format_desc->block.height == 0);
432 
433    src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
434    dst_row = dst;
435 
436    format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
437 }
438 
439 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)440 util_format_write_4i(enum pipe_format format,
441                       const int *src, unsigned src_stride,
442                       void *dst, unsigned dst_stride,
443                       unsigned x, unsigned y, unsigned w, unsigned h)
444 {
445    const struct util_format_description *format_desc;
446    uint8_t *dst_row;
447    const int32_t *src_row;
448 
449    format_desc = util_format_description(format);
450 
451    assert(x % format_desc->block.width == 0);
452    assert(y % format_desc->block.height == 0);
453 
454    dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
455    src_row = src;
456 
457    format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
458 }
459 
460 /**
461  * Check if we can safely memcopy from the source format to the dest format.
462  * This basically covers the cases of a "used" channel copied to a typeless
463  * channel, plus some 1-channel cases.
464  * Examples of compatible copy formats include:
465  *    b8g8r8a8_unorm -> b8g8r8x8_unorm
466  *    a8r8g8b8_unorm -> x8r8g8b8_unorm
467  *    b5g5r5a1_unorm -> b5g5r5x1_unorm
468  *    b4g4r4a4_unorm -> b4g4r4x4_unorm
469  *    l8_unorm -> r8_unorm
470  *    i8_unorm -> l8_unorm
471  *    i8_unorm -> a8_unorm
472  *    i8_unorm -> r8_unorm
473  *    l16_unorm -> r16_unorm
474  *    z24_unorm_s8_uint -> z24x8_unorm
475  *    s8_uint_z24_unorm -> x8z24_unorm
476  *    r8g8b8a8_unorm -> r8g8b8x8_unorm
477  *    a8b8g8r8_srgb -> x8b8g8r8_srgb
478  *    b8g8r8a8_srgb -> b8g8r8x8_srgb
479  *    a8r8g8b8_srgb -> x8r8g8b8_srgb
480  *    a8b8g8r8_unorm -> x8b8g8r8_unorm
481  *    r10g10b10a2_uscaled -> r10g10b10x2_uscaled
482  *    r10sg10sb10sa2u_norm -> r10g10b10x2_snorm
483  */
484 boolean
util_is_format_compatible(const struct util_format_description * src_desc,const struct util_format_description * dst_desc)485 util_is_format_compatible(const struct util_format_description *src_desc,
486                           const struct util_format_description *dst_desc)
487 {
488    unsigned chan;
489 
490    if (src_desc->format == dst_desc->format) {
491       return TRUE;
492    }
493 
494    if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
495        dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
496       return FALSE;
497    }
498 
499    if (src_desc->block.bits != dst_desc->block.bits ||
500        src_desc->nr_channels != dst_desc->nr_channels ||
501        src_desc->colorspace != dst_desc->colorspace) {
502       return FALSE;
503    }
504 
505    for (chan = 0; chan < 4; ++chan) {
506       if (src_desc->channel[chan].size !=
507           dst_desc->channel[chan].size) {
508          return FALSE;
509       }
510    }
511 
512    for (chan = 0; chan < 4; ++chan) {
513       enum pipe_swizzle swizzle = dst_desc->swizzle[chan];
514 
515       if (swizzle < 4) {
516          if (src_desc->swizzle[chan] != swizzle) {
517             return FALSE;
518          }
519          if ((src_desc->channel[swizzle].type !=
520               dst_desc->channel[swizzle].type) ||
521              (src_desc->channel[swizzle].normalized !=
522               dst_desc->channel[swizzle].normalized)) {
523             return FALSE;
524          }
525       }
526    }
527 
528    return TRUE;
529 }
530 
531 
532 boolean
util_format_fits_8unorm(const struct util_format_description * format_desc)533 util_format_fits_8unorm(const struct util_format_description *format_desc)
534 {
535    unsigned chan;
536 
537    /*
538     * After linearized sRGB values require more than 8bits.
539     */
540 
541    if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
542       return FALSE;
543    }
544 
545    switch (format_desc->layout) {
546 
547    case UTIL_FORMAT_LAYOUT_S3TC:
548       /*
549        * These are straight forward.
550        */
551       return TRUE;
552    case UTIL_FORMAT_LAYOUT_RGTC:
553       if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
554           format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
555           format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
556           format_desc->format == PIPE_FORMAT_LATC2_SNORM)
557          return FALSE;
558       return TRUE;
559    case UTIL_FORMAT_LAYOUT_BPTC:
560       if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM)
561          return TRUE;
562       return FALSE;
563 
564    case UTIL_FORMAT_LAYOUT_ETC:
565       if (format_desc->format == PIPE_FORMAT_ETC1_RGB8)
566          return TRUE;
567       return FALSE;
568 
569    case UTIL_FORMAT_LAYOUT_PLAIN:
570       /*
571        * For these we can find a generic rule.
572        */
573 
574       for (chan = 0; chan < format_desc->nr_channels; ++chan) {
575          switch (format_desc->channel[chan].type) {
576          case UTIL_FORMAT_TYPE_VOID:
577             break;
578          case UTIL_FORMAT_TYPE_UNSIGNED:
579             if (!format_desc->channel[chan].normalized ||
580                 format_desc->channel[chan].size > 8) {
581                return FALSE;
582             }
583             break;
584          default:
585             return FALSE;
586          }
587       }
588       return TRUE;
589 
590    default:
591       /*
592        * Handle all others on a case by case basis.
593        */
594 
595       switch (format_desc->format) {
596       case PIPE_FORMAT_R1_UNORM:
597       case PIPE_FORMAT_UYVY:
598       case PIPE_FORMAT_YUYV:
599       case PIPE_FORMAT_R8G8_B8G8_UNORM:
600       case PIPE_FORMAT_G8R8_G8B8_UNORM:
601          return TRUE;
602 
603       default:
604          return FALSE;
605       }
606    }
607 }
608 
609 
610 boolean
util_format_translate(enum pipe_format dst_format,void * dst,unsigned dst_stride,unsigned dst_x,unsigned dst_y,enum pipe_format src_format,const void * src,unsigned src_stride,unsigned src_x,unsigned src_y,unsigned width,unsigned height)611 util_format_translate(enum pipe_format dst_format,
612                       void *dst, unsigned dst_stride,
613                       unsigned dst_x, unsigned dst_y,
614                       enum pipe_format src_format,
615                       const void *src, unsigned src_stride,
616                       unsigned src_x, unsigned src_y,
617                       unsigned width, unsigned height)
618 {
619    const struct util_format_description *dst_format_desc;
620    const struct util_format_description *src_format_desc;
621    uint8_t *dst_row;
622    const uint8_t *src_row;
623    unsigned x_step, y_step;
624    unsigned dst_step;
625    unsigned src_step;
626 
627    dst_format_desc = util_format_description(dst_format);
628    src_format_desc = util_format_description(src_format);
629 
630    if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
631       /*
632        * Trivial case.
633        */
634 
635       util_copy_rect(dst, dst_format, dst_stride,  dst_x, dst_y,
636                      width, height, src, (int)src_stride,
637                      src_x, src_y);
638       return TRUE;
639    }
640 
641    assert(dst_x % dst_format_desc->block.width == 0);
642    assert(dst_y % dst_format_desc->block.height == 0);
643    assert(src_x % src_format_desc->block.width == 0);
644    assert(src_y % src_format_desc->block.height == 0);
645 
646    dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
647    src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8);
648 
649    /*
650     * This works because all pixel formats have pixel blocks with power of two
651     * sizes.
652     */
653 
654    y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
655    x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
656    assert(y_step % dst_format_desc->block.height == 0);
657    assert(y_step % src_format_desc->block.height == 0);
658 
659    dst_step = y_step / dst_format_desc->block.height * dst_stride;
660    src_step = y_step / src_format_desc->block.height * src_stride;
661 
662    /*
663     * TODO: double formats will loose precision
664     * TODO: Add a special case for formats that are mere swizzles of each other
665     */
666 
667    if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
668        dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
669       float *tmp_z = NULL;
670       uint8_t *tmp_s = NULL;
671 
672       assert(x_step == 1);
673       assert(y_step == 1);
674 
675       if (src_format_desc->unpack_z_float &&
676           dst_format_desc->pack_z_float) {
677          tmp_z = MALLOC(width * sizeof *tmp_z);
678       }
679 
680       if (src_format_desc->unpack_s_8uint &&
681           dst_format_desc->pack_s_8uint) {
682          tmp_s = MALLOC(width * sizeof *tmp_s);
683       }
684 
685       while (height--) {
686          if (tmp_z) {
687             src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1);
688             dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1);
689          }
690 
691          if (tmp_s) {
692             src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1);
693             dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1);
694          }
695 
696          dst_row += dst_step;
697          src_row += src_step;
698       }
699 
700       FREE(tmp_s);
701 
702       FREE(tmp_z);
703 
704       return TRUE;
705    }
706 
707    if (util_format_fits_8unorm(src_format_desc) ||
708        util_format_fits_8unorm(dst_format_desc)) {
709       unsigned tmp_stride;
710       uint8_t *tmp_row;
711 
712       if (!src_format_desc->unpack_rgba_8unorm ||
713           !dst_format_desc->pack_rgba_8unorm) {
714          return FALSE;
715       }
716 
717       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
718       tmp_row = MALLOC(y_step * tmp_stride);
719       if (!tmp_row)
720          return FALSE;
721 
722       while (height >= y_step) {
723          src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
724          dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
725 
726          dst_row += dst_step;
727          src_row += src_step;
728          height -= y_step;
729       }
730 
731       if (height) {
732          src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height);
733          dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
734       }
735 
736       FREE(tmp_row);
737    }
738    else {
739       unsigned tmp_stride;
740       float *tmp_row;
741 
742       if (!src_format_desc->unpack_rgba_float ||
743           !dst_format_desc->pack_rgba_float) {
744          return FALSE;
745       }
746 
747       tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
748       tmp_row = MALLOC(y_step * tmp_stride);
749       if (!tmp_row)
750          return FALSE;
751 
752       while (height >= y_step) {
753          src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
754          dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
755 
756          dst_row += dst_step;
757          src_row += src_step;
758          height -= y_step;
759       }
760 
761       if (height) {
762          src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height);
763          dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
764       }
765 
766       FREE(tmp_row);
767    }
768    return TRUE;
769 }
770 
771 boolean
util_format_translate_3d(enum pipe_format dst_format,void * dst,unsigned dst_stride,unsigned dst_slice_stride,unsigned dst_x,unsigned dst_y,unsigned dst_z,enum pipe_format src_format,const void * src,unsigned src_stride,unsigned src_slice_stride,unsigned src_x,unsigned src_y,unsigned src_z,unsigned width,unsigned height,unsigned depth)772 util_format_translate_3d(enum pipe_format dst_format,
773                          void *dst, unsigned dst_stride,
774                          unsigned dst_slice_stride,
775                          unsigned dst_x, unsigned dst_y,
776                          unsigned dst_z,
777                          enum pipe_format src_format,
778                          const void *src, unsigned src_stride,
779                          unsigned src_slice_stride,
780                          unsigned src_x, unsigned src_y,
781                          unsigned src_z, unsigned width,
782                          unsigned height, unsigned depth)
783 {
784    uint8_t *dst_layer;
785    const uint8_t *src_layer;
786    unsigned z;
787    dst_layer = dst;
788    src_layer = src;
789    dst_layer += dst_z * dst_slice_stride;
790    src_layer += src_z * src_slice_stride;
791    for (z = 0; z < depth; ++z) {
792       if (!util_format_translate(dst_format, dst_layer, dst_stride,
793                                  dst_x, dst_y,
794                                  src_format, src_layer, src_stride,
795                                  src_x, src_y,
796                                  width, height))
797           return FALSE;
798 
799       dst_layer += dst_slice_stride;
800       src_layer += src_slice_stride;
801    }
802    return TRUE;
803 }
804 
util_format_compose_swizzles(const unsigned char swz1[4],const unsigned char swz2[4],unsigned char dst[4])805 void util_format_compose_swizzles(const unsigned char swz1[4],
806                                   const unsigned char swz2[4],
807                                   unsigned char dst[4])
808 {
809    unsigned i;
810 
811    for (i = 0; i < 4; i++) {
812       dst[i] = swz2[i] <= PIPE_SWIZZLE_W ?
813                swz1[swz2[i]] : swz2[i];
814    }
815 }
816 
util_format_apply_color_swizzle(union pipe_color_union * dst,const union pipe_color_union * src,const unsigned char swz[4],const boolean is_integer)817 void util_format_apply_color_swizzle(union pipe_color_union *dst,
818                                      const union pipe_color_union *src,
819                                      const unsigned char swz[4],
820                                      const boolean is_integer)
821 {
822    unsigned c;
823 
824    if (is_integer) {
825       for (c = 0; c < 4; ++c) {
826          switch (swz[c]) {
827          case PIPE_SWIZZLE_X:   dst->ui[c] = src->ui[0]; break;
828          case PIPE_SWIZZLE_Y: dst->ui[c] = src->ui[1]; break;
829          case PIPE_SWIZZLE_Z:  dst->ui[c] = src->ui[2]; break;
830          case PIPE_SWIZZLE_W: dst->ui[c] = src->ui[3]; break;
831          default:
832             dst->ui[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1 : 0;
833             break;
834          }
835       }
836    } else {
837       for (c = 0; c < 4; ++c) {
838          switch (swz[c]) {
839          case PIPE_SWIZZLE_X:   dst->f[c] = src->f[0]; break;
840          case PIPE_SWIZZLE_Y: dst->f[c] = src->f[1]; break;
841          case PIPE_SWIZZLE_Z:  dst->f[c] = src->f[2]; break;
842          case PIPE_SWIZZLE_W: dst->f[c] = src->f[3]; break;
843          default:
844             dst->f[c] = (swz[c] == PIPE_SWIZZLE_1) ? 1.0f : 0.0f;
845             break;
846          }
847       }
848    }
849 }
850 
pipe_swizzle_4f(float * dst,const float * src,const unsigned char swz[4])851 void pipe_swizzle_4f(float *dst, const float *src,
852                             const unsigned char swz[4])
853 {
854    unsigned i;
855 
856    for (i = 0; i < 4; i++) {
857       if (swz[i] <= PIPE_SWIZZLE_W)
858          dst[i] = src[swz[i]];
859       else if (swz[i] == PIPE_SWIZZLE_0)
860          dst[i] = 0;
861       else if (swz[i] == PIPE_SWIZZLE_1)
862          dst[i] = 1;
863    }
864 }
865 
util_format_unswizzle_4f(float * dst,const float * src,const unsigned char swz[4])866 void util_format_unswizzle_4f(float *dst, const float *src,
867                               const unsigned char swz[4])
868 {
869    unsigned i;
870 
871    for (i = 0; i < 4; i++) {
872       switch (swz[i]) {
873       case PIPE_SWIZZLE_X:
874          dst[0] = src[i];
875          break;
876       case PIPE_SWIZZLE_Y:
877          dst[1] = src[i];
878          break;
879       case PIPE_SWIZZLE_Z:
880          dst[2] = src[i];
881          break;
882       case PIPE_SWIZZLE_W:
883          dst[3] = src[i];
884          break;
885       }
886    }
887 }
888