~ubuntu-branches/ubuntu/natty/mesa/natty-proposed

« back to all changes in this revision

Viewing changes to src/mesa/main/es_generator.py

  • Committer: Bazaar Package Importer
  • Author(s): Robert Hooker, Robert Hooker, Christopher James Halse Rogers
  • Date: 2010-09-14 08:55:40 UTC
  • mfrom: (1.2.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20100914085540-m4fpl0hdjlfd4jgz
Tags: 7.9~git20100909-0ubuntu1
[ Robert Hooker ]
* New upstream git snapshot up to commit 94118fe2d4b1e5 (LP: #631413)
* New features include ATI HD5xxx series support in r600, and a vastly
  improved glsl compiler.
* Remove pre-generated .pc's, use the ones generated at build time
  instead.
* Remove all references to mesa-utils now that its no longer shipped
  with the mesa source.
* Disable the experimental ARB_fragment_shader option by default on
  i915, it exposes incomplete functionality that breaks KDE compositing
  among other things. It can be enabled via driconf still. (LP: #628930).

[ Christopher James Halse Rogers ]
* debian/patches/04_osmesa_version.diff:
  - Refresh for new upstream
* Bugs fixed in this release:
  - Fixes severe rendering corruption in Unity on radeon (LP: #628727,
    LP: #596292, LP: #599741, LP: #630315, LP: #613694, LP: #599741).
  - Also fixes rendering in gnome-shell (LP: #578619).
  - Flickering in OpenGL apps on radeon (LP: #626943, LP: #610541).
  - Provides preliminary support for new intel chips (LP: #601052).
* debian/rules:
  - Update configure flags to match upstream reshuffling.
  - Explicitly remove gallium DRI drivers that we don't want to ship.
* Update debian/gbp.conf for this Maverick-specific packaging
* libegl1-mesa-dri-x11,kms: There are no longer separate kms or x11 drivers
  for EGL, libegl1-mesa-drivers now contains a single driver that provides
  both backends.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/glapi/glapioffsets.h"
 
224
#include "%sapi/glapi/glapidispatch.h"
 
225
 
 
226
#if FEATURE_remap_table
 
227
 
 
228
#if !FEATURE_GL
 
229
int driDispatchRemapTable[driDispatchRemapTable_size];
 
230
#endif
 
231
 
 
232
#define need_MESA_remap_table
 
233
 
 
234
#include "%sapi/main/remap_helper.h"
 
235
 
 
236
void
 
237
_mesa_init_remap_table_%s(void)
 
238
{
 
239
   _mesa_do_init_remap_table(_mesa_function_pool,
 
240
                             driDispatchRemapTable_size,
 
241
                             MESA_remap_table_functions);
 
242
}
 
243
 
 
244
void
 
245
_mesa_map_static_functions_%s(void)
 
246
{
 
247
}
 
248
 
 
249
#endif
 
250
 
 
251
typedef void (*_glapi_proc)(void); /* generic function pointer */
 
252
""" % (shortname, shortname, shortname, shortname, shortname, shortname);
 
253
 
 
254
# Finally we get to the all-important functions
 
255
print """/*************************************************************
 
256
 * Generated functions begin here
 
257
 */
 
258
"""
 
259
for funcName in keys:
 
260
    if verbose > 0: sys.stderr.write("%s: processing function %s\n" % (program, funcName))
 
261
 
 
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)
 
267
 
 
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"
 
274
    else:
 
275
        errorReturn = "return (%s) 0" % returnType
 
276
 
 
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.
 
283
    # 
 
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.
 
289
    #
 
290
    # variables: C code to create any local variables determined to
 
291
    # be necessary.
 
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
 
305
    variables = []
 
306
    conversionCodeOutgoing = []
 
307
    conversionCodeIncoming = []
 
308
    switchCode = []
 
309
 
 
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_"
 
318
        aliasprefix = "_es_"
 
319
    else:
 
320
        funcPrefix = "_es_"
 
321
        aliasprefix = apiutil.AliasPrefix(funcName)
 
322
    alias = apiutil.ConversionFunction(funcName)
 
323
    prefixOverride = apiutil.FunctionPrefix(funcName)
 
324
    if prefixOverride != "_mesa_":
 
325
        aliasprefix = apiutil.FunctionPrefix(funcName)
 
326
    if not alias:
 
327
        # There may still be a Mesa alias for the function
 
328
        if apiutil.Alias(funcName):
 
329
            passthroughFuncName = "%s%s" % (aliasprefix, apiutil.Alias(funcName))
 
330
        else:
 
331
            passthroughFuncName = "%s%s" % (aliasprefix, funcName)
 
332
    else: # a specific alias is provided
 
333
        passthroughFuncName = "%s%s" % (aliasprefix, alias)
 
334
 
 
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)
 
341
 
 
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
 
346
        # conversion.
 
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
 
353
 
 
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))
 
357
 
 
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)
 
367
 
 
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)))
 
376
 
 
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.
 
381
 
 
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
 
386
 
 
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;")
 
391
 
 
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))
 
398
 
 
399
            # This array will hold the actual converted values.
 
400
            variables.append("    %s converted_%s[%d];" % (paramConvertToType, paramName, paramMaxVecSize))
 
401
 
 
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)))
 
427
 
 
428
                conversionCodeOutgoing.append("    }")
 
429
 
 
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.
 
436
            #
 
437
            # Whether we use incoming conversion or outgoing conversion
 
438
            # is determined later - we only ever use one or the other.
 
439
 
 
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)
 
449
 
 
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("    }")
 
464
 
 
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
 
469
 
 
470
        # endif conversion management
 
471
 
 
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
 
479
            # non-GLenum value.
 
480
            errorDefaultCase = "GL_INVALID_ENUM"
 
481
 
 
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)
 
487
 
 
488
            for valueIndex in range(len(paramValidValues)):
 
489
                (paramValue, dependentVecSize, dependentParamName, dependentValidValues, errorCode, valueConvert) = paramValidValues[valueIndex]
 
490
 
 
491
                # We're going to need information on the dependent param
 
492
                # as well.
 
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))
 
497
 
 
498
                    (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = params[depParamIndex]
 
499
                else:
 
500
                    (depParamName, depParamType, depParamMaxVecSize, depParamConvertToType, depParamValidValues, depParamValueConversion) = (None, None, None, None, [], None)
 
501
 
 
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
 
510
                else:
 
511
                    usedDependentVecSize = None
 
512
 
 
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
 
519
                    else:
 
520
                        usedNextDependentVecSize = None
 
521
 
 
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))
 
527
                else:
 
528
                    switchCode.append("        case %s:" % paramValue)
 
529
 
 
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"
 
537
 
 
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:
 
543
                    continue
 
544
 
 
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:
 
551
                    conditional=""
 
552
 
 
553
                    # If the parameter being checked is actually an array,
 
554
                    # check only its first element.
 
555
                    if depParamMaxVecSize == 0:
 
556
                        valueToCheck = dependentParamName
 
557
                    else:
 
558
                        valueToCheck = "%s[0]" % dependentParamName
 
559
 
 
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
 
569
 
 
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)
 
575
 
 
576
                # If there's a dependent vector size for this parameter
 
577
                # that we're actually going to use (i.e. we need conversion),
 
578
                # mark it.
 
579
                if usedDependentVecSize:
 
580
                    switchCode.append("            n_%s = %s;" % (dependentParamName, dependentVecSize))
 
581
 
 
582
                # In all cases, break out of the switch if any valid
 
583
                # value is found.
 
584
                switchCode.append("            break;")
 
585
 
 
586
 
 
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))
 
595
            else:
 
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)
 
598
 
 
599
            # End of our switch code.
 
600
            switchCode.append("    }")
 
601
 
 
602
        # endfor every recognized parameter value
 
603
 
 
604
    # endfor every param
 
605
 
 
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"
 
612
 
 
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)
 
619
 
 
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.
 
625
    #
 
626
    # Core functions have a simple category (e.g. "GLES1.1");
 
627
    # we generate only a simple callback for them.
 
628
    #
 
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.
 
632
    #
 
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(":")
 
638
 
 
639
        # This category isn't for us, if the base category doesn't match
 
640
        # our version
 
641
        if compoundCategory[0] != version:
 
642
            continue
 
643
 
 
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
 
648
            extensionName = None
 
649
            extensionSuffix = ""
 
650
        else:
 
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
 
656
 
 
657
        # Now the generated function.  The text used to mark an API-level
 
658
        # function, oddly, is version-specific.
 
659
        if extensionName:
 
660
            print "/* Extension %s */" % extensionName
 
661
 
 
662
        if (not variables and
 
663
            not switchCode and
 
664
            not conversionCodeOutgoing and
 
665
            not conversionCodeIncoming):
 
666
            # pass through directly
 
667
            print "#define %s %s" % (fullFuncName, passthroughFuncName)
 
668
            print
 
669
            continue
 
670
 
 
671
        print "static %s GL_APIENTRY %s(%s)" % (returnType, fullFuncName, declarationString)
 
672
        print "{"
 
673
 
 
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"
 
679
 
 
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"
 
684
 
 
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"
 
690
 
 
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.
 
696
 
 
697
        if returnType == "void":
 
698
            print "    %s(%s);" % (passthroughFuncName, passthroughCallString)
 
699
        else:
 
700
            print "    return %s(%s);" % (passthroughFuncName, passthroughCallString)
 
701
 
 
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)
 
707
 
 
708
        # All done.
 
709
        print "}"
 
710
        print
 
711
    # end for each category provided for a function
 
712
 
 
713
# end for each function
 
714
 
 
715
print """
 
716
struct _glapi_table *
 
717
_mesa_create_exec_table_%s(void)
 
718
{
 
719
   struct _glapi_table *exec;
 
720
   exec = _mesa_alloc_dispatch_table(sizeof *exec);
 
721
   if (exec == NULL)
 
722
      return NULL;
 
723
 
 
724
""" % shortname
 
725
 
 
726
for func in keys:
 
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:
 
732
            continue
 
733
        entry = func
 
734
        if ext:
 
735
            suffix = ext[0].split("_")[0]
 
736
            entry += suffix
 
737
        print "    SET_%s(exec, %s%s);" % (entry, prefix, entry)
 
738
print ""
 
739
print "   return exec;"
 
740
print "}"
 
741
 
 
742
print """
 
743
#endif /* FEATURE_%s */""" % (shortname.upper())