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