• 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 /** Test if the format contains RGB, but not alpha */
44 boolean
util_format_has_alpha(enum pipe_format format)45 util_format_has_alpha(enum pipe_format format)
46 {
47    const struct util_format_description *desc =
48       util_format_description(format);
49 
50    return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
51            desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
52           desc->swizzle[3] != UTIL_FORMAT_SWIZZLE_1;
53 }
54 
55 
56 boolean
util_format_is_luminance(enum pipe_format format)57 util_format_is_luminance(enum pipe_format format)
58 {
59    const struct util_format_description *desc =
60       util_format_description(format);
61 
62    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
63         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
64        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
65        desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
66        desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
67        desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1) {
68       return TRUE;
69    }
70    return FALSE;
71 }
72 
73 boolean
util_format_is_alpha(enum pipe_format format)74 util_format_is_alpha(enum pipe_format format)
75 {
76    const struct util_format_description *desc =
77       util_format_description(format);
78 
79    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
80         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
81        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_0 &&
82        desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_0 &&
83        desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_0 &&
84        desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_X) {
85       return TRUE;
86    }
87    return FALSE;
88 }
89 
90 boolean
util_format_is_pure_integer(enum pipe_format format)91 util_format_is_pure_integer(enum pipe_format format)
92 {
93    const struct util_format_description *desc = util_format_description(format);
94    int i;
95 
96    /* Find the first non-void channel. */
97    i = util_format_get_first_non_void_channel(format);
98    if (i == -1)
99       return FALSE;
100 
101    return desc->channel[i].pure_integer ? TRUE : FALSE;
102 }
103 
104 boolean
util_format_is_pure_sint(enum pipe_format format)105 util_format_is_pure_sint(enum pipe_format format)
106 {
107    const struct util_format_description *desc = util_format_description(format);
108    int i;
109 
110    i = util_format_get_first_non_void_channel(format);
111    if (i == -1)
112       return FALSE;
113 
114    return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
115 }
116 
117 boolean
util_format_is_pure_uint(enum pipe_format format)118 util_format_is_pure_uint(enum pipe_format format)
119 {
120    const struct util_format_description *desc = util_format_description(format);
121    int i;
122 
123    i = util_format_get_first_non_void_channel(format);
124    if (i == -1)
125       return FALSE;
126 
127    return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
128 }
129 
130 /**
131  * Returns true if all non-void channels are normalized signed.
132  */
133 boolean
util_format_is_snorm(enum pipe_format format)134 util_format_is_snorm(enum pipe_format format)
135 {
136    const struct util_format_description *desc = util_format_description(format);
137    int i;
138 
139    if (desc->is_mixed)
140       return FALSE;
141 
142    i = util_format_get_first_non_void_channel(format);
143    if (i == -1)
144       return FALSE;
145 
146    return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
147           !desc->channel[i].pure_integer &&
148           desc->channel[i].normalized;
149 }
150 
151 boolean
util_format_is_luminance_alpha(enum pipe_format format)152 util_format_is_luminance_alpha(enum pipe_format format)
153 {
154    const struct util_format_description *desc =
155       util_format_description(format);
156 
157    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
158         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
159        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
160        desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
161        desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
162        desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_Y) {
163       return TRUE;
164    }
165    return FALSE;
166 }
167 
168 
169 boolean
util_format_is_intensity(enum pipe_format format)170 util_format_is_intensity(enum pipe_format format)
171 {
172    const struct util_format_description *desc =
173       util_format_description(format);
174 
175    if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
176         desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
177        desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
178        desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
179        desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
180        desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_X) {
181       return TRUE;
182    }
183    return FALSE;
184 }
185 
186 /**
187  * Calculates the MRD for the depth format. MRD is used in depth bias
188  * for UNORM and unbound depth buffers. When the depth buffer is floating
189  * point, the depth bias calculation does not use the MRD. However, the
190  * default MRD will be 1.0 / ((1 << 24) - 1).
191  */
192 double
util_get_depth_format_mrd(const struct util_format_description * desc)193 util_get_depth_format_mrd(const struct util_format_description *desc)
194 {
195    /*
196     * Depth buffer formats without a depth component OR scenarios
197     * without a bound depth buffer default to D24.
198     */
199    double mrd = 1.0 / ((1 << 24) - 1);
200    unsigned depth_channel;
201 
202    assert(desc);
203 
204    /*
205     * Some depth formats do not store the depth component in the first
206     * channel, detect the format and adjust the depth channel. Get the
207     * swizzled depth component channel.
208     */
209    depth_channel = desc->swizzle[0];
210 
211    if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED &&
212        desc->channel[depth_channel].normalized) {
213       int depth_bits;
214 
215       depth_bits = desc->channel[depth_channel].size;
216       mrd = 1.0 / ((1ULL << depth_bits) - 1);
217    }
218 
219    return mrd;
220 }
221 
222 boolean
util_is_format_compatible(const struct util_format_description * src_desc,const struct util_format_description * dst_desc)223 util_is_format_compatible(const struct util_format_description *src_desc,
224                           const struct util_format_description *dst_desc)
225 {
226    unsigned chan;
227 
228    if (src_desc->format == dst_desc->format) {
229       return TRUE;
230    }
231 
232    if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
233        dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
234       return FALSE;
235    }
236 
237    if (src_desc->block.bits != dst_desc->block.bits ||
238        src_desc->nr_channels != dst_desc->nr_channels ||
239        src_desc->colorspace != dst_desc->colorspace) {
240       return FALSE;
241    }
242 
243    for (chan = 0; chan < 4; ++chan) {
244       if (src_desc->channel[chan].size !=
245           dst_desc->channel[chan].size) {
246          return FALSE;
247       }
248    }
249 
250    for (chan = 0; chan < 4; ++chan) {
251       enum util_format_swizzle swizzle = dst_desc->swizzle[chan];
252 
253       if (swizzle < 4) {
254          if (src_desc->swizzle[chan] != swizzle) {
255             return FALSE;
256          }
257          if ((src_desc->channel[swizzle].type !=
258               dst_desc->channel[swizzle].type) ||
259              (src_desc->channel[swizzle].normalized !=
260               dst_desc->channel[swizzle].normalized)) {
261             return FALSE;
262          }
263       }
264    }
265 
266    return TRUE;
267 }
268 
269 
270 boolean
util_format_fits_8unorm(const struct util_format_description * format_desc)271 util_format_fits_8unorm(const struct util_format_description *format_desc)
272 {
273    unsigned chan;
274 
275    /*
276     * After linearized sRGB values require more than 8bits.
277     */
278 
279    if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
280       return FALSE;
281    }
282 
283    switch (format_desc->layout) {
284 
285    case UTIL_FORMAT_LAYOUT_S3TC:
286       /*
287        * These are straight forward.
288        */
289       return TRUE;
290    case UTIL_FORMAT_LAYOUT_RGTC:
291       if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
292           format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
293           format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
294           format_desc->format == PIPE_FORMAT_LATC2_SNORM)
295          return FALSE;
296       return TRUE;
297    case UTIL_FORMAT_LAYOUT_BPTC:
298       if (format_desc->format == PIPE_FORMAT_BPTC_RGBA_UNORM)
299          return TRUE;
300       return FALSE;
301 
302    case UTIL_FORMAT_LAYOUT_PLAIN:
303       /*
304        * For these we can find a generic rule.
305        */
306 
307       for (chan = 0; chan < format_desc->nr_channels; ++chan) {
308          switch (format_desc->channel[chan].type) {
309          case UTIL_FORMAT_TYPE_VOID:
310             break;
311          case UTIL_FORMAT_TYPE_UNSIGNED:
312             if (!format_desc->channel[chan].normalized ||
313                 format_desc->channel[chan].size > 8) {
314                return FALSE;
315             }
316             break;
317          default:
318             return FALSE;
319          }
320       }
321       return TRUE;
322 
323    default:
324       /*
325        * Handle all others on a case by case basis.
326        */
327 
328       switch (format_desc->format) {
329       case PIPE_FORMAT_R1_UNORM:
330       case PIPE_FORMAT_UYVY:
331       case PIPE_FORMAT_YUYV:
332       case PIPE_FORMAT_R8G8_B8G8_UNORM:
333       case PIPE_FORMAT_G8R8_G8B8_UNORM:
334          return TRUE;
335 
336       default:
337          return FALSE;
338       }
339    }
340 }
341 
342 
util_format_compose_swizzles(const unsigned char swz1[4],const unsigned char swz2[4],unsigned char dst[4])343 void util_format_compose_swizzles(const unsigned char swz1[4],
344                                   const unsigned char swz2[4],
345                                   unsigned char dst[4])
346 {
347    unsigned i;
348 
349    for (i = 0; i < 4; i++) {
350       dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ?
351                swz1[swz2[i]] : swz2[i];
352    }
353 }
354 
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)355 void util_format_apply_color_swizzle(union pipe_color_union *dst,
356                                      const union pipe_color_union *src,
357                                      const unsigned char swz[4],
358                                      const boolean is_integer)
359 {
360    unsigned c;
361 
362    if (is_integer) {
363       for (c = 0; c < 4; ++c) {
364          switch (swz[c]) {
365          case PIPE_SWIZZLE_RED:   dst->ui[c] = src->ui[0]; break;
366          case PIPE_SWIZZLE_GREEN: dst->ui[c] = src->ui[1]; break;
367          case PIPE_SWIZZLE_BLUE:  dst->ui[c] = src->ui[2]; break;
368          case PIPE_SWIZZLE_ALPHA: dst->ui[c] = src->ui[3]; break;
369          default:
370             dst->ui[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1 : 0;
371             break;
372          }
373       }
374    } else {
375       for (c = 0; c < 4; ++c) {
376          switch (swz[c]) {
377          case PIPE_SWIZZLE_RED:   dst->f[c] = src->f[0]; break;
378          case PIPE_SWIZZLE_GREEN: dst->f[c] = src->f[1]; break;
379          case PIPE_SWIZZLE_BLUE:  dst->f[c] = src->f[2]; break;
380          case PIPE_SWIZZLE_ALPHA: dst->f[c] = src->f[3]; break;
381          default:
382             dst->f[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1.0f : 0.0f;
383             break;
384          }
385       }
386    }
387 }
388 
util_format_swizzle_4f(float * dst,const float * src,const unsigned char swz[4])389 void util_format_swizzle_4f(float *dst, const float *src,
390                             const unsigned char swz[4])
391 {
392    unsigned i;
393 
394    for (i = 0; i < 4; i++) {
395       if (swz[i] <= UTIL_FORMAT_SWIZZLE_W)
396          dst[i] = src[swz[i]];
397       else if (swz[i] == UTIL_FORMAT_SWIZZLE_0)
398          dst[i] = 0;
399       else if (swz[i] == UTIL_FORMAT_SWIZZLE_1)
400          dst[i] = 1;
401    }
402 }
403 
util_format_unswizzle_4f(float * dst,const float * src,const unsigned char swz[4])404 void util_format_unswizzle_4f(float *dst, const float *src,
405                               const unsigned char swz[4])
406 {
407    unsigned i;
408 
409    for (i = 0; i < 4; i++) {
410       switch (swz[i]) {
411       case UTIL_FORMAT_SWIZZLE_X:
412          dst[0] = src[i];
413          break;
414       case UTIL_FORMAT_SWIZZLE_Y:
415          dst[1] = src[i];
416          break;
417       case UTIL_FORMAT_SWIZZLE_Z:
418          dst[2] = src[i];
419          break;
420       case UTIL_FORMAT_SWIZZLE_W:
421          dst[3] = src[i];
422          break;
423       }
424    }
425 }
426