import sys
-ext = sys.argv[1]
+if len(sys.argv)<2:
+ print """Usage:
+ extgen.py <extension> [<version>] [<secondary> ...]"
+
+Reads gl.spec and generates files to use <extension>. Any promoted functions
+are exposed with their promoted names. If <secondary> extensions are given,
+any promoted functions from those are pulled in as well. <version> can be
+given to override the version where <extension> was promoted to core."""
+ sys.exit(0)
-funcs = []
+ext = sys.argv[1]
+exttype = ext.split('_')[0]
+secondary = sys.argv[2:]
+ver = None
+if secondary and secondary[0][0].isdigit():
+ ver = secondary.pop(0)
+bp_ext = None
+
+class Function:
+ def __init__(self, name):
+ self.name = name
+ self.version = None
+ self.category = None
+ self.vectorequiv = None
+ self.aliases = []
+ self.extfunc = None
+
+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:
- parts = line.split()
- if parts[0]=="category" and parts[1]==ext:
- funcs.append(cur_func)
- else:
- paren = line.find('(')
- if paren>0:
- cur_func = line[:paren]
+
+def parse_file(fn):
+ for line in open(fn):
+ if line[0]=='#' or line.find(':')>=0:
+ continue
+ elif line[0]=='\t':
+ if cur_func:
+ parts = line.split()
+ if parts[0]=="category":
+ cur_func.category = parts[1]
+ elif parts[0]=="vectorequiv":
+ cur_func.vectorequiv = parts[1]
+ elif parts[0]=="alias":
+ cur_func.aliases.append(parts[1])
+ elif parts[0]=="version":
+ cur_func.version = parts[1]
+ elif parts[0]=="delete":
+ del funcs[cur_func.name]
+ cur_func = None
+ else:
+ paren = line.find('(')
+ if paren>0:
+ name = line[:paren]
+ if name in funcs:
+ cur_func = funcs[name]
+ else:
+ cur_func = Function(name)
+ funcs[name] = cur_func
+
+parse_file("gl.spec")
+parse_file("gl.spec.fixes")
+
+for f in funcs.itervalues():
+ if f.category==ext or f.category in secondary:
+ if not f.aliases and f.vectorequiv:
+ for g in funcs.itervalues():
+ if g!=f and g.vectorequiv==f.vectorequiv and f.name.startswith(g.name):
+ f.aliases.append(g.name)
+ break
+
+ for a in f.aliases:
+ if a in funcs:
+ funcs[a].extfunc = f
+
+def is_relevant(f):
+ if f.category==ext and not f.aliases:
+ return True
+ if f.extfunc:
+ e = f.extfunc
+ if e.category==ext or e.category in secondary:
+ return True
+ return False
+
+funcs = [f for f in funcs.itervalues() if is_relevant(f)]
+funcs.sort(key=(lambda f: f.name))
+
+for f in funcs:
+ if f.extfunc:
+ if not ver:
+ ver = f.version
+ if not f.category.startswith("VERSION_"):
+ bp_ext = f.category
+ if not f.extfunc and not f.name.endswith(exttype):
+ bp_ext = f.category
+
+if ver:
+ ver = map(int, ver.split('.'))
out = file(ext.lower()+".h", "w")
out.write("#ifndef MSP_GL_%s_\n"%ext.upper())
out.write("#define MSP_GL_%s_\n"%ext.upper())
out.write("""
+#include "extension.h"
#include "gl.h"
#include <GL/glext.h>
namespace Msp {
namespace GL {
-
""")
+if funcs:
+ out.write("\n")
for f in funcs:
- out.write("extern PFNGL%sPROC gl%s;\n"%(f.upper(), f))
+ out.write("extern PFNGL%sPROC gl%s;\n"%(f.name.upper(), f.name))
-out.write("\nvoid init_%s();\n"%ext.lower())
+out.write("\nextern Extension %s;\n"%ext)
out.write("""
} // namespace GL
""")
out = file(ext.lower()+".cpp", "w")
-out.write("#include \"extension.h\"\n")
out.write("#include \"%s.h\"\n"%ext.lower())
out.write("""
namespace Msp {
namespace GL {
-
""")
+if funcs:
+ out.write("\n")
for f in funcs:
- out.write("PFNGL%sPROC gl%s = 0;\n"%(f.upper(), f))
-
-out.write("\nvoid init_%s()\n{\n"%ext.lower())
-for f in funcs:
- out.write("\tgl%s = reinterpret_cast<PFNGL%sPROC>(get_proc_address(\"gl%s\"));\n"%(f, f.upper(), f))
+ out.write("PFNGL%sPROC gl%s = 0;\n"%(f.name.upper(), f.name))
+
+out.write("\nExtension::SupportLevel init_%s()\n{\n"%ext.lower())
+if ver:
+ out.write("\tif(is_version_at_least(%d, %d)"%tuple(ver))
+ if bp_ext:
+ out.write(" || is_supported(\"GL_%s\")"%bp_ext)
+ out.write(")\n\t{\n")
+ for f in funcs:
+ out.write("\t\tgl%s = reinterpret_cast<PFNGL%sPROC>(get_proc_address(\"gl%s\"));\n"%(f.name, f.name.upper(), f.name))
+ out.write("\t\treturn Extension::CORE;\n")
+ out.write("\t}\n")
+if ext!=bp_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\tgl%s = reinterpret_cast<PFNGL%sPROC>(get_proc_address(\"gl%s\"));\n"%(f.name, f.name.upper(), n))
+ 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"%(ext, ext, ext.lower()))
+
out.write("""
} // namespace GL
} // namespace Msp