• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #pragma once
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 #include <assert.h>
34 #include <vulkan/vulkan.h>
35 #include <util/macros.h>
36 enum vk_format_layout {
37 	/**
38 	 * Formats with vk_format_block::width == vk_format_block::height == 1
39 	 * that can be described as an ordinary data structure.
40 	 */
41 	VK_FORMAT_LAYOUT_PLAIN = 0,
42 
43 	/**
44 	 * Formats with sub-sampled channels.
45 	 *
46 	 * This is for formats like YVYU where there is less than one sample per
47 	 * pixel.
48 	 */
49 	VK_FORMAT_LAYOUT_SUBSAMPLED = 3,
50 
51 	/**
52 	 * S3 Texture Compression formats.
53 	 */
54 	VK_FORMAT_LAYOUT_S3TC = 4,
55 
56 	/**
57 	 * Red-Green Texture Compression formats.
58 	 */
59 	VK_FORMAT_LAYOUT_RGTC = 5,
60 
61 	/**
62 	 * Ericsson Texture Compression
63 	 */
64 	VK_FORMAT_LAYOUT_ETC = 6,
65 
66 	/**
67 	 * BC6/7 Texture Compression
68 	 */
69 	VK_FORMAT_LAYOUT_BPTC = 7,
70 
71 	/**
72 	 * ASTC
73 	 */
74 	VK_FORMAT_LAYOUT_ASTC = 8,
75 
76 	/**
77 	 * Everything else that doesn't fit in any of the above layouts.
78 	 */
79 	VK_FORMAT_LAYOUT_OTHER = 9
80 };
81 
82 struct vk_format_block
83 {
84 	/** Block width in pixels */
85 	unsigned width;
86 
87 	/** Block height in pixels */
88 	unsigned height;
89 
90 	/** Block size in bits */
91 	unsigned bits;
92 };
93 
94 enum vk_format_type {
95 	VK_FORMAT_TYPE_VOID = 0,
96 	VK_FORMAT_TYPE_UNSIGNED = 1,
97 	VK_FORMAT_TYPE_SIGNED = 2,
98 	VK_FORMAT_TYPE_FIXED = 3,
99 	VK_FORMAT_TYPE_FLOAT = 4
100 };
101 
102 
103 enum vk_format_colorspace {
104 	VK_FORMAT_COLORSPACE_RGB = 0,
105 	VK_FORMAT_COLORSPACE_SRGB = 1,
106 	VK_FORMAT_COLORSPACE_YUV = 2,
107 	VK_FORMAT_COLORSPACE_ZS = 3
108 };
109 
110 struct vk_format_channel_description {
111 	unsigned type:5;
112 	unsigned normalized:1;
113 	unsigned pure_integer:1;
114 	unsigned scaled:1;
115 	unsigned size:8;
116 	unsigned shift:16;
117 };
118 
119 struct vk_format_description
120 {
121 	VkFormat format;
122 	const char *name;
123 	const char *short_name;
124 
125 	struct vk_format_block block;
126 	enum vk_format_layout layout;
127 
128 	unsigned nr_channels:3;
129 	unsigned is_array:1;
130 	unsigned is_bitmask:1;
131 	unsigned is_mixed:1;
132 
133 	struct vk_format_channel_description channel[4];
134 
135 	unsigned char swizzle[4];
136 
137 	enum vk_format_colorspace colorspace;
138 };
139 
140 extern const struct vk_format_description vk_format_description_table[];
141 
142 const struct vk_format_description *vk_format_description(VkFormat format);
143 
144 /**
145  * Return total bits needed for the pixel format per block.
146  */
147 static inline unsigned
vk_format_get_blocksizebits(VkFormat format)148 vk_format_get_blocksizebits(VkFormat format)
149 {
150 	const struct vk_format_description *desc = vk_format_description(format);
151 
152 	assert(desc);
153 	if (!desc) {
154 		return 0;
155 	}
156 
157 	return desc->block.bits;
158 }
159 
160 /**
161  * Return bytes per block (not pixel) for the given format.
162  */
163 static inline unsigned
vk_format_get_blocksize(VkFormat format)164 vk_format_get_blocksize(VkFormat format)
165 {
166 	unsigned bits = vk_format_get_blocksizebits(format);
167 	unsigned bytes = bits / 8;
168 
169 	assert(bits % 8 == 0);
170 	assert(bytes > 0);
171 	if (bytes == 0) {
172 		bytes = 1;
173 	}
174 
175 	return bytes;
176 }
177 
178 static inline unsigned
vk_format_get_blockwidth(VkFormat format)179 vk_format_get_blockwidth(VkFormat format)
180 {
181 	const struct vk_format_description *desc = vk_format_description(format);
182 
183 	assert(desc);
184 	if (!desc) {
185 		return 1;
186 	}
187 
188 	return desc->block.width;
189 }
190 
191 static inline unsigned
vk_format_get_blockheight(VkFormat format)192 vk_format_get_blockheight(VkFormat format)
193 {
194 	const struct vk_format_description *desc = vk_format_description(format);
195 
196 	assert(desc);
197 	if (!desc) {
198 		return 1;
199 	}
200 
201 	return desc->block.height;
202 }
203 
204 /**
205  * Return the index of the first non-void channel
206  * -1 if no non-void channels
207  */
208 static inline int
vk_format_get_first_non_void_channel(VkFormat format)209 vk_format_get_first_non_void_channel(VkFormat format)
210 {
211 	const struct vk_format_description *desc = vk_format_description(format);
212 	int i;
213 
214 	for (i = 0; i < 4; i++)
215 		if (desc->channel[i].type != VK_FORMAT_TYPE_VOID)
216 			break;
217 
218 	if (i == 4)
219 		return -1;
220 
221 	return i;
222 }
223 
224 enum vk_swizzle {
225 	VK_SWIZZLE_X,
226 	VK_SWIZZLE_Y,
227 	VK_SWIZZLE_Z,
228 	VK_SWIZZLE_W,
229 	VK_SWIZZLE_0,
230 	VK_SWIZZLE_1,
231 	VK_SWIZZLE_NONE,
232 	VK_SWIZZLE_MAX, /**< Number of enums counter (must be last) */
233 };
234 
235 static inline VkImageAspectFlags
vk_format_aspects(VkFormat format)236 vk_format_aspects(VkFormat format)
237 {
238 	switch (format) {
239 	case VK_FORMAT_UNDEFINED:
240 		return 0;
241 
242 	case VK_FORMAT_S8_UINT:
243 		return VK_IMAGE_ASPECT_STENCIL_BIT;
244 
245 	case VK_FORMAT_D16_UNORM_S8_UINT:
246 	case VK_FORMAT_D24_UNORM_S8_UINT:
247 	case VK_FORMAT_D32_SFLOAT_S8_UINT:
248 		return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
249 
250 	case VK_FORMAT_D16_UNORM:
251 	case VK_FORMAT_X8_D24_UNORM_PACK32:
252 	case VK_FORMAT_D32_SFLOAT:
253 		return VK_IMAGE_ASPECT_DEPTH_BIT;
254 
255 	default:
256 		return VK_IMAGE_ASPECT_COLOR_BIT;
257 	}
258 }
259 
260 static inline enum vk_swizzle
radv_swizzle_conv(VkComponentSwizzle component,const unsigned char chan[4],VkComponentSwizzle vk_swiz)261 radv_swizzle_conv(VkComponentSwizzle component, const unsigned char chan[4], VkComponentSwizzle vk_swiz)
262 {
263 	int x;
264 
265 	if (vk_swiz == VK_COMPONENT_SWIZZLE_IDENTITY)
266 		vk_swiz = component;
267 	switch (vk_swiz) {
268 	case VK_COMPONENT_SWIZZLE_ZERO:
269 		return VK_SWIZZLE_0;
270 	case VK_COMPONENT_SWIZZLE_ONE:
271 		return VK_SWIZZLE_1;
272 	case VK_COMPONENT_SWIZZLE_R:
273 		for (x = 0; x < 4; x++)
274 			if (chan[x] == 0)
275 				return x;
276 		return VK_SWIZZLE_0;
277 	case VK_COMPONENT_SWIZZLE_G:
278 		for (x = 0; x < 4; x++)
279 			if (chan[x] == 1)
280 				return x;
281 		return VK_SWIZZLE_0;
282 	case VK_COMPONENT_SWIZZLE_B:
283 		for (x = 0; x < 4; x++)
284 			if (chan[x] == 2)
285 				return x;
286 		return VK_SWIZZLE_0;
287 	case VK_COMPONENT_SWIZZLE_A:
288 		for (x = 0; x < 4; x++)
289 			if (chan[x] == 3)
290 				return x;
291 		return VK_SWIZZLE_1;
292 	default:
293 		unreachable("Illegal swizzle");
294 	}
295 }
296 
vk_format_compose_swizzles(const VkComponentMapping * mapping,const unsigned char swz[4],enum vk_swizzle dst[4])297 static inline void vk_format_compose_swizzles(const VkComponentMapping *mapping,
298 					      const unsigned char swz[4],
299 					      enum vk_swizzle dst[4])
300 {
301 	dst[0] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_R, swz, mapping->r);
302 	dst[1] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_G, swz, mapping->g);
303 	dst[2] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_B, swz, mapping->b);
304 	dst[3] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_A, swz, mapping->a);
305 }
306 
307 static inline bool
vk_format_is_compressed(VkFormat format)308 vk_format_is_compressed(VkFormat format)
309 {
310 	const struct vk_format_description *desc = vk_format_description(format);
311 
312 	assert(desc);
313 	if (!desc) {
314 		return false;
315 	}
316 
317 	switch (desc->layout) {
318 	case VK_FORMAT_LAYOUT_S3TC:
319 	case VK_FORMAT_LAYOUT_RGTC:
320 	case VK_FORMAT_LAYOUT_ETC:
321 	case VK_FORMAT_LAYOUT_BPTC:
322 	case VK_FORMAT_LAYOUT_ASTC:
323 		/* XXX add other formats in the future */
324 		return true;
325 	default:
326 		return false;
327 	}
328 }
329 
330 static inline bool
vk_format_has_depth(const struct vk_format_description * desc)331 vk_format_has_depth(const struct vk_format_description *desc)
332 {
333 	return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
334 		desc->swizzle[0] != VK_SWIZZLE_NONE;
335 }
336 
337 static inline bool
vk_format_has_stencil(const struct vk_format_description * desc)338 vk_format_has_stencil(const struct vk_format_description *desc)
339 {
340 	return desc->colorspace == VK_FORMAT_COLORSPACE_ZS &&
341 		desc->swizzle[1] != VK_SWIZZLE_NONE;
342 }
343 
344 static inline bool
vk_format_is_depth_or_stencil(VkFormat format)345 vk_format_is_depth_or_stencil(VkFormat format)
346 {
347 	const struct vk_format_description *desc = vk_format_description(format);
348 
349 	assert(desc);
350 	if (!desc) {
351 		return false;
352 	}
353 
354 	return vk_format_has_depth(desc) ||
355 		vk_format_has_stencil(desc);
356 }
357 
358 static inline bool
vk_format_is_depth(VkFormat format)359 vk_format_is_depth(VkFormat format)
360 {
361 	const struct vk_format_description *desc = vk_format_description(format);
362 
363 	assert(desc);
364 	if (!desc) {
365 		return false;
366 	}
367 
368 	return vk_format_has_depth(desc);
369 }
370 
371 static inline bool
vk_format_is_color(VkFormat format)372 vk_format_is_color(VkFormat format)
373 {
374 	return !vk_format_is_depth_or_stencil(format);
375 }
376 
377 static inline VkFormat
vk_format_depth_only(VkFormat format)378 vk_format_depth_only(VkFormat format)
379 {
380 	switch (format) {
381 	case VK_FORMAT_D16_UNORM_S8_UINT:
382 		return VK_FORMAT_D16_UNORM;
383 	case VK_FORMAT_D24_UNORM_S8_UINT:
384 		return VK_FORMAT_X8_D24_UNORM_PACK32;
385 	case VK_FORMAT_D32_SFLOAT_S8_UINT:
386 		return VK_FORMAT_D32_SFLOAT;
387 	default:
388 		return format;
389 	}
390 }
391 
392 static inline bool
vk_format_is_int(VkFormat format)393 vk_format_is_int(VkFormat format)
394 {
395 	const struct vk_format_description *desc = vk_format_description(format);
396 	int channel =  vk_format_get_first_non_void_channel(format);
397 
398 	return channel >= 0 && desc->channel[channel].pure_integer;
399 }
400 
401 static inline VkFormat
vk_format_stencil_only(VkFormat format)402 vk_format_stencil_only(VkFormat format)
403 {
404 	return VK_FORMAT_S8_UINT;
405 }
406 
407 static inline unsigned
vk_format_get_component_bits(VkFormat format,enum vk_format_colorspace colorspace,unsigned component)408 vk_format_get_component_bits(VkFormat format,
409 			     enum vk_format_colorspace colorspace,
410 			     unsigned component)
411 {
412 	const struct vk_format_description *desc = vk_format_description(format);
413 	enum vk_format_colorspace desc_colorspace;
414 
415 	assert(format);
416 	if (!format) {
417 		return 0;
418 	}
419 
420 	assert(component < 4);
421 
422 	/* Treat RGB and SRGB as equivalent. */
423 	if (colorspace == VK_FORMAT_COLORSPACE_SRGB) {
424 		colorspace = VK_FORMAT_COLORSPACE_RGB;
425 	}
426 	if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) {
427 		desc_colorspace = VK_FORMAT_COLORSPACE_RGB;
428 	} else {
429 		desc_colorspace = desc->colorspace;
430 	}
431 
432 	if (desc_colorspace != colorspace) {
433 		return 0;
434 	}
435 
436 	switch (desc->swizzle[component]) {
437 	case VK_SWIZZLE_X:
438 		return desc->channel[0].size;
439 	case VK_SWIZZLE_Y:
440 		return desc->channel[1].size;
441 	case VK_SWIZZLE_Z:
442 		return desc->channel[2].size;
443 	case VK_SWIZZLE_W:
444 		return desc->channel[3].size;
445 	default:
446 		return 0;
447 	}
448 }
449 #ifdef __cplusplus
450 } // extern "C" {
451 #endif
452