1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * Based on u_format.h which is:
6 * Copyright 2009-2010 VMware, Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 */
26
27 #ifndef VK_FORMAT_H
28 #define VK_FORMAT_H
29
30 #include <assert.h>
31 #include <vulkan/vulkan.h>
32 #include <util/macros.h>
33
34 enum vk_format_layout {
35 /**
36 * Formats with vk_format_block::width == vk_format_block::height == 1
37 * that can be described as an ordinary data structure.
38 */
39 VK_FORMAT_LAYOUT_PLAIN = 0,
40
41 /**
42 * Formats with sub-sampled channels.
43 *
44 * This is for formats like YVYU where there is less than one sample per
45 * pixel.
46 */
47 VK_FORMAT_LAYOUT_SUBSAMPLED = 3,
48
49 /**
50 * S3 Texture Compression formats.
51 */
52 VK_FORMAT_LAYOUT_S3TC = 4,
53
54 /**
55 * Red-Green Texture Compression formats.
56 */
57 VK_FORMAT_LAYOUT_RGTC = 5,
58
59 /**
60 * Ericsson Texture Compression
61 */
62 VK_FORMAT_LAYOUT_ETC = 6,
63
64 /**
65 * BC6/7 Texture Compression
66 */
67 VK_FORMAT_LAYOUT_BPTC = 7,
68
69 /**
70 * ASTC
71 */
72 VK_FORMAT_LAYOUT_ASTC = 8,
73
74 /**
75 * Everything else that doesn't fit in any of the above layouts.
76 */
77 VK_FORMAT_LAYOUT_OTHER = 9,
78
79 /**
80 * Formats that contain multiple planes.
81 */
82 VK_FORMAT_LAYOUT_MULTIPLANE = 10,
83 };
84
85 struct vk_format_block
86 {
87 /** Block width in pixels */
88 unsigned width;
89
90 /** Block height in pixels */
91 unsigned height;
92
93 /** Block size in bits */
94 unsigned bits;
95 };
96
97 enum vk_format_type {
98 VK_FORMAT_TYPE_VOID = 0,
99 VK_FORMAT_TYPE_UNSIGNED = 1,
100 VK_FORMAT_TYPE_SIGNED = 2,
101 VK_FORMAT_TYPE_FIXED = 3,
102 VK_FORMAT_TYPE_FLOAT = 4
103 };
104
105
106 enum vk_format_colorspace {
107 VK_FORMAT_COLORSPACE_RGB = 0,
108 VK_FORMAT_COLORSPACE_SRGB = 1,
109 VK_FORMAT_COLORSPACE_YUV = 2,
110 VK_FORMAT_COLORSPACE_ZS = 3
111 };
112
113 struct vk_format_channel_description {
114 unsigned type:5;
115 unsigned normalized:1;
116 unsigned pure_integer:1;
117 unsigned scaled:1;
118 unsigned size:8;
119 unsigned shift:16;
120 };
121
122 struct vk_format_description
123 {
124 VkFormat format;
125 const char *name;
126 const char *short_name;
127
128 struct vk_format_block block;
129 enum vk_format_layout layout;
130
131 unsigned nr_channels:3;
132 unsigned is_array:1;
133 unsigned is_bitmask:1;
134 unsigned is_mixed:1;
135
136 struct vk_format_channel_description channel[4];
137
138 unsigned char swizzle[4];
139
140 enum vk_format_colorspace colorspace;
141
142 unsigned plane_count:2;
143 unsigned width_divisor:2;
144 unsigned height_divisor:2;
145 VkFormat plane_formats[3];
146 };
147
148 extern const struct vk_format_description vk_format_description_table[];
149
150 const struct vk_format_description *vk_format_description(VkFormat format);
151
152 /**
153 * Return total bits needed for the pixel format per block.
154 */
155 static inline unsigned
vk_format_get_blocksizebits(VkFormat format)156 vk_format_get_blocksizebits(VkFormat format)
157 {
158 const struct vk_format_description *desc = vk_format_description(format);
159
160 assert(desc);
161 if (!desc) {
162 return 0;
163 }
164
165 return desc->block.bits;
166 }
167
168 /**
169 * Return bytes per block (not pixel) for the given format.
170 */
171 static inline unsigned
vk_format_get_blocksize(VkFormat format)172 vk_format_get_blocksize(VkFormat format)
173 {
174 unsigned bits = vk_format_get_blocksizebits(format);
175 unsigned bytes = bits / 8;
176
177 assert(bits % 8 == 0);
178 assert(bytes > 0);
179 if (bytes == 0) {
180 bytes = 1;
181 }
182
183 return bytes;
184 }
185
186 static inline unsigned
vk_format_get_blockwidth(VkFormat format)187 vk_format_get_blockwidth(VkFormat format)
188 {
189 const struct vk_format_description *desc = vk_format_description(format);
190
191 assert(desc);
192 if (!desc) {
193 return 1;
194 }
195
196 return desc->block.width;
197 }
198
199 static inline unsigned
vk_format_get_blockheight(VkFormat format)200 vk_format_get_blockheight(VkFormat format)
201 {
202 const struct vk_format_description *desc = vk_format_description(format);
203
204 assert(desc);
205 if (!desc) {
206 return 1;
207 }
208
209 return desc->block.height;
210 }
211
212 /**
213 * Return the index of the first non-void channel
214 * -1 if no non-void channels
215 */
216 static inline int
vk_format_get_first_non_void_channel(VkFormat format)217 vk_format_get_first_non_void_channel(VkFormat format)
218 {
219 const struct vk_format_description *desc = vk_format_description(format);
220 int i;
221
222 for (i = 0; i < 4; i++)
223 if (desc->channel[i].type != VK_FORMAT_TYPE_VOID)
224 break;
225
226 if (i == 4)
227 return -1;
228
229 return i;
230 }
231
232 enum vk_swizzle {
233 VK_SWIZZLE_X,
234 VK_SWIZZLE_Y,
235 VK_SWIZZLE_Z,
236 VK_SWIZZLE_W,
237 VK_SWIZZLE_0,
238 VK_SWIZZLE_1,
239 VK_SWIZZLE_NONE,
240 VK_SWIZZLE_MAX, /**< Number of enums counter (must be last) */
241 };
242
243 static inline VkImageAspectFlags
vk_format_aspects(VkFormat format)244 vk_format_aspects(VkFormat format)
245 {
246 switch (format) {
247 case VK_FORMAT_UNDEFINED:
248 return 0;
249
250 case VK_FORMAT_S8_UINT:
251 return VK_IMAGE_ASPECT_STENCIL_BIT;
252
253 case VK_FORMAT_D16_UNORM_S8_UINT:
254 case VK_FORMAT_D24_UNORM_S8_UINT:
255 case VK_FORMAT_D32_SFLOAT_S8_UINT:
256 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
257
258 case VK_FORMAT_D16_UNORM:
259 case VK_FORMAT_X8_D24_UNORM_PACK32:
260 case VK_FORMAT_D32_SFLOAT:
261 return VK_IMAGE_ASPECT_DEPTH_BIT;
262
263 default:
264 return VK_IMAGE_ASPECT_COLOR_BIT;
265 }
266 }
267
268 static inline enum vk_swizzle
radv_swizzle_conv(VkComponentSwizzle component,const unsigned char chan[4],VkComponentSwizzle vk_swiz)269 radv_swizzle_conv(VkComponentSwizzle component, const unsigned char chan[4], VkComponentSwizzle vk_swiz)
270 {
271 int x;
272
273 if (vk_swiz == VK_COMPONENT_SWIZZLE_IDENTITY)
274 vk_swiz = component;
275 switch (vk_swiz) {
276 case VK_COMPONENT_SWIZZLE_ZERO:
277 return VK_SWIZZLE_0;
278 case VK_COMPONENT_SWIZZLE_ONE:
279 return VK_SWIZZLE_1;
280 case VK_COMPONENT_SWIZZLE_R:
281 for (x = 0; x < 4; x++)
282 if (chan[x] == 0)
283 return (enum vk_swizzle)x;
284 return VK_SWIZZLE_0;
285 case VK_COMPONENT_SWIZZLE_G:
286 for (x = 0; x < 4; x++)
287 if (chan[x] == 1)
288 return (enum vk_swizzle)x;
289 return VK_SWIZZLE_0;
290 case VK_COMPONENT_SWIZZLE_B:
291 for (x = 0; x < 4; x++)
292 if (chan[x] == 2)
293 return (enum vk_swizzle)x;
294 return VK_SWIZZLE_0;
295 case VK_COMPONENT_SWIZZLE_A:
296 for (x = 0; x < 4; x++)
297 if (chan[x] == 3)
298 return (enum vk_swizzle)x;
299 return VK_SWIZZLE_1;
300 default:
301 unreachable("Illegal swizzle");
302 }
303 }
304
vk_format_compose_swizzles(const VkComponentMapping * mapping,const unsigned char swz[4],enum vk_swizzle dst[4])305 static inline void vk_format_compose_swizzles(const VkComponentMapping *mapping,
306 const unsigned char swz[4],
307 enum vk_swizzle dst[4])
308 {
309 dst[0] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_R, swz, mapping->r);
310 dst[1] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_G, swz, mapping->g);
311 dst[2] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_B, swz, mapping->b);
312 dst[3] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_A, swz, mapping->a);
313 }
314
315 static inline bool
vk_format_is_compressed(VkFormat format)316 vk_format_is_compressed(VkFormat format)
317 {
318 const struct vk_format_description *desc = vk_format_description(format);
319
320 assert(desc);
321 if (!desc) {
322 return false;
323 }
324
325 switch (desc->layout) {
326 case VK_FORMAT_LAYOUT_S3TC:
327 case VK_FORMAT_LAYOUT_RGTC:
328 case VK_FORMAT_LAYOUT_ETC:
329 case VK_FORMAT_LAYOUT_BPTC:
330 case VK_FORMAT_LAYOUT_ASTC:
331 /* XXX add other formats in the future */
332 return true;
333 default:
334 return false;
335 }
336 }
337
338 static inline bool
vk_format_is_subsampled(VkFormat format)339 vk_format_is_subsampled(VkFormat format)
340 {
341 const struct vk_format_description *desc = vk_format_description(format);
342
343 assert(desc);
344 if (!desc) {
345 return false;
346 }
347
348 return desc->layout == VK_FORMAT_LAYOUT_SUBSAMPLED;
349 }
350
351 static inline bool
vk_format_has_depth(const struct vk_format_description * desc)352 vk_format_has_depth(const struct vk_format_description *desc)
353 {
354 return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
355 desc->swizzle[0] != VK_SWIZZLE_NONE;
356 }
357
358 static inline bool
vk_format_has_stencil(const struct vk_format_description * desc)359 vk_format_has_stencil(const struct vk_format_description *desc)
360 {
361 return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
362 desc->swizzle[1] != VK_SWIZZLE_NONE;
363 }
364
365 static inline bool
vk_format_is_depth_or_stencil(VkFormat format)366 vk_format_is_depth_or_stencil(VkFormat format)
367 {
368 const struct vk_format_description *desc = vk_format_description(format);
369
370 assert(desc);
371 if (!desc) {
372 return false;
373 }
374
375 return vk_format_has_depth(desc) ||
376 vk_format_has_stencil(desc);
377 }
378
379 static inline bool
vk_format_is_depth(VkFormat format)380 vk_format_is_depth(VkFormat format)
381 {
382 const struct vk_format_description *desc = vk_format_description(format);
383
384 assert(desc);
385 if (!desc) {
386 return false;
387 }
388
389 return vk_format_has_depth(desc);
390 }
391
392 static inline bool
vk_format_is_stencil(VkFormat format)393 vk_format_is_stencil(VkFormat format)
394 {
395 const struct vk_format_description *desc = vk_format_description(format);
396
397 assert(desc);
398 if (!desc) {
399 return false;
400 }
401
402 return vk_format_has_stencil(desc);
403 }
404
405 static inline bool
vk_format_is_color(VkFormat format)406 vk_format_is_color(VkFormat format)
407 {
408 return !vk_format_is_depth_or_stencil(format);
409 }
410
411 static inline VkFormat
vk_format_depth_only(VkFormat format)412 vk_format_depth_only(VkFormat format)
413 {
414 switch (format) {
415 case VK_FORMAT_D16_UNORM_S8_UINT:
416 return VK_FORMAT_D16_UNORM;
417 case VK_FORMAT_D24_UNORM_S8_UINT:
418 return VK_FORMAT_X8_D24_UNORM_PACK32;
419 case VK_FORMAT_D32_SFLOAT_S8_UINT:
420 return VK_FORMAT_D32_SFLOAT;
421 default:
422 return format;
423 }
424 }
425
426 static inline bool
vk_format_is_int(VkFormat format)427 vk_format_is_int(VkFormat format)
428 {
429 const struct vk_format_description *desc = vk_format_description(format);
430 int channel = vk_format_get_first_non_void_channel(format);
431
432 return channel >= 0 && desc->channel[channel].pure_integer;
433 }
434
435 static inline bool
vk_format_is_srgb(VkFormat format)436 vk_format_is_srgb(VkFormat format)
437 {
438 const struct vk_format_description *desc = vk_format_description(format);
439 return desc->colorspace == VK_FORMAT_COLORSPACE_SRGB;
440 }
441
442 static inline VkFormat
vk_format_no_srgb(VkFormat format)443 vk_format_no_srgb(VkFormat format)
444 {
445 switch(format) {
446 case VK_FORMAT_R8_SRGB:
447 return VK_FORMAT_R8_UNORM;
448 case VK_FORMAT_R8G8_SRGB:
449 return VK_FORMAT_R8G8_UNORM;
450 case VK_FORMAT_R8G8B8_SRGB:
451 return VK_FORMAT_R8G8B8_UNORM;
452 case VK_FORMAT_B8G8R8_SRGB:
453 return VK_FORMAT_B8G8R8_UNORM;
454 case VK_FORMAT_R8G8B8A8_SRGB:
455 return VK_FORMAT_R8G8B8A8_UNORM;
456 case VK_FORMAT_B8G8R8A8_SRGB:
457 return VK_FORMAT_B8G8R8A8_UNORM;
458 case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
459 return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
460 case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
461 return VK_FORMAT_BC1_RGB_UNORM_BLOCK;
462 case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
463 return VK_FORMAT_BC1_RGBA_UNORM_BLOCK;
464 case VK_FORMAT_BC2_SRGB_BLOCK:
465 return VK_FORMAT_BC2_UNORM_BLOCK;
466 case VK_FORMAT_BC3_SRGB_BLOCK:
467 return VK_FORMAT_BC3_UNORM_BLOCK;
468 case VK_FORMAT_BC7_SRGB_BLOCK:
469 return VK_FORMAT_BC7_UNORM_BLOCK;
470 case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
471 return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
472 case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
473 return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
474 case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
475 return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
476 default:
477 assert(!vk_format_is_srgb(format));
478 return format;
479 }
480 }
481
482 static inline VkFormat
vk_format_stencil_only(VkFormat format)483 vk_format_stencil_only(VkFormat format)
484 {
485 return VK_FORMAT_S8_UINT;
486 }
487
488 static inline unsigned
vk_format_get_component_bits(VkFormat format,enum vk_format_colorspace colorspace,unsigned component)489 vk_format_get_component_bits(VkFormat format,
490 enum vk_format_colorspace colorspace,
491 unsigned component)
492 {
493 const struct vk_format_description *desc = vk_format_description(format);
494 enum vk_format_colorspace desc_colorspace;
495
496 assert(format);
497 if (!format) {
498 return 0;
499 }
500
501 assert(component < 4);
502
503 /* Treat RGB and SRGB as equivalent. */
504 if (colorspace == VK_FORMAT_COLORSPACE_SRGB) {
505 colorspace = VK_FORMAT_COLORSPACE_RGB;
506 }
507 if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
508 desc_colorspace = VK_FORMAT_COLORSPACE_RGB;
509 } else {
510 desc_colorspace = desc->colorspace;
511 }
512
513 if (desc_colorspace != colorspace) {
514 return 0;
515 }
516
517 switch (desc->swizzle[component]) {
518 case VK_SWIZZLE_X:
519 return desc->channel[0].size;
520 case VK_SWIZZLE_Y:
521 return desc->channel[1].size;
522 case VK_SWIZZLE_Z:
523 return desc->channel[2].size;
524 case VK_SWIZZLE_W:
525 return desc->channel[3].size;
526 default:
527 return 0;
528 }
529 }
530
531 static inline VkFormat
vk_to_non_srgb_format(VkFormat format)532 vk_to_non_srgb_format(VkFormat format)
533 {
534 switch(format) {
535 case VK_FORMAT_R8_SRGB :
536 return VK_FORMAT_R8_UNORM;
537 case VK_FORMAT_R8G8_SRGB:
538 return VK_FORMAT_R8G8_UNORM;
539 case VK_FORMAT_R8G8B8_SRGB:
540 return VK_FORMAT_R8G8B8_UNORM;
541 case VK_FORMAT_B8G8R8_SRGB:
542 return VK_FORMAT_B8G8R8_UNORM;
543 case VK_FORMAT_R8G8B8A8_SRGB :
544 return VK_FORMAT_R8G8B8A8_UNORM;
545 case VK_FORMAT_B8G8R8A8_SRGB:
546 return VK_FORMAT_B8G8R8A8_UNORM;
547 case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
548 return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
549 default:
550 return format;
551 }
552 }
553
554 static inline unsigned
vk_format_get_nr_components(VkFormat format)555 vk_format_get_nr_components(VkFormat format)
556 {
557 const struct vk_format_description *desc = vk_format_description(format);
558 return desc->nr_channels;
559 }
560
561 static inline unsigned
vk_format_get_plane_count(VkFormat format)562 vk_format_get_plane_count(VkFormat format)
563 {
564 const struct vk_format_description *desc = vk_format_description(format);
565
566 return desc->plane_count;
567 }
568
569 static inline VkFormat
vk_format_get_plane_format(VkFormat format,unsigned plane_id)570 vk_format_get_plane_format(VkFormat format, unsigned plane_id)
571 {
572 const struct vk_format_description *desc = vk_format_description(format);
573
574 if (desc->layout != VK_FORMAT_LAYOUT_MULTIPLANE) {
575 assert(plane_id == 0);
576 return format;
577 }
578
579 assert(plane_id < desc->plane_count);
580
581 return desc->plane_formats[plane_id];
582 }
583
584
585 #endif /* VK_FORMAT_H */
586