Home | History | Annotate | Download | only in main
      1 #*************************************************************************
      2 # Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
      3 # All Rights Reserved.
      4 #
      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 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9 # and/or sell copies of the Software, and to permit persons to whom the
     10 # Software is furnished to do so, subject to the following conditions:
     11 #
     12 # The above copyright notice and this permission notice shall be included
     13 # in all copies or substantial portions of the Software.
     14 #
     15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 # TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
     20 # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21 # SOFTWARE.
     22 #*************************************************************************
     23 
     24 
     25 import sys, os
     26 import APIspecutil as apiutil
     27 
     28 # These dictionary entries are used for automatic conversion.
     29 # The string will be used as a format string with the conversion
     30 # variable.
     31 Converters = {
     32     'GLfloat': {
     33         'GLdouble': "(GLdouble) (%s)",
     34         'GLfixed' : "(GLint) (%s * 65536)",
     35     },
     36     'GLfixed': {
     37         'GLfloat': "(GLfloat) (%s / 65536.0f)",
     38         'GLdouble': "(GLdouble) (%s / 65536.0)",
     39     },
     40     'GLdouble': {
     41         'GLfloat': "(GLfloat) (%s)",
     42         'GLfixed': "(GLfixed) (%s * 65536)",
     43     },
     44     'GLclampf': {
     45         'GLclampd': "(GLclampd) (%s)",
     46         'GLclampx': "(GLclampx) (%s * 65536)",
     47     },
     48     'GLclampx': {
     49         'GLclampf': "(GLclampf) (%s / 65536.0f)",
     50         'GLclampd': "(GLclampd) (%s / 65536.0)",
     51     },
     52     'GLubyte': {
     53         'GLfloat': "(GLfloat) (%s / 255.0f)",
     54     },
     55 }
     56 
     57 def GetBaseType(type):
     58     typeTokens = type.split(' ')
     59     baseType = None
     60     typeModifiers = []
     61     for t in typeTokens:
     62         if t in ['const', '*']:
     63             typeModifiers.append(t)
     64         else:
     65             baseType = t
     66     return (baseType, typeModifiers)
     67 
     68 def ConvertValue(value, fromType, toType):
     69     """Returns a string that represents the given parameter string, 
     70     type-converted if necessary."""
     71 
     72     if not Converters.has_key(fromType):
     73         print >> sys.stderr, "No base converter for type '%s' found.  Ignoring." % fromType
     74         return value
     75 
     76     if not Converters[fromType].has_key(toType):
     77         print >> sys.stderr, "No converter found for type '%s' to type '%s'.  Ignoring." % (fromType, toType)
     78         return value
     79 
     80     # This part is simple.  Return the proper conversion.
     81     conversionString = Converters[fromType][toType]
     82     return conversionString % value
     83 
     84 FormatStrings = {
     85     'GLenum' : '0x%x',
     86     'GLfloat' : '%f',
     87     'GLint' : '%d',
     88     'GLbitfield' : '0x%x',
     89 }
     90 def GetFormatString(type):
     91     if FormatStrings.has_key(type):
     92         return FormatStrings[type]
     93     else:
     94         return None
     95 
     96 
     97 ######################################################################
     98 # Version-specific values to be used in the main script
     99 # header: which header file to include
    100 # api: what text specifies an API-level function
    101 VersionSpecificValues = {
    102     'GLES1.1' : {
    103         'description' : 'GLES1.1 functions',
    104         'header' : 'GLES/gl.h',
    105         'extheader' : 'GLES/glext.h',
    106         'shortname' : 'es1'
    107     },
    108     'GLES2.0': {
    109         'description' : 'GLES2.0 functions',
    110         'header' : 'GLES2/gl2.h',
    111         'extheader' : 'GLES2/gl2ext.h',
    112         'shortname' : 'es2'
    113     }
    114 }
    115 
    116 
    117 ######################################################################
    118 # Main code for the script begins here.
    119 
    120 # Get the name of the program (without the directory part) for use in
    121 # error messages.
    122 program = os.path.basename(sys.argv[0])
    123 
    124 # Set default values
    125 verbose = 0
    126 functionList = "APIspec.xml"
    127 version = "GLES1.1"
    128 
    129 # Allow for command-line switches
    130 import getopt, time
    131 options = "hvV:S:"
    132 try:
    133     optlist, args = getopt.getopt(sys.argv[1:], options)
    134 except getopt.GetoptError, message:
    135     sys.stderr.write("%s: %s.  Use -h for help.\n" % (program, message))
    136     sys.exit(1)
    137 
    138 for option, optarg in optlist:
    139     if option == "-h":
    140         sys.stderr.write("Usage: %s [-%s]\n" % (program, options))
    141         sys.stderr.write("Parse an API specification file and generate wrapper functions for a given GLES version\n")
    142         sys.stderr.write("-h gives help\n")
    143         sys.stderr.write("-v is verbose\n")
    144         sys.stderr.write("-V specifies GLES version to generate [%s]:\n" % version)
    145         for key in VersionSpecificValues.keys():
    146             sys.stderr.write("    %s - %s\n" % (key, VersionSpecificValues[key]['description']))
    147         sys.stderr.write("-S specifies API specification file to use [%s]\n" % functionList)
    148         sys.exit(1)
    149     elif option == "-v":
    150         verbose += 1
    151     elif option == "-V":
    152         version = optarg
    153     elif option == "-S":
    154         functionList = optarg
    155 
    156 # Beyond switches, we support no further command-line arguments
    157 if len(args) >  0:
    158     sys.stderr.write("%s: only switch arguments are supported - use -h for help\n" % program)
    159     sys.exit(1)
    160 
    161 # If we don't have a valid version, abort.
    162 if not VersionSpecificValues.has_key(version):
    163     sys.stderr.write("%s: version '%s' is not valid - use -h for help\n" % (program, version))
    164     sys.exit(1)
    165 
    166 # Grab the version-specific items we need to use
    167 versionHeader = VersionSpecificValues[version]['header']
    168 versionExtHeader = VersionSpecificValues[version]['extheader']
    169 shortname = VersionSpecificValues[version]['shortname']
    170 
    171 # If we get to here, we're good to go.  The "version" parameter
    172 # directs GetDispatchedFunctions to only allow functions from
    173 # that "category" (version in our parlance).  This allows 
    174 # functions with different declarations in different categories
    175 # to exist (glTexImage2D, for example, is different between
    176 # GLES1 and GLES2).
    177 keys = apiutil.GetAllFunctions(functionList, version)
    178 
    179 allSpecials = apiutil.AllSpecials()
    180 
    181 print """/* DO NOT EDIT *************************************************
    182  * THIS FILE AUTOMATICALLY GENERATED BY THE %s SCRIPT
    183  * API specification file:   %s
    184  * GLES version:             %s
    185  * date:                     %s
    186  */
    187 """ % (program, functionList, version, time.strftime("%Y-%m-%d %H:%M:%S"))
    188 
    189 # The headers we choose are version-specific.
    190 print """
    191 #include "%s"
    192 #include "%s"
    193 #include "main/mfeatures.h"
    194 #include "main/compiler.h"
    195 #include "main/api_exec.h"
    196 
    197 #if FEATURE_%s
    198 
    199 #ifndef GLAPIENTRYP
    200 #define GLAPIENTRYP GL_APIENTRYP
    201 #endif
    202 """ % (versionHeader, versionExtHeader, shortname.upper())
    203 
    204 if version == "GLES1.1":
    205     print '#include "main/es1_conversion.h"'
    206     print
    207 
    208 # Everyone needs these types.
    209 print """
    210 /* These types are needed for the Mesa veneer, but are not defined in
    211  * the standard GLES headers.
    212  */
    213 typedef double GLdouble;
    214 typedef double GLclampd;
    215 
    216 /* Mesa error handling requires these */
    217 extern void *_mesa_get_current_context(void);
    218 extern void _mesa_error(void *ctx, GLenum error, const char *fmtString, ... );
    219 """
    220 
    221 # Finally we get to the all-important functions
    222 print """/*************************************************************
    223  * Generated functions begin here
    224  */
    225 """
    226 for funcName in keys:
    227     if verbose > 0: sys.stderr.write("%s: processing function %s\n" % (program, funcName))
    228 
    229     # start figuring out what this function will look like.
    230     returnType = apiutil.ReturnType(funcName)
    231     props = apiutil.Properties(funcName)
    232     params = apiutil.Parameters(funcName)
    233     declarationString = apiutil.MakeDeclarationString(params)
    234 
    235     # In case of error, a function may have to return.  Make
    236     # sure we have valid return values in this case.
    237     if returnType == "void":
    238         errorReturn = "return"
    239     elif returnType == "GLboolean":
    240         errorReturn = "return GL_FALSE"
    241     else:
    242         errorReturn = "return (%s) 0" % returnType
    243 
    244     # These are the output of this large calculation block.
    245     # passthroughDeclarationString: a typed set of parameters that
    246     # will be used to create the "extern" reference for the
    247     # underlying Mesa or support function.  Note that as generated
    248     # these have an extra ", " at the beginning, which will be
    249     # removed before use.
    250     # 
    251     # passthroughDeclarationString: an untyped list of parameters
    252     # that will be used to call the underlying Mesa or support
    253     # function (including references to converted parameters).
    254     # This will also be generated with an extra ", " at the
    255     # beginning, which will be removed before use.
    256     #
    257     # variables: C code to create any local variables determined to
    258     # be necessary.
    259     # conversionCodeOutgoing: C code to convert application parameters
    260     # to a necessary type before calling the underlying support code.
    261     # May be empty if no conversion is required.  
    262     # conversionCodeIncoming: C code to do the converse: convert 
    263     # values returned by underlying Mesa code to the types needed
    264     # by the application.
    265     # Note that *either* the conversionCodeIncoming will be used (for
    266     # generated query functions), *or* the conversionCodeOutgoing will
    267     # be used (for generated non-query functions), never both.
    268     passthroughFuncName = ""
    269     passthroughDeclarationString = ""
    270     passthroughCallString = ""
    271     prefixOverride = None
    272     variables = []
    273     conversionCodeOutgoing = []
    274     conversionCodeIncoming = []
    275     switchCode = []
    276 
    277     # Calculate the name of the underlying support function to call.
    278     # By default, the passthrough function is named _mesa_<funcName>.
    279     # We're allowed to override the prefix and/or the function name
    280     # for each function record, though.  The "ConversionFunction"
    281     # utility is poorly named, BTW...
    282     if funcName in allSpecials:
    283         # perform checks and pass through
    284         funcPrefix = "_check_"
    285         aliasprefix = "_es_"
    286     else:
    287         funcPrefix = "_es_"
    288         aliasprefix = apiutil.AliasPrefix(funcName)
    289     alias = apiutil.ConversionFunction(funcName)
    290     prefixOverride = apiutil.FunctionPrefix(funcName)
    291     if prefixOverride != "_mesa_":
    292         aliasprefix = apiutil.FunctionPrefix(funcName)
    293     if not alias:
    294         # There may still be a Mesa alias for the function
    295         if apiutil.Alias(funcName):
    296             passthroughFuncName = "%s%s" % (aliasprefix, apiutil.Alias(funcName))
    297         else:
    298             passthroughFuncName = "%s%s" % (aliasprefix, funcName)
    299     else: # a specific alias is provided
    300         passthroughFuncName = "%s%s" % (aliasprefix, alias)
    301 
    302     # Look at every parameter: each one may have only specific
    303     # allowed values, or dependent parameters to check, or 
    304     # variant-sized vector arrays to calculate
    305     for (paramName, paramType, paramMaxVecSize, paramConvertToType, paramValidValues, paramValueConversion) in params:
    306         # We'll need this below if we're doing conversions
    307         (paramBaseType, paramTypeModifiers) = GetBaseType(paramType)
    308 
    309         # Conversion management.
    310         # We'll handle three cases, easiest to hardest: a parameter
    311         # that doesn't require conversion, a scalar parameter that
    312         # requires conversion, and a vector parameter that requires
    313         # conversion.
    314         if paramConvertToType == None:
    315             # Unconverted parameters are easy, whether they're vector
    316             # or scalar - just add them to the call list.  No conversions
    317             # or anything to worry about.
    318             passthroughDeclarationString += ", %s %s" % (paramType, paramName)
    319             passthroughCallString += ", %s" % paramName
    320 
    321         elif paramMaxVecSize == 0: # a scalar parameter that needs conversion
    322             # A scalar to hold a converted parameter
    323             variables.append("    %s converted_%s;" % (paramConvertToType, paramName))
    324 
    325             # Outgoing conversion depends on whether we have to conditionally
    326             # perform value conversion.
    327             if paramValueConversion == "none":
    328                 conversionCodeOutgoing.append("    converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
    329             elif paramValueConversion == "some":
    330                 # We'll need a conditional variable to keep track of
    331                 # whether we're converting values or not.
    332                 if ("    int convert_%s_value = 1;" % paramName) not in variables:
    333                     variables.append("    int convert_%s_value = 1;" % paramName)
    334 
    335                 # Write code based on that conditional.
    336                 conversionCodeOutgoing.append("    if (convert_%s_value) {" % paramName)
    337                 conversionCodeOutgoing.append("        converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType))) 
    338                 conversionCodeOutgoing.append("    } else {")
    339                 conversionCodeOutgoing.append("        converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
    340                 conversionCodeOutgoing.append("    }")
    341             else: # paramValueConversion == "all"
    342                 conversionCodeOutgoing.append("    converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
    343 
    344             # Note that there can be no incoming conversion for a
    345             # scalar parameter; changing the scalar will only change
    346             # the local value, and won't ultimately change anything
    347             # that passes back to the application.
    348 
    349             # Call strings.  The unusual " ".join() call will join the
    350             # array of parameter modifiers with spaces as separators.
    351             passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
    352             passthroughCallString += ", converted_%s" % paramName
    353 
    354         else: # a vector parameter that needs conversion
    355             # We'll need an index variable for conversions
    356             if "    register unsigned int i;" not in variables:
    357                 variables.append("    register unsigned int i;")
    358 
    359             # This variable will hold the (possibly variant) size of
    360             # this array needing conversion.  By default, we'll set
    361             # it to the maximal size (which is correct for functions
    362             # with a constant-sized vector parameter); for true
    363             # variant arrays, we'll modify it with other code.
    364             variables.append("    unsigned int n_%s = %d;" % (paramName, paramMaxVecSize))
    365 
    366             # This array will hold the actual converted values.
    367             variables.append("    %s converted_%s[%d];" % (paramConvertToType, paramName, paramMaxVecSize))
    368 
    369             # Again, we choose the conversion code based on whether we
    370             # have to always convert values, never convert values, or 
    371             # conditionally convert values.
    372             if paramValueConversion == "none":
    373                 conversionCodeOutgoing.append("    for (i = 0; i < n_%s; i++) {" % paramName)
    374                 conversionCodeOutgoing.append("        converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
    375                 conversionCodeOutgoing.append("    }")
    376             elif paramValueConversion == "some":
    377                 # We'll need a conditional variable to keep track of
    378                 # whether we're converting values or not.
    379                 if ("    int convert_%s_value = 1;" % paramName) not in variables:
    380                     variables.append("    int convert_%s_value = 1;" % paramName)
    381                 # Write code based on that conditional.
    382                 conversionCodeOutgoing.append("    if (convert_%s_value) {" % paramName)
    383                 conversionCodeOutgoing.append("        for (i = 0; i < n_%s; i++) {" % paramName)
    384                 conversionCodeOutgoing.append("            converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType))) 
    385                 conversionCodeOutgoing.append("        }")
    386                 conversionCodeOutgoing.append("    } else {")
    387                 conversionCodeOutgoing.append("        for (i = 0; i < n_%s; i++) {" % paramName)
    388                 conversionCodeOutgoing.append("            converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
    389                 conversionCodeOutgoing.append("        }")
    390                 conversionCodeOutgoing.append("    }")
    391             else: # paramValueConversion == "all"
    392                 conversionCodeOutgoing.append("    for (i = 0; i < n_%s; i++) {" % paramName)
    393                 conversionCodeOutgoing.append("        converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
    394 
    395                 conversionCodeOutgoing.append("    }")
    396 
    397             # If instead we need an incoming conversion (i.e. results
    398             # from Mesa have to be converted before handing back
    399             # to the application), this is it.  Fortunately, we don't
    400             # have to worry about conditional value conversion - the
    401             # functions that do (e.g. glGetFixedv()) are handled
    402             # specially, outside this code generation.
    403             #
    404             # Whether we use incoming conversion or outgoing conversion
    405             # is determined later - we only ever use one or the other.
    406 
    407             if paramValueConversion == "none":
    408                 conversionCodeIncoming.append("    for (i = 0; i < n_%s; i++) {" % paramName)
    409                 conversionCodeIncoming.append("        %s[i] = (%s) converted_%s[i];" % (paramName, paramConvertToType, paramName))
    410                 conversionCodeIncoming.append("    }")
    411             elif paramValueConversion == "some":
    412                 # We'll need a conditional variable to keep track of
    413                 # whether we're converting values or not.
    414                 if ("    int convert_%s_value = 1;" % paramName) not in variables:
    415                     variables.append("    int convert_%s_value = 1;" % paramName)
    416 
    417                 # Write code based on that conditional.
    418                 conversionCodeIncoming.append("    if (convert_%s_value) {" % paramName)
    419                 conversionCodeIncoming.append("        for (i = 0; i < n_%s; i++) {" % paramName)
    420                 conversionCodeIncoming.append("            %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType))) 
    421                 conversionCodeIncoming.append("        }")
    422                 conversionCodeIncoming.append("    } else {")
    423                 conversionCodeIncoming.append("        for (i = 0; i < n_%s; i++) {" % paramName)
    424                 conversionCodeIncoming.append("            %s[i] = (%s) converted_%s[i];" % (paramName, paramBaseType, paramName))
    425                 conversionCodeIncoming.append("        }")
    426                 conversionCodeIncoming.append("    }")
    427             else: # paramValueConversion == "all"
    428                 conversionCodeIncoming.append("    for (i = 0; i < n_%s; i++) {" % paramName)
    429                 conversionCodeIncoming.append("        %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
    430                 conversionCodeIncoming.append("    }")
    431 
    432             # Call strings.  The unusual " ".join() call will join the
    433             # array of parameter modifiers with spaces as separators.
    434             passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
    435             passthroughCallString += ", converted_%s" % paramName
    436 
    437         # endif conversion management
    438 
    439         # Parameter checking.  If the parameter has a specific list of
    440         # valid values, we have to make sure that the passed-in values
    441         # match these, or we make an error.
    442         if len(paramValidValues) > 0:
    443             # We're about to make a big switch statement with an
    444             # error at the end.  By default, the error is GL_INVALID_ENUM,
    445             # unless we find a "case" statement in the middle with a
    446             # non-GLenum value.
    447             errorDefaultCase = "GL_INVALID_ENUM"
    448 
    449             # This parameter has specific valid values.  Make a big
    450             # switch statement to handle it.  Note that the original
    451             # parameters are always what is checked, not the
    452             # converted parameters.
    453             switchCode.append("    switch(%s) {" % paramName)
    454 
    455             for valueIndex in range(len(paramValidValues)):
    456                 (paramValue, dependentVecSize, dependentParamName, dependentValidValues, errorCode, valueConvert) = paramValidValues[valueIndex]
    457 
    458                 # We're going to need information on the dependent param
    459                 # as well.
    460                 if dependentParamName:
    461                     depParamIndex = apiutil.FindParamIndex(params, dependentParamName)
    462                     if depParamIndex == None:
    463                         sys.stderr.write("%s: can't find dependent param '%s' for function '%s'\n" % (program, dependentParamName, funcName))
    464 
    465                     (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = params[depParamIndex]
    466                 else:
    467                     (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = (None, None, None, None, [], None)
    468 
    469                 # This is a sneaky trick.  It's valid syntax for a parameter
    470                 # that is *not* going to be converted to be declared
    471                 # with a dependent vector size; but in this case, the
    472                 # dependent vector size is unused and unnecessary.
    473                 # So check for this and ignore the dependent vector size
    474                 # if the parameter is not going to be converted.
    475                 if depParamConvertToType:
    476                     usedDependentVecSize = dependentVecSize
    477                 else:
    478                     usedDependentVecSize = None
    479 
    480                 # We'll peek ahead at the next parameter, to see whether
    481                 # we can combine cases
    482                 if valueIndex + 1 < len(paramValidValues) :
    483                     (nextParamValue, nextDependentVecSize, nextDependentParamName, nextDependentValidValues, nextErrorCode, nextValueConvert) = paramValidValues[valueIndex + 1]
    484                     if depParamConvertToType:
    485                         usedNextDependentVecSize = nextDependentVecSize
    486                     else:
    487                         usedNextDependentVecSize = None
    488 
    489                 # Create a case for this value.  As a mnemonic,
    490                 # if we have a dependent vector size that we're ignoring,
    491                 # add it as a comment.
    492                 if usedDependentVecSize == None and dependentVecSize != None:
    493                     switchCode.append("        case %s: /* size %s */" % (paramValue, dependentVecSize))
    494                 else:
    495                     switchCode.append("        case %s:" % paramValue)
    496 
    497                 # If this is not a GLenum case, then switch our error
    498                 # if no value is matched to be GL_INVALID_VALUE instead
    499                 # of GL_INVALID_ENUM.  (Yes, this does get confused
    500                 # if there are both values and GLenums in the same
    501                 # switch statement, which shouldn't happen.)
    502                 if paramValue[0:3] != "GL_":
    503                     errorDefaultCase = "GL_INVALID_VALUE"
    504 
    505                 # If all the remaining parameters are identical to the
    506                 # next set, then we're done - we'll just create the
    507                 # official code on the next pass through, and the two
    508                 # cases will share the code.
    509                 if valueIndex + 1 < len(paramValidValues) and usedDependentVecSize == usedNextDependentVecSize and dependentParamName == nextDependentParamName and dependentValidValues == nextDependentValidValues and errorCode == nextErrorCode and valueConvert == nextValueConvert:
    510                     continue
    511 
    512                 # Otherwise, we'll have to generate code for this case.
    513                 # Start off with a check: if there is a dependent parameter,
    514                 # and a list of valid values for that parameter, we need
    515                 # to generate an error if something other than one
    516                 # of those values is passed.
    517                 if len(dependentValidValues) > 0:
    518                     conditional=""
    519 
    520                     # If the parameter being checked is actually an array,
    521                     # check only its first element.
    522                     if depParamMaxVecSize == 0:
    523                         valueToCheck = dependentParamName
    524                     else:
    525                         valueToCheck = "%s[0]" % dependentParamName
    526 
    527                     for v in dependentValidValues:
    528                         conditional += " && %s != %s" % (valueToCheck, v)
    529                     switchCode.append("            if (%s) {" % conditional[4:])
    530                     if errorCode == None:
    531                         errorCode = "GL_INVALID_ENUM"
    532                     switchCode.append('                _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=0x%s)", %s);' % (errorCode, funcName, paramName, "%x", paramName))
    533                     switchCode.append("                %s;" % errorReturn)
    534                     switchCode.append("            }")
    535                 # endif there are dependent valid values
    536 
    537                 # The dependent parameter may require conditional
    538                 # value conversion.  If it does, and we don't want
    539                 # to convert values, we'll have to generate code for that
    540                 if depParamValueConversion == "some" and valueConvert == "noconvert":
    541                     switchCode.append("            convert_%s_value = 0;" % dependentParamName)
    542 
    543                 # If there's a dependent vector size for this parameter
    544                 # that we're actually going to use (i.e. we need conversion),
    545                 # mark it.
    546                 if usedDependentVecSize:
    547                     switchCode.append("            n_%s = %s;" % (dependentParamName, dependentVecSize))
    548 
    549                 # In all cases, break out of the switch if any valid
    550                 # value is found.
    551                 switchCode.append("            break;")
    552 
    553 
    554             # Need a default case to catch all the other, invalid
    555             # parameter values.  These will all generate errors.
    556             switchCode.append("        default:")
    557             if errorCode == None:
    558                 errorCode = "GL_INVALID_ENUM"
    559             formatString = GetFormatString(paramType)
    560             if formatString == None:
    561                 switchCode.append('            _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s)");' % (errorCode, funcName, paramName))
    562             else:
    563                 switchCode.append('            _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=%s)", %s);' % (errorCode, funcName, paramName, formatString, paramName))
    564             switchCode.append("            %s;" % errorReturn)
    565 
    566             # End of our switch code.
    567             switchCode.append("    }")
    568 
    569         # endfor every recognized parameter value
    570 
    571     # endfor every param
    572 
    573     if conversionCodeOutgoing != [] or conversionCodeIncoming != []:
    574         continue
    575 
    576     # Here, the passthroughDeclarationString and passthroughCallString
    577     # are complete; remove the extra ", " at the front of each.
    578     passthroughDeclarationString = passthroughDeclarationString[2:]
    579     passthroughCallString = passthroughCallString[2:]
    580     if not passthroughDeclarationString:
    581         passthroughDeclarationString = "void"
    582 
    583     # The Mesa functions are scattered across all the Mesa
    584     # header files.  The easiest way to manage declarations
    585     # is to create them ourselves.
    586     if funcName in allSpecials:
    587         print "/* this function is special and is defined elsewhere */"
    588     print "extern %s GL_APIENTRY %s(%s);" % (returnType, passthroughFuncName, passthroughDeclarationString)
    589 
    590     # A function may be a core function (i.e. it exists in
    591     # the core specification), a core addition (extension
    592     # functions added officially to the core), a required
    593     # extension (usually an extension for an earlier version
    594     # that has been officially adopted), or an optional extension.
    595     #
    596     # Core functions have a simple category (e.g. "GLES1.1");
    597     # we generate only a simple callback for them.
    598     #
    599     # Core additions have two category listings, one simple
    600     # and one compound (e.g.  ["GLES1.1", "GLES1.1:OES_fixed_point"]).  
    601     # We generate the core function, and also an extension function.
    602     #
    603     # Required extensions and implemented optional extensions
    604     # have a single compound category "GLES1.1:OES_point_size_array".
    605     # For these we generate just the extension function.
    606     for categorySpec in apiutil.Categories(funcName):
    607         compoundCategory = categorySpec.split(":")
    608 
    609         # This category isn't for us, if the base category doesn't match
    610         # our version
    611         if compoundCategory[0] != version:
    612             continue
    613 
    614         # Otherwise, determine if we're writing code for a core
    615         # function (no suffix) or an extension function.
    616         if len(compoundCategory) == 1:
    617             # This is a core function
    618             extensionName = None
    619             extensionSuffix = ""
    620         else:
    621             # This is an extension function.  We'll need to append
    622             # the extension suffix.
    623             extensionName = compoundCategory[1]
    624             extensionSuffix = extensionName.split("_")[0]
    625         fullFuncName = funcPrefix + funcName + extensionSuffix
    626 
    627         # Now the generated function.  The text used to mark an API-level
    628         # function, oddly, is version-specific.
    629         if extensionName:
    630             print "/* Extension %s */" % extensionName
    631 
    632         if (not variables and
    633             not switchCode and
    634             not conversionCodeOutgoing and
    635             not conversionCodeIncoming):
    636             # pass through directly
    637             print "#define %s %s" % (fullFuncName, passthroughFuncName)
    638             print
    639             continue
    640 
    641         print "static %s GL_APIENTRY %s(%s)" % (returnType, fullFuncName, declarationString)
    642         print "{"
    643 
    644         # Start printing our code pieces.  Start with any local
    645         # variables we need.  This unusual syntax joins the 
    646         # lines in the variables[] array with the "\n" separator.
    647         if len(variables) > 0:
    648             print "\n".join(variables) + "\n"
    649 
    650         # If there's any sort of parameter checking or variable
    651         # array sizing, the switch code will contain it.
    652         if len(switchCode) > 0:
    653             print "\n".join(switchCode) + "\n"
    654 
    655         # In the case of an outgoing conversion (i.e. parameters must
    656         # be converted before calling the underlying Mesa function),
    657         # use the appropriate code.
    658         if "get" not in props and len(conversionCodeOutgoing) > 0:
    659             print "\n".join(conversionCodeOutgoing) + "\n"
    660 
    661         # Call the Mesa function.  Note that there are very few functions
    662         # that return a value (i.e. returnType is not "void"), and that
    663         # none of them require incoming translation; so we're safe
    664         # to generate code that directly returns in those cases,
    665         # even though it's not completely independent.
    666 
    667         if returnType == "void":
    668             print "    %s(%s);" % (passthroughFuncName, passthroughCallString)
    669         else:
    670             print "    return %s(%s);" % (passthroughFuncName, passthroughCallString)
    671 
    672         # If the function is one that returns values (i.e. "get" in props),
    673         # it might return values of a different type than we need, that
    674         # require conversion before passing back to the application.
    675         if "get" in props and len(conversionCodeIncoming) > 0:
    676             print "\n".join(conversionCodeIncoming)
    677 
    678         # All done.
    679         print "}"
    680         print
    681     # end for each category provided for a function
    682 
    683 # end for each function
    684 
    685 print """
    686 #include "glapi/glapi.h"
    687 
    688 #if FEATURE_remap_table
    689 
    690 /* define esLocalRemapTable */
    691 #include "main/api_exec_%s_dispatch.h"
    692 
    693 #define need_MESA_remap_table
    694 #include "main/api_exec_%s_remap_helper.h"
    695 
    696 static void
    697 init_remap_table(void)
    698 {
    699    _glthread_DECLARE_STATIC_MUTEX(mutex);
    700    static GLboolean initialized = GL_FALSE;
    701    const struct gl_function_pool_remap *remap = MESA_remap_table_functions;
    702    int i;
    703 
    704    _glthread_LOCK_MUTEX(mutex);
    705    if (initialized) {
    706       _glthread_UNLOCK_MUTEX(mutex);
    707       return;
    708    }
    709 
    710    for (i = 0; i < esLocalRemapTable_size; i++) {
    711       GLint offset;
    712       const char *spec;
    713 
    714       /* sanity check */
    715       ASSERT(i == remap[i].remap_index);
    716       spec = _mesa_function_pool + remap[i].pool_index;
    717 
    718       offset = _mesa_map_function_spec(spec);
    719       esLocalRemapTable[i] = offset;
    720    }
    721    initialized = GL_TRUE;
    722    _glthread_UNLOCK_MUTEX(mutex);
    723 }
    724 
    725 #else /* FEATURE_remap_table */
    726 
    727 #include "%sapi/main/dispatch.h"
    728 
    729 static INLINE void
    730 init_remap_table(void)
    731 {
    732 }
    733 
    734 #endif /* FEATURE_remap_table */
    735 
    736 struct _glapi_table *
    737 _mesa_create_exec_table_%s(void)
    738 {
    739    struct _glapi_table *exec;
    740 
    741    exec = _mesa_alloc_dispatch_table(_gloffset_COUNT);
    742    if (exec == NULL)
    743       return NULL;
    744 
    745    init_remap_table();
    746 """ % (shortname, shortname, shortname, shortname)
    747 
    748 for func in keys:
    749     prefix = "_es_" if func not in allSpecials else "_check_"
    750     for spec in apiutil.Categories(func):
    751         ext = spec.split(":")
    752         # version does not match
    753         if ext.pop(0) != version:
    754             continue
    755         entry = func
    756         if ext:
    757             suffix = ext[0].split("_")[0]
    758             entry += suffix
    759         print "    SET_%s(exec, %s%s);" % (entry, prefix, entry)
    760 print ""
    761 print "   return exec;"
    762 print "}"
    763 
    764 print """
    765 #endif /* FEATURE_%s */""" % (shortname.upper())
    766