75fc26f5db0eb71036bbaaad1abe0f21cf251047
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>
31 import gl_XML
, glX_XML
35 class glx_enum_function(object):
36 def __init__(self
, func_name
, enum_dict
):
41 # "enums" is a set of lists. The element in the set is the
42 # value of the enum. The list is the list of names for that
43 # value. For example, [0x8126] = {"POINT_SIZE_MIN",
44 # "POINT_SIZE_MIN_ARB", "POINT_SIZE_MIN_EXT",
45 # "POINT_SIZE_MIN_SGIS"}.
49 # "count" is indexed by count values. Each element of count
50 # is a list of index to "enums" that have that number of
51 # associated data elements. For example, [4] =
52 # {GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION,
53 # GL_AMBIENT_AND_DIFFUSE} (the enum names are used here,
54 # but the actual hexadecimal values would be in the array).
59 # Fill self.count and self.enums using the dictionary of enums
60 # that was passed in. The generic Get functions (e.g.,
61 # GetBooleanv and friends) are handled specially here. In
62 # the data the generic Get functions are referred to as "Get".
64 if func_name
in ["GetIntegerv", "GetBooleanv", "GetFloatv", "GetDoublev"]:
67 match_name
= func_name
70 for enum_name
in enum_dict
:
71 e
= enum_dict
[ enum_name
]
73 if e
.functions
.has_key( match_name
):
74 [count
, mode
] = e
.functions
[ match_name
]
76 if mode_set
and mode
!= self
.mode
:
77 raise RuntimeError("Not all enums for %s have the same mode." % (func_name
))
81 if self
.enums
.has_key( e
.value
):
82 if e
.name
not in self
.enums
[ e
.value
]:
83 self
.enums
[ e
.value
].append( e
)
85 if not self
.count
.has_key( count
):
86 self
.count
[ count
] = []
88 self
.enums
[ e
.value
] = [ e
]
89 self
.count
[ count
].append( e
.value
)
95 def signature( self
):
100 raise RuntimeError("i is None. WTF?")
103 for e
in self
.count
[i
]:
104 self
.sig
+= "%04x,%d," % (e
, i
)
113 def PrintUsingTable(self
):
114 """Emit the body of the __gl*_size function using a pair
115 of look-up tables and a mask. The mask is calculated such
116 that (e & mask) is unique for all the valid values of e for
117 this function. The result of (e & mask) is used as an index
118 into the first look-up table. If it matches e, then the
119 same entry of the second table is returned. Otherwise zero
122 It seems like this should cause better code to be generated.
123 However, on x86 at least, the resulting .o file is about 20%
124 larger then the switch-statment version. I am leaving this
125 code in because the results may be different on other
126 platforms (e.g., PowerPC or x86-64)."""
133 if self
.count
.has_key(-1):
136 # Determine if there is some mask M, such that M = (2^N) - 1,
137 # that will generate unique values for all of the enums.
140 for i
in [1, 2, 3, 4, 5, 6, 7, 8]:
147 if (a
& mask
) == (b
& mask
):
155 if (mask
!= 0) and (mask
< (2 * count
)):
159 for i
in range(0, mask
+ 1):
160 masked_enums
[i
] = "0";
164 for e
in self
.count
[c
]:
166 enum_obj
= self
.enums
[e
][0]
167 masked_enums
[i
] = '0x%04x /* %s */' % (e
, enum_obj
.name
)
171 print ' static const GLushort a[%u] = {' % (mask
+ 1)
172 for e
in masked_enums
:
173 print ' %s, ' % (masked_enums
[e
])
176 print ' static const GLubyte b[%u] = {' % (mask
+ 1)
177 for c
in masked_count
:
178 print ' %u, ' % (masked_count
[c
])
181 print ' const unsigned idx = (e & 0x%02xU);' % (mask
)
183 print ' return (e == a[idx]) ? (GLint) b[idx] : 0;'
189 def PrintUsingSwitch(self
, name
):
190 """Emit the body of the __gl*_size function using a
193 print ' switch( e ) {'
196 for e
in self
.count
[c
]:
199 # There may be multiple enums with the same
200 # value. This happens has extensions are
201 # promoted from vendor-specific or EXT to
202 # ARB and to the core. Emit the first one as
203 # a case label, and emit the others as
204 # commented-out case labels.
207 for enum_obj
in self
.enums
[e
]:
208 list[ enum_obj
.priority() ] = enum_obj
.name
215 print ' case GL_%s:' % (j
)
218 print '/* case GL_%s:*/' % (j
)
221 print ' return __gl%s_variable_size( e );' % (name
)
223 print ' return %u;' % (c
)
225 print ' default: return 0;'
229 def Print(self
, name
):
230 print '_X_INTERNAL PURE FASTCALL GLint'
231 print '__gl%s_size( GLenum e )' % (name
)
234 if not self
.PrintUsingTable():
235 self
.PrintUsingSwitch(name
)
241 class glx_server_enum_function(glx_enum_function
):
242 def __init__(self
, func
, enum_dict
):
243 glx_enum_function
.__init
__(self
, func
.name
, enum_dict
)
249 def signature( self
):
251 sig
= glx_enum_function
.signature(self
)
253 p
= self
.function
.variable_length_parameter()
255 sig
+= "%u" % (p
.size())
262 def Print(self
, name
, printer
):
264 printer
.common_func_print_just_header( f
)
269 for param_name
in f
.count_parameter_list
:
270 o
= f
.offset_of( param_name
)
273 for param_name
in f
.counter_list
:
274 o
= f
.offset_of( param_name
)
280 p
= f
.parameters_by_name
[ foo
[o
] ]
282 printer
.common_emit_one_arg(p
, "pc", 0)
283 fixup
.append( p
.name
)
286 print ' GLsizei compsize;'
289 printer
.common_emit_fixups(fixup
)
292 print ' compsize = __gl%s_size(%s);' % (f
.name
, string
.join(f
.count_parameter_list
, ","))
293 p
= f
.variable_length_parameter()
294 print ' return __GLX_PAD(%s);' % (p
.size_string())
300 class PrintGlxSizeStubs_common(gl_XML
.gl_print_base
):
304 def __init__(self
, which_functions
):
305 gl_XML
.gl_print_base
.__init
__(self
)
307 self
.name
= "glX_proto_size.py (from Mesa)"
308 self
.license
= license
.bsd_license_template
% ( "(C) Copyright IBM Corporation 2004", "IBM")
310 self
.emit_set
= ((which_functions
& PrintGlxSizeStubs_common
.do_set
) != 0)
311 self
.emit_get
= ((which_functions
& PrintGlxSizeStubs_common
.do_get
) != 0)
315 class PrintGlxSizeStubs_c(PrintGlxSizeStubs_common
):
316 def printRealHeader(self
):
318 print '#include <X11/Xfuncproto.h>'
319 print '#include <GL/gl.h>'
321 print '#include "indirect_size_get.h"'
322 print '#include "glxserver.h"'
323 print '#include "indirect_util.h"'
325 print '#include "indirect_size.h"'
333 print '#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(GLX_USE_APPLEGL)'
334 print '# undef HAVE_ALIAS'
336 print '#ifdef HAVE_ALIAS'
337 print '# define ALIAS2(from,to) \\'
338 print ' _X_INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
339 print ' __attribute__ ((alias( # to )));'
340 print '# define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
342 print '# define ALIAS(from,to) \\'
343 print ' _X_INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
344 print ' { return __gl ## to ## _size( e ); }'
350 def printBody(self
, api
):
354 for func
in api
.functionIterateGlx():
355 ef
= glx_enum_function( func
.name
, api
.enums_by_name
)
356 if len(ef
.enums
) == 0:
359 if (ef
.is_set() and self
.emit_set
) or (not ef
.is_set() and self
.emit_get
):
361 if enum_sigs
.has_key( sig
):
362 aliases
.append( [func
.name
, enum_sigs
[ sig
]] )
364 enum_sigs
[ sig
] = func
.name
365 ef
.Print( func
.name
)
368 for [alias_name
, real_name
] in aliases
:
369 print 'ALIAS( %s, %s )' % (alias_name
, real_name
)
373 class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common
):
374 def printRealHeader(self
):
377 * Prototypes for functions used to determine the number of data elements in
378 * various GLX protocol messages.
380 * \\author Ian Romanick <idr@us.ibm.com>
383 print '#include <X11/Xfuncproto.h>'
387 self
.printFastcall();
391 def printBody(self
, api
):
392 for func
in api
.functionIterateGlx():
393 ef
= glx_enum_function( func
.name
, api
.enums_by_name
)
394 if len(ef
.enums
) == 0:
397 if (ef
.is_set() and self
.emit_set
) or (not ef
.is_set() and self
.emit_get
):
398 print 'extern _X_INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (func
.name
)
401 class PrintGlxReqSize_common(gl_XML
.gl_print_base
):
402 """Common base class for PrintGlxSizeReq_h and PrintGlxSizeReq_h.
404 The main purpose of this common base class is to provide the infrastructure
405 for the derrived classes to iterate over the same set of functions.
409 gl_XML
.gl_print_base
.__init
__(self
)
411 self
.name
= "glX_proto_size.py (from Mesa)"
412 self
.license
= license
.bsd_license_template
% ( "(C) Copyright IBM Corporation 2005", "IBM")
415 class PrintGlxReqSize_h(PrintGlxReqSize_common
):
417 PrintGlxReqSize_common
.__init
__(self
)
418 self
.header_tag
= "_INDIRECT_REQSIZE_H_"
421 def printRealHeader(self
):
422 print '#include <X11/Xfuncproto.h>'
428 def printBody(self
, api
):
429 for func
in api
.functionIterateGlx():
430 if not func
.ignore
and func
.has_variable_size_request():
431 print 'extern PURE _X_HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap);' % (func
.name
)
434 class PrintGlxReqSize_c(PrintGlxReqSize_common
):
435 """Create the server-side 'request size' functions.
437 Create the server-side functions that are used to determine what the
438 size of a varible length command should be. The server then uses
439 this value to determine if the incoming command packed it malformed.
443 PrintGlxReqSize_common
.__init
__(self
)
444 self
.counter_sigs
= {}
447 def printRealHeader(self
):
449 print '#include <GL/gl.h>'
450 print '#include "glxserver.h"'
451 print '#include "glxbyteorder.h"'
452 print '#include "indirect_size.h"'
453 print '#include "indirect_reqsize.h"'
455 print '#define __GLX_PAD(x) (((x) + 3) & ~3)'
457 print '#if defined(__CYGWIN__) || defined(__MINGW32__)'
458 print '# undef HAVE_ALIAS'
460 print '#ifdef HAVE_ALIAS'
461 print '# define ALIAS2(from,to) \\'
462 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
463 print ' __attribute__ ((alias( # to )));'
464 print '# define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize )'
466 print '# define ALIAS(from,to) \\'
467 print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\'
468 print ' { return __glX ## to ## ReqSize( pc, swap ); }'
474 def printBody(self
, api
):
479 for func
in api
.functionIterateGlx():
480 if not func
.has_variable_size_request(): continue
482 ef
= glx_server_enum_function( func
, api
.enums_by_name
)
483 if len(ef
.enums
) == 0: continue
487 if not enum_functions
.has_key(func
.name
):
488 enum_functions
[ func
.name
] = sig
490 if not enum_sigs
.has_key( sig
):
491 enum_sigs
[ sig
] = ef
495 for func
in api
.functionIterateGlx():
496 # Even though server-handcode fuctions are on "the
497 # list", and prototypes are generated for them, there
498 # isn't enough information to generate a size
499 # function. If there was enough information, they
500 # probably wouldn't need to be handcoded in the first
503 if func
.server_handcode
: continue
504 if not func
.has_variable_size_request(): continue
506 if enum_functions
.has_key(func
.name
):
507 sig
= enum_functions
[func
.name
]
508 ef
= enum_sigs
[ sig
]
510 if ef
.name
!= func
.name
:
511 aliases
.append( [func
.name
, ef
.name
] )
513 ef
.Print( func
.name
, self
)
516 self
.printPixelFunction(func
)
517 elif func
.has_variable_size_request():
518 a
= self
.printCountedFunction(func
)
519 if a
: aliases
.append(a
)
522 for [alias_name
, real_name
] in aliases
:
523 print 'ALIAS( %s, %s )' % (alias_name
, real_name
)
528 def common_emit_fixups(self
, fixup
):
529 """Utility function to emit conditional byte-swaps."""
534 print ' %s = bswap_32(%s);' % (name
, name
)
540 def common_emit_one_arg(self
, p
, pc
, adjust
):
543 src
= '(%s *)' % (p
.type_string())
544 print '%-18s = *%11s(%s + %u);' % (dst
, src
, pc
, offset
+ adjust
);
548 def common_func_print_just_header(self
, f
):
550 print '__glX%sReqSize( const GLbyte * pc, Bool swap )' % (f
.name
)
554 def printPixelFunction(self
, f
):
555 self
.common_func_print_just_header(f
)
557 f
.offset_of( f
.parameters
[0].name
)
558 [dim
, w
, h
, d
, junk
] = f
.get_images()[0].get_dimensions()
560 print ' GLint row_length = * (GLint *)(pc + 4);'
563 fixup
= ['row_length', 'skip_rows', 'alignment']
564 print ' GLint image_height = 0;'
565 print ' GLint skip_images = 0;'
566 print ' GLint skip_rows = * (GLint *)(pc + 8);'
567 print ' GLint alignment = * (GLint *)(pc + 16);'
569 fixup
= ['row_length', 'image_height', 'skip_rows', 'skip_images', 'alignment']
570 print ' GLint image_height = * (GLint *)(pc + 8);'
571 print ' GLint skip_rows = * (GLint *)(pc + 16);'
572 print ' GLint skip_images = * (GLint *)(pc + 20);'
573 print ' GLint alignment = * (GLint *)(pc + 32);'
576 for p
in f
.parameterIterateGlxSend():
577 if p
.name
in [w
, h
, d
, img
.img_format
, img
.img_type
, img
.img_target
]:
578 self
.common_emit_one_arg(p
, "pc", 0)
579 fixup
.append( p
.name
)
583 self
.common_emit_fixups(fixup
)
585 if img
.img_null_flag
:
587 print ' if (*(CARD32 *) (pc + %s))' % (img
.offset
- 4)
591 print ' return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (img
.img_format
, img
.img_type
, img
.img_target
, w
, h
, d
)
592 print ' image_height, row_length, skip_images,'
593 print ' skip_rows, alignment);'
599 def printCountedFunction(self
, f
):
609 # Calculate the offset of each counter parameter and the
610 # size string for the variable length parameter(s). While
611 # that is being done, calculate a unique signature for this
614 for p
in f
.parameterIterateGlxSend():
616 fixup
.append( p
.name
)
622 sig
+= "(%u,%u)" % (f
.offset_of(p
.counter
), s
)
623 size
+= '%s%s' % (plus
, p
.size_string())
627 # If the calculated signature matches a function that has
628 # already be emitted, don't emit this function. Instead, add
629 # it to the list of function aliases.
631 if self
.counter_sigs
.has_key(sig
):
632 n
= self
.counter_sigs
[sig
];
636 self
.counter_sigs
[sig
] = f
.name
638 self
.common_func_print_just_header(f
)
641 self
.common_emit_one_arg(p
, "pc", 0)
645 self
.common_emit_fixups(fixup
)
648 print ' return __GLX_PAD(%s);' % (size
)
656 """Parse arguments and return a namespace."""
657 parser
= argparse
.ArgumentParser()
658 parser
.set_defaults(which_functions
=(PrintGlxSizeStubs_common
.do_get |
659 PrintGlxSizeStubs_common
.do_set
))
660 parser
.add_argument('-f',
662 default
='gl_API.xml',
663 help='an XML file describing an OpenGL API.')
664 parser
.add_argument('-m',
666 choices
=['size_c', 'size_h', 'reqsize_c', 'reqsize_h'],
667 help='Which file to generate')
668 getset
= parser
.add_mutually_exclusive_group()
669 getset
.add_argument('--only-get',
670 dest
='which_functions',
671 action
='store_const',
672 const
=PrintGlxSizeStubs_common
.do_get
,
673 help='only emit "get-type" functions')
674 getset
.add_argument('--only-set',
675 dest
='which_functions',
676 action
='store_const',
677 const
=PrintGlxSizeStubs_common
.do_set
,
678 help='only emit "set-type" functions')
679 parser
.add_argument('--header-tag',
683 help='set header tag value')
684 return parser
.parse_args()
691 if args
.mode
== "size_c":
692 printer
= PrintGlxSizeStubs_c(args
.which_functions
)
693 elif args
.mode
== "size_h":
694 printer
= PrintGlxSizeStubs_h(args
.which_functions
)
695 if args
.header_tag
is not None:
696 printer
.header_tag
= args
.header_tag
697 elif args
.mode
== "reqsize_c":
698 printer
= PrintGlxReqSize_c()
699 elif args
.mode
== "reqsize_h":
700 printer
= PrintGlxReqSize_h()
702 api
= gl_XML
.parse_GL_API(args
.filename
, glX_XML
.glx_item_factory())
707 if __name__
== '__main__':