st/dri: Use fence extension in drisw.c
[mesa.git] / src / gallium / auxiliary / util / u_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
38 RGB = 'rgb'
39 SRGB = 'srgb'
40 YUV = 'yuv'
41 ZS = 'zs'
42
43
44 def is_pot(x):
45 return (x & (x - 1)) == 0
46
47
48 VERY_LARGE = 99999999999999999999999
49
50
51 class Channel:
52 '''Describe the channel of a color channel.'''
53
54 def __init__(self, type, norm, pure, size, name = ''):
55 self.type = type
56 self.norm = norm
57 self.pure = pure
58 self.size = size
59 self.sign = type in (SIGNED, FIXED, FLOAT)
60 self.name = name
61
62 def __str__(self):
63 s = str(self.type)
64 if self.norm:
65 s += 'n'
66 if self.pure:
67 s += 'p'
68 s += str(self.size)
69 return s
70
71 def __eq__(self, other):
72 return self.type == other.type and self.norm == other.norm and self.pure == other.pure and self.size == other.size
73
74 def max(self):
75 '''Maximum representable number.'''
76 if self.type == FLOAT:
77 return VERY_LARGE
78 if self.type == FIXED:
79 return (1 << (self.size/2)) - 1
80 if self.norm:
81 return 1
82 if self.type == UNSIGNED:
83 return (1 << self.size) - 1
84 if self.type == SIGNED:
85 return (1 << (self.size - 1)) - 1
86 assert False
87
88 def min(self):
89 '''Minimum representable number.'''
90 if self.type == FLOAT:
91 return -VERY_LARGE
92 if self.type == FIXED:
93 return -(1 << (self.size/2))
94 if self.type == UNSIGNED:
95 return 0
96 if self.norm:
97 return -1
98 if self.type == SIGNED:
99 return -(1 << (self.size - 1))
100 assert False
101
102
103 class Format:
104 '''Describe a pixel format.'''
105
106 def __init__(self, name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace):
107 self.name = name
108 self.layout = layout
109 self.block_width = block_width
110 self.block_height = block_height
111 self.le_channels = le_channels
112 self.le_swizzles = le_swizzles
113 self.be_channels = be_channels
114 self.be_swizzles = be_swizzles
115 self.name = name
116 self.colorspace = colorspace
117
118 def __str__(self):
119 return self.name
120
121 def short_name(self):
122 '''Make up a short norm for a format, suitable to be used as suffix in
123 function names.'''
124
125 name = self.name
126 if name.startswith('PIPE_FORMAT_'):
127 name = name[len('PIPE_FORMAT_'):]
128 name = name.lower()
129 return name
130
131 def block_size(self):
132 size = 0
133 for channel in self.le_channels:
134 size += channel.size
135 return size
136
137 def nr_channels(self):
138 nr_channels = 0
139 for channel in self.le_channels:
140 if channel.size:
141 nr_channels += 1
142 return nr_channels
143
144 def array_element(self):
145 if self.layout != PLAIN:
146 return None
147 ref_channel = self.le_channels[0]
148 if ref_channel.type == VOID:
149 ref_channel = self.le_channels[1]
150 for channel in self.le_channels:
151 if channel.size and (channel.size != ref_channel.size or channel.size % 8):
152 return None
153 if channel.type != VOID:
154 if channel.type != ref_channel.type:
155 return None
156 if channel.norm != ref_channel.norm:
157 return None
158 if channel.pure != ref_channel.pure:
159 return None
160 return ref_channel
161
162 def is_array(self):
163 return self.array_element() != None
164
165 def is_mixed(self):
166 if self.layout != PLAIN:
167 return False
168 ref_channel = self.le_channels[0]
169 if ref_channel.type == VOID:
170 ref_channel = self.le_channels[1]
171 for channel in self.le_channels[1:]:
172 if channel.type != VOID:
173 if channel.type != ref_channel.type:
174 return True
175 if channel.norm != ref_channel.norm:
176 return True
177 if channel.pure != ref_channel.pure:
178 return True
179 return False
180
181 def is_pot(self):
182 return is_pot(self.block_size())
183
184 def is_int(self):
185 if self.layout != PLAIN:
186 return False
187 for channel in self.le_channels:
188 if channel.type not in (VOID, UNSIGNED, SIGNED):
189 return False
190 return True
191
192 def is_float(self):
193 if self.layout != PLAIN:
194 return False
195 for channel in self.le_channels:
196 if channel.type not in (VOID, FLOAT):
197 return False
198 return True
199
200 def is_bitmask(self):
201 if self.layout != PLAIN:
202 return False
203 if self.block_size() not in (8, 16, 32):
204 return False
205 for channel in self.le_channels:
206 if channel.type not in (VOID, UNSIGNED, SIGNED):
207 return False
208 return True
209
210 def is_pure_color(self):
211 if self.layout != PLAIN or self.colorspace == ZS:
212 return False
213 pures = [channel.pure
214 for channel in self.le_channels
215 if channel.type != VOID]
216 for x in pures:
217 assert x == pures[0]
218 return pures[0]
219
220 def channel_type(self):
221 types = [channel.type
222 for channel in self.le_channels
223 if channel.type != VOID]
224 for x in types:
225 assert x == types[0]
226 return types[0]
227
228 def is_pure_signed(self):
229 return self.is_pure_color() and self.channel_type() == SIGNED
230
231 def is_pure_unsigned(self):
232 return self.is_pure_color() and self.channel_type() == UNSIGNED
233
234 def has_channel(self, id):
235 return self.le_swizzles[id] != SWIZZLE_NONE
236
237 def has_depth(self):
238 return self.colorspace == ZS and self.has_channel(0)
239
240 def has_stencil(self):
241 return self.colorspace == ZS and self.has_channel(1)
242
243 def stride(self):
244 return self.block_size()/8
245
246
247 _type_parse_map = {
248 '': VOID,
249 'x': VOID,
250 'u': UNSIGNED,
251 's': SIGNED,
252 'h': FIXED,
253 'f': FLOAT,
254 }
255
256 _swizzle_parse_map = {
257 'x': SWIZZLE_X,
258 'y': SWIZZLE_Y,
259 'z': SWIZZLE_Z,
260 'w': SWIZZLE_W,
261 '0': SWIZZLE_0,
262 '1': SWIZZLE_1,
263 '_': SWIZZLE_NONE,
264 }
265
266 def _parse_channels(fields, layout, colorspace, swizzles):
267 if layout == PLAIN:
268 names = ['']*4
269 if colorspace in (RGB, SRGB):
270 for i in range(4):
271 swizzle = swizzles[i]
272 if swizzle < 4:
273 names[swizzle] += 'rgba'[i]
274 elif colorspace == ZS:
275 for i in range(4):
276 swizzle = swizzles[i]
277 if swizzle < 4:
278 names[swizzle] += 'zs'[i]
279 else:
280 assert False
281 for i in range(4):
282 if names[i] == '':
283 names[i] = 'x'
284 else:
285 names = ['x', 'y', 'z', 'w']
286
287 channels = []
288 for i in range(0, 4):
289 field = fields[i]
290 if field:
291 type = _type_parse_map[field[0]]
292 if field[1] == 'n':
293 norm = True
294 pure = False
295 size = int(field[2:])
296 elif field[1] == 'p':
297 pure = True
298 norm = False
299 size = int(field[2:])
300 else:
301 norm = False
302 pure = False
303 size = int(field[1:])
304 else:
305 type = VOID
306 norm = False
307 pure = False
308 size = 0
309 channel = Channel(type, norm, pure, size, names[i])
310 channels.append(channel)
311
312 return channels
313
314 def parse(filename):
315 '''Parse the format description in CSV format in terms of the
316 Channel and Format classes above.'''
317
318 stream = open(filename)
319 formats = []
320 for line in stream:
321 try:
322 comment = line.index('#')
323 except ValueError:
324 pass
325 else:
326 line = line[:comment]
327 line = line.strip()
328 if not line:
329 continue
330
331 fields = [field.strip() for field in line.split(',')]
332 if len (fields) == 10:
333 fields += fields[4:9]
334 assert len (fields) == 15
335
336 name = fields[0]
337 layout = fields[1]
338 block_width, block_height = map(int, fields[2:4])
339 colorspace = fields[9]
340
341 le_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
342 le_channels = _parse_channels(fields[4:8], layout, colorspace, le_swizzles)
343
344 be_swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[14]]
345 be_channels = _parse_channels(fields[10:14], layout, colorspace, be_swizzles)
346
347 le_shift = 0
348 for channel in le_channels:
349 channel.shift = le_shift
350 le_shift += channel.size
351
352 be_shift = 0
353 for channel in be_channels[3::-1]:
354 channel.shift = be_shift
355 be_shift += channel.size
356
357 assert le_shift == be_shift
358 for i in range(4):
359 assert (le_swizzles[i] != SWIZZLE_NONE) == (be_swizzles[i] != SWIZZLE_NONE)
360
361 format = Format(name, layout, block_width, block_height, le_channels, le_swizzles, be_channels, be_swizzles, colorspace)
362 formats.append(format)
363 return formats
364