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