X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=scripts%2Fextgen.py;h=eef6475adbdad5506ad39068286e2efa03b3922a;hp=3cd2f5728f3b3d2019f17a0c9171eb230b85c454;hb=710418caebcbcb9ed22bb828cb1dcd88d6b99aa1;hpb=16ab664fe93bffba059ea53deccbfed0305f7440 diff --git a/scripts/extgen.py b/scripts/extgen.py index 3cd2f572..eef6475a 100755 --- a/scripts/extgen.py +++ b/scripts/extgen.py @@ -4,15 +4,23 @@ import sys import os import xml.dom import xml.dom.minidom +import itertools + +### Command line processing ### if len(sys.argv)<2: print """Usage: - extgen.py [] [ ...]" + extgen.py [] [ ...] + extgen.py [] -Reads gl.spec and generates files to use . Any promoted functions +Reads gl.xml and generates files to use . Any promoted functions are exposed with their promoted names. If extensions are given, -any promoted functions from those are pulled in as well. can be -given to override the version where was promoted to core.""" +any promoted functions from those are pulled in as well. can +be given to override the version where was promoted to core. + +In the second form, the parameters are read from . If is +absent, the extension's lowercased name is used. Anything after the last dot +in is removed and replaced with cpp and h.""" sys.exit(0) ext = sys.argv[1] @@ -39,23 +47,37 @@ else: ver = secondary.pop(0) exttype = ext.split('_')[0] -bp_ext = None +backport_ext = None if not out_base: out_base = ext.lower() -class Function: - def __init__(self, name): +### XML file parsing ### + +class Thing: + FUNCTION = 1 + ENUM = 2 + + def __init__(self, name, kind): self.name = name - self.typedef = None + self.kind = kind self.version = None - self.category = None - self.vectorequiv = None + self.extension = None self.aliases = [] - self.extfunc = None + self.source = None -funcs = {} -cur_func = None +class Function(Thing): + def __init__(self, name): + Thing.__init__(self, name, Thing.FUNCTION) + self.typedef = None + self.vectorequiv = None + +class Enum(Thing): + def __init__(self, name): + Thing.__init__(self, name, Thing.ENUM) + self.value = 0 + +things = {} def get_nested_elements(elem, path): if '/' in path: @@ -82,10 +104,10 @@ def parse_file(fn): commands = get_nested_elements(root, "commands/command") for cmd in commands: name = get_text_contents(get_nested_elements(cmd, "proto/name")[0]) - func = funcs.get(name) + func = things.get(name) if not func: func = Function(name) - funcs[name] = func + things[name] = func aliases = cmd.getElementsByTagName("alias") for a in aliases: @@ -95,6 +117,16 @@ def parse_file(fn): if vec: func.vectorequiv = vec[0].getAttribute("name") + enums = get_nested_elements(root, "enums/enum") + for en in enums: + name = en.getAttribute("name") + enum = things.get(name) + if not enum: + enum = Enum(name) + things[name] = enum + + enum.value = int(en.getAttribute("value"), 16) + features = root.getElementsByTagName("feature") for feat in features: api = feat.getAttribute("api") @@ -102,18 +134,20 @@ def parse_file(fn): version = feat.getAttribute("number") commands = get_nested_elements(feat, "require/command") - for c in commands: - name = c.getAttribute("name") - func = funcs.get(name) - if func: - func.version = version + enums = get_nested_elements(feat, "require/enum") + for t in itertools.chain(commands, enums): + name = t.getAttribute("name") + thing = things.get(name) + if thing: + thing.version = version if feat.getAttribute("name")=="MSPGL_REMOVE": commands = get_nested_elements(feat, "remove/command") - for c in commands: - name = c.getAttribute("name") - if name in funcs: - del funcs[name] + enums = get_nested_elements(feat, "require/enum") + for t in itertools.chain(commands, enums): + name = t.getAttribute("name") + if name in things: + del things[name] extensions = get_nested_elements(root, "extensions/extension") for ext in extensions: @@ -123,49 +157,75 @@ def parse_file(fn): supported = ext.getAttribute("supported").split('|') if "gl" in supported: commands = get_nested_elements(ext, "require/command") - for c in commands: - name = c.getAttribute("name") - func = funcs.get(name) - if func: - func.category = ext_name + enums = get_nested_elements(ext, "require/enum") + for t in itertools.chain(commands, enums): + name = t.getAttribute("name") + thing = things.get(name) + if thing: + thing.extension = ext_name parse_file("gl.xml") parse_file("gl.fixes.xml") -for f in funcs.itervalues(): - if f.category==ext or f.category in secondary: - for a in f.aliases: - aliasfunc = funcs.get(a) - if aliasfunc: - aliasfunc.extfunc = f - -def is_relevant(f): - if f.category==ext and not f.aliases: +### Additional processing ### + +# Find aliases for enums +enums = [t for t in things.itervalues() if t.kind==Thing.ENUM] +core_enums_by_value = dict((e.value, e) for e in enums if e.version) + +for e in enums: + if e.kind==t.ENUM and e.extension: + ce = core_enums_by_value.get(e.value) + if ce and ce!=e: + e.aliases.append(ce.name) + +# Create references from core things to their extension counterparts +for t in things.itervalues(): + if t.extension==ext or t.extension in secondary: + for a in t.aliases: + alias = things.get(a) + if alias: + alias.source = t + +def is_relevant(t): + # Unpromoted extension things are relevant + if t.extension==ext and not t.aliases: return True - if f.extfunc: - e = f.extfunc - if e.category==ext or e.category in secondary: + + # Core things promoted from the extension are also relevant + if t.source: + e = t.source + if e.extension==ext or e.extension in secondary: return True + return False -funcs = [f for f in funcs.itervalues() if is_relevant(f)] +funcs = [t for t in things.itervalues() if t.kind==Thing.FUNCTION and is_relevant(t)] funcs.sort(key=(lambda f: f.name)) +enums = [e for e in enums if is_relevant(e)] +enums.sort(key=(lambda e: e.value)) -for f in funcs: +for t in itertools.chain(funcs, enums): if not ver: - ver = f.version + ver = t.version - if f.category and not f.name.endswith(exttype): - bp_ext = f.category + # Things in backport extensions don't acquire an extension suffix + if t.extension and not t.name.endswith(exttype): + backport_ext = t.extension - if f.extfunc: - f.typedef = "PFN%sPROC"%f.extfunc.name.upper() +for f in funcs: + if f.source: + # Typedefs for early core functions are not available in all + # implementations + f.typedef = "PFN%sPROC"%f.source.name.upper() else: f.typedef = "PFN%sPROC"%f.name.upper() if ver: ver = map(int, ver.split('.')) +### Output ### + out = file(out_base+".h", "w") out.write("#ifndef MSP_GL_%s_\n"%ext.upper()) out.write("#define MSP_GL_%s_\n"%ext.upper()) @@ -178,10 +238,22 @@ namespace Msp { namespace GL { """) -if funcs: - out.write("\n") -for f in funcs: - out.write("extern %s %s;\n"%(f.typedef, f.name)) +if funcs or enums: + out.write("\n#ifndef GL_%s\n"%ext) + for f in funcs: + out.write("typedef int (*%s)(...);\n"%f.typedef) + if funcs and enums: + out.write("\n") + for e in enums: + out.write("#define %s 0x%04X\n"%(e.name, e.value)) + out.write("#endif\n\n") + + # Apple's OpenGL implementation doesn't have a GetProcAddress function; link + # directly to the OpenGL library + out.write("\n#if !defined(__APPLE__) || !defined(GL_%s)\n"%ext) + for f in funcs: + out.write("extern %s %s;\n"%(f.typedef, f.name)) + out.write("#endif\n") out.write("\nextern Extension %s;\n"%ext) @@ -201,29 +273,38 @@ namespace GL { """) if funcs: - out.write("\n") -for f in funcs: - out.write("%s %s = 0;\n"%(f.typedef, f.name)) + out.write("\n#if !defined(__APPLE__) || !defined(GL_%s)\n"%ext) + for f in funcs: + out.write("%s %s = 0;\n"%(f.typedef, f.name)) + out.write("\n#endif\n") out.write("\nExtension::SupportLevel init_%s()\n{\n"%ext.lower()) +out.write("#ifdef GL_%s\n"%ext) if ver: out.write("\tif(is_version_at_least(%d, %d)"%tuple(ver)) - if bp_ext: - out.write(" || is_supported(\"GL_%s\")"%bp_ext) + if backport_ext: + out.write(" || is_supported(\"GL_%s\")"%backport_ext) out.write(")\n\t{\n") - for f in funcs: - out.write("\t\t%s = reinterpret_cast<%s>(get_proc_address(\"%s\"));\n"%(f.name, f.typedef, f.name)) + if funcs: + out.write("#ifndef __APPLE__\n") + for f in funcs: + out.write("\t\t%s = reinterpret_cast<%s>(get_proc_address(\"%s\"));\n"%(f.name, f.typedef, f.name)) + out.write("#endif\n") out.write("\t\treturn Extension::CORE;\n") out.write("\t}\n") -if ext!=bp_ext: +if ext!=backport_ext: out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(ext)) - for f in funcs: - n = f.name - if f.extfunc: - n = f.extfunc.name - out.write("\t\t%s = reinterpret_cast<%s>(get_proc_address(\"%s\"));\n"%(f.name, f.typedef, n)) + if funcs: + out.write("#ifndef __APPLE__\n") + for f in funcs: + n = f.name + if f.source: + n = f.source.name + out.write("\t\t%s = reinterpret_cast<%s>(get_proc_address(\"%s\"));\n"%(f.name, f.typedef, n)) + out.write("#endif\n") out.write("\t\treturn Extension::EXTENSION;\n") out.write("\t}\n") +out.write("#endif\n") out.write("\treturn Extension::UNSUPPORTED;\n") out.write("}\n")