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