1 /*
2  * Copyright 2017 Google
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include "formats.h"
26 #include "util/macros.h"
27 
28 /**
29  * For an sRGB format, return the corresponding linear color space format.
30  * For non-sRGB formats, return the format as-is.
31  */
32 mesa_format
_mesa_get_srgb_format_linear(mesa_format format)33 _mesa_get_srgb_format_linear(mesa_format format)
34 {
35    switch (format) {
36    case MESA_FORMAT_A8B8G8R8_SRGB:
37       return MESA_FORMAT_A8B8G8R8_UNORM;
38    case MESA_FORMAT_B8G8R8A8_SRGB:
39       return MESA_FORMAT_B8G8R8A8_UNORM;
40    case MESA_FORMAT_A8R8G8B8_SRGB:
41       return MESA_FORMAT_A8R8G8B8_UNORM;
42    case MESA_FORMAT_B8G8R8X8_SRGB:
43       return MESA_FORMAT_B8G8R8X8_UNORM;
44    case MESA_FORMAT_X8R8G8B8_SRGB:
45       return MESA_FORMAT_X8R8G8B8_UNORM;
46    case MESA_FORMAT_R8G8B8A8_SRGB:
47       return MESA_FORMAT_R8G8B8A8_UNORM;
48    case MESA_FORMAT_R8G8B8X8_SRGB:
49       return MESA_FORMAT_R8G8B8X8_UNORM;
50    case MESA_FORMAT_X8B8G8R8_SRGB:
51       return MESA_FORMAT_X8B8G8R8_UNORM;
52    case MESA_FORMAT_R_SRGB8:
53       return MESA_FORMAT_R_UNORM8;
54    case MESA_FORMAT_L_SRGB8:
55       return MESA_FORMAT_L_UNORM8;
56    case MESA_FORMAT_LA_SRGB8:
57       return MESA_FORMAT_LA_UNORM8;
58    case MESA_FORMAT_BGR_SRGB8:
59       return MESA_FORMAT_BGR_UNORM8;
60    case MESA_FORMAT_SRGB_DXT1:
61       return MESA_FORMAT_RGB_DXT1;
62    case MESA_FORMAT_SRGBA_DXT1:
63       return MESA_FORMAT_RGBA_DXT1;
64    case MESA_FORMAT_SRGBA_DXT3:
65       return MESA_FORMAT_RGBA_DXT3;
66    case MESA_FORMAT_SRGBA_DXT5:
67       return MESA_FORMAT_RGBA_DXT5;
68    case MESA_FORMAT_ETC2_SRGB8:
69       return MESA_FORMAT_ETC2_RGB8;
70    case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
71       return MESA_FORMAT_ETC2_RGBA8_EAC;
72    case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
73       return MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1;
74    case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
75       return MESA_FORMAT_BPTC_RGBA_UNORM;
76    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4:
77       return MESA_FORMAT_RGBA_ASTC_4x4;
78    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4:
79       return MESA_FORMAT_RGBA_ASTC_5x4;
80    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5:
81       return MESA_FORMAT_RGBA_ASTC_5x5;
82    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5:
83       return MESA_FORMAT_RGBA_ASTC_6x5;
84    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6:
85       return MESA_FORMAT_RGBA_ASTC_6x6;
86    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x5:
87       return MESA_FORMAT_RGBA_ASTC_8x5;
88    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x6:
89       return MESA_FORMAT_RGBA_ASTC_8x6;
90    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x8:
91       return MESA_FORMAT_RGBA_ASTC_8x8;
92    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x5:
93       return MESA_FORMAT_RGBA_ASTC_10x5;
94    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x6:
95       return MESA_FORMAT_RGBA_ASTC_10x6;
96    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x8:
97       return MESA_FORMAT_RGBA_ASTC_10x8;
98    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x10:
99       return MESA_FORMAT_RGBA_ASTC_10x10;
100    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x10:
101       return MESA_FORMAT_RGBA_ASTC_12x10;
102    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x12:
103       return MESA_FORMAT_RGBA_ASTC_12x12;
104    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_3x3x3:
105       return MESA_FORMAT_RGBA_ASTC_3x3x3;
106    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x3x3:
107       return MESA_FORMAT_RGBA_ASTC_4x3x3;
108    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x3:
109       return MESA_FORMAT_RGBA_ASTC_4x4x3;
110    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x4:
111       return MESA_FORMAT_RGBA_ASTC_4x4x4;
112    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4x4:
113       return MESA_FORMAT_RGBA_ASTC_5x4x4;
114    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x4:
115       return MESA_FORMAT_RGBA_ASTC_5x5x4;
116    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x5:
117       return MESA_FORMAT_RGBA_ASTC_5x5x5;
118    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5x5:
119       return MESA_FORMAT_RGBA_ASTC_6x5x5;
120    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x5:
121       return MESA_FORMAT_RGBA_ASTC_6x6x5;
122    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x6:
123       return MESA_FORMAT_RGBA_ASTC_6x6x6;
124    default:
125       return format;
126    }
127 }
128 
129 /**
130  * For a linear format, return the corresponding sRGB color space format.
131  * For an sRGB format, return the format as-is.
132  * Assert-fails if the format is not sRGB and does not have an sRGB equivalent.
133  */
134 mesa_format
_mesa_get_linear_format_srgb(mesa_format format)135 _mesa_get_linear_format_srgb(mesa_format format)
136 {
137    switch (format) {
138    case MESA_FORMAT_A8B8G8R8_UNORM:
139       return MESA_FORMAT_A8B8G8R8_SRGB;
140    case MESA_FORMAT_B8G8R8A8_UNORM:
141       return MESA_FORMAT_B8G8R8A8_SRGB;
142    case MESA_FORMAT_A8R8G8B8_UNORM:
143       return MESA_FORMAT_A8R8G8B8_SRGB;
144    case MESA_FORMAT_B8G8R8X8_UNORM:
145       return MESA_FORMAT_B8G8R8X8_SRGB;
146    case MESA_FORMAT_X8R8G8B8_UNORM:
147       return MESA_FORMAT_X8R8G8B8_SRGB;
148    case MESA_FORMAT_R8G8B8A8_UNORM:
149       return MESA_FORMAT_R8G8B8A8_SRGB;
150    case MESA_FORMAT_R8G8B8X8_UNORM:
151       return MESA_FORMAT_R8G8B8X8_SRGB;
152    case MESA_FORMAT_X8B8G8R8_UNORM:
153       return MESA_FORMAT_X8B8G8R8_SRGB;
154    case MESA_FORMAT_R_UNORM8:
155       return MESA_FORMAT_R_SRGB8;
156    case MESA_FORMAT_L_UNORM8:
157       return MESA_FORMAT_L_SRGB8;
158    case MESA_FORMAT_LA_UNORM8:
159       return MESA_FORMAT_LA_SRGB8;
160    case MESA_FORMAT_BGR_UNORM8:
161       return MESA_FORMAT_BGR_SRGB8;
162    case MESA_FORMAT_RGB_DXT1:
163       return MESA_FORMAT_SRGB_DXT1;
164    case MESA_FORMAT_RGBA_DXT1:
165       return MESA_FORMAT_SRGBA_DXT1;
166    case MESA_FORMAT_RGBA_DXT3:
167       return MESA_FORMAT_SRGBA_DXT3;
168    case MESA_FORMAT_RGBA_DXT5:
169       return MESA_FORMAT_SRGBA_DXT5;
170    case MESA_FORMAT_ETC2_RGB8:
171       return MESA_FORMAT_ETC2_SRGB8;
172    case MESA_FORMAT_ETC2_RGBA8_EAC:
173       return MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC;
174    case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
175       return MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1;
176    case MESA_FORMAT_BPTC_RGBA_UNORM:
177       return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM;
178    case MESA_FORMAT_RGBA_ASTC_4x4:
179       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4;
180    case MESA_FORMAT_RGBA_ASTC_5x4:
181       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4;
182    case MESA_FORMAT_RGBA_ASTC_5x5:
183       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5;
184    case MESA_FORMAT_RGBA_ASTC_6x5:
185       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5;
186    case MESA_FORMAT_RGBA_ASTC_6x6:
187       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6;
188    case MESA_FORMAT_RGBA_ASTC_8x5:
189       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x5;
190    case MESA_FORMAT_RGBA_ASTC_8x6:
191       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x6;
192    case MESA_FORMAT_RGBA_ASTC_8x8:
193       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x8;
194    case MESA_FORMAT_RGBA_ASTC_10x5:
195       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x5;
196    case MESA_FORMAT_RGBA_ASTC_10x6:
197       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x6;
198    case MESA_FORMAT_RGBA_ASTC_10x8:
199       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x8;
200    case MESA_FORMAT_RGBA_ASTC_10x10:
201       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x10;
202    case MESA_FORMAT_RGBA_ASTC_12x10:
203       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x10;
204    case MESA_FORMAT_RGBA_ASTC_12x12:
205       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x12;
206    case MESA_FORMAT_RGBA_ASTC_3x3x3:
207       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_3x3x3;
208    case MESA_FORMAT_RGBA_ASTC_4x3x3:
209       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x3x3;
210    case MESA_FORMAT_RGBA_ASTC_4x4x3:
211       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x3;
212    case MESA_FORMAT_RGBA_ASTC_4x4x4:
213       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x4;
214    case MESA_FORMAT_RGBA_ASTC_5x4x4:
215       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4x4;
216    case MESA_FORMAT_RGBA_ASTC_5x5x4:
217       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x4;
218    case MESA_FORMAT_RGBA_ASTC_5x5x5:
219       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x5;
220    case MESA_FORMAT_RGBA_ASTC_6x5x5:
221       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5x5;
222    case MESA_FORMAT_RGBA_ASTC_6x6x5:
223       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x5;
224    case MESA_FORMAT_RGBA_ASTC_6x6x6:
225       return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x6;
226    case MESA_FORMAT_A8B8G8R8_SRGB:
227    case MESA_FORMAT_B8G8R8A8_SRGB:
228    case MESA_FORMAT_A8R8G8B8_SRGB:
229    case MESA_FORMAT_B8G8R8X8_SRGB:
230    case MESA_FORMAT_X8R8G8B8_SRGB:
231    case MESA_FORMAT_R8G8B8A8_SRGB:
232    case MESA_FORMAT_R8G8B8X8_SRGB:
233    case MESA_FORMAT_X8B8G8R8_SRGB:
234    case MESA_FORMAT_R_SRGB8:
235    case MESA_FORMAT_L_SRGB8:
236    case MESA_FORMAT_LA_SRGB8:
237    case MESA_FORMAT_BGR_SRGB8:
238    case MESA_FORMAT_SRGB_DXT1:
239    case MESA_FORMAT_SRGBA_DXT1:
240    case MESA_FORMAT_SRGBA_DXT3:
241    case MESA_FORMAT_SRGBA_DXT5:
242    case MESA_FORMAT_ETC2_SRGB8:
243    case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
244    case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
245    case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
246    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4:
247    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4:
248    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5:
249    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5:
250    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6:
251    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x5:
252    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x6:
253    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x8:
254    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x5:
255    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x6:
256    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x8:
257    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x10:
258    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x10:
259    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x12:
260    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_3x3x3:
261    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x3x3:
262    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x3:
263    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x4:
264    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4x4:
265    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x4:
266    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x5:
267    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5x5:
268    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x5:
269    case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x6:
270       return format;
271    default:
272       unreachable("Given format does not have an sRGB equivalent");
273    }
274 }
275 
276 /**
277  * For an intensity format, return the corresponding red format.  For other
278  * formats, return the format as-is.
279  */
280 mesa_format
_mesa_get_intensity_format_red(mesa_format format)281 _mesa_get_intensity_format_red(mesa_format format)
282 {
283    switch (format) {
284    case MESA_FORMAT_I_UNORM8:
285       return MESA_FORMAT_R_UNORM8;
286    case MESA_FORMAT_I_UNORM16:
287       return MESA_FORMAT_R_UNORM16;
288    case MESA_FORMAT_I_SNORM8:
289       return MESA_FORMAT_R_SNORM8;
290    case MESA_FORMAT_I_SNORM16:
291       return MESA_FORMAT_R_SNORM16;
292    case MESA_FORMAT_I_FLOAT16:
293       return MESA_FORMAT_R_FLOAT16;
294    case MESA_FORMAT_I_FLOAT32:
295       return MESA_FORMAT_R_FLOAT32;
296    case MESA_FORMAT_I_UINT8:
297       return MESA_FORMAT_R_UINT8;
298    case MESA_FORMAT_I_UINT16:
299       return MESA_FORMAT_R_UINT16;
300    case MESA_FORMAT_I_UINT32:
301       return MESA_FORMAT_R_UINT32;
302    case MESA_FORMAT_I_SINT8:
303       return MESA_FORMAT_R_SINT8;
304    case MESA_FORMAT_I_SINT16:
305       return MESA_FORMAT_R_SINT16;
306    case MESA_FORMAT_I_SINT32:
307       return MESA_FORMAT_R_SINT32;
308    default:
309       return format;
310    }
311 }
312 
313 /**
314  * If the format has an alpha channel, and there exists a non-alpha
315  * variant of the format with an identical bit layout, then return
316  * the non-alpha format. Otherwise return the original format.
317  *
318  * Examples:
319  *    Fallback exists:
320  *       MESA_FORMAT_R8G8B8X8_UNORM -> MESA_FORMAT_R8G8B8A8_UNORM
321  *       MESA_FORMAT_RGBX_UNORM16 -> MESA_FORMAT_RGBA_UNORM16
322  *
323  *    No fallback:
324  *       MESA_FORMAT_R8G8B8A8_UNORM -> MESA_FORMAT_R8G8B8A8_UNORM
325  *       MESA_FORMAT_Z_FLOAT32 -> MESA_FORMAT_Z_FLOAT32
326  */
327 mesa_format
_mesa_format_fallback_rgbx_to_rgba(mesa_format format)328 _mesa_format_fallback_rgbx_to_rgba(mesa_format format)
329 {
330    switch (format) {
331    case MESA_FORMAT_X8B8G8R8_UNORM:
332       return MESA_FORMAT_A8B8G8R8_UNORM;
333    case MESA_FORMAT_R8G8B8X8_UNORM:
334       return MESA_FORMAT_R8G8B8A8_UNORM;
335    case MESA_FORMAT_B8G8R8X8_UNORM:
336       return MESA_FORMAT_B8G8R8A8_UNORM;
337    case MESA_FORMAT_X8R8G8B8_UNORM:
338       return MESA_FORMAT_A8R8G8B8_UNORM;
339    case MESA_FORMAT_B4G4R4X4_UNORM:
340       return MESA_FORMAT_B4G4R4A4_UNORM;
341    case MESA_FORMAT_X1B5G5R5_UNORM:
342       return MESA_FORMAT_A1B5G5R5_UNORM;
343    case MESA_FORMAT_B5G5R5X1_UNORM:
344       return MESA_FORMAT_B5G5R5A1_UNORM;
345    case MESA_FORMAT_B10G10R10X2_UNORM:
346       return MESA_FORMAT_B10G10R10A2_UNORM;
347    case MESA_FORMAT_R10G10B10X2_UNORM:
348       return MESA_FORMAT_R10G10B10A2_UNORM;
349    case MESA_FORMAT_RGBX_UNORM16:
350       return MESA_FORMAT_RGBA_UNORM16;
351    case MESA_FORMAT_X8B8G8R8_SNORM:
352       return MESA_FORMAT_A8B8G8R8_SNORM;
353    case MESA_FORMAT_R8G8B8X8_SNORM:
354       return MESA_FORMAT_R8G8B8A8_SNORM;
355    case MESA_FORMAT_RGBX_SNORM16:
356       return MESA_FORMAT_RGBA_SNORM16;
357    case MESA_FORMAT_B8G8R8X8_SRGB:
358       return MESA_FORMAT_B8G8R8A8_SRGB;
359    case MESA_FORMAT_X8R8G8B8_SRGB:
360       return MESA_FORMAT_A8R8G8B8_SRGB;
361    case MESA_FORMAT_R8G8B8X8_SRGB:
362       return MESA_FORMAT_R8G8B8A8_SRGB;
363    case MESA_FORMAT_X8B8G8R8_SRGB:
364       return MESA_FORMAT_A8B8G8R8_SRGB;
365    case MESA_FORMAT_RGBX_FLOAT16:
366       return MESA_FORMAT_RGBA_FLOAT16;
367    case MESA_FORMAT_RGBX_FLOAT32:
368       return MESA_FORMAT_RGBA_FLOAT32;
369    case MESA_FORMAT_RGBX_UINT16:
370       return MESA_FORMAT_RGBA_UINT16;
371    case MESA_FORMAT_RGBX_UINT32:
372       return MESA_FORMAT_RGBA_UINT32;
373    case MESA_FORMAT_RGBX_SINT8:
374       return MESA_FORMAT_RGBA_SINT8;
375    case MESA_FORMAT_RGBX_SINT16:
376       return MESA_FORMAT_RGBA_SINT16;
377    case MESA_FORMAT_RGBX_SINT32:
378       return MESA_FORMAT_RGBA_SINT32;
379    default:
380       return format;
381    }
382 }
383