]> git.tdb.fi Git - libs/gl.git/blob - scripts/extgen.py
Complete rewrite of extension handling
[libs/gl.git] / scripts / extgen.py
1 #!/usr/bin/python
2
3 import sys
4
5 if len(sys.argv)<2:
6         print """Usage:
7   extgen.py <extension> [<version>] [<secondary> ...]"
8
9 Reads gl.spec and generates files to use <extension>.  Any promoted functions
10 are exposed with their promoted names.  If <secondary> extensions are given,
11 any promoted functions from those are pulled in as well.  <version> can be
12 given to override the version where <extension> was promoted to core."""
13         sys.exit(0)
14
15 ext = sys.argv[1]
16 exttype = ext.split('_')[0]
17 secondary = sys.argv[2:]
18 ver = None
19 if secondary and secondary[0][0].isdigit():
20         ver = secondary.pop(0)
21 bp_ext = None
22
23 class Function:
24         def __init__(self, name):
25                 self.name = name
26                 self.version = None
27                 self.category = None
28                 self.vectorequiv = None
29                 self.aliases = []
30                 self.extfunc = None
31
32 funcs = {}
33 cur_func = None
34
35 def parse_file(fn):
36         for line in open(fn):
37                 if line[0]=='#' or line.find(':')>=0:
38                         continue
39                 elif line[0]=='\t':
40                         if cur_func:
41                                 parts = line.split()
42                                 if parts[0]=="category":
43                                         cur_func.category = parts[1]
44                                 elif parts[0]=="vectorequiv":
45                                         cur_func.vectorequiv = parts[1]
46                                 elif parts[0]=="alias":
47                                         cur_func.aliases.append(parts[1])
48                                 elif parts[0]=="version":
49                                         cur_func.version = parts[1]
50                                 elif parts[0]=="delete":
51                                         del funcs[cur_func.name]
52                                         cur_func = None
53                 else:
54                         paren = line.find('(')
55                         if paren>0:
56                                 name = line[:paren]
57                                 if name in funcs:
58                                         cur_func = funcs[name]
59                                 else:
60                                         cur_func = Function(name)
61                                         funcs[name] = cur_func
62
63 parse_file("gl.spec")
64 parse_file("gl.spec.fixes")
65
66 for f in funcs.itervalues():
67         if f.category==ext or f.category in secondary:
68                 if not f.aliases and f.vectorequiv:
69                         for g in funcs.itervalues():
70                                 if g!=f and g.vectorequiv==f.vectorequiv and f.name.startswith(g.name):
71                                         f.aliases.append(g.name)
72                                         break
73
74                 for a in f.aliases:
75                         if a in funcs:
76                                 funcs[a].extfunc = f
77
78 def is_relevant(f):
79         if f.category==ext and not f.aliases:
80                 return True
81         if f.extfunc:
82                 e = f.extfunc
83                 if e.category==ext or e.category in secondary:
84                         return True
85         return False
86
87 funcs = [f for f in funcs.itervalues() if is_relevant(f)]
88 funcs.sort(key=(lambda f: f.name))
89
90 for f in funcs:
91         if f.extfunc:
92                 if not ver:
93                         ver = f.version
94                 if not f.category.startswith("VERSION_"):
95                         bp_ext = f.category
96         if not f.extfunc and not f.name.endswith(exttype):
97                 bp_ext = f.category
98
99 if ver:
100         ver = map(int, ver.split('.'))
101
102 out = file(ext.lower()+".h", "w")
103 out.write("#ifndef MSP_GL_%s_\n"%ext.upper())
104 out.write("#define MSP_GL_%s_\n"%ext.upper())
105
106 out.write("""
107 #include "extension.h"
108 #include "gl.h"
109 #include <GL/glext.h>
110
111 namespace Msp {
112 namespace GL {
113 """)
114
115 if funcs:
116         out.write("\n")
117 for f in funcs:
118         out.write("extern PFNGL%sPROC gl%s;\n"%(f.name.upper(), f.name))
119
120 out.write("\nextern Extension %s;\n"%ext)
121
122 out.write("""
123 } // namespace GL
124 } // namespace Msp
125
126 #endif
127 """)
128
129 out = file(ext.lower()+".cpp", "w")
130 out.write("#include \"%s.h\"\n"%ext.lower())
131
132 out.write("""
133 namespace Msp {
134 namespace GL {
135 """)
136
137 if funcs:
138         out.write("\n")
139 for f in funcs:
140         out.write("PFNGL%sPROC gl%s = 0;\n"%(f.name.upper(), f.name))
141
142 out.write("\nExtension::SupportLevel init_%s()\n{\n"%ext.lower())
143 if ver:
144         out.write("\tif(is_version_at_least(%d, %d)"%tuple(ver))
145         if bp_ext:
146                 out.write(" || is_supported(\"GL_%s\")"%bp_ext)
147         out.write(")\n\t{\n")
148         for f in funcs:
149                 out.write("\t\tgl%s = reinterpret_cast<PFNGL%sPROC>(get_proc_address(\"gl%s\"));\n"%(f.name, f.name.upper(), f.name))
150         out.write("\t\treturn Extension::CORE;\n")
151         out.write("\t}\n")
152 if ext!=bp_ext:
153         out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(ext))
154         for f in funcs:
155                 n = f.name
156                 if f.extfunc:
157                         n = f.extfunc.name
158                 out.write("\t\tgl%s = reinterpret_cast<PFNGL%sPROC>(get_proc_address(\"gl%s\"));\n"%(f.name, f.name.upper(), n))
159         out.write("\t\treturn Extension::EXTENSION;\n")
160         out.write("\t}\n")
161 out.write("\treturn Extension::UNSUPPORTED;\n")
162 out.write("}\n")
163
164 out.write("\nExtension %s(\"GL_%s\", init_%s);\n"%(ext, ext, ext.lower()))
165
166 out.write("""
167 } // namespace GL
168 } // namespace Msp
169 """)