R1/2/3/4/5xx: fixed calculation of cliprects in CopyBuffer.
[mesa.git] / src / mesa / glapi / gl_XML.py
index e4de4cacdd681aa1b6fcd06f33a23d1d61ef9d12..b7a7388400dd261b303d3239998362ecdf134558 100644 (file)
@@ -40,6 +40,16 @@ def parse_GL_API( file_name, factory = None ):
        api = factory.create_item( "api", None, None )
        api.process_element( doc )
 
+       # After the XML has been processed, we need to go back and assign
+       # dispatch offsets to the functions that request that their offsets
+       # be assigned by the scripts.  Typically this means all functions
+       # that are not part of the ABI.
+
+       for func in api.functionIterateByCategory():
+               if func.assign_offset:
+                       func.offset = api.next_offset;
+                       api.next_offset += 1
+
        doc.freeDoc()
 
        return api
@@ -194,7 +204,7 @@ class gl_print_base:
                """
 
                self.undef_list.append("FASTCALL")
-               print """#  if defined(__i386__) && defined(__GNUC__)
+               print """#  if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
 #    define FASTCALL __attribute__((fastcall))
 #  else
 #    define FASTCALL
@@ -214,7 +224,7 @@ class gl_print_base:
                """
 
                self.undef_list.append(S)
-               print """#  if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+               print """#  if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
 #    define %s  __attribute__((visibility("%s")))
 #  else
 #    define %s
@@ -242,23 +252,6 @@ class gl_print_base:
                return
 
 
-       def printHaveAlias(self):
-               """Conditionally define `HAVE_ALIAS'.
-
-               Conditionally defines a preprocessor macro `HAVE_ALIAS'.  The
-               existance of this macro can be used to determine whether or
-               not GCC's alias function attribute can be used.
-
-               The name is also added to the file's undef_list.
-               """
-
-               self.undef_list.append("HAVE_ALIAS")
-               print """#  if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
-#    define HAVE_ALIAS
-#  endif"""
-               return
-
-
 def real_function_name(element):
        name = element.nsProp( "name", None )
        alias = element.nsProp( "alias", None )
@@ -269,18 +262,68 @@ def real_function_name(element):
                return name
 
 
-class gl_item:
-       def __init__(self, element, context):
-               self.context = context
+def real_category_name(c):
+       if re.compile("[1-9][0-9]*[.][0-9]+").match(c):
+               return "GL_VERSION_" + c.replace(".", "_")
+       else:
+               return c
 
-               self.name = element.nsProp( "name", None )
 
-               c = element.parent.nsProp( "name", None )
-               if re.compile("[1-9][0-9]*[.][0-9]+").match(c):
-                       self.category = "GL_VERSION_" + c.replace(".", "_")
+def classify_category(name, number):
+       """Based on the category name and number, select a numerical class for it.
+       
+       Categories are divided into four classes numbered 0 through 3.  The
+       classes are:
+
+               0. Core GL versions, sorted by version number.
+               1. ARB extensions, sorted by extension number.
+               2. Non-ARB extensions, sorted by extension number.
+               3. Un-numbered extensions, sorted by extension name.
+       """
+
+       try:
+               core_version = float(name)
+       except Exception,e:
+               core_version = 0.0
+
+       if core_version > 0.0:
+               cat_type = 0
+               key = name
+       elif name.startswith("GL_ARB_") or name.startswith("GLX_ARB_") or name.startswith("WGL_ARB_"):
+               cat_type = 1
+               key = int(number)
+       else:
+               if number != None:
+                       cat_type = 2
+                       key = int(number)
                else:
-                       self.category = c
+                       cat_type = 3
+                       key = name
 
+
+       return [cat_type, key]
+
+
+def create_parameter_string(parameters, include_names):
+       """Create a parameter string from a list of gl_parameters."""
+
+       list = []
+       for p in parameters:
+               if include_names:
+                       list.append( p.string() )
+               else:
+                       list.append( p.type_string() )
+
+       if len(list) == 0: list = ["void"]
+
+       return string.join(list, ", ")
+
+
+class gl_item:
+       def __init__(self, element, context):
+               self.context = context
+               self.name = element.nsProp( "name", None )
+               self.category = real_category_name( element.parent.nsProp( "name", None ) )
                return
 
 
@@ -395,8 +438,9 @@ class gl_parameter:
                #if ts == "GLdouble":
                #       print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
 
-               self.is_counter = is_attr_true( element, 'counter' )
-               self.is_output  = is_attr_true( element, 'output' )
+               self.is_client_only = is_attr_true( element, 'client_only' )
+               self.is_counter     = is_attr_true( element, 'counter' )
+               self.is_output      = is_attr_true( element, 'output' )
 
 
                # Pixel data has special parameters.
