1 | # $Id: dlm_generated.py 56473 2015-06-17 11:08:31Z 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 | params = apiutil.Parameters(functionName)
|
---|
129 | print 'static void execute%s(DLMInstanceList *x, SPUDispatchTable *dispatchTable)' % functionName
|
---|
130 | print '{'
|
---|
131 | if len(params) > 0:
|
---|
132 | print '\tstruct instance%s *instance = (struct instance%s *)x;' % (functionName, functionName)
|
---|
133 | print '\tif (dispatchTable->%s != NULL) {' % (functionName)
|
---|
134 | print '\t\tdispatchTable->%s(%s);' % (functionName, InstanceCallString(params))
|
---|
135 | print '\t}'
|
---|
136 | print '\telse {'
|
---|
137 | print '\t\tcrWarning("DLM warning: execute%s called with NULL dispatch entry");' % (functionName)
|
---|
138 | print '\t}'
|
---|
139 | print '}'
|
---|
140 |
|
---|
141 | def generate_bbox_code(functionName):
|
---|
142 | assert functionName[0:6] == "Vertex"
|
---|
143 | pattern = "(VertexAttribs|VertexAttrib|Vertex)(1|2|3|4)(N?)(f|d|i|s|b|ub|us|ui)(v?)"
|
---|
144 | m = re.match(pattern, functionName)
|
---|
145 | if m:
|
---|
146 | name = m.group(1)
|
---|
147 | size = int(m.group(2))
|
---|
148 | normalize = m.group(3)
|
---|
149 | type = m.group(4)
|
---|
150 | vector = m.group(5)
|
---|
151 |
|
---|
152 | # only update bbox for vertex attribs if index == 0
|
---|
153 | if name == "VertexAttrib":
|
---|
154 | test = "if (index == 0) {"
|
---|
155 | elif name == "VertexAttribs":
|
---|
156 | test = "if (index == 0) {"
|
---|
157 | else:
|
---|
158 | assert name == "Vertex"
|
---|
159 | test = "{"
|
---|
160 |
|
---|
161 | # find names of the X, Y, Z, W values
|
---|
162 | xName = ""
|
---|
163 | yName = ""
|
---|
164 | zName = "0.0"
|
---|
165 | wName = ""
|
---|
166 | if vector == "v":
|
---|
167 | xName = "v[0]"
|
---|
168 | if size > 1:
|
---|
169 | yName = "v[1]"
|
---|
170 | if size > 2:
|
---|
171 | zName = "v[2]"
|
---|
172 | if size > 3:
|
---|
173 | wName = "v[3]"
|
---|
174 | else:
|
---|
175 | xName = "x"
|
---|
176 | if size > 1:
|
---|
177 | yName = "y"
|
---|
178 | if size > 2:
|
---|
179 | zName = "z"
|
---|
180 | if size > 3:
|
---|
181 | wName = "w"
|
---|
182 |
|
---|
183 | # start emitting code
|
---|
184 | print '\t%s' % test
|
---|
185 |
|
---|
186 | if normalize == "N":
|
---|
187 | if type == "b":
|
---|
188 | denom = "128.0f"
|
---|
189 | elif type == "s":
|
---|
190 | denom = "32768.0f"
|
---|
191 | elif type == "i":
|
---|
192 | denom = "2147483647.0f"
|
---|
193 | elif type == "ub":
|
---|
194 | denom = "255.0f"
|
---|
195 | elif type == "us":
|
---|
196 | denom = "65535.0f"
|
---|
197 | elif type == "ui":
|
---|
198 | denom = "4294967295.0f"
|
---|
199 |
|
---|
200 | print '\t\tGLfloat nx = (GLfloat) %s / %s;' % (xName, denom)
|
---|
201 | xName = "nx"
|
---|
202 | if yName:
|
---|
203 | print '\t\tGLfloat ny = (GLfloat) %s / %s;' % (yName, denom)
|
---|
204 | yName = "ny"
|
---|
205 | if zName:
|
---|
206 | print '\t\tGLfloat nz = (GLfloat) %s / %s;' % (zName, denom)
|
---|
207 | zName = "nz"
|
---|
208 | if 0 and wName:
|
---|
209 | print '\t\tGLfloat nw = (GLfloat) %s / %s;' % (wName, denom)
|
---|
210 | wName = "nw"
|
---|
211 |
|
---|
212 | if xName:
|
---|
213 | print '\t\tif (%s < state->currentListInfo->bbox.xmin)' % xName
|
---|
214 | print '\t\t\tstate->currentListInfo->bbox.xmin = %s;' % xName
|
---|
215 | print '\t\tif (%s > state->currentListInfo->bbox.xmax)' % xName
|
---|
216 | print '\t\t\tstate->currentListInfo->bbox.xmax = %s;' % xName
|
---|
217 | if yName:
|
---|
218 | print '\t\tif (%s < state->currentListInfo->bbox.ymin)' % yName
|
---|
219 | print '\t\t\tstate->currentListInfo->bbox.ymin = %s;' % yName
|
---|
220 | print '\t\tif (%s > state->currentListInfo->bbox.ymax)' % yName
|
---|
221 | print '\t\t\tstate->currentListInfo->bbox.ymax = %s;' % yName
|
---|
222 | if zName:
|
---|
223 | print '\t\tif (%s < state->currentListInfo->bbox.zmin)' % zName
|
---|
224 | print '\t\t\tstate->currentListInfo->bbox.zmin = %s;' % zName
|
---|
225 | print '\t\tif (%s > state->currentListInfo->bbox.zmax)' % zName
|
---|
226 | print '\t\t\tstate->currentListInfo->bbox.zmax = %s;' % zName
|
---|
227 | # XXX what about divide by W if we have 4 components?
|
---|
228 | print '\t}'
|
---|
229 |
|
---|
230 | else:
|
---|
231 | print ' /* bbox error for %s !!!!! */' % functionName
|
---|
232 |
|
---|
233 | # These code snippets isolate the code required to add a given instance
|
---|
234 | # to the display list correctly. They are used during generation, to
|
---|
235 | # generate correct code, and also to create useful utilities.
|
---|
236 | def AddInstanceToList(pad):
|
---|
237 | print '%s/* Add this instance to the current display list. */' % pad
|
---|
238 | print '%sinstance->next = NULL;' % pad
|
---|
239 | print '%sinstance->stateNext = NULL;' % pad
|
---|
240 | print '%sif (!state->currentListInfo->first) {' % pad
|
---|
241 | print '%s\tstate->currentListInfo->first = (DLMInstanceList *)instance;' % pad
|
---|
242 | print '%s}' % pad
|
---|
243 | print '%selse {' % pad
|
---|
244 | print '%s\tstate->currentListInfo->last->next = (DLMInstanceList *)instance;' % pad
|
---|
245 | print '%s}' % pad
|
---|
246 | print '%sstate->currentListInfo->last = (DLMInstanceList *)instance;' % pad
|
---|
247 | print '%sstate->currentListInfo->numInstances++;' % pad
|
---|
248 |
|
---|
249 | def AddInstanceToStateList(pad):
|
---|
250 | print '%s/* Instances that change state have to be added to the state list as well. */' % pad
|
---|
251 | print '%sif (!state->currentListInfo->stateFirst) {' % pad
|
---|
252 | print '%s\tstate->currentListInfo->stateFirst = (DLMInstanceList *)instance;' % pad
|
---|
253 | print '%s}' % pad
|
---|
254 | print '%selse {' % pad
|
---|
255 | print '%s\tstate->currentListInfo->stateLast->stateNext = (DLMInstanceList *)instance;' % pad
|
---|
256 | print '%s}' % pad
|
---|
257 | print '%sstate->currentListInfo->stateLast = (DLMInstanceList *)instance;' % pad
|
---|
258 |
|
---|
259 |
|
---|
260 | # The compile wrapper collects the parameters into a DLMInstanceList
|
---|
261 | # element, and adds that element to the end of the display list currently
|
---|
262 | # being compiled.
|
---|
263 | def wrap_compile(functionName):
|
---|
264 | params = apiutil.Parameters(functionName)
|
---|
265 | return_type = apiutil.ReturnType(functionName)
|
---|
266 | # Make sure the return type is void. It's nonsensical to compile
|
---|
267 | # an element with any other return type.
|
---|
268 | if return_type != 'void':
|
---|
269 | print '/* Nonsense: DL function %s has a %s return type?!? */' % (functionName, return_type)
|
---|
270 | # return
|
---|
271 | # Define a structure to hold all the parameters. Note that the
|
---|
272 | # top parameters must exactly match the DLMInstanceList structure
|
---|
273 | # in include/cr_dlm.h, or everything will break horribly.
|
---|
274 | # Start off by getting all the pointer info we could ever use
|
---|
275 | # from the parameters
|
---|
276 | (pointers, pointername, pointerarg, pointertype, pointersize, pointercomment) = GetPointerInfo(functionName)
|
---|
277 |
|
---|
278 | # Finally, the compile wrapper. This one will diverge strongly
|
---|
279 | # depending on whether or not there are pointer parameters.
|
---|
280 | callstring = apiutil.MakeCallString(params)
|
---|
281 | argstring = apiutil.MakeDeclarationString(params)
|
---|
282 | props = apiutil.Properties(functionName)
|
---|
283 | if "useclient" in props or "pixelstore" in props:
|
---|
284 | callstring += ", c"
|
---|
285 | argstring += ", CRClientState *c"
|
---|
286 | print 'void DLM_APIENTRY crDLMCompile%s( %s )' % (functionName, argstring)
|
---|
287 | print '{'
|
---|
288 | print ' CRDLMContextState *state = CURRENT_STATE();'
|
---|
289 | print ' struct instance%s *instance;' % (functionName)
|
---|
290 |
|
---|
291 | # The calling SPU is supposed to verify that the element is supposed to be
|
---|
292 | # compiled before it is actually compiled; typically, this is done based
|
---|
293 | # on whether a glNewList has been executed more recently than a glEndList.
|
---|
294 | # But some functions are dual-natured, sometimes being compiled, and sometimes
|
---|
295 | # being executed immediately. We can check for this here.
|
---|
296 | if "checklist" in apiutil.ChromiumProps(functionName):
|
---|
297 | print '\tif (crDLMCheckList%s(%s)) {' % (functionName, apiutil.MakeCallString(params))
|
---|
298 | print '\t\tcrdlm_error(__LINE__, __FILE__, GL_INVALID_OPERATION,'
|
---|
299 | print '\t\t "this instance of function %s should not be compiled");' % functionName;
|
---|
300 | print '\t\treturn;'
|
---|
301 | print '\t}'
|
---|
302 |
|
---|
303 | if len(pointers) > 1 or pointersize == 'special':
|
---|
304 | # Pass NULL, to just allocate space
|
---|
305 | print '\tinstance = crCalloc(sizeof(struct instance%s) + crdlm_pointers_%s(NULL, %s));' % (functionName, functionName, callstring)
|
---|
306 | else:
|
---|
307 | print '\tinstance = crCalloc(sizeof(struct instance%s));' % (functionName)
|
---|
308 | print '\tif (!instance) {'
|
---|
309 | print '\t\tcrdlm_error(__LINE__, __FILE__, GL_OUT_OF_MEMORY,'
|
---|
310 | print '\t\t\t"out of memory adding %s to display list");' % (functionName)
|
---|
311 | print '\t\treturn;'
|
---|
312 | print '\t}'
|
---|
313 |
|
---|
314 | # Put in the fields that must always exist
|
---|
315 | print '\tinstance->execute = execute%s;' % functionName
|
---|
316 |
|
---|
317 | # Apply all the simple (i.e. non-pointer) parameters
|
---|
318 | for index in range(len(params)):
|
---|
319 | if index not in pointers:
|
---|
320 | name = params[index][0]
|
---|
321 | print '\tinstance->%s = %s;' % (name, name)
|
---|
322 |
|
---|
323 | # We need to know instance size in bytes in order to save its state later.
|
---|
324 | print '\tinstance->cbInstance = sizeof(struct instance%s);' % functionName
|
---|
325 |
|
---|
326 | # Set OPCODE.
|
---|
327 | print '\tinstance->iVBoxOpCode = VBOX_DL_OPCODE_%s;' % functionName
|
---|
328 |
|
---|
329 | # If there's a pointer parameter, apply it.
|
---|
330 | if len(pointers) == 1:
|
---|
331 | print '\tif (%s == NULL) {' % (params[pointers[0]][0])
|
---|
332 | print '\t\tinstance->%s = NULL;' % (params[pointers[0]][0])
|
---|
333 | print '\t}'
|
---|
334 | print '\telse {'
|
---|
335 | print '\t\tinstance->%s = instance->%s;' % (params[pointers[0]][0], pointerarg)
|
---|
336 | print '\t}'
|
---|
337 | if pointersize == 'special':
|
---|
338 | print '\tinstance->cbInstance += crdlm_pointers_%s(instance, %s);' % (functionName, callstring)
|
---|
339 | else:
|
---|
340 | print '\tcrMemcpy((void *)instance->%s, (void *) %s, %s*sizeof(%s));' % (params[pointers[0]][0], params[pointers[0]][0], pointersize, pointertype)
|
---|
341 | elif len(pointers) == 2:
|
---|
342 | # this seems to work
|
---|
343 | print '\tinstance->cbInstance += crdlm_pointers_%s(instance, %s);' % (functionName, callstring)
|
---|
344 | elif len(pointers) > 2:
|
---|
345 | print "#error don't know how to handle pointer parameters for %s" % (functionName)
|
---|
346 |
|
---|
347 | # Add the element to the current display list
|
---|
348 | AddInstanceToList('\t')
|
---|
349 | # If the element is a state-changing element, add it to the current state list
|
---|
350 | if apiutil.SetsTrackedState(functionName):
|
---|
351 | AddInstanceToStateList('\t')
|
---|
352 |
|
---|
353 | # XXX might need a better test here
|
---|
354 | if functionName[0:6] == "Vertex":
|
---|
355 | generate_bbox_code(functionName)
|
---|
356 |
|
---|
357 | print '}'
|
---|
358 |
|
---|
359 | whichfile=sys.argv[1]
|
---|
360 | if whichfile == 'headers':
|
---|
361 | print """#ifndef _DLM_GENERATED_H
|
---|
362 | #define _DLM_GENERATED_H
|
---|
363 |
|
---|
364 | /* DO NOT EDIT. This file is auto-generated by dlm_generated.py. */
|
---|
365 | """
|
---|
366 | else:
|
---|
367 | print """#include <stdio.h>
|
---|
368 | #include "cr_spu.h"
|
---|
369 | #include "cr_dlm.h"
|
---|
370 | #include "cr_mem.h"
|
---|
371 | #include "cr_error.h"
|
---|
372 | #include "state/cr_statefuncs.h"
|
---|
373 | #include "dlm.h"
|
---|
374 | #include "dlm_pointers.h"
|
---|
375 | #include "dlm_generated.h"
|
---|
376 |
|
---|
377 | /* DO NOT EDIT. This file is auto-generated by dlm_generated.py. */
|
---|
378 | """
|
---|
379 |
|
---|
380 | # Add in the "add_to_dl" utility function, which will be used by
|
---|
381 | # external (i.e. non-generated) functions. The utility ensures that
|
---|
382 | # any external functions that are written for compiling elements
|
---|
383 | # don't have to be rewritten if the conventions for adding to display
|
---|
384 | # lists are changed.
|
---|
385 | print """
|
---|
386 | void crdlm_add_to_list(
|
---|
387 | DLMInstanceList *instance,
|
---|
388 | void (*executeFunc)(DLMInstanceList *x, SPUDispatchTable *dispatchTable)"""
|
---|
389 |
|
---|
390 | if (whichfile == 'headers'):
|
---|
391 | print ");"
|
---|
392 | else:
|
---|
393 | print """) {
|
---|
394 | CRDLMContextState *state = CURRENT_STATE();
|
---|
395 | instance->execute = executeFunc;"""
|
---|
396 |
|
---|
397 | # Add in the common code for adding the instance to the display list
|
---|
398 | AddInstanceToList(" ")
|
---|
399 |
|
---|
400 | print '}'
|
---|
401 | print ''
|
---|
402 |
|
---|
403 | # Now generate the functions that won't use the crdlm_add_to_list utility.
|
---|
404 | # These all directly add their own instances to the current display list
|
---|
405 | # themselves, without using the crdlm_add_to_list() function.
|
---|
406 | keys = apiutil.GetDispatchedFunctions(sys.argv[3]+"/APIspec.txt")
|
---|
407 | for func_name in keys:
|
---|
408 | if apiutil.CanCompile(func_name):
|
---|
409 | print "\n/*** %s ***/" % func_name
|
---|
410 | # Auto-generate an appropriate DL function. First, functions
|
---|
411 | # that go into the display list but that rely on state will
|
---|
412 | # have to have their argument strings expanded, to take pointers
|
---|
413 | # to that appropriate state.
|
---|
414 | if whichfile == "headers":
|
---|
415 | wrap_struct(func_name)
|
---|
416 | elif not apiutil.FindSpecial("dlm", func_name):
|
---|
417 | wrap_execute(func_name)
|
---|
418 | wrap_compile(func_name)
|
---|
419 | # All others just pass through
|
---|
420 |
|
---|
421 | if whichfile == 'headers':
|
---|
422 | print "#endif /* _DLM_GENERATED_H */"
|
---|