2
# (C) Copyright IBM Corporation 2004, 2005
5
# Permission is hereby granted, free of charge, to any person obtaining a
6
# copy of this software and associated documentation files (the "Software"),
7
# to deal in the Software without restriction, including without limitation
8
# on the rights to use, copy, modify, merge, publish, distribute, sub
9
# license, and/or sell copies of the Software, and to permit persons to whom
10
# the Software is furnished to do so, subject to the following conditions:
12
# The above copyright notice and this permission notice (including the next
13
# paragraph) shall be included in all copies or substantial portions of the
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19
# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25
# Ian Romanick <idr@us.ibm.com>
30
import gl_XML, glX_XML
34
class glx_enum_function(object):
35
def __init__(self, func_name, enum_dict):
40
# "enums" is a set of lists. The element in the set is the
41
# value of the enum. The list is the list of names for that
42
# value. For example, [0x8126] = {"POINT_SIZE_MIN",
43
# "POINT_SIZE_MIN_ARB", "POINT_SIZE_MIN_EXT",
44
# "POINT_SIZE_MIN_SGIS"}.
48
# "count" is indexed by count values. Each element of count
49
# is a list of index to "enums" that have that number of
50
# associated data elements. For example, [4] =
51
# {GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION,
52
# GL_AMBIENT_AND_DIFFUSE} (the enum names are used here,
53
# but the actual hexadecimal values would be in the array).
58
# Fill self.count and self.enums using the dictionary of enums
59
# that was passed in. The generic Get functions (e.g.,
60
# GetBooleanv and friends) are handled specially here. In
61
# the data the generic Get functions are referred to as "Get".
63
if func_name in ["GetIntegerv", "GetBooleanv", "GetFloatv", "GetDoublev"]:
66
match_name = func_name
69
for enum_name in enum_dict:
70
e = enum_dict[ enum_name ]
72
if match_name in e.functions:
73
[count, mode] = e.functions[ match_name ]
75
if mode_set and mode != self.mode:
76
raise RuntimeError("Not all enums for %s have the same mode." % (func_name))
80
if e.value in self.enums:
81
if e.name not in self.enums[ e.value ]:
82
self.enums[ e.value ].append( e )
84
if count not in self.count:
85
self.count[ count ] = []
87
self.enums[ e.value ] = [ e ]
88
self.count[ count ].append( e.value )
94
def signature( self ):
99
raise RuntimeError("i is None. WTF?")
102
for e in self.count[i]:
103
self.sig += "%04x,%d," % (e, i)
112
def PrintUsingTable(self):
113
"""Emit the body of the __gl*_size function using a pair
114
of look-up tables and a mask. The mask is calculated such
115
that (e & mask) is unique for all the valid values of e for
116
this function. The result of (e & mask) is used as an index
117
into the first look-up table. If it matches e, then the
118
same entry of the second table is returned. Otherwise zero
121
It seems like this should cause better code to be generated.
122
However, on x86 at least, the resulting .o file is about 20%
123
larger then the switch-statment version. I am leaving this
124
code in because the results may be different on other
125
platforms (e.g., PowerPC or x86-64)."""
135
# Determine if there is some mask M, such that M = (2^N) - 1,
136
# that will generate unique values for all of the enums.
139
for i in [1, 2, 3, 4, 5, 6, 7, 8]:
146
if (a & mask) == (b & mask):
154
if (mask != 0) and (mask < (2 * count)):
158
for i in range(0, mask + 1):
159
masked_enums[i] = "0";
163
for e in self.count[c]:
165
enum_obj = self.enums[e][0]
166
masked_enums[i] = '0x%04x /* %s */' % (e, enum_obj.name )
170
print(' static const GLushort a[%u] = {' % (mask + 1))
171
for e in masked_enums:
172
print(' %s, ' % (masked_enums[e]))
175
print(' static const GLubyte b[%u] = {' % (mask + 1))
176
for c in masked_count:
177
print(' %u, ' % (masked_count[c]))
180
print(' const unsigned idx = (e & 0x%02xU);' % (mask))
182
print(' return (e == a[idx]) ? (GLint) b[idx] : 0;')
188
def PrintUsingSwitch(self, name):
189
"""Emit the body of the __gl*_size function using a
192
print(' switch( e ) {')
194
for c in sorted(self.count):
195
for e in self.count[c]:
198
# There may be multiple enums with the same
199
# value. This happens has extensions are
200
# promoted from vendor-specific or EXT to
201
# ARB and to the core. Emit the first one as
202
# a case label, and emit the others as
203
# commented-out case labels.
206
for enum_obj in self.enums[e]:
207
list[ enum_obj.priority() ] = enum_obj.name
209
keys = sorted(list.keys())
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 )
275
keys = sorted(foo.keys())
277
p = f.parameters_by_name[ foo[o] ]
279
printer.common_emit_one_arg(p, "pc", 0)
280
fixup.append( p.name )
283
print(' GLsizei compsize;')
286
printer.common_emit_fixups(fixup)
289
print(' compsize = __gl%s_size(%s);' % (f.name, string.join(f.count_parameter_list, ",")))
290
p = f.variable_length_parameter()
291
print(' return safe_pad(%s);' % (p.size_string()))
297
class PrintGlxSizeStubs_common(gl_XML.gl_print_base):
301
def __init__(self, which_functions):
302
gl_XML.gl_print_base.__init__(self)
304
self.name = "glX_proto_size.py (from Mesa)"
305
self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
307
self.emit_set = ((which_functions & PrintGlxSizeStubs_common.do_set) != 0)
308
self.emit_get = ((which_functions & PrintGlxSizeStubs_common.do_get) != 0)
312
class PrintGlxSizeStubs_c(PrintGlxSizeStubs_common):
313
def printRealHeader(self):
315
print('#include <X11/Xfuncproto.h>')
316
print('#include <GL/gl.h>')
318
print('#include "indirect_size_get.h"')
319
print('#include "glxserver.h"')
320
print('#include "indirect_util.h"')
322
print('#include "indirect_size.h"')
330
print('#ifdef HAVE_FUNC_ATTRIBUTE_ALIAS')
331
print('# define ALIAS2(from,to) \\')
332
print(' _X_INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\')
333
print(' __attribute__ ((alias( # to )));')
334
print('# define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )')
336
print('# define ALIAS(from,to) \\')
337
print(' _X_INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\')
338
print(' { return __gl ## to ## _size( e ); }')
344
def printBody(self, api):
348
for func in api.functionIterateGlx():
349
ef = glx_enum_function( func.name, api.enums_by_name )
350
if len(ef.enums) == 0:
353
if (ef.is_set() and self.emit_set) or (not ef.is_set() and self.emit_get):
356
aliases.append( [func.name, enum_sigs[ sig ]] )
358
enum_sigs[ sig ] = func.name
359
ef.Print( func.name )
362
for [alias_name, real_name] in aliases:
363
print('ALIAS( %s, %s )' % (alias_name, real_name))
367
class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common):
368
def printRealHeader(self):
371
* Prototypes for functions used to determine the number of data elements in
372
* various GLX protocol messages.
374
* \\author Ian Romanick <idr@us.ibm.com>
377
print('#include <X11/Xfuncproto.h>')
381
self.printFastcall();
385
def printBody(self, api):
386
for func in api.functionIterateGlx():
387
ef = glx_enum_function( func.name, api.enums_by_name )
388
if len(ef.enums) == 0:
391
if (ef.is_set() and self.emit_set) or (not ef.is_set() and self.emit_get):
392
print('extern _X_INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (func.name))
395
class PrintGlxReqSize_common(gl_XML.gl_print_base):
396
"""Common base class for PrintGlxSizeReq_h and PrintGlxSizeReq_h.
398
The main purpose of this common base class is to provide the infrastructure
399
for the derrived classes to iterate over the same set of functions.
403
gl_XML.gl_print_base.__init__(self)
405
self.name = "glX_proto_size.py (from Mesa)"
406
self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
409
class PrintGlxReqSize_h(PrintGlxReqSize_common):
411
PrintGlxReqSize_common.__init__(self)
412
self.header_tag = "_INDIRECT_REQSIZE_H_"
415
def printRealHeader(self):
416
print('#include <X11/Xfuncproto.h>')
422
def printBody(self, api):
423
for func in api.functionIterateGlx():
424
if not func.ignore and func.has_variable_size_request():
425
print('extern PURE _X_HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap, int reqlen);' % (func.name))
428
class PrintGlxReqSize_c(PrintGlxReqSize_common):
429
"""Create the server-side 'request size' functions.
431
Create the server-side functions that are used to determine what the
432
size of a varible length command should be. The server then uses
433
this value to determine if the incoming command packed it malformed.
437
PrintGlxReqSize_common.__init__(self)
438
self.counter_sigs = {}
441
def printRealHeader(self):
443
print('#include <GL/gl.h>')
444
print('#include "glxserver.h"')
445
print('#include "glxbyteorder.h"')
446
print('#include "indirect_size.h"')
447
print('#include "indirect_reqsize.h"')
449
print('#ifdef HAVE_FUNC_ATTRIBUTE_ALIAS')
450
print('# define ALIAS2(from,to) \\')
451
print(' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap, int reqlen ) \\')
452
print(' __attribute__ ((alias( # to )));')
453
print('# define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize )')
455
print('# define ALIAS(from,to) \\')
456
print(' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap, int reqlen ) \\')
457
print(' { return __glX ## to ## ReqSize( pc, swap, reqlen ); }')
463
def printBody(self, api):
468
for func in api.functionIterateGlx():
469
if not func.has_variable_size_request(): continue
471
ef = glx_server_enum_function( func, api.enums_by_name )
472
if len(ef.enums) == 0: continue
476
if func.name not in enum_functions:
477
enum_functions[ func.name ] = sig
479
if sig not in enum_sigs:
480
enum_sigs[ sig ] = ef
484
for func in api.functionIterateGlx():
485
# Even though server-handcode fuctions are on "the
486
# list", and prototypes are generated for them, there
487
# isn't enough information to generate a size
488
# function. If there was enough information, they
489
# probably wouldn't need to be handcoded in the first
492
if func.server_handcode: continue
493
if not func.has_variable_size_request(): continue
495
if func.name in enum_functions:
496
sig = enum_functions[func.name]
497
ef = enum_sigs[ sig ]
499
if ef.name != func.name:
500
aliases.append( [func.name, ef.name] )
502
ef.Print( func.name, self )
505
self.printPixelFunction(func)
506
elif func.has_variable_size_request():
507
a = self.printCountedFunction(func)
508
if a: aliases.append(a)
511
for [alias_name, real_name] in aliases:
512
print('ALIAS( %s, %s )' % (alias_name, real_name))
517
def common_emit_fixups(self, fixup):
518
"""Utility function to emit conditional byte-swaps."""
521
print(' if (swap) {')
523
print(' %s = bswap_32(%s);' % (name, name))
529
def common_emit_one_arg(self, p, pc, adjust):
532
src = '(%s *)' % (p.type_string())
533
print('%-18s = *%11s(%s + %u);' % (dst, src, pc, offset + adjust));
537
def common_func_print_just_header(self, f):
539
print('__glX%sReqSize( const GLbyte * pc, Bool swap, int reqlen )' % (f.name))
543
def printPixelFunction(self, f):
544
self.common_func_print_just_header(f)
546
f.offset_of( f.parameters[0].name )
547
[dim, w, h, d, junk] = f.get_images()[0].get_dimensions()
549
print(' GLint row_length = * (GLint *)(pc + 4);')
552
fixup = ['row_length', 'skip_rows', 'alignment']
553
print(' GLint image_height = 0;')
554
print(' GLint skip_images = 0;')
555
print(' GLint skip_rows = * (GLint *)(pc + 8);')
556
print(' GLint alignment = * (GLint *)(pc + 16);')
558
fixup = ['row_length', 'image_height', 'skip_rows', 'skip_images', 'alignment']
559
print(' GLint image_height = * (GLint *)(pc + 8);')
560
print(' GLint skip_rows = * (GLint *)(pc + 16);')
561
print(' GLint skip_images = * (GLint *)(pc + 20);')
562
print(' GLint alignment = * (GLint *)(pc + 32);')
565
for p in f.parameterIterateGlxSend():
566
if p.name in [w, h, d, img.img_format, img.img_type, img.img_target]:
567
self.common_emit_one_arg(p, "pc", 0)
568
fixup.append( p.name )
572
self.common_emit_fixups(fixup)
574
if img.img_null_flag:
576
print(' if (*(CARD32 *) (pc + %s))' % (img.offset - 4))
580
print(' return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (img.img_format, img.img_type, img.img_target, w, h, d ))
581
print(' image_height, row_length, skip_images,')
582
print(' skip_rows, alignment);')
588
def printCountedFunction(self, f):
597
# Calculate the offset of each counter parameter and the
598
# size string for the variable length parameter(s). While
599
# that is being done, calculate a unique signature for this
602
for p in f.parameterIterateGlxSend():
604
fixup.append( p.name )
610
sig += "(%u,%u)" % (f.offset_of(p.counter), s)
612
size = p.size_string()
614
size = "safe_add(%s, %s)" % (size, p.size_string())
616
# If the calculated signature matches a function that has
617
# already be emitted, don't emit this function. Instead, add
618
# it to the list of function aliases.
620
if sig in self.counter_sigs:
621
n = self.counter_sigs[sig];
625
self.counter_sigs[sig] = f.name
627
self.common_func_print_just_header(f)
630
self.common_emit_one_arg(p, "pc", 0)
634
self.common_emit_fixups(fixup)
637
print(' return safe_pad(%s);' % (size))
645
"""Parse arguments and return a namespace."""
646
parser = argparse.ArgumentParser()
647
parser.set_defaults(which_functions=(PrintGlxSizeStubs_common.do_get |
648
PrintGlxSizeStubs_common.do_set))
649
parser.add_argument('-f',
651
default='gl_API.xml',
652
help='an XML file describing an OpenGL API.')
653
parser.add_argument('-m',
655
choices=['size_c', 'size_h', 'reqsize_c', 'reqsize_h'],
656
help='Which file to generate')
657
getset = parser.add_mutually_exclusive_group()
658
getset.add_argument('--only-get',
659
dest='which_functions',
660
action='store_const',
661
const=PrintGlxSizeStubs_common.do_get,
662
help='only emit "get-type" functions')
663
getset.add_argument('--only-set',
664
dest='which_functions',
665
action='store_const',
666
const=PrintGlxSizeStubs_common.do_set,
667
help='only emit "set-type" functions')
668
parser.add_argument('--header-tag',
672
help='set header tag value')
673
return parser.parse_args()
680
if args.mode == "size_c":
681
printer = PrintGlxSizeStubs_c(args.which_functions)
682
elif args.mode == "size_h":
683
printer = PrintGlxSizeStubs_h(args.which_functions)
684
if args.header_tag is not None:
685
printer.header_tag = args.header_tag
686
elif args.mode == "reqsize_c":
687
printer = PrintGlxReqSize_c()
688
elif args.mode == "reqsize_h":
689
printer = PrintGlxReqSize_h()
691
api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory())
696
if __name__ == '__main__':