@@ -554,9 +598,24 @@ class gl_function( gl_item ):
                self.return_type = "void"
                self.parameters = []
                self.offset = -1
-               self.uninitialized = 1
+               self.initialized = 0
                self.images = []
 
+               self.assign_offset = 0
+
+               self.static_entry_points = []
+
+               # Track the parameter string (for the function prototype)
+               # for each entry-point.  This is done because some functions
+               # change their prototype slightly when promoted from extension
+               # to ARB extension to core.  glTexImage3DEXT and glTexImage3D
+               # are good examples of this.  Scripts that need to generate
+               # code for these differing aliases need to real prototype
+               # for each entry-point.  Otherwise, they may generate code
+               # that won't compile.
+
+               self.parameter_strings = {}
+
                self.process_element( element )
 
                return
@@ -566,6 +625,9 @@ class gl_function( gl_item ):
                name = element.nsProp( "name", None )
                alias = element.nsProp( "alias", None )
 
+               if is_attr_true(element, "static_dispatch"):
+                       self.static_entry_points.append(name)
+
                self.entry_points.append( name )
                if alias:
                        true_name = alias
@@ -582,6 +644,8 @@ class gl_function( gl_item ):
                                        self.offset = o
                                except Exception, e:
                                        self.offset = -1
+                                       if offset == "assign":
+                                               self.assign_offset = 1
 
 
                if not self.name:
@@ -591,36 +655,29 @@ class gl_function( gl_item ):
 
 
                # There are two possible cases.  The first time an entry-point
-               # with data is seen, self.uninitialzied will be 1.  On that
+               # with data is seen, self.initialized will be 0.  On that
                # pass, we just fill in the data.  The next time an
-               # entry-point with data is seen, self.uninitialized will be 0.
+               # entry-point with data is seen, self.initialized will be 1.
                # On that pass we have to make that the new values match the
                # valuse from the previous entry-point.
 
+               parameters = []
+               return_type = "void"
                child = element.children
-               if self.uninitialized:
-                       while child:
-                               if child.type == "element":
-                                       if child.name == "return":
-                                               self.return_type = child.nsProp( "type", None )
-                                       elif child.name == "param":
-                                               param = self.context.factory.create_item( "parameter", child, self.context)
-                                               self.parameters.append( param )
-
-                               child = child.next
-               else:
-                       parameters = []
-                       while child:
-                               if child.type == "element":
-                                       if child.name == "return":
-                                               return_type = child.nsProp( "type", None )
-                                               if self.return_type != return_type:
-                                                       raise RuntimeError( "Return type changed in %s.  Was %s, now %s." % (name, self.return_type, return_type))
-                                       elif child.name == "param":
-                                               param = self.context.factory.create_item( "parameter", child, self.context)
-                                               parameters.append( param )
-
-                               child = child.next
+               while child:
+                       if child.type == "element":
+                               if child.name == "return":
+                                       return_type = child.nsProp( "type", None )
+                               elif child.name == "param":
+                                       param = self.context.factory.create_item( "parameter", child, self.context)
+                                       parameters.append( param )
+
+                       child = child.next
+
+
+               if self.initialized:
+                       if self.return_type != return_type:
+                               raise RuntimeError( "Return type changed in %s.  Was %s, now %s." % (name, self.return_type, return_type))
 
                        if len(parameters) != len(self.parameters):
                                raise RuntimeError( "Parameter count mismatch in %s.  Was %d, now %d." % (name, len(self.parameters), len(parameters)))
@@ -632,26 +689,19 @@ class gl_function( gl_item ):
                                        raise RuntimeError( 'Parameter type mismatch in %s.  "%s" was "%s", now "%s".' % (name, p2.name, p2.type_expr.original_string, p1.type_expr.original_string))
 
 
-                       # This is done becuase we may hit an alias before we
-                       # hit the "real" entry.  The aliases may not have all
-                       # of the parameter information (e.g., counter,
-                       # variable_param, etc. fields) required to generate
-                       # GLX code.
-
-                       if true_name == name:
-                               self.parameters = parameters
+               if true_name == name or not self.initialized:
+                       self.return_type = return_type
+                       self.parameters = parameters
 
-                               for param in self.parameters:
-                                       if param.is_image():
-                                               self.images.append( param )
-
-               if true_name == name:
                        for param in self.parameters:
                                if param.is_image():
                                        self.images.append( param )
 
                if element.children:
-                       self.uninitialized = 0
+                       self.initialized = 1
+                       self.parameter_strings[name] = create_parameter_string(parameters, 1)
+               else:
+                       self.parameter_strings[name] = None
 
                return
 
@@ -665,15 +715,39 @@ class gl_function( gl_item ):
                return self.parameters.__iter__();
 
 
