aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main/es_generator.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main/es_generator.py')
-rw-r--r--mesalib/src/mesa/main/es_generator.py1503
1 files changed, 760 insertions, 743 deletions
diff --git a/mesalib/src/mesa/main/es_generator.py b/mesalib/src/mesa/main/es_generator.py
index ecb34bb5c..36bd14d6c 100644
--- a/mesalib/src/mesa/main/es_generator.py
+++ b/mesalib/src/mesa/main/es_generator.py
@@ -1,743 +1,760 @@
-#*************************************************************************
-# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
-# All Rights Reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-# TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#*************************************************************************
-
-
-import sys, os
-import APIspecutil as apiutil
-
-# These dictionary entries are used for automatic conversion.
-# The string will be used as a format string with the conversion
-# variable.
-Converters = {
- 'GLfloat': {
- 'GLdouble': "(GLdouble) (%s)",
- 'GLfixed' : "(GLint) (%s * 65536)",
- },
- 'GLfixed': {
- 'GLfloat': "(GLfloat) (%s / 65536.0f)",
- 'GLdouble': "(GLdouble) (%s / 65536.0)",
- },
- 'GLdouble': {
- 'GLfloat': "(GLfloat) (%s)",
- 'GLfixed': "(GLfixed) (%s * 65536)",
- },
- 'GLclampf': {
- 'GLclampd': "(GLclampd) (%s)",
- 'GLclampx': "(GLclampx) (%s * 65536)",
- },
- 'GLclampx': {
- 'GLclampf': "(GLclampf) (%s / 65536.0f)",
- 'GLclampd': "(GLclampd) (%s / 65536.0)",
- },
- 'GLubyte': {
- 'GLfloat': "(GLfloat) (%s / 255.0f)",
- },
-}
-
-def GetBaseType(type):
- typeTokens = type.split(' ')
- baseType = None
- typeModifiers = []
- for t in typeTokens:
- if t in ['const', '*']:
- typeModifiers.append(t)
- else:
- baseType = t
- return (baseType, typeModifiers)
-
-def ConvertValue(value, fromType, toType):
- """Returns a string that represents the given parameter string,
- type-converted if necessary."""
-
- if not Converters.has_key(fromType):
- print >> sys.stderr, "No base converter for type '%s' found. Ignoring." % fromType
- return value
-
- if not Converters[fromType].has_key(toType):
- print >> sys.stderr, "No converter found for type '%s' to type '%s'. Ignoring." % (fromType, toType)
- return value
-
- # This part is simple. Return the proper conversion.
- conversionString = Converters[fromType][toType]
- return conversionString % value
-
-FormatStrings = {
- 'GLenum' : '0x%x',
- 'GLfloat' : '%f',
- 'GLint' : '%d',
- 'GLbitfield' : '0x%x',
-}
-def GetFormatString(type):
- if FormatStrings.has_key(type):
- return FormatStrings[type]
- else:
- return None
-
-
-######################################################################
-# Version-specific values to be used in the main script
-# header: which header file to include
-# api: what text specifies an API-level function
-VersionSpecificValues = {
- 'GLES1.1' : {
- 'description' : 'GLES1.1 functions',
- 'header' : 'GLES/gl.h',
- 'extheader' : 'GLES/glext.h',
- 'shortname' : 'es1'
- },
- 'GLES2.0': {
- 'description' : 'GLES2.0 functions',
- 'header' : 'GLES2/gl2.h',
- 'extheader' : 'GLES2/gl2ext.h',
- 'shortname' : 'es2'
- }
-}
-
-
-######################################################################
-# Main code for the script begins here.
-
-# Get the name of the program (without the directory part) for use in
-# error messages.
-program = os.path.basename(sys.argv[0])
-
-# Set default values
-verbose = 0
-functionList = "APIspec.xml"
-version = "GLES1.1"
-
-# Allow for command-line switches
-import getopt, time
-options = "hvV:S:"
-try:
- optlist, args = getopt.getopt(sys.argv[1:], options)
-except getopt.GetoptError, message:
- sys.stderr.write("%s: %s. Use -h for help.\n" % (program, message))
- sys.exit(1)
-
-for option, optarg in optlist:
- if option == "-h":
- sys.stderr.write("Usage: %s [-%s]\n" % (program, options))
- sys.stderr.write("Parse an API specification file and generate wrapper functions for a given GLES version\n")
- sys.stderr.write("-h gives help\n")
- sys.stderr.write("-v is verbose\n")
- sys.stderr.write("-V specifies GLES version to generate [%s]:\n" % version)
- for key in VersionSpecificValues.keys():
- sys.stderr.write(" %s - %s\n" % (key, VersionSpecificValues[key]['description']))
- sys.stderr.write("-S specifies API specification file to use [%s]\n" % functionList)
- sys.exit(1)
- elif option == "-v":
- verbose += 1
- elif option == "-V":
- version = optarg
- elif option == "-S":
- functionList = optarg
-
-# Beyond switches, we support no further command-line arguments
-if len(args) > 0:
- sys.stderr.write("%s: only switch arguments are supported - use -h for help\n" % program)
- sys.exit(1)
-
-# If we don't have a valid version, abort.
-if not VersionSpecificValues.has_key(version):
- sys.stderr.write("%s: version '%s' is not valid - use -h for help\n" % (program, version))
- sys.exit(1)
-
-# Grab the version-specific items we need to use
-versionHeader = VersionSpecificValues[version]['header']
-versionExtHeader = VersionSpecificValues[version]['extheader']
-shortname = VersionSpecificValues[version]['shortname']
-
-# If we get to here, we're good to go. The "version" parameter
-# directs GetDispatchedFunctions to only allow functions from
-# that "category" (version in our parlance). This allows
-# functions with different declarations in different categories
-# to exist (glTexImage2D, for example, is different between
-# GLES1 and GLES2).
-keys = apiutil.GetAllFunctions(functionList, version)
-
-allSpecials = apiutil.AllSpecials()
-
-print """/* DO NOT EDIT *************************************************
- * THIS FILE AUTOMATICALLY GENERATED BY THE %s SCRIPT
- * API specification file: %s
- * GLES version: %s
- * date: %s
- */
-""" % (program, functionList, version, time.strftime("%Y-%m-%d %H:%M:%S"))
-
-# The headers we choose are version-specific.
-print """
-#include "%s"
-#include "%s"
-#include "main/mfeatures.h"
-
-#if FEATURE_%s
-""" % (versionHeader, versionExtHeader, shortname.upper())
-
-# Everyone needs these types.
-print """
-/* These types are needed for the Mesa veneer, but are not defined in
- * the standard GLES headers.
- */
-typedef double GLdouble;
-typedef double GLclampd;
-
-/* Mesa error handling requires these */
-extern void *_mesa_get_current_context(void);
-extern void _mesa_error(void *ctx, GLenum error, const char *fmtString, ... );
-
-#include "main/compiler.h"
-#include "main/api_exec.h"
-#include "main/remap.h"
-
-/* cannot include main/dispatch.h here */
-#ifdef IN_DRI_DRIVER
-#define _GLAPI_USE_REMAP_TABLE
-#endif
-/* glapi uses GLAPIENTRY while GLES headers define GL_APIENTRY */
-#ifndef GLAPIENTRY
-#define GLAPIENTRY GL_APIENTRY
-#endif
-#include "%sapi/glapi/glapitable.h"
-#include "%sapi/glapi/glapioffsets.h"
-#include "%sapi/glapi/glapidispatch.h"
-
-#if FEATURE_remap_table
-
-#if !FEATURE_GL
-int driDispatchRemapTable[driDispatchRemapTable_size];
-#endif
-
-#define need_MESA_remap_table
-
-#include "%sapi/main/remap_helper.h"
-
-void
-_mesa_init_remap_table_%s(void)
-{
- _mesa_do_init_remap_table(_mesa_function_pool,
- driDispatchRemapTable_size,
- MESA_remap_table_functions);
-}
-
-void
-_mesa_map_static_functions_%s(void)
-{
-}
-
-#endif
-
-typedef void (*_glapi_proc)(void); /* generic function pointer */
-""" % (shortname, shortname, shortname, shortname, shortname, shortname);
-
-# Finally we get to the all-important functions
-print """/*************************************************************
- * Generated functions begin here
- */
-"""
-for funcName in keys:
- if verbose > 0: sys.stderr.write("%s: processing function %s\n" % (program, funcName))
-
- # start figuring out what this function will look like.
- returnType = apiutil.ReturnType(funcName)
- props = apiutil.Properties(funcName)
- params = apiutil.Parameters(funcName)
- declarationString = apiutil.MakeDeclarationString(params)
-
- # In case of error, a function may have to return. Make
- # sure we have valid return values in this case.
- if returnType == "void":
- errorReturn = "return"
- elif returnType == "GLboolean":
- errorReturn = "return GL_FALSE"
- else:
- errorReturn = "return (%s) 0" % returnType
-
- # These are the output of this large calculation block.
- # passthroughDeclarationString: a typed set of parameters that
- # will be used to create the "extern" reference for the
- # underlying Mesa or support function. Note that as generated
- # these have an extra ", " at the beginning, which will be
- # removed before use.
- #
- # passthroughDeclarationString: an untyped list of parameters
- # that will be used to call the underlying Mesa or support
- # function (including references to converted parameters).
- # This will also be generated with an extra ", " at the
- # beginning, which will be removed before use.
- #
- # variables: C code to create any local variables determined to
- # be necessary.
- # conversionCodeOutgoing: C code to convert application parameters
- # to a necessary type before calling the underlying support code.
- # May be empty if no conversion is required.
- # conversionCodeIncoming: C code to do the converse: convert
- # values returned by underlying Mesa code to the types needed
- # by the application.
- # Note that *either* the conversionCodeIncoming will be used (for
- # generated query functions), *or* the conversionCodeOutgoing will
- # be used (for generated non-query functions), never both.
- passthroughFuncName = ""
- passthroughDeclarationString = ""
- passthroughCallString = ""
- prefixOverride = None
- variables = []
- conversionCodeOutgoing = []
- conversionCodeIncoming = []
- switchCode = []
-
- # Calculate the name of the underlying support function to call.
- # By default, the passthrough function is named _mesa_<funcName>.
- # We're allowed to override the prefix and/or the function name
- # for each function record, though. The "ConversionFunction"
- # utility is poorly named, BTW...
- if funcName in allSpecials:
- # perform checks and pass through
- funcPrefix = "_check_"
- aliasprefix = "_es_"
- else:
- funcPrefix = "_es_"
- aliasprefix = apiutil.AliasPrefix(funcName)
- alias = apiutil.ConversionFunction(funcName)
- prefixOverride = apiutil.FunctionPrefix(funcName)
- if prefixOverride != "_mesa_":
- aliasprefix = apiutil.FunctionPrefix(funcName)
- if not alias:
- # There may still be a Mesa alias for the function
- if apiutil.Alias(funcName):
- passthroughFuncName = "%s%s" % (aliasprefix, apiutil.Alias(funcName))
- else:
- passthroughFuncName = "%s%s" % (aliasprefix, funcName)
- else: # a specific alias is provided
- passthroughFuncName = "%s%s" % (aliasprefix, alias)
-
- # Look at every parameter: each one may have only specific
- # allowed values, or dependent parameters to check, or
- # variant-sized vector arrays to calculate
- for (paramName, paramType, paramMaxVecSize, paramConvertToType, paramValidValues, paramValueConversion) in params:
- # We'll need this below if we're doing conversions
- (paramBaseType, paramTypeModifiers) = GetBaseType(paramType)
-
- # Conversion management.
- # We'll handle three cases, easiest to hardest: a parameter
- # that doesn't require conversion, a scalar parameter that
- # requires conversion, and a vector parameter that requires
- # conversion.
- if paramConvertToType == None:
- # Unconverted parameters are easy, whether they're vector
- # or scalar - just add them to the call list. No conversions
- # or anything to worry about.
- passthroughDeclarationString += ", %s %s" % (paramType, paramName)
- passthroughCallString += ", %s" % paramName
-
- elif paramMaxVecSize == 0: # a scalar parameter that needs conversion
- # A scalar to hold a converted parameter
- variables.append(" %s converted_%s;" % (paramConvertToType, paramName))
-
- # Outgoing conversion depends on whether we have to conditionally
- # perform value conversion.
- if paramValueConversion == "none":
- conversionCodeOutgoing.append(" converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
- elif paramValueConversion == "some":
- # We'll need a conditional variable to keep track of
- # whether we're converting values or not.
- if (" int convert_%s_value = 1;" % paramName) not in variables:
- variables.append(" int convert_%s_value = 1;" % paramName)
-
- # Write code based on that conditional.
- conversionCodeOutgoing.append(" if (convert_%s_value) {" % paramName)
- conversionCodeOutgoing.append(" converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
- conversionCodeOutgoing.append(" } else {")
- conversionCodeOutgoing.append(" converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
- conversionCodeOutgoing.append(" }")
- else: # paramValueConversion == "all"
- conversionCodeOutgoing.append(" converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
-
- # Note that there can be no incoming conversion for a
- # scalar parameter; changing the scalar will only change
- # the local value, and won't ultimately change anything
- # that passes back to the application.
-
- # Call strings. The unusual " ".join() call will join the
- # array of parameter modifiers with spaces as separators.
- passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
- passthroughCallString += ", converted_%s" % paramName
-
- else: # a vector parameter that needs conversion
- # We'll need an index variable for conversions
- if " register unsigned int i;" not in variables:
- variables.append(" register unsigned int i;")
-
- # This variable will hold the (possibly variant) size of
- # this array needing conversion. By default, we'll set
- # it to the maximal size (which is correct for functions
- # with a constant-sized vector parameter); for true
- # variant arrays, we'll modify it with other code.
- variables.append(" unsigned int n_%s = %d;" % (paramName, paramMaxVecSize))
-
- # This array will hold the actual converted values.
- variables.append(" %s converted_%s[%d];" % (paramConvertToType, paramName, paramMaxVecSize))
-
- # Again, we choose the conversion code based on whether we
- # have to always convert values, never convert values, or
- # conditionally convert values.
- if paramValueConversion == "none":
- conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
- conversionCodeOutgoing.append(" converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
- conversionCodeOutgoing.append(" }")
- elif paramValueConversion == "some":
- # We'll need a conditional variable to keep track of
- # whether we're converting values or not.
- if (" int convert_%s_value = 1;" % paramName) not in variables:
- variables.append(" int convert_%s_value = 1;" % paramName)
- # Write code based on that conditional.
- conversionCodeOutgoing.append(" if (convert_%s_value) {" % paramName)
- conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
- conversionCodeOutgoing.append(" converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
- conversionCodeOutgoing.append(" }")
- conversionCodeOutgoing.append(" } else {")
- conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
- conversionCodeOutgoing.append(" converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
- conversionCodeOutgoing.append(" }")
- conversionCodeOutgoing.append(" }")
- else: # paramValueConversion == "all"
- conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
- conversionCodeOutgoing.append(" converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
-
- conversionCodeOutgoing.append(" }")
-
- # If instead we need an incoming conversion (i.e. results
- # from Mesa have to be converted before handing back
- # to the application), this is it. Fortunately, we don't
- # have to worry about conditional value conversion - the
- # functions that do (e.g. glGetFixedv()) are handled
- # specially, outside this code generation.
- #
- # Whether we use incoming conversion or outgoing conversion
- # is determined later - we only ever use one or the other.
-
- if paramValueConversion == "none":
- conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
- conversionCodeIncoming.append(" %s[i] = (%s) converted_%s[i];" % (paramName, paramConvertToType, paramName))
- conversionCodeIncoming.append(" }")
- elif paramValueConversion == "some":
- # We'll need a conditional variable to keep track of
- # whether we're converting values or not.
- if (" int convert_%s_value = 1;" % paramName) not in variables:
- variables.append(" int convert_%s_value = 1;" % paramName)
-
- # Write code based on that conditional.
- conversionCodeIncoming.append(" if (convert_%s_value) {" % paramName)
- conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
- conversionCodeIncoming.append(" %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
- conversionCodeIncoming.append(" }")
- conversionCodeIncoming.append(" } else {")
- conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
- conversionCodeIncoming.append(" %s[i] = (%s) converted_%s[i];" % (paramName, paramBaseType, paramName))
- conversionCodeIncoming.append(" }")
- conversionCodeIncoming.append(" }")
- else: # paramValueConversion == "all"
- conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
- conversionCodeIncoming.append(" %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
- conversionCodeIncoming.append(" }")
-
- # Call strings. The unusual " ".join() call will join the
- # array of parameter modifiers with spaces as separators.
- passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
- passthroughCallString += ", converted_%s" % paramName
-
- # endif conversion management
-
- # Parameter checking. If the parameter has a specific list of
- # valid values, we have to make sure that the passed-in values
- # match these, or we make an error.
- if len(paramValidValues) > 0:
- # We're about to make a big switch statement with an
- # error at the end. By default, the error is GL_INVALID_ENUM,
- # unless we find a "case" statement in the middle with a
- # non-GLenum value.
- errorDefaultCase = "GL_INVALID_ENUM"
-
- # This parameter has specific valid values. Make a big
- # switch statement to handle it. Note that the original
- # parameters are always what is checked, not the
- # converted parameters.
- switchCode.append(" switch(%s) {" % paramName)
-
- for valueIndex in range(len(paramValidValues)):
- (paramValue, dependentVecSize, dependentParamName, dependentValidValues, errorCode, valueConvert) = paramValidValues[valueIndex]
-
- # We're going to need information on the dependent param
- # as well.
- if dependentParamName:
- depParamIndex = apiutil.FindParamIndex(params, dependentParamName)
- if depParamIndex == None:
- sys.stderr.write("%s: can't find dependent param '%s' for function '%s'\n" % (program, dependentParamName, funcName))
-
- (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = params[depParamIndex]
- else:
- (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = (None, None, None, None, [], None)
-
- # This is a sneaky trick. It's valid syntax for a parameter
- # that is *not* going to be converted to be declared
- # with a dependent vector size; but in this case, the
- # dependent vector size is unused and unnecessary.
- # So check for this and ignore the dependent vector size
- # if the parameter is not going to be converted.
- if depParamConvertToType:
- usedDependentVecSize = dependentVecSize
- else:
- usedDependentVecSize = None
-
- # We'll peek ahead at the next parameter, to see whether
- # we can combine cases
- if valueIndex + 1 < len(paramValidValues) :
- (nextParamValue, nextDependentVecSize, nextDependentParamName, nextDependentValidValues, nextErrorCode, nextValueConvert) = paramValidValues[valueIndex + 1]
- if depParamConvertToType:
- usedNextDependentVecSize = nextDependentVecSize
- else:
- usedNextDependentVecSize = None
-
- # Create a case for this value. As a mnemonic,
- # if we have a dependent vector size that we're ignoring,
- # add it as a comment.
- if usedDependentVecSize == None and dependentVecSize != None:
- switchCode.append(" case %s: /* size %s */" % (paramValue, dependentVecSize))
- else:
- switchCode.append(" case %s:" % paramValue)
-
- # If this is not a GLenum case, then switch our error
- # if no value is matched to be GL_INVALID_VALUE instead
- # of GL_INVALID_ENUM. (Yes, this does get confused
- # if there are both values and GLenums in the same
- # switch statement, which shouldn't happen.)
- if paramValue[0:3] != "GL_":
- errorDefaultCase = "GL_INVALID_VALUE"
-
- # If all the remaining parameters are identical to the
- # next set, then we're done - we'll just create the
- # official code on the next pass through, and the two
- # cases will share the code.
- if valueIndex + 1 < len(paramValidValues) and usedDependentVecSize == usedNextDependentVecSize and dependentParamName == nextDependentParamName and dependentValidValues == nextDependentValidValues and errorCode == nextErrorCode and valueConvert == nextValueConvert:
- continue
-
- # Otherwise, we'll have to generate code for this case.
- # Start off with a check: if there is a dependent parameter,
- # and a list of valid values for that parameter, we need
- # to generate an error if something other than one
- # of those values is passed.
- if len(dependentValidValues) > 0:
- conditional=""
-
- # If the parameter being checked is actually an array,
- # check only its first element.
- if depParamMaxVecSize == 0:
- valueToCheck = dependentParamName
- else:
- valueToCheck = "%s[0]" % dependentParamName
-
- for v in dependentValidValues:
- conditional += " && %s != %s" % (valueToCheck, v)
- switchCode.append(" if (%s) {" % conditional[4:])
- if errorCode == None:
- errorCode = "GL_INVALID_ENUM"
- switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=0x%s)", %s);' % (errorCode, funcName, paramName, "%x", paramName))
- switchCode.append(" %s;" % errorReturn)
- switchCode.append(" }")
- # endif there are dependent valid values
-
- # The dependent parameter may require conditional
- # value conversion. If it does, and we don't want
- # to convert values, we'll have to generate code for that
- if depParamValueConversion == "some" and valueConvert == "noconvert":
- switchCode.append(" convert_%s_value = 0;" % dependentParamName)
-
- # If there's a dependent vector size for this parameter
- # that we're actually going to use (i.e. we need conversion),
- # mark it.
- if usedDependentVecSize:
- switchCode.append(" n_%s = %s;" % (dependentParamName, dependentVecSize))
-
- # In all cases, break out of the switch if any valid
- # value is found.
- switchCode.append(" break;")
-
-
- # Need a default case to catch all the other, invalid
- # parameter values. These will all generate errors.
- switchCode.append(" default:")
- if errorCode == None:
- errorCode = "GL_INVALID_ENUM"
- formatString = GetFormatString(paramType)
- if formatString == None:
- switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s)");' % (errorCode, funcName, paramName))
- else:
- switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=%s)", %s);' % (errorCode, funcName, paramName, formatString, paramName))
- switchCode.append(" %s;" % errorReturn)
-
- # End of our switch code.
- switchCode.append(" }")
-
- # endfor every recognized parameter value
-
- # endfor every param
-
- # Here, the passthroughDeclarationString and passthroughCallString
- # are complete; remove the extra ", " at the front of each.
- passthroughDeclarationString = passthroughDeclarationString[2:]
- passthroughCallString = passthroughCallString[2:]
- if not passthroughDeclarationString:
- passthroughDeclarationString = "void"
-
- # The Mesa functions are scattered across all the Mesa
- # header files. The easiest way to manage declarations
- # is to create them ourselves.
- if funcName in allSpecials:
- print "/* this function is special and is defined elsewhere */"
- print "extern %s GL_APIENTRY %s(%s);" % (returnType, passthroughFuncName, passthroughDeclarationString)
-
- # A function may be a core function (i.e. it exists in
- # the core specification), a core addition (extension
- # functions added officially to the core), a required
- # extension (usually an extension for an earlier version
- # that has been officially adopted), or an optional extension.
- #
- # Core functions have a simple category (e.g. "GLES1.1");
- # we generate only a simple callback for them.
- #
- # Core additions have two category listings, one simple
- # and one compound (e.g. ["GLES1.1", "GLES1.1:OES_fixed_point"]).
- # We generate the core function, and also an extension function.
- #
- # Required extensions and implemented optional extensions
- # have a single compound category "GLES1.1:OES_point_size_array".
- # For these we generate just the extension function.
- for categorySpec in apiutil.Categories(funcName):
- compoundCategory = categorySpec.split(":")
-
- # This category isn't for us, if the base category doesn't match
- # our version
- if compoundCategory[0] != version:
- continue
-
- # Otherwise, determine if we're writing code for a core
- # function (no suffix) or an extension function.
- if len(compoundCategory) == 1:
- # This is a core function
- extensionName = None
- extensionSuffix = ""
- else:
- # This is an extension function. We'll need to append
- # the extension suffix.
- extensionName = compoundCategory[1]
- extensionSuffix = extensionName.split("_")[0]
- fullFuncName = funcPrefix + funcName + extensionSuffix
-
- # Now the generated function. The text used to mark an API-level
- # function, oddly, is version-specific.
- if extensionName:
- print "/* Extension %s */" % extensionName
-
- if (not variables and
- not switchCode and
- not conversionCodeOutgoing and
- not conversionCodeIncoming):
- # pass through directly
- print "#define %s %s" % (fullFuncName, passthroughFuncName)
- print
- continue
-
- print "static %s GL_APIENTRY %s(%s)" % (returnType, fullFuncName, declarationString)
- print "{"
-
- # Start printing our code pieces. Start with any local
- # variables we need. This unusual syntax joins the
- # lines in the variables[] array with the "\n" separator.
- if len(variables) > 0:
- print "\n".join(variables) + "\n"
-
- # If there's any sort of parameter checking or variable
- # array sizing, the switch code will contain it.
- if len(switchCode) > 0:
- print "\n".join(switchCode) + "\n"
-
- # In the case of an outgoing conversion (i.e. parameters must
- # be converted before calling the underlying Mesa function),
- # use the appropriate code.
- if "get" not in props and len(conversionCodeOutgoing) > 0:
- print "\n".join(conversionCodeOutgoing) + "\n"
-
- # Call the Mesa function. Note that there are very few functions
- # that return a value (i.e. returnType is not "void"), and that
- # none of them require incoming translation; so we're safe
- # to generate code that directly returns in those cases,
- # even though it's not completely independent.
-
- if returnType == "void":
- print " %s(%s);" % (passthroughFuncName, passthroughCallString)
- else:
- print " return %s(%s);" % (passthroughFuncName, passthroughCallString)
-
- # If the function is one that returns values (i.e. "get" in props),
- # it might return values of a different type than we need, that
- # require conversion before passing back to the application.
- if "get" in props and len(conversionCodeIncoming) > 0:
- print "\n".join(conversionCodeIncoming)
-
- # All done.
- print "}"
- print
- # end for each category provided for a function
-
-# end for each function
-
-print """
-struct _glapi_table *
-_mesa_create_exec_table_%s(void)
-{
- struct _glapi_table *exec;
- exec = _mesa_alloc_dispatch_table(sizeof *exec);
- if (exec == NULL)
- return NULL;
-
-""" % shortname
-
-for func in keys:
- prefix = "_es_" if func not in allSpecials else "_check_"
- for spec in apiutil.Categories(func):
- ext = spec.split(":")
- # version does not match
- if ext.pop(0) != version:
- continue
- entry = func
- if ext:
- suffix = ext[0].split("_")[0]
- entry += suffix
- print " SET_%s(exec, %s%s);" % (entry, prefix, entry)
-print ""
-print " return exec;"
-print "}"
-
-print """
-#endif /* FEATURE_%s */""" % (shortname.upper())
+#*************************************************************************
+# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+# All Rights Reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# TUNGSTEN GRAPHICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#*************************************************************************
+
+
+import sys, os
+import APIspecutil as apiutil
+
+# These dictionary entries are used for automatic conversion.
+# The string will be used as a format string with the conversion
+# variable.
+Converters = {
+ 'GLfloat': {
+ 'GLdouble': "(GLdouble) (%s)",
+ 'GLfixed' : "(GLint) (%s * 65536)",
+ },
+ 'GLfixed': {
+ 'GLfloat': "(GLfloat) (%s / 65536.0f)",
+ 'GLdouble': "(GLdouble) (%s / 65536.0)",
+ },
+ 'GLdouble': {
+ 'GLfloat': "(GLfloat) (%s)",
+ 'GLfixed': "(GLfixed) (%s * 65536)",
+ },
+ 'GLclampf': {
+ 'GLclampd': "(GLclampd) (%s)",
+ 'GLclampx': "(GLclampx) (%s * 65536)",
+ },
+ 'GLclampx': {
+ 'GLclampf': "(GLclampf) (%s / 65536.0f)",
+ 'GLclampd': "(GLclampd) (%s / 65536.0)",
+ },
+ 'GLubyte': {
+ 'GLfloat': "(GLfloat) (%s / 255.0f)",
+ },
+}
+
+def GetBaseType(type):
+ typeTokens = type.split(' ')
+ baseType = None
+ typeModifiers = []
+ for t in typeTokens:
+ if t in ['const', '*']:
+ typeModifiers.append(t)
+ else:
+ baseType = t
+ return (baseType, typeModifiers)
+
+def ConvertValue(value, fromType, toType):
+ """Returns a string that represents the given parameter string,
+ type-converted if necessary."""
+
+ if not Converters.has_key(fromType):
+ print >> sys.stderr, "No base converter for type '%s' found. Ignoring." % fromType
+ return value
+
+ if not Converters[fromType].has_key(toType):
+ print >> sys.stderr, "No converter found for type '%s' to type '%s'. Ignoring." % (fromType, toType)
+ return value
+
+ # This part is simple. Return the proper conversion.
+ conversionString = Converters[fromType][toType]
+ return conversionString % value
+
+FormatStrings = {
+ 'GLenum' : '0x%x',
+ 'GLfloat' : '%f',
+ 'GLint' : '%d',
+ 'GLbitfield' : '0x%x',
+}
+def GetFormatString(type):
+ if FormatStrings.has_key(type):
+ return FormatStrings[type]
+ else:
+ return None
+
+
+######################################################################
+# Version-specific values to be used in the main script
+# header: which header file to include
+# api: what text specifies an API-level function
+VersionSpecificValues = {
+ 'GLES1.1' : {
+ 'description' : 'GLES1.1 functions',
+ 'header' : 'GLES/gl.h',
+ 'extheader' : 'GLES/glext.h',
+ 'shortname' : 'es1'
+ },
+ 'GLES2.0': {
+ 'description' : 'GLES2.0 functions',
+ 'header' : 'GLES2/gl2.h',
+ 'extheader' : 'GLES2/gl2ext.h',
+ 'shortname' : 'es2'
+ }
+}
+
+
+######################################################################
+# Main code for the script begins here.
+
+# Get the name of the program (without the directory part) for use in
+# error messages.
+program = os.path.basename(sys.argv[0])
+
+# Set default values
+verbose = 0
+functionList = "APIspec.xml"
+version = "GLES1.1"
+
+# Allow for command-line switches
+import getopt, time
+options = "hvV:S:"
+try:
+ optlist, args = getopt.getopt(sys.argv[1:], options)
+except getopt.GetoptError, message:
+ sys.stderr.write("%s: %s. Use -h for help.\n" % (program, message))
+ sys.exit(1)
+
+for option, optarg in optlist:
+ if option == "-h":
+ sys.stderr.write("Usage: %s [-%s]\n" % (program, options))
+ sys.stderr.write("Parse an API specification file and generate wrapper functions for a given GLES version\n")
+ sys.stderr.write("-h gives help\n")
+ sys.stderr.write("-v is verbose\n")
+ sys.stderr.write("-V specifies GLES version to generate [%s]:\n" % version)
+ for key in VersionSpecificValues.keys():
+ sys.stderr.write(" %s - %s\n" % (key, VersionSpecificValues[key]['description']))
+ sys.stderr.write("-S specifies API specification file to use [%s]\n" % functionList)
+ sys.exit(1)
+ elif option == "-v":
+ verbose += 1
+ elif option == "-V":
+ version = optarg
+ elif option == "-S":
+ functionList = optarg
+
+# Beyond switches, we support no further command-line arguments
+if len(args) > 0:
+ sys.stderr.write("%s: only switch arguments are supported - use -h for help\n" % program)
+ sys.exit(1)
+
+# If we don't have a valid version, abort.
+if not VersionSpecificValues.has_key(version):
+ sys.stderr.write("%s: version '%s' is not valid - use -h for help\n" % (program, version))
+ sys.exit(1)
+
+# Grab the version-specific items we need to use
+versionHeader = VersionSpecificValues[version]['header']
+versionExtHeader = VersionSpecificValues[version]['extheader']
+shortname = VersionSpecificValues[version]['shortname']
+
+# If we get to here, we're good to go. The "version" parameter
+# directs GetDispatchedFunctions to only allow functions from
+# that "category" (version in our parlance). This allows
+# functions with different declarations in different categories
+# to exist (glTexImage2D, for example, is different between
+# GLES1 and GLES2).
+keys = apiutil.GetAllFunctions(functionList, version)
+
+allSpecials = apiutil.AllSpecials()
+
+print """/* DO NOT EDIT *************************************************
+ * THIS FILE AUTOMATICALLY GENERATED BY THE %s SCRIPT
+ * API specification file: %s
+ * GLES version: %s
+ * date: %s
+ */
+""" % (program, functionList, version, time.strftime("%Y-%m-%d %H:%M:%S"))
+
+# The headers we choose are version-specific.
+print """
+#include "%s"
+#include "%s"
+#include "main/mfeatures.h"
+#include "main/compiler.h"
+#include "main/api_exec.h"
+
+#if FEATURE_%s
+""" % (versionHeader, versionExtHeader, shortname.upper())
+
+# Everyone needs these types.
+print """
+/* These types are needed for the Mesa veneer, but are not defined in
+ * the standard GLES headers.
+ */
+typedef double GLdouble;
+typedef double GLclampd;
+
+/* Mesa error handling requires these */
+extern void *_mesa_get_current_context(void);
+extern void _mesa_error(void *ctx, GLenum error, const char *fmtString, ... );
+"""
+
+# Finally we get to the all-important functions
+print """/*************************************************************
+ * Generated functions begin here
+ */
+"""
+for funcName in keys:
+ if verbose > 0: sys.stderr.write("%s: processing function %s\n" % (program, funcName))
+
+ # start figuring out what this function will look like.
+ returnType = apiutil.ReturnType(funcName)
+ props = apiutil.Properties(funcName)
+ params = apiutil.Parameters(funcName)
+ declarationString = apiutil.MakeDeclarationString(params)
+
+ # In case of error, a function may have to return. Make
+ # sure we have valid return values in this case.
+ if returnType == "void":
+ errorReturn = "return"
+ elif returnType == "GLboolean":
+ errorReturn = "return GL_FALSE"
+ else:
+ errorReturn = "return (%s) 0" % returnType
+
+ # These are the output of this large calculation block.
+ # passthroughDeclarationString: a typed set of parameters that
+ # will be used to create the "extern" reference for the
+ # underlying Mesa or support function. Note that as generated
+ # these have an extra ", " at the beginning, which will be
+ # removed before use.
+ #
+ # passthroughDeclarationString: an untyped list of parameters
+ # that will be used to call the underlying Mesa or support
+ # function (including references to converted parameters).
+ # This will also be generated with an extra ", " at the
+ # beginning, which will be removed before use.
+ #
+ # variables: C code to create any local variables determined to
+ # be necessary.
+ # conversionCodeOutgoing: C code to convert application parameters
+ # to a necessary type before calling the underlying support code.
+ # May be empty if no conversion is required.
+ # conversionCodeIncoming: C code to do the converse: convert
+ # values returned by underlying Mesa code to the types needed
+ # by the application.
+ # Note that *either* the conversionCodeIncoming will be used (for
+ # generated query functions), *or* the conversionCodeOutgoing will
+ # be used (for generated non-query functions), never both.
+ passthroughFuncName = ""
+ passthroughDeclarationString = ""
+ passthroughCallString = ""
+ prefixOverride = None
+ variables = []
+ conversionCodeOutgoing = []
+ conversionCodeIncoming = []
+ switchCode = []
+
+ # Calculate the name of the underlying support function to call.
+ # By default, the passthrough function is named _mesa_<funcName>.
+ # We're allowed to override the prefix and/or the function name
+ # for each function record, though. The "ConversionFunction"
+ # utility is poorly named, BTW...
+ if funcName in allSpecials:
+ # perform checks and pass through
+ funcPrefix = "_check_"
+ aliasprefix = "_es_"
+ else:
+ funcPrefix = "_es_"
+ aliasprefix = apiutil.AliasPrefix(funcName)
+ alias = apiutil.ConversionFunction(funcName)
+ prefixOverride = apiutil.FunctionPrefix(funcName)
+ if prefixOverride != "_mesa_":
+ aliasprefix = apiutil.FunctionPrefix(funcName)
+ if not alias:
+ # There may still be a Mesa alias for the function
+ if apiutil.Alias(funcName):
+ passthroughFuncName = "%s%s" % (aliasprefix, apiutil.Alias(funcName))
+ else:
+ passthroughFuncName = "%s%s" % (aliasprefix, funcName)
+ else: # a specific alias is provided
+ passthroughFuncName = "%s%s" % (aliasprefix, alias)
+
+ # Look at every parameter: each one may have only specific
+ # allowed values, or dependent parameters to check, or
+ # variant-sized vector arrays to calculate
+ for (paramName, paramType, paramMaxVecSize, paramConvertToType, paramValidValues, paramValueConversion) in params:
+ # We'll need this below if we're doing conversions
+ (paramBaseType, paramTypeModifiers) = GetBaseType(paramType)
+
+ # Conversion management.
+ # We'll handle three cases, easiest to hardest: a parameter
+ # that doesn't require conversion, a scalar parameter that
+ # requires conversion, and a vector parameter that requires
+ # conversion.
+ if paramConvertToType == None:
+ # Unconverted parameters are easy, whether they're vector
+ # or scalar - just add them to the call list. No conversions
+ # or anything to worry about.
+ passthroughDeclarationString += ", %s %s" % (paramType, paramName)
+ passthroughCallString += ", %s" % paramName
+
+ elif paramMaxVecSize == 0: # a scalar parameter that needs conversion
+ # A scalar to hold a converted parameter
+ variables.append(" %s converted_%s;" % (paramConvertToType, paramName))
+
+ # Outgoing conversion depends on whether we have to conditionally
+ # perform value conversion.
+ if paramValueConversion == "none":
+ conversionCodeOutgoing.append(" converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
+ elif paramValueConversion == "some":
+ # We'll need a conditional variable to keep track of
+ # whether we're converting values or not.
+ if (" int convert_%s_value = 1;" % paramName) not in variables:
+ variables.append(" int convert_%s_value = 1;" % paramName)
+
+ # Write code based on that conditional.
+ conversionCodeOutgoing.append(" if (convert_%s_value) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
+ conversionCodeOutgoing.append(" } else {")
+ conversionCodeOutgoing.append(" converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
+ conversionCodeOutgoing.append(" }")
+ else: # paramValueConversion == "all"
+ conversionCodeOutgoing.append(" converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
+
+ # Note that there can be no incoming conversion for a
+ # scalar parameter; changing the scalar will only change
+ # the local value, and won't ultimately change anything
+ # that passes back to the application.
+
+ # Call strings. The unusual " ".join() call will join the
+ # array of parameter modifiers with spaces as separators.
+ passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
+ passthroughCallString += ", converted_%s" % paramName
+
+ else: # a vector parameter that needs conversion
+ # We'll need an index variable for conversions
+ if " register unsigned int i;" not in variables:
+ variables.append(" register unsigned int i;")
+
+ # This variable will hold the (possibly variant) size of
+ # this array needing conversion. By default, we'll set
+ # it to the maximal size (which is correct for functions
+ # with a constant-sized vector parameter); for true
+ # variant arrays, we'll modify it with other code.
+ variables.append(" unsigned int n_%s = %d;" % (paramName, paramMaxVecSize))
+
+ # This array will hold the actual converted values.
+ variables.append(" %s converted_%s[%d];" % (paramConvertToType, paramName, paramMaxVecSize))
+
+ # Again, we choose the conversion code based on whether we
+ # have to always convert values, never convert values, or
+ # conditionally convert values.
+ if paramValueConversion == "none":
+ conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
+ conversionCodeOutgoing.append(" }")
+ elif paramValueConversion == "some":
+ # We'll need a conditional variable to keep track of
+ # whether we're converting values or not.
+ if (" int convert_%s_value = 1;" % paramName) not in variables:
+ variables.append(" int convert_%s_value = 1;" % paramName)
+ # Write code based on that conditional.
+ conversionCodeOutgoing.append(" if (convert_%s_value) {" % paramName)
+ conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
+ conversionCodeOutgoing.append(" }")
+ conversionCodeOutgoing.append(" } else {")
+ conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
+ conversionCodeOutgoing.append(" }")
+ conversionCodeOutgoing.append(" }")
+ else: # paramValueConversion == "all"
+ conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeOutgoing.append(" converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
+
+ conversionCodeOutgoing.append(" }")
+
+ # If instead we need an incoming conversion (i.e. results
+ # from Mesa have to be converted before handing back
+ # to the application), this is it. Fortunately, we don't
+ # have to worry about conditional value conversion - the
+ # functions that do (e.g. glGetFixedv()) are handled
+ # specially, outside this code generation.
+ #
+ # Whether we use incoming conversion or outgoing conversion
+ # is determined later - we only ever use one or the other.
+
+ if paramValueConversion == "none":
+ conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeIncoming.append(" %s[i] = (%s) converted_%s[i];" % (paramName, paramConvertToType, paramName))
+ conversionCodeIncoming.append(" }")
+ elif paramValueConversion == "some":
+ # We'll need a conditional variable to keep track of
+ # whether we're converting values or not.
+ if (" int convert_%s_value = 1;" % paramName) not in variables:
+ variables.append(" int convert_%s_value = 1;" % paramName)
+
+ # Write code based on that conditional.
+ conversionCodeIncoming.append(" if (convert_%s_value) {" % paramName)
+ conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeIncoming.append(" %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
+ conversionCodeIncoming.append(" }")
+ conversionCodeIncoming.append(" } else {")
+ conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeIncoming.append(" %s[i] = (%s) converted_%s[i];" % (paramName, paramBaseType, paramName))
+ conversionCodeIncoming.append(" }")
+ conversionCodeIncoming.append(" }")
+ else: # paramValueConversion == "all"
+ conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
+ conversionCodeIncoming.append(" %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
+ conversionCodeIncoming.append(" }")
+
+ # Call strings. The unusual " ".join() call will join the
+ # array of parameter modifiers with spaces as separators.
+ passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
+ passthroughCallString += ", converted_%s" % paramName
+
+ # endif conversion management
+
+ # Parameter checking. If the parameter has a specific list of
+ # valid values, we have to make sure that the passed-in values
+ # match these, or we make an error.
+ if len(paramValidValues) > 0:
+ # We're about to make a big switch statement with an
+ # error at the end. By default, the error is GL_INVALID_ENUM,
+ # unless we find a "case" statement in the middle with a
+ # non-GLenum value.
+ errorDefaultCase = "GL_INVALID_ENUM"
+
+ # This parameter has specific valid values. Make a big
+ # switch statement to handle it. Note that the original
+ # parameters are always what is checked, not the
+ # converted parameters.
+ switchCode.append(" switch(%s) {" % paramName)
+
+ for valueIndex in range(len(paramValidValues)):
+ (paramValue, dependentVecSize, dependentParamName, dependentValidValues, errorCode, valueConvert) = paramValidValues[valueIndex]
+
+ # We're going to need information on the dependent param
+ # as well.
+ if dependentParamName:
+ depParamIndex = apiutil.FindParamIndex(params, dependentParamName)
+ if depParamIndex == None:
+ sys.stderr.write("%s: can't find dependent param '%s' for function '%s'\n" % (program, dependentParamName, funcName))
+
+ (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = params[depParamIndex]
+ else:
+ (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = (None, None, None, None, [], None)
+
+ # This is a sneaky trick. It's valid syntax for a parameter
+ # that is *not* going to be converted to be declared
+ # with a dependent vector size; but in this case, the
+ # dependent vector size is unused and unnecessary.
+ # So check for this and ignore the dependent vector size
+ # if the parameter is not going to be converted.
+ if depParamConvertToType:
+ usedDependentVecSize = dependentVecSize
+ else:
+ usedDependentVecSize = None
+
+ # We'll peek ahead at the next parameter, to see whether
+ # we can combine cases
+ if valueIndex + 1 < len(paramValidValues) :
+ (nextParamValue, nextDependentVecSize, nextDependentParamName, nextDependentValidValues, nextErrorCode, nextValueConvert) = paramValidValues[valueIndex + 1]
+ if depParamConvertToType:
+ usedNextDependentVecSize = nextDependentVecSize
+ else:
+ usedNextDependentVecSize = None
+
+ # Create a case for this value. As a mnemonic,
+ # if we have a dependent vector size that we're ignoring,
+ # add it as a comment.
+ if usedDependentVecSize == None and dependentVecSize != None:
+ switchCode.append(" case %s: /* size %s */" % (paramValue, dependentVecSize))
+ else:
+ switchCode.append(" case %s:" % paramValue)
+
+ # If this is not a GLenum case, then switch our error
+ # if no value is matched to be GL_INVALID_VALUE instead
+ # of GL_INVALID_ENUM. (Yes, this does get confused
+ # if there are both values and GLenums in the same
+ # switch statement, which shouldn't happen.)
+ if paramValue[0:3] != "GL_":
+ errorDefaultCase = "GL_INVALID_VALUE"
+
+ # If all the remaining parameters are identical to the
+ # next set, then we're done - we'll just create the
+ # official code on the next pass through, and the two
+ # cases will share the code.
+ if valueIndex + 1 < len(paramValidValues) and usedDependentVecSize == usedNextDependentVecSize and dependentParamName == nextDependentParamName and dependentValidValues == nextDependentValidValues and errorCode == nextErrorCode and valueConvert == nextValueConvert:
+ continue
+
+ # Otherwise, we'll have to generate code for this case.
+ # Start off with a check: if there is a dependent parameter,
+ # and a list of valid values for that parameter, we need
+ # to generate an error if something other than one
+ # of those values is passed.
+ if len(dependentValidValues) > 0:
+ conditional=""
+
+ # If the parameter being checked is actually an array,
+ # check only its first element.
+ if depParamMaxVecSize == 0:
+ valueToCheck = dependentParamName
+ else:
+ valueToCheck = "%s[0]" % dependentParamName
+
+ for v in dependentValidValues:
+ conditional += " && %s != %s" % (valueToCheck, v)
+ switchCode.append(" if (%s) {" % conditional[4:])
+ if errorCode == None:
+ errorCode = "GL_INVALID_ENUM"
+ switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=0x%s)", %s);' % (errorCode, funcName, paramName, "%x", paramName))
+ switchCode.append(" %s;" % errorReturn)
+ switchCode.append(" }")
+ # endif there are dependent valid values
+
+ # The dependent parameter may require conditional
+ # value conversion. If it does, and we don't want
+ # to convert values, we'll have to generate code for that
+ if depParamValueConversion == "some" and valueConvert == "noconvert":
+ switchCode.append(" convert_%s_value = 0;" % dependentParamName)
+
+ # If there's a dependent vector size for this parameter
+ # that we're actually going to use (i.e. we need conversion),
+ # mark it.
+ if usedDependentVecSize:
+ switchCode.append(" n_%s = %s;" % (dependentParamName, dependentVecSize))
+
+ # In all cases, break out of the switch if any valid
+ # value is found.
+ switchCode.append(" break;")
+
+
+ # Need a default case to catch all the other, invalid
+ # parameter values. These will all generate errors.
+ switchCode.append(" default:")
+ if errorCode == None:
+ errorCode = "GL_INVALID_ENUM"
+ formatString = GetFormatString(paramType)
+ if formatString == None:
+ switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s)");' % (errorCode, funcName, paramName))
+ else:
+ switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=%s)", %s);' % (errorCode, funcName, paramName, formatString, paramName))
+ switchCode.append(" %s;" % errorReturn)
+
+ # End of our switch code.
+ switchCode.append(" }")
+
+ # endfor every recognized parameter value
+
+ # endfor every param
+
+ # Here, the passthroughDeclarationString and passthroughCallString
+ # are complete; remove the extra ", " at the front of each.
+ passthroughDeclarationString = passthroughDeclarationString[2:]
+ passthroughCallString = passthroughCallString[2:]
+ if not passthroughDeclarationString:
+ passthroughDeclarationString = "void"
+
+ # The Mesa functions are scattered across all the Mesa
+ # header files. The easiest way to manage declarations
+ # is to create them ourselves.
+ if funcName in allSpecials:
+ print "/* this function is special and is defined elsewhere */"
+ print "extern %s GL_APIENTRY %s(%s);" % (returnType, passthroughFuncName, passthroughDeclarationString)
+
+ # A function may be a core function (i.e. it exists in
+ # the core specification), a core addition (extension
+ # functions added officially to the core), a required
+ # extension (usually an extension for an earlier version
+ # that has been officially adopted), or an optional extension.
+ #
+ # Core functions have a simple category (e.g. "GLES1.1");
+ # we generate only a simple callback for them.
+ #
+ # Core additions have two category listings, one simple
+ # and one compound (e.g. ["GLES1.1", "GLES1.1:OES_fixed_point"]).
+ # We generate the core function, and also an extension function.
+ #
+ # Required extensions and implemented optional extensions
+ # have a single compound category "GLES1.1:OES_point_size_array".
+ # For these we generate just the extension function.
+ for categorySpec in apiutil.Categories(funcName):
+ compoundCategory = categorySpec.split(":")
+
+ # This category isn't for us, if the base category doesn't match
+ # our version
+ if compoundCategory[0] != version:
+ continue
+
+ # Otherwise, determine if we're writing code for a core
+ # function (no suffix) or an extension function.
+ if len(compoundCategory) == 1:
+ # This is a core function
+ extensionName = None
+ extensionSuffix = ""
+ else:
+ # This is an extension function. We'll need to append
+ # the extension suffix.
+ extensionName = compoundCategory[1]
+ extensionSuffix = extensionName.split("_")[0]
+ fullFuncName = funcPrefix + funcName + extensionSuffix
+
+ # Now the generated function. The text used to mark an API-level
+ # function, oddly, is version-specific.
+ if extensionName:
+ print "/* Extension %s */" % extensionName
+
+ if (not variables and
+ not switchCode and
+ not conversionCodeOutgoing and
+ not conversionCodeIncoming):
+ # pass through directly
+ print "#define %s %s" % (fullFuncName, passthroughFuncName)
+ print
+ continue
+
+ print "static %s GL_APIENTRY %s(%s)" % (returnType, fullFuncName, declarationString)
+ print "{"
+
+ # Start printing our code pieces. Start with any local
+ # variables we need. This unusual syntax joins the
+ # lines in the variables[] array with the "\n" separator.
+ if len(variables) > 0:
+ print "\n".join(variables) + "\n"
+
+ # If there's any sort of parameter checking or variable
+ # array sizing, the switch code will contain it.
+ if len(switchCode) > 0:
+ print "\n".join(switchCode) + "\n"
+
+ # In the case of an outgoing conversion (i.e. parameters must
+ # be converted before calling the underlying Mesa function),
+ # use the appropriate code.
+ if "get" not in props and len(conversionCodeOutgoing) > 0:
+ print "\n".join(conversionCodeOutgoing) + "\n"
+
+ # Call the Mesa function. Note that there are very few functions
+ # that return a value (i.e. returnType is not "void"), and that
+ # none of them require incoming translation; so we're safe
+ # to generate code that directly returns in those cases,
+ # even though it's not completely independent.
+
+ if returnType == "void":
+ print " %s(%s);" % (passthroughFuncName, passthroughCallString)
+ else:
+ print " return %s(%s);" % (passthroughFuncName, passthroughCallString)
+
+ # If the function is one that returns values (i.e. "get" in props),
+ # it might return values of a different type than we need, that
+ # require conversion before passing back to the application.
+ if "get" in props and len(conversionCodeIncoming) > 0:
+ print "\n".join(conversionCodeIncoming)
+
+ # All done.
+ print "}"
+ print
+ # end for each category provided for a function
+
+# end for each function
+
+print """
+#include "glapi/glapi.h"
+
+#if FEATURE_remap_table
+
+/* cannot include main/dispatch.h here */
+#define _GLAPI_USE_REMAP_TABLE
+#include "%sapi/main/glapidispatch.h"
+
+#define need_MESA_remap_table
+#include "%sapi/main/remap_helper.h"
+
+/* force SET_* macros to use the local remap table */
+#define driDispatchRemapTable remap_table
+static int remap_table[driDispatchRemapTable_size];
+
+static void
+init_remap_table(void)
+{
+ _glthread_DECLARE_STATIC_MUTEX(mutex);
+ static GLboolean initialized = GL_FALSE;
+ const struct gl_function_pool_remap *remap = MESA_remap_table_functions;
+ int i;
+
+ _glthread_LOCK_MUTEX(mutex);
+ if (initialized) {
+ _glthread_UNLOCK_MUTEX(mutex);
+ return;
+ }
+
+ for (i = 0; i < driDispatchRemapTable_size; i++) {
+ GLint offset;
+ const char *spec;
+
+ /* sanity check */
+ ASSERT(i == remap[i].remap_index);
+ spec = _mesa_function_pool + remap[i].pool_index;
+
+ offset = _mesa_map_function_spec(spec);
+ remap_table[i] = offset;
+ }
+ initialized = GL_TRUE;
+ _glthread_UNLOCK_MUTEX(mutex);
+}
+
+#else /* FEATURE_remap_table */
+
+/* cannot include main/dispatch.h here */
+#include "%sapi/main/glapidispatch.h"
+
+static INLINE void
+init_remap_table(void)
+{
+}
+
+#endif /* FEATURE_remap_table */
+
+struct _glapi_table *
+_mesa_create_exec_table_%s(void)
+{
+ struct _glapi_table *exec;
+
+ exec = _mesa_alloc_dispatch_table(_gloffset_COUNT);
+ if (exec == NULL)
+ return NULL;
+
+ init_remap_table();
+""" % (shortname, shortname, shortname, shortname)
+
+for func in keys:
+ prefix = "_es_" if func not in allSpecials else "_check_"
+ for spec in apiutil.Categories(func):
+ ext = spec.split(":")
+ # version does not match
+ if ext.pop(0) != version:
+ continue
+ entry = func
+ if ext:
+ suffix = ext[0].split("_")[0]
+ entry += suffix
+ print " SET_%s(exec, %s%s);" % (entry, prefix, entry)
+print ""
+print " return exec;"
+print "}"
+
+print """
+#endif /* FEATURE_%s */""" % (shortname.upper())