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