summaryrefslogtreecommitdiffstats
path: root/src/mesa/main/APIspec.py
diff options
context:
space:
mode:
authorPaul Berry <[email protected]>2012-10-23 13:24:17 -0700
committerPaul Berry <[email protected]>2012-11-01 11:26:30 -0700
commita8ab7e335df4cd7841bbbe572d5494796bb4e398 (patch)
tree40b64014369daff017681f309f65cb0d1f9fbdc8 /src/mesa/main/APIspec.py
parent8386088e3dc6fbd223dca7cc966b86f9ab0652b5 (diff)
dispatch: stop generating separate GLES1 API code.
This patch removes the generated files api_exec_es1.c, api_exec_es1_dispatch.h, and api_exec_es1_remap_helper.h (and the source files and build rules used to generate them), since they are no longer used. GLES1 now uses the same dispatch table layout as all the other APIs. Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/mesa/main/APIspec.py')
-rw-r--r--src/mesa/main/APIspec.py617
1 files changed, 0 insertions, 617 deletions
diff --git a/src/mesa/main/APIspec.py b/src/mesa/main/APIspec.py
deleted file mode 100644
index 6947f7301cd..00000000000
--- a/src/mesa/main/APIspec.py
+++ /dev/null
@@ -1,617 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright (C) 2009 Chia-I Wu <[email protected]>
-#
-# 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.
-"""
-A parser for APIspec.
-"""
-
-class SpecError(Exception):
- """Error in the spec file."""
-
-
-class Spec(object):
- """A Spec is an abstraction of the API spec."""
-
- def __init__(self, doc):
- self.doc = doc
-
- self.spec_node = doc.getRootElement()
- self.tmpl_nodes = {}
- self.api_nodes = {}
- self.impl_node = None
-
- # parse <apispec>
- node = self.spec_node.children
- while node:
- if node.type == "element":
- if node.name == "template":
- self.tmpl_nodes[node.prop("name")] = node
- elif node.name == "api":
- self.api_nodes[node.prop("name")] = node
- else:
- raise SpecError("unexpected node %s in apispec" %
- node.name)
- node = node.next
-
- # find an implementation
- for name, node in self.api_nodes.iteritems():
- if node.prop("implementation") == "true":
- self.impl_node = node
- break
- if not self.impl_node:
- raise SpecError("unable to find an implementation")
-
- def get_impl(self):
- """Return the implementation."""
- return API(self, self.impl_node)
-
- def get_api(self, name):
- """Return an API."""
- return API(self, self.api_nodes[name])
-
-
-class API(object):
- """An API consists of categories and functions."""
-
- def __init__(self, spec, api_node):
- self.name = api_node.prop("name")
- self.is_impl = (api_node.prop("implementation") == "true")
-
- self.categories = []
- self.functions = []
-
- # parse <api>
- func_nodes = []
- node = api_node.children
- while node:
- if node.type == "element":
- if node.name == "category":
- cat = node.prop("name")
- self.categories.append(cat)
- elif node.name == "function":
- func_nodes.append(node)
- else:
- raise SpecError("unexpected node %s in api" % node.name)
- node = node.next
-
- # realize functions
- for func_node in func_nodes:
- tmpl_node = spec.tmpl_nodes[func_node.prop("template")]
- try:
- func = Function(tmpl_node, func_node, self.is_impl,
- self.categories)
- except SpecError, e:
- func_name = func_node.prop("name")
- raise SpecError("failed to parse %s: %s" % (func_name, e))
- self.functions.append(func)
-
- def match(self, func, conversions={}):
- """Find a matching function in the API."""
- match = None
- need_conv = False
- for f in self.functions:
- matched, conv = f.match(func, conversions)
- if matched:
- match = f
- need_conv = conv
- # exact match
- if not need_conv:
- break
- return (match, need_conv)
-
-
-class Function(object):
- """Parse and realize a <template> node."""
-
- def __init__(self, tmpl_node, func_node, force_skip_desc=False, categories=[]):
- self.tmpl_name = tmpl_node.prop("name")
- self.direction = tmpl_node.prop("direction")
-
- self.name = func_node.prop("name")
- self.prefix = func_node.prop("default_prefix")
- self.is_external = (func_node.prop("external") == "true")
-
- if force_skip_desc:
- self._skip_desc = True
- else:
- self._skip_desc = (func_node.prop("skip_desc") == "true")
-
- self._categories = categories
-
- # these attributes decide how the template is realized
- self._gltype = func_node.prop("gltype")
- if func_node.hasProp("vector_size"):
- self._vector_size = int(func_node.prop("vector_size"))
- else:
- self._vector_size = 0
- self._expand_vector = (func_node.prop("expand_vector") == "true")
-
- self.return_type = "void"
- param_nodes = []
-
- # find <proto>
- proto_node = tmpl_node.children
- while proto_node:
- if proto_node.type == "element" and proto_node.name == "proto":
- break
- proto_node = proto_node.next
- if not proto_node:
- raise SpecError("no proto")
- # and parse it
- node = proto_node.children
- while node:
- if node.type == "element":
- if node.name == "return":
- self.return_type = node.prop("type")
- elif node.name == "param" or node.name == "vector":
- if self.support_node(node):
- # make sure the node is not hidden
- if not (self._expand_vector and
- (node.prop("hide_if_expanded") == "true")):
- param_nodes.append(node)
- else:
- raise SpecError("unexpected node %s in proto" % node.name)
- node = node.next
-
- self._init_params(param_nodes)
- self._init_descs(tmpl_node, param_nodes)
-
- def __str__(self):
- return "%s %s%s(%s)" % (self.return_type, self.prefix, self.name,
- self.param_string(True))
-
- def _init_params(self, param_nodes):
- """Parse and initialize parameters."""
- self.params = []
-
- for param_node in param_nodes:
- size = self.param_node_size(param_node)
- # when no expansion, vector is just like param
- if param_node.name == "param" or not self._expand_vector:
- param = Parameter(param_node, self._gltype, size)
- self.params.append(param)
- continue
-
- if not size or size > param_node.lsCountNode():
- raise SpecError("could not expand %s with unknown or "
- "mismatch sizes" % param.name)
-
- # expand the vector
- expanded_params = []
- child = param_node.children
- while child:
- if (child.type == "element" and child.name == "param" and
- self.support_node(child)):
- expanded_params.append(Parameter(child, self._gltype))
- if len(expanded_params) == size:
- break
- child = child.next
- # just in case that lsCountNode counts unknown nodes
- if len(expanded_params) < size:
- raise SpecError("not enough named parameters")
-
- self.params.extend(expanded_params)
-
- def _init_descs(self, tmpl_node, param_nodes):
- """Parse and initialize parameter descriptions."""
- self.checker = Checker()
- if self._skip_desc:
- return
-
- node = tmpl_node.children
- while node:
- if node.type == "element" and node.name == "desc":
- if self.support_node(node):
- # parse <desc>
- desc = Description(node, self._categories)
- self.checker.add_desc(desc)
- node = node.next
-
- self.checker.validate(self, param_nodes)
-
- def support_node(self, node):
- """Return true if a node is in the supported category."""
- return (not node.hasProp("category") or
- node.prop("category") in self._categories)
-
- def get_param(self, name):
- """Return the named parameter."""
- for param in self.params:
- if param.name == name:
- return param
- return None
-
- def param_node_size(self, param):
- """Return the size of a vector."""
- if param.name != "vector":
- return 0
-
- size = param.prop("size")
- if size.isdigit():
- size = int(size)
- else:
- size = 0
- if not size:
- size = self._vector_size
- if not size and self._expand_vector:
- # return the number of named parameters
- size = param.lsCountNode()
- return size
-
- def param_string(self, declaration):
- """Return the C code of the parameters."""
- args = []
- if declaration:
- for param in self.params:
- sep = "" if param.type.endswith("*") else " "
- args.append("%s%s%s" % (param.type, sep, param.name))
- if not args:
- args.append("void")
- else:
- for param in self.params:
- args.append(param.name)
- return ", ".join(args)
-
- def match(self, other, conversions={}):
- """Return true if the functions match, probably with a conversion."""
- if (self.tmpl_name != other.tmpl_name or
- self.return_type != other.return_type or
- len(self.params) != len(other.params)):
- return (False, False)
-
- need_conv = False
- for i in xrange(len(self.params)):
- src = other.params[i]
- dst = self.params[i]
- if (src.is_vector != dst.is_vector or src.size != dst.size):
- return (False, False)
- if src.type != dst.type:
- if dst.base_type() in conversions.get(src.base_type(), []):
- need_conv = True
- else:
- # unable to convert
- return (False, False)
-
- return (True, need_conv)
-
-
-class Parameter(object):
- """A parameter of a function."""
-
- def __init__(self, param_node, gltype=None, size=0):
- self.is_vector = (param_node.name == "vector")
-
- self.name = param_node.prop("name")
- self.size = size
-
- type = param_node.prop("type")
- if gltype:
- type = type.replace("GLtype", gltype)
- elif type.find("GLtype") != -1:
- raise SpecError("parameter %s has unresolved type" % self.name)
-
- self.type = type
-
- def base_type(self):
- """Return the base GL type by stripping qualifiers."""
- return [t for t in self.type.split(" ") if t.startswith("GL")][0]
-
-
-class Checker(object):
- """A checker is the collection of all descriptions on the same level.
- Descriptions of the same parameter are concatenated.
- """
-
- def __init__(self):
- self.switches = {}
- self.switch_constants = {}
-
- def add_desc(self, desc):
- """Add a description."""
- # TODO allow index to vary
- const_attrs = ["index", "error", "convert", "size_str"]
- if desc.name not in self.switches:
- self.switches[desc.name] = []
- self.switch_constants[desc.name] = {}
- for attr in const_attrs:
- self.switch_constants[desc.name][attr] = None
-
- # some attributes, like error code, should be the same for all descs
- consts = self.switch_constants[desc.name]
- for attr in const_attrs:
- if getattr(desc, attr) is not None:
- if (consts[attr] is not None and
- consts[attr] != getattr(desc, attr)):
- raise SpecError("mismatch %s for %s" % (attr, desc.name))
- consts[attr] = getattr(desc, attr)
-
- self.switches[desc.name].append(desc)
-
- def validate(self, func, param_nodes):
- """Validate the checker against a function."""
- tmp = Checker()
-
- for switch in self.switches.itervalues():
- valid_descs = []
- for desc in switch:
- if desc.validate(func, param_nodes):
- valid_descs.append(desc)
- # no possible values
- if not valid_descs:
- return False
- for desc in valid_descs:
- if not desc._is_noop:
- tmp.add_desc(desc)
-
- self.switches = tmp.switches
- self.switch_constants = tmp.switch_constants
- return True
-
- def flatten(self, name=None):
- """Return a flat list of all descriptions of the named parameter."""
- flat_list = []
- for switch in self.switches.itervalues():
- for desc in switch:
- if not name or desc.name == name:
- flat_list.append(desc)
- flat_list.extend(desc.checker.flatten(name))
- return flat_list
-
- def always_check(self, name):
- """Return true if the parameter is checked in all possible pathes."""
- if name in self.switches:
- return True
-
- # a param is always checked if any of the switch always checks it
- for switch in self.switches.itervalues():
- # a switch always checks it if all of the descs always check it
- always = True
- for desc in switch:
- if not desc.checker.always_check(name):
- always = False
- break
- if always:
- return True
- return False
-
- def _c_switch(self, name, indent="\t"):
- """Output C switch-statement for the named parameter, for debug."""
- switch = self.switches.get(name, [])
- # make sure there are valid values
- need_switch = False
- for desc in switch:
- if desc.values:
- need_switch = True
- if not need_switch:
- return []
-
- stmts = []
- var = switch[0].name
- if switch[0].index >= 0:
- var += "[%d]" % switch[0].index
- stmts.append("switch (%s) { /* assume GLenum */" % var)
-
- for desc in switch:
- if desc.values:
- for val in desc.values:
- stmts.append("case %s:" % val)
- for dep_name in desc.checker.switches.iterkeys():
- dep_stmts = [indent + s for s in desc.checker._c_switch(dep_name, indent)]
- stmts.extend(dep_stmts)
- stmts.append(indent + "break;")
-
- stmts.append("default:")
- stmts.append(indent + "ON_ERROR(%s);" % switch[0].error);
- stmts.append(indent + "break;")
- stmts.append("}")
-
- return stmts
-
- def dump(self, indent="\t"):
- """Dump the descriptions in C code."""
- stmts = []
- for name in self.switches.iterkeys():
- c_switch = self._c_switch(name)
- print "\n".join(c_switch)
-
-
-class Description(object):
- """A description desribes a parameter and its relationship with other
- parameters.
- """
-
- def __init__(self, desc_node, categories=[]):
- self._categories = categories
- self._is_noop = False
-
- self.name = desc_node.prop("name")
- self.index = -1
-
- self.error = desc_node.prop("error") or "GL_INVALID_ENUM"
- # vector_size may be C code
- self.size_str = desc_node.prop("vector_size")
-
- self._has_enum = False
- self.values = []
- dep_nodes = []
-
- # parse <desc>
- valid_names = ["value", "range", "desc"]
- node = desc_node.children
- while node:
- if node.type == "element":
- if node.name in valid_names:
- # ignore nodes that require unsupported categories
- if (node.prop("category") and
- node.prop("category") not in self._categories):
- node = node.next
- continue
- else:
- raise SpecError("unexpected node %s in desc" % node.name)
-
- if node.name == "value":
- val = node.prop("name")
- if not self._has_enum and val.startswith("GL_"):
- self._has_enum = True
- self.values.append(val)
- elif node.name == "range":
- first = int(node.prop("from"))
- last = int(node.prop("to"))
- base = node.prop("base") or ""
- if not self._has_enum and base.startswith("GL_"):
- self._has_enum = True
- # expand range
- for i in xrange(first, last + 1):
- self.values.append("%s%d" % (base, i))
- else: # dependent desc
- dep_nodes.append(node)
- node = node.next
-
- # default to convert if there is no enum
- self.convert = not self._has_enum
- if desc_node.hasProp("convert"):
- self.convert = (desc_node.prop("convert") == "true")
-
- self._init_deps(dep_nodes)
-
- def _init_deps(self, dep_nodes):
- """Parse and initialize dependents."""
- self.checker = Checker()
-
- for dep_node in dep_nodes:
- # recursion!
- dep = Description(dep_node, self._categories)
- self.checker.add_desc(dep)
-
- def _search_param_node(self, param_nodes, name=None):
- """Search the template parameters for the named node."""
- param_node = None
- param_index = -1
-
- if not name:
- name = self.name
- for node in param_nodes:
- if name == node.prop("name"):
- param_node = node
- elif node.name == "vector":
- child = node.children
- idx = 0
- while child:
- if child.type == "element" and child.name == "param":
- if name == child.prop("name"):
- param_node = node
- param_index = idx
- break
- idx += 1
- child = child.next
- if param_node:
- break
- return (param_node, param_index)
-
- def _find_final(self, func, param_nodes):
- """Find the final parameter."""
- param = func.get_param(self.name)
- param_index = -1
-
- # the described param is not in the final function
- if not param:
- # search the template parameters
- node, index = self._search_param_node(param_nodes)
- if not node:
- raise SpecError("invalid desc %s in %s" %
- (self.name, func.name))
-
- # a named parameter of a vector
- if index >= 0:
- param = func.get_param(node.prop("name"))
- param_index = index
- elif node.name == "vector":
- # must be an expanded vector, check its size
- if self.size_str and self.size_str.isdigit():
- size = int(self.size_str)
- expanded_size = func.param_node_size(node)
- if size != expanded_size:
- return (False, None, -1)
- # otherwise, it is a valid, but no-op, description
-
- return (True, param, param_index)
-
- def validate(self, func, param_nodes):
- """Validate a description against certain function."""
- if self.checker.switches and not self.values:
- raise SpecError("no valid values for %s" % self.name)
-
- valid, param, param_index = self._find_final(func, param_nodes)
- if not valid:
- return False
-
- # the description is valid, but the param is gone
- # mark it no-op so that it will be skipped
- if not param:
- self._is_noop = True
- return True
-
- if param.is_vector:
- # if param was known, this should have been done in __init__
- if self._has_enum:
- self.size_str = "1"
- # size mismatch
- if (param.size and self.size_str and self.size_str.isdigit() and
- param.size != int(self.size_str)):
- return False
- elif self.size_str:
- # only vector accepts vector_size
- raise SpecError("vector_size is invalid for %s" % param.name)
-
- if not self.checker.validate(func, param_nodes):
- return False
-
- # update the description
- self.name = param.name
- self.index = param_index
-
- return True
-
-
-def main():
- import libxml2
-
- filename = "APIspec.xml"
- apinames = ["GLES1.1", "GLES2.0"]
-
- doc = libxml2.readFile(filename, None,
- libxml2.XML_PARSE_DTDLOAD +
- libxml2.XML_PARSE_DTDVALID +
- libxml2.XML_PARSE_NOBLANKS)
-
- spec = Spec(doc)
- impl = spec.get_impl()
- for apiname in apinames:
- spec.get_api(apiname)
-
- doc.freeDoc()
-
- print "%s is successfully parsed" % filename
-
-
-if __name__ == "__main__":
- main()