1
#*************************************************************************
2
# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
12
# The above copyright notice and this permission notice shall be included
13
# in all copies or substantial portions of the Software.
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
22
#*************************************************************************
26
import APIspecutil as apiutil
28
# These dictionary entries are used for automatic conversion.
29
# The string will be used as a format string with the conversion
33
'GLdouble': "(GLdouble) (%s)",
34
'GLfixed' : "(GLint) (%s * 65536)",
37
'GLfloat': "(GLfloat) (%s / 65536.0f)",
38
'GLdouble': "(GLdouble) (%s / 65536.0)",
41
'GLfloat': "(GLfloat) (%s)",
42
'GLfixed': "(GLfixed) (%s * 65536)",
45
'GLclampd': "(GLclampd) (%s)",
46
'GLclampx': "(GLclampx) (%s * 65536)",
49
'GLclampf': "(GLclampf) (%s / 65536.0f)",
50
'GLclampd': "(GLclampd) (%s / 65536.0)",
53
'GLfloat': "(GLfloat) (%s / 255.0f)",
57
def GetBaseType(type):
58
typeTokens = type.split(' ')
62
if t in ['const', '*']:
63
typeModifiers.append(t)
66
return (baseType, typeModifiers)
68
def ConvertValue(value, fromType, toType):
69
"""Returns a string that represents the given parameter string,
70
type-converted if necessary."""
72
if not Converters.has_key(fromType):
73
print >> sys.stderr, "No base converter for type '%s' found. Ignoring." % fromType
76
if not Converters[fromType].has_key(toType):
77
print >> sys.stderr, "No converter found for type '%s' to type '%s'. Ignoring." % (fromType, toType)
80
# This part is simple. Return the proper conversion.
81
conversionString = Converters[fromType][toType]
82
return conversionString % value
88
'GLbitfield' : '0x%x',
90
def GetFormatString(type):
91
if FormatStrings.has_key(type):
92
return FormatStrings[type]
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 = {
103
'description' : 'GLES1.1 functions',
104
'header' : 'GLES/gl.h',
105
'extheader' : 'GLES/glext.h',
109
'description' : 'GLES2.0 functions',
110
'header' : 'GLES2/gl2.h',
111
'extheader' : 'GLES2/gl2ext.h',
117
######################################################################
118
# Main code for the script begins here.
120
# Get the name of the program (without the directory part) for use in
122
program = os.path.basename(sys.argv[0])
126
functionList = "APIspec.xml"
129
# Allow for command-line switches
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))
138
for option, optarg in optlist:
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)
154
functionList = optarg
156
# Beyond switches, we support no further command-line arguments
158
sys.stderr.write("%s: only switch arguments are supported - use -h for help\n" % program)
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))
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']
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
177
keys = apiutil.GetAllFunctions(functionList, version)
179
allSpecials = apiutil.AllSpecials()
181
print """/* DO NOT EDIT *************************************************
182
* THIS FILE AUTOMATICALLY GENERATED BY THE %s SCRIPT
183
* API specification file: %s
187
""" % (program, functionList, version, time.strftime("%Y-%m-%d %H:%M:%S"))
189
# The headers we choose are version-specific.
193
#include "main/mfeatures.h"
196
""" % (versionHeader, versionExtHeader, shortname.upper())
198
# Everyone needs these types.
200
/* These types are needed for the Mesa veneer, but are not defined in
201
* the standard GLES headers.
203
typedef double GLdouble;
204
typedef double GLclampd;
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, ... );
210
#include "main/compiler.h"
211
#include "main/api_exec.h"
212
#include "main/remap.h"
214
/* cannot include main/dispatch.h here */
216
#define _GLAPI_USE_REMAP_TABLE
218
/* glapi uses GLAPIENTRY while GLES headers define GL_APIENTRY */
220
#define GLAPIENTRY GL_APIENTRY
222
#include "%sapi/glapi/glapitable.h"
223
#include "%sapi/glapi/glapioffsets.h"
224
#include "%sapi/glapi/glapidispatch.h"
226
#if FEATURE_remap_table
229
int driDispatchRemapTable[driDispatchRemapTable_size];
232
#define need_MESA_remap_table
234
#include "%sapi/main/remap_helper.h"
237
_mesa_init_remap_table_%s(void)
239
_mesa_do_init_remap_table(_mesa_function_pool,
240
driDispatchRemapTable_size,
241
MESA_remap_table_functions);
245
_mesa_map_static_functions_%s(void)
251
typedef void (*_glapi_proc)(void); /* generic function pointer */
252
""" % (shortname, shortname, shortname, shortname, shortname, shortname);
254
# Finally we get to the all-important functions
255
print """/*************************************************************
256
* Generated functions begin here
259
for funcName in keys:
260
if verbose > 0: sys.stderr.write("%s: processing function %s\n" % (program, funcName))
262
# start figuring out what this function will look like.
263
returnType = apiutil.ReturnType(funcName)
264
props = apiutil.Properties(funcName)
265
params = apiutil.Parameters(funcName)
266
declarationString = apiutil.MakeDeclarationString(params)
268
# In case of error, a function may have to return. Make
269
# sure we have valid return values in this case.
270
if returnType == "void":
271
errorReturn = "return"
272
elif returnType == "GLboolean":
273
errorReturn = "return GL_FALSE"
275
errorReturn = "return (%s) 0" % returnType
277
# These are the output of this large calculation block.
278
# passthroughDeclarationString: a typed set of parameters that
279
# will be used to create the "extern" reference for the
280
# underlying Mesa or support function. Note that as generated
281
# these have an extra ", " at the beginning, which will be
282
# removed before use.
284
# passthroughDeclarationString: an untyped list of parameters
285
# that will be used to call the underlying Mesa or support
286
# function (including references to converted parameters).
287
# This will also be generated with an extra ", " at the
288
# beginning, which will be removed before use.
290
# variables: C code to create any local variables determined to
292
# conversionCodeOutgoing: C code to convert application parameters
293
# to a necessary type before calling the underlying support code.
294
# May be empty if no conversion is required.
295
# conversionCodeIncoming: C code to do the converse: convert
296
# values returned by underlying Mesa code to the types needed
297
# by the application.
298
# Note that *either* the conversionCodeIncoming will be used (for
299
# generated query functions), *or* the conversionCodeOutgoing will
300
# be used (for generated non-query functions), never both.
301
passthroughFuncName = ""
302
passthroughDeclarationString = ""
303
passthroughCallString = ""
304
prefixOverride = None
306
conversionCodeOutgoing = []
307
conversionCodeIncoming = []
310
# Calculate the name of the underlying support function to call.
311
# By default, the passthrough function is named _mesa_<funcName>.
312
# We're allowed to override the prefix and/or the function name
313
# for each function record, though. The "ConversionFunction"
314
# utility is poorly named, BTW...
315
if funcName in allSpecials:
316
# perform checks and pass through
317
funcPrefix = "_check_"
321
aliasprefix = apiutil.AliasPrefix(funcName)
322
alias = apiutil.ConversionFunction(funcName)
323
prefixOverride = apiutil.FunctionPrefix(funcName)
324
if prefixOverride != "_mesa_":
325
aliasprefix = apiutil.FunctionPrefix(funcName)
327
# There may still be a Mesa alias for the function
328
if apiutil.Alias(funcName):
329
passthroughFuncName = "%s%s" % (aliasprefix, apiutil.Alias(funcName))
331
passthroughFuncName = "%s%s" % (aliasprefix, funcName)
332
else: # a specific alias is provided
333
passthroughFuncName = "%s%s" % (aliasprefix, alias)
335
# Look at every parameter: each one may have only specific
336
# allowed values, or dependent parameters to check, or
337
# variant-sized vector arrays to calculate
338
for (paramName, paramType, paramMaxVecSize, paramConvertToType, paramValidValues, paramValueConversion) in params:
339
# We'll need this below if we're doing conversions
340
(paramBaseType, paramTypeModifiers) = GetBaseType(paramType)
342
# Conversion management.
343
# We'll handle three cases, easiest to hardest: a parameter
344
# that doesn't require conversion, a scalar parameter that
345
# requires conversion, and a vector parameter that requires
347
if paramConvertToType == None:
348
# Unconverted parameters are easy, whether they're vector
349
# or scalar - just add them to the call list. No conversions
350
# or anything to worry about.
351
passthroughDeclarationString += ", %s %s" % (paramType, paramName)
352
passthroughCallString += ", %s" % paramName
354
elif paramMaxVecSize == 0: # a scalar parameter that needs conversion
355
# A scalar to hold a converted parameter
356
variables.append(" %s converted_%s;" % (paramConvertToType, paramName))
358
# Outgoing conversion depends on whether we have to conditionally
359
# perform value conversion.
360
if paramValueConversion == "none":
361
conversionCodeOutgoing.append(" converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
362
elif paramValueConversion == "some":
363
# We'll need a conditional variable to keep track of
364
# whether we're converting values or not.
365
if (" int convert_%s_value = 1;" % paramName) not in variables:
366
variables.append(" int convert_%s_value = 1;" % paramName)
368
# Write code based on that conditional.
369
conversionCodeOutgoing.append(" if (convert_%s_value) {" % paramName)
370
conversionCodeOutgoing.append(" converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
371
conversionCodeOutgoing.append(" } else {")
372
conversionCodeOutgoing.append(" converted_%s = (%s) %s;" % (paramName, paramConvertToType, paramName))
373
conversionCodeOutgoing.append(" }")
374
else: # paramValueConversion == "all"
375
conversionCodeOutgoing.append(" converted_%s = %s;" % (paramName, ConvertValue(paramName, paramBaseType, paramConvertToType)))
377
# Note that there can be no incoming conversion for a
378
# scalar parameter; changing the scalar will only change
379
# the local value, and won't ultimately change anything
380
# that passes back to the application.
382
# Call strings. The unusual " ".join() call will join the
383
# array of parameter modifiers with spaces as separators.
384
passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
385
passthroughCallString += ", converted_%s" % paramName
387
else: # a vector parameter that needs conversion
388
# We'll need an index variable for conversions
389
if " register unsigned int i;" not in variables:
390
variables.append(" register unsigned int i;")
392
# This variable will hold the (possibly variant) size of
393
# this array needing conversion. By default, we'll set
394
# it to the maximal size (which is correct for functions
395
# with a constant-sized vector parameter); for true
396
# variant arrays, we'll modify it with other code.
397
variables.append(" unsigned int n_%s = %d;" % (paramName, paramMaxVecSize))
399
# This array will hold the actual converted values.
400
variables.append(" %s converted_%s[%d];" % (paramConvertToType, paramName, paramMaxVecSize))
402
# Again, we choose the conversion code based on whether we
403
# have to always convert values, never convert values, or
404
# conditionally convert values.
405
if paramValueConversion == "none":
406
conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
407
conversionCodeOutgoing.append(" converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
408
conversionCodeOutgoing.append(" }")
409
elif paramValueConversion == "some":
410
# We'll need a conditional variable to keep track of
411
# whether we're converting values or not.
412
if (" int convert_%s_value = 1;" % paramName) not in variables:
413
variables.append(" int convert_%s_value = 1;" % paramName)
414
# Write code based on that conditional.
415
conversionCodeOutgoing.append(" if (convert_%s_value) {" % paramName)
416
conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
417
conversionCodeOutgoing.append(" converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
418
conversionCodeOutgoing.append(" }")
419
conversionCodeOutgoing.append(" } else {")
420
conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
421
conversionCodeOutgoing.append(" converted_%s[i] = (%s) %s[i];" % (paramName, paramConvertToType, paramName))
422
conversionCodeOutgoing.append(" }")
423
conversionCodeOutgoing.append(" }")
424
else: # paramValueConversion == "all"
425
conversionCodeOutgoing.append(" for (i = 0; i < n_%s; i++) {" % paramName)
426
conversionCodeOutgoing.append(" converted_%s[i] = %s;" % (paramName, ConvertValue("%s[i]" % paramName, paramBaseType, paramConvertToType)))
428
conversionCodeOutgoing.append(" }")
430
# If instead we need an incoming conversion (i.e. results
431
# from Mesa have to be converted before handing back
432
# to the application), this is it. Fortunately, we don't
433
# have to worry about conditional value conversion - the
434
# functions that do (e.g. glGetFixedv()) are handled
435
# specially, outside this code generation.
437
# Whether we use incoming conversion or outgoing conversion
438
# is determined later - we only ever use one or the other.
440
if paramValueConversion == "none":
441
conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
442
conversionCodeIncoming.append(" %s[i] = (%s) converted_%s[i];" % (paramName, paramConvertToType, paramName))
443
conversionCodeIncoming.append(" }")
444
elif paramValueConversion == "some":
445
# We'll need a conditional variable to keep track of
446
# whether we're converting values or not.
447
if (" int convert_%s_value = 1;" % paramName) not in variables:
448
variables.append(" int convert_%s_value = 1;" % paramName)
450
# Write code based on that conditional.
451
conversionCodeIncoming.append(" if (convert_%s_value) {" % paramName)
452
conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
453
conversionCodeIncoming.append(" %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
454
conversionCodeIncoming.append(" }")
455
conversionCodeIncoming.append(" } else {")
456
conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
457
conversionCodeIncoming.append(" %s[i] = (%s) converted_%s[i];" % (paramName, paramBaseType, paramName))
458
conversionCodeIncoming.append(" }")
459
conversionCodeIncoming.append(" }")
460
else: # paramValueConversion == "all"
461
conversionCodeIncoming.append(" for (i = 0; i < n_%s; i++) {" % paramName)
462
conversionCodeIncoming.append(" %s[i] = %s;" % (paramName, ConvertValue("converted_%s[i]" % paramName, paramConvertToType, paramBaseType)))
463
conversionCodeIncoming.append(" }")
465
# Call strings. The unusual " ".join() call will join the
466
# array of parameter modifiers with spaces as separators.
467
passthroughDeclarationString += ", %s %s %s" % (paramConvertToType, " ".join(paramTypeModifiers), paramName)
468
passthroughCallString += ", converted_%s" % paramName
470
# endif conversion management
472
# Parameter checking. If the parameter has a specific list of
473
# valid values, we have to make sure that the passed-in values
474
# match these, or we make an error.
475
if len(paramValidValues) > 0:
476
# We're about to make a big switch statement with an
477
# error at the end. By default, the error is GL_INVALID_ENUM,
478
# unless we find a "case" statement in the middle with a
480
errorDefaultCase = "GL_INVALID_ENUM"
482
# This parameter has specific valid values. Make a big
483
# switch statement to handle it. Note that the original
484
# parameters are always what is checked, not the
485
# converted parameters.
486
switchCode.append(" switch(%s) {" % paramName)
488
for valueIndex in range(len(paramValidValues)):
489
(paramValue, dependentVecSize, dependentParamName, dependentValidValues, errorCode, valueConvert) = paramValidValues[valueIndex]
491
# We're going to need information on the dependent param
493
if dependentParamName:
494
depParamIndex = apiutil.FindParamIndex(params, dependentParamName)
495
if depParamIndex == None:
496
sys.stderr.write("%s: can't find dependent param '%s' for function '%s'\n" % (program, dependentParamName, funcName))
498
(depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = params[depParamIndex]
500
(depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = (None, None, None, None, [], None)
502
# This is a sneaky trick. It's valid syntax for a parameter
503
# that is *not* going to be converted to be declared
504
# with a dependent vector size; but in this case, the
505
# dependent vector size is unused and unnecessary.
506
# So check for this and ignore the dependent vector size
507
# if the parameter is not going to be converted.
508
if depParamConvertToType:
509
usedDependentVecSize = dependentVecSize
511
usedDependentVecSize = None
513
# We'll peek ahead at the next parameter, to see whether
514
# we can combine cases
515
if valueIndex + 1 < len(paramValidValues) :
516
(nextParamValue, nextDependentVecSize, nextDependentParamName, nextDependentValidValues, nextErrorCode, nextValueConvert) = paramValidValues[valueIndex + 1]
517
if depParamConvertToType:
518
usedNextDependentVecSize = nextDependentVecSize
520
usedNextDependentVecSize = None
522
# Create a case for this value. As a mnemonic,
523
# if we have a dependent vector size that we're ignoring,
524
# add it as a comment.
525
if usedDependentVecSize == None and dependentVecSize != None:
526
switchCode.append(" case %s: /* size %s */" % (paramValue, dependentVecSize))
528
switchCode.append(" case %s:" % paramValue)
530
# If this is not a GLenum case, then switch our error
531
# if no value is matched to be GL_INVALID_VALUE instead
532
# of GL_INVALID_ENUM. (Yes, this does get confused
533
# if there are both values and GLenums in the same
534
# switch statement, which shouldn't happen.)
535
if paramValue[0:3] != "GL_":
536
errorDefaultCase = "GL_INVALID_VALUE"
538
# If all the remaining parameters are identical to the
539
# next set, then we're done - we'll just create the
540
# official code on the next pass through, and the two
541
# cases will share the code.
542
if valueIndex + 1 < len(paramValidValues) and usedDependentVecSize == usedNextDependentVecSize and dependentParamName == nextDependentParamName and dependentValidValues == nextDependentValidValues and errorCode == nextErrorCode and valueConvert == nextValueConvert:
545
# Otherwise, we'll have to generate code for this case.
546
# Start off with a check: if there is a dependent parameter,
547
# and a list of valid values for that parameter, we need
548
# to generate an error if something other than one
549
# of those values is passed.
550
if len(dependentValidValues) > 0:
553
# If the parameter being checked is actually an array,
554
# check only its first element.
555
if depParamMaxVecSize == 0:
556
valueToCheck = dependentParamName
558
valueToCheck = "%s[0]" % dependentParamName
560
for v in dependentValidValues:
561
conditional += " && %s != %s" % (valueToCheck, v)
562
switchCode.append(" if (%s) {" % conditional[4:])
563
if errorCode == None:
564
errorCode = "GL_INVALID_ENUM"
565
switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=0x%s)", %s);' % (errorCode, funcName, paramName, "%x", paramName))
566
switchCode.append(" %s;" % errorReturn)
567
switchCode.append(" }")
568
# endif there are dependent valid values
570
# The dependent parameter may require conditional
571
# value conversion. If it does, and we don't want
572
# to convert values, we'll have to generate code for that
573
if depParamValueConversion == "some" and valueConvert == "noconvert":
574
switchCode.append(" convert_%s_value = 0;" % dependentParamName)
576
# If there's a dependent vector size for this parameter
577
# that we're actually going to use (i.e. we need conversion),
579
if usedDependentVecSize:
580
switchCode.append(" n_%s = %s;" % (dependentParamName, dependentVecSize))
582
# In all cases, break out of the switch if any valid
584
switchCode.append(" break;")
587
# Need a default case to catch all the other, invalid
588
# parameter values. These will all generate errors.
589
switchCode.append(" default:")
590
if errorCode == None:
591
errorCode = "GL_INVALID_ENUM"
592
formatString = GetFormatString(paramType)
593
if formatString == None:
594
switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s)");' % (errorCode, funcName, paramName))
596
switchCode.append(' _mesa_error(_mesa_get_current_context(), %s, "gl%s(%s=%s)", %s);' % (errorCode, funcName, paramName, formatString, paramName))
597
switchCode.append(" %s;" % errorReturn)
599
# End of our switch code.
600
switchCode.append(" }")
602
# endfor every recognized parameter value
606
# Here, the passthroughDeclarationString and passthroughCallString
607
# are complete; remove the extra ", " at the front of each.
608
passthroughDeclarationString = passthroughDeclarationString[2:]
609
passthroughCallString = passthroughCallString[2:]
610
if not passthroughDeclarationString:
611
passthroughDeclarationString = "void"
613
# The Mesa functions are scattered across all the Mesa
614
# header files. The easiest way to manage declarations
615
# is to create them ourselves.
616
if funcName in allSpecials:
617
print "/* this function is special and is defined elsewhere */"
618
print "extern %s GL_APIENTRY %s(%s);" % (returnType, passthroughFuncName, passthroughDeclarationString)
620
# A function may be a core function (i.e. it exists in
621
# the core specification), a core addition (extension
622
# functions added officially to the core), a required
623
# extension (usually an extension for an earlier version
624
# that has been officially adopted), or an optional extension.
626
# Core functions have a simple category (e.g. "GLES1.1");
627
# we generate only a simple callback for them.
629
# Core additions have two category listings, one simple
630
# and one compound (e.g. ["GLES1.1", "GLES1.1:OES_fixed_point"]).
631
# We generate the core function, and also an extension function.
633
# Required extensions and implemented optional extensions
634
# have a single compound category "GLES1.1:OES_point_size_array".
635
# For these we generate just the extension function.
636
for categorySpec in apiutil.Categories(funcName):
637
compoundCategory = categorySpec.split(":")
639
# This category isn't for us, if the base category doesn't match
641
if compoundCategory[0] != version:
644
# Otherwise, determine if we're writing code for a core
645
# function (no suffix) or an extension function.
646
if len(compoundCategory) == 1:
647
# This is a core function
651
# This is an extension function. We'll need to append
652
# the extension suffix.
653
extensionName = compoundCategory[1]
654
extensionSuffix = extensionName.split("_")[0]
655
fullFuncName = funcPrefix + funcName + extensionSuffix
657
# Now the generated function. The text used to mark an API-level
658
# function, oddly, is version-specific.
660
print "/* Extension %s */" % extensionName
662
if (not variables and
664
not conversionCodeOutgoing and
665
not conversionCodeIncoming):
666
# pass through directly
667
print "#define %s %s" % (fullFuncName, passthroughFuncName)
671
print "static %s GL_APIENTRY %s(%s)" % (returnType, fullFuncName, declarationString)
674
# Start printing our code pieces. Start with any local
675
# variables we need. This unusual syntax joins the
676
# lines in the variables[] array with the "\n" separator.
677
if len(variables) > 0:
678
print "\n".join(variables) + "\n"
680
# If there's any sort of parameter checking or variable
681
# array sizing, the switch code will contain it.
682
if len(switchCode) > 0:
683
print "\n".join(switchCode) + "\n"
685
# In the case of an outgoing conversion (i.e. parameters must
686
# be converted before calling the underlying Mesa function),
687
# use the appropriate code.
688
if "get" not in props and len(conversionCodeOutgoing) > 0:
689
print "\n".join(conversionCodeOutgoing) + "\n"
691
# Call the Mesa function. Note that there are very few functions
692
# that return a value (i.e. returnType is not "void"), and that
693
# none of them require incoming translation; so we're safe
694
# to generate code that directly returns in those cases,
695
# even though it's not completely independent.
697
if returnType == "void":
698
print " %s(%s);" % (passthroughFuncName, passthroughCallString)
700
print " return %s(%s);" % (passthroughFuncName, passthroughCallString)
702
# If the function is one that returns values (i.e. "get" in props),
703
# it might return values of a different type than we need, that
704
# require conversion before passing back to the application.
705
if "get" in props and len(conversionCodeIncoming) > 0:
706
print "\n".join(conversionCodeIncoming)
711
# end for each category provided for a function
713
# end for each function
716
struct _glapi_table *
717
_mesa_create_exec_table_%s(void)
719
struct _glapi_table *exec;
720
exec = _mesa_alloc_dispatch_table(sizeof *exec);
727
prefix = "_es_" if func not in allSpecials else "_check_"
728
for spec in apiutil.Categories(func):
729
ext = spec.split(":")
730
# version does not match
731
if ext.pop(0) != version:
735
suffix = ext[0].split("_")[0]
737
print " SET_%s(exec, %s%s);" % (entry, prefix, entry)
739
print " return exec;"
743
#endif /* FEATURE_%s */""" % (shortname.upper())