add debugging for compresssed textures
[mesa.git] / src / mesa / glapi / gl_XML.py
1 #!/usr/bin/python2
2
3 # (C) Copyright IBM Corporation 2004
4 # All Rights Reserved.
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a
7 # copy of this software and associated documentation files (the "Software"),
8 # to deal in the Software without restriction, including without limitation
9 # on the rights to use, copy, modify, merge, publish, distribute, sub
10 # license, and/or sell copies of the Software, and to permit persons to whom
11 # the Software is furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice (including the next
14 # paragraph) shall be included in all copies or substantial portions of the
15 # Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 # IN THE SOFTWARE.
24 #
25 # Authors:
26 # Ian Romanick <idr@us.ibm.com>
27
28 from xml.sax import saxutils
29 from xml.sax import make_parser
30 from xml.sax.handler import feature_namespaces
31
32 import sys, re
33
34 class glItem:
35 """Generic class on which all other API entity types are based."""
36
37 def __init__(self, tag_name, name, context):
38 self.name = name
39 self.category = context.get_category_define()
40 self.context = context
41 self.tag_name = tag_name
42
43 context.append(tag_name, self)
44 return
45
46 def startElement(self, name, attrs):
47 """Generic startElement handler.
48
49 The startElement handler is called for all elements except
50 the one that starts the object. For a foo element, the
51 XML "<foo><bar/></foo>" would cause the startElement handler
52 to be called once, but the endElement handler would be called
53 twice."""
54 return
55
56 def endElement(self, name):
57 """Generic endElement handler.
58
59 Generic endElement handler. Returns 1 if the tag containing
60 the object is complete. Otherwise 0 is returned. All
61 derived class endElement handlers should call this method. If
62 the name of the ending tag is the same as the tag that
63 started this object, the object is assumed to be complete.
64
65 This fails if a tag can contain another tag with the same
66 name. The XML "<foo><foo/><bar/></foo>" would fail. The
67 object would end before the bar tag was processed.
68
69 The endElement handler is called for every end element
70 associated with an object, even the element that started the
71 object. See the description of startElement an example."""
72
73 if name == self.tag_name:
74 return 1
75 else:
76 return 0
77 return
78
79 def get_category_define(self):
80 return self.category
81
82
83 class glEnum( glItem ):
84 """Subclass of glItem for representing GL enumerants.
85
86 This class is not complete, and is not really used yet."""
87
88 def __init__(self, context, name, attrs):
89 self.value = int(attrs.get('value', "0x0000"), 0)
90 self.functions = {}
91
92 enum_name = "GL_" + attrs.get('name', None)
93 glItem.__init__(self, name, enum_name, context)
94
95 def startElement(self, name, attrs):
96 if name == "size":
97 name = attrs.get('name', None)
98 count = int(attrs.get('count', "0"), 0)
99 self.functions[name] = count
100
101 return
102
103
104 class glType( glItem ):
105 """Subclass of glItem for representing GL types."""
106
107 def __init__(self, context, name, attrs):
108 self.size = int(attrs.get('size', "0"))
109
110 type_name = "GL" + attrs.get('name', None)
111 glItem.__init__(self, name, type_name, context)
112
113
114 class glParameter( glItem ):
115 """Parameter of a glFunction."""
116 p_type = None
117 p_type_string = ""
118 p_count = 0
119 p_count_parameters = None
120 counter = None
121 is_output = 0
122 is_counter = 0
123 is_pointer = 0
124
125 def __init__(self, context, name, attrs):
126 p_name = attrs.get('name', None)
127 self.p_type_string = attrs.get('type', None)
128 self.p_count_parameters = attrs.get('variable_param', None)
129
130 self.p_type = context.context.find_type(self.p_type_string)
131 if self.p_type == None:
132 raise RuntimeError("Unknown type '%s' in function '%s'." % (self.p_type_string, context.name))
133
134
135 # The count tag can be either a numeric string or the name of
136 # a variable. If it is the name of a variable, the int(c)
137 # statement will throw an exception, and the except block will
138 # take over.
139
140 c = attrs.get('count', "0")
141 try:
142 self.p_count = int(c)
143 self.counter = None
144 except Exception,e:
145 self.p_count = 0
146 self.counter = c
147
148 if attrs.get('counter', "false") == "true":
149 self.is_counter = 1
150 else:
151 self.is_counter = 0
152
153 if attrs.get('output', "false") == "true":
154 self.is_output = 1
155 else:
156 self.is_output = 0
157
158 if self.p_count > 0 or self.counter != None or self.p_count_parameters != None :
159 has_count = 1
160 else:
161 has_count = 0
162
163
164 # If there is a * anywhere in the parameter's type, then it
165 # is a pointer.
166
167 if re.compile("[*]").search(self.p_type_string):
168 # We could do some other validation here. For
169 # example, an output parameter should not be const,
170 # but every non-output parameter should.
171
172 self.is_pointer = 1;
173 else:
174 # If a parameter is not a pointer, then there cannot
175 # be an associated count (either fixed size or
176 # variable) and the parameter cannot be an output.
177
178 if has_count or self.is_output:
179 raise RuntimeError("Non-pointer type has count or is output.")
180 self.is_pointer = 0;
181
182 glItem.__init__(self, name, p_name, context)
183 return
184
185
186 def is_variable_length_array(self):
187 """Determine if a parameter is a variable length array.
188
189 A parameter is considered to be a variable length array if
190 its size depends on the value of another parameter that is
191 an enumerant. The params parameter to glTexEnviv is an
192 example of a variable length array parameter. Arrays whose
193 size depends on a count variable, such as the lists parameter
194 to glCallLists, are not variable length arrays in this
195 sense."""
196
197 return self.p_count_parameters != None
198
199
200 def is_array(self):
201 return self.is_pointer
202
203
204 def count_string(self):
205 """Return a string representing the number of items
206
207 Returns a string representing the number of items in a
208 parameter. For scalar types this will always be "1". For
209 vector types, it will depend on whether or not it is a
210 fixed length vector (like the parameter of glVertex3fv),
211 a counted length (like the vector parameter of
212 glDeleteTextures), or a general variable length vector."""
213
214 if self.is_array():
215 if self.is_variable_length_array():
216 return "compsize"
217 elif self.counter != None:
218 return self.counter
219 else:
220 return str(self.p_count)
221 else:
222 return "1"
223
224
225 def size(self):
226 if self.is_variable_length_array():
227 return 0
228 elif self.p_count == 0:
229 return self.p_type.size
230 else:
231 return self.p_type.size * self.p_count
232
233
234 class glParameterIterator:
235 """Class to iterate over a list of glParameters.
236
237 Objects of this class are returned by the __iter__ method of the
238 glFunction class. They are used to iterate over the list of
239 parameters to the function."""
240
241 def __init__(self, data):
242 self.data = data
243 self.index = 0
244
245 def next(self):
246 if self.index == len( self.data ):
247 raise StopIteration
248 i = self.index
249 self.index += 1
250 return self.data[i]
251
252
253 class glFunction( glItem ):
254 real_name = ""
255 fn_alias = None
256 fn_offset = -1
257 fn_return_type = "void"
258 fn_parameters = []
259
260 def __init__(self, context, name, attrs):
261 self.fn_alias = attrs.get('alias', None)
262 self.fn_parameters = []
263
264 temp = attrs.get('offset', None)
265 if temp == None or temp == "?":
266 self.fn_offset = -1
267 else:
268 self.fn_offset = int(temp)
269
270 fn_name = attrs.get('name', None)
271 if self.fn_alias != None:
272 self.real_name = self.fn_alias
273 else:
274 self.real_name = fn_name
275
276 glItem.__init__(self, name, fn_name, context)
277 return
278
279
280 def __iter__(self):
281 return glParameterIterator(self.fn_parameters)
282
283
284 def startElement(self, name, attrs):
285 if name == "param":
286 try:
287 glParameter(self, name, attrs)
288 except RuntimeError:
289 print "Error with parameter '%s' in function '%s'." \
290 % (attrs.get('name','(unknown)'), self.name)
291 raise
292 elif name == "return":
293 self.set_return_type(attrs.get('type', None))
294
295
296 def append(self, tag_name, p):
297 if tag_name != "param":
298 raise RuntimeError("Trying to append '%s' to parameter list of function '%s'." % (tag_name, self.name))
299
300 self.fn_parameters.append(p)
301
302
303 def set_return_type(self, t):
304 self.fn_return_type = t
305
306
307 def get_parameter_string(self):
308 arg_string = ""
309 comma = ""
310 for p in self:
311 arg_string = arg_string + comma + p.p_type_string + " " + p.name
312 comma = ", "
313
314 if arg_string == "":
315 arg_string = "void"
316
317 return arg_string
318
319
320 class glItemFactory:
321 """Factory to create objects derived from glItem."""
322
323 def create(self, context, name, attrs):
324 if name == "function":
325 return glFunction(context, name, attrs)
326 elif name == "type":
327 return glType(context, name, attrs)
328 elif name == "enum":
329 return glEnum(context, name, attrs)
330 else:
331 return None
332
333
334 class FilterGLAPISpecBase(saxutils.XMLFilterBase):
335 name = "a"
336 license = "The license for this file is unspecified."
337 functions = {}
338 next_alias = -2
339 types = {}
340 xref = {}
341 current_object = None
342 factory = None
343 current_category = ""
344
345 def __init__(self):
346 saxutils.XMLFilterBase.__init__(self)
347 self.functions = {}
348 self.types = {}
349 self.xref = {}
350 self.factory = glItemFactory()
351
352
353 def find_type(self,type_name):
354 for t in self.types:
355 if re.compile(t).search(type_name):
356 return self.types[t]
357 print "Unable to find base type matching \"%s\"." % (type_name)
358 return None
359
360
361 def find_function(self,function_name):
362 index = self.xref[function_name]
363 return self.functions[index]
364
365
366 def printFunctions(self):
367 keys = self.functions.keys()
368 keys.sort()
369 prevk = -1
370 for k in keys:
371 if k < 0: continue
372
373 if self.functions[k].fn_alias == None:
374 if k != prevk + 1:
375 #print 'Missing offset %d' % (prevk)
376 pass
377 prevk = int(k)
378 self.printFunction(self.functions[k])
379
380 keys.reverse()
381 for k in keys:
382 if self.functions[k].fn_alias != None:
383 self.printFunction(self.functions[k])
384
385 return
386
387
388 def printHeader(self):
389 """Print the header associated with all files and call the printRealHeader method."""
390
391 print '/* DO NOT EDIT - This file generated automatically by %s script */' \
392 % (self.name)
393 print ''
394 print '/*'
395 print ' * ' + self.license.replace('\n', '\n * ')
396 print ' */'
397 print ''
398 self.printRealHeader();
399 return
400
401
402 def printFooter(self):
403 """Print the header associated with all files and call the printRealFooter method."""
404
405 self.printFunctions()
406 self.printRealFooter()
407
408
409 def get_category_define(self):
410 """Convert the category name to the #define that would be found in glext.h"""
411
412 if re.compile("[1-9][0-9]*[.][0-9]+").match(self.current_category):
413 s = self.current_category
414 return "GL_VERSION_" + s.replace(".", "_")
415 else:
416 return self.current_category
417
418
419 def append(self, object_type, obj):
420 if object_type == "function":
421 # If the function is not an alias and has a negative
422 # offset, then we do not need to track it. These are
423 # functions that don't have an assigned offset
424
425 if obj.fn_offset >= 0 or obj.fn_alias != None:
426 if obj.fn_offset >= 0:
427 index = obj.fn_offset
428 else:
429 index = self.next_alias
430 self.next_alias -= 1
431
432 self.functions[index] = obj
433 self.xref[obj.name] = index
434 elif object_type == "type":
435 self.types[obj.name] = obj
436
437 return
438
439
440 def startElement(self, name, attrs):
441 """Start a new element in the XML stream.
442
443 Starts a new element. There are three types of elements that
444 are specially handled by this function. When a "category"
445 element is encountered, the name of the category is saved.
446 If an element is encountered and no API object is
447 in-progress, a new object is created using the API factory.
448 Any future elements, until that API object is closed, are
449 passed to the current objects startElement method.
450
451 This paradigm was chosen becuase it allows subclasses of the
452 basic API types (i.e., glFunction, glEnum, etc.) to handle
453 additional XML data, GLX protocol information, that the base
454 classes do not know about."""
455
456 if self.current_object != None:
457 self.current_object.startElement(name, attrs)
458 elif name == "category":
459 self.current_category = attrs.get('name', "")
460 else:
461 self.current_object = self.factory.create(self, name, attrs)
462 return
463
464
465 def endElement(self, name):
466 if self.current_object != None:
467 if self.current_object.endElement(name):
468 self.current_object = None
469 return
470
471
472 def printFunction(self,offset):
473 """Print a single function.
474
475 In the base class, this function is empty. All derived
476 classes should over-ride this function."""
477 return
478
479
480 def printRealHeader(self):
481 """Print the "real" header for the created file.
482
483 In the base class, this function is empty. All derived
484 classes should over-ride this function."""
485 return
486
487
488 def printRealFooter(self):
489 """Print the "real" footer for the created file.
490
491 In the base class, this function is empty. All derived
492 classes should over-ride this function."""
493 return