1 | # $Id: dlm_generated.py 65381 2017-01-20 09:23:53Z vboxsync $
|
---|
2 | import sys, cPickle, re
|
---|
3 |
|
---|
4 | sys.path.append( "../glapi_parser" )
|
---|
5 | import apiutil
|
---|
6 |
|
---|
7 | # A routine that can create call strings from instance names
|
---|
8 | def InstanceCallString( params ):
|
---|
9 | output = ''
|
---|
10 | for index in range(0,len(params)):
|
---|
11 | if index > 0:
|
---|
12 | output += ", "
|
---|
13 | if params[index][0] != '':
|
---|
14 | output += 'instance->' + params[index][0]
|
---|
15 | return output
|
---|
16 |
|
---|
17 | def GetPointerType(basetype):
|
---|
18 | words = basetype.split()
|
---|
19 | if words[0] == 'const':
|
---|
20 | words = words[1:]
|
---|
21 | if words[-1].endswith('*'):
|
---|
22 | words[-1] = words[-1][:-1].strip()
|
---|
23 | if words[-1] == '':
|
---|
24 | words = words[:-1]
|
---|
25 | if words[0] == 'void' or words[0] == 'GLvoid':
|
---|
26 | words[0] = 'int'
|
---|
27 | return ' '.join(words)
|
---|
28 |
|
---|
29 |
|
---|
30 | def GetPointerInfo(functionName):
|
---|
31 | # We'll keep track of all the parameters that require pointers.
|
---|
32 | # They'll require special handling later.
|
---|
33 | params = apiutil.Parameters(functionName)
|
---|
34 | pointers = []
|
---|
35 | pointername=''
|
---|
36 | pointerarg=''
|
---|
37 | pointertype=''
|
---|
38 | pointersize=0
|
---|
39 | pointercomment=''
|
---|
40 |
|
---|
41 | index = 0
|
---|
42 | for (name, type, vecSize) in params:
|
---|
43 | # Watch out for the word "const" (which should be ignored)
|
---|
44 | # and for types that end in "*" (which are pointers and need
|
---|
45 | # special treatment)
|
---|
46 | words = type.split()
|
---|
47 | if words[-1].endswith('*'):
|
---|
48 | pointers.append(index)
|
---|
49 | index += 1
|
---|
50 |
|
---|
51 | # If any argument was a pointer, we need a special pointer data
|
---|
52 | # array. The pointer data will be stored into this array, and
|
---|
53 | # references to the array will be generated as parameters.
|
---|
54 | if len(pointers) == 1:
|
---|
55 | index = pointers[0]
|
---|
56 | pointername = params[index][0]
|
---|
57 | pointerarg = pointername + 'Data'
|
---|
58 | pointertype = GetPointerType(params[index][1])
|
---|
59 | pointersize = params[index][2]
|
---|
60 | if pointersize == 0:
|
---|
61 | pointersize = "special"
|
---|
62 | elif len(pointers) > 1:
|
---|
63 | pointerarg = 'data';
|
---|
64 | pointertype = GetPointerType(params[pointers[0]][1])
|
---|
65 | for index in range(1,len(pointers)):
|
---|
66 | if GetPointerType(params[pointers[index]][1]) != pointertype:
|
---|
67 | pointertype = 'GLvoid *'
|
---|
68 |
|
---|
69 | return (pointers,pointername,pointerarg,pointertype,pointersize,pointercomment)
|
---|
70 |
|
---|
71 | def wrap_struct(functionName):
|
---|
72 | params = apiutil.Parameters(functionName)
|
---|
73 | argstring = apiutil.MakeDeclarationString(params)
|
---|
74 | extendedArgstring = argstring
|
---|
75 | props = apiutil.Properties(functionName)
|
---|
76 | if "useclient" in props or "pixelstore" in props:
|
---|
77 | extendedArgstring += ", CRClientState *c"
|
---|
78 |
|
---|
79 | # We'll keep track of all the parameters that require pointers.
|
---|
80 | # They'll require special handling later.
|
---|
81 | (pointers, pointername, pointerarg, pointertype, pointersize, pointercomment) = GetPointerInfo(functionName)
|
---|
82 |
|
---|
83 | # Start writing the header
|
---|
84 | print 'struct instance%s {' % (functionName)
|
---|
85 | print ' DLMInstanceList *next;'
|
---|
86 | print ' DLMInstanceList *stateNext;'
|
---|
87 | print ' int cbInstance;'
|
---|
88 | print ' VBoxDLOpCode iVBoxOpCode;'
|
---|
89 | print ' void (DLM_APIENTRY *execute)(DLMInstanceList *instance, SPUDispatchTable *dispatchTable);'
|
---|
90 | for (name, type, vecSize) in params:
|
---|
91 | # Watch out for the word "const" (which should be ignored)
|
---|
92 | # and for types that end in "*" (which are pointers and need
|
---|
93 | # special treatment)
|
---|
94 | words = type.split()
|
---|
95 | if words[0] == 'const':
|
---|
96 | words = words[1:]
|
---|
97 | if words[0] != "void":
|
---|
98 | print ' %s %s;' % (' '.join(words), name)
|
---|
99 |
|
---|
100 | # If any argument was a pointer, we need a special pointer data
|
---|
101 | # array. The pointer data will be stored into this array, and
|
---|
102 | # references to the array will be generated as parameters.
|
---|
103 | if len(pointers) == 1:
|
---|
104 | if pointersize == None:
|
---|
105 | print " /* Oh no - pointer parameter %s found, but no pointer class specified and can't guess */" % pointername
|
---|
106 | else:
|
---|
107 | if pointersize == 'special':
|
---|
108 | print ' %s %s[1];%s' % (pointertype, pointerarg, pointercomment)
|
---|
109 | else:
|
---|
110 | print ' %s %s[%s];%s' % (pointertype, pointerarg, pointersize,pointercomment)
|
---|
111 | elif len(pointers) > 1:
|
---|
112 | print ' %s %s[1];%s' % (pointertype, pointerarg,pointercomment)
|
---|
113 |
|
---|
114 | print '};'
|
---|
115 |
|
---|
116 | # Pointers only happen with instances
|
---|
117 | if len(pointers) > 1 or (len(pointers) == 1 and pointersize == 'special'):
|
---|
118 | print 'int crdlm_pointers_%s(struct instance%s *instance, %s);' % (functionName, functionName, extendedArgstring)
|
---|
119 |
|
---|
120 | # See if the GL function must sometimes allow passthrough even
|
---|
121 | # if the display list is open
|
---|
122 | if "checklist" in apiutil.ChromiumProps(functionName):
|
---|
123 | print 'int crdlm_checklist_%s(%s);' % (functionName, argstring)
|
---|
124 |
|
---|
125 | return
|
---|
126 |
|
---|
127 | def wrap_execute(functionName):
|
---|
128 |
|
---|
129 | params = apiutil.Parameters(functionName)
|
---|
130 | (pointers, _, pointerarg, _, _, _) = GetPointerInfo(functionName)
|
---|
131 |
|
---|
132 | print 'static void execute%s(DLMInstanceList *x, SPUDispatchTable *dispatchTable)' % functionName
|
---|
133 | print '{'
|
---|
134 | if len(params) > 0:
|
---|
135 | print ' struct instance%s *instance = (struct instance%s *)x;' % (functionName, functionName)
|
---|
136 |
|
---|
137 | if len(pointers) == 1:
|
---|
138 | print ' instance->%s = instance->%s;' % (params[pointers[0]][0], pointerarg)
|
---|
139 |
|
---|
140 | print ' if (dispatchTable->%s != NULL)' % (functionName)
|
---|
141 | print ' dispatchTable->%s(%s);' % (functionName, InstanceCallString(params))
|
---|
142 | print ' else'
|
---|
143 | print ' crWarning("DLM warning: execute%s called with NULL dispatch entry");' % (functionName)
|
---|
144 | print '}'
|
---|
145 |
|
---|
146 | # These code snippets isolate the code required to add a given instance
|
---|
147 | # to the display list correctly. They are used during generation, to
|
---|
148 | # generate correct code, and also to create useful utilities.
|
---|
149 | def AddInstanceToList(pad):
|
---|
150 | print '%s/* Add this instance to the current display list. */' % pad
|
---|
151 | print '%sinstance->next = NULL;' % pad
|
---|
152 | print '%sinstance->stateNext = NULL;' % pad
|
---|
153 | print '%sif (!state->currentListInfo->first) {' % pad
|
---|
154 | print '%s state->currentListInfo->first = (DLMInstanceList *)instance;' % pad
|
---|
155 | print '%s}' % pad
|
---|
156 | print '%selse {' % pad
|
---|
157 | print '%s state->currentListInfo->last->next = (DLMInstanceList *)instance;' % pad
|
---|
158 | print '%s}' % pad
|
---|
159 | print '%sstate->currentListInfo->last = (DLMInstanceList *)instance;' % pad
|
---|
160 | print '%sstate->currentListInfo->numInstances++;' % pad
|
---|
161 |
|
---|
162 | def AddInstanceToStateList(pad):
|
---|
163 | print '%s/* Instances that change state have to be added to the state list as well. */' % pad
|
---|
164 | print '%sif (!state->currentListInfo->stateFirst) {' % pad
|
---|
165 | print '%s state->currentListInfo->stateFirst = (DLMInstanceList *)instance;' % pad
|
---|
166 | print '%s}' % pad
|
---|
167 | print '%selse {' % pad
|
---|
168 | print '%s state->currentListInfo->stateLast->stateNext = (DLMInstanceList *)instance;' % pad
|
---|
169 | print '%s}' % pad
|
---|
170 | print '%sstate->currentListInfo->stateLast = (DLMInstanceList *)instance;' % pad
|
---|
171 |
|
---|
172 |
|
---|
173 | # The compile wrapper collects the parameters into a DLMInstanceList
|
---|
174 | # element, and adds that element to the end of the display list currently
|
---|
175 | # being compiled.
|
---|
176 | def wrap_compile(functionName):
|
---|
177 | params = apiutil.Parameters(functionName)
|
---|
178 | return_type = apiutil.ReturnType(functionName)
|
---|
179 | # Make sure the return type is void. It's nonsensical to compile
|
---|
180 | # an element with any other return type.
|
---|
181 | if return_type != 'void':
|
---|
182 | print '/* Nonsense: DL function %s has a %s return type?!? */' % (functionName, return_type)
|
---|
183 |
|
---|
184 | # Define a structure to hold all the parameters. Note that the
|
---|
185 | # top parameters must exactly match the DLMInstanceList structure
|
---|
186 | # in include/cr_dlm.h, or everything will break horribly.
|
---|
187 | # Start off by getting all the pointer info we could ever use
|
---|
188 | # from the parameters
|
---|
189 | (pointers, pointername, pointerarg, pointertype, pointersize, pointercomment) = GetPointerInfo(functionName)
|
---|
190 |
|
---|
191 | # Finally, the compile wrapper. This one will diverge strongly
|
---|
192 | # depending on whether or not there are pointer parameters.
|
---|
193 | callstring = apiutil.MakeCallString(params)
|
---|
194 | argstring = apiutil.MakeDeclarationString(params)
|
---|
195 | props = apiutil.Properties(functionName)
|
---|
196 | if "useclient" in props or "pixelstore" in props:
|
---|
197 | callstring += ", c"
|
---|
198 | argstring += ", CRClientState *c"
|
---|
199 | print 'void DLM_APIENTRY crDLMCompile%s(%s)' % (functionName, argstring)
|
---|
200 | print '{'
|
---|
201 | print ' CRDLMContextState *state = CURRENT_STATE();'
|
---|
202 | print ' struct instance%s *instance;' % (functionName)
|
---|
203 |
|
---|
204 | # The calling SPU is supposed to verify that the element is supposed to be
|
---|
205 | # compiled before it is actually compiled; typically, this is done based
|
---|
206 | # on whether a glNewList has been executed more recently than a glEndList.
|
---|
207 | # But some functions are dual-natured, sometimes being compiled, and sometimes
|
---|
208 | # being executed immediately. We can check for this here.
|
---|
209 | if "checklist" in apiutil.ChromiumProps(functionName):
|
---|
210 | print ' if (crDLMCheckList%s(%s))' % (functionName, apiutil.MakeCallString(params))
|
---|
211 | print ' {'
|
---|
212 | print ' crdlm_error(__LINE__, __FILE__, GL_INVALID_OPERATION,'
|
---|
213 | print ' "this instance of function %s should not be compiled");' % functionName;
|
---|
214 | print ' return;'
|
---|
215 | print ' }'
|
---|
216 |
|
---|
217 | if len(pointers) > 1 or pointersize == 'special':
|
---|
218 | # Pass NULL, to just allocate space
|
---|
219 | print ' instance = crCalloc(sizeof(struct instance%s) + crdlm_pointers_%s(NULL, %s));' % (functionName, functionName, callstring)
|
---|
220 | else:
|
---|
221 | print ' instance = crCalloc(sizeof(struct instance%s));' % (functionName)
|
---|
222 | print ' if (!instance)'
|
---|
223 | print ' {'
|
---|
224 | print ' crdlm_error(__LINE__, __FILE__, GL_OUT_OF_MEMORY,'
|
---|
225 | print ' "out of memory adding %s to display list");' % (functionName)
|
---|
226 | print ' return;'
|
---|
227 | print ' }'
|
---|
228 |
|
---|
229 | # Put in the fields that must always exist
|
---|
230 | print ' instance->execute = execute%s;' % functionName
|
---|
231 |
|
---|
232 | # Apply all the simple (i.e. non-pointer) parameters
|
---|
233 | for index in range(len(params)):
|
---|
234 | if index not in pointers:
|
---|
235 | name = params[index][0]
|
---|
236 | print ' instance->%s = %s;' % (name, name)
|
---|
237 |
|
---|
238 | # We need to know instance size in bytes in order to save its state later.
|
---|
239 | print ' instance->cbInstance = sizeof(struct instance%s);' % functionName
|
---|
240 |
|
---|
241 | # Set OPCODE.
|
---|
242 | print ' instance->iVBoxOpCode = VBOX_DL_OPCODE_%s;' % functionName
|
---|
243 |
|
---|
244 | # If there's a pointer parameter, apply it.
|
---|
245 | if len(pointers) == 1:
|
---|
246 |
|
---|
247 | print ' if (%s == NULL)' % (params[pointers[0]][0])
|
---|
248 | print ' instance->%s = NULL;' % (params[pointers[0]][0])
|
---|
249 | print ' else'
|
---|
250 | print ' instance->%s = instance->%s;' % (params[pointers[0]][0], pointerarg)
|
---|
251 |
|
---|
252 | if pointersize == 'special':
|
---|
253 | print ' instance->cbInstance += crdlm_pointers_%s(instance, %s);' % (functionName, callstring)
|
---|
254 | else:
|
---|
255 | print ' crMemcpy((void *)instance->%s, (void *) %s, %s*sizeof(%s));' % (params[pointers[0]][0], params[pointers[0]][0], pointersize, pointertype)
|
---|
256 | elif len(pointers) == 2:
|
---|
257 | # this seems to work
|
---|
258 | print ' instance->cbInstance += crdlm_pointers_%s(instance, %s);' % (functionName, callstring)
|
---|
259 | elif len(pointers) > 2:
|
---|
260 | print "#error don't know how to handle pointer parameters for %s" % (functionName)
|
---|
261 |
|
---|
262 | # Add the element to the current display list
|
---|
263 | AddInstanceToList(' ')
|
---|
264 | # If the element is a state-changing element, add it to the current state list
|
---|
265 | if apiutil.SetsTrackedState(functionName):
|
---|
266 | AddInstanceToStateList(' ')
|
---|
267 | print '}'
|
---|
268 |
|
---|
269 | whichfile=sys.argv[1]
|
---|
270 | if whichfile == 'headers':
|
---|
271 | print """#ifndef _DLM_GENERATED_H
|
---|
272 | #define _DLM_GENERATED_H
|
---|
273 |
|
---|
274 | #include <VBoxUhgsmi.h>
|
---|
275 |
|
---|
276 | /* DO NOT EDIT. This file is auto-generated by dlm_generated.py. */
|
---|
277 | """
|
---|
278 | else:
|
---|
279 | print """#include <stdio.h>
|
---|
280 | #include "cr_spu.h"
|
---|
281 | #include "cr_dlm.h"
|
---|
282 | #include "cr_mem.h"
|
---|
283 | #include "cr_error.h"
|
---|
284 | #include "state/cr_statefuncs.h"
|
---|
285 | #include "dlm.h"
|
---|
286 | #include "dlm_pointers.h"
|
---|
287 | #include "dlm_generated.h"
|
---|
288 |
|
---|
289 | /* DO NOT EDIT. This file is auto-generated by dlm_generated.py. */
|
---|
290 | """
|
---|
291 |
|
---|
292 | # Add in the "add_to_dl" utility function, which will be used by
|
---|
293 | # external (i.e. non-generated) functions. The utility ensures that
|
---|
294 | # any external functions that are written for compiling elements
|
---|
295 | # don't have to be rewritten if the conventions for adding to display
|
---|
296 | # lists are changed.
|
---|
297 | print """
|
---|
298 | void crdlm_add_to_list(
|
---|
299 | DLMInstanceList *instance,
|
---|
300 | void (*executeFunc)(DLMInstanceList *x, SPUDispatchTable *dispatchTable)"""
|
---|
301 |
|
---|
302 | if (whichfile == 'headers'):
|
---|
303 | print ");"
|
---|
304 | else:
|
---|
305 | print """) {
|
---|
306 | CRDLMContextState *state = CURRENT_STATE();
|
---|
307 | instance->execute = executeFunc;"""
|
---|
308 |
|
---|
309 | # Add in the common code for adding the instance to the display list
|
---|
310 | AddInstanceToList(" ")
|
---|
311 |
|
---|
312 | print '}'
|
---|
313 | print ''
|
---|
314 |
|
---|
315 | # Now generate the functions that won't use the crdlm_add_to_list utility.
|
---|
316 | # These all directly add their own instances to the current display list
|
---|
317 | # themselves, without using the crdlm_add_to_list() function.
|
---|
318 | keys = apiutil.GetDispatchedFunctions(sys.argv[3]+"/APIspec.txt")
|
---|
319 | for func_name in keys:
|
---|
320 | if apiutil.CanCompile(func_name):
|
---|
321 | print "\n/*** %s ***/" % func_name
|
---|
322 | # Auto-generate an appropriate DL function. First, functions
|
---|
323 | # that go into the display list but that rely on state will
|
---|
324 | # have to have their argument strings expanded, to take pointers
|
---|
325 | # to that appropriate state.
|
---|
326 | if whichfile == "headers":
|
---|
327 | wrap_struct(func_name)
|
---|
328 | elif not apiutil.FindSpecial("dlm", func_name):
|
---|
329 | wrap_execute(func_name)
|
---|
330 | wrap_compile(func_name)
|
---|
331 |
|
---|
332 |
|
---|
333 | # Generate mapping between OPCODE and routines to be executed.
|
---|
334 |
|
---|
335 | if whichfile == "headers":
|
---|
336 | # Execute routine prototype needed to add static array of routines.
|
---|
337 | print ''
|
---|
338 | print 'struct DLMInstanceList;'
|
---|
339 | print 'typedef void (*VBoxDLMExecuteFn)(struct DLMInstanceList *instance, SPUDispatchTable *dispatchTable);'
|
---|
340 | print ''
|
---|
341 | print 'extern VBoxDLMExecuteFn g_VBoxDLMExecuteFns[VBOX_DL_OPCODE_MAX];'
|
---|
342 | print ''
|
---|
343 | else:
|
---|
344 | print ''
|
---|
345 | print 'VBoxDLMExecuteFn g_VBoxDLMExecuteFns[] = {'
|
---|
346 |
|
---|
347 | for func_name in keys:
|
---|
348 | if apiutil.CanCompile(func_name) and not apiutil.FindSpecial("dlm", func_name):
|
---|
349 | print ' execute%s,' % func_name
|
---|
350 |
|
---|
351 | print '};'
|
---|
352 | print ''
|
---|
353 |
|
---|
354 | if whichfile == 'headers':
|
---|
355 | print "#endif /* _DLM_GENERATED_H */"
|
---|