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