2004-05-18 18:33:40 +00:00
|
|
|
#!/usr/bin/python2
|
|
|
|
|
|
2005-01-07 02:39:09 +00:00
|
|
|
# (C) Copyright IBM Corporation 2004, 2005
|
2004-05-18 18:33:40 +00:00
|
|
|
# All Rights Reserved.
|
|
|
|
|
#
|
|
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
# copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
# to deal in the Software without restriction, including without limitation
|
|
|
|
|
# on the rights to use, copy, modify, merge, publish, distribute, sub
|
|
|
|
|
# license, and/or sell copies of the Software, and to permit persons to whom
|
|
|
|
|
# the Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
#
|
|
|
|
|
# The above copyright notice and this permission notice (including the next
|
|
|
|
|
# paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
# Software.
|
|
|
|
|
#
|
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
# IN THE SOFTWARE.
|
|
|
|
|
#
|
|
|
|
|
# Authors:
|
|
|
|
|
# Ian Romanick <idr@us.ibm.com>
|
|
|
|
|
|
|
|
|
|
from xml.sax import saxutils
|
|
|
|
|
from xml.sax import make_parser
|
|
|
|
|
from xml.sax.handler import feature_namespaces
|
|
|
|
|
|
2004-10-28 21:11:02 +00:00
|
|
|
import re
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-04-14 23:00:34 +00:00
|
|
|
def is_attr_true( attrs, name ):
|
|
|
|
|
"""Read a name value from an element's attributes.
|
|
|
|
|
|
|
|
|
|
The value read from the attribute list must be either 'true' or
|
|
|
|
|
'false'. If the value is 'false', zero will be returned. If the
|
|
|
|
|
value is 'true', non-zero will be returned. An exception will be
|
|
|
|
|
raised for any other value."""
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
value = attrs.get((None, name), "false")
|
2005-04-14 23:00:34 +00:00
|
|
|
if value == "true":
|
|
|
|
|
return 1
|
|
|
|
|
elif value == "false":
|
|
|
|
|
return 0
|
|
|
|
|
else:
|
|
|
|
|
raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name))
|
|
|
|
|
|
|
|
|
|
|
2005-04-18 19:42:23 +00:00
|
|
|
def parse_GL_API( handler, file_name ):
|
|
|
|
|
"""Boiler-plate code to create an XML parser and use it.
|
|
|
|
|
|
|
|
|
|
Creates an XML parser and uses that parser with the application
|
|
|
|
|
supplied SAX callback, which should be derived from
|
|
|
|
|
FilterGLAPISpecBase.
|
|
|
|
|
"""
|
|
|
|
|
parser = make_parser()
|
|
|
|
|
parser.setFeature(feature_namespaces, 1)
|
|
|
|
|
parser.setContentHandler( handler )
|
|
|
|
|
|
|
|
|
|
handler.printHeader()
|
|
|
|
|
parser.parse( file_name )
|
|
|
|
|
|
|
|
|
|
handler.printFooter()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
class glItem:
|
|
|
|
|
"""Generic class on which all other API entity types are based."""
|
|
|
|
|
|
|
|
|
|
def __init__(self, tag_name, name, context):
|
|
|
|
|
self.name = name
|
|
|
|
|
self.category = context.get_category_define()
|
|
|
|
|
self.context = context
|
|
|
|
|
self.tag_name = tag_name
|
|
|
|
|
|
|
|
|
|
context.append(tag_name, self)
|
|
|
|
|
return
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
def startElementNS(self, name, qname, attrs):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Generic startElement handler.
|
|
|
|
|
|
|
|
|
|
The startElement handler is called for all elements except
|
|
|
|
|
the one that starts the object. For a foo element, the
|
|
|
|
|
XML "<foo><bar/></foo>" would cause the startElement handler
|
|
|
|
|
to be called once, but the endElement handler would be called
|
|
|
|
|
twice."""
|
2004-05-18 18:33:40 +00:00
|
|
|
return
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
def endElementNS(self, name, qname):
|
2004-05-18 18:33:40 +00:00
|
|
|
"""Generic endElement handler.
|
|
|
|
|
|
|
|
|
|
Generic endElement handler. Returns 1 if the tag containing
|
|
|
|
|
the object is complete. Otherwise 0 is returned. All
|
|
|
|
|
derived class endElement handlers should call this method. If
|
|
|
|
|
the name of the ending tag is the same as the tag that
|
|
|
|
|
started this object, the object is assumed to be complete.
|
|
|
|
|
|
|
|
|
|
This fails if a tag can contain another tag with the same
|
|
|
|
|
name. The XML "<foo><foo/><bar/></foo>" would fail. The
|
2004-05-19 23:33:08 +00:00
|
|
|
object would end before the bar tag was processed.
|
|
|
|
|
|
|
|
|
|
The endElement handler is called for every end element
|
|
|
|
|
associated with an object, even the element that started the
|
|
|
|
|
object. See the description of startElement an example."""
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
if name == (None, self.tag_name):
|
2004-05-18 18:33:40 +00:00
|
|
|
return 1
|
|
|
|
|
else:
|
|
|
|
|
return 0
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
def get_category_define(self):
|
|
|
|
|
return self.category
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
|
|
|
|
|
class glEnum( glItem ):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Subclass of glItem for representing GL enumerants.
|
|
|
|
|
|
|
|
|
|
This class is not complete, and is not really used yet."""
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def __init__(self, context, name, attrs):
|
2005-04-18 19:16:07 +00:00
|
|
|
self.value = int(attrs.get((None, 'value'), "0x0000"), 0)
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
enum_name = "GL_" + attrs.get((None, 'name'), None)
|
2004-05-18 18:33:40 +00:00
|
|
|
glItem.__init__(self, name, enum_name, context)
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
temp = attrs.get((None, 'count'), None)
|
2005-03-17 21:48:37 +00:00
|
|
|
self.default_count = 0
|
|
|
|
|
if temp == "?":
|
|
|
|
|
self.default_count = -1
|
|
|
|
|
elif temp:
|
2005-01-25 01:20:11 +00:00
|
|
|
try:
|
|
|
|
|
c = int(temp)
|
|
|
|
|
except Exception,e:
|
|
|
|
|
raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
|
|
|
|
|
|
|
|
|
|
self.default_count = c
|
|
|
|
|
return
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-01-24 21:29:13 +00:00
|
|
|
def process_attributes(self, attrs):
|
2005-04-18 19:16:07 +00:00
|
|
|
name = attrs.get((None, 'name'), None)
|
2005-01-24 21:29:13 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
temp = attrs.get((None, 'count'), None)
|
2005-01-25 01:20:11 +00:00
|
|
|
if temp == None:
|
|
|
|
|
c = self.default_count
|
|
|
|
|
else:
|
|
|
|
|
try:
|
|
|
|
|
c = int(temp)
|
|
|
|
|
except Exception,e:
|
|
|
|
|
raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
mode_str = attrs.get((None, 'mode'), "set")
|
2005-01-25 01:20:11 +00:00
|
|
|
if mode_str == "set":
|
|
|
|
|
mode = 1
|
|
|
|
|
elif mode_str == "get":
|
|
|
|
|
mode = 0
|
|
|
|
|
else:
|
|
|
|
|
raise RuntimeError("Invalid mode '%s' for function '%s' in enum '%s'." % (mode_str, self.context.name, self.name))
|
2005-01-24 21:29:13 +00:00
|
|
|
|
2005-01-25 01:20:11 +00:00
|
|
|
return [name, c, mode]
|
2004-05-18 18:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class glType( glItem ):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Subclass of glItem for representing GL types."""
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def __init__(self, context, name, attrs):
|
2005-04-18 19:16:07 +00:00
|
|
|
self.size = int(attrs.get((None, 'size'), "0"))
|
|
|
|
|
self.glx_name = attrs.get((None, 'glx_name'), "")
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
type_name = "GL" + attrs.get((None, 'name'), None)
|
2004-05-18 18:33:40 +00:00
|
|
|
glItem.__init__(self, name, type_name, context)
|
|
|
|
|
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
class glParameter( glItem ):
|
|
|
|
|
"""Parameter of a glFunction."""
|
2004-05-18 18:33:40 +00:00
|
|
|
p_type = None
|
|
|
|
|
p_type_string = ""
|
|
|
|
|
p_count = 0
|
|
|
|
|
counter = None
|
|
|
|
|
is_output = 0
|
|
|
|
|
is_counter = 0
|
|
|
|
|
is_pointer = 0
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
def __init__(self, context, name, attrs):
|
2005-04-18 19:16:07 +00:00
|
|
|
p_name = attrs.get((None, 'name'), None)
|
|
|
|
|
self.p_type_string = attrs.get((None, 'type'), None)
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
temp = attrs.get((None, 'variable_param'), None)
|
2005-02-02 00:54:45 +00:00
|
|
|
if temp:
|
2005-04-14 23:03:44 +00:00
|
|
|
self.count_parameter_list = temp.split( ' ' )
|
2005-02-01 00:13:04 +00:00
|
|
|
else:
|
|
|
|
|
self.count_parameter_list = []
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
self.p_type = context.context.find_type(self.p_type_string)
|
|
|
|
|
if self.p_type == None:
|
|
|
|
|
raise RuntimeError("Unknown type '%s' in function '%s'." % (self.p_type_string, context.name))
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
# The count tag can be either a numeric string or the name of
|
|
|
|
|
# a variable. If it is the name of a variable, the int(c)
|
|
|
|
|
# statement will throw an exception, and the except block will
|
|
|
|
|
# take over.
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
c = attrs.get((None, 'count'), "0")
|
2004-05-18 18:33:40 +00:00
|
|
|
try:
|
|
|
|
|
self.p_count = int(c)
|
2004-05-19 23:33:08 +00:00
|
|
|
self.counter = None
|
2004-05-18 18:33:40 +00:00
|
|
|
except Exception,e:
|
|
|
|
|
self.p_count = 0
|
|
|
|
|
self.counter = c
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
self.count_scale = int(attrs.get((None, 'count_scale'), "1"))
|
|
|
|
|
|
2005-04-14 23:00:34 +00:00
|
|
|
self.is_counter = is_attr_true( attrs, 'counter' )
|
|
|
|
|
self.is_output = is_attr_true( attrs, 'output' )
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-01-07 02:39:09 +00:00
|
|
|
# Pixel data has special parameters.
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
self.width = attrs.get((None, 'img_width'), None)
|
|
|
|
|
self.height = attrs.get((None, 'img_height'), None)
|
|
|
|
|
self.depth = attrs.get((None, 'img_depth'), None)
|
|
|
|
|
self.extent = attrs.get((None, 'img_extent'), None)
|
2005-01-07 02:39:09 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
self.img_xoff = attrs.get((None, 'img_xoff'), None)
|
|
|
|
|
self.img_yoff = attrs.get((None, 'img_yoff'), None)
|
|
|
|
|
self.img_zoff = attrs.get((None, 'img_zoff'), None)
|
|
|
|
|
self.img_woff = attrs.get((None, 'img_woff'), None)
|
2005-01-07 02:39:09 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
self.img_format = attrs.get((None, 'img_format'), None)
|
|
|
|
|
self.img_type = attrs.get((None, 'img_type'), None)
|
|
|
|
|
self.img_target = attrs.get((None, 'img_target'), None)
|
2005-01-07 02:39:09 +00:00
|
|
|
|
2005-04-14 23:00:34 +00:00
|
|
|
self.img_pad_dimensions = is_attr_true( attrs, 'img_pad_dimensions' )
|
|
|
|
|
self.img_null_flag = is_attr_true( attrs, 'img_null_flag' )
|
|
|
|
|
self.img_send_null = is_attr_true( attrs, 'img_send_null' )
|
2005-01-07 02:39:09 +00:00
|
|
|
|
2005-02-02 00:54:45 +00:00
|
|
|
if self.p_count > 0 or self.counter or self.count_parameter_list:
|
2004-05-18 18:33:40 +00:00
|
|
|
has_count = 1
|
|
|
|
|
else:
|
|
|
|
|
has_count = 0
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
# If there is a * anywhere in the parameter's type, then it
|
|
|
|
|
# is a pointer.
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
if re.compile("[*]").search(self.p_type_string):
|
2004-05-18 18:33:40 +00:00
|
|
|
# We could do some other validation here. For
|
|
|
|
|
# example, an output parameter should not be const,
|
|
|
|
|
# but every non-output parameter should.
|
|
|
|
|
|
|
|
|
|
self.is_pointer = 1;
|
|
|
|
|
else:
|
|
|
|
|
# If a parameter is not a pointer, then there cannot
|
|
|
|
|
# be an associated count (either fixed size or
|
|
|
|
|
# variable) and the parameter cannot be an output.
|
|
|
|
|
|
|
|
|
|
if has_count or self.is_output:
|
|
|
|
|
raise RuntimeError("Non-pointer type has count or is output.")
|
|
|
|
|
self.is_pointer = 0;
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
glItem.__init__(self, name, p_name, context)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def is_variable_length_array(self):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Determine if a parameter is a variable length array.
|
|
|
|
|
|
|
|
|
|
A parameter is considered to be a variable length array if
|
|
|
|
|
its size depends on the value of another parameter that is
|
|
|
|
|
an enumerant. The params parameter to glTexEnviv is an
|
|
|
|
|
example of a variable length array parameter. Arrays whose
|
|
|
|
|
size depends on a count variable, such as the lists parameter
|
|
|
|
|
to glCallLists, are not variable length arrays in this
|
|
|
|
|
sense."""
|
|
|
|
|
|
2005-02-02 00:54:45 +00:00
|
|
|
return self.count_parameter_list or self.counter or self.width
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def is_array(self):
|
|
|
|
|
return self.is_pointer
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def count_string(self):
|
|
|
|
|
"""Return a string representing the number of items
|
|
|
|
|
|
|
|
|
|
Returns a string representing the number of items in a
|
|
|
|
|
parameter. For scalar types this will always be "1". For
|
|
|
|
|
vector types, it will depend on whether or not it is a
|
|
|
|
|
fixed length vector (like the parameter of glVertex3fv),
|
|
|
|
|
a counted length (like the vector parameter of
|
|
|
|
|
glDeleteTextures), or a general variable length vector."""
|
|
|
|
|
|
|
|
|
|
if self.is_array():
|
2005-02-02 00:54:45 +00:00
|
|
|
if self.count_parameter_list:
|
2004-05-18 18:33:40 +00:00
|
|
|
return "compsize"
|
|
|
|
|
elif self.counter != None:
|
|
|
|
|
return self.counter
|
|
|
|
|
else:
|
|
|
|
|
return str(self.p_count)
|
|
|
|
|
else:
|
|
|
|
|
return "1"
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def size(self):
|
2005-02-02 00:54:45 +00:00
|
|
|
if self.count_parameter_list or self.counter or self.width or self.is_output:
|
2004-05-18 18:33:40 +00:00
|
|
|
return 0
|
|
|
|
|
elif self.p_count == 0:
|
|
|
|
|
return self.p_type.size
|
|
|
|
|
else:
|
2005-03-06 08:55:39 +00:00
|
|
|
return self.p_type.size * self.p_count * self.count_scale
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2004-12-01 00:29:48 +00:00
|
|
|
def size_string(self):
|
|
|
|
|
s = self.size()
|
|
|
|
|
if s == 0:
|
|
|
|
|
a_prod = "compsize"
|
|
|
|
|
b_prod = self.p_type.size
|
|
|
|
|
|
2005-02-01 00:13:04 +00:00
|
|
|
# Handle functions like glCompressedTexImage2D that
|
|
|
|
|
# have a counted 'void *' parameter.
|
|
|
|
|
|
|
|
|
|
if b_prod == 0: b_prod = 1
|
|
|
|
|
|
2005-02-02 00:54:45 +00:00
|
|
|
if not self.count_parameter_list and self.counter != None:
|
2005-03-06 08:55:39 +00:00
|
|
|
if self.count_scale > 1:
|
|
|
|
|
a_prod = '(%s * %u)' % (self.counter, self.count_scale)
|
|
|
|
|
else:
|
|
|
|
|
a_prod = self.counter
|
2005-02-02 00:54:45 +00:00
|
|
|
elif self.count_parameter_list and self.counter == None:
|
2004-12-01 00:29:48 +00:00
|
|
|
pass
|
2005-02-02 00:54:45 +00:00
|
|
|
elif self.count_parameter_list and self.counter != None:
|
2005-03-06 08:55:39 +00:00
|
|
|
if self.count_scale > 1:
|
|
|
|
|
b_prod = '(%s * %u)' % (self.counter, self.count_scale)
|
|
|
|
|
else:
|
|
|
|
|
b_prod = self.counter
|
2005-01-07 02:39:09 +00:00
|
|
|
elif self.width:
|
|
|
|
|
return "compsize"
|
2004-12-01 00:29:48 +00:00
|
|
|
else:
|
|
|
|
|
raise RuntimeError("Parameter '%s' to function '%s' has size 0." % (self.name, self.context.name))
|
|
|
|
|
|
|
|
|
|
return "(%s * %s)" % (a_prod, b_prod)
|
|
|
|
|
else:
|
|
|
|
|
return str(s)
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
class glParameterIterator:
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Class to iterate over a list of glParameters.
|
|
|
|
|
|
2004-12-21 21:26:36 +00:00
|
|
|
Objects of this class are returned by the parameterIterator method of
|
|
|
|
|
the glFunction class. They are used to iterate over the list of
|
2004-05-19 23:33:08 +00:00
|
|
|
parameters to the function."""
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def __init__(self, data):
|
|
|
|
|
self.data = data
|
|
|
|
|
self.index = 0
|
2004-12-21 21:26:36 +00:00
|
|
|
|
|
|
|
|
def __iter__(self):
|
|
|
|
|
return self
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def next(self):
|
|
|
|
|
if self.index == len( self.data ):
|
|
|
|
|
raise StopIteration
|
|
|
|
|
i = self.index
|
|
|
|
|
self.index += 1
|
|
|
|
|
return self.data[i]
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
class glFunction( glItem ):
|
|
|
|
|
def __init__(self, context, name, attrs):
|
2005-04-18 19:16:07 +00:00
|
|
|
self.fn_alias = attrs.get((None, 'alias'), None)
|
2004-05-18 18:33:40 +00:00
|
|
|
self.fn_parameters = []
|
2005-01-07 02:39:09 +00:00
|
|
|
self.image = None
|
2005-02-01 00:13:04 +00:00
|
|
|
self.count_parameter_list = []
|
2005-02-02 00:54:45 +00:00
|
|
|
self.fn_return_type = "void"
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
temp = attrs.get((None, 'offset'), None)
|
2004-05-18 18:33:40 +00:00
|
|
|
if temp == None or temp == "?":
|
|
|
|
|
self.fn_offset = -1
|
|
|
|
|
else:
|
|
|
|
|
self.fn_offset = int(temp)
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
fn_name = attrs.get((None, 'name'), None)
|
2004-05-18 18:33:40 +00:00
|
|
|
if self.fn_alias != None:
|
|
|
|
|
self.real_name = self.fn_alias
|
|
|
|
|
else:
|
|
|
|
|
self.real_name = fn_name
|
|
|
|
|
|
2005-03-03 21:21:59 +00:00
|
|
|
self.parameters_by_name = {}
|
|
|
|
|
self.variable_length_parameters = []
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
glItem.__init__(self, name, fn_name, context)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
2004-12-21 21:26:36 +00:00
|
|
|
def parameterIterator(self):
|
2004-05-18 18:33:40 +00:00
|
|
|
return glParameterIterator(self.fn_parameters)
|
|
|
|
|
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
def startElementNS(self, name, qname, attrs):
|
|
|
|
|
[uri, true_name] = name
|
|
|
|
|
if true_name == "param":
|
2004-05-18 18:33:40 +00:00
|
|
|
try:
|
2005-04-18 19:16:07 +00:00
|
|
|
self.context.factory.create(self, true_name, attrs)
|
2004-05-18 18:33:40 +00:00
|
|
|
except RuntimeError:
|
|
|
|
|
print "Error with parameter '%s' in function '%s'." \
|
2005-04-18 19:16:07 +00:00
|
|
|
% (attrs.get((None, 'name'),'(unknown)'), self.name)
|
2004-05-18 18:33:40 +00:00
|
|
|
raise
|
2005-04-18 19:16:07 +00:00
|
|
|
elif true_name == "return":
|
|
|
|
|
self.set_return_type(attrs.get((None, 'type'), None))
|
2004-05-18 18:33:40 +00:00
|
|
|
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
def endElementNS(self, name, qname):
|
2005-03-03 21:21:59 +00:00
|
|
|
"""Handle the end of a <function> element.
|
|
|
|
|
|
|
|
|
|
At the end of a <function> element, there is some semantic
|
|
|
|
|
checking that can be done. This prevents some possible
|
|
|
|
|
exceptions from being thrown elsewhere in the code.
|
|
|
|
|
"""
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
[uri, true_name] = name
|
|
|
|
|
if true_name == "function":
|
2005-03-03 21:21:59 +00:00
|
|
|
for p in self.variable_length_parameters:
|
|
|
|
|
if p.counter:
|
|
|
|
|
counter = self.parameters_by_name[ p.counter ]
|
|
|
|
|
if not self.parameters_by_name.has_key( p.counter ):
|
|
|
|
|
raise RuntimeError("Parameter '%s' of function '%s' has counter '%s', but function has no such parameter." % (p.name, self.name, p.counter))
|
|
|
|
|
elif not self.parameters_by_name[ p.counter ].is_counter:
|
|
|
|
|
raise RuntimeError("Parameter '%s' of function '%s' has counter '%s', but '%s' is not marked as a counter." % (p.name, self.name, p.counter, p.counter))
|
|
|
|
|
|
|
|
|
|
for n in p.count_parameter_list:
|
|
|
|
|
if not self.parameters_by_name.has_key( n ):
|
|
|
|
|
raise RuntimeError("Parameter '%s' of function '%s' has size parameter '%s', but function has no such parameter." % (p.name, self.name, n))
|
|
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
else:
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
def append(self, tag_name, p):
|
|
|
|
|
if tag_name != "param":
|
|
|
|
|
raise RuntimeError("Trying to append '%s' to parameter list of function '%s'." % (tag_name, self.name))
|
|
|
|
|
|
2005-01-07 02:39:09 +00:00
|
|
|
if p.width:
|
|
|
|
|
self.image = p
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
self.fn_parameters.append(p)
|
2005-02-01 00:13:04 +00:00
|
|
|
if p.count_parameter_list != []:
|
|
|
|
|
self.count_parameter_list.extend( p.count_parameter_list )
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-03-03 21:21:59 +00:00
|
|
|
if p.is_variable_length_array():
|
|
|
|
|
self.variable_length_parameters.append(p)
|
|
|
|
|
|
|
|
|
|
self.parameters_by_name[ p.name ] = p
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def set_return_type(self, t):
|
|
|
|
|
self.fn_return_type = t
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def get_parameter_string(self):
|
|
|
|
|
arg_string = ""
|
|
|
|
|
comma = ""
|
2004-12-21 21:26:36 +00:00
|
|
|
for p in glFunction.parameterIterator(self):
|
2004-05-19 23:33:08 +00:00
|
|
|
arg_string = arg_string + comma + p.p_type_string + " " + p.name
|
2004-05-18 18:33:40 +00:00
|
|
|
comma = ", "
|
|
|
|
|
|
|
|
|
|
if arg_string == "":
|
|
|
|
|
arg_string = "void"
|
|
|
|
|
|
|
|
|
|
return arg_string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class glItemFactory:
|
|
|
|
|
"""Factory to create objects derived from glItem."""
|
|
|
|
|
|
|
|
|
|
def create(self, context, name, attrs):
|
|
|
|
|
if name == "function":
|
|
|
|
|
return glFunction(context, name, attrs)
|
|
|
|
|
elif name == "type":
|
|
|
|
|
return glType(context, name, attrs)
|
|
|
|
|
elif name == "enum":
|
|
|
|
|
return glEnum(context, name, attrs)
|
2004-12-01 00:29:48 +00:00
|
|
|
elif name == "param":
|
|
|
|
|
return glParameter(context, name, attrs)
|
2004-05-18 18:33:40 +00:00
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
2005-01-25 23:53:13 +00:00
|
|
|
class glFunctionIterator:
|
|
|
|
|
"""Class to iterate over a list of glFunctions
|
|
|
|
|
|
|
|
|
|
Objects of this classare returned by
|
|
|
|
|
FilterGLAPISpecBase::functionIterator. This default version
|
|
|
|
|
iterates over the functions in order of dispatch table offset. All
|
|
|
|
|
of the "true" functions are iterated first, followed by the alias
|
|
|
|
|
functions."""
|
|
|
|
|
|
|
|
|
|
def __init__(self, context):
|
|
|
|
|
self.context = context
|
|
|
|
|
self.keys = context.functions.keys()
|
|
|
|
|
self.keys.sort()
|
|
|
|
|
|
|
|
|
|
self.prevk = -1
|
|
|
|
|
self.direction = 1
|
|
|
|
|
|
|
|
|
|
for self.index in range(0, len(self.keys)):
|
|
|
|
|
if self.keys[ self.index ] >= 0: break
|
|
|
|
|
|
|
|
|
|
if self.index == len(self.keys):
|
|
|
|
|
self.direction = -1
|
|
|
|
|
self.index -= 1
|
|
|
|
|
|
|
|
|
|
self.split = self.index - 1
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __iter__(self):
|
|
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def next(self):
|
|
|
|
|
if self.index < 0:
|
|
|
|
|
raise StopIteration
|
|
|
|
|
|
|
|
|
|
k = self.keys[ self.index ]
|
|
|
|
|
|
|
|
|
|
#if self.context.functions[k].fn_alias == None:
|
|
|
|
|
# if k != self.prevk + 1:
|
|
|
|
|
# print 'Missing offset %d' % (prevk)
|
|
|
|
|
# self.prevk = int(k)
|
|
|
|
|
|
|
|
|
|
self.index += self.direction
|
|
|
|
|
|
|
|
|
|
if self.index == len(self.keys):
|
|
|
|
|
self.index = self.split
|
|
|
|
|
self.direction = -1
|
|
|
|
|
|
|
|
|
|
return self.context.functions[k]
|
|
|
|
|
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
class FilterGLAPISpecBase(saxutils.XMLFilterBase):
|
|
|
|
|
name = "a"
|
|
|
|
|
license = "The license for this file is unspecified."
|
|
|
|
|
next_alias = -2
|
|
|
|
|
current_object = None
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
saxutils.XMLFilterBase.__init__(self)
|
|
|
|
|
self.functions = {}
|
|
|
|
|
self.types = {}
|
2005-03-17 20:56:13 +00:00
|
|
|
self.functions_by_name = {}
|
2004-05-18 18:33:40 +00:00
|
|
|
self.factory = glItemFactory()
|
2005-01-28 19:00:54 +00:00
|
|
|
self.header_tag = None
|
2005-02-01 00:28:47 +00:00
|
|
|
self.undef_list = []
|
2005-03-17 20:56:13 +00:00
|
|
|
self.current_category = ""
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def find_type(self,type_name):
|
|
|
|
|
for t in self.types:
|
|
|
|
|
if re.compile(t).search(type_name):
|
|
|
|
|
return self.types[t]
|
|
|
|
|
print "Unable to find base type matching \"%s\"." % (type_name)
|
|
|
|
|
return None
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def find_function(self,function_name):
|
2005-03-17 20:56:13 +00:00
|
|
|
return self.functions_by_name[function_name]
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2005-01-25 23:53:13 +00:00
|
|
|
def functionIterator(self):
|
|
|
|
|
return glFunctionIterator(self)
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-01-25 23:53:13 +00:00
|
|
|
def printFunctions(self):
|
|
|
|
|
for f in self.functionIterator():
|
|
|
|
|
self.printFunction(f)
|
2004-05-18 18:33:40 +00:00
|
|
|
return
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def printHeader(self):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Print the header associated with all files and call the printRealHeader method."""
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
print '/* DO NOT EDIT - This file generated automatically by %s script */' \
|
|
|
|
|
% (self.name)
|
|
|
|
|
print ''
|
|
|
|
|
print '/*'
|
|
|
|
|
print ' * ' + self.license.replace('\n', '\n * ')
|
|
|
|
|
print ' */'
|
|
|
|
|
print ''
|
2005-01-28 19:00:54 +00:00
|
|
|
if self.header_tag:
|
|
|
|
|
print '#if !defined( %s )' % (self.header_tag)
|
|
|
|
|
print '# define %s' % (self.header_tag)
|
|
|
|
|
print ''
|
2004-05-18 18:33:40 +00:00
|
|
|
self.printRealHeader();
|
|
|
|
|
return
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def printFooter(self):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Print the header associated with all files and call the printRealFooter method."""
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
self.printFunctions()
|
|
|
|
|
self.printRealFooter()
|
2005-01-28 19:00:54 +00:00
|
|
|
if self.header_tag:
|
2005-02-01 00:28:47 +00:00
|
|
|
if self.undef_list:
|
|
|
|
|
print ''
|
|
|
|
|
for u in self.undef_list:
|
|
|
|
|
print "# undef %s" % (u)
|
|
|
|
|
print ''
|
|
|
|
|
print '#endif /* !defined( %s ) */' % (self.header_tag)
|
2004-05-18 18:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_category_define(self):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Convert the category name to the #define that would be found in glext.h"""
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
if re.compile("[1-9][0-9]*[.][0-9]+").match(self.current_category):
|
|
|
|
|
s = self.current_category
|
|
|
|
|
return "GL_VERSION_" + s.replace(".", "_")
|
|
|
|
|
else:
|
|
|
|
|
return self.current_category
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def append(self, object_type, obj):
|
|
|
|
|
if object_type == "function":
|
|
|
|
|
# If the function is not an alias and has a negative
|
|
|
|
|
# offset, then we do not need to track it. These are
|
|
|
|
|
# functions that don't have an assigned offset
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
if not self.functions_by_name.has_key(obj.name):
|
|
|
|
|
self.functions_by_name[obj.name] = obj
|
2004-05-18 18:33:40 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
if obj.fn_offset >= 0 or obj.fn_alias != None:
|
|
|
|
|
if obj.fn_offset >= 0:
|
|
|
|
|
index = obj.fn_offset
|
|
|
|
|
else:
|
|
|
|
|
index = self.next_alias
|
|
|
|
|
self.next_alias -= 1
|
2005-03-17 20:56:13 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
self.functions[index] = obj
|
|
|
|
|
else:
|
|
|
|
|
# We should do some checking here to make
|
|
|
|
|
# sure the functions are an identical match.
|
|
|
|
|
pass
|
2005-03-17 20:56:13 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
elif object_type == "type":
|
|
|
|
|
self.types[obj.name] = obj
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
def startElementNS(self, name, qname, attrs):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Start a new element in the XML stream.
|
|
|
|
|
|
|
|
|
|
Starts a new element. There are three types of elements that
|
|
|
|
|
are specially handled by this function. When a "category"
|
|
|
|
|
element is encountered, the name of the category is saved.
|
|
|
|
|
If an element is encountered and no API object is
|
|
|
|
|
in-progress, a new object is created using the API factory.
|
|
|
|
|
Any future elements, until that API object is closed, are
|
|
|
|
|
passed to the current objects startElement method.
|
|
|
|
|
|
|
|
|
|
This paradigm was chosen becuase it allows subclasses of the
|
|
|
|
|
basic API types (i.e., glFunction, glEnum, etc.) to handle
|
|
|
|
|
additional XML data, GLX protocol information, that the base
|
|
|
|
|
classes do not know about."""
|
|
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
[uri, true_name] = name
|
|
|
|
|
if uri is None:
|
|
|
|
|
if self.current_object != None:
|
|
|
|
|
self.current_object.startElementNS(name, qname, attrs)
|
|
|
|
|
elif true_name == "category":
|
|
|
|
|
self.current_category = attrs.get((None, 'name'), "")
|
|
|
|
|
elif true_name == "include":
|
|
|
|
|
self.next_include = attrs.get((None, 'name'), "")
|
|
|
|
|
else:
|
|
|
|
|
self.current_object = self.factory.create(self, true_name, attrs)
|
2004-05-18 18:33:40 +00:00
|
|
|
return
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2005-04-18 19:16:07 +00:00
|
|
|
def endElementNS(self, name, qname):
|
2004-05-18 18:33:40 +00:00
|
|
|
if self.current_object != None:
|
2005-04-18 19:16:07 +00:00
|
|
|
if self.current_object.endElementNS(name, qname):
|
2004-05-18 18:33:40 +00:00
|
|
|
self.current_object = None
|
2005-02-08 02:11:14 +00:00
|
|
|
elif name == "include":
|
|
|
|
|
parser = make_parser()
|
2005-04-18 19:16:07 +00:00
|
|
|
parser.setFeature(feature_namespaces, 1)
|
2005-02-08 02:11:14 +00:00
|
|
|
parser.setContentHandler(self)
|
|
|
|
|
|
|
|
|
|
f = open(self.next_include)
|
|
|
|
|
parser.parse(f)
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
return
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2005-02-01 00:28:47 +00:00
|
|
|
def printPure(self):
|
|
|
|
|
self.undef_list.append("PURE")
|
|
|
|
|
print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
|
|
|
|
|
# define PURE __attribute__((pure))
|
|
|
|
|
# else
|
|
|
|
|
# define PURE
|
|
|
|
|
# endif"""
|
|
|
|
|
|
|
|
|
|
def printFastcall(self):
|
|
|
|
|
self.undef_list.append("FASTCALL")
|
|
|
|
|
print """# if defined(__i386__) && defined(__GNUC__)
|
|
|
|
|
# define FASTCALL __attribute__((fastcall))
|
|
|
|
|
# else
|
|
|
|
|
# define FASTCALL
|
|
|
|
|
# endif"""
|
|
|
|
|
|
|
|
|
|
def printVisibility(self, S, s):
|
|
|
|
|
self.undef_list.append(S)
|
|
|
|
|
print """# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
|
|
|
|
|
# define %s __attribute__((visibility("%s")))
|
|
|
|
|
# else
|
|
|
|
|
# define %s
|
|
|
|
|
# endif""" % (S, s, S)
|
|
|
|
|
|
|
|
|
|
def printNoinline(self):
|
|
|
|
|
self.undef_list.append("NOINLINE")
|
|
|
|
|
print """# if defined(__GNUC__)
|
|
|
|
|
# define NOINLINE __attribute__((noinline))
|
|
|
|
|
# else
|
|
|
|
|
# define NOINLINE
|
|
|
|
|
# endif"""
|
|
|
|
|
|
|
|
|
|
def printHaveAlias(self):
|
|
|
|
|
self.undef_list.append("HAVE_ALIAS")
|
|
|
|
|
print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
|
|
|
|
|
# define HAVE_ALIAS
|
|
|
|
|
# endif"""
|
|
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def printFunction(self,offset):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Print a single function.
|
|
|
|
|
|
|
|
|
|
In the base class, this function is empty. All derived
|
|
|
|
|
classes should over-ride this function."""
|
2004-05-18 18:33:40 +00:00
|
|
|
return
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def printRealHeader(self):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Print the "real" header for the created file.
|
|
|
|
|
|
|
|
|
|
In the base class, this function is empty. All derived
|
|
|
|
|
classes should over-ride this function."""
|
2004-05-18 18:33:40 +00:00
|
|
|
return
|
|
|
|
|
|
2004-05-19 23:33:08 +00:00
|
|
|
|
2004-05-18 18:33:40 +00:00
|
|
|
def printRealFooter(self):
|
2004-05-19 23:33:08 +00:00
|
|
|
"""Print the "real" footer for the created file.
|
|
|
|
|
|
|
|
|
|
In the base class, this function is empty. All derived
|
|
|
|
|
classes should over-ride this function."""
|
2004-05-18 18:33:40 +00:00
|
|
|
return
|