blob: 78b540001661ce4eb67a8c2b668443007d4c921c [file] [log] [blame]
Tobin Ehlis92dbf802014-10-22 09:06:33 -06001#!/usr/bin/env python3
2#
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>
27
28import sys
29
30import xgl
31
32class Subcommand(object):
33 def __init__(self, argv):
34 self.argv = argv
35 self.protos = ()
36 self.headers = ()
37
38 def run(self):
39 self.protos = xgl.core + xgl.ext_wsi_x11
40 self.headers = xgl.core_headers + xgl.ext_wsi_x11_headers
41 print(self.generate())
42
43 def generate(self):
44 copyright = self.generate_copyright()
45 header = self.generate_header()
46 body = self.generate_body()
47 footer = self.generate_footer()
48
49 contents = []
50 if copyright:
51 contents.append(copyright)
52 if header:
53 contents.append(header)
54 if body:
55 contents.append(body)
56 if footer:
57 contents.append(footer)
58
59 return "\n\n".join(contents)
60
61 def generate_copyright(self):
62 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
63
64/*
65 * XGL
66 *
67 * Copyright (C) 2014 LunarG, Inc.
68 *
69 * Permission is hereby granted, free of charge, to any person obtaining a
70 * copy of this software and associated documentation files (the "Software"),
71 * to deal in the Software without restriction, including without limitation
72 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
73 * and/or sell copies of the Software, and to permit persons to whom the
74 * Software is furnished to do so, subject to the following conditions:
75 *
76 * The above copyright notice and this permission notice shall be included
77 * in all copies or substantial portions of the Software.
78 *
79 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
82 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
83 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
84 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
85 * DEALINGS IN THE SOFTWARE.
86 */"""
87
88 def generate_header(self):
89 return "\n".join(["#include <" + h + ">" for h in self.headers])
90
91 def generate_body(self):
92 pass
93
94 def generate_footer(self):
95 pass
96
97 # Return set of printf '%' qualifier and input to that qualifier
98 def _get_printf_params(self, xgl_type, name, last_create):
99 # TODO : Need ENUM and STRUCT checks here
100 if "_TYPE" in xgl_type: # TODO : This should be generic ENUM check
101 return ("%s", "string_%s(%s)" % (xgl_type.strip('const ').strip('*'), name))
102 if "XGL_CHAR*" == xgl_type:
103 return ("%s", name)
104 if "UINT64" in xgl_type:
105 if '*' in xgl_type:
106 return ("%lu", "*%s" % name)
107 return ("%lu", name)
108 if "FLOAT" in xgl_type:
109 if '[' in xgl_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
110 return ("[%f, %f, %f, %f]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
111 return ("%f", name)
Tobin Ehlis0a1e06d2014-11-11 17:28:22 -0700112 if "BOOL" in xgl_type or 'xcb_randr_crtc_t' in xgl_type:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600113 return ("%u", name)
Tobin Ehlis0a1e06d2014-11-11 17:28:22 -0700114 if True in [t in xgl_type for t in ["INT", "SIZE", "FLAGS", "MASK", "xcb_window_t"]]:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600115 if '[' in xgl_type: # handle array, current hard-coded to 4 (TODO: Make this dynamic)
116 return ("[%i, %i, %i, %i]", "%s[0], %s[1], %s[2], %s[3]" % (name, name, name, name))
117 if '*' in xgl_type:
118 return ("%i", "*%s" % name)
119 return ("%i", name)
Tobin Ehlis0a1e06d2014-11-11 17:28:22 -0700120 # TODO : This is special-cased as there's only one "format" param currently and it's nice to expand it
121 if "XGL_FORMAT" == xgl_type and "format" == name:
122 return ("{format.channelFormat = %s, format.numericFormat = %s}", "string_XGL_CHANNEL_FORMAT(format.channelFormat), string_XGL_NUM_FORMAT(format.numericFormat)")
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600123 if last_create:
124 return ("%p", "(void*)*%s" % name)
125 return ("%p", "(void*)%s" % name)
126
127 def _generate_icd_dispatch_table(self):
128 proto_map = {}
129 for proto in self.protos:
130 proto_map[proto.name] = proto
131
132 entries = []
133 for name in xgl.icd_dispatch_table:
134 proto = proto_map[name]
135 entries.append(proto.c_typedef(attr="XGLAPI"))
136
137 return """struct icd_dispatch_table {
138 %s;
139};""" % ";\n ".join(entries)
140
141 def _generate_dispatch_entrypoints(self, qual="", layer="generic"):
142 if qual:
143 qual += " "
144
145 funcs = []
146 for proto in self.protos:
147 if proto.name != "GetProcAddr" and proto.name != "InitAndEnumerateGpus":
148 if "generic" == layer:
149 decl = proto.c_func(prefix="xgl", attr="XGLAPI")
150 param0_name = proto.params[0].name
151 ret_val = ''
152 stmt = ''
153 if proto.ret != "XGL_VOID":
154 ret_val = "XGL_RESULT result = "
155 stmt = " return result;\n"
156 if proto.params[0].ty != "XGL_PHYSICAL_GPU":
157 funcs.append('%s%s\n'
158 '{\n'
159 ' %snextTable.%s;\n'
160 '%s'
161 '}' % (qual, decl, ret_val, proto.c_call(), stmt))
162 else:
163 c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1)
164 funcs.append('%s%s\n'
165 '{\n'
166 ' XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n'
167 ' printf("At start of layered %s\\n");\n'
168 ' pCurObj = gpuw;\n'
169 ' pthread_once(&tabOnce, initLayerTable);\n'
170 ' %snextTable.%s;\n'
171 ' printf("Completed layered %s\\n");\n'
172 '%s'
173 '}' % (qual, decl, proto.params[0].name, proto.name, ret_val, c_call, proto.name, stmt))
Tobin Ehlis574b0142014-11-12 13:11:15 -0700174 elif "apidump" in layer:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600175 decl = proto.c_func(prefix="xgl", attr="XGLAPI")
176 param0_name = proto.params[0].name
177 ret_val = ''
178 stmt = ''
Tobin Ehlis73ff5672014-10-23 08:19:47 -0600179 cis_param_index = [] # Store list of indices when func has struct params
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600180 create_func = False
Tobin Ehlis0a1e06d2014-11-11 17:28:22 -0700181 if 'Create' in proto.name or 'Alloc' in proto.name or 'MapMemory' in proto.name:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600182 create_func = True
183 if proto.ret != "XGL_VOID":
184 ret_val = "XGL_RESULT result = "
185 stmt = " return result;\n"
Tobin Ehlis574b0142014-11-12 13:11:15 -0700186 f_open = ''
187 f_close = ''
188 if "file" in layer:
189 f_open = 'pOutFile = fopen(outFileName, "a");\n '
190 log_func = 'fprintf(pOutFile, "xgl%s(' % proto.name
191 f_close = '\n fclose(pOutFile);'
192 else:
193 log_func = 'printf("xgl%s(' % proto.name
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600194 print_vals = ''
195 pindex = 0
196 for p in proto.params:
197 if p.name == proto.params[-1].name and create_func: # last param of create func
198 (pft, pfi) = self._get_printf_params(p.ty, p.name, True)
199 else:
200 (pft, pfi) = self._get_printf_params(p.ty, p.name, False)
201 log_func += '%s = %s, ' % (p.name, pft)
202 print_vals += ', %s' % (pfi)
Tobin Ehlis73ff5672014-10-23 08:19:47 -0600203 # TODO : Just want this to be simple check for params of STRUCT type
204 if "pCreateInfo" in p.name or ('const' in p.ty and '*' in p.ty and False not in [tmp_ty not in p.ty for tmp_ty in ['XGL_CHAR', 'XGL_VOID', 'XGL_CMD_BUFFER', 'XGL_QUEUE_SEMAPHORE', 'XGL_FENCE', 'XGL_SAMPLER', 'XGL_UINT32']]):
Tobin Ehlis0a1e06d2014-11-11 17:28:22 -0700205 if 'Wsi' not in proto.name:
206 cis_param_index.append(pindex)
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600207 pindex += 1
208 log_func = log_func.strip(', ')
209 if proto.ret != "XGL_VOID":
210 log_func += ') = %s\\n"'
211 print_vals += ', string_XGL_RESULT(result)'
212 else:
213 log_func += ')\\n"'
214 log_func = '%s%s);' % (log_func, print_vals)
Tobin Ehlis73ff5672014-10-23 08:19:47 -0600215 if len(cis_param_index) > 0:
216 log_func += '\n char *pTmpStr;'
217 for sp_index in cis_param_index:
218 cis_print_func = 'xgl_print_%s' % (proto.params[sp_index].ty.strip('const ').strip('*').lower())
219 log_func += '\n if (%s) {' % (proto.params[sp_index].name)
220 log_func += '\n pTmpStr = %s(%s, " ");' % (cis_print_func, proto.params[sp_index].name)
Tobin Ehlis574b0142014-11-12 13:11:15 -0700221 if "file" in layer:
222 log_func += '\n fprintf(pOutFile, " %s (%%p)\\n%%s\\n", (void*)%s, pTmpStr);' % (proto.params[sp_index].name, proto.params[sp_index].name)
223 else:
224 log_func += '\n printf(" %s (%%p)\\n%%s\\n", (void*)%s, pTmpStr);' % (proto.params[sp_index].name, proto.params[sp_index].name)
Tobin Ehlis73ff5672014-10-23 08:19:47 -0600225 log_func += '\n free(pTmpStr);\n }'
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600226 if proto.params[0].ty != "XGL_PHYSICAL_GPU":
227 funcs.append('%s%s\n'
228 '{\n'
229 ' %snextTable.%s;\n'
Tobin Ehlis574b0142014-11-12 13:11:15 -0700230 ' %s%s%s\n'
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600231 '%s'
Tobin Ehlis574b0142014-11-12 13:11:15 -0700232 '}' % (qual, decl, ret_val, proto.c_call(), f_open, log_func, f_close, stmt))
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600233 else:
234 c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1)
235 funcs.append('%s%s\n'
236 '{\n'
237 ' XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n'
238 ' pCurObj = gpuw;\n'
239 ' pthread_once(&tabOnce, initLayerTable);\n'
240 ' %snextTable.%s;\n'
Tobin Ehlis574b0142014-11-12 13:11:15 -0700241 ' %s%s%s\n'
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600242 '%s'
Tobin Ehlis574b0142014-11-12 13:11:15 -0700243 '}' % (qual, decl, proto.params[0].name, ret_val, c_call, f_open, log_func, f_close, stmt))
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600244 elif "objecttracker" == layer:
245 decl = proto.c_func(prefix="xgl", attr="XGLAPI")
246 param0_name = proto.params[0].name
247 create_line = ''
248 destroy_line = ''
249 using_line = ' ll_increment_use_count((XGL_VOID*)%s);\n printf("OBJ[%%llu] : USING %s object %%p (%%lu total uses)\\n", object_track_index++, (void*)%s, ll_get_obj_uses((XGL_VOID*)%s));\n' % (param0_name, param0_name, param0_name, param0_name)
Tobin Ehliscd7235b2014-10-28 09:19:13 -0600250 if 'Create' in proto.name or 'Alloc' in proto.name:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600251 create_line = ' printf("OBJ[%%llu] : CREATE %s object %%p\\n", object_track_index++, (void*)*%s);\n ll_insert_obj((XGL_VOID*)*%s, "%s");\n' % (proto.params[-1].ty.strip('*'), proto.params[-1].name, proto.params[-1].name, proto.params[-1].ty.strip('*'))
Tobin Ehliscd7235b2014-10-28 09:19:13 -0600252 if 'Destroy' in proto.name or 'Free' in proto.name:
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600253 destroy_line = ' printf("OBJ[%%llu] : DESTROY %s object %%p\\n", object_track_index++, (void*)%s);\n ll_remove_obj((XGL_VOID*)%s);\n' % (param0_name, param0_name, param0_name)
254 using_line = ''
Tobin Ehliscd7235b2014-10-28 09:19:13 -0600255 if 'DestroyDevice' in proto.name:
256 destroy_line += ' // Report any remaining objects in LL\n objNode *pTrav = pObjLLHead;\n while (pTrav) {\n'
257 destroy_line += ' printf("OBJ ERROR : %s object %p has not been destroyed (was used %lu times).\\n", pTrav->objType, pTrav->pObj, pTrav->numUses);\n'
258 destroy_line += ' pTrav = pTrav->pNext;\n }\n'
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600259 ret_val = ''
260 stmt = ''
261 if proto.ret != "XGL_VOID":
262 ret_val = "XGL_RESULT result = "
263 stmt = " return result;\n"
264 if proto.params[0].ty != "XGL_PHYSICAL_GPU":
265 funcs.append('%s%s\n'
266 '{\n'
267 '%s'
268 ' %snextTable.%s;\n'
269 '%s%s'
270 '%s'
271 '}' % (qual, decl, using_line, ret_val, proto.c_call(), create_line, destroy_line, stmt))
272 else:
273 c_call = proto.c_call().replace("(" + proto.params[0].name, "((XGL_PHYSICAL_GPU)gpuw->nextObject", 1)
274 funcs.append('%s%s\n'
275 '{\n'
276 ' XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) %s;\n'
277 '%s'
278 ' pCurObj = gpuw;\n'
279 ' pthread_once(&tabOnce, initLayerTable);\n'
280 ' %snextTable.%s;\n'
281 '%s%s'
282 '%s'
283 '}' % (qual, decl, proto.params[0].name, using_line, ret_val, c_call, create_line, destroy_line, stmt))
284
285 # TODO : Put this code somewhere so it gets called at the end if objects not deleted :
286 # // Report any remaining objects in LL
287 # objNode *pTrav = pObjLLHead;
288 # while (pTrav) {
289 # printf("WARN : %s object %p has not been destroyed.\n", pTrav->objType, pTrav->pObj);
290 # }
291
292 return "\n\n".join(funcs)
293
294 def _generate_layer_gpa_function(self, prefix="xgl"):
295 func_body = []
296 func_body.append("XGL_LAYER_EXPORT XGL_VOID* XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const XGL_CHAR* funcName)\n"
297 "{\n"
298 " XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;\n"
299 " if (gpu == NULL)\n"
300 " return NULL;\n"
301 " pCurObj = gpuw;\n"
302 " pthread_once(&tabOnce, initLayerTable);\n\n"
303 ' if (!strncmp("xglGetProcAddr", (const char *) funcName, sizeof("xglGetProcAddr")))\n'
304 ' return xglGetProcAddr;')
305 for name in xgl.icd_dispatch_table:
306 if name == "GetProcAddr":
307 continue
308 if name == "InitAndEnumerateGpus":
309 func_body.append(' else if (!strncmp("%s%s", (const char *) funcName, sizeof("%s%s")))\n'
310 ' return nextTable.%s;' % (prefix, name, prefix, name, name))
311 else:
312 func_body.append(' else if (!strncmp("%s%s", (const char *) funcName, sizeof("%s%s")))\n'
313 ' return %s%s;' % (prefix, name, prefix, name, prefix, name))
314
315 func_body.append(" else {\n"
316 " XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;\n"
317 " if (gpuw->pGPA == NULL)\n"
318 " return NULL;\n"
319 " return gpuw->pGPA(gpuw->nextObject, funcName);\n"
320 " }\n"
321 "}\n")
322 return "\n".join(func_body)
323
324 def _generate_layer_dispatch_table(self, prefix='xgl'):
325 func_body = []
326 func_body.append('static void initLayerTable()\n'
327 '{\n'
328 ' GetProcAddrType fpNextGPA;\n'
329 ' fpNextGPA = pCurObj->pGPA;\n'
330 ' assert(fpNextGPA);\n');
331
332 for name in xgl.icd_dispatch_table:
333 func_body.append(' %sType fp%s = fpNextGPA((XGL_PHYSICAL_GPU) pCurObj->nextObject, (XGL_CHAR *) "%s%s");\n'
334 ' nextTable.%s = fp%s;' % (name, name, prefix, name, name, name))
335
336 func_body.append("}\n")
337 return "\n".join(func_body)
338
339class LayerFuncsSubcommand(Subcommand):
340 def generate_header(self):
341 return '#include <xglLayer.h>\n#include "loader.h"'
342
343 def generate_body(self):
344 return self._generate_dispatch_entrypoints("static", True)
345
346class LayerDispatchSubcommand(Subcommand):
347 def generate_header(self):
348 return '#include "layer_wrappers.h"'
349
350 def generate_body(self):
351 return self._generate_layer_dispatch_table()
352
353class GenericLayerSubcommand(Subcommand):
354 def generate_header(self):
355 return '#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include <pthread.h>\n#include "xglLayer.h"\n\nstatic XGL_LAYER_DISPATCH_TABLE nextTable;\nstatic XGL_BASE_LAYER_OBJECT *pCurObj;\nstatic pthread_once_t tabOnce = PTHREAD_ONCE_INIT;\n'
356
357 def generate_body(self):
358 body = [self._generate_layer_dispatch_table(),
359 self._generate_dispatch_entrypoints("XGL_LAYER_EXPORT", "generic"),
360 self._generate_layer_gpa_function()]
361
362 return "\n\n".join(body)
363
364class ApiDumpSubcommand(Subcommand):
365 def generate_header(self):
Tobin Ehlis0a1e06d2014-11-11 17:28:22 -0700366 return '#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include <pthread.h>\n#include "xglLayer.h"\n#include "xgl_struct_string_helper.h"\n\nstatic XGL_LAYER_DISPATCH_TABLE nextTable;\nstatic XGL_BASE_LAYER_OBJECT *pCurObj;\nstatic pthread_once_t tabOnce = PTHREAD_ONCE_INIT;\n'
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600367
368 def generate_body(self):
369 body = [self._generate_layer_dispatch_table(),
370 self._generate_dispatch_entrypoints("XGL_LAYER_EXPORT", "apidump"),
371 self._generate_layer_gpa_function()]
372
373 return "\n\n".join(body)
374
Tobin Ehlis574b0142014-11-12 13:11:15 -0700375class ApiDumpFileSubcommand(Subcommand):
376 def generate_header(self):
377 return '#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include <pthread.h>\n#include "xglLayer.h"\n#include "xgl_struct_string_helper.h"\n\nstatic XGL_LAYER_DISPATCH_TABLE nextTable;\nstatic XGL_BASE_LAYER_OBJECT *pCurObj;\nstatic pthread_once_t tabOnce = PTHREAD_ONCE_INIT;\n\nstatic FILE* pOutFile;\nstatic char* outFileName = "xgl_apidump.txt";\n'
378
379 def generate_body(self):
380 body = [self._generate_layer_dispatch_table(),
381 self._generate_dispatch_entrypoints("XGL_LAYER_EXPORT", "apidump-file"),
382 self._generate_layer_gpa_function()]
383
384 return "\n\n".join(body)
385
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600386class ObjectTrackerSubcommand(Subcommand):
387 def generate_header(self):
388 header_txt = []
389 header_txt.append('#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <assert.h>\n#include <pthread.h>')
390 header_txt.append('#include "xglLayer.h"\n\nstatic XGL_LAYER_DISPATCH_TABLE nextTable;\nstatic XGL_BASE_LAYER_OBJECT *pCurObj;')
391 header_txt.append('static pthread_once_t tabOnce = PTHREAD_ONCE_INIT;\nstatic long long unsigned int object_track_index = 0;\n')
392 header_txt.append('typedef struct _objNode {')
393 header_txt.append(' XGL_VOID *pObj;')
394 header_txt.append(' const char *objType;')
395 header_txt.append(' uint64_t numUses;')
396 header_txt.append(' struct _objNode *pNext;')
397 header_txt.append('} objNode;\n')
398 header_txt.append('static objNode *pObjLLHead = NULL;\n')
399 header_txt.append('static void ll_insert_obj(XGL_VOID* pObj, const char* type) {')
400 header_txt.append(' objNode* pNewObjNode = (objNode*)malloc(sizeof(objNode));')
401 header_txt.append(' pNewObjNode->pObj = pObj;')
402 header_txt.append(' pNewObjNode->objType = type;')
403 header_txt.append(' pNewObjNode->numUses = 0;')
404 header_txt.append(' pNewObjNode->pNext = pObjLLHead;')
405 header_txt.append(' pObjLLHead = pNewObjNode;')
406 header_txt.append('}\n')
407 header_txt.append('static void ll_increment_use_count(XGL_VOID* pObj) {')
408 header_txt.append(' objNode *pTrav = pObjLLHead;')
409 header_txt.append(' while (pTrav) {')
410 header_txt.append(' if (pTrav->pObj == pObj) {')
411 header_txt.append(' pTrav->numUses++;')
412 header_txt.append(' return;')
413 header_txt.append(' }')
414 header_txt.append(' pTrav = pTrav->pNext;')
415 header_txt.append(' }')
416 header_txt.append(' // If we do not find obj, insert it and then intrement count')
Tobin Ehliscd7235b2014-10-28 09:19:13 -0600417 header_txt.append(' printf("OBJ WARN : Unable to increment count for obj %p, will add to list as UNKNOWN type and increment count\\n", pObj);')
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600418 header_txt.append(' ll_insert_obj(pObj, "UNKNOWN");')
419 header_txt.append(' ll_increment_use_count(pObj);')
420 header_txt.append('}')
421 header_txt.append('static uint64_t ll_get_obj_uses(XGL_VOID* pObj) {')
422 header_txt.append(' objNode *pTrav = pObjLLHead;')
423 header_txt.append(' while (pTrav) {')
424 header_txt.append(' if (pTrav->pObj == pObj) {')
425 header_txt.append(' return pTrav->numUses;')
426 header_txt.append(' }')
427 header_txt.append(' pTrav = pTrav->pNext;')
428 header_txt.append(' }')
429 header_txt.append(' return 0;')
430 header_txt.append('}')
431 header_txt.append('static void ll_remove_obj(XGL_VOID* pObj) {')
432 header_txt.append(' objNode *pTrav = pObjLLHead;')
433 header_txt.append(' objNode *pPrev = pObjLLHead;')
434 header_txt.append(' while (pTrav) {')
435 header_txt.append(' if (pTrav->pObj == pObj) {')
436 header_txt.append(' pPrev->pNext = pTrav->pNext;')
437 header_txt.append(' if (pObjLLHead == pTrav)')
438 header_txt.append(' pObjLLHead = pTrav->pNext;')
439 header_txt.append(' printf("OBJ_STAT Removed %s obj %p that was used %lu times.\\n", pTrav->objType, pTrav->pObj, pTrav->numUses);')
440 header_txt.append(' free(pTrav);')
441 header_txt.append(' return;')
442 header_txt.append(' }')
443 header_txt.append(' pPrev = pTrav;')
444 header_txt.append(' pTrav = pTrav->pNext;')
445 header_txt.append(' }')
446 header_txt.append(' printf("ERROR : Unable to remove obj %p\\n", pObj);')
447 header_txt.append('}')
448
449 return "\n".join(header_txt)
450
451 def generate_body(self):
452 body = [self._generate_layer_dispatch_table(),
453 self._generate_dispatch_entrypoints("XGL_LAYER_EXPORT", "objecttracker"),
454 self._generate_layer_gpa_function()]
455
456 return "\n\n".join(body)
457
458def main():
459 subcommands = {
460 "layer-funcs" : LayerFuncsSubcommand,
461 "layer-dispatch" : LayerDispatchSubcommand,
462 "generic-layer" : GenericLayerSubcommand,
463 "api-dump" : ApiDumpSubcommand,
Tobin Ehlis574b0142014-11-12 13:11:15 -0700464 "api-dump-file" : ApiDumpFileSubcommand,
Tobin Ehlis92dbf802014-10-22 09:06:33 -0600465 "object-tracker" : ObjectTrackerSubcommand,
466 }
467
468 if len(sys.argv) < 2 or sys.argv[1] not in subcommands:
469 print("Usage: %s <subcommand> [options]" % sys.argv[0])
470 print
471 print("Available sucommands are: %s" % " ".join(subcommands))
472 exit(1)
473
474 subcmd = subcommands[sys.argv[1]](sys.argv[2:])
475 subcmd.run()
476
477if __name__ == "__main__":
478 main()