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 struct vk_format_block 81 { 82 /** Block width in pixels */ 83 unsigned width; 84 85 /** Block height in pixels */ 86 unsigned height; 87 88 /** Block size in bits */ 89 unsigned bits; 90 }; 91 92 enum vk_format_type { 93 VK_FORMAT_TYPE_VOID = 0, 94 VK_FORMAT_TYPE_UNSIGNED = 1, 95 VK_FORMAT_TYPE_SIGNED = 2, 96 VK_FORMAT_TYPE_FIXED = 3, 97 VK_FORMAT_TYPE_FLOAT = 4 98 }; 99 100 101 enum vk_format_colorspace { 102 VK_FORMAT_COLORSPACE_RGB = 0, 103 VK_FORMAT_COLORSPACE_SRGB = 1, 104 VK_FORMAT_COLORSPACE_YUV = 2, 105 VK_FORMAT_COLORSPACE_ZS = 3 106 }; 107 108 struct vk_format_channel_description { 109 unsigned type:5; 110 unsigned normalized:1; 111 unsigned pure_integer:1; 112 unsigned scaled:1; 113 unsigned size:8; 114 unsigned shift:16; 115 }; 116 117 struct vk_format_description 118 { 119 VkFormat format; 120 const char *name; 121 const char *short_name; 122 123 struct vk_format_block block; 124 enum vk_format_layout layout; 125 126 unsigned nr_channels:3; 127 unsigned is_array:1; 128 unsigned is_bitmask:1; 129 unsigned is_mixed:1; 130 131 struct vk_format_channel_description channel[4]; 132 133 unsigned char swizzle[4]; 134 135 enum vk_format_colorspace colorspace; 136 }; 137 138 extern const struct vk_format_description vk_format_description_table[]; 139 140 const struct vk_format_description *vk_format_description(VkFormat format); 141 142 /** 143 * Return total bits needed for the pixel format per block. 144 */ 145 static inline unsigned 146 vk_format_get_blocksizebits(VkFormat format) 147 { 148 const struct vk_format_description *desc = vk_format_description(format); 149 150 assert(desc); 151 if (!desc) { 152 return 0; 153 } 154 155 return desc->block.bits; 156 } 157 158 /** 159 * Return bytes per block (not pixel) for the given format. 160 */ 161 static inline unsigned 162 vk_format_get_blocksize(VkFormat format) 163 { 164 unsigned bits = vk_format_get_blocksizebits(format); 165 unsigned bytes = bits / 8; 166 167 assert(bits % 8 == 0); 168 assert(bytes > 0); 169 if (bytes == 0) { 170 bytes = 1; 171 } 172 173 return bytes; 174 } 175 176 static inline unsigned 177 vk_format_get_blockwidth(VkFormat format) 178 { 179 const struct vk_format_description *desc = vk_format_description(format); 180 181 assert(desc); 182 if (!desc) { 183 return 1; 184 } 185 186 return desc->block.width; 187 } 188 189 static inline unsigned 190 vk_format_get_blockheight(VkFormat format) 191 { 192 const struct vk_format_description *desc = vk_format_description(format); 193 194 assert(desc); 195 if (!desc) { 196 return 1; 197 } 198 199 return desc->block.height; 200 } 201 202 /** 203 * Return the index of the first non-void channel 204 * -1 if no non-void channels 205 */ 206 static inline int 207 vk_format_get_first_non_void_channel(VkFormat format) 208 { 209 const struct vk_format_description *desc = vk_format_description(format); 210 int i; 211 212 for (i = 0; i < 4; i++) 213 if (desc->channel[i].type != VK_FORMAT_TYPE_VOID) 214 break; 215 216 if (i == 4) 217 return -1; 218 219 return i; 220 } 221 222 enum vk_swizzle { 223 VK_SWIZZLE_X, 224 VK_SWIZZLE_Y, 225 VK_SWIZZLE_Z, 226 VK_SWIZZLE_W, 227 VK_SWIZZLE_0, 228 VK_SWIZZLE_1, 229 VK_SWIZZLE_NONE, 230 VK_SWIZZLE_MAX, /**< Number of enums counter (must be last) */ 231 }; 232 233 static inline VkImageAspectFlags 234 vk_format_aspects(VkFormat format) 235 { 236 switch (format) { 237 case VK_FORMAT_UNDEFINED: 238 return 0; 239 240 case VK_FORMAT_S8_UINT: 241 return VK_IMAGE_ASPECT_STENCIL_BIT; 242 243 case VK_FORMAT_D16_UNORM_S8_UINT: 244 case VK_FORMAT_D24_UNORM_S8_UINT: 245 case VK_FORMAT_D32_SFLOAT_S8_UINT: 246 return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 247 248 case VK_FORMAT_D16_UNORM: 249 case VK_FORMAT_X8_D24_UNORM_PACK32: 250 case VK_FORMAT_D32_SFLOAT: 251 return VK_IMAGE_ASPECT_DEPTH_BIT; 252 253 default: 254 return VK_IMAGE_ASPECT_COLOR_BIT; 255 } 256 } 257 258 static inline enum vk_swizzle 259 radv_swizzle_conv(VkComponentSwizzle component, const unsigned char chan[4], VkComponentSwizzle vk_swiz) 260 { 261 int x; 262 263 if (vk_swiz == VK_COMPONENT_SWIZZLE_IDENTITY) 264 vk_swiz = component; 265 switch (vk_swiz) { 266 case VK_COMPONENT_SWIZZLE_ZERO: 267 return VK_SWIZZLE_0; 268 case VK_COMPONENT_SWIZZLE_ONE: 269 return VK_SWIZZLE_1; 270 case VK_COMPONENT_SWIZZLE_R: 271 for (x = 0; x < 4; x++) 272 if (chan[x] == 0) 273 return x; 274 return VK_SWIZZLE_0; 275 case VK_COMPONENT_SWIZZLE_G: 276 for (x = 0; x < 4; x++) 277 if (chan[x] == 1) 278 return x; 279 return VK_SWIZZLE_0; 280 case VK_COMPONENT_SWIZZLE_B: 281 for (x = 0; x < 4; x++) 282 if (chan[x] == 2) 283 return x; 284 return VK_SWIZZLE_0; 285 case VK_COMPONENT_SWIZZLE_A: 286 for (x = 0; x < 4; x++) 287 if (chan[x] == 3) 288 return x; 289 return VK_SWIZZLE_1; 290 default: 291 unreachable("Illegal swizzle"); 292 } 293 } 294 295 static inline void vk_format_compose_swizzles(const VkComponentMapping *mapping, 296 const unsigned char swz[4], 297 enum vk_swizzle dst[4]) 298 { 299 dst[0] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_R, swz, mapping->r); 300 dst[1] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_G, swz, mapping->g); 301 dst[2] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_B, swz, mapping->b); 302 dst[3] = radv_swizzle_conv(VK_COMPONENT_SWIZZLE_A, swz, mapping->a); 303 } 304 305 static inline bool 306 vk_format_is_compressed(VkFormat format) 307 { 308 const struct vk_format_description *desc = vk_format_description(format); 309 310 assert(desc); 311 if (!desc) { 312 return false; 313 } 314 315 switch (desc->layout) { 316 case VK_FORMAT_LAYOUT_S3TC: 317 case VK_FORMAT_LAYOUT_RGTC: 318 case VK_FORMAT_LAYOUT_ETC: 319 case VK_FORMAT_LAYOUT_BPTC: 320 case VK_FORMAT_LAYOUT_ASTC: 321 /* XXX add other formats in the future */ 322 return true; 323 default: 324 return false; 325 } 326 } 327 328 static inline bool 329 vk_format_has_depth(const struct vk_format_description *desc) 330 { 331 return desc->colorspace == VK_FORMAT_COLORSPACE_ZS && 332 desc->swizzle[0] != VK_SWIZZLE_NONE; 333 } 334 335 static inline bool 336 vk_format_has_stencil(const struct vk_format_description *desc) 337 { 338 return desc->colorspace == VK_FORMAT_COLORSPACE_ZS && 339 desc->swizzle[1] != VK_SWIZZLE_NONE; 340 } 341 342 static inline bool 343 vk_format_is_depth_or_stencil(VkFormat format) 344 { 345 const struct vk_format_description *desc = vk_format_description(format); 346 347 assert(desc); 348 if (!desc) { 349 return false; 350 } 351 352 return vk_format_has_depth(desc) || 353 vk_format_has_stencil(desc); 354 } 355 356 static inline bool 357 vk_format_is_depth(VkFormat format) 358 { 359 const struct vk_format_description *desc = vk_format_description(format); 360 361 assert(desc); 362 if (!desc) { 363 return false; 364 } 365 366 return vk_format_has_depth(desc); 367 } 368 369 static inline bool 370 vk_format_is_stencil(VkFormat format) 371 { 372 const struct vk_format_description *desc = vk_format_description(format); 373 374 assert(desc); 375 if (!desc) { 376 return false; 377 } 378 379 return vk_format_has_stencil(desc); 380 } 381 382 static inline bool 383 vk_format_is_color(VkFormat format) 384 { 385 return !vk_format_is_depth_or_stencil(format); 386 } 387 388 static inline VkFormat 389 vk_format_depth_only(VkFormat format) 390 { 391 switch (format) { 392 case VK_FORMAT_D16_UNORM_S8_UINT: 393 return VK_FORMAT_D16_UNORM; 394 case VK_FORMAT_D24_UNORM_S8_UINT: 395 return VK_FORMAT_X8_D24_UNORM_PACK32; 396 case VK_FORMAT_D32_SFLOAT_S8_UINT: 397 return VK_FORMAT_D32_SFLOAT; 398 default: 399 return format; 400 } 401 } 402 403 static inline bool 404 vk_format_is_int(VkFormat format) 405 { 406 const struct vk_format_description *desc = vk_format_description(format); 407 int channel = vk_format_get_first_non_void_channel(format); 408 409 return channel >= 0 && desc->channel[channel].pure_integer; 410 } 411 412 static inline bool 413 vk_format_is_srgb(VkFormat format) 414 { 415 const struct vk_format_description *desc = vk_format_description(format); 416 return desc->colorspace == VK_FORMAT_COLORSPACE_SRGB; 417 } 418 419 static inline VkFormat 420 vk_format_stencil_only(VkFormat format) 421 { 422 return VK_FORMAT_S8_UINT; 423 } 424 425 static inline unsigned 426 vk_format_get_component_bits(VkFormat format, 427 enum vk_format_colorspace colorspace, 428 unsigned component) 429 { 430 const struct vk_format_description *desc = vk_format_description(format); 431 enum vk_format_colorspace desc_colorspace; 432 433 assert(format); 434 if (!format) { 435 return 0; 436 } 437 438 assert(component < 4); 439 440 /* Treat RGB and SRGB as equivalent. */ 441 if (colorspace == VK_FORMAT_COLORSPACE_SRGB) { 442 colorspace = VK_FORMAT_COLORSPACE_RGB; 443 } 444 if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) { 445 desc_colorspace = VK_FORMAT_COLORSPACE_RGB; 446 } else { 447 desc_colorspace = desc->colorspace; 448 } 449 450 if (desc_colorspace != colorspace) { 451 return 0; 452 } 453 454 switch (desc->swizzle[component]) { 455 case VK_SWIZZLE_X: 456 return desc->channel[0].size; 457 case VK_SWIZZLE_Y: 458 return desc->channel[1].size; 459 case VK_SWIZZLE_Z: 460 return desc->channel[2].size; 461 case VK_SWIZZLE_W: 462 return desc->channel[3].size; 463 default: 464 return 0; 465 } 466 } 467 468 static inline VkFormat 469 vk_to_non_srgb_format(VkFormat format) 470 { 471 switch(format) { 472 case VK_FORMAT_R8_SRGB : 473 return VK_FORMAT_R8_UNORM; 474 case VK_FORMAT_R8G8_SRGB: 475 return VK_FORMAT_R8G8_UNORM; 476 case VK_FORMAT_R8G8B8_SRGB: 477 return VK_FORMAT_R8G8B8_UNORM; 478 case VK_FORMAT_B8G8R8_SRGB: 479 return VK_FORMAT_B8G8R8_UNORM; 480 case VK_FORMAT_R8G8B8A8_SRGB : 481 return VK_FORMAT_R8G8B8A8_UNORM; 482 case VK_FORMAT_B8G8R8A8_SRGB: 483 return VK_FORMAT_B8G8R8A8_UNORM; 484 case VK_FORMAT_A8B8G8R8_SRGB_PACK32: 485 return VK_FORMAT_A8B8G8R8_UNORM_PACK32; 486 default: 487 return format; 488 } 489 } 490 491 #endif /* VK_FORMAT_H */ 492