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
58 # that was passed in. The generic Get functions (e.g.,
59 # GetBooleanv and friends) are handled specially here. In
60 # the data the generic Get functions are refered to as "Get".
62 if func_name
in ["GetIntegerv", "GetBooleanv", "GetFloatv", "GetDoublev"]:
65 match_name
= func_name
68 for enum_name
in enum_dict
:
69 e
= enum_dict
[ enum_name
]
71 if e
.functions
.has_key( match_name
):
72 [count
, mode
] = e
.functions
[ match_name
]
74 if mode_set
and mode
!= self
.mode
:
75 raise RuntimeError("Not all enums for %s have the same mode." % (func_name
))
79 if self
.enums
.has_key( e
.value
):
80 if e
.name
not in self
.enums
[ e
.value
]:
81 self
.enums
[ e
.value
].append( e
)
83 if not self
.count
.has_key( count
):
84 self
.count
[ count
] = []
86 self
.enums
[ e
.value
] = [ e
]
87 self
.count
[ count
].append( e
.value
)
93 def signature( self
):
98 raise RuntimeError("i is None. WTF?")
101 for e
in self
.count
[i
]:
102 self
.sig
+= "%04x,%d," % (e
, i
)
111 def PrintUsingTable(self
):
112 """Emit the body of the __gl*_size function using a pair
113 of look-up tables and a mask. The mask is calculated such
114 that (e & mask) is unique for all the valid values of e for
115 this function. The result of (e & mask) is used as an index
116 into the first look-up table. If it matches e, then the
117 same entry of the second table is returned. Otherwise zero
120 It seems like this should cause better code to be generated.
121 However, on x86 at least, the resulting .o file is about 20%
122 larger then the switch-statment version. I am leaving this
123 code in because the results may be different on other
124 platforms (e.g., PowerPC or x86-64)."""
131 if self
.count
.has_key(-1):
134 # Determine if there is some mask M, such that M = (2^N) - 1,
135 # that will generate unique values for all of the enums.
138 for i
in [1, 2, 3, 4, 5, 6, 7, 8]:
145 if (a
& mask
) == (b
& mask
):
153 if (mask
!= 0) and (mask
< (2 * count
)):
157 for i
in range(0, mask
+ 1):
158 masked_enums
[i
] = "0";
162 for e
in self
.count
[c
]:
164 enum_obj
= self
.enums
[e
][0]
165 masked_enums
[i
] = '0x%04x /* %s */' % (e
, enum_obj
.name
)
169 print ' static const GLushort a[%u] = {' % (mask
+ 1)
170 for e
in masked_enums
:
171 print ' %s, ' % (masked_enums
[e
])
174 print ' static const GLubyte b[%u] = {' % (mask
+ 1)
175 for c
in masked_count
:
176 print ' %u, ' % (masked_count
[c
])
179 print ' const unsigned idx = (e & 0x%02xU);' % (mask
)
181 print ' return (e == a[idx]) ? (GLint) b[idx] : 0;'
187 def PrintUsingSwitch(self
, name
):
188 """Emit the body of the __gl*_size function using a
191 print ' switch( e ) {'
194 for e
in self
.count
[c
]:
197 # There may be multiple enums with the same
198 # value. This happens has extensions are
199 # promoted from vendor-specific or EXT to
200 # ARB and to the core. Emit the first one as
201 # a case label, and emit the others as
202 # commented-out case labels.
205 for enum_obj
in self
.enums
[e
]:
206 list[ enum_obj
.priority() ] = enum_obj
.name
213 print ' case GL_%s:' % (j
)
216 print '/* case GL_%s:*/' % (j
)
219 print ' return __gl%s_variable_size( e );' % (name
)
221 print ' return %u;' % (c
)
223 print ' default: return 0;'
227 def Print(self
, name
):
228 print '_X_INTERNAL PURE FASTCALL GLint'
229 print '__gl%s_size( GLenum e )' % (name
)
232 if not self
.PrintUsingTable():
233 self
.PrintUsingSwitch(name
)
239 class glx_server_enum_function(glx_enum_function
):
240 def __init__(self
, func
, enum_dict
):
241 glx_enum_function
.__init
__(self
, func
.name
, enum_dict
)
247 def signature( self
):
249 sig
= glx_enum_function
.signature(self
)
251 p
= self
.function
.variable_length_parameter()
253 sig
+= "%u" % (p
.size())
260 def Print(self
, name
, printer
):
262 printer
.common_func_print_just_header( f
)
267 for param_name
in f
.count_parameter_list
:
268 o
= f
.offset_of( param_name
)
271 for param_name
in f
.counter_list
:
272 o
= f
.offset_of( param_name
)
278 p
= f
.parameters_by_name
[ foo
[o
] ]
280 printer
.common_emit_one_arg(p
, "pc", 0)
281 fixup
.append( p
.name
)
284 print ' GLsizei compsize;'
287 printer
.common_emit_fixups(fixup
)
290 print ' compsize = __gl%s_size(%s);' % (f
.name
, string
.join(f
.count_parameter_list
, ","))
291 p
= f
.variable_length_parameter()
292 print ' return __GLX_PAD(%s);' % (p
.size_string())
298 class PrintGlxSizeStubs_common(gl_XML
.gl_print_base
):
302 def __init__(self
, which_functions
):
303 gl_XML
.gl_print_base
.__init
__(self
)
305 self
.name
= "glX_proto_size.py (from Mesa)"
306 self
.license
= license
.bsd_license_template
% ( "(C) Copyright IBM Corporation 2004", "IBM")
308 self
.emit_set
= ((which_functions
& PrintGlxSizeStubs_common
.do_set
) != 0)
309 self
.emit_get
= ((which_functions
& PrintGlxSizeStubs_common
.do_get
) != 0)
313 class PrintGlxSizeStubs_c(PrintGlxSizeStubs_common
):
314 def printRealHeader(self
):
316 print '#include <X11/Xfuncproto.h>'
317 print '#include <GL/gl.h>'
319 print '#include "indirect_size_get.h"'
320 print '#include "glxserver.h"'
321 print '#include "indirect_util.h"'
323 print '#include "indirect_size.h"'
331 print '#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(GLX_USE_APPLEGL)'
332 print '# undef HAVE_ALIAS'
334 print '#ifdef HAVE_ALIAS'
335 print '# define ALIAS2(from,to) \\'
336 print ' _X_INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
337 print ' __attribute__ ((alias( # to )));'
338 print '# define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
340 print '# define ALIAS(from,to) \\'
341 print ' _X_INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
342 print ' { return __gl ## to ## _size( e ); }'
348 def printBody(self
, api
):
352 for func
in api
.functionIterateGlx():
353 ef
= glx_enum_function( func
.name
, api
.enums_by_name
)
354 if len(ef
.enums
) == 0:
357 if (ef
.is_set() and self
.emit_set
) or (not ef
.is_set() and self
.emit_get
):
359 if enum_sigs
.has_key( sig
):
360 aliases
.append( [func
.name
, enum_sigs
[ sig
]] )
362 enum_sigs
[ sig
] = func
.name
363 ef
.Print( func
.name
)
366 for [alias_name
, real_name
] in aliases
:
367 print 'ALIAS( %s, %s )' % (alias_name
, real_name
)
371 class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common
):
372 def printRealHeader(self
):
375 * Prototypes for functions used to determine the number of data elements in
376 * various GLX protocol messages.
378 * \\author Ian Romanick <idr@us.ibm.com>
381 print '#include <X11/Xfuncproto.h>'
385 self
.printFastcall();
389 def printBody(self
, api
):
390 for func
in api
.functionIterateGlx():
391 ef
= glx_enum_function( func
.name
, api
.enums_by_name
)
392 if len(ef
.enums
) == 0:
395 if (ef
.is_set() and self
.emit_set
) or (not ef
.is_set() and self
.emit_get
):
396 print 'extern _X_INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (func
.name
)
399 class PrintGlxReqSize_common(gl_XML
.gl_print_base
):
400 """Common base class for PrintGlxSizeReq_h and PrintGlxSizeReq_h.
402 The main purpose of this common base class is to provide the infrastructure
403 for the derrived classes to iterate over the same set of functions.
407 gl_XML
.gl_print_base
.__init
__(self
)
409 self
.name
= "glX_proto_size.py (from Mesa)"
410 self
.license
= license
.bsd_license_template
% ( "(C) Copyright IBM Corporation 2005", "IBM")
413 class PrintGlxReqSize_h(PrintGlxReqSize_common
):
415 PrintGlxReqSize_common
.__init
__(self
)
416 self
.header_tag
= "_INDIRECT_REQSIZE_H_"
419 def printRealHeader(self
):
420 print '#include <X11/Xfuncproto.h>'
426 def printBody(self
, api
):
427 for func
in api
.functionIterateGlx():
428 if not func
.ignore
and func
.has_variable_size_request():
429 print 'extern PURE _X_HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap);' % (func
.name
)
432 class PrintGlxReqSize_c(PrintGlxReqSize_common
):
433 """Create the server-side 'request size' functions.
435 Create the server-side functions that are used to determine what the
436 size of a varible length command should be. The server then uses
437 this value to determine if the incoming command packed it malformed.
441 PrintGlxReqSize_common
.__init
__(self
)
442 self
.counter_sigs
= {}
445 def printRealHeader(self
):
447 print '#include <GL/gl.h>'
448 print '#include "glxserver.h"'
449 print '#include "glxbyteorder.h"'
450 print '#include "indirect_size.h"'
451 print '#include "indirect_reqsize.h"'
453 print '#define __GLX_PAD(x) (((x) + 3) & ~3)'
455 print '#if defined(__CYGWIN__) || defined(__MINGW32__)'
456 print '# undef HAVE_ALIAS'
458 print '#ifdef HAVE_ALIAS'
459 print '# define ALIAS2(from,to) \\'
460 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
461 print ' __attribute__ ((alias( # to )));'
462 print '# define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize )'
464 print '# define ALIAS(from,to) \\'
465 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
466 print ' { return __glX ## to ## ReqSize( pc, swap ); }'
472 def printBody(self
, api
):
477 for func
in api
.functionIterateGlx():
478 if not func
.has_variable_size_request(): continue
480 ef
= glx_server_enum_function( func
, api
.enums_by_name
)
481 if len(ef
.enums
) == 0: continue
485 if not enum_functions
.has_key(func
.name
):
486 enum_functions
[ func
.name
] = sig
488 if not enum_sigs
.has_key( sig
):
489 enum_sigs
[ sig
] = ef
493 for func
in api
.functionIterateGlx():
494 # Even though server-handcode fuctions are on "the
495 # list", and prototypes are generated for them, there
496 # isn't enough information to generate a size
497 # function. If there was enough information, they
498 # probably wouldn't need to be handcoded in the first
501 if func
.server_handcode
: continue
502 if not func
.has_variable_size_request(): continue
504 if enum_functions
.has_key(func
.name
):
505 sig
= enum_functions
[func
.name
]
506 ef
= enum_sigs
[ sig
]
508 if ef
.name
!= func
.name
:
509 aliases
.append( [func
.name
, ef
.name
] )
511 ef
.Print( func
.name
, self
)
514 self
.printPixelFunction(func
)
515 elif func
.has_variable_size_request():
516 a
= self
.printCountedFunction(func
)
517 if a
: aliases
.append(a
)
520 for [alias_name
, real_name
] in aliases
:
521 print 'ALIAS( %s, %s )' % (alias_name
, real_name
)
526 def common_emit_fixups(self
, fixup
):
527 """Utility function to emit conditional byte-swaps."""
532 print ' %s = bswap_32(%s);' % (name
, name
)
538 def common_emit_one_arg(self
, p
, pc
, adjust
):
541 src
= '(%s *)' % (p
.type_string())
542 print '%-18s = *%11s(%s + %u);' % (dst
, src
, pc
, offset
+ adjust
);
546 def common_func_print_just_header(self
, f
):
548 print '__glX%sReqSize( const GLbyte * pc, Bool swap )' % (f
.name
)
552 def printPixelFunction(self
, f
):
553 self
.common_func_print_just_header(f
)
555 f
.offset_of( f
.parameters
[0].name
)
556 [dim
, w
, h
, d
, junk
] = f
.get_images()[0].get_dimensions()
558 print ' GLint row_length = * (GLint *)(pc + 4);'
561 fixup
= ['row_length', 'skip_rows', 'alignment']
562 print ' GLint image_height = 0;'
563 print ' GLint skip_images = 0;'
564 print ' GLint skip_rows = * (GLint *)(pc + 8);'
565 print ' GLint alignment = * (GLint *)(pc + 16);'
567 fixup
= ['row_length', 'image_height', 'skip_rows', 'skip_images', 'alignment']
568 print ' GLint image_height = * (GLint *)(pc + 8);'
569 print ' GLint skip_rows = * (GLint *)(pc + 16);'
570 print ' GLint skip_images = * (GLint *)(pc + 20);'
571 print ' GLint alignment = * (GLint *)(pc + 32);'
574 for p
in f
.parameterIterateGlxSend():
575 if p
.name
in [w
, h
, d
, img
.img_format
, img
.img_type
, img
.img_target
]:
576 self
.common_emit_one_arg(p
, "pc", 0)
577 fixup
.append( p
.name
)
581 self
.common_emit_fixups(fixup
)
583 if img
.img_null_flag
:
585 print ' if (*(CARD32 *) (pc + %s))' % (img
.offset
- 4)
589 print ' return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (img
.img_format
, img
.img_type
, img
.img_target
, w
, h
, d
)
590 print ' image_height, row_length, skip_images,'
591 print ' skip_rows, alignment);'
597 def printCountedFunction(self
, f
):
607 # Calculate the offset of each counter parameter and the
608 # size string for the variable length parameter(s). While
609 # that is being done, calculate a unique signature for this
612 for p
in f
.parameterIterateGlxSend():
614 fixup
.append( p
.name
)
620 sig
+= "(%u,%u)" % (f
.offset_of(p
.counter
), s
)
621 size
+= '%s%s' % (plus
, p
.size_string())
625 # If the calculated signature matches a function that has
626 # already be emitted, don't emit this function. Instead, add
627 # it to the list of function aliases.
629 if self
.counter_sigs
.has_key(sig
):
630 n
= self
.counter_sigs
[sig
];
634 self
.counter_sigs
[sig
] = f
.name
636 self
.common_func_print_just_header(f
)
639 self
.common_emit_one_arg(p
, "pc", 0)
643 self
.common_emit_fixups(fixup
)
646 print ' return __GLX_PAD(%s);' % (size
)
654 print "Usage: %s [-f input_file_name] -m output_mode [--only-get | --only-set] [--get-alias-set]" % sys
.argv
[0]
655 print " -m output_mode Output mode can be one of 'size_c' or 'size_h'."
656 print " --only-get Only emit 'get'-type functions."
657 print " --only-set Only emit 'set'-type functions."
659 print "By default, both 'get' and 'set'-type functions are emitted."
663 if __name__
== '__main__':
664 file_name
= "gl_API.xml"
667 (args
, trail
) = getopt
.getopt(sys
.argv
[1:], "f:m:h:", ["only-get", "only-set", "header-tag"])
673 which_functions
= PrintGlxSizeStubs_common
.do_get | PrintGlxSizeStubs_common
.do_set
675 for (arg
,val
) in args
:
680 elif arg
== "--only-get":
681 which_functions
= PrintGlxSizeStubs_common
.do_get
682 elif arg
== "--only-set":
683 which_functions
= PrintGlxSizeStubs_common
.do_set
684 elif (arg
== '-h') or (arg
== "--header-tag"):
688 printer
= PrintGlxSizeStubs_c( which_functions
)
689 elif mode
== "size_h":
690 printer
= PrintGlxSizeStubs_h( which_functions
)
692 printer
.header_tag
= header_tag
693 elif mode
== "reqsize_c":
694 printer
= PrintGlxReqSize_c()
695 elif mode
== "reqsize_h":
696 printer
= PrintGlxReqSize_h()
700 api
= gl_XML
.parse_GL_API( file_name
, glX_XML
.glx_item_factory() )