blob: 77015f69020a997c54029c837203be1acd30764b [file] [log] [blame]
Chia-I Wufb2559d2014-08-01 11:19:52 +08001#!/usr/bin/env python3
Chia-I Wu44e42362014-09-02 08:32:09 +08002#
3# XGL
4#
5# Copyright (C) 2014 LunarG, Inc.
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11# and/or sell copies of the Software, and to permit persons to whom the
12# Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice shall be included
15# in all copies or substantial portions of the Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23# DEALINGS IN THE SOFTWARE.
24#
25# Authors:
26# Chia-I Wu <olv@lunarg.com>
Chia-I Wufb2559d2014-08-01 11:19:52 +080027
28import sys
29
30import xgl
31
32class Subcommand(object):
33 def __init__(self, argv):
34 self.argv = argv
Chia-I Wuec30dcb2015-01-01 08:46:31 +080035 self.headers = xgl.headers
36 self.protos = xgl.protos
Chia-I Wufb2559d2014-08-01 11:19:52 +080037
38 def run(self):
Chia-I Wufb2559d2014-08-01 11:19:52 +080039 print(self.generate())
40
41 def generate(self):
42 copyright = self.generate_copyright()
43 header = self.generate_header()
44 body = self.generate_body()
45 footer = self.generate_footer()
46
47 contents = []
48 if copyright:
49 contents.append(copyright)
50 if header:
51 contents.append(header)
52 if body:
53 contents.append(body)
54 if footer:
55 contents.append(footer)
56
57 return "\n\n".join(contents)
58
59 def generate_copyright(self):
60 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
61
62/*
63 * XGL
64 *
65 * Copyright (C) 2014 LunarG, Inc.
66 *
67 * Permission is hereby granted, free of charge, to any person obtaining a
68 * copy of this software and associated documentation files (the "Software"),
69 * to deal in the Software without restriction, including without limitation
70 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
71 * and/or sell copies of the Software, and to permit persons to whom the
72 * Software is furnished to do so, subject to the following conditions:
73 *
74 * The above copyright notice and this permission notice shall be included
75 * in all copies or substantial portions of the Software.
76 *
77 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
78 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
80 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
82 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
83 * DEALINGS IN THE SOFTWARE.
84 */"""
85
86 def generate_header(self):
Chia-I Wu6ae460f2014-09-13 13:36:06 +080087 return "\n".join(["#include <" + h + ">" for h in self.headers])
Chia-I Wufb2559d2014-08-01 11:19:52 +080088
89 def generate_body(self):
90 pass
91
92 def generate_footer(self):
93 pass
94
Chia-I Wud4a76ae2015-01-04 10:15:48 +080095class LoaderEntrypointsSubcommand(Subcommand):
Chia-I Wu26864352015-01-02 00:21:24 +080096 def generate_header(self):
97 return "#include \"loader.h\""
98
99 def _generate_loader_dispatch_entrypoints(self, qual=""):
Chia-I Wu468e3c32014-08-04 08:03:57 +0800100 if qual:
101 qual += " "
102
Chia-I Wudac3e492014-08-02 23:49:43 +0800103 funcs = []
104 for proto in self.protos:
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700105 if not xgl.is_dispatchable(proto):
106 continue
107 decl = proto.c_func(prefix="xgl", attr="XGLAPI")
108 stmt = "(*disp)->%s" % proto.c_call()
Chia-I Wu26864352015-01-02 00:21:24 +0800109 if proto.name == "CreateDevice":
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700110 funcs.append("%s%s\n"
111 "{\n"
Jon Ashburn10053332014-11-17 10:17:37 -0700112 " loader_activate_layers(%s, %s);\n"
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700113 " XGL_BASE_LAYER_OBJECT* wrapped_obj = (XGL_BASE_LAYER_OBJECT*)%s;\n"
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700114 " const XGL_LAYER_DISPATCH_TABLE **disp =\n"
115 " (const XGL_LAYER_DISPATCH_TABLE **) wrapped_obj->baseObject;\n"
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700116 " %s = wrapped_obj->nextObject;\n"
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700117 " XGL_RESULT res = %s;\n"
118 " *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;\n"
119 " return res;\n"
120 "}" % (qual, decl, proto.params[0].name, proto.params[1].name,
121 proto.params[0].name, proto.params[0].name, stmt,
122 proto.params[-1].name))
123 elif xgl.does_function_create_object(proto.name) and qual == "LOADER_EXPORT ":
124 funcs.append("%s%s\n"
125 "{\n"
126 " const XGL_LAYER_DISPATCH_TABLE **disp =\n"
127 " (const XGL_LAYER_DISPATCH_TABLE **) %s;\n"
128 " XGL_RESULT res = %s;\n"
Jon Ashburn5863b732015-01-06 09:24:44 -0700129 % (qual, decl, proto.params[0].name, stmt))
130 if proto.name == "WsiX11CreatePresentableImage":
131 funcs.append(
132 " *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;\n"
133 % ( proto.params[-2].name))
134 funcs.append(
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700135 " *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;\n"
136 " return res;\n"
Jon Ashburn5863b732015-01-06 09:24:44 -0700137 "}" % ( proto.params[-1].name))
Chia-I Wu26864352015-01-02 00:21:24 +0800138 elif proto.name == "GetMultiGpuCompatibility":
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700139 funcs.append("%s%s\n"
140 "{\n"
141 " XGL_BASE_LAYER_OBJECT* wrapped_obj0 = (XGL_BASE_LAYER_OBJECT*)%s;\n"
142 " XGL_BASE_LAYER_OBJECT* wrapped_obj1 = (XGL_BASE_LAYER_OBJECT*)%s;\n"
143 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
144 " (const XGL_LAYER_DISPATCH_TABLE * const *) wrapped_obj0->baseObject;\n"
145 " %s = wrapped_obj0->nextObject;\n"
146 " %s = wrapped_obj1->nextObject;\n"
147 " return %s;\n"
148 "}" % (qual, decl, proto.params[0].name, proto.params[1].name,
149 proto.params[0].name, proto.params[1].name, stmt))
Chia-I Wu26864352015-01-02 00:21:24 +0800150 elif proto.params[0].ty != "XGL_PHYSICAL_GPU":
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700151 if proto.ret != "XGL_VOID":
152 stmt = "return " + stmt
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700153 funcs.append("%s%s\n"
154 "{\n"
155 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
156 " (const XGL_LAYER_DISPATCH_TABLE * const *) %s;\n"
157 " %s;\n"
158 "}" % (qual, decl, proto.params[0].name, stmt))
159 else:
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700160 if proto.ret != "XGL_VOID":
161 stmt = "return " + stmt
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700162 funcs.append("%s%s\n"
163 "{\n"
164 " XGL_BASE_LAYER_OBJECT* wrapped_obj = (XGL_BASE_LAYER_OBJECT*)%s;\n"
165 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
166 " (const XGL_LAYER_DISPATCH_TABLE * const *) wrapped_obj->baseObject;\n"
167 " %s = wrapped_obj->nextObject;\n"
168 " %s;\n"
169 "}" % (qual, decl, proto.params[0].name, proto.params[0].name, stmt))
Chia-I Wudac3e492014-08-02 23:49:43 +0800170
171 return "\n\n".join(funcs)
172
Chia-I Wufb2559d2014-08-01 11:19:52 +0800173 def generate_body(self):
Chia-I Wu26864352015-01-02 00:21:24 +0800174 body = [self._generate_loader_dispatch_entrypoints("LOADER_EXPORT")]
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600175
176 return "\n\n".join(body)
177
Chia-I Wu28b8d8c2015-01-04 10:19:50 +0800178class DispatchTableOpsSubcommand(Subcommand):
179 def run(self):
180 if len(self.argv) != 1:
181 print("DispatchTableOpsSubcommand: <prefix> unspecified")
182 return
183
184 self.prefix = self.argv[0]
185 super().run()
186
187 def generate_header(self):
188 return "\n".join(["#include <xgl.h>",
189 "#include <xglLayer.h>",
190 "#include <string.h>"])
191
192 def _generate_init(self):
193 stmts = []
194 for proto in self.protos:
195 if proto.name == "GetProcAddr":
196 stmts.append("table->%s = gpa; /* direct assignment */" %
197 proto.name)
198 else:
199 stmts.append("table->%s = (%sType) gpa(gpu, \"xgl%s\");" %
200 (proto.name, proto.name, proto.name))
201
202 func = []
203 func.append("static inline void %s_initialize_dispatch_table(XGL_LAYER_DISPATCH_TABLE *table,"
204 % self.prefix)
205 func.append("%s GetProcAddrType gpa,"
206 % (" " * len(self.prefix)))
207 func.append("%s XGL_PHYSICAL_GPU gpu)"
208 % (" " * len(self.prefix)))
209 func.append("{")
210 func.append(" %s" % "\n ".join(stmts))
211 func.append("}")
212
213 return "\n".join(func)
214
215 def _generate_lookup(self):
216 lookups = []
217 for proto in self.protos:
218 lookups.append("if (!strcmp(name, \"%s\"))" % (proto.name))
219 lookups.append(" return (void *) table->%s;"
220 % (proto.name))
221
222 func = []
223 func.append("static inline void *%s_lookup_dispatch_table(const XGL_LAYER_DISPATCH_TABLE *table,"
224 % self.prefix)
225 func.append("%s const char *name)"
226 % (" " * len(self.prefix)))
227 func.append("{")
228 func.append(" if (!name || name[0] != 'x' || name[1] != 'g' || name[2] != 'l')")
229 func.append(" return NULL;")
230 func.append("")
231 func.append(" name += 3;")
232 func.append(" %s" % "\n ".join(lookups))
233 func.append("")
234 func.append(" return NULL;")
235 func.append("}")
236
237 return "\n".join(func)
238
239 def generate_body(self):
240 body = [self._generate_init(),
241 self._generate_lookup()]
242
243 return "\n\n".join(body)
244
Chia-I Wu731517d2015-01-03 23:48:15 +0800245class IcdDummyEntrypointsSubcommand(Subcommand):
Chia-I Wu30c78292014-08-04 10:08:08 +0800246 def run(self):
Chia-I Wu731517d2015-01-03 23:48:15 +0800247 if len(self.argv) == 1:
248 self.prefix = self.argv[0]
249 self.qual = "static"
250 else:
251 self.prefix = "xgl"
252 self.qual = "ICD_EXPORT"
Chia-I Wu30c78292014-08-04 10:08:08 +0800253
254 super().run()
255
256 def generate_header(self):
257 return "#include \"icd.h\""
258
259 def _generate_stub_decl(self, proto):
Chia-I Wu77c5cdf2015-01-04 12:05:41 +0800260 return proto.c_pretty_decl(self.prefix + proto.name, attr="XGLAPI")
Chia-I Wu30c78292014-08-04 10:08:08 +0800261
262 def _generate_stubs(self):
263 stubs = []
264 for proto in self.protos:
Chia-I Wu30c78292014-08-04 10:08:08 +0800265 decl = self._generate_stub_decl(proto)
266 if proto.ret != "XGL_VOID":
Chia-I Wu731517d2015-01-03 23:48:15 +0800267 stmt = " return XGL_ERROR_UNKNOWN;\n"
Chia-I Wu30c78292014-08-04 10:08:08 +0800268 else:
269 stmt = ""
270
Chia-I Wu731517d2015-01-03 23:48:15 +0800271 stubs.append("%s %s\n{\n%s}" % (self.qual, decl, stmt))
Chia-I Wu30c78292014-08-04 10:08:08 +0800272
273 return "\n\n".join(stubs)
274
Chia-I Wu30c78292014-08-04 10:08:08 +0800275 def generate_body(self):
Chia-I Wu731517d2015-01-03 23:48:15 +0800276 return self._generate_stubs()
Chia-I Wu30c78292014-08-04 10:08:08 +0800277
Chia-I Wu58f20852015-01-04 00:11:17 +0800278class IcdGetProcAddrSubcommand(IcdDummyEntrypointsSubcommand):
279 def generate_header(self):
280 return "\n".join(["#include <string.h>", "#include \"icd.h\""])
281
282 def generate_body(self):
283 for proto in self.protos:
284 if proto.name == "GetProcAddr":
285 gpa_proto = proto
286
287 gpa_decl = self._generate_stub_decl(gpa_proto)
288 gpa_pname = gpa_proto.params[-1].name
289
290 lookups = []
291 for proto in self.protos:
292 lookups.append("if (!strcmp(%s, \"%s\"))" %
293 (gpa_pname, proto.name))
294 lookups.append(" return (%s) %s%s;" %
295 (gpa_proto.ret, self.prefix, proto.name))
296
297 body = []
298 body.append("%s %s" % (self.qual, gpa_decl))
299 body.append("{")
300 body.append(" if (!%s || %s[0] != 'x' || %s[1] != 'g' || %s[2] != 'l')" %
301 (gpa_pname, gpa_pname, gpa_pname, gpa_pname))
302 body.append(" return NULL;")
303 body.append("")
304 body.append(" %s += 3;" % gpa_pname)
305 body.append(" %s" % "\n ".join(lookups))
306 body.append("")
307 body.append(" return NULL;")
308 body.append("}")
309
310 return "\n".join(body)
311
Chia-I Wufb2559d2014-08-01 11:19:52 +0800312def main():
313 subcommands = {
Chia-I Wud4a76ae2015-01-04 10:15:48 +0800314 "loader-entrypoints": LoaderEntrypointsSubcommand,
Chia-I Wu28b8d8c2015-01-04 10:19:50 +0800315 "dispatch-table-ops": DispatchTableOpsSubcommand,
Chia-I Wu731517d2015-01-03 23:48:15 +0800316 "icd-dummy-entrypoints": IcdDummyEntrypointsSubcommand,
Chia-I Wu58f20852015-01-04 00:11:17 +0800317 "icd-get-proc-addr": IcdGetProcAddrSubcommand,
Chia-I Wufb2559d2014-08-01 11:19:52 +0800318 }
319
320 if len(sys.argv) < 2 or sys.argv[1] not in subcommands:
321 print("Usage: %s <subcommand> [options]" % sys.argv[0])
322 print
323 print("Available sucommands are: %s" % " ".join(subcommands))
324 exit(1)
325
326 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
327 subcmd.run()
328
329if __name__ == "__main__":
330 main()