+
+ def write_header(self, fn):
+ out = open(fn, "w")
+ self.write_header_intro(out)
+ self.write_enum_definitions(out)
+ self.write_function_pointer_declarations(out)
+ out.write("extern Extension {};\n".format(self.ext_name))
+ self.write_header_outro(out)
+
+ def write_source(self, fn):
+ out = open(fn, "w")
+ self.write_source_intro(out)
+ self.write_function_pointer_definitions(out)
+ self.write_init_function(out)
+ out.write("\nExtension {}(\"GL_{}\", init_{});\n".format(self.ext_name, self.ext_name, self.ext_name.lower()))
+ self.write_source_outro(out)
+
+
+def dump_api_support(supp, api, indent):
+ if supp.core_version:
+ print(indent+"core in version {}".format(supp.core_version))
+ if supp.deprecated_version:
+ print(indent+"deprecated in version {}".format(supp.deprecated_version))
+ for e in supp.extensions:
+ print(indent+"extension {} (preference {})".format(e.name, e.preference))
+ for r in supp.sources:
+ print(indent+"source {}".format(r.name))
+ dump_thing_info(r, api, indent+" ")
+
+def dump_thing_info(thing, api, indent):
+ for a in thing.aliases:
+ print(indent+"alias {}".format(a))
+ if api:
+ supp = thing.api_support.get(api)
+ dump_api_support(supp, api, indent)
+ else:
+ for a, s in thing.api_support.items():
+ print(indent+"api {}".format(a))
+ dump_api_support(s, a, indent+" ")
+
+
+class ExtensionParser:
+ def __init__(self, host_api):
+ self.host_api = host_api
+ self.target_ext = None
+ self.core_version = None
+ self.deprecated_version = None
+ self.backport_ext = None
+ self.source_exts = []
+ self.ignore_things = []
+ self.optional_things = []
+
+ def parse(self, fn):
+ for line in open(fn):
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+
+ parts = line.split()
+ api = None
+ keyword = parts[0]
+ if ":" in keyword:
+ api, keyword = keyword.split(":")
+
+ if api is not None and api!=self.host_api:
+ continue
+
+ if keyword=="extension":
+ self.target_ext = parts[1]
+ elif keyword=="core_version":
+ self.core_version = Version(*map(int, parts[1].split('.')))
+ elif keyword=="deprecated":
+ self.deprecated_version = Version(*map(int, parts[1].split('.')))
+ elif keyword=="backport":
+ self.backport_ext = parts[1]
+ elif keyword=="source":
+ self.source_exts.append(parts[1])
+ elif keyword=="ignore":
+ self.ignore_things.append(parts[1])
+ elif keyword=="optional":
+ self.optional_things.append(parts[1])
+ else:
+ print("Unknown keyword "+keyword)
+ return False
+
+ return True
+
+
+def get_extension(api_map, ext_name):
+ if "." in ext_name:
+ ext_api_name, ext_name = ext_name.split(".")
+ else:
+ ext_api_name = "gl"
+
+ return api_map[ext_api_name].extensions[ext_name]
+
+def resolve_things(api, things):
+ rthings = []
+ for t in things:
+ ct = [api.core_things[a] for a in t.aliases if a in api.core_things]
+ if ct:
+ rthings += ct
+ else:
+ rthings.append(t)
+
+ return rthings
+
+def collect_extension_things(host_api, target_ext, ignore):
+ ext_things = [t for n, t in target_ext.things.items() if n not in ignore]
+ return resolve_things(target_ext.api, ext_things)
+
+def collect_optional_things(target_ext, names):
+ things = []
+ for t in names:
+ if t in target_ext.things:
+ things.append(target_ext.things[t])
+ else:
+ things.append(target_ext.api.core_things[t])
+ return resolve_things(target_ext.api, things)
+
+def main():
+ if len(sys.argv)<2:
+ print("""Usage:
+ extgen.py [api] <extfile> [<outfile>]
+
+Reads gl.xml and generates C++ source files to use an OpenGL extension
+described in <extfile>. If <outfile> is absent, the extension's lowercased
+name is used. Anything after the last dot in <outfile> is removed and
+replaced with cpp and h.""")
+ sys.exit(1)
+
+ i = 1
+
+ debug = False
+ if sys.argv[i]=="-g":
+ debug = True
+ i += 1
+
+ host_api_name = "gl"
+ if sys.argv[i].startswith("gl"):
+ host_api_name = sys.argv[i]
+ i += 1
+
+ ext_parser = ExtensionParser(host_api_name)
+ if not ext_parser.parse(sys.argv[i]):
+ sys.exit(1)
+ i += 1
+
+ if i<len(sys.argv):
+ out_base = os.path.splitext(sys.argv[i])[0]
+ else:
+ out_base = ext_parser.target_ext.lower()
+
+ xml_parser = GlXmlParser()
+ xml_parser.parse_file("gl.xml")
+ xml_parser.parse_file("gl.fixes.xml")
+ xml_parser.parse_file("gl.msp.xml")
+ xml_parser.finalize()
+
+ host_api = xml_parser.apis[host_api_name]
+ target_ext = get_extension(xml_parser.apis, ext_parser.target_ext)
+ things = collect_extension_things(host_api, target_ext, ext_parser.ignore_things+ext_parser.optional_things)
+ optional_things = collect_optional_things(target_ext, ext_parser.optional_things)
+
+ if debug:
+ print("--- Things included in this extension ---")
+ all_things = things+optional_things
+ all_things.sort(key=(lambda t: t.name))
+ for t in all_things:
+ print(t.name)
+ if t in optional_things:
+ print(" optional")
+ dump_thing_info(t, None, " ")
+
+ generator = SourceGenerator(host_api, target_ext.name, things, optional_things, debug)
+ if ext_parser.core_version:
+ generator.core_version = ext_parser.core_version
+ if ext_parser.deprecated_version:
+ generator.deprecated_version = ext_parser.deprecated_version
+ if ext_parser.backport_ext:
+ if ext_parser.backport_ext=="none":
+ generator.backport_ext = None
+ else:
+ generator.backport_ext = get_extension(xml_parser.apis, ext_parser.backport_ext)
+ if ext_parser.source_exts:
+ generator.base_version = None
+ if len(ext_parser.source_exts)==1 and ext_parser.source_exts[0]=="none":
+ generator.source_exts = []
+ else:
+ generator.source_exts = map((lambda e: get_extension(xml_parser.apis, e)), ext_parser.source_exts)
+ if debug:
+ generator.dump_info()
+ generator.write_header(out_base+".h")
+ generator.write_source(out_base+".cpp")
+
+if __name__=="__main__":
+ main()