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