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