blob: eecf71b5bbbc11021ba394a42e53556865c14c77 [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
Chia-I Wuf7d6d3c2015-01-05 12:55:13 +080032def generate_get_proc_addr_check(name):
33 return " if (!%s || %s[0] != 'x' || %s[1] != 'g' || %s[2] != 'l')\n" \
34 " return NULL;" % ((name,) * 4)
35
Chia-I Wufb2559d2014-08-01 11:19:52 +080036class Subcommand(object):
37 def __init__(self, argv):
38 self.argv = argv
Chia-I Wuec30dcb2015-01-01 08:46:31 +080039 self.headers = xgl.headers
40 self.protos = xgl.protos
Chia-I Wufb2559d2014-08-01 11:19:52 +080041
42 def run(self):
Chia-I Wufb2559d2014-08-01 11:19:52 +080043 print(self.generate())
44
45 def generate(self):
46 copyright = self.generate_copyright()
47 header = self.generate_header()
48 body = self.generate_body()
49 footer = self.generate_footer()
50
51 contents = []
52 if copyright:
53 contents.append(copyright)
54 if header:
55 contents.append(header)
56 if body:
57 contents.append(body)
58 if footer:
59 contents.append(footer)
60
61 return "\n\n".join(contents)
62
63 def generate_copyright(self):
64 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
65
66/*
67 * XGL
68 *
69 * Copyright (C) 2014 LunarG, Inc.
70 *
71 * Permission is hereby granted, free of charge, to any person obtaining a
72 * copy of this software and associated documentation files (the "Software"),
73 * to deal in the Software without restriction, including without limitation
74 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
75 * and/or sell copies of the Software, and to permit persons to whom the
76 * Software is furnished to do so, subject to the following conditions:
77 *
78 * The above copyright notice and this permission notice shall be included
79 * in all copies or substantial portions of the Software.
80 *
81 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
82 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
83 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
84 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
85 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
86 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
87 * DEALINGS IN THE SOFTWARE.
88 */"""
89
90 def generate_header(self):
Chia-I Wu6ae460f2014-09-13 13:36:06 +080091 return "\n".join(["#include <" + h + ">" for h in self.headers])
Chia-I Wufb2559d2014-08-01 11:19:52 +080092
93 def generate_body(self):
94 pass
95
96 def generate_footer(self):
97 pass
98
Chia-I Wud4a76ae2015-01-04 10:15:48 +080099class LoaderEntrypointsSubcommand(Subcommand):
Chia-I Wu26864352015-01-02 00:21:24 +0800100 def generate_header(self):
101 return "#include \"loader.h\""
102
Chia-I Wu9e7e5542015-01-04 15:51:00 +0800103 def _does_function_create_object(self, proto):
104 out_objs = proto.object_out_params()
105 return out_objs and out_objs[-1] == proto.params[-1]
Chia-I Wu565734c2015-01-04 15:32:52 +0800106
Chia-I Wu565734c2015-01-04 15:32:52 +0800107 def _is_dispatchable(self, proto):
Chia-I Wu31b115a2015-01-04 15:38:47 +0800108 if proto.name in ["GetProcAddr", "EnumerateLayers"]:
109 return False
Chia-I Wu565734c2015-01-04 15:32:52 +0800110
Chia-I Wu31b115a2015-01-04 15:38:47 +0800111 in_objs = proto.object_in_params()
112 return in_objs and in_objs[0] == proto.params[0]
Chia-I Wu565734c2015-01-04 15:32:52 +0800113
Chia-I Wu26864352015-01-02 00:21:24 +0800114 def _generate_loader_dispatch_entrypoints(self, qual=""):
Chia-I Wu468e3c32014-08-04 08:03:57 +0800115 if qual:
116 qual += " "
117
Chia-I Wudac3e492014-08-02 23:49:43 +0800118 funcs = []
119 for proto in self.protos:
Chia-I Wu565734c2015-01-04 15:32:52 +0800120 if not self._is_dispatchable(proto):
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700121 continue
122 decl = proto.c_func(prefix="xgl", attr="XGLAPI")
123 stmt = "(*disp)->%s" % proto.c_call()
Chia-I Wu26864352015-01-02 00:21:24 +0800124 if proto.name == "CreateDevice":
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700125 funcs.append("%s%s\n"
126 "{\n"
Jon Ashburn10053332014-11-17 10:17:37 -0700127 " loader_activate_layers(%s, %s);\n"
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700128 " XGL_BASE_LAYER_OBJECT* wrapped_obj = (XGL_BASE_LAYER_OBJECT*)%s;\n"
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700129 " const XGL_LAYER_DISPATCH_TABLE **disp =\n"
130 " (const XGL_LAYER_DISPATCH_TABLE **) wrapped_obj->baseObject;\n"
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700131 " %s = wrapped_obj->nextObject;\n"
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700132 " XGL_RESULT res = %s;\n"
133 " *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;\n"
134 " return res;\n"
135 "}" % (qual, decl, proto.params[0].name, proto.params[1].name,
136 proto.params[0].name, proto.params[0].name, stmt,
137 proto.params[-1].name))
Chia-I Wu9e7e5542015-01-04 15:51:00 +0800138 elif self._does_function_create_object(proto):
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700139 funcs.append("%s%s\n"
140 "{\n"
141 " const XGL_LAYER_DISPATCH_TABLE **disp =\n"
142 " (const XGL_LAYER_DISPATCH_TABLE **) %s;\n"
143 " XGL_RESULT res = %s;\n"
Jon Ashburn5863b732015-01-06 09:24:44 -0700144 % (qual, decl, proto.params[0].name, stmt))
145 if proto.name == "WsiX11CreatePresentableImage":
146 funcs.append(
147 " *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;\n"
148 % ( proto.params[-2].name))
149 funcs.append(
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700150 " *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;\n"
151 " return res;\n"
Jon Ashburn5863b732015-01-06 09:24:44 -0700152 "}" % ( proto.params[-1].name))
Chia-I Wu26864352015-01-02 00:21:24 +0800153 elif proto.name == "GetMultiGpuCompatibility":
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700154 funcs.append("%s%s\n"
155 "{\n"
156 " XGL_BASE_LAYER_OBJECT* wrapped_obj0 = (XGL_BASE_LAYER_OBJECT*)%s;\n"
157 " XGL_BASE_LAYER_OBJECT* wrapped_obj1 = (XGL_BASE_LAYER_OBJECT*)%s;\n"
158 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
159 " (const XGL_LAYER_DISPATCH_TABLE * const *) wrapped_obj0->baseObject;\n"
160 " %s = wrapped_obj0->nextObject;\n"
161 " %s = wrapped_obj1->nextObject;\n"
162 " return %s;\n"
163 "}" % (qual, decl, proto.params[0].name, proto.params[1].name,
164 proto.params[0].name, proto.params[1].name, stmt))
Chia-I Wu26864352015-01-02 00:21:24 +0800165 elif proto.params[0].ty != "XGL_PHYSICAL_GPU":
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700166 if proto.ret != "XGL_VOID":
167 stmt = "return " + stmt
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700168 funcs.append("%s%s\n"
169 "{\n"
170 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
171 " (const XGL_LAYER_DISPATCH_TABLE * const *) %s;\n"
172 " %s;\n"
173 "}" % (qual, decl, proto.params[0].name, stmt))
174 else:
Jon Ashburnd6bfe022014-12-03 14:30:48 -0700175 if proto.ret != "XGL_VOID":
176 stmt = "return " + stmt
Tobin Ehlis66bbbf52014-11-12 11:47:07 -0700177 funcs.append("%s%s\n"
178 "{\n"
179 " XGL_BASE_LAYER_OBJECT* wrapped_obj = (XGL_BASE_LAYER_OBJECT*)%s;\n"
180 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
181 " (const XGL_LAYER_DISPATCH_TABLE * const *) wrapped_obj->baseObject;\n"
182 " %s = wrapped_obj->nextObject;\n"
183 " %s;\n"
184 "}" % (qual, decl, proto.params[0].name, proto.params[0].name, stmt))
Chia-I Wudac3e492014-08-02 23:49:43 +0800185
186 return "\n\n".join(funcs)
187
Chia-I Wufb2559d2014-08-01 11:19:52 +0800188 def generate_body(self):
Chia-I Wu26864352015-01-02 00:21:24 +0800189 body = [self._generate_loader_dispatch_entrypoints("LOADER_EXPORT")]
Jon Ashburnd43f9b62014-10-14 19:15:22 -0600190
191 return "\n\n".join(body)
192
Chia-I Wu28b8d8c2015-01-04 10:19:50 +0800193class DispatchTableOpsSubcommand(Subcommand):
194 def run(self):
195 if len(self.argv) != 1:
196 print("DispatchTableOpsSubcommand: <prefix> unspecified")
197 return
198
199 self.prefix = self.argv[0]
200 super().run()
201
202 def generate_header(self):
203 return "\n".join(["#include <xgl.h>",
204 "#include <xglLayer.h>",
205 "#include <string.h>"])
206
207 def _generate_init(self):
208 stmts = []
209 for proto in self.protos:
210 if proto.name == "GetProcAddr":
211 stmts.append("table->%s = gpa; /* direct assignment */" %
212 proto.name)
213 else:
214 stmts.append("table->%s = (%sType) gpa(gpu, \"xgl%s\");" %
215 (proto.name, proto.name, proto.name))
216
217 func = []
218 func.append("static inline void %s_initialize_dispatch_table(XGL_LAYER_DISPATCH_TABLE *table,"
219 % self.prefix)
220 func.append("%s GetProcAddrType gpa,"
221 % (" " * len(self.prefix)))
222 func.append("%s XGL_PHYSICAL_GPU gpu)"
223 % (" " * len(self.prefix)))
224 func.append("{")
225 func.append(" %s" % "\n ".join(stmts))
226 func.append("}")
227
228 return "\n".join(func)
229
230 def _generate_lookup(self):
231 lookups = []
232 for proto in self.protos:
233 lookups.append("if (!strcmp(name, \"%s\"))" % (proto.name))
234 lookups.append(" return (void *) table->%s;"
235 % (proto.name))
236
237 func = []
238 func.append("static inline void *%s_lookup_dispatch_table(const XGL_LAYER_DISPATCH_TABLE *table,"
239 % self.prefix)
240 func.append("%s const char *name)"
241 % (" " * len(self.prefix)))
242 func.append("{")
Chia-I Wuf7d6d3c2015-01-05 12:55:13 +0800243 func.append(generate_get_proc_addr_check("name"))
Chia-I Wu28b8d8c2015-01-04 10:19:50 +0800244 func.append("")
245 func.append(" name += 3;")
246 func.append(" %s" % "\n ".join(lookups))
247 func.append("")
248 func.append(" return NULL;")
249 func.append("}")
250
251 return "\n".join(func)
252
253 def generate_body(self):
254 body = [self._generate_init(),
255 self._generate_lookup()]
256
257 return "\n\n".join(body)
258
Chia-I Wu731517d2015-01-03 23:48:15 +0800259class IcdDummyEntrypointsSubcommand(Subcommand):
Chia-I Wu30c78292014-08-04 10:08:08 +0800260 def run(self):
Chia-I Wu731517d2015-01-03 23:48:15 +0800261 if len(self.argv) == 1:
262 self.prefix = self.argv[0]
263 self.qual = "static"
264 else:
265 self.prefix = "xgl"
266 self.qual = "ICD_EXPORT"
Chia-I Wu30c78292014-08-04 10:08:08 +0800267
268 super().run()
269
270 def generate_header(self):
271 return "#include \"icd.h\""
272
273 def _generate_stub_decl(self, proto):
Chia-I Wu77c5cdf2015-01-04 12:05:41 +0800274 return proto.c_pretty_decl(self.prefix + proto.name, attr="XGLAPI")
Chia-I Wu30c78292014-08-04 10:08:08 +0800275
276 def _generate_stubs(self):
277 stubs = []
278 for proto in self.protos:
Chia-I Wu30c78292014-08-04 10:08:08 +0800279 decl = self._generate_stub_decl(proto)
280 if proto.ret != "XGL_VOID":
Chia-I Wu731517d2015-01-03 23:48:15 +0800281 stmt = " return XGL_ERROR_UNKNOWN;\n"
Chia-I Wu30c78292014-08-04 10:08:08 +0800282 else:
283 stmt = ""
284
Chia-I Wu731517d2015-01-03 23:48:15 +0800285 stubs.append("%s %s\n{\n%s}" % (self.qual, decl, stmt))
Chia-I Wu30c78292014-08-04 10:08:08 +0800286
287 return "\n\n".join(stubs)
288
Chia-I Wu30c78292014-08-04 10:08:08 +0800289 def generate_body(self):
Chia-I Wu731517d2015-01-03 23:48:15 +0800290 return self._generate_stubs()
Chia-I Wu30c78292014-08-04 10:08:08 +0800291
Chia-I Wu58f20852015-01-04 00:11:17 +0800292class IcdGetProcAddrSubcommand(IcdDummyEntrypointsSubcommand):
293 def generate_header(self):
294 return "\n".join(["#include <string.h>", "#include \"icd.h\""])
295
296 def generate_body(self):
297 for proto in self.protos:
298 if proto.name == "GetProcAddr":
299 gpa_proto = proto
300
301 gpa_decl = self._generate_stub_decl(gpa_proto)
302 gpa_pname = gpa_proto.params[-1].name
303
304 lookups = []
305 for proto in self.protos:
306 lookups.append("if (!strcmp(%s, \"%s\"))" %
307 (gpa_pname, proto.name))
308 lookups.append(" return (%s) %s%s;" %
309 (gpa_proto.ret, self.prefix, proto.name))
310
311 body = []
312 body.append("%s %s" % (self.qual, gpa_decl))
313 body.append("{")
Chia-I Wuf7d6d3c2015-01-05 12:55:13 +0800314 body.append(generate_get_proc_addr_check(gpa_pname))
Chia-I Wu58f20852015-01-04 00:11:17 +0800315 body.append("")
316 body.append(" %s += 3;" % gpa_pname)
317 body.append(" %s" % "\n ".join(lookups))
318 body.append("")
319 body.append(" return NULL;")
320 body.append("}")
321
322 return "\n".join(body)
323
Chia-I Wufb2559d2014-08-01 11:19:52 +0800324def main():
325 subcommands = {
Chia-I Wud4a76ae2015-01-04 10:15:48 +0800326 "loader-entrypoints": LoaderEntrypointsSubcommand,
Chia-I Wu28b8d8c2015-01-04 10:19:50 +0800327 "dispatch-table-ops": DispatchTableOpsSubcommand,
Chia-I Wu731517d2015-01-03 23:48:15 +0800328 "icd-dummy-entrypoints": IcdDummyEntrypointsSubcommand,
Chia-I Wu58f20852015-01-04 00:11:17 +0800329 "icd-get-proc-addr": IcdGetProcAddrSubcommand,
Chia-I Wufb2559d2014-08-01 11:19:52 +0800330 }
331
332 if len(sys.argv) < 2 or sys.argv[1] not in subcommands:
333 print("Usage: %s <subcommand> [options]" % sys.argv[0])
334 print
335 print("Available sucommands are: %s" % " ".join(subcommands))
336 exit(1)
337
338 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
339 subcmd.run()
340
341if __name__ == "__main__":
342 main()