Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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. """ % (versionHeader, versionExtHeader, shortname.upper())
  199.  
  200. # Everyone needs these types.
  201. print """
  202. /* These types are needed for the Mesa veneer, but are not defined in
  203. * the standard GLES headers.
  204. */
  205. typedef double GLdouble;
  206. typedef double GLclampd;
  207.  
  208. /* Mesa error handling requires these */
  209. extern void *_mesa_get_current_context(void);
  210. extern void _mesa_error(void *ctx, GLenum error, const char *fmtString, ... );
  211. """
  212.  
  213. # Finally we get to the all-important functions
  214. print """/*************************************************************
  215. * Generated functions begin here
  216. */
  217. """
  218. for funcName in keys:
  219.     if verbose > 0: sys.stderr.write("%s: processing function %s\n" % (program, funcName))
  220.  
  221.     # start figuring out what this function will look like.
  222.     returnType = apiutil.ReturnType(funcName)
  223.     props = apiutil.Properties(funcName)
  224.     params = apiutil.Parameters(funcName)
  225.     declarationString = apiutil.MakeDeclarationString(params)
  226.  
  227.     # In case of error, a function may have to return.  Make
  228.     # sure we have valid return values in this case.
  229.     if returnType == "void":
  230.         errorReturn = "return"
  231.     elif returnType == "GLboolean":
  232.         errorReturn = "return GL_FALSE"
  233.     else:
  234.         errorReturn = "return (%s) 0" % returnType
  235.  
  236.     # These are the output of this large calculation block.
  237.     # passthroughDeclarationString: a typed set of parameters that
  238.     # will be used to create the "extern" reference for the
  239.     # underlying Mesa or support function.  Note that as generated
  240.     # these have an extra ", " at the beginning, which will be
  241.     # removed before use.
  242.     #
  243.     # passthroughDeclarationString: an untyped list of parameters
  244.     # that will be used to call the underlying Mesa or support
  245.     # function (including references to converted parameters).
  246.     # This will also be generated with an extra ", " at the
  247.     # beginning, which will be removed before use.
  248.     #
  249.     # variables: C code to create any local variables determined to
  250.     # be necessary.
  251.     # conversionCodeOutgoing: C code to convert application parameters
  252.     # to a necessary type before calling the underlying support code.
  253.     # May be empty if no conversion is required.  
  254.     # conversionCodeIncoming: C code to do the converse: convert
  255.     # values returned by underlying Mesa code to the types needed
  256.     # by the application.
  257.     # Note that *either* the conversionCodeIncoming will be used (for
  258.     # generated query functions), *or* the conversionCodeOutgoing will
  259.     # be used (for generated non-query functions), never both.
  260.     passthroughFuncName = ""
  261.     passthroughDeclarationString = ""
  262.     passthroughCallString = ""
  263.     prefixOverride = None
  264.     variables = []
  265.     conversionCodeOutgoing = []
  266.     conversionCodeIncoming = []
  267.     switchCode = []
  268.  
  269.     # Calculate the name of the underlying support function to call.
  270.     # By default, the passthrough function is named _mesa_<funcName>.
  271.     # We're allowed to override the prefix and/or the function name
  272.     # for each function record, though.  The "ConversionFunction"
  273.     # utility is poorly named, BTW...
  274.     if funcName in allSpecials:
  275.         # perform checks and pass through
  276.         funcPrefix = "_check_"
  277.         aliasprefix = "_es_"
  278.     else:
  279.         funcPrefix = "_es_"
  280.         aliasprefix = apiutil.AliasPrefix(funcName)
  281.     alias = apiutil.ConversionFunction(funcName)
  282.     prefixOverride = apiutil.FunctionPrefix(funcName)
  283.     if prefixOverride != "_mesa_":
  284.         aliasprefix = apiutil.FunctionPrefix(funcName)
  285.     if not alias:
  286.         # There may still be a Mesa alias for the function
  287.         if apiutil.Alias(funcName):
  288.             passthroughFuncName = "%s%s" % (aliasprefix, apiutil.Alias(funcName))
  289.         else:
  290.             passthroughFuncName = "%s%s" % (aliasprefix, funcName)
  291.     else: # a specific alias is provided
  292.         passthroughFuncName = "%s%s" % (aliasprefix, alias)
  293.  
  294.     # Look at every parameter: each one may have only specific
  295.     # allowed values, or dependent parameters to check, or
  296.     # variant-sized vector arrays to calculate
  297.     for (paramName, paramType, paramMaxVecSize, paramConvertToType, paramValidValues, paramValueConversion) in params:
  298.         # We'll need this below if we're doing conversions
  299.         (paramBaseType, paramTypeModifiers) = GetBaseType(paramType)
  300.  
  301.         # Conversion management.
  302.         # We'll handle three cases, easiest to hardest: a parameter
  303.         # that doesn't require conversion, a scalar parameter that
  304.         # requires conversion, and a vector parameter that requires
  305.         # conversion.
  306.         if paramConvertToType == None:
  307.             # Unconverted parameters are easy, whether they're vector
  308.             # or scalar - just add them to the call list.  No conversions
  309.             # or anything to worry about.
  310.             passthroughDeclarationString += ", %s %s" % (paramType, paramName)
  311.             passthroughCallString += ", %s" % paramName
  312.  
  313.         elif paramMaxVecSize == 0: # a scalar parameter that needs conversion
  314.             # A scalar to hold a converted parameter
  315.             variables.append("    %s converted_%s;" % (paramConvertToType, paramName))
  316.  
  317.             # Outgoing conversion depends on whether we have to conditionally
  318.             # perform value conversion.
  319.             if paramValueConversion == "none":
  320.                 conversionCodeOutgoing.append("    converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
  321.             elif paramValueConversion == "some":
  322.                 # We'll need a conditional variable to keep track of
  323.                 # whether we're converting values or not.
  324.                 if ("    int convert_%s_value = 1;" % paramName) not in variables:
  325.                     variables.append("    int convert_%s_value = 1;" % paramName)
  326.  
  327.                 # Write code based on that conditional.
  328.                 conversionCodeOutgoing.append("    if (convert_%s_value) {" % paramName)
  329.                 conversionCodeOutgoing.append("        converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
  330.                 conversionCodeOutgoing.append("    } else {")
  331.                 conversionCodeOutgoing.append("        converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
  332.                 conversionCodeOutgoing.append("    }")
  333.             else: # paramValueConversion == "all"
  334.                 conversionCodeOutgoing.append("    converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
  335.  
  336.             # Note that there can be no incoming conversion for a
  337.             # scalar parameter; changing the scalar will only change
  338.             # the local value, and won't ultimately change anything
  339.             # that passes back to the application.
  340.  
  341.             # Call strings.  The unusual " ".join() call will join the
  342.             # array of parameter modifiers with spaces as separators.
  343.             passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
  344.             passthroughCallString += ", converted_%s" % paramName
  345.  
  346.         else: # a vector parameter that needs conversion
  347.             # We'll need an index variable for conversions
  348.             if "    register unsigned int i;" not in variables:
  349.                 variables.append("    register unsigned int i;")
  350.  
  351.             # This variable will hold the (possibly variant) size of
  352.             # this array needing conversion.  By default, we'll set
  353.             # it to the maximal size (which is correct for functions
  354.             # with a constant-sized vector parameter); for true
  355.             # variant arrays, we'll modify it with other code.
  356.             variables.append("    unsigned int n_%s = %d;" % (paramName, paramMaxVecSize))
  357.  
  358.             # This array will hold the actual converted values.
  359.             variables.append("    %s converted_%s[%d];" % (paramConvertToType, paramName, paramMaxVecSize))
  360.  
  361.             # Again, we choose the conversion code based on whether we
  362.             # have to always convert values, never convert values, or
  363.             # conditionally convert values.
  364.             if paramValueConversion == "none":
  365.                 conversionCodeOutgoing.append("    for (i = 0; i < n_%s; i++) {" % paramName)
  366.                 conversionCodeOutgoing.append("        converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
  367.                 conversionCodeOutgoing.append("    }")
  368.             elif paramValueConversion == "some":
  369.                 # We'll need a conditional variable to keep track of
  370.                 # whether we're converting values or not.
  371.                 if ("    int convert_%s_value = 1;" % paramName) not in variables:
  372.                     variables.append("    int convert_%s_value = 1;" % paramName)
  373.                 # Write code based on that conditional.
  374.                 conversionCodeOutgoing.append("    if (convert_%s_value) {" % paramName)
  375.                 conversionCodeOutgoing.append("        for (i = 0; i < n_%s; i++) {" % paramName)
  376.                 conversionCodeOutgoing.append("            converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
  377.                 conversionCodeOutgoing.append("        }")
  378.                 conversionCodeOutgoing.append("    } else {")
  379.                 conversionCodeOutgoing.append("        for (i = 0; i < n_%s; i++) {" % paramName)
  380.                 conversionCodeOutgoing.append("            converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
  381.                 conversionCodeOutgoing.append("        }")
  382.                 conversionCodeOutgoing.append("    }")
  383.             else: # paramValueConversion == "all"
  384.                 conversionCodeOutgoing.append("    for (i = 0; i < n_%s; i++) {" % paramName)
  385.                 conversionCodeOutgoing.append("        converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
  386.  
  387.                 conversionCodeOutgoing.append("    }")
  388.  
  389.             # If instead we need an incoming conversion (i.e. results
  390.             # from Mesa have to be converted before handing back
  391.             # to the application), this is it.  Fortunately, we don't
  392.             # have to worry about conditional value conversion - the
  393.             # functions that do (e.g. glGetFixedv()) are handled
  394.             # specially, outside this code generation.
  395.             #
  396.             # Whether we use incoming conversion or outgoing conversion
  397.             # is determined later - we only ever use one or the other.
  398.  
  399.             if paramValueConversion == "none":
  400.                 conversionCodeIncoming.append("    for (i = 0; i < n_%s; i++) {" % paramName)
  401.                 conversionCodeIncoming.append("        %s[i] = (%s) converted_%s[i];" % (paramName, paramConvertToType, paramName))
  402.                 conversionCodeIncoming.append("    }")
  403.             elif paramValueConversion == "some":
  404.                 # We'll need a conditional variable to keep track of
  405.                 # whether we're converting values or not.
  406.                 if ("    int convert_%s_value = 1;" % paramName) not in variables:
  407.                     variables.append("    int convert_%s_value = 1;" % paramName)
  408.  
  409.                 # Write code based on that conditional.
  410.                 conversionCodeIncoming.append("    if (convert_%s_value) {" % paramName)
  411.                 conversionCodeIncoming.append("        for (i = 0; i < n_%s; i++) {" % paramName)
  412.                 conversionCodeIncoming.append("            %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
  413.                 conversionCodeIncoming.append("        }")
  414.                 conversionCodeIncoming.append("    } else {")
  415.                 conversionCodeIncoming.append("        for (i = 0; i < n_%s; i++) {" % paramName)
  416.                 conversionCodeIncoming.append("            %s[i] = (%s) converted_%s[i];" % (paramName, paramBaseType, paramName))
  417.                 conversionCodeIncoming.append("        }")
  418.                 conversionCodeIncoming.append("    }")
  419.             else: # paramValueConversion == "all"
  420.                 conversionCodeIncoming.append("    for (i = 0; i < n_%s; i++) {" % paramName)
  421.                 conversionCodeIncoming.append("        %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
  422.                 conversionCodeIncoming.append("    }")
  423.  
  424.             # Call strings.  The unusual " ".join() call will join the
  425.             # array of parameter modifiers with spaces as separators.
  426.             passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
  427.             passthroughCallString += ", converted_%s" % paramName
  428.  
  429.         # endif conversion management
  430.  
  431.         # Parameter checking.  If the parameter has a specific list of
  432.         # valid values, we have to make sure that the passed-in values
  433.         # match these, or we make an error.
  434.         if len(paramValidValues) > 0:
  435.             # We're about to make a big switch statement with an
  436.             # error at the end.  By default, the error is GL_INVALID_ENUM,
  437.             # unless we find a "case" statement in the middle with a
  438.             # non-GLenum value.
  439.             errorDefaultCase = "GL_INVALID_ENUM"
  440.  
  441.             # This parameter has specific valid values.  Make a big
  442.             # switch statement to handle it.  Note that the original
  443.             # parameters are always what is checked, not the
  444.             # converted parameters.
  445.             switchCode.append("    switch(%s) {" % paramName)
  446.  
  447.             for valueIndex in range(len(paramValidValues)):
  448.                 (paramValue, dependentVecSize, dependentParamName, dependentValidValues, errorCode, valueConvert) = paramValidValues[valueIndex]
  449.  
  450.                 # We're going to need information on the dependent param
  451.                 # as well.
  452.                 if dependentParamName:
  453.                     depParamIndex = apiutil.FindParamIndex(params, dependentParamName)
  454.                     if depParamIndex == None:
  455.                         sys.stderr.write("%s: can't find dependent param '%s' for function '%s'\n" % (program, dependentParamName, funcName))
  456.  
  457.                     (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = params[depParamIndex]
  458.                 else:
  459.                     (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = (None, None, None, None, [], None)
  460.  
  461.                 # This is a sneaky trick.  It's valid syntax for a parameter
  462.                 # that is *not* going to be converted to be declared
  463.                 # with a dependent vector size; but in this case, the
  464.                 # dependent vector size is unused and unnecessary.
  465.                 # So check for this and ignore the dependent vector size
  466.                 # if the parameter is not going to be converted.
  467.                 if depParamConvertToType:
  468.                     usedDependentVecSize = dependentVecSize
  469.                 else:
  470.                     usedDependentVecSize = None
  471.  
  472.                 # We'll peek ahead at the next parameter, to see whether
  473.                 # we can combine cases
  474.                 if valueIndex + 1 < len(paramValidValues) :
  475.                     (nextParamValue, nextDependentVecSize, nextDependentParamName, nextDependentValidValues, nextErrorCode, nextValueConvert) = paramValidValues[valueIndex + 1]
  476.                     if depParamConvertToType:
  477.                         usedNextDependentVecSize = nextDependentVecSize
  478.                     else:
  479.                         usedNextDependentVecSize = None
  480.  
  481.                 # Create a case for this value.  As a mnemonic,
  482.                 # if we have a dependent vector size that we're ignoring,
  483.                 # add it as a comment.
  484.                 if usedDependentVecSize == None and dependentVecSize != None:
  485.                     switchCode.append("        case %s: /* size %s */" % (paramValue, dependentVecSize))
  486.                 else:
  487.                     switchCode.append("        case %s:" % paramValue)
  488.  
  489.                 # If this is not a GLenum case, then switch our error
  490.                 # if no value is matched to be GL_INVALID_VALUE instead
  491.                 # of GL_INVALID_ENUM.  (Yes, this does get confused
  492.                 # if there are both values and GLenums in the same
  493.                 # switch statement, which shouldn't happen.)
  494.                 if paramValue[0:3] != "GL_":
  495.                     errorDefaultCase = "GL_INVALID_VALUE"
  496.  
  497.                 # If all the remaining parameters are identical to the
  498.                 # next set, then we're done - we'll just create the
  499.                 # official code on the next pass through, and the two
  500.                 # cases will share the code.
  501.                 if valueIndex + 1 < len(paramValidValues) and usedDependentVecSize == usedNextDependentVecSize and dependentParamName == nextDependentParamName and dependentValidValues == nextDependentValidValues and errorCode == nextErrorCode and valueConvert == nextValueConvert:
  502.                     continue
  503.  
  504.                 # Otherwise, we'll have to generate code for this case.
  505.                 # Start off with a check: if there is a dependent parameter,
  506.                 # and a list of valid values for that parameter, we need
  507.                 # to generate an error if something other than one
  508.                 # of those values is passed.
  509.                 if len(dependentValidValues) > 0:
  510.                     conditional=""
  511.  
  512.                     # If the parameter being checked is actually an array,
  513.                     # check only its first element.
  514.                     if depParamMaxVecSize == 0:
  515.                         valueToCheck = dependentParamName
  516.                     else:
  517.                         valueToCheck = "%s[0]" % dependentParamName
  518.  
  519.                     for v in dependentValidValues:
  520.                         conditional += " && %s != %s" % (valueToCheck, v)
  521.                     switchCode.append("            if (%s) {" % conditional[4:])
  522.                     if errorCode == None:
  523.                         errorCode = "GL_INVALID_ENUM"
  524.                     switchCode.append('                _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=0x%s)", %s);' % (errorCode, funcName, paramName, "%x", paramName))
  525.                     switchCode.append("                %s;" % errorReturn)
  526.                     switchCode.append("            }")
  527.                 # endif there are dependent valid values
  528.  
  529.                 # The dependent parameter may require conditional
  530.                 # value conversion.  If it does, and we don't want
  531.                 # to convert values, we'll have to generate code for that
  532.                 if depParamValueConversion == "some" and valueConvert == "noconvert":
  533.                     switchCode.append("            convert_%s_value = 0;" % dependentParamName)
  534.  
  535.                 # If there's a dependent vector size for this parameter
  536.                 # that we're actually going to use (i.e. we need conversion),
  537.                 # mark it.
  538.                 if usedDependentVecSize:
  539.                     switchCode.append("            n_%s = %s;" % (dependentParamName, dependentVecSize))
  540.  
  541.                 # In all cases, break out of the switch if any valid
  542.                 # value is found.
  543.                 switchCode.append("            break;")
  544.  
  545.  
  546.             # Need a default case to catch all the other, invalid
  547.             # parameter values.  These will all generate errors.
  548.             switchCode.append("        default:")
  549.             if errorCode == None:
  550.                 errorCode = "GL_INVALID_ENUM"
  551.             formatString = GetFormatString(paramType)
  552.             if formatString == None:
  553.                 switchCode.append('            _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s)");' % (errorCode, funcName, paramName))
  554.             else:
  555.                 switchCode.append('            _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=%s)", %s);' % (errorCode, funcName, paramName, formatString, paramName))
  556.             switchCode.append("            %s;" % errorReturn)
  557.  
  558.             # End of our switch code.
  559.             switchCode.append("    }")
  560.  
  561.         # endfor every recognized parameter value
  562.  
  563.     # endfor every param
  564.  
  565.     # Here, the passthroughDeclarationString and passthroughCallString
  566.     # are complete; remove the extra ", " at the front of each.
  567.     passthroughDeclarationString = passthroughDeclarationString[2:]
  568.     passthroughCallString = passthroughCallString[2:]
  569.     if not passthroughDeclarationString:
  570.         passthroughDeclarationString = "void"
  571.  
  572.     # The Mesa functions are scattered across all the Mesa
  573.     # header files.  The easiest way to manage declarations
  574.     # is to create them ourselves.
  575.     if funcName in allSpecials:
  576.         print "/* this function is special and is defined elsewhere */"
  577.     print "extern %s GL_APIENTRY %s(%s);" % (returnType, passthroughFuncName, passthroughDeclarationString)
  578.  
  579.     # A function may be a core function (i.e. it exists in
  580.     # the core specification), a core addition (extension
  581.     # functions added officially to the core), a required
  582.     # extension (usually an extension for an earlier version
  583.     # that has been officially adopted), or an optional extension.
  584.     #
  585.     # Core functions have a simple category (e.g. "GLES1.1");
  586.     # we generate only a simple callback for them.
  587.     #
  588.     # Core additions have two category listings, one simple
  589.     # and one compound (e.g.  ["GLES1.1", "GLES1.1:OES_fixed_point"]).  
  590.     # We generate the core function, and also an extension function.
  591.     #
  592.     # Required extensions and implemented optional extensions
  593.     # have a single compound category "GLES1.1:OES_point_size_array".
  594.     # For these we generate just the extension function.
  595.     for categorySpec in apiutil.Categories(funcName):
  596.         compoundCategory = categorySpec.split(":")
  597.  
  598.         # This category isn't for us, if the base category doesn't match
  599.         # our version
  600.         if compoundCategory[0] != version:
  601.             continue
  602.  
  603.         # Otherwise, determine if we're writing code for a core
  604.         # function (no suffix) or an extension function.
  605.         if len(compoundCategory) == 1:
  606.             # This is a core function
  607.             extensionName = None
  608.             extensionSuffix = ""
  609.         else:
  610.             # This is an extension function.  We'll need to append
  611.             # the extension suffix.
  612.             extensionName = compoundCategory[1]
  613.             extensionSuffix = extensionName.split("_")[0]
  614.         fullFuncName = funcPrefix + funcName + extensionSuffix
  615.  
  616.         # Now the generated function.  The text used to mark an API-level
  617.         # function, oddly, is version-specific.
  618.         if extensionName:
  619.             print "/* Extension %s */" % extensionName
  620.  
  621.         if (not variables and
  622.             not switchCode and
  623.             not conversionCodeOutgoing and
  624.             not conversionCodeIncoming):
  625.             # pass through directly
  626.             print "#define %s %s" % (fullFuncName, passthroughFuncName)
  627.             print
  628.             continue
  629.  
  630.         print "static %s GL_APIENTRY %s(%s)" % (returnType, fullFuncName, declarationString)
  631.         print "{"
  632.  
  633.         # Start printing our code pieces.  Start with any local
  634.         # variables we need.  This unusual syntax joins the
  635.         # lines in the variables[] array with the "\n" separator.
  636.         if len(variables) > 0:
  637.             print "\n".join(variables) + "\n"
  638.  
  639.         # If there's any sort of parameter checking or variable
  640.         # array sizing, the switch code will contain it.
  641.         if len(switchCode) > 0:
  642.             print "\n".join(switchCode) + "\n"
  643.  
  644.         # In the case of an outgoing conversion (i.e. parameters must
  645.         # be converted before calling the underlying Mesa function),
  646.         # use the appropriate code.
  647.         if "get" not in props and len(conversionCodeOutgoing) > 0:
  648.             print "\n".join(conversionCodeOutgoing) + "\n"
  649.  
  650.         # Call the Mesa function.  Note that there are very few functions
  651.         # that return a value (i.e. returnType is not "void"), and that
  652.         # none of them require incoming translation; so we're safe
  653.         # to generate code that directly returns in those cases,
  654.         # even though it's not completely independent.
  655.  
  656.         if returnType == "void":
  657.             print "    %s(%s);" % (passthroughFuncName, passthroughCallString)
  658.         else:
  659.             print "    return %s(%s);" % (passthroughFuncName, passthroughCallString)
  660.  
  661.         # If the function is one that returns values (i.e. "get" in props),
  662.         # it might return values of a different type than we need, that
  663.         # require conversion before passing back to the application.
  664.         if "get" in props and len(conversionCodeIncoming) > 0:
  665.             print "\n".join(conversionCodeIncoming)
  666.  
  667.         # All done.
  668.         print "}"
  669.         print
  670.     # end for each category provided for a function
  671.  
  672. # end for each function
  673.  
  674. print """
  675. #include "glapi/glapi.h"
  676.  
  677. #if FEATURE_remap_table
  678.  
  679. /* cannot include main/dispatch.h here */
  680. #define _GLAPI_USE_REMAP_TABLE
  681. #include "%sapi/main/glapidispatch.h"
  682.  
  683. #define need_MESA_remap_table
  684. #include "%sapi/main/remap_helper.h"
  685.  
  686. /* force SET_* macros to use the local remap table */
  687. #define driDispatchRemapTable remap_table
  688. static int remap_table[driDispatchRemapTable_size];
  689.  
  690. static void
  691. init_remap_table(void)
  692. {
  693.   _glthread_DECLARE_STATIC_MUTEX(mutex);
  694.   static GLboolean initialized = GL_FALSE;
  695.   const struct gl_function_pool_remap *remap = MESA_remap_table_functions;
  696.   int i;
  697.  
  698.   _glthread_LOCK_MUTEX(mutex);
  699.   if (initialized) {
  700.      _glthread_UNLOCK_MUTEX(mutex);
  701.      return;
  702.   }
  703.  
  704.   for (i = 0; i < driDispatchRemapTable_size; i++) {
  705.      GLint offset;
  706.      const char *spec;
  707.  
  708.      /* sanity check */
  709.      ASSERT(i == remap[i].remap_index);
  710.      spec = _mesa_function_pool + remap[i].pool_index;
  711.  
  712.      offset = _mesa_map_function_spec(spec);
  713.      remap_table[i] = offset;
  714.   }
  715.   initialized = GL_TRUE;
  716.   _glthread_UNLOCK_MUTEX(mutex);
  717. }
  718.  
  719. #else /* FEATURE_remap_table */
  720.  
  721. /* cannot include main/dispatch.h here */
  722. #include "%sapi/main/glapidispatch.h"
  723.  
  724. static INLINE void
  725. init_remap_table(void)
  726. {
  727. }
  728.  
  729. #endif /* FEATURE_remap_table */
  730.  
  731. struct _glapi_table *
  732. _mesa_create_exec_table_%s(void)
  733. {
  734.   struct _glapi_table *exec;
  735.  
  736.   exec = _mesa_alloc_dispatch_table(_gloffset_COUNT);
  737.   if (exec == NULL)
  738.      return NULL;
  739.  
  740.   init_remap_table();
  741. """ % (shortname, shortname, shortname, shortname)
  742.  
  743. for func in keys:
  744.     prefix = "_es_" if func not in allSpecials else "_check_"
  745.     for spec in apiutil.Categories(func):
  746.         ext = spec.split(":")
  747.         # version does not match
  748.         if ext.pop(0) != version:
  749.             continue
  750.         entry = func
  751.         if ext:
  752.             suffix = ext[0].split("_")[0]
  753.             entry += suffix
  754.         print "    SET_%s(exec, %s%s);" % (entry, prefix, entry)
  755. print ""
  756. print "   return exec;"
  757. print "}"
  758.  
  759. print """
  760. #endif /* FEATURE_%s */""" % (shortname.upper())
  761.