X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fglapi%2FglX_proto_size.py;h=95cb5110cc3cc8d7dd08619883a90ddd33d15432;hb=507f4e7a7448fb246febefe8819b7b3ac70a35b4;hp=ecab65d3f0c077915638eeeb17c127bd35d28a0d;hpb=5aa6dc329b983b95071700c3af9353e3b35454d9;p=mesa.git diff --git a/src/mesa/glapi/glX_proto_size.py b/src/mesa/glapi/glX_proto_size.py index ecab65d3f0c..95cb5110cc3 100644 --- a/src/mesa/glapi/glX_proto_size.py +++ b/src/mesa/glapi/glX_proto_size.py @@ -25,114 +25,313 @@ # Authors: # Ian Romanick -from xml.sax import saxutils -from xml.sax import make_parser -from xml.sax.handler import feature_namespaces - -import gl_XML -import glX_XML +import gl_XML, glX_XML import license -import sys, getopt, copy +import sys, getopt, copy, string -class SizeStubFunctionIterator: - """Iterate over functions that need "size" information. - - Iterate over the functions that have variable sized data. First the - "set"-type functions are iterated followed by the "get"-type - functions. - """ +class glx_enum_function: + def __init__(self, func_name, enum_dict): + self.name = func_name + self.mode = 1 + self.sig = None + + # "enums" is a set of lists. The element in the set is the + # value of the enum. The list is the list of names for that + # value. For example, [0x8126] = {"POINT_SIZE_MIN", + # "POINT_SIZE_MIN_ARB", "POINT_SIZE_MIN_EXT", + # "POINT_SIZE_MIN_SGIS"}. + + self.enums = {} + + # "count" is indexed by count values. Each element of count + # is a list of index to "enums" that have that number of + # associated data elements. For example, [4] = + # {GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION, + # GL_AMBIENT_AND_DIFFUSE} (the enum names are used here, + # but the actual hexadecimal values would be in the array). + + self.count = {} + + + # Fill self.count and self.enums using the dictionary of enums + # that was passed in. The generic Get functions (e.g., + # GetBooleanv and friends) are handled specially here. In + # the data the generic Get functions are refered to as "Get". + + if func_name in ["GetIntegerv", "GetBooleanv", "GetFloatv", "GetDoublev"]: + match_name = "Get" + else: + match_name = func_name - def __init__(self, context): - self.data = [] - self.index = 0 + mode_set = 0 + for enum_name in enum_dict: + e = enum_dict[ enum_name ] - set_functions = [] - get_functions = [] - extra_data = [] + if e.functions.has_key( match_name ): + [count, mode] = e.functions[ match_name ] - for f in gl_XML.glFunctionIterator(context): - if f.fn_offset < 0: break + if mode_set and mode != self.mode: + raise RuntimeError("Not all enums for %s have the same mode." % (func_name)) - if context.glx_enum_functions.has_key(f.name): - ef = context.glx_enum_functions[f.name] - if ef.is_set(): - set_functions.append(f) + self.mode = mode + + if self.enums.has_key( e.value ): + if e.name not in self.enums[ e.value ]: + self.enums[ e.value ].append( e ) else: - get_functions.append(f) + if not self.count.has_key( count ): + self.count[ count ] = [] + + self.enums[ e.value ] = [ e ] + self.count[ count ].append( e.value ) + + + return - if (context.which_functions & PrintGlxSizeStubs_c.do_set) != 0: - self.data += set_functions - elif context.get_alias_set: - extra_data = set_functions + def signature( self ): + if self.sig == None: + self.sig = "" + for i in self.count: + if i == None: + raise RuntimeError("i is None. WTF?") - if (context.which_functions & PrintGlxSizeStubs_c.do_get) != 0: - self.data += get_functions + self.count[i].sort() + for e in self.count[i]: + self.sig += "%04x,%d," % (e, i) + return self.sig - for f in extra_data + self.data: - sig = context.glx_enum_functions[f.name].signature() - if not context.glx_enum_sigs.has_key(sig): - context.glx_enum_sigs[sig] = f.name; + def is_set( self ): + return self.mode + + def PrintUsingTable(self): + """Emit the body of the __gl*_size function using a pair + of look-up tables and a mask. The mask is calculated such + that (e & mask) is unique for all the valid values of e for + this function. The result of (e & mask) is used as an index + into the first look-up table. If it matches e, then the + same entry of the second table is returned. Otherwise zero + is returned. + + It seems like this should cause better code to be generated. + However, on x86 at least, the resulting .o file is about 20% + larger then the switch-statment version. I am leaving this + code in because the results may be different on other + platforms (e.g., PowerPC or x86-64).""" + + return 0 + count = 0 + for a in self.enums: + count += 1 + + if self.count.has_key(-1): + return 0 + + # Determine if there is some mask M, such that M = (2^N) - 1, + # that will generate unique values for all of the enums. + + mask = 0 + for i in [1, 2, 3, 4, 5, 6, 7, 8]: + mask = (1 << i) - 1 + + fail = 0; + for a in self.enums: + for b in self.enums: + if a != b: + if (a & mask) == (b & mask): + fail = 1; + + if not fail: + break; + else: + mask = 0 + + if (mask != 0) and (mask < (2 * count)): + masked_enums = {} + masked_count = {} + + for i in range(0, mask + 1): + masked_enums[i] = "0"; + masked_count[i] = 0; + + for c in self.count: + for e in self.count[c]: + i = e & mask + enum_obj = self.enums[e][0] + masked_enums[i] = '0x%04x /* %s */' % (e, enum_obj.name ) + masked_count[i] = c + + + print ' static const GLushort a[%u] = {' % (mask + 1) + for e in masked_enums: + print ' %s, ' % (masked_enums[e]) + print ' };' + + print ' static const GLubyte b[%u] = {' % (mask + 1) + for c in masked_count: + print ' %u, ' % (masked_count[c]) + print ' };' + + print ' const unsigned idx = (e & 0x%02xU);' % (mask) + print '' + print ' return (e == a[idx]) ? (GLint) b[idx] : 0;' + return 1; + else: + return 0; + + + def PrintUsingSwitch(self, name): + """Emit the body of the __gl*_size function using a + switch-statement.""" + + print ' switch( e ) {' + + for c in self.count: + for e in self.count[c]: + first = 1 + + # There may be multiple enums with the same + # value. This happens has extensions are + # promoted from vendor-specific or EXT to + # ARB and to the core. Emit the first one as + # a case label, and emit the others as + # commented-out case labels. + + list = {} + for enum_obj in self.enums[e]: + list[ enum_obj.priority() ] = enum_obj.name + + keys = list.keys() + keys.sort() + for k in keys: + j = list[k] + if first: + print ' case GL_%s:' % (j) + first = 0 + else: + print '/* case GL_%s:*/' % (j) + + if c == -1: + print ' return __gl%s_variable_size( e );' % (name) + else: + print ' return %u;' % (c) + + print ' default: return 0;' + print ' }' + + + def Print(self, name): + print 'INTERNAL PURE FASTCALL GLint' + print '__gl%s_size( GLenum e )' % (name) + print '{' + + if not self.PrintUsingTable(): + self.PrintUsingSwitch(name) + + print '}' + print '' + + +class glx_server_enum_function(glx_enum_function): + def __init__(self, func, enum_dict): + glx_enum_function.__init__(self, func.name, enum_dict) + + self.function = func return - def __iter__(self): - return self + def signature( self ): + if self.sig == None: + sig = glx_enum_function.signature(self) + + p = self.function.variable_length_parameter() + if p: + sig += "%u" % (p.size()) + + self.sig = sig + + return self.sig; + + + def Print(self, name, printer): + f = self.function + printer.common_func_print_just_header( f ) + + fixup = [] + + foo = {} + for param_name in f.count_parameter_list: + o = f.offset_of( param_name ) + foo[o] = param_name + + for param_name in f.counter_list: + o = f.offset_of( param_name ) + foo[o] = param_name + keys = foo.keys() + keys.sort() + for o in keys: + p = f.parameters_by_name[ foo[o] ] - def next(self): - if self.index == len(self.data): - raise StopIteration + printer.common_emit_one_arg(p, "pc", 0) + fixup.append( p.name ) - f = self.data[ self.index ] - self.index += 1 - return f + print ' GLsizei compsize;' + print '' + printer.common_emit_fixups(fixup) + + print '' + print ' compsize = __gl%s_size(%s);' % (f.name, string.join(f.count_parameter_list, ",")) + p = f.variable_length_parameter() + print ' return __GLX_PAD(%s);' % (p.size_string()) -class PrintGlxSizeStubs_common(glX_XML.GlxProto): + print '}' + print '' + + +class PrintGlxSizeStubs_common(gl_XML.gl_print_base): do_get = (1 << 0) do_set = (1 << 1) - do_get_alias_set = (1 << 2) def __init__(self, which_functions): - glX_XML.GlxProto.__init__(self) - self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM") - self.aliases = [] - self.glx_enum_sigs = {} - self.name = "glX_proto_size.py (from Mesa)" - self.which_functions = which_functions - - if (((which_functions & PrintGlxSizeStubs_common.do_set) != 0) and ((which_functions & PrintGlxSizeStubs_common.do_get) != 0)) or ((which_functions & PrintGlxSizeStubs_common.do_get_alias_set) != 0): - self.get_alias_set = 1 - else: - self.get_alias_set = 0 + gl_XML.gl_print_base.__init__(self) + self.name = "glX_proto_size.py (from Mesa)" + self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM") - def functionIterator(self): - return SizeStubFunctionIterator(self) + self.emit_set = ((which_functions & PrintGlxSizeStubs_common.do_set) != 0) + self.emit_get = ((which_functions & PrintGlxSizeStubs_common.do_get) != 0) + return class PrintGlxSizeStubs_c(PrintGlxSizeStubs_common): def printRealHeader(self): print '' print '#include ' - print '#include "indirect_size.h"' + if self.emit_get: + print '#include "indirect_size_get.h"' + print '#include "glxserver.h"' + print '#include "indirect_util.h"' + print '#include "indirect_size.h"' + print '' - glX_XML.printHaveAlias() - print '' - glX_XML.printPure() + self.printPure() print '' - glX_XML.printFastcall() + self.printFastcall() print '' - glX_XML.printVisibility( "INTERNAL", "internal" ) + self.printVisibility( "INTERNAL", "internal" ) print '' print '' + print '#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__APPLE__)' + print '# undef HAVE_ALIAS' + print '#endif' print '#ifdef HAVE_ALIAS' print '# define ALIAS2(from,to) \\' print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\' @@ -147,56 +346,309 @@ class PrintGlxSizeStubs_c(PrintGlxSizeStubs_common): print '' - def printRealFooter(self): - for a in self.aliases: - print a + def printBody(self, api): + enum_sigs = {} + aliases = [] + for func in api.functionIterateGlx(): + ef = glx_enum_function( func.name, api.enums_by_name ) + if len(ef.enums) == 0: + continue - def printFunction(self, f): - ef = self.glx_enum_functions[f.name] - n = self.glx_enum_sigs[ ef.signature() ]; + if (ef.is_set() and self.emit_set) or (not ef.is_set() and self.emit_get): + sig = ef.signature() + if enum_sigs.has_key( sig ): + aliases.append( [func.name, enum_sigs[ sig ]] ) + else: + enum_sigs[ sig ] = func.name + ef.Print( func.name ) - if n != f.name: - a = 'ALIAS( %s, %s )' % (f.name, n) - self.aliases.append(a) - else: - ef.Print( f.name ) + + for [alias_name, real_name] in aliases: + print 'ALIAS( %s, %s )' % (alias_name, real_name) class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common): def printRealHeader(self): - print """ -/** + print """/** * \\file * Prototypes for functions used to determine the number of data elements in * various GLX protocol messages. * * \\author Ian Romanick */ +""" + self.printPure(); + print '' + self.printFastcall(); + print '' + self.printVisibility( "INTERNAL", "internal" ); + print '' -#if !defined( _GLXSIZE_H_ ) -# define _GLXSIZE_H_ -""" - glX_XML.printPure(); + def printBody(self, api): + for func in api.functionIterateGlx(): + ef = glx_enum_function( func.name, api.enums_by_name ) + if len(ef.enums) == 0: + continue + + if (ef.is_set() and self.emit_set) or (not ef.is_set() and self.emit_get): + print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (func.name) + + +class PrintGlxReqSize_common(gl_XML.gl_print_base): + """Common base class for PrintGlxSizeReq_h and PrintGlxSizeReq_h. + + The main purpose of this common base class is to provide the infrastructure + for the derrived classes to iterate over the same set of functions. + """ + + def __init__(self): + gl_XML.gl_print_base.__init__(self) + + self.name = "glX_proto_size.py (from Mesa)" + self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM") + + +class PrintGlxReqSize_h(PrintGlxReqSize_common): + def __init__(self): + PrintGlxReqSize_common.__init__(self) + self.header_tag = "_INDIRECT_REQSIZE_H_" + + + def printRealHeader(self): + self.printVisibility("HIDDEN", "hidden") + print '' + self.printPure() + print '' + + + def printBody(self, api): + for func in api.functionIterateGlx(): + if not func.ignore and func.has_variable_size_request(): + print 'extern PURE HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap);' % (func.name) + + +class PrintGlxReqSize_c(PrintGlxReqSize_common): + """Create the server-side 'request size' functions. + + Create the server-side functions that are used to determine what the + size of a varible length command should be. The server then uses + this value to determine if the incoming command packed it malformed. + """ + + def __init__(self): + PrintGlxReqSize_common.__init__(self) + self.counter_sigs = {} + + + def printRealHeader(self): print '' - glX_XML.printFastcall(); + print '#include ' + print '#include "glxserver.h"' + print '#include "glxbyteorder.h"' + print '#include "indirect_size.h"' + print '#include "indirect_reqsize.h"' + print '' + print '#define __GLX_PAD(x) (((x) + 3) & ~3)' + print '' + print '#if defined(__CYGWIN__) || defined(__MINGW32__)' + print '# undef HAVE_ALIAS' + print '#endif' + print '#ifdef HAVE_ALIAS' + print '# define ALIAS2(from,to) \\' + print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\' + print ' __attribute__ ((alias( # to )));' + print '# define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize )' + print '#else' + print '# define ALIAS(from,to) \\' + print ' GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap ) \\' + print ' { return __glX ## to ## ReqSize( pc, swap ); }' + print '#endif' print '' - glX_XML.printVisibility( "INTERNAL", "internal" ); print '' - def printRealFooter(self): + + def printBody(self, api): + aliases = [] + enum_functions = {} + enum_sigs = {} + + for func in api.functionIterateGlx(): + if not func.has_variable_size_request(): continue + + ef = glx_server_enum_function( func, api.enums_by_name ) + if len(ef.enums) == 0: continue + + sig = ef.signature() + + if not enum_functions.has_key(func.name): + enum_functions[ func.name ] = sig + + if not enum_sigs.has_key( sig ): + enum_sigs[ sig ] = ef + + + + for func in api.functionIterateGlx(): + # Even though server-handcode fuctions are on "the + # list", and prototypes are generated for them, there + # isn't enough information to generate a size + # function. If there was enough information, they + # probably wouldn't need to be handcoded in the first + # place! + + if func.server_handcode: continue + if not func.has_variable_size_request(): continue + + if enum_functions.has_key(func.name): + sig = enum_functions[func.name] + ef = enum_sigs[ sig ] + + if ef.name != func.name: + aliases.append( [func.name, ef.name] ) + else: + ef.Print( func.name, self ) + + elif func.images: + self.printPixelFunction(func) + elif func.has_variable_size_request(): + a = self.printCountedFunction(func) + if a: aliases.append(a) + + + for [alias_name, real_name] in aliases: + print 'ALIAS( %s, %s )' % (alias_name, real_name) + + return + + + def common_emit_fixups(self, fixup): + """Utility function to emit conditional byte-swaps.""" + + if fixup: + print ' if (swap) {' + for name in fixup: + print ' %s = bswap_32(%s);' % (name, name) + print ' }' + + return + + + def common_emit_one_arg(self, p, pc, adjust): + offset = p.offset + dst = p.string() + src = '(%s *)' % (p.type_string()) + print '%-18s = *%11s(%s + %u);' % (dst, src, pc, offset + adjust); + return + + + def common_func_print_just_header(self, f): + print 'int' + print '__glX%sReqSize( const GLbyte * pc, Bool swap )' % (f.name) + print '{' + + + def printPixelFunction(self, f): + self.common_func_print_just_header(f) + + f.offset_of( f.parameters[0].name ) + [dim, w, h, d, junk] = f.get_images()[0].get_dimensions() + + print ' GLint row_length = * (GLint *)(pc + 4);' + + if dim < 3: + fixup = ['row_length', 'skip_rows', 'alignment'] + print ' GLint image_height = 0;' + print ' GLint skip_images = 0;' + print ' GLint skip_rows = * (GLint *)(pc + 8);' + print ' GLint alignment = * (GLint *)(pc + 16);' + else: + fixup = ['row_length', 'image_height', 'skip_rows', 'skip_images', 'alignment'] + print ' GLint image_height = * (GLint *)(pc + 8);' + print ' GLint skip_rows = * (GLint *)(pc + 16);' + print ' GLint skip_images = * (GLint *)(pc + 20);' + print ' GLint alignment = * (GLint *)(pc + 32);' + + img = f.images[0] + for p in f.parameterIterateGlxSend(): + if p.name in [w, h, d, img.img_format, img.img_type, img.img_target]: + self.common_emit_one_arg(p, "pc", 0) + fixup.append( p.name ) + + print '' + + self.common_emit_fixups(fixup) + + if img.img_null_flag: + print '' + print ' if (*(CARD32 *) (pc + %s))' % (img.offset - 4) + print ' return 0;' + + print '' + print ' return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (img.img_format, img.img_type, img.img_target, w, h, d ) + print ' image_height, row_length, skip_images,' + print ' skip_rows, alignment);' + print '}' print '' - print "# undef INTERNAL" - print "# undef PURE" - print "# undef FASTCALL" - print "#endif /* !defined( _GLXSIZE_H_ ) */" + return + + + def printCountedFunction(self, f): + + sig = "" + offset = 0 + fixup = [] + params = [] + plus = '' + size = '' + param_offsets = {} + + # Calculate the offset of each counter parameter and the + # size string for the variable length parameter(s). While + # that is being done, calculate a unique signature for this + # function. + + for p in f.parameterIterateGlxSend(): + if p.is_counter: + fixup.append( p.name ) + params.append( p ) + elif p.counter: + s = p.size() + if s == 0: s = 1 + + sig += "(%u,%u)" % (f.offset_of(p.counter), s) + size += '%s%s' % (plus, p.size_string()) + plus = ' + ' + + + # If the calculated signature matches a function that has + # already be emitted, don't emit this function. Instead, add + # it to the list of function aliases. + + if self.counter_sigs.has_key(sig): + n = self.counter_sigs[sig]; + alias = [f.name, n] + else: + alias = None + self.counter_sigs[sig] = f.name + + self.common_func_print_just_header(f) + + for p in params: + self.common_emit_one_arg(p, "pc", 0) + + + print '' + self.common_emit_fixups(fixup) + print '' + print ' return __GLX_PAD(%s);' % (size) + print '}' + print '' - def printFunction(self, f): - ef = self.glx_enum_functions[f.name] - print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (f.name) + return alias def show_usage(): @@ -204,8 +656,6 @@ def show_usage(): print " -m output_mode Output mode can be one of 'size_c' or 'size_h'." print " --only-get Only emit 'get'-type functions." print " --only-set Only emit 'set'-type functions." - print " --get-alias-set When only 'get'-type functions are emitted, allow them" - print " to be aliases to 'set'-type funcitons." print "" print "By default, both 'get' and 'set'-type functions are emitted." sys.exit(1) @@ -215,11 +665,12 @@ if __name__ == '__main__': file_name = "gl_API.xml" try: - (args, trail) = getopt.getopt(sys.argv[1:], "f:m:", ["only-get", "only-set", "get-alias-set"]) + (args, trail) = getopt.getopt(sys.argv[1:], "f:m:h:", ["only-get", "only-set", "header-tag"]) except Exception,e: show_usage() mode = None + header_tag = None which_functions = PrintGlxSizeStubs_common.do_get | PrintGlxSizeStubs_common.do_set for (arg,val) in args: @@ -231,22 +682,23 @@ if __name__ == '__main__': which_functions = PrintGlxSizeStubs_common.do_get elif arg == "--only-set": which_functions = PrintGlxSizeStubs_common.do_set - elif arg == "--get-alias-set": - which_functions |= PrintGlxSizeStubs_common.do_get_alias_set + elif (arg == '-h') or (arg == "--header-tag"): + header_tag = val if mode == "size_c": - dh = PrintGlxSizeStubs_c( which_functions ) + printer = PrintGlxSizeStubs_c( which_functions ) elif mode == "size_h": - dh = PrintGlxSizeStubs_h( which_functions ) + printer = PrintGlxSizeStubs_h( which_functions ) + if header_tag: + printer.header_tag = header_tag + elif mode == "reqsize_c": + printer = PrintGlxReqSize_c() + elif mode == "reqsize_h": + printer = PrintGlxReqSize_h() else: show_usage() - parser = make_parser() - parser.setFeature(feature_namespaces, 0) - parser.setContentHandler(dh) + api = gl_XML.parse_GL_API( file_name, glX_XML.glx_item_factory() ) - f = open(file_name) - dh.printHeader() - parser.parse(f) - dh.printFooter() + printer.Print( api )