3 # (C) Copyright IBM Corporation 2004, 2005
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:
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
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
26 # Ian Romanick <idr@us.ibm.com>
28 import gl_XML
, glX_XML
30 import sys
, getopt
, copy
, string
33 class glx_enum_function
:
34 def __init__(self
, func_name
, enum_dict
):
39 # "enums" is a set of lists. The element in the set is the
40 # value of the enum. The list is the list of names for that
41 # value. For example, [0x8126] = {"POINT_SIZE_MIN",
42 # "POINT_SIZE_MIN_ARB", "POINT_SIZE_MIN_EXT",
43 # "POINT_SIZE_MIN_SGIS"}.
47 # "count" is indexed by count values. Each element of count
48 # is a list of index to "enums" that have that number of
49 # associated data elements. For example, [4] =
50 # {GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION,
51 # GL_AMBIENT_AND_DIFFUSE} (the enum names are used here,
52 # but the actual hexadecimal values would be in the array).
57 # Fill self.count and self.enums using the dictionary of enums
61 for enum_name
in enum_dict
:
62 e
= enum_dict
[ enum_name
]
64 if e
.functions
.has_key( func_name
):
65 [count
, mode
] = e
.functions
[ func_name
]
67 if mode_set
and mode
!= self
.mode
:
68 raise RuntimeError("Not all enums for %s have the same mode." % (func_name
))
72 if self
.enums
.has_key( e
.value
):
73 if e
.name
not in self
.enums
[ e
.value
]:
74 self
.enums
[ e
.value
].append( e
)
76 if not self
.count
.has_key( count
):
77 self
.count
[ count
] = []
79 self
.enums
[ e
.value
] = [ e
]
80 self
.count
[ count
].append( e
.value
)
86 def signature( self
):
91 raise RuntimeError("i is None. WTF?")
94 for e
in self
.count
[i
]:
95 self
.sig
+= "%04x,%u," % (e
, i
)
104 def PrintUsingTable(self
):
105 """Emit the body of the __gl*_size function using a pair
106 of look-up tables and a mask. The mask is calculated such
107 that (e & mask) is unique for all the valid values of e for
108 this function. The result of (e & mask) is used as an index
109 into the first look-up table. If it matches e, then the
110 same entry of the second table is returned. Otherwise zero
113 It seems like this should cause better code to be generated.
114 However, on x86 at least, the resulting .o file is about 20%
115 larger then the switch-statment version. I am leaving this
116 code in because the results may be different on other
117 platforms (e.g., PowerPC or x86-64)."""
124 if self
.count
.has_key(-1):
127 # Determine if there is some mask M, such that M = (2^N) - 1,
128 # that will generate unique values for all of the enums.
131 for i
in [1, 2, 3, 4, 5, 6, 7, 8]:
138 if (a
& mask
) == (b
& mask
):
146 if (mask
!= 0) and (mask
< (2 * count
)):
150 for i
in range(0, mask
+ 1):
151 masked_enums
[i
] = "0";
155 for e
in self
.count
[c
]:
157 enum_obj
= self
.enums
[e
][0]
158 masked_enums
[i
] = '0x%04x /* %s */' % (e
, enum_obj
.name
)
162 print ' static const GLushort a[%u] = {' % (mask
+ 1)
163 for e
in masked_enums
:
164 print ' %s, ' % (masked_enums
[e
])
167 print ' static const GLubyte b[%u] = {' % (mask
+ 1)
168 for c
in masked_count
:
169 print ' %u, ' % (masked_count
[c
])
172 print ' const unsigned idx = (e & 0x%02xU);' % (mask
)
174 print ' return (e == a[idx]) ? (GLint) b[idx] : 0;'
180 def PrintUsingSwitch(self
, name
):
181 """Emit the body of the __gl*_size function using a
184 print ' switch( e ) {'
187 for e
in self
.count
[c
]:
190 # There may be multiple enums with the same
191 # value. This happens has extensions are
192 # promoted from vendor-specific or EXT to
193 # ARB and to the core. Emit the first one as
194 # a case label, and emit the others as
195 # commented-out case labels.
198 for enum_obj
in self
.enums
[e
]:
199 list[ enum_obj
.priority() ] = enum_obj
.name
206 print ' case GL_%s:' % (j
)
209 print '/* case GL_%s:*/' % (j
)
212 print ' return __gl%s_variable_size( e );' % (name
)
214 print ' return %u;' % (c
)
216 print ' default: return 0;'
220 def Print(self
, name
):
221 print 'INTERNAL PURE FASTCALL GLint'
222 print '__gl%s_size( GLenum e )' % (name
)
225 if not self
.PrintUsingTable():
226 self
.PrintUsingSwitch(name
)
232 class glx_server_enum_function(glx_enum_function
):
233 def __init__(self
, func
, enum_dict
):
234 glx_enum_function
.__init
__(self
, func
.name
, enum_dict
)
240 def signature( self
):
242 sig
= glx_enum_function
.signature(self
)
244 p
= self
.function
.variable_length_parameter()
246 sig
+= "%u" % (p
.size())
253 def Print(self
, name
, printer
):
255 printer
.common_func_print_just_header( f
)
260 for param_name
in f
.count_parameter_list
:
261 o
= f
.offset_of( param_name
)
264 for param_name
in f
.counter_list
:
265 o
= f
.offset_of( param_name
)
271 p
= f
.parameters_by_name
[ foo
[o
] ]
273 printer
.common_emit_one_arg(p
, "pc", " ", 0)
274 fixup
.append( p
.name
)
277 print ' GLsizei compsize;'
280 printer
.common_emit_fixups(fixup
)
283 print ' compsize = __gl%s_size(%s);' % (f
.name
, string
.join(f
.count_parameter_list
, ","))
284 p
= f
.variable_length_parameter()
285 print ' return __GLX_PAD(%s);' % (p
.size_string())
291 class PrintGlxSizeStubs_common(gl_XML
.gl_print_base
):
295 def __init__(self
, which_functions
):
296 gl_XML
.gl_print_base
.__init
__(self
)
298 self
.name
= "glX_proto_size.py (from Mesa)"
299 self
.license
= license
.bsd_license_template
% ( "(C) Copyright IBM Corporation 2004", "IBM")
301 self
.emit_set
= ((which_functions
& PrintGlxSizeStubs_common
.do_set
) != 0)
302 self
.emit_get
= ((which_functions
& PrintGlxSizeStubs_common
.do_get
) != 0)
306 class PrintGlxSizeStubs_c(PrintGlxSizeStubs_common
):
307 def printRealHeader(self
):
309 print '#include <GL/gl.h>'
311 print '#include "indirect_size_get.h"'
313 print '#include "indirect_size.h"'
320 self
.printVisibility( "INTERNAL", "internal" )
323 print '#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__APPLE__)'
324 print '# undef HAVE_ALIAS'
326 print '#ifdef HAVE_ALIAS'
327 print '# define ALIAS2(from,to) \\'
328 print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
329 print ' __attribute__ ((alias( # to )));'
330 print '# define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
332 print '# define ALIAS(from,to) \\'
333 print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
334 print ' { return __gl ## to ## _size( e ); }'
340 def printBody(self
, api
):
344 for func
in api
.functionIterateGlx():
345 ef
= glx_enum_function( func
.name
, api
.enums_by_name
)
346 if len(ef
.enums
) == 0:
349 if (ef
.is_set() and self
.emit_set
) or (not ef
.is_set() and self
.emit_get
):
351 if enum_sigs
.has_key( sig
):
352 aliases
.append( [func
.name
, enum_sigs
[ sig
]] )
354 enum_sigs
[ sig
] = func
.name
355 ef
.Print( func
.name
)
358 for [alias_name
, real_name
] in aliases
:
359 print 'ALIAS( %s, %s )' % (alias_name
, real_name
)
363 class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common
):
364 def printRealHeader(self
):
367 * Prototypes for functions used to determine the number of data elements in
368 * various GLX protocol messages.
370 * \\author Ian Romanick <idr@us.ibm.com>
375 self
.printFastcall();
377 self
.printVisibility( "INTERNAL", "internal" );
381 def printBody(self
, api
):
382 for func
in api
.functionIterateGlx():
383 ef
= glx_enum_function( func
.name
, api
.enums_by_name
)
384 if len(ef
.enums
) == 0:
387 if (ef
.is_set() and self
.emit_set
) or (not ef
.is_set() and self
.emit_get
):
388 print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (func
.name
)
391 class PrintGlxReqSize_common(gl_XML
.gl_print_base
):
392 """Common base class for PrintGlxSizeReq_h and PrintGlxSizeReq_h.
394 The main purpose of this common base class is to provide the infrastructure
395 for the derrived classes to iterate over the same set of functions.
399 gl_XML
.gl_print_base
.__init
__(self
)
401 self
.name
= "glX_proto_size.py (from Mesa)"
402 self
.license
= license
.bsd_license_template
% ( "(C) Copyright IBM Corporation 2005", "IBM")
405 class PrintGlxReqSize_h(PrintGlxReqSize_common
):
407 PrintGlxReqSize_common
.__init
__(self
)
408 self
.header_tag
= "_INDIRECT_REQSIZE_H_"
411 def printRealHeader(self
):
412 self
.printVisibility("HIDDEN", "hidden")
418 def printBody(self
, api
):
419 for func
in api
.functionIterateGlx():
420 if not func
.ignore
and func
.has_variable_size_request():
421 print 'extern PURE HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap);' % (func
.name
)
424 class PrintGlxReqSize_c(PrintGlxReqSize_common
):
426 PrintGlxReqSize_common
.__init
__(self
)
427 self
.counter_sigs
= {}
430 def printRealHeader(self
):
432 print '#include <GL/gl.h>'
433 print '#include <byteswap.h>'
434 print '#include "glxserver.h"'
435 print '#include "indirect_size.h"'
436 print '#include "indirect_reqsize.h"'
439 print '#define __GLX_PAD(x) (((x) + 3) & ~3)'
441 print '#if defined(__CYGWIN__) || defined(__MINGW32__)'
442 print '# undef HAVE_ALIAS'
444 print '#ifdef HAVE_ALIAS'
445 print '# define ALIAS2(from,to) \\'
446 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
447 print ' __attribute__ ((alias( # to )));'
448 print '# define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize )'
450 print '# define ALIAS(from,to) \\'
451 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
452 print ' { return __glX ## to ## ReqSize( pc, swap ); }'
458 def printBody(self
, api
):
463 for func
in api
.functionIterateGlx():
464 if not func
.has_variable_size_request(): continue
466 ef
= glx_server_enum_function( func
, api
.enums_by_name
)
467 if len(ef
.enums
) == 0: continue
471 if not enum_functions
.has_key(func
.name
):
472 enum_functions
[ func
.name
] = sig
474 if not enum_sigs
.has_key( sig
):
475 enum_sigs
[ sig
] = ef
479 for func
in api
.functionIterateGlx():
480 # Even though server-handcode fuctions are on "the
481 # list", and prototypes are generated for them, there
482 # isn't enough information to generate a size
483 # function. If there was enough information, they
484 # probably wouldn't need to be handcoded in the first
487 if func
.server_handcode
: continue
488 if not func
.has_variable_size_request(): continue
490 if enum_functions
.has_key(func
.name
):
491 sig
= enum_functions
[func
.name
]
492 ef
= enum_sigs
[ sig
]
494 if ef
.name
!= func
.name
:
495 aliases
.append( [func
.name
, ef
.name
] )
497 ef
.Print( func
.name
, self
)
500 self
.printPixelFunction(func
)
501 elif func
.has_variable_size_request():
502 a
= self
.printCountedFunction(func
)
503 if a
: aliases
.append(a
)
506 for [alias_name
, real_name
] in aliases
:
507 print 'ALIAS( %s, %s )' % (alias_name
, real_name
)
512 def common_emit_fixups(self
, fixup
):
513 """Utility function to emit conditional byte-swaps."""
518 print ' %-14s = bswap_32( %s );' % (name
, name
)
524 def common_emit_one_arg(self
, p
, pc
, indent
, adjust
):
527 src
= '(%s *)' % (p
.type_string())
528 print '%s%-18s = *%11s(%s + %u);' % (indent
, dst
, src
, pc
, offset
+ adjust
);
532 def common_func_print_just_header(self
, f
):
534 print '__glX%sReqSize( const GLbyte * pc, Bool swap )' % (f
.name
)
538 def printPixelFunction(self
, f
):
539 self
.common_func_print_just_header(f
)
541 f
.offset_of( f
.parameters
[0].name
)
542 [dim
, w
, h
, d
, junk
] = f
.dimensions()
544 print ' GLint row_length = * (GLint *)(pc + 4);'
547 fixup
= ['row_length', 'skip_rows', 'alignment']
548 print ' GLint image_height = 0;'
549 print ' GLint skip_images = 0;'
550 print ' GLint skip_rows = * (GLint *)(pc + 8);'
551 print ' GLint alignment = * (GLint *)(pc + 16);'
553 fixup
= ['row_length', 'image_height', 'skip_rows', 'skip_images', 'alignment']
554 print ' GLint image_height = * (GLint *)(pc + 8);'
555 print ' GLint skip_rows = * (GLint *)(pc + 16);'
556 print ' GLint skip_images = * (GLint *)(pc + 20);'
557 print ' GLint alignment = * (GLint *)(pc + 32);'
560 for p
in f
.parameterIterateGlxSend():
561 if p
.name
in [w
, h
, d
, img
.img_format
, img
.img_type
, img
.img_target
]:
562 self
.common_emit_one_arg( p
, "pc", " ", 0 )
563 fixup
.append( p
.name
)
567 self
.common_emit_fixups(fixup
)
570 print ' return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (img
.img_format
, img
.img_type
, img
.img_target
, w
, h
, d
)
571 print ' image_height, row_length, skip_images,'
572 print ' skip_rows, alignment);'
578 def printCountedFunction(self
, f
):
588 # Calculate the offset of each counter parameter and the
589 # size string for the variable length parameter(s). While
590 # that is being done, calculate a unique signature for this
593 for p
in f
.parameterIterateGlxSend():
595 fixup
.append( p
.name
)
601 sig
+= "(%u,%u)" % (f
.offset_of(p
.counter
), s
)
602 size
+= '%s%s' % (plus
, p
.size_string())
606 # If the calculated signature matches a function that has
607 # already be emitted, don't emit this function. Instead, add
608 # it to the list of function aliases.
610 if self
.counter_sigs
.has_key(sig
):
611 n
= self
.counter_sigs
[sig
];
615 self
.counter_sigs
[sig
] = f
.name
617 self
.common_func_print_just_header(f
)
620 self
.common_emit_one_arg(p
, "pc", " ", 0 )
624 self
.common_emit_fixups(fixup
)
627 print ' return __GLX_PAD(%s);' % (size
)
635 print "Usage: %s [-f input_file_name] -m output_mode [--only-get | --only-set] [--get-alias-set]" % sys
.argv
[0]
636 print " -m output_mode Output mode can be one of 'size_c' or 'size_h'."
637 print " --only-get Only emit 'get'-type functions."
638 print " --only-set Only emit 'set'-type functions."
639 print " --get-alias-set When only 'get'-type functions are emitted, allow them"
640 print " to be aliases to 'set'-type funcitons."
642 print "By default, both 'get' and 'set'-type functions are emitted."
646 if __name__
== '__main__':
647 file_name
= "gl_API.xml"
650 (args
, trail
) = getopt
.getopt(sys
.argv
[1:], "f:m:h:", ["only-get", "only-set", "header-tag"])
656 which_functions
= PrintGlxSizeStubs_common
.do_get | PrintGlxSizeStubs_common
.do_set
658 for (arg
,val
) in args
:
663 elif arg
== "--only-get":
664 which_functions
= PrintGlxSizeStubs_common
.do_get
665 elif arg
== "--only-set":
666 which_functions
= PrintGlxSizeStubs_common
.do_set
667 elif (arg
== '-h') or (arg
== "--header-tag"):
671 printer
= PrintGlxSizeStubs_c( which_functions
)
672 elif mode
== "size_h":
673 printer
= PrintGlxSizeStubs_h( which_functions
)
675 printer
.header_tag
= header_tag
676 elif mode
== "reqsize_c":
677 printer
= PrintGlxReqSize_c()
678 elif mode
== "reqsize_h":
679 printer
= PrintGlxReqSize_h()
683 api
= gl_XML
.parse_GL_API( file_name
, glX_XML
.glx_item_factory() )