-       def get_parameter_string(self):
-               list = []
-               for p in self.parameters:
-                       list.append( p.string() )
+       def get_parameter_string(self, entrypoint = None):
+               if entrypoint:
+                       s = self.parameter_strings[ entrypoint ]
+                       if s:
+                               return s
+               
+               return create_parameter_string( self.parameters, 1 )
 
-               if len(list) == 0:
-                       return "void"
+       def get_called_parameter_string(self):
+               p_string = ""
+               comma = ""
+
+               for p in self.parameterIterator():
+                       p_string = p_string + comma + p.name
+                       comma = ", "
+
+               return p_string
+
+
+       def is_static_entry_point(self, name):
+               return name in self.static_entry_points
+
+       def dispatch_name(self):
+               if self.name in self.static_entry_points:
+                       return self.name
                else:
-                       return string.join(list, ", ")
+                       return "_dispatch_stub_%u" % (self.offset)
+
+       def static_name(self, name):
+               if name in self.static_entry_points:
+                       return name
+               else:
+                       return "_dispatch_stub_%u" % (self.offset)
 
 
 class gl_item_factory:
@@ -699,10 +773,14 @@ class gl_api:
                self.functions_by_name = {}
                self.enums_by_name = {}
                self.types_by_name = {}
+
                self.category_dict = {}
+               self.categories = [{}, {}, {}, {}]
 
                self.factory = factory
 
+               self.next_offset = 0
+
                typeexpr.create_initial_types()
                return
 
@@ -735,12 +813,18 @@ class gl_api:
                cat_name = cat.nsProp( "name", None )
                cat_number = cat.nsProp( "number", None )
 
+               [cat_type, key] = classify_category(cat_name, cat_number)
+               self.categories[cat_type][key] = [cat_name, cat_number]
+
                child = cat.children
                while child:
                        if child.type == "element":
                                if child.name == "function":
                                        func_name = real_function_name( child )
 
+                                       temp_name = child.nsProp( "name", None )
+                                       self.category_dict[ temp_name ] = [cat_name, cat_number]
+
                                        if self.functions_by_name.has_key( func_name ):
                                                func = self.functions_by_name[ func_name ]
                                                func.process_element( child )
@@ -748,8 +832,9 @@ class gl_api:
                                                func = self.factory.create_item( "function", child, self )
                                                self.functions_by_name[ func_name ] = func
 
-                                       if func_name == child.nsProp("name", None):
-                                               self.category_dict[ func.name ] = [cat_name, cat_number]
+                                       if func.offset >= self.next_offset:
+                                               self.next_offset = func.offset + 1
+
 
                                elif child.name == "enum":
                                        enum = self.factory.create_item( "enum", child, self )
@@ -764,6 +849,43 @@ class gl_api:
                return
 
 
+       def functionIterateByCategory(self, cat = None):
+               """Iterate over functions by category.
+               
+               If cat is None, all known functions are iterated in category
+               order.  See classify_category for details of the ordering.
+               Within a category, functions are sorted by name.  If cat is
+               not None, then only functions in that category are iterated.
+               """
+               lists = [{}, {}, {}, {}]
+
+               for func in self.functionIterateAll():
+                       [cat_name, cat_number] = self.category_dict[func.name]
+
+                       if (cat == None) or (cat == cat_name):
+                               [func_cat_type, key] = classify_category(cat_name, cat_number)
+
+                               if not lists[func_cat_type].has_key(key):
+                                       lists[func_cat_type][key] = {}
+
+                               lists[func_cat_type][key][func.name] = func
+
+
+               functions = []
+               for func_cat_type in range(0,4):
+                       keys = lists[func_cat_type].keys()
+                       keys.sort()
+
+                       for key in keys:
+                               names = lists[func_cat_type][key].keys()
+                               names.sort()
+
+                               for name in names:
+                                       functions.append(lists[func_cat_type][key][name])
+
+               return functions.__iter__()
+
+
        def functionIterateByOffset(self):
                max_offset = -1
                for func in self.functions_by_name.itervalues():
@@ -800,6 +922,25 @@ class gl_api:
                return list.__iter__()
 
 
+       def categoryIterate(self):
+               """Iterate over categories.
+               
+               Iterate over all known categories in the order specified by
+               classify_category.  Each iterated value is a tuple of the
+               name and number (which may be None) of the category.
+               """
+
+               list = []
+               for cat_type in range(0,4):
+                       keys = self.categories[cat_type].keys()
+                       keys.sort()
+                       
+                       for key in keys:
+                               list.append(self.categories[cat_type][key])
+                               
+               return list.__iter__()
+
+
        def get_category_for_name( self, name ):
                if self.category_dict.has_key(name):
                        return self.category_dict[name]