Small refactor. Add glXFunctionIterator, which derrives from
[mesa.git] / src / mesa / glapi / glX_proto_size.py
1 #!/usr/bin/env python
2
3 # (C) Copyright IBM Corporation 2004, 2005
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 gl_XML
33 import glX_XML
34 import license
35 import sys, getopt, copy
36
37
38 class SizeStubFunctionIterator(glX_XML.glXFunctionIterator):
39 """Iterate over functions that need "size" information.
40
41 Iterate over the functions that have variable sized data. First the
42 "set"-type functions are iterated followed by the "get"-type
43 functions.
44 """
45
46 def __init__(self, context):
47 self.data = []
48 self.index = 0
49
50 set_functions = []
51 get_functions = []
52 extra_data = []
53
54 for f in gl_XML.glFunctionIterator(context):
55 if context.glx_enum_functions.has_key(f.name):
56 ef = context.glx_enum_functions[f.name]
57 if ef.is_set():
58 set_functions.append(f)
59 else:
60 get_functions.append(f)
61
62
63 if (context.which_functions & PrintGlxSizeStubs_c.do_set) != 0:
64 self.data += set_functions
65 elif context.get_alias_set:
66 extra_data = set_functions
67
68 if (context.which_functions & PrintGlxSizeStubs_c.do_get) != 0:
69 self.data += get_functions
70
71
72 for f in extra_data + self.data:
73 sig = context.glx_enum_functions[f.name].signature()
74
75 if not context.glx_enum_sigs.has_key(sig):
76 context.glx_enum_sigs[sig] = f.name;
77
78 return
79
80
81 def next(self):
82 if self.index == len(self.data):
83 raise StopIteration
84
85 f = self.data[ self.index ]
86 self.index += 1
87
88 return f
89
90
91 class glXServerEnumFunction(glX_XML.glXEnumFunction):
92 def signature( self ):
93 if self.sig == None:
94 sig = glX_XML.glXEnumFunction.signature(self)
95
96 f = self.context.find_function( self.name )
97 p = f.variable_length_parameter()
98
99 try:
100 sig += "%u" % (p.p_type.size)
101 except Exception,e:
102 print '%s' % (self.name)
103 raise e
104
105 self.sig = sig
106
107 return self.sig;
108
109
110 def Print(self, name):
111 f = self.context.find_function( self.name )
112 self.context.common_func_print_just_header( f )
113
114 fixup = []
115 o = 0
116 for p in f.parameterIterator(1, 1):
117 if f.count_parameter_list.count(p.name) or p.name == f.counter:
118 self.context.common_emit_one_arg(p, o, "pc", " ", 0)
119 fixup.append(p.name)
120
121 o += p.size()
122
123 print ' GLsizei compsize;'
124 print ''
125
126 self.context.common_emit_fixups(fixup)
127
128 print ''
129 print ' compsize = %s;' % (context.size_call(context, f))
130 p = f.variable_length_parameter()
131 print ' return __GLX_PAD(%s);' % (p.size_string())
132
133 print '}'
134 print ''
135
136
137 class PrintGlxSizeStubs_common(glX_XML.GlxProto):
138 do_get = (1 << 0)
139 do_set = (1 << 1)
140 do_get_alias_set = (1 << 2)
141
142 def __init__(self, which_functions):
143 glX_XML.GlxProto.__init__(self)
144 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
145 self.aliases = []
146 self.glx_enum_sigs = {}
147 self.name = "glX_proto_size.py (from Mesa)"
148 self.which_functions = which_functions
149
150 if (((which_functions & PrintGlxSizeStubs_common.do_set) != 0) and ((which_functions & PrintGlxSizeStubs_common.do_get) != 0)) or ((which_functions & PrintGlxSizeStubs_common.do_get_alias_set) != 0):
151 self.get_alias_set = 1
152 else:
153 self.get_alias_set = 0
154
155
156 def functionIterator(self):
157 return SizeStubFunctionIterator(self)
158
159
160 class PrintGlxSizeStubs_c(PrintGlxSizeStubs_common):
161 def printRealHeader(self):
162 print ''
163 print '#include <GL/gl.h>'
164 print '#include "indirect_size.h"'
165
166 print ''
167 self.printHaveAlias()
168 print ''
169 self.printPure()
170 print ''
171 self.printFastcall()
172 print ''
173 self.printVisibility( "INTERNAL", "internal" )
174 print ''
175 print ''
176 print '#ifdef HAVE_ALIAS'
177 print '# define ALIAS2(from,to) \\'
178 print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
179 print ' __attribute__ ((alias( # to )));'
180 print '# define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
181 print '#else'
182 print '# define ALIAS(from,to) \\'
183 print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
184 print ' { return __gl ## to ## _size( e ); }'
185 print '#endif'
186 print ''
187 print ''
188
189
190 def printRealFooter(self):
191 for a in self.aliases:
192 print a
193
194
195 def printFunction(self, f):
196 ef = self.glx_enum_functions[f.name]
197 n = self.glx_enum_sigs[ ef.signature() ];
198
199 if n != f.name:
200 a = 'ALIAS( %s, %s )' % (f.name, n)
201 self.aliases.append(a)
202 else:
203 ef.Print( f.name )
204
205
206
207 class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common):
208 def printRealHeader(self):
209 print """/**
210 * \\file
211 * Prototypes for functions used to determine the number of data elements in
212 * various GLX protocol messages.
213 *
214 * \\author Ian Romanick <idr@us.ibm.com>
215 */
216 """
217 self.printPure();
218 print ''
219 self.printFastcall();
220 print ''
221 self.printVisibility( "INTERNAL", "internal" );
222 print ''
223
224
225 def printFunction(self, f):
226 ef = self.glx_enum_functions[f.name]
227 print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (f.name)
228
229
230 class PrintGlxReqSize_h(glX_XML.GlxProto):
231 def __init__(self):
232 glX_XML.GlxProto.__init__(self)
233 self.name = "glX_proto_size.py (from Mesa)"
234 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
235 self.aliases = []
236 self.glx_enum_sigs = {}
237 self.header_tag = "_INDIRECT_REQSIZE_H_"
238
239
240 def printRealHeader(self):
241 self.printVisibility("HIDDEN", "hidden")
242 print ''
243 self.printPure()
244 print ''
245
246
247 def printFunction(self, f):
248 if f.glx_rop == 0: return
249
250 has_counter = 0
251 for p in f.parameterIterator(1,2):
252 if p.is_counter:
253 has_counter = 1
254 break
255
256 if self.glx_enum_functions.has_key(f.name) or f.image or has_counter:
257 print 'extern PURE HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap);' % (f.name)
258
259
260 class PrintGlxReqSize_c(glX_XML.GlxProto):
261 def __init__(self):
262 glX_XML.GlxProto.__init__(self)
263 self.name = "glX_proto_size.py (from Mesa)"
264 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
265 self.aliases = []
266 self.glx_enum_sigs = {}
267 self.counter_sigs = {}
268
269
270 def createEnumFunction(self, n):
271 return glXServerEnumFunction(n, self)
272
273
274 def printRealHeader(self):
275 print ''
276 print '#include <GL/gl.h>'
277 print '#include <byteswap.h>'
278 print '#include "glxserver.h"'
279 print '#include "indirect_size.h"'
280 print '#include "indirect_reqsize.h"'
281
282 print ''
283 print '#define __GLX_PAD(x) (((x) + 3) & ~3)'
284 print ''
285 self.printHaveAlias()
286 print ''
287 print '#ifdef HAVE_ALIAS'
288 print '# define ALIAS2(from,to) \\'
289 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
290 print ' __attribute__ ((alias( # to )));'
291 print '# define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize )'
292 print '#else'
293 print '# define ALIAS(from,to) \\'
294 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
295 print ' { return __glX ## to ## ReqSize( pc, swap ); }'
296 print '#endif'
297 print ''
298 print ''
299
300
301 def printRealFooter(self):
302 for a in self.aliases:
303 print a
304
305
306 def printFunction(self, f):
307 if f.glx_rop == 0 or f.server_handcode: return
308
309 if self.glx_enum_functions.has_key(f.name):
310 ef = self.glx_enum_functions[f.name]
311
312 sig = ef.signature();
313 if self.glx_enum_sigs.has_key(sig):
314 n = self.glx_enum_sigs[sig];
315 a = 'ALIAS( %s, %s )' % (f.name, n)
316 self.aliases.append(a)
317 else:
318 ef.Print( f.name )
319 self.glx_enum_sigs[sig] = f.name;
320 elif f.image:
321 self.printPixelFunction(f)
322 else:
323 for p in f.parameterIterator(1,2):
324 if p.counter and not p.is_output:
325 self.printCountedFunction(f)
326 break
327
328
329 def common_emit_fixups(self, fixup):
330 """Utility function to emit conditional byte-swaps."""
331
332 if fixup:
333 print ' if (swap) {'
334 for name in fixup:
335 print ' %-14s = bswap_32( %s );' % (name, name)
336 print ' }'
337
338 return
339
340
341 def common_emit_one_arg(self, p, offset, pc, indent, adjust):
342 dst = '%s %s' % (p.p_type_string, p.name)
343 src = '(%s *)' % (p.p_type_string)
344 print '%s%-18s = *%11s(%s + %u);' % (indent, dst, src, pc, offset + adjust);
345 return
346
347
348 def common_func_print_just_header(self, f):
349 print 'int'
350 print '__glX%sReqSize( const GLbyte * pc, Bool swap )' % (f.name)
351 print '{'
352
353
354 def printPixelFunction(self, f):
355 self.common_func_print_just_header(f)
356
357 [dim, w, h, d, junk] = f.dimensions()
358
359 offset = f.offset_of_first_parameter()
360
361 print ' GLint row_length = * (GLint *)(pc + 4);'
362
363 if dim < 3:
364 fixup = ['row_length', 'skip_rows', 'alignment']
365 print ' GLint image_height = 0;'
366 print ' GLint skip_images = 0;'
367 print ' GLint skip_rows = * (GLint *)(pc + 8);'
368 print ' GLint alignment = * (GLint *)(pc + 16);'
369 else:
370 fixup = ['row_length', 'image_height', 'skip_rows', 'skip_images', 'alignment']
371 print ' GLint image_height = * (GLint *)(pc + 8);'
372 print ' GLint skip_rows = * (GLint *)(pc + 16);'
373 print ' GLint skip_images = * (GLint *)(pc + 20);'
374 print ' GLint alignment = * (GLint *)(pc + 32);'
375
376 for p in f.parameterIterator(1, 2):
377 if p.name in [w, h, d, f.image.img_format, f.image.img_type, f.image.img_target]:
378 self.common_emit_one_arg(p, offset, "pc", " ", 0 )
379 fixup.append( p.name )
380
381 offset += p.size()
382
383 print ''
384
385 self.common_emit_fixups(fixup)
386
387 print ''
388 print ' return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (f.image.img_format, f.image.img_type, f.image.img_target, w, h, d )
389 print ' image_height, row_length, skip_images,'
390 print ' skip_rows, alignment);'
391 print '}'
392 print ''
393 return
394
395
396 def printCountedFunction(self, f):
397
398 sig = ""
399 offset = 0
400 fixup = []
401 params = []
402 plus = ''
403 size = ''
404 param_offsets = {}
405
406 # Calculate the offset of each counter parameter and the
407 # size string for the variable length parameter(s). While
408 # that is being done, calculate a unique signature for this
409 # function.
410
411 for p in f.parameterIterator(1,2):
412 if p.is_counter:
413 param_offsets[ p.name ] = offset
414 fixup.append( p.name )
415 params.append( [p, offset] )
416 elif p.counter:
417 s = p.p_type.size
418 if s == 0: s = 1
419
420 sig += "(%u,%u)" % (param_offsets[p.counter], s)
421 size += '%s%s' % (plus, p.size_string())
422 plus = ' + '
423
424
425 offset += p.size()
426
427
428 # If the calculate signature matches a function that has
429 # already be emitted, don't emit this function. Instead, add
430 # it to the list of function aliases.
431
432 if self.counter_sigs.has_key(sig):
433 n = self.counter_sigs[sig];
434 a = 'ALIAS( %s, %s )' % (f.name, n)
435 self.aliases.append(a)
436 else:
437 self.counter_sigs[sig] = f.name
438
439 self.common_func_print_just_header(f)
440
441 for [p, offset] in params:
442 self.common_emit_one_arg(p, offset, "pc", " ", 0 )
443
444
445 print ''
446 self.common_emit_fixups(fixup)
447 print ''
448
449 print ' return __GLX_PAD(%s);' % (size)
450 print '}'
451 print ''
452
453 return
454
455
456 def show_usage():
457 print "Usage: %s [-f input_file_name] -m output_mode [--only-get | --only-set] [--get-alias-set]" % sys.argv[0]
458 print " -m output_mode Output mode can be one of 'size_c' or 'size_h'."
459 print " --only-get Only emit 'get'-type functions."
460 print " --only-set Only emit 'set'-type functions."
461 print " --get-alias-set When only 'get'-type functions are emitted, allow them"
462 print " to be aliases to 'set'-type funcitons."
463 print ""
464 print "By default, both 'get' and 'set'-type functions are emitted."
465 sys.exit(1)
466
467
468 if __name__ == '__main__':
469 file_name = "gl_API.xml"
470
471 try:
472 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:h:", ["only-get", "only-set", "get-alias-set", "header-tag"])
473 except Exception,e:
474 show_usage()
475
476 mode = None
477 header_tag = None
478 which_functions = PrintGlxSizeStubs_common.do_get | PrintGlxSizeStubs_common.do_set
479
480 for (arg,val) in args:
481 if arg == "-f":
482 file_name = val
483 elif arg == "-m":
484 mode = val
485 elif arg == "--only-get":
486 which_functions = PrintGlxSizeStubs_common.do_get
487 elif arg == "--only-set":
488 which_functions = PrintGlxSizeStubs_common.do_set
489 elif arg == "--get-alias-set":
490 which_functions |= PrintGlxSizeStubs_common.do_get_alias_set
491 elif (arg == '-h') or (arg == "--header-tag"):
492 header_tag = val
493
494 if mode == "size_c":
495 dh = PrintGlxSizeStubs_c( which_functions )
496 elif mode == "size_h":
497 dh = PrintGlxSizeStubs_h( which_functions )
498 if header_tag:
499 dh.header_tag = header_tag
500 elif mode == "reqsize_c":
501 dh = PrintGlxReqSize_c()
502 elif mode == "reqsize_h":
503 dh = PrintGlxReqSize_h()
504 else:
505 show_usage()
506
507 parser = make_parser()
508 parser.setFeature(feature_namespaces, 0)
509 parser.setContentHandler(dh)
510
511 f = open(file_name)
512
513 dh.printHeader()
514 parser.parse(f)
515 dh.printFooter()