blob: a0f79923c5d993579e6cdab82334c72e88564ac3 [file] [log] [blame]
Chia-I Wufb2559d2014-08-01 11:19:52 +08001#!/usr/bin/env python3
Chia-I Wu701f3f62014-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 Wu6cdaedb2015-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 Wuc4f24e82015-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 Wu6bdf0192014-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 Wub3d5e192015-01-04 10:15:48 +080099class LoaderEntrypointsSubcommand(Subcommand):
Chia-I Wu2e4f5302015-01-02 00:21:24 +0800100 def generate_header(self):
101 return "#include \"loader.h\""
102
Chia-I Wu47e5b6d2015-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 Wu27697e42015-01-04 15:32:52 +0800106
Chia-I Wu27697e42015-01-04 15:32:52 +0800107 def _is_dispatchable(self, proto):
Chia-I Wudf2d6392015-01-04 15:38:47 +0800108 if proto.name in ["GetProcAddr", "EnumerateLayers"]:
109 return False
Chia-I Wu27697e42015-01-04 15:32:52 +0800110
Chia-I Wudf2d6392015-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 Wu27697e42015-01-04 15:32:52 +0800113
Chia-I Wu2e4f5302015-01-02 00:21:24 +0800114 def _generate_loader_dispatch_entrypoints(self, qual=""):
Chia-I Wu19300602014-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 Wu27697e42015-01-04 15:32:52 +0800120 if not self._is_dispatchable(proto):
Tobin Ehlisea7fe0b2014-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 Wu2e4f5302015-01-02 00:21:24 +0800124 if proto.name == "CreateDevice":
Tobin Ehlisea7fe0b2014-11-12 11:47:07 -0700125 funcs.append("%s%s\n"
126 "{\n"
Jon Ashburn613b0c12014-11-17 10:17:37 -0700127 " loader_activate_layers(%s, %s);\n"
Tobin Ehlisea7fe0b2014-11-12 11:47:07 -0700128 " XGL_BASE_LAYER_OBJECT* wrapped_obj = (XGL_BASE_LAYER_OBJECT*)%s;\n"
Jon Ashburne05c8c62014-12-03 14:30:48 -0700129 " const XGL_LAYER_DISPATCH_TABLE **disp =\n"
130 " (const XGL_LAYER_DISPATCH_TABLE **) wrapped_obj->baseObject;\n"
Tobin Ehlisea7fe0b2014-11-12 11:47:07 -0700131 " %s = wrapped_obj->nextObject;\n"
Jon Ashburne05c8c62014-12-03 14:30:48 -0700132 " XGL_RESULT res = %s;\n"
Jon Ashburne04fd1b2015-01-09 10:13:48 -0700133 " if (res == XGL_SUCCESS)\n"
134 " *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;\n"
Jon Ashburne05c8c62014-12-03 14:30:48 -0700135 " return res;\n"
136 "}" % (qual, decl, proto.params[0].name, proto.params[1].name,
137 proto.params[0].name, proto.params[0].name, stmt,
138 proto.params[-1].name))
Chia-I Wu47e5b6d2015-01-04 15:51:00 +0800139 elif self._does_function_create_object(proto):
Jon Ashburne04fd1b2015-01-09 10:13:48 -0700140 if proto.name == "WsiX11CreatePresentableImage":
141 obj_write_stmt = "\n *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;" % ( proto.params[-2].name)
142 else:
143 obj_write_stmt = ""
Jon Ashburne05c8c62014-12-03 14:30:48 -0700144 funcs.append("%s%s\n"
145 "{\n"
146 " const XGL_LAYER_DISPATCH_TABLE **disp =\n"
147 " (const XGL_LAYER_DISPATCH_TABLE **) %s;\n"
148 " XGL_RESULT res = %s;\n"
Jon Ashburne04fd1b2015-01-09 10:13:48 -0700149 " if (res == XGL_SUCCESS) {%s\n"
150 " *(const XGL_LAYER_DISPATCH_TABLE **) (*%s) = *disp;\n"
151 " }\n"
Jon Ashburne05c8c62014-12-03 14:30:48 -0700152 " return res;\n"
Jon Ashburne04fd1b2015-01-09 10:13:48 -0700153 "}"
154 % (qual, decl, proto.params[0].name, stmt, obj_write_stmt, proto.params[-1].name))
Chia-I Wu11078b02015-01-04 16:27:24 +0800155 elif proto.name == "AllocDescriptorSets":
156 funcs.append("%s%s\n"
157 "{\n"
158 " const XGL_LAYER_DISPATCH_TABLE **disp =\n"
159 " (const XGL_LAYER_DISPATCH_TABLE **) %s;\n"
160 " uint32_t i;\n"
161 " XGL_RESULT res = %s;\n"
162 " for (i = 0; i < *%s; i++)\n"
163 " *(const XGL_LAYER_DISPATCH_TABLE **) (%s[i]) = *disp;\n"
164 " return res;\n"
165 "}" % (qual, decl, proto.params[0].name, stmt, proto.params[-1].name, proto.params[-2].name))
Chia-I Wu2e4f5302015-01-02 00:21:24 +0800166 elif proto.name == "GetMultiGpuCompatibility":
Jon Ashburne05c8c62014-12-03 14:30:48 -0700167 funcs.append("%s%s\n"
168 "{\n"
169 " XGL_BASE_LAYER_OBJECT* wrapped_obj0 = (XGL_BASE_LAYER_OBJECT*)%s;\n"
170 " XGL_BASE_LAYER_OBJECT* wrapped_obj1 = (XGL_BASE_LAYER_OBJECT*)%s;\n"
171 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
172 " (const XGL_LAYER_DISPATCH_TABLE * const *) wrapped_obj0->baseObject;\n"
173 " %s = wrapped_obj0->nextObject;\n"
174 " %s = wrapped_obj1->nextObject;\n"
175 " return %s;\n"
176 "}" % (qual, decl, proto.params[0].name, proto.params[1].name,
177 proto.params[0].name, proto.params[1].name, stmt))
Chia-I Wu2e4f5302015-01-02 00:21:24 +0800178 elif proto.params[0].ty != "XGL_PHYSICAL_GPU":
Jon Ashburne05c8c62014-12-03 14:30:48 -0700179 if proto.ret != "XGL_VOID":
180 stmt = "return " + stmt
Tobin Ehlisea7fe0b2014-11-12 11:47:07 -0700181 funcs.append("%s%s\n"
182 "{\n"
183 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
184 " (const XGL_LAYER_DISPATCH_TABLE * const *) %s;\n"
185 " %s;\n"
186 "}" % (qual, decl, proto.params[0].name, stmt))
187 else:
Jon Ashburne05c8c62014-12-03 14:30:48 -0700188 if proto.ret != "XGL_VOID":
189 stmt = "return " + stmt
Tobin Ehlisea7fe0b2014-11-12 11:47:07 -0700190 funcs.append("%s%s\n"
191 "{\n"
192 " XGL_BASE_LAYER_OBJECT* wrapped_obj = (XGL_BASE_LAYER_OBJECT*)%s;\n"
193 " const XGL_LAYER_DISPATCH_TABLE * const *disp =\n"
194 " (const XGL_LAYER_DISPATCH_TABLE * const *) wrapped_obj->baseObject;\n"
195 " %s = wrapped_obj->nextObject;\n"
196 " %s;\n"
197 "}" % (qual, decl, proto.params[0].name, proto.params[0].name, stmt))
Chia-I Wudac3e492014-08-02 23:49:43 +0800198
199 return "\n\n".join(funcs)
200
Chia-I Wufb2559d2014-08-01 11:19:52 +0800201 def generate_body(self):
Chia-I Wu2e4f5302015-01-02 00:21:24 +0800202 body = [self._generate_loader_dispatch_entrypoints("LOADER_EXPORT")]
Jon Ashburnd38bfb12014-10-14 19:15:22 -0600203
204 return "\n\n".join(body)
205
Chia-I Wu29271d72015-01-04 10:19:50 +0800206class DispatchTableOpsSubcommand(Subcommand):
207 def run(self):
208 if len(self.argv) != 1:
209 print("DispatchTableOpsSubcommand: <prefix> unspecified")
210 return
211
212 self.prefix = self.argv[0]
213 super().run()
214
215 def generate_header(self):
216 return "\n".join(["#include <xgl.h>",
217 "#include <xglLayer.h>",
218 "#include <string.h>"])
219
220 def _generate_init(self):
221 stmts = []
222 for proto in self.protos:
223 if proto.name == "GetProcAddr":
224 stmts.append("table->%s = gpa; /* direct assignment */" %
225 proto.name)
226 else:
Mark Lobodzinski391bb6d2015-01-09 15:12:03 -0600227 stmts.append("table->%s = (xgl%sType) gpa(gpu, \"xgl%s\");" %
Chia-I Wu29271d72015-01-04 10:19:50 +0800228 (proto.name, proto.name, proto.name))
229
230 func = []
231 func.append("static inline void %s_initialize_dispatch_table(XGL_LAYER_DISPATCH_TABLE *table,"
232 % self.prefix)
Mark Lobodzinski391bb6d2015-01-09 15:12:03 -0600233 func.append("%s xglGetProcAddrType gpa,"
Chia-I Wu29271d72015-01-04 10:19:50 +0800234 % (" " * len(self.prefix)))
235 func.append("%s XGL_PHYSICAL_GPU gpu)"
236 % (" " * len(self.prefix)))
237 func.append("{")
238 func.append(" %s" % "\n ".join(stmts))
239 func.append("}")
240
241 return "\n".join(func)
242
243 def _generate_lookup(self):
244 lookups = []
245 for proto in self.protos:
246 lookups.append("if (!strcmp(name, \"%s\"))" % (proto.name))
247 lookups.append(" return (void *) table->%s;"
248 % (proto.name))
249
250 func = []
251 func.append("static inline void *%s_lookup_dispatch_table(const XGL_LAYER_DISPATCH_TABLE *table,"
252 % self.prefix)
253 func.append("%s const char *name)"
254 % (" " * len(self.prefix)))
255 func.append("{")
Chia-I Wu6cdaedb2015-01-05 12:55:13 +0800256 func.append(generate_get_proc_addr_check("name"))
Chia-I Wu29271d72015-01-04 10:19:50 +0800257 func.append("")
258 func.append(" name += 3;")
259 func.append(" %s" % "\n ".join(lookups))
260 func.append("")
261 func.append(" return NULL;")
262 func.append("}")
263
264 return "\n".join(func)
265
266 def generate_body(self):
267 body = [self._generate_init(),
268 self._generate_lookup()]
269
270 return "\n\n".join(body)
271
Chia-I Wueeb0ab62015-01-03 23:48:15 +0800272class IcdDummyEntrypointsSubcommand(Subcommand):
Chia-I Wudf3c4322014-08-04 10:08:08 +0800273 def run(self):
Chia-I Wueeb0ab62015-01-03 23:48:15 +0800274 if len(self.argv) == 1:
275 self.prefix = self.argv[0]
276 self.qual = "static"
277 else:
278 self.prefix = "xgl"
279 self.qual = "ICD_EXPORT"
Chia-I Wudf3c4322014-08-04 10:08:08 +0800280
281 super().run()
282
283 def generate_header(self):
284 return "#include \"icd.h\""
285
286 def _generate_stub_decl(self, proto):
Chia-I Wu595ada12015-01-04 12:05:41 +0800287 return proto.c_pretty_decl(self.prefix + proto.name, attr="XGLAPI")
Chia-I Wudf3c4322014-08-04 10:08:08 +0800288
289 def _generate_stubs(self):
290 stubs = []
291 for proto in self.protos:
Chia-I Wudf3c4322014-08-04 10:08:08 +0800292 decl = self._generate_stub_decl(proto)
293 if proto.ret != "XGL_VOID":
Chia-I Wueeb0ab62015-01-03 23:48:15 +0800294 stmt = " return XGL_ERROR_UNKNOWN;\n"
Chia-I Wudf3c4322014-08-04 10:08:08 +0800295 else:
296 stmt = ""
297
Chia-I Wueeb0ab62015-01-03 23:48:15 +0800298 stubs.append("%s %s\n{\n%s}" % (self.qual, decl, stmt))
Chia-I Wudf3c4322014-08-04 10:08:08 +0800299
300 return "\n\n".join(stubs)
301
Chia-I Wudf3c4322014-08-04 10:08:08 +0800302 def generate_body(self):
Chia-I Wueeb0ab62015-01-03 23:48:15 +0800303 return self._generate_stubs()
Chia-I Wudf3c4322014-08-04 10:08:08 +0800304
Chia-I Wu7f6d66e2015-01-04 00:11:17 +0800305class IcdGetProcAddrSubcommand(IcdDummyEntrypointsSubcommand):
306 def generate_header(self):
307 return "\n".join(["#include <string.h>", "#include \"icd.h\""])
308
309 def generate_body(self):
310 for proto in self.protos:
311 if proto.name == "GetProcAddr":
312 gpa_proto = proto
313
314 gpa_decl = self._generate_stub_decl(gpa_proto)
315 gpa_pname = gpa_proto.params[-1].name
316
317 lookups = []
318 for proto in self.protos:
319 lookups.append("if (!strcmp(%s, \"%s\"))" %
320 (gpa_pname, proto.name))
321 lookups.append(" return (%s) %s%s;" %
322 (gpa_proto.ret, self.prefix, proto.name))
323
324 body = []
325 body.append("%s %s" % (self.qual, gpa_decl))
326 body.append("{")
Chia-I Wu6cdaedb2015-01-05 12:55:13 +0800327 body.append(generate_get_proc_addr_check(gpa_pname))
Chia-I Wu7f6d66e2015-01-04 00:11:17 +0800328 body.append("")
329 body.append(" %s += 3;" % gpa_pname)
330 body.append(" %s" % "\n ".join(lookups))
331 body.append("")
332 body.append(" return NULL;")
333 body.append("}")
334
335 return "\n".join(body)
336
Chia-I Wuef9f1822015-01-05 12:56:13 +0800337class LayerInterceptProcSubcommand(Subcommand):
338 def run(self):
339 self.prefix = "xgl"
340
341 # we could get the list from argv if wanted
342 self.intercepted = [proto.name for proto in self.protos
343 if proto.name not in ["InitAndEnumerateGpus"]]
344
345 for proto in self.protos:
346 if proto.name == "GetProcAddr":
347 self.gpa = proto
348
349 super().run()
350
351 def generate_header(self):
352 return "\n".join(["#include <string.h>", "#include \"xglLayer.h\""])
353
354 def generate_body(self):
355 lookups = []
356 for proto in self.protos:
357 if proto.name not in self.intercepted:
358 lookups.append("/* no %s%s */" % (self.prefix, proto.name))
359 continue
360
361 lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
362 lookups.append(" return (%s) %s%s;" %
363 (self.gpa.ret, self.prefix, proto.name))
364
365 body = []
366 body.append("static inline %s layer_intercept_proc(const char *name)" %
367 self.gpa.ret)
368 body.append("{")
369 body.append(generate_get_proc_addr_check("name"))
370 body.append("")
371 body.append(" name += 3;")
372 body.append(" %s" % "\n ".join(lookups))
373 body.append("")
374 body.append(" return NULL;")
375 body.append("}")
376
377 return "\n".join(body)
378
Chia-I Wufb2559d2014-08-01 11:19:52 +0800379def main():
380 subcommands = {
Chia-I Wub3d5e192015-01-04 10:15:48 +0800381 "loader-entrypoints": LoaderEntrypointsSubcommand,
Chia-I Wu29271d72015-01-04 10:19:50 +0800382 "dispatch-table-ops": DispatchTableOpsSubcommand,
Chia-I Wueeb0ab62015-01-03 23:48:15 +0800383 "icd-dummy-entrypoints": IcdDummyEntrypointsSubcommand,
Chia-I Wu7f6d66e2015-01-04 00:11:17 +0800384 "icd-get-proc-addr": IcdGetProcAddrSubcommand,
Chia-I Wuef9f1822015-01-05 12:56:13 +0800385 "layer-intercept-proc": LayerInterceptProcSubcommand,
Chia-I Wufb2559d2014-08-01 11:19:52 +0800386 }
387
388 if len(sys.argv) < 2 or sys.argv[1] not in subcommands:
389 print("Usage: %s <subcommand> [options]" % sys.argv[0])
390 print
391 print("Available sucommands are: %s" % " ".join(subcommands))
392 exit(1)
393
394 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
395 subcmd.run()
396
397if __name__ == "__main__":
398 main()