Add GlxProto::createEnumFunction and add a 'context' parameter to the
authorIan Romanick <idr@us.ibm.com>
Tue, 1 Feb 2005 00:13:04 +0000 (00:13 +0000)
committerIan Romanick <idr@us.ibm.com>
Tue, 1 Feb 2005 00:13:04 +0000 (00:13 +0000)
glXEnumFunction constructor.  The allows sub-classes of GlxProto to
over-ride the concrete class used for glXEnumFunction.

In addition to tracking p_count_parameters in glParameter, break the comma
separated list of parameter names into a Python list called
count_parameter_list.  It is now possible to query if a name is the name of
one of the count parameters just by comparing
param.count_parameter_list.count(n) to zero.  Eventually the remaining uses
of p_count_parameters will be replaced with uses of count_parameter_list.

Make sure that 'void *' parameters are handled correctly in
glParameter::size_string.

Add PrintGlxReqSize_h and PrintGlxReqSize_c.  These classes emit prototypes
and functions used on the server-side to determine the expected size of an
incoming GL command.

src/mesa/glapi/glX_XML.py
src/mesa/glapi/glX_proto_size.py
src/mesa/glapi/gl_XML.py

index 1db12f5c940dfb24baf4e34d2581863f85bfc718..56a2113f0507a446b770a568d1ae5d75a0232aab 100644 (file)
@@ -81,8 +81,9 @@ class glXItemFactory(gl_XML.glItemFactory):
                        return gl_XML.glItemFactory.create(self, context, name, attrs)
 
 class glXEnumFunction:
-       def __init__(self, name):
+       def __init__(self, name, context):
                self.name = name
+               self.context = context
                self.mode = 0
                self.sig = None
 
@@ -261,7 +262,7 @@ class glXEnum(gl_XML.glEnum):
                        [n, c, mode] = self.process_attributes(attrs)
 
                        if not self.context.glx_enum_functions.has_key( n ):
-                               f = glXEnumFunction( n )
+                               f = self.context.createEnumFunction( n )
                                f.set_mode( mode )
                                self.context.glx_enum_functions[ f.name ] = f
 
@@ -692,3 +693,7 @@ class GlxProto(gl_XML.FilterGLAPISpecBase):
                else:
                        gl_XML.FilterGLAPISpecBase.endElement(self, name)
                return
+
+
+       def createEnumFunction(self, n):
+               return glXEnumFunction(n, self)
index cf0885a5a6f40827cab581b5f6bfc4edd7145d32..e8a137c5e120a8ef1fec90261538e4d813245c9b 100644 (file)
@@ -94,6 +94,52 @@ class SizeStubFunctionIterator:
                return f
 
 
+class glXServerEnumFunction(glX_XML.glXEnumFunction):
+       def signature( self ):
+               if self.sig == None:
+                       sig = glX_XML.glXEnumFunction.signature(self)
+
+                       f = self.context.find_function( self.name )
+                       p = f.variable_length_parameter()
+
+                       try:
+                               sig += "%u" % (p.p_type.size)
+                       except Exception,e:
+                               print '%s' % (self.name)
+                               raise e
+
+                       self.sig = sig
+
+               return self.sig;
+
+
+       def Print(self, name):
+               f = self.context.find_function( self.name )
+               self.context.common_func_print_just_header( f )
+
+               fixup = []
+               o = 0
+               for p in f.parameterIterator(1, 1):
+                       if f.count_parameter_list.count(p.name) or p.name == f.counter:
+                               self.context.common_emit_one_arg(p, o, "pc", "    ", 0)
+                               fixup.append(p.name)
+
+                       o += p.size()
+
+               print '    GLsizei compsize;'
+               print ''
+
+               self.context.common_emit_fixups(fixup)
+
+               print ''
+               print '    compsize = __gl%s_size(%s);' % (self.name, f.count_parameters)
+               p = f.variable_length_parameter()
+               print '    return __GLX_PAD(%s);' % (p.size_string())
+
+               print '}'
+               print ''
+
+
 class PrintGlxSizeStubs_common(glX_XML.GlxProto):
        do_get = (1 << 0)
        do_set = (1 << 1)
