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