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