@@ -193,6 +239,238 @@ class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common):
                print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (f.name)
 
 
+class PrintGlxReqSize_h(glX_XML.GlxProto):
+       def __init__(self):
+               glX_XML.GlxProto.__init__(self)
+               self.name = "glX_proto_size.py (from Mesa)"
+               self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
+               self.aliases = []
+               self.glx_enum_sigs = {}
+               self.header_tag = "_INDIRECT_REQSIZE_H_"
+
+
+       def printRealHeader(self):
+               glX_XML.printVisibility("HIDDEN", "hidden")
+               print ''
+               glX_XML.printPure()
+               print ''
+
+
+       def printRealFooter(self):
+               print ''
+               print '#  undef HIDDEN'
+               print '#  undef PURE'
+
+
+       def printFunction(self, f):
+               if f.glx_rop == 0 or f.ignore: return
+
+               has_counter = 0
+               for p in f.parameterIterator(1,2):
+                       if p.is_counter:
+                               has_counter = 1
+                               break
+
+               if self.glx_enum_functions.has_key(f.name) or f.image or has_counter:
+                       print 'extern PURE HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap);' % (f.name)
+
+
+class PrintGlxReqSize_c(glX_XML.GlxProto):
+       def __init__(self):
+               glX_XML.GlxProto.__init__(self)
+               self.name = "glX_proto_size.py (from Mesa)"
+               self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
+               self.aliases = []
+               self.glx_enum_sigs = {}
+               self.counter_sigs = {}
+
+
+       def createEnumFunction(self, n):
+               return glXServerEnumFunction(n, self)
+
+
+       def printRealHeader(self):
+               print ''
+               print '#include <GL/gl.h>'
+               print '#include <byteswap.h>'
+               print '#include "glxserver.h"'
+               print '#include "indirect_size.h"'
+               print '#include "indirect_reqsize.h"'
+               
+               print ''
+               print '#define __GLX_PAD(x)  (((x) + 3) & ~3)'
+               print ''
+               glX_XML.printHaveAlias()
+               print ''
+               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 ''
+               print ''
+
+
+       def printRealFooter(self):
+               for a in self.aliases:
+                       print a
+
+
+       def printFunction(self, f):
+               if f.glx_rop == 0 or f.server_handcode or f.ignore: return
+
+               if self.glx_enum_functions.has_key(f.name):
+                       ef = self.glx_enum_functions[f.name]
+
+                       sig = ef.signature();
+                       if self.glx_enum_sigs.has_key(sig):
+                               n = self.glx_enum_sigs[sig];
+                               a = 'ALIAS( %s, %s )' % (f.name, n)
+                               self.aliases.append(a)
+                       else:
+                               ef.Print( f.name )
+                               self.glx_enum_sigs[sig] = f.name;
+               elif f.image:
+                       self.printPixelFunction(f)
+               else:
+                       for p in f.parameterIterator(1,2):
+                               if p.counter and not p.is_output:
+                                       self.printCountedFunction(f)
+                                       break
+
+
+       def common_emit_fixups(self, fixup):
+               """Utility function to emit conditional byte-swaps."""
+
+               if fixup:
+                       print '    if (swap) {'
+                       for name in fixup:
+                               print '        %-14s = bswap_32( %s );' % (name, name)
+                       print '    }'
+
+               return
+
+
+       def common_emit_one_arg(self, p, offset, pc, indent, adjust):
+               dst = '%s %s' % (p.p_type_string, p.name)
+               src = '(%s *)' % (p.p_type_string)
+               print '%s%-18s = *%11s(%s + %u);' % (indent, 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)
+               
+               [dim, w, h, d, junk] = f.dimensions()
+
+               offset = f.offset_of_first_parameter()
+
+               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);'
+
+               for p in f.parameterIterator(1, 2):
+                       if p.name in [w, h, d, f.image.img_format, f.image.img_type, f.image.img_target]:
+                               self.common_emit_one_arg(p, offset, "pc", "    ", 0 )
+                               fixup.append( p.name )
+
+                       offset += p.size()
+
+               print ''
+
+               self.common_emit_fixups(fixup)
+
+               print ''
+               print '    return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (f.image.img_format, f.image.img_type, f.image.img_target, w, h, d )
+               print '                          image_height, row_length, skip_images,'
+               print '                          skip_rows, alignment);'
+               print '}'
+               print ''
+               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.parameterIterator(1,2):
+                       if p.is_counter:
+                               param_offsets[ p.name ] = offset
+                               fixup.append( p.name )
+                               params.append( [p, offset] )
+                       elif p.counter:
+                               s = p.p_type.size
+                               if s == 0: s = 1
+
+                               sig += "(%u,%u)" % (param_offsets[p.counter], s)
+                               size += '%s%s' % (plus, p.size_string())
+                               plus = ' + '
+
+
+                       offset += p.size()
+
+
+               # If the calculate 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];
+                       a = 'ALIAS( %s, %s )' % (f.name, n)
+                       self.aliases.append(a)
+               else:
+                       self.counter_sigs[sig] = f.name
+
+                       self.common_func_print_just_header(f)
+
+                       for [p, offset] in params:
+                               self.common_emit_one_arg(p, offset, "pc", "    ", 0 )
+
+
+                       print ''
+                       self.common_emit_fixups(fixup)
+                       print ''
+
+                       print '    return __GLX_PAD(%s);' % (size)
+                       print '}'
+                       print ''
+
+               return
+
+
 def show_usage():
        print "Usage: %s [-f input_file_name] -m output_mode [--only-get | --only-set] [--get-alias-set]" % sys.argv[0]
        print "    -m output_mode   Output mode can be one of 'size_c' or 'size_h'."
