]> git.tdb.fi Git - libs/gl.git/blobdiff - scripts/extgen.py
Complete rewrite of extension handling
[libs/gl.git] / scripts / extgen.py
index f349d5251473a8f147d3af9edf082a636e89a6fd..d6727123d97cb842a5836ea1b7d2f4a901396962 100755 (executable)
 
 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
@@ -44,23 +127,42 @@ out.write("""
 """)
 
 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