vulkan/wsi/x11: add support to detect if we can support rendering (v3)
[mesa.git] / src / amd / vulkan / vk_format_parse.py
1 #!/usr/bin/env python
2
3 '''
4 /**************************************************************************
5 *
6 * Copyright 2009 VMware, Inc.
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sub license, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
19 * of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
25 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 *
29 **************************************************************************/
30 '''
31
32
33 VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
34
35 SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
36
37 PLAIN = 'plain'
38 SCALED = 'scaled'
39
40 RGB = 'rgb'
41 SRGB = 'srgb'
42 YUV = 'yuv'
43 ZS = 'zs'
44
45
46 def is_pot(x):
47 return (x & (x - 1)) == 0
48
49
50 VERY_LARGE = 99999999999999999999999
51
52
53 class Channel:
54 '''Describe the channel of a color channel.'''
55
56 def __init__(self, type, norm, pure, scaled, size, name = ''):
57 self.type = type
58 self.norm = norm
59 self.pure = pure
60 self.size = size
61 self.scaled = scaled
62 self.sign = type in (SIGNED, FIXED, FLOAT)
63 self.name = name
64
65 def __str__(self):
66 s = str(self.type)
67 if self.norm:
68 s += 'n'
69 if self.pure:
70 s += 'p'
71 if self.scaled:
72 s += 's'
73 s += str(self.size)
74 return s
75
76 def __eq__(self, other):
77 return self.type == other.type and self.norm == other.norm and self.pure == other.pure and self.size == other.size and self.scaled == other.scaled
78
79 def max(self):
80 '''Maximum representable number.'''
81 if self.type == FLOAT:
82 return VERY_LARGE
83 if self.type == FIXED:
84 return (1 << (self.size/2)) - 1
85 if self.norm:
86 return 1
87 if self.type == UNSIGNED:
88 return (1 << self.size) - 1
89 if self.type == SIGNED:
90 return (1 << (self.size - 1)) - 1
91 assert False
92
93 def min(self):
94 '''Minimum representable number.'''
95 if self.type == FLOAT:
96 return -VERY_LARGE
97 if self.type == FIXED:
98 return -(1 << (self.size/2))
99 if self.type == UNSIGNED:
100 return 0
101 if self.norm:
102 return -1
103 if self.type == SIGNED:
104 return -(1 << (self.size - 1))
105 assert False
106
107
108 class Format:
109 '''Describe a pixel format.'''
110
111 def __init__(self, name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace):
112 self.name = name
113 self.layout = layout
114 self.block_width = block_width
115 self.block_height = block_height
116 self.le_channels = le_channels
117 self.le_swizzles = le_swizzles
118 self.be_channels = be_channels
119 self.be_swizzles = be_swizzles
120 self.name = name
121 self.colorspace = colorspace
122
123 def __str__(self):
124 return self.name
125
126 def short_name(self):
127 '''Make up a short norm for a format, suitable to be used as suffix in
128 function names.'''
129
130 name = self.name
131 if name.startswith('VK_FORMAT_'):
132 name = name[len('VK_FORMAT_'):]
133 name = name.lower()
134 return name
135
136 def block_size(self):
137 size = 0
138 for channel in self.le_channels:
139 size += channel.size
140 return size
141
142 def nr_channels(self):
143 nr_channels = 0
144 for channel in self.le_channels:
145 if channel.size:
146 nr_channels += 1
147 return nr_channels
148
149 def array_element(self):
150 if self.layout != PLAIN:
151 return None
152 ref_channel = self.le_channels[0]
153 if ref_channel.type == VOID:
154 ref_channel = self.le_channels[1]
155 for channel in self.le_channels:
156 if channel.size and (channel.size != ref_channel.size or channel.size % 8):
157 return None
158 if channel.type != VOID:
159 if channel.type != ref_channel.type:
160 return None
161 if channel.norm != ref_channel.norm:
162 return None
163 if channel.pure != ref_channel.pure:
164 return None
165 if channel.scaled != ref_channel.scaled:
166 return None
167 return ref_channel
168
169 def is_array(self):
170 return self.array_element() != None
171
172 def is_mixed(self):
173 if self.layout != PLAIN:
174 return False
175 ref_channel = self.le_channels[0]
176 if ref_channel.type == VOID:
177 ref_channel = self.le_channels[1]
178 for channel in self.le_channels[1:]:
179 if channel.type != VOID:
180 if channel.type != ref_channel.type:
181 return True
182 if channel.norm != ref_channel.norm:
183 return True
184 if channel.pure != ref_channel.pure:
185 return True
186 if channel.scaled != ref_channel.scaled:
187 return True
188 return False
189
190 def is_pot(self):
191 return is_pot(self.block_size())
192
193 def is_int(self):
194 if self.layout != PLAIN:
195 return False
196 for channel in self.le_channels:
197 if channel.type not in (VOID, UNSIGNED, SIGNED):
198 return False
199 return True
200
201 def is_float(self):
202 if self.layout != PLAIN:
203 return False
204 for channel in self.le_channels:
205 if channel.type not in (VOID, FLOAT):
206 return False
207 return True
208
209 def is_bitmask(self):
210 if self.layout != PLAIN:
211 return False
212 if self.block_size() not in (8, 16, 32):
213 return False
214 for channel in self.le_channels:
215 if channel.type not in (VOID, UNSIGNED, SIGNED):
216 return False
217 return True
218
219 def is_pure_color(self):
220 if self.layout != PLAIN or self.colorspace == ZS:
221 return False
222 pures = [channel.pure
223 for channel in self.le_channels
224 if channel.type != VOID]
225 for x in pures:
226 assert x == pures[0]
227 return pures[0]
228
229 def channel_type(self):
230 types = [channel.type
231 for channel in self.le_channels
232 if channel.type != VOID]
233 for x in types:
234 assert x == types[0]
235 return types[0]
236
237 def is_pure_signed(self):
238 return self.is_pure_color() and self.channel_type() == SIGNED
239
240 def is_pure_unsigned(self):
241 return self.is_pure_color() and self.channel_type() == UNSIGNED
242
243 def has_channel(self, id):
244 return self.le_swizzles[id] != SWIZZLE_NONE
245
246 def has_depth(self):
247 return self.colorspace == ZS and self.has_channel(0)
248
249 def has_stencil(self):
250 return self.colorspace == ZS and self.has_channel(1)
251
252 def stride(self):
253 return self.block_size()/8
254
255
256 _type_parse_map = {
257 '': VOID,
258 'x': VOID,
259 'u': UNSIGNED,
260 's': SIGNED,
261 'h': FIXED,
262 'f': FLOAT,
263 }
264
265 _swizzle_parse_map = {
266 'x': SWIZZLE_X,
267 'y': SWIZZLE_Y,
268 'z': SWIZZLE_Z,
269 'w': SWIZZLE_W,
270 '0': SWIZZLE_0,
271 '1': SWIZZLE_1,
272 '_': SWIZZLE_NONE,
273 }
274
275 def _parse_channels(fields, layout, colorspace, swizzles):
276 if layout == PLAIN:
277 names = ['']*4
278 if colorspace in (RGB, SRGB):
279 for i in range(4):
280 swizzle = swizzles[i]
281 if swizzle < 4:
282 names[swizzle] += 'rgba'[i]
283 elif colorspace == ZS:
284 for i in range(4):
285 swizzle = swizzles[i]
286 if swizzle < 4:
287 names[swizzle] += 'zs'[i]
288 else:
289 assert False
290 for i in range(4):
291 if names[i] == '':
292 names[i] = 'x'
293 else:
294 names = ['x', 'y', 'z', 'w']
295
296 channels = []
297 for i in range(0, 4):
298 field = fields[i]
299 if field:
300 type = _type_parse_map[field[0]]
301 if field[1] == 'n':
302 norm = True
303 pure = False
304 scaled = False
305 size = int(field[2:])
306 elif field[1] == 'p':
307 pure = True
308 norm = False
309 scaled = False
310 size = int(field[2:])
311 elif field[1] == 's':
312 pure = False
313 norm = False
314 scaled = True
315 size = int(field[2:])
316 else:
317 norm = False
318 pure = False
319 scaled = False
320 size = int(field[1:])
321 else:
322 type = VOID
323 norm = False
324 pure = False
325 scaled = False
326 size = 0
327 channel = Channel(type, norm, pure, scaled, size, names[i])
328 channels.append(channel)
329
330 return channels
331
332 def parse(filename):
333 '''Parse the format description in CSV format in terms of the
334 Channel and Format classes above.'''
335
336 stream = open(filename)
337 formats = []
338 for line in stream:
339 try:
340 comment = line.index('#')
341 except ValueError:
342 pass
343 else:
344 line = line[:comment]
345 line = line.strip()
346 if not line:
347 continue
348
349 fields = [field.strip() for field in line.split(',')]
350 if len (fields) < 10:
351 continue
352 if len (fields) == 10:
353 fields += fields[4:9]
354 assert len (fields) == 15
355
356 name = fields[0]
357 layout = fields[1]
358 block_width, block_height = map(int, fields[2:4])
359 colorspace = fields[9]
360
361 le_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
362 le_channels = _parse_channels(fields[4:8], layout, colorspace, le_swizzles)
363
364 be_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[14]]
365 be_channels = _parse_channels(fields[10:14], layout, colorspace, be_swizzles)
366
367 le_shift = 0
368 for channel in le_channels:
369 channel.shift = le_shift
370 le_shift += channel.size
371
372 be_shift = 0
373 for channel in be_channels[3::-1]:
374 channel.shift = be_shift
375 be_shift += channel.size
376
377 assert le_shift == be_shift
378 for i in range(4):
379 assert (le_swizzles[i] != SWIZZLE_NONE) == (be_swizzles[i] != SWIZZLE_NONE)
380
381 format = Format(name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace)
382 formats.append(format)
383 return formats
384