@@ -237,6 +515,10 @@ if __name__ == '__main__':
                dh = PrintGlxSizeStubs_h( which_functions )
                if header_tag:
                        dh.header_tag = header_tag
+       elif mode == "reqsize_c":
+               dh = PrintGlxReqSize_c()
+       elif mode == "reqsize_h":
+               dh = PrintGlxReqSize_h()
        else:
                show_usage()
 
index 21f6dc0e62d9a1c3f57c98bb21e8ba99b25effed..086133cdf1e1c07d4ab4e7b6d2129d197722445f 100644 (file)
@@ -153,6 +153,12 @@ class glParameter( glItem ):
                self.p_type_string = attrs.get('type', None)
                self.p_count_parameters = attrs.get('variable_param', None)
 
+               if self.p_count_parameters:
+                       temp = self.p_count_parameters.replace( ' ', '' )
+                       self.count_parameter_list = temp.split( ',' )
+               else:
+                       self.count_parameter_list = []
+
                self.p_type = context.context.find_type(self.p_type_string)
                if self.p_type == None:
                        raise RuntimeError("Unknown type '%s' in function '%s'." % (self.p_type_string, context.name))
@@ -300,6 +306,11 @@ class glParameter( glItem ):
                        a_prod = "compsize"
                        b_prod = self.p_type.size
 
+                       # Handle functions like glCompressedTexImage2D that
+                       # have a counted 'void *' parameter.
+
+                       if b_prod == 0: b_prod = 1
+
                        if self.p_count_parameters == None and self.counter != None:
                                a_prod = self.counter
                        elif self.p_count_parameters != None and self.counter == None:
@@ -349,6 +360,7 @@ class glFunction( glItem ):
                self.fn_alias = attrs.get('alias', None)
                self.fn_parameters = []
                self.image = None
+               self.count_parameter_list = []
 
                temp = attrs.get('offset', None)
                if temp == None or temp == "?":
@@ -390,6 +402,8 @@ class glFunction( glItem ):
                        self.image = p
 
                self.fn_parameters.append(p)
+               if p.count_parameter_list != []:
+                       self.count_parameter_list.extend( p.count_parameter_list )
 
 
        def set_return_type(self, t):