8 ### Command line processing ###
12 extgen.py <extension> [<core_version>] [<secondary> ...]
13 extgen.py <extfile> [<outfile>]
15 Reads gl.xml and generates files to use <extension>. Any promoted functions
16 are exposed with their promoted names. If <secondary> extensions are given,
17 any promoted functions from those are pulled in as well. <core_version> can
18 be given to override the version where <extension> was promoted to core.
20 In the second form, the parameters are read from <extfile>. If <outfile> is
21 absent, the extension's lowercased name is used. Anything after the last dot
22 in <outfile> is removed and replaced with cpp and h."""
27 if ext.endswith(".glext"):
34 if parts[0]=="extension":
36 elif parts[0]=="core_version":
38 elif parts[0]=="secondary":
39 secondary.append(parts[1])
41 out_base = os.path.splitext(sys.argv[2])[0]
43 secondary = sys.argv[2:]
45 if secondary and secondary[0][0].isdigit():
46 ver = secondary.pop(0)
48 exttype = ext.split('_')[0]
52 out_base = ext.lower()
54 ### XML file parsing ###
57 def __init__(self, name):
62 self.vectorequiv = None
68 def get_nested_elements(elem, path):
70 head, tail = path.split('/', 1)
72 for e in elem.getElementsByTagName(head):
73 result += get_nested_elements(e, tail)
76 return elem.getElementsByTagName(path)
78 def get_text_contents(node):
80 for c in node.childNodes:
81 if c.nodeType==xml.dom.Node.TEXT_NODE or c.nodeType==xml.dom.Node.CDATA_SECTION_NODE:
84 result += get_text_contents(c)
88 doc = xml.dom.minidom.parse(fn)
89 root = doc.documentElement
90 commands = get_nested_elements(root, "commands/command")
92 name = get_text_contents(get_nested_elements(cmd, "proto/name")[0])
93 func = funcs.get(name)
98 aliases = cmd.getElementsByTagName("alias")
100 func.aliases.append(a.getAttribute("name"))
102 vec = cmd.getElementsByTagName("vecequiv")
104 func.vectorequiv = vec[0].getAttribute("name")
106 features = root.getElementsByTagName("feature")
107 for feat in features:
108 api = feat.getAttribute("api")
110 version = feat.getAttribute("number")
112 commands = get_nested_elements(feat, "require/command")
114 name = c.getAttribute("name")
115 func = funcs.get(name)
117 func.version = version
119 if feat.getAttribute("name")=="MSPGL_REMOVE":
120 commands = get_nested_elements(feat, "remove/command")
122 name = c.getAttribute("name")
126 extensions = get_nested_elements(root, "extensions/extension")
127 for ext in extensions:
128 ext_name = ext.getAttribute("name")
129 if ext_name.startswith("GL_"):
130 ext_name = ext_name[3:]
131 supported = ext.getAttribute("supported").split('|')
132 if "gl" in supported:
133 commands = get_nested_elements(ext, "require/command")
135 name = c.getAttribute("name")
136 func = funcs.get(name)
138 func.extension = ext_name
141 parse_file("gl.fixes.xml")
143 ### Additional processing ###
145 # Create references from core functions to their extension counterparts
146 for f in funcs.itervalues():
147 if f.extension==ext or f.extension in secondary:
149 aliasfunc = funcs.get(a)
151 aliasfunc.extfunc = f
154 # Unpromoted extension functions are relevant
155 if f.extension==ext and not f.aliases:
158 # Core functions promoted from the extension are also relevant
161 if e.extension==ext or e.extension in secondary:
166 funcs = [f for f in funcs.itervalues() if is_relevant(f)]
167 funcs.sort(key=(lambda f: f.name))
173 # Functions in backport extensions don't acquire an extension suffix
174 if f.extension and not f.name.endswith(exttype):
175 backport_ext = f.extension
178 # Typedefs for early core functions are not available in all
180 f.typedef = "PFN%sPROC"%f.extfunc.name.upper()
182 f.typedef = "PFN%sPROC"%f.name.upper()
185 ver = map(int, ver.split('.'))
189 out = file(out_base+".h", "w")
190 out.write("#ifndef MSP_GL_%s_\n"%ext.upper())
191 out.write("#define MSP_GL_%s_\n"%ext.upper())
194 #include <msp/gl/extension.h>
195 #include <msp/gl/gl.h>
204 out.write("extern %s %s;\n"%(f.typedef, f.name))
206 out.write("\nextern Extension %s;\n"%ext)
215 out = file(out_base+".cpp", "w")
216 out.write("#include \"%s.h\"\n"%ext.lower())
226 out.write("%s %s = 0;\n"%(f.typedef, f.name))
228 out.write("\nExtension::SupportLevel init_%s()\n{\n"%ext.lower())
230 out.write("\tif(is_version_at_least(%d, %d)"%tuple(ver))
232 out.write(" || is_supported(\"GL_%s\")"%backport_ext)
233 out.write(")\n\t{\n")
235 out.write("\t\t%s = reinterpret_cast<%s>(get_proc_address(\"%s\"));\n"%(f.name, f.typedef, f.name))
236 out.write("\t\treturn Extension::CORE;\n")
238 if ext!=backport_ext:
239 out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(ext))
244 out.write("\t\t%s = reinterpret_cast<%s>(get_proc_address(\"%s\"));\n"%(f.name, f.typedef, n))
245 out.write("\t\treturn Extension::EXTENSION;\n")
247 out.write("\treturn Extension::UNSUPPORTED;\n")
250 out.write("\nExtension %s(\"GL_%s\", init_%s);\n"%(ext, ext, ext.lower()))