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 '#ifdef HAVE_ALIAS'
324 print '# define ALIAS2(from,to) \\'
325 print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
326 print ' __attribute__ ((alias( # to )));'
327 print '# define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
329 print '# define ALIAS(from,to) \\'
330 print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
331 print ' { return __gl ## to ## _size( e ); }'
337 def printBody(self
, api
):
341 for func
in api
.functionIterateGlx():
342 ef
= glx_enum_function( func
.name
, api
.enums_by_name
)
343 if len(ef
.enums
) == 0:
346 if (ef
.is_set() and self
.emit_set
) or (not ef
.is_set() and self
.emit_get
):
348 if enum_sigs
.has_key( sig
):
349 aliases
.append( [func
.name
, enum_sigs
[ sig
]] )
351 enum_sigs
[ sig
] = func
.name
352 ef
.Print( func
.name
)
355 for [alias_name
, real_name
] in aliases
:
356 print 'ALIAS( %s, %s )' % (alias_name
, real_name
)
360 class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common
):
361 def printRealHeader(self
):
364 * Prototypes for functions used to determine the number of data elements in
365 * various GLX protocol messages.
367 * \\author Ian Romanick <idr@us.ibm.com>
372 self
.printFastcall();
374 self
.printVisibility( "INTERNAL", "internal" );
378 def printBody(self
, api
):
379 for func
in api
.functionIterateGlx():
380 ef
= glx_enum_function( func
.name
, api
.enums_by_name
)
381 if len(ef
.enums
) == 0:
384 if (ef
.is_set() and self
.emit_set
) or (not ef
.is_set() and self
.emit_get
):
385 print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (func
.name
)
388 class PrintGlxReqSize_common(gl_XML
.gl_print_base
):
389 """Common base class for PrintGlxSizeReq_h and PrintGlxSizeReq_h.
391 The main purpose of this common base class is to provide the infrastructure
392 for the derrived classes to iterate over the same set of functions.
396 gl_XML
.gl_print_base
.__init
__(self
)
398 self
.name
= "glX_proto_size.py (from Mesa)"
399 self
.license
= license
.bsd_license_template
% ( "(C) Copyright IBM Corporation 2005", "IBM")
402 class PrintGlxReqSize_h(PrintGlxReqSize_common
):
404 PrintGlxReqSize_common
.__init
__(self
)
405 self
.header_tag
= "_INDIRECT_REQSIZE_H_"
408 def printRealHeader(self
):
409 self
.printVisibility("HIDDEN", "hidden")
415 def printBody(self
, api
):
416 for func
in api
.functionIterateGlx():
417 if not func
.ignore
and func
.has_variable_size_request():
418 print 'extern PURE HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap);' % (func
.name
)
421 class PrintGlxReqSize_c(PrintGlxReqSize_common
):
423 PrintGlxReqSize_common
.__init
__(self
)
424 self
.counter_sigs
= {}
427 def printRealHeader(self
):
429 print '#include <GL/gl.h>'
430 print '#include <byteswap.h>'
431 print '#include "glxserver.h"'
432 print '#include "indirect_size.h"'
433 print '#include "indirect_reqsize.h"'
436 print '#define __GLX_PAD(x) (((x) + 3) & ~3)'
438 print '#ifdef HAVE_ALIAS'
439 print '# define ALIAS2(from,to) \\'
440 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
441 print ' __attribute__ ((alias( # to )));'
442 print '# define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize )'
444 print '# define ALIAS(from,to) \\'
445 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
446 print ' { return __glX ## to ## ReqSize( pc, swap ); }'
452 def printBody(self
, api
):
457 for func
in api
.functionIterateGlx():
458 if not func
.has_variable_size_request(): continue
460 ef
= glx_server_enum_function( func
, api
.enums_by_name
)
461 if len(ef
.enums
) == 0: continue
465 if not enum_functions
.has_key(func
.name
):
466 enum_functions
[ func
.name
] = sig
468 if not enum_sigs
.has_key( sig
):
469 enum_sigs
[ sig
] = ef
473 for func
in api
.functionIterateGlx():
474 # Even though server-handcode fuctions are on "the
475 # list", and prototypes are generated for them, there
476 # isn't enough information to generate a size
477 # function. If there was enough information, they
478 # probably wouldn't need to be handcoded in the first
481 if func
.server_handcode
: continue
482 if not func
.has_variable_size_request(): continue
484 if enum_functions
.has_key(func
.name
):
485 sig
= enum_functions
[func
.name
]
486 ef
= enum_sigs
[ sig
]
488 if ef
.name
!= func
.name
:
489 aliases
.append( [func
.name
, ef
.name
] )
491 ef
.Print( func
.name
, self
)
494 self
.printPixelFunction(func
)
495 elif func
.has_variable_size_request():
496 a
= self
.printCountedFunction(func
)
497 if a
: aliases
.append(a
)
500 for [alias_name
, real_name
] in aliases
:
501 print 'ALIAS( %s, %s )' % (alias_name
, real_name
)
506 def common_emit_fixups(self
, fixup
):
507 """Utility function to emit conditional byte-swaps."""
512 print ' %-14s = bswap_32( %s );' % (name
, name
)
518 def common_emit_one_arg(self
, p
, pc
, indent
, adjust
):
521 src
= '(%s *)' % (p
.type_string())
522 print '%s%-18s = *%11s(%s + %u);' % (indent
, dst
, src
, pc
, offset
+ adjust
);
526 def common_func_print_just_header(self
, f
):
528 print '__glX%sReqSize( const GLbyte * pc, Bool swap )' % (f
.name
)
532 def printPixelFunction(self
, f
):
533 self
.common_func_print_just_header(f
)
535 f
.offset_of( f
.parameters
[0].name
)
536 [dim
, w
, h
, d
, junk
] = f
.dimensions()
538 print ' GLint row_length = * (GLint *)(pc + 4);'
541 fixup
= ['row_length', 'skip_rows', 'alignment']
542 print ' GLint image_height = 0;'
543 print ' GLint skip_images = 0;'
544 print ' GLint skip_rows = * (GLint *)(pc + 8);'
545 print ' GLint alignment = * (GLint *)(pc + 16);'
547 fixup
= ['row_length', 'image_height', 'skip_rows', 'skip_images', 'alignment']
548 print ' GLint image_height = * (GLint *)(pc + 8);'
549 print ' GLint skip_rows = * (GLint *)(pc + 16);'
550 print ' GLint skip_images = * (GLint *)(pc + 20);'
551 print ' GLint alignment = * (GLint *)(pc + 32);'
554 for p
in f
.parameterIterateGlxSend():
555 if p
.name
in [w
, h
, d
, img
.img_format
, img
.img_type
, img
.img_target
]:
556 self
.common_emit_one_arg( p
, "pc", " ", 0 )
557 fixup
.append( p
.name
)
561 self
.common_emit_fixups(fixup
)
564 print ' return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (img
.img_format
, img
.img_type
, img
.img_target
, w
, h
, d
)
565 print ' image_height, row_length, skip_images,'
566 print ' skip_rows, alignment);'
572 def printCountedFunction(self
, f
):
582 # Calculate the offset of each counter parameter and the
583 # size string for the variable length parameter(s). While
584 # that is being done, calculate a unique signature for this
587 for p
in f
.parameterIterateGlxSend():
589 fixup
.append( p
.name
)
595 sig
+= "(%u,%u)" % (f
.offset_of(p
.counter
), s
)
596 size
+= '%s%s' % (plus
, p
.size_string())
600 # If the calculated signature matches a function that has
601 # already be emitted, don't emit this function. Instead, add
602 # it to the list of function aliases.
604 if self
.counter_sigs
.has_key(sig
):
605 n
= self
.counter_sigs
[sig
];
609 self
.counter_sigs
[sig
] = f
.name
611 self
.common_func_print_just_header(f
)
614 self
.common_emit_one_arg(p
, "pc", " ", 0 )
618 self
.common_emit_fixups(fixup
)
621 print ' return __GLX_PAD(%s);' % (size
)
629 print "Usage: %s [-f input_file_name] -m output_mode [--only-get | --only-set] [--get-alias-set]" % sys
.argv
[0]
630 print " -m output_mode Output mode can be one of 'size_c' or 'size_h'."
631 print " --only-get Only emit 'get'-type functions."
632 print " --only-set Only emit 'set'-type functions."
633 print " --get-alias-set When only 'get'-type functions are emitted, allow them"
634 print " to be aliases to 'set'-type funcitons."
636 print "By default, both 'get' and 'set'-type functions are emitted."
640 if __name__
== '__main__':
641 file_name
= "gl_API.xml"
644 (args
, trail
) = getopt
.getopt(sys
.argv
[1:], "f:m:h:", ["only-get", "only-set", "header-tag"])
650 which_functions
= PrintGlxSizeStubs_common
.do_get | PrintGlxSizeStubs_common
.do_set
652 for (arg
,val
) in args
:
657 elif arg
== "--only-get":
658 which_functions
= PrintGlxSizeStubs_common
.do_get
659 elif arg
== "--only-set":
660 which_functions
= PrintGlxSizeStubs_common
.do_set
661 elif (arg
== '-h') or (arg
== "--header-tag"):
665 printer
= PrintGlxSizeStubs_c( which_functions
)
666 elif mode
== "size_h":
667 printer
= PrintGlxSizeStubs_h( which_functions
)
669 printer
.header_tag
= header_tag
670 elif mode
== "reqsize_c":
671 printer
= PrintGlxReqSize_c()
672 elif mode
== "reqsize_h":
673 printer
= PrintGlxReqSize_h()
677 api
= gl_XML
.parse_GL_API( file_name
, glX_XML
.glx_item_factory() )