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 */
32mesa_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_RG_SRGB8:
57      return MESA_FORMAT_RG_UNORM8;
58   case MESA_FORMAT_LA_SRGB8:
59      return MESA_FORMAT_LA_UNORM8;
60   case MESA_FORMAT_BGR_SRGB8:
61      return MESA_FORMAT_BGR_UNORM8;
62   case MESA_FORMAT_SRGB_DXT1:
63      return MESA_FORMAT_RGB_DXT1;
64   case MESA_FORMAT_SRGBA_DXT1:
65      return MESA_FORMAT_RGBA_DXT1;
66   case MESA_FORMAT_SRGBA_DXT3:
67      return MESA_FORMAT_RGBA_DXT3;
68   case MESA_FORMAT_SRGBA_DXT5:
69      return MESA_FORMAT_RGBA_DXT5;
70   case MESA_FORMAT_ETC2_SRGB8:
71      return MESA_FORMAT_ETC2_RGB8;
72   case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
73      return MESA_FORMAT_ETC2_RGBA8_EAC;
74   case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
75      return MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1;
76   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
77      return MESA_FORMAT_BPTC_RGBA_UNORM;
78   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4:
79      return MESA_FORMAT_RGBA_ASTC_4x4;
80   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4:
81      return MESA_FORMAT_RGBA_ASTC_5x4;
82   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5:
83      return MESA_FORMAT_RGBA_ASTC_5x5;
84   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5:
85      return MESA_FORMAT_RGBA_ASTC_6x5;
86   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6:
87      return MESA_FORMAT_RGBA_ASTC_6x6;
88   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x5:
89      return MESA_FORMAT_RGBA_ASTC_8x5;
90   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x6:
91      return MESA_FORMAT_RGBA_ASTC_8x6;
92   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x8:
93      return MESA_FORMAT_RGBA_ASTC_8x8;
94   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x5:
95      return MESA_FORMAT_RGBA_ASTC_10x5;
96   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x6:
97      return MESA_FORMAT_RGBA_ASTC_10x6;
98   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x8:
99      return MESA_FORMAT_RGBA_ASTC_10x8;
100   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x10:
101      return MESA_FORMAT_RGBA_ASTC_10x10;
102   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x10:
103      return MESA_FORMAT_RGBA_ASTC_12x10;
104   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x12:
105      return MESA_FORMAT_RGBA_ASTC_12x12;
106   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_3x3x3:
107      return MESA_FORMAT_RGBA_ASTC_3x3x3;
108   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x3x3:
109      return MESA_FORMAT_RGBA_ASTC_4x3x3;
110   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x3:
111      return MESA_FORMAT_RGBA_ASTC_4x4x3;
112   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x4:
113      return MESA_FORMAT_RGBA_ASTC_4x4x4;
114   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4x4:
115      return MESA_FORMAT_RGBA_ASTC_5x4x4;
116   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x4:
117      return MESA_FORMAT_RGBA_ASTC_5x5x4;
118   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x5:
119      return MESA_FORMAT_RGBA_ASTC_5x5x5;
120   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5x5:
121      return MESA_FORMAT_RGBA_ASTC_6x5x5;
122   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x5:
123      return MESA_FORMAT_RGBA_ASTC_6x6x5;
124   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x6:
125      return MESA_FORMAT_RGBA_ASTC_6x6x6;
126   default:
127      return format;
128   }
129}
130
131/**
132 * For a linear format, return the corresponding sRGB color space format.
133 * For an sRGB format, return the format as-is.
134 * Assert-fails if the format is not sRGB and does not have an sRGB equivalent.
135 */
136mesa_format
137_mesa_get_linear_format_srgb(mesa_format format)
138{
139   switch (format) {
140   case MESA_FORMAT_A8B8G8R8_UNORM:
141      return MESA_FORMAT_A8B8G8R8_SRGB;
142   case MESA_FORMAT_B8G8R8A8_UNORM:
143      return MESA_FORMAT_B8G8R8A8_SRGB;
144   case MESA_FORMAT_A8R8G8B8_UNORM:
145      return MESA_FORMAT_A8R8G8B8_SRGB;
146   case MESA_FORMAT_B8G8R8X8_UNORM:
147      return MESA_FORMAT_B8G8R8X8_SRGB;
148   case MESA_FORMAT_X8R8G8B8_UNORM:
149      return MESA_FORMAT_X8R8G8B8_SRGB;
150   case MESA_FORMAT_R8G8B8A8_UNORM:
151      return MESA_FORMAT_R8G8B8A8_SRGB;
152   case MESA_FORMAT_R8G8B8X8_UNORM:
153      return MESA_FORMAT_R8G8B8X8_SRGB;
154   case MESA_FORMAT_X8B8G8R8_UNORM:
155      return MESA_FORMAT_X8B8G8R8_SRGB;
156   case MESA_FORMAT_R_UNORM8:
157      return MESA_FORMAT_R_SRGB8;
158   case MESA_FORMAT_L_UNORM8:
159      return MESA_FORMAT_L_SRGB8;
160   case MESA_FORMAT_RG_UNORM8:
161      return MESA_FORMAT_RG_SRGB8;
162   case MESA_FORMAT_LA_UNORM8:
163      return MESA_FORMAT_LA_SRGB8;
164   case MESA_FORMAT_BGR_UNORM8:
165      return MESA_FORMAT_BGR_SRGB8;
166   case MESA_FORMAT_RGB_DXT1:
167      return MESA_FORMAT_SRGB_DXT1;
168   case MESA_FORMAT_RGBA_DXT1:
169      return MESA_FORMAT_SRGBA_DXT1;
170   case MESA_FORMAT_RGBA_DXT3:
171      return MESA_FORMAT_SRGBA_DXT3;
172   case MESA_FORMAT_RGBA_DXT5:
173      return MESA_FORMAT_SRGBA_DXT5;
174   case MESA_FORMAT_ETC2_RGB8:
175      return MESA_FORMAT_ETC2_SRGB8;
176   case MESA_FORMAT_ETC2_RGBA8_EAC:
177      return MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC;
178   case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1:
179      return MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1;
180   case MESA_FORMAT_BPTC_RGBA_UNORM:
181      return MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM;
182   case MESA_FORMAT_RGBA_ASTC_4x4:
183      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4;
184   case MESA_FORMAT_RGBA_ASTC_5x4:
185      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4;
186   case MESA_FORMAT_RGBA_ASTC_5x5:
187      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5;
188   case MESA_FORMAT_RGBA_ASTC_6x5:
189      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5;
190   case MESA_FORMAT_RGBA_ASTC_6x6:
191      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6;
192   case MESA_FORMAT_RGBA_ASTC_8x5:
193      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x5;
194   case MESA_FORMAT_RGBA_ASTC_8x6:
195      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x6;
196   case MESA_FORMAT_RGBA_ASTC_8x8:
197      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x8;
198   case MESA_FORMAT_RGBA_ASTC_10x5:
199      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x5;
200   case MESA_FORMAT_RGBA_ASTC_10x6:
201      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x6;
202   case MESA_FORMAT_RGBA_ASTC_10x8:
203      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x8;
204   case MESA_FORMAT_RGBA_ASTC_10x10:
205      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x10;
206   case MESA_FORMAT_RGBA_ASTC_12x10:
207      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x10;
208   case MESA_FORMAT_RGBA_ASTC_12x12:
209      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x12;
210   case MESA_FORMAT_RGBA_ASTC_3x3x3:
211      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_3x3x3;
212   case MESA_FORMAT_RGBA_ASTC_4x3x3:
213      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x3x3;
214   case MESA_FORMAT_RGBA_ASTC_4x4x3:
215      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x3;
216   case MESA_FORMAT_RGBA_ASTC_4x4x4:
217      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x4;
218   case MESA_FORMAT_RGBA_ASTC_5x4x4:
219      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4x4;
220   case MESA_FORMAT_RGBA_ASTC_5x5x4:
221      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x4;
222   case MESA_FORMAT_RGBA_ASTC_5x5x5:
223      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x5;
224   case MESA_FORMAT_RGBA_ASTC_6x5x5:
225      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5x5;
226   case MESA_FORMAT_RGBA_ASTC_6x6x5:
227      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x5;
228   case MESA_FORMAT_RGBA_ASTC_6x6x6:
229      return MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x6;
230   case MESA_FORMAT_A8B8G8R8_SRGB:
231   case MESA_FORMAT_B8G8R8A8_SRGB:
232   case MESA_FORMAT_A8R8G8B8_SRGB:
233   case MESA_FORMAT_B8G8R8X8_SRGB:
234   case MESA_FORMAT_X8R8G8B8_SRGB:
235   case MESA_FORMAT_R8G8B8A8_SRGB:
236   case MESA_FORMAT_R8G8B8X8_SRGB:
237   case MESA_FORMAT_X8B8G8R8_SRGB:
238   case MESA_FORMAT_R_SRGB8:
239   case MESA_FORMAT_L_SRGB8:
240   case MESA_FORMAT_RG_SRGB8:
241   case MESA_FORMAT_LA_SRGB8:
242   case MESA_FORMAT_BGR_SRGB8:
243   case MESA_FORMAT_SRGB_DXT1:
244   case MESA_FORMAT_SRGBA_DXT1:
245   case MESA_FORMAT_SRGBA_DXT3:
246   case MESA_FORMAT_SRGBA_DXT5:
247   case MESA_FORMAT_ETC2_SRGB8:
248   case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC:
249   case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1:
250   case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
251   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4:
252   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4:
253   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5:
254   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5:
255   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6:
256   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x5:
257   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x6:
258   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_8x8:
259   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x5:
260   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x6:
261   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x8:
262   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_10x10:
263   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x10:
264   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_12x12:
265   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_3x3x3:
266   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x3x3:
267   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x3:
268   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_4x4x4:
269   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x4x4:
270   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x4:
271   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5x5:
272   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x5x5:
273   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x5:
274   case MESA_FORMAT_SRGB8_ALPHA8_ASTC_6x6x6:
275      return format;
276   default:
277      unreachable("Given format does not have an sRGB equivalent");
278   }
279}
280
281/**
282 * For an intensity format, return the corresponding red format.  For other
283 * formats, return the format as-is.
284 */
285mesa_format
286_mesa_get_intensity_format_red(mesa_format format)
287{
288   switch (format) {
289   case MESA_FORMAT_I_UNORM8:
290      return MESA_FORMAT_R_UNORM8;
291   case MESA_FORMAT_I_UNORM16:
292      return MESA_FORMAT_R_UNORM16;
293   case MESA_FORMAT_I_SNORM8:
294      return MESA_FORMAT_R_SNORM8;
295   case MESA_FORMAT_I_SNORM16:
296      return MESA_FORMAT_R_SNORM16;
297   case MESA_FORMAT_I_FLOAT16:
298      return MESA_FORMAT_R_FLOAT16;
299   case MESA_FORMAT_I_FLOAT32:
300      return MESA_FORMAT_R_FLOAT32;
301   case MESA_FORMAT_I_UINT8:
302      return MESA_FORMAT_R_UINT8;
303   case MESA_FORMAT_I_UINT16:
304      return MESA_FORMAT_R_UINT16;
305   case MESA_FORMAT_I_UINT32:
306      return MESA_FORMAT_R_UINT32;
307   case MESA_FORMAT_I_SINT8:
308      return MESA_FORMAT_R_SINT8;
309   case MESA_FORMAT_I_SINT16:
310      return MESA_FORMAT_R_SINT16;
311   case MESA_FORMAT_I_SINT32:
312      return MESA_FORMAT_R_SINT32;
313   default:
314      return format;
315   }
316}
317
318/**
319 * If the format has an alpha channel, and there exists a non-alpha
320 * variant of the format with an identical bit layout, then return
321 * the non-alpha format. Otherwise return the original format.
322 *
323 * Examples:
324 *    Fallback exists:
325 *       MESA_FORMAT_R8G8B8X8_UNORM -> MESA_FORMAT_R8G8B8A8_UNORM
326 *       MESA_FORMAT_RGBX_UNORM16 -> MESA_FORMAT_RGBA_UNORM16
327 *
328 *    No fallback:
329 *       MESA_FORMAT_R8G8B8A8_UNORM -> MESA_FORMAT_R8G8B8A8_UNORM
330 *       MESA_FORMAT_Z_FLOAT32 -> MESA_FORMAT_Z_FLOAT32
331 */
332mesa_format
333_mesa_format_fallback_rgbx_to_rgba(mesa_format format)
334{
335   switch (format) {
336   case MESA_FORMAT_X8B8G8R8_UNORM:
337      return MESA_FORMAT_A8B8G8R8_UNORM;
338   case MESA_FORMAT_R8G8B8X8_UNORM:
339      return MESA_FORMAT_R8G8B8A8_UNORM;
340   case MESA_FORMAT_B8G8R8X8_UNORM:
341      return MESA_FORMAT_B8G8R8A8_UNORM;
342   case MESA_FORMAT_X8R8G8B8_UNORM:
343      return MESA_FORMAT_A8R8G8B8_UNORM;
344   case MESA_FORMAT_B4G4R4X4_UNORM:
345      return MESA_FORMAT_B4G4R4A4_UNORM;
346   case MESA_FORMAT_X1B5G5R5_UNORM:
347      return MESA_FORMAT_A1B5G5R5_UNORM;
348   case MESA_FORMAT_B5G5R5X1_UNORM:
349      return MESA_FORMAT_B5G5R5A1_UNORM;
350   case MESA_FORMAT_B10G10R10X2_UNORM:
351      return MESA_FORMAT_B10G10R10A2_UNORM;
352   case MESA_FORMAT_R10G10B10X2_UNORM:
353      return MESA_FORMAT_R10G10B10A2_UNORM;
354   case MESA_FORMAT_RGBX_UNORM16:
355      return MESA_FORMAT_RGBA_UNORM16;
356   case MESA_FORMAT_X8B8G8R8_SNORM:
357      return MESA_FORMAT_A8B8G8R8_SNORM;
358   case MESA_FORMAT_R8G8B8X8_SNORM:
359      return MESA_FORMAT_R8G8B8A8_SNORM;
360   case MESA_FORMAT_RGBX_SNORM16:
361      return MESA_FORMAT_RGBA_SNORM16;
362   case MESA_FORMAT_B8G8R8X8_SRGB:
363      return MESA_FORMAT_B8G8R8A8_SRGB;
364   case MESA_FORMAT_X8R8G8B8_SRGB:
365      return MESA_FORMAT_A8R8G8B8_SRGB;
366   case MESA_FORMAT_R8G8B8X8_SRGB:
367      return MESA_FORMAT_R8G8B8A8_SRGB;
368   case MESA_FORMAT_X8B8G8R8_SRGB:
369      return MESA_FORMAT_A8B8G8R8_SRGB;
370   case MESA_FORMAT_RGBX_FLOAT16:
371      return MESA_FORMAT_RGBA_FLOAT16;
372   case MESA_FORMAT_RGBX_FLOAT32:
373      return MESA_FORMAT_RGBA_FLOAT32;
374   case MESA_FORMAT_RGBX_UINT16:
375      return MESA_FORMAT_RGBA_UINT16;
376   case MESA_FORMAT_RGBX_UINT32:
377      return MESA_FORMAT_RGBA_UINT32;
378   case MESA_FORMAT_RGBX_SINT8:
379      return MESA_FORMAT_RGBA_SINT8;
380   case MESA_FORMAT_RGBX_SINT16:
381      return MESA_FORMAT_RGBA_SINT16;
382   case MESA_FORMAT_RGBX_SINT32:
383      return MESA_FORMAT_RGBA_SINT32;
384   default:
385      return format;
386   }
387}
388