X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=scripts%2Fextgen.py;h=fbb66815ae1de93102485065bace98bde781b05f;hb=67538c60b8baa6816b8ae2d343ae62d881e6c58d;hp=f349d5251473a8f147d3af9edf082a636e89a6fd;hpb=4acc43935d3b19bae688e89ed42119e326a26f2d;p=libs%2Fgl.git diff --git a/scripts/extgen.py b/scripts/extgen.py index f349d525..fbb66815 100755 --- a/scripts/extgen.py +++ b/scripts/extgen.py @@ -1,40 +1,394 @@ #!/usr/bin/python import sys +import os +import xml.dom +import xml.dom.minidom +import itertools -ext = sys.argv[1] +### Command line processing ### -funcs = [] -cur_func = None -for line in file("gl.spec"): - if line[0]=='#' or line.find(':')>=0: - continue - elif line[0]=='\t' and cur_func: +if len(sys.argv)<2: + print """Usage: + extgen.py [api] [] [ ...] + extgen.py [api] [] + +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. + +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) + +target_api = "gl" + +i = 1 +if sys.argv[i].startswith("gl"): + target_api = sys.argv[i] + i += 1 + +target_ext = sys.argv[i] +out_base = None +if target_ext.endswith(".glext"): + fn = target_ext + target_ext = None + core_version = None + secondary = [] + for line in open(fn): parts = line.split() - if parts[0]=="category" and parts[1]==ext: - funcs.append(cur_func) + if parts[0]=="extension": + target_ext = parts[1] + elif parts[0]=="core_version": + if parts[1]==target_api: + core_version = parts[2] + elif parts[0]=="secondary": + secondary.append(parts[1]) + if i+10: - cur_func = line[:paren] + return target_api + +for e in enums: + if all(v=="ext" for v in e.supported_apis.values()) and e.value in core_enums_by_value: + if core_enums_by_value[e.value] is None: + candidates = [ce for ce in core_enums if ce.value==e.value] + key_api = get_key_api(candidates) + core_enums_by_value[e.value] = list(sorted(candidates, key=(lambda x: x.supported_apis.get(key_api, "ext")))) + for ce in core_enums_by_value[e.value]: + if ce.bitmask==e.bitmask: + e.aliases.append(ce.name) + break + +# Create references from core things to their extension counterparts +for t in things.itervalues(): + if t.extension: + for a in t.aliases: + alias = things.get(a) + if alias: + if target_api in t.supported_apis: + alias.sources.insert(0, t) + else: + alias.sources.append(t) + +# Find the things we want to include in this extension +def is_relevant(t): + # Unpromoted extension things are relevant + if t.extension and t.extension==target_ext and not t.aliases: + return True + + # Core things promoted from the extension are also relevant + for s in t.sources: + if s.extension==target_ext or s.extension.name in secondary: + return True + + return False -out = file(ext.lower()+".h", "w") -out.write("#ifndef MSP_GL_%s_\n"%ext.upper()) -out.write("#define MSP_GL_%s_\n"%ext.upper()) +funcs = [t for t in things.itervalues() if t.kind==Thing.FUNCTION and is_relevant(t)] +funcs.sort(key=(lambda f: f.name)) +enums = filter(is_relevant, enums) +enums.sort(key=(lambda e: e.value)) + +# Some final preparations for creating the files +for t in itertools.chain(funcs, enums): + if target_api in t.supported_apis and t.supported_apis[target_api]!="ext": + t.version = t.supported_apis[target_api] + if not core_version: + core_version = t.version + + # Things in backport extensions don't acquire an extension suffix + if t.extension and not t.name.endswith(ext_type) and target_api in t.supported_apis: + backport_ext = t.extension + +for f in funcs: + f.typedef = "FPtr_%s"%f.name + +if target_api in target_ext.supported_apis: + source_ext = target_ext +else: + candidates = {} + for t in itertools.chain(funcs, enums): + for s in t.sources: + if target_api in s.supported_apis: + candidates[s.extension.name] = candidates.get(s.extension.name, 0)+1 + if candidates: + source_ext = extensions[max(candidates.iteritems(), key=(lambda x: x[1]))[0]] + else: + source_ext = None + +### Output ### + +out = file(out_base+".h", "w") +out.write("#ifndef MSP_GL_%s_\n"%target_ext.name.upper()) +out.write("#define MSP_GL_%s_\n"%target_ext.name.upper()) out.write(""" -#include "gl.h" -#include +#include +#include namespace Msp { namespace GL { """) -for f in funcs: - out.write("extern PFNGL%sPROC gl%s;\n"%(f.upper(), f)) +if funcs or enums: + if funcs: + for f in funcs: + out.write("typedef %s (*%s)(%s);\n"%(f.return_type, f.typedef, ", ".join(f.params))) + out.write("\n") -out.write("\nvoid init_%s();\n"%ext.lower()) + if enums: + api_prefix = "GL" + if target_api=="gles2": + api_prefix = "GL_ES" + + enums_by_category = {} + for e in enums: + cat = None + if e.version: + cat = api_prefix+"_VERSION_"+"_".join(map(str, e.version)) + elif e.extension: + cat = "GL_"+e.extension.name + enums_by_category.setdefault(cat, []).append(e) + + for cat in sorted(enums_by_category.keys()): + if cat: + out.write("#ifndef %s\n"%cat) + for e in enums_by_category[cat]: + out.write("#define %s 0x%04X\n"%(e.name, e.value)) + if cat: + out.write("#endif\n") + out.write("\n") + + for f in funcs: + out.write("extern %s %s;\n"%(f.typedef, f.name)) + +out.write("extern Extension %s;\n"%target_ext.name) out.write(""" } // namespace GL @@ -43,10 +397,17 @@ out.write(""" #endif """) -out = file(ext.lower()+".cpp", "w") -out.write("#include \"extension.h\"\n") -out.write("#include \"%s.h\"\n"%ext.lower()) +out = file(out_base+".cpp", "w") +out.write("#include \"%s.h\"\n"%target_ext.name.lower()) +if funcs: + out.write(""" +#ifdef __APPLE__ +#define GET_PROC_ADDRESS(x) ::x +#else +#define GET_PROC_ADDRESS(x) get_proc_address(#x) +#endif +""") out.write(""" namespace Msp { namespace GL { @@ -54,13 +415,34 @@ namespace GL { """) for f in funcs: - out.write("PFNGL%sPROC gl%s = 0;\n"%(f.upper(), f)) + out.write("%s %s = 0;\n"%(f.typedef, f.name)) -out.write("\nvoid init_%s()\n{\n"%ext.lower()) -for f in funcs: - out.write("\tgl%s = reinterpret_cast(get_proc_address(\"gl%s\"));\n"%(f, f.upper(), f)) +out.write("\nExtension::SupportLevel init_%s()\n{\n"%target_ext.name.lower()) +if core_version: + out.write("\tif(is_version_at_least(%d, %d)"%tuple(core_version)) + if backport_ext: + out.write(" || is_supported(\"GL_%s\")"%backport_ext.name) + out.write(")\n\t{\n") + for f in funcs: + if f.version or target_api in f.supported_apis: + out.write("\t\t%s = reinterpret_cast<%s>(GET_PROC_ADDRESS(%s));\n"%(f.name, f.typedef, f.name)) + out.write("\t\treturn Extension::CORE;\n") + out.write("\t}\n") +if source_ext and source_ext!=backport_ext: + out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(source_ext.name)) + for f in funcs: + s = f + if f.sources: + s = f.sources[0] + if s.version or target_api in s.supported_apis: + out.write("\t\t%s = reinterpret_cast<%s>(GET_PROC_ADDRESS(%s));\n"%(f.name, f.typedef, s.name)) + out.write("\t\treturn Extension::EXTENSION;\n") + out.write("\t}\n") +out.write("\treturn Extension::UNSUPPORTED;\n") out.write("}\n") +out.write("\nExtension %s(\"GL_%s\", init_%s);\n"%(target_ext.name, target_ext.name, target_ext.name.lower())) + out.write(""" } // namespace GL } // namespace Msp