glapi: add gl_dispatch_functions_start and end
[mesa.git] / src / mesa / glapi / gl_XML.py
index 808a0a474e74f6b11eae8a1fb2ee621ca3f78c88..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
@@ -214,7 +224,7 @@ class gl_print_base:
                """
 
                self.undef_list.append(S)
-               print """#  if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && !defined(__CYGWIN__) && !defined(__MINGW32__)
+               print """#  if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__)
 #    define %s  __attribute__((visibility("%s")))
 #  else
 #    define %s
@@ -259,6 +269,41 @@ def real_category_name(c):
                return c
 
 
+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:
+                       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."""
 
@@ -393,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.
@@ -555,6 +601,10 @@ class gl_function( gl_item ):
                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
@@ -575,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
@@ -591,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:
@@ -668,6 +723,32 @@ class gl_function( gl_item ):
                
                return create_parameter_string( self.parameters, 1 )
 
+       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 "_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:
        """Factory to create objects derived from gl_item."""
@@ -692,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
 
@@ -728,6 +813,9 @@ 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":
@@ -744,6 +832,9 @@ class gl_api:
                                                func = self.factory.create_item( "function", child, self )
                                                self.functions_by_name[ func_name ] = func
 
+                                       if func.offset >= self.next_offset:
+                                               self.next_offset = func.offset + 1
+
 
                                elif child.name == "enum":
                                        enum = self.factory.create_item( "enum", child, self )
@@ -758,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():
@@ -794,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]