VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/glapi_parser/apiutil.py@ 41109

Last change on this file since 41109 was 30440, checked in by vboxsync, 15 years ago

crOpenGL: wddm friendly windows info tracking + more consistent updates (disabled except windows yet)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 17.7 KB
Line 
1#!/usr/common/bin/python
2
3# apiutil.py
4#
5# This file defines a bunch of utility functions for OpenGL API code
6# generation.
7
8import sys, string, re
9
10
11#======================================================================
12
13def CopyrightC( ):
14 print """/* Copyright (c) 2001, Stanford University
15 All rights reserved.
16
17 See the file LICENSE.txt for information on redistributing this software. */
18 """
19
20def CopyrightDef( ):
21 print """; Copyright (c) 2001, Stanford University
22 ; All rights reserved.
23 ;
24 ; See the file LICENSE.txt for information on redistributing this software.
25 """
26
27
28
29#======================================================================
30
31class APIFunction:
32 """Class to represent a GL API function (name, return type,
33 parameters, etc)."""
34 def __init__(self):
35 self.name = ''
36 self.returnType = ''
37 self.category = ''
38 self.offset = -1
39 self.alias = ''
40 self.vectoralias = ''
41 self.params = []
42 self.paramlist = []
43 self.paramvec = []
44 self.paramaction = []
45 self.paramprop = []
46 self.paramset = []
47 self.props = []
48 self.chromium = []
49
50
51
52def ProcessSpecFile(filename, userFunc):
53 """Open the named API spec file and call userFunc(record) for each record
54 processed."""
55 specFile = open(filename, "r")
56 if not specFile:
57 print "Error: couldn't open %s file!" % filename
58 sys.exit()
59
60 record = APIFunction()
61
62 for line in specFile.readlines():
63
64 # split line into tokens
65 tokens = string.split(line)
66
67 if len(tokens) > 0 and line[0] != '#':
68
69 if tokens[0] == 'name':
70 if record.name != '':
71 # process the function now
72 userFunc(record)
73 # reset the record
74 record = APIFunction()
75
76 record.name = tokens[1]
77
78 elif tokens[0] == 'return':
79 record.returnType = string.join(tokens[1:], ' ')
80
81 elif tokens[0] == 'param':
82 name = tokens[1]
83 type = string.join(tokens[2:], ' ')
84 vecSize = 0
85 record.params.append((name, type, vecSize))
86
87 elif tokens[0] == 'paramprop':
88 name = tokens[1]
89 str = tokens[2:]
90 enums = []
91 for i in range(len(str)):
92 enums.append(str[i])
93 record.paramprop.append((name, enums))
94
95 elif tokens[0] == 'paramlist':
96 name = tokens[1]
97 str = tokens[2:]
98 list = []
99 for i in range(len(str)):
100 list.append(str[i])
101 record.paramlist.append((name,list))
102
103 elif tokens[0] == 'paramvec':
104 name = tokens[1]
105 str = tokens[2:]
106 vec = []
107 for i in range(len(str)):
108 vec.append(str[i])
109 record.paramvec.append((name,vec))
110
111 elif tokens[0] == 'paramset':
112 line = tokens[1:]
113 result = []
114 for i in range(len(line)):
115 tset = line[i]
116 if tset == '[':
117 nlist = []
118 elif tset == ']':
119 result.append(nlist)
120 nlist = []
121 else:
122 nlist.append(tset)
123 if result != []:
124 record.paramset.append(result)
125
126 elif tokens[0] == 'paramaction':
127 name = tokens[1]
128 str = tokens[2:]
129 list = []
130 for i in range(len(str)):
131 list.append(str[i])
132 record.paramaction.append((name,list))
133
134 elif tokens[0] == 'category':
135 record.category = tokens[1]
136
137 elif tokens[0] == 'offset':
138 if tokens[1] == '?':
139 record.offset = -2
140 else:
141 record.offset = int(tokens[1])
142
143 elif tokens[0] == 'alias':
144 record.alias = tokens[1]
145
146 elif tokens[0] == 'vectoralias':
147 record.vectoralias = tokens[1]
148
149 elif tokens[0] == 'props':
150 record.props = tokens[1:]
151
152 elif tokens[0] == 'chromium':
153 record.chromium = tokens[1:]
154
155 elif tokens[0] == 'vector':
156 vecName = tokens[1]
157 vecSize = int(tokens[2])
158 for i in range(len(record.params)):
159 (name, type, oldSize) = record.params[i]
160 if name == vecName:
161 record.params[i] = (name, type, vecSize)
162 break
163
164 else:
165 print 'Invalid token %s after function %s' % (tokens[0], record.name)
166 #endif
167 #endif
168 #endfor
169 specFile.close()
170#enddef
171
172
173
174
175
176# Dictionary [name] of APIFunction:
177__FunctionDict = {}
178
179# Dictionary [name] of name
180__VectorVersion = {}
181
182# Reverse mapping of function name aliases
183__ReverseAliases = {}
184
185
186def AddFunction(record):
187 assert not __FunctionDict.has_key(record.name)
188 #if not "omit" in record.chromium:
189 __FunctionDict[record.name] = record
190
191
192
193def GetFunctionDict(specFile = ""):
194 if not specFile:
195 specFile = sys.argv[1]+"/APIspec.txt"
196 if len(__FunctionDict) == 0:
197 ProcessSpecFile(specFile, AddFunction)
198 # Look for vector aliased functions
199 for func in __FunctionDict.keys():
200 va = __FunctionDict[func].vectoralias
201 if va != '':
202 __VectorVersion[va] = func
203 #endif
204
205 # and look for regular aliases (for glloader)
206 a = __FunctionDict[func].alias
207 if a:
208 __ReverseAliases[a] = func
209 #endif
210 #endfor
211 #endif
212 return __FunctionDict
213
214
215def GetAllFunctions(specFile = ""):
216 """Return sorted list of all functions known to Chromium."""
217 d = GetFunctionDict(specFile)
218 funcs = []
219 for func in d.keys():
220 rec = d[func]
221 if not "omit" in rec.chromium:
222 funcs.append(func)
223 funcs.sort()
224 return funcs
225
226
227def GetDispatchedFunctions(specFile = ""):
228 """Return sorted list of all functions handled by SPU dispatch table."""
229 d = GetFunctionDict(specFile)
230 funcs = []
231 for func in d.keys():
232 rec = d[func]
233 if (not "omit" in rec.chromium and
234 not "stub" in rec.chromium and
235 rec.alias == ''):
236 funcs.append(func)
237 funcs.sort()
238 return funcs
239
240#======================================================================
241
242def ReturnType(funcName):
243 """Return the C return type of named function.
244 Examples: "void" or "const GLubyte *". """
245 d = GetFunctionDict()
246 return d[funcName].returnType
247
248
249def Parameters(funcName):
250 """Return list of tuples (name, type, vecSize) of function parameters.
251 Example: if funcName=="ClipPlane" return
252 [ ("plane", "GLenum", 0), ("equation", "const GLdouble *", 4) ] """
253 d = GetFunctionDict()
254 return d[funcName].params
255
256def ParamAction(funcName):
257 """Return list of names of actions for testing.
258 For PackerTest only."""
259 d = GetFunctionDict()
260 return d[funcName].paramaction
261
262def ParamList(funcName):
263 """Return list of tuples (name, list of values) of function parameters.
264 For PackerTest only."""
265 d = GetFunctionDict()
266 return d[funcName].paramlist
267
268def ParamVec(funcName):
269 """Return list of tuples (name, vector of values) of function parameters.
270 For PackerTest only."""
271 d = GetFunctionDict()
272 return d[funcName].paramvec
273
274def ParamSet(funcName):
275 """Return list of tuples (name, list of values) of function parameters.
276 For PackerTest only."""
277 d = GetFunctionDict()
278 return d[funcName].paramset
279
280
281def Properties(funcName):
282 """Return list of properties of the named GL function."""
283 d = GetFunctionDict()
284 return d[funcName].props
285
286def AllWithProperty(property):
287 """Return list of functions that have the named property."""
288 funcs = []
289 for funcName in GetDispatchedFunctions():
290 if property in Properties(funcName):
291 funcs.append(funcName)
292 return funcs
293
294def Category(funcName):
295 """Return the category of the named GL function."""
296 d = GetFunctionDict()
297 return d[funcName].category
298
299def ChromiumProps(funcName):
300 """Return list of Chromium-specific properties of the named GL function."""
301 d = GetFunctionDict()
302 return d[funcName].chromium
303
304def ParamProps(funcName):
305 """Return list of Parameter-specific properties of the named GL function."""
306 d = GetFunctionDict()
307 return d[funcName].paramprop
308
309def Alias(funcName):
310 """Return the function that the named function is an alias of.
311 Ex: Alias('DrawArraysEXT') = 'DrawArrays'.
312 """
313 d = GetFunctionDict()
314 return d[funcName].alias
315
316
317def ReverseAlias(funcName):
318 """Like Alias(), but the inverse."""
319 d = GetFunctionDict()
320 if funcName in __ReverseAliases.keys():
321 return __ReverseAliases[funcName]
322 else:
323 return ''
324
325
326def NonVectorFunction(funcName):
327 """Return the non-vector version of the given function, or ''.
328 For example: NonVectorFunction("Color3fv") = "Color3f"."""
329 d = GetFunctionDict()
330 return d[funcName].vectoralias
331
332
333def VectorFunction(funcName):
334 """Return the vector version of the given non-vector-valued function,
335 or ''.
336 For example: VectorVersion("Color3f") = "Color3fv"."""
337 d = GetFunctionDict()
338 if funcName in __VectorVersion.keys():
339 return __VectorVersion[funcName]
340 else:
341 return ''
342
343
344def GetCategoryWrapper(func_name):
345 """Return a C preprocessor token to test in order to wrap code.
346 This handles extensions.
347 Example: GetTestWrapper("glActiveTextureARB") = "CR_multitexture"
348 Example: GetTestWrapper("glBegin") = ""
349 """
350 cat = Category(func_name)
351 if (cat == "1.0" or
352 cat == "1.1" or
353 cat == "1.2" or
354 cat == "Chromium" or
355 cat == "GL_chromium" or
356 cat == "VBox"):
357 return ''
358 elif (cat == '1.3' or
359 cat == '1.4' or
360 cat == '1.5' or
361 cat == '2.0' or
362 cat == '2.1'):
363 # i.e. OpenGL 1.3 or 1.4 or 1.5
364 return "OPENGL_VERSION_" + string.replace(cat, ".", "_")
365 else:
366 assert cat != ''
367 return string.replace(cat, "GL_", "")
368
369
370def CanCompile(funcName):
371 """Return 1 if the function can be compiled into display lists, else 0."""
372 props = Properties(funcName)
373 if ("nolist" in props or
374 "get" in props or
375 "setclient" in props):
376 return 0
377 else:
378 return 1
379
380def HasChromiumProperty(funcName, propertyList):
381 """Return 1 if the function or any alias has any property in the
382 propertyList"""
383 for funcAlias in [funcName, NonVectorFunction(funcName), VectorFunction(funcName)]:
384 if funcAlias:
385 props = ChromiumProps(funcAlias)
386 for p in propertyList:
387 if p in props:
388 return 1
389 return 0
390
391def CanPack(funcName):
392 """Return 1 if the function can be packed, else 0."""
393 return HasChromiumProperty(funcName, ['pack', 'extpack', 'expandpack'])
394
395def HasPackOpcode(funcName):
396 """Return 1 if the function has a true pack opcode"""
397 return HasChromiumProperty(funcName, ['pack', 'extpack'])
398
399def SetsState(funcName):
400 """Return 1 if the function sets server-side state, else 0."""
401 props = Properties(funcName)
402
403 # Exceptions. The first set of these functions *do* have
404 # server-side state-changing effects, but will be missed
405 # by the general query, because they either render (e.g.
406 # Bitmap) or do not compile into display lists (e.g. all the others).
407 #
408 # The second set do *not* have server-side state-changing
409 # effects, despite the fact that they do not render
410 # and can be compiled. They are control functions
411 # that are not trackable via state.
412 if funcName in ['Bitmap', 'DeleteTextures', 'FeedbackBuffer',
413 'RenderMode', 'BindBufferARB', 'DeleteFencesNV']:
414 return 1
415 elif funcName in ['ExecuteProgramNV']:
416 return 0
417
418 # All compilable functions that do not render and that do
419 # not set or use client-side state (e.g. DrawArrays, et al.), set
420 # server-side state.
421 if CanCompile(funcName) and "render" not in props and "useclient" not in props and "setclient" not in props:
422 return 1
423
424 # All others don't set server-side state.
425 return 0
426
427def SetsClientState(funcName):
428 """Return 1 if the function sets client-side state, else 0."""
429 props = Properties(funcName)
430 if "setclient" in props:
431 return 1
432 return 0
433
434def SetsTrackedState(funcName):
435 """Return 1 if the function sets state that is tracked by
436 the state tracker, else 0."""
437 # These functions set state, but aren't tracked by the state
438 # tracker for various reasons:
439 # - because the state tracker doesn't manage display lists
440 # (e.g. CallList and CallLists)
441 # - because the client doesn't have information about what
442 # the server supports, so the function has to go to the
443 # server (e.g. CompressedTexImage calls)
444 # - because they require a round-trip to the server (e.g.
445 # the CopyTexImage calls, SetFenceNV, TrackMatrixNV)
446 if funcName in [
447 'CopyTexImage1D', 'CopyTexImage2D',
448 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'CopyTexSubImage3D',
449 'CallList', 'CallLists',
450 'CompressedTexImage1DARB', 'CompressedTexSubImage1DARB',
451 'CompressedTexImage2DARB', 'CompressedTexSubImage2DARB',
452 'CompressedTexImage3DARB', 'CompressedTexSubImage3DARB',
453 'SetFenceNV'
454 ]:
455 return 0
456
457 # Anything else that affects client-side state is trackable.
458 if SetsClientState(funcName):
459 return 1
460
461 # Anything else that doesn't set state at all is certainly
462 # not trackable.
463 if not SetsState(funcName):
464 return 0
465
466 # Per-vertex state isn't tracked the way other state is
467 # tracked, so it is specifically excluded.
468 if "pervertex" in Properties(funcName):
469 return 0
470
471 # Everything else is fine
472 return 1
473
474def UsesClientState(funcName):
475 """Return 1 if the function uses client-side state, else 0."""
476 props = Properties(funcName)
477 if "pixelstore" in props or "useclient" in props:
478 return 1
479 return 0
480
481def IsQuery(funcName):
482 """Return 1 if the function returns information to the user, else 0."""
483 props = Properties(funcName)
484 if "get" in props:
485 return 1
486 return 0
487
488def FuncGetsState(funcName):
489 """Return 1 if the function gets GL state, else 0."""
490 d = GetFunctionDict()
491 props = Properties(funcName)
492 if "get" in props:
493 return 1
494 else:
495 return 0
496
497def IsPointer(dataType):
498 """Determine if the datatype is a pointer. Return 1 or 0."""
499 if string.find(dataType, "*") == -1:
500 return 0
501 else:
502 return 1
503
504
505def PointerType(pointerType):
506 """Return the type of a pointer.
507 Ex: PointerType('const GLubyte *') = 'GLubyte'
508 """
509 t = string.split(pointerType, ' ')
510 if t[0] == "const":
511 t[0] = t[1]
512 return t[0]
513
514
515
516
517def OpcodeName(funcName):
518 """Return the C token for the opcode for the given function."""
519 return "CR_" + string.upper(funcName) + "_OPCODE"
520
521
522def ExtendedOpcodeName(funcName):
523 """Return the C token for the extended opcode for the given function."""
524 return "CR_" + string.upper(funcName) + "_EXTEND_OPCODE"
525
526
527
528
529#======================================================================
530
531def MakeCallString(params):
532 """Given a list of (name, type, vectorSize) parameters, make a C-style
533 formal parameter string.
534 Ex return: 'index, x, y, z'.
535 """
536 result = ''
537 i = 1
538 n = len(params)
539 for (name, type, vecSize) in params:
540 result += name
541 if i < n:
542 result = result + ', '
543 i += 1
544 #endfor
545 return result
546#enddef
547
548
549def MakeDeclarationString(params):
550 """Given a list of (name, type, vectorSize) parameters, make a C-style
551 parameter declaration string.
552 Ex return: 'GLuint index, GLfloat x, GLfloat y, GLfloat z'.
553 """
554 n = len(params)
555 if n == 0:
556 return 'void'
557 else:
558 result = ''
559 i = 1
560 for (name, type, vecSize) in params:
561 result = result + type + ' ' + name
562 if i < n:
563 result = result + ', '
564 i += 1
565 #endfor
566 return result
567 #endif
568#enddef
569
570
571def MakePrototypeString(params):
572 """Given a list of (name, type, vectorSize) parameters, make a C-style
573 parameter prototype string (types only).
574 Ex return: 'GLuint, GLfloat, GLfloat, GLfloat'.
575 """
576 n = len(params)
577 if n == 0:
578 return 'void'
579 else:
580 result = ''
581 i = 1
582 for (name, type, vecSize) in params:
583 result = result + type
584 # see if we need a comma separator
585 if i < n:
586 result = result + ', '
587 i += 1
588 #endfor
589 return result
590 #endif
591#enddef
592
593
594#======================================================================
595
596__lengths = {
597 'GLbyte': 1,
598 'GLubyte': 1,
599 'GLshort': 2,
600 'GLushort': 2,
601 'GLint': 4,
602 'GLuint': 4,
603 'GLfloat': 4,
604 'GLclampf': 4,
605 'GLdouble': 8,
606 'GLclampd': 8,
607 'GLenum': 4,
608 'GLboolean': 1,
609 'GLsizei': 4,
610 'GLbitfield': 4,
611 'void': 0, # XXX why?
612 'int': 4,
613 'GLintptrARB': 4, # XXX or 8 bytes?
614 'GLsizeiptrARB': 4, # XXX or 8 bytes?
615 'GLhandleARB': 4,
616 'GLcharARB': 1,
617 'uintptr_t': 4
618}
619
620def sizeof(type):
621 """Return size of C datatype, in bytes."""
622 if not type in __lengths.keys():
623 print >>sys.stderr, "%s not in lengths!" % type
624 return __lengths[type]
625
626
627#======================================================================
628align_types = 1
629
630def FixAlignment( pos, alignment ):
631 # if we want double-alignment take word-alignment instead,
632 # yes, this is super-lame, but we know what we are doing
633 if alignment > 4:
634 alignment = 4
635 if align_types and alignment and ( pos % alignment ):
636 pos += alignment - ( pos % alignment )
637 return pos
638
639def WordAlign( pos ):
640 return FixAlignment( pos, 4 )
641
642def PointerSize():
643 return 8 # Leave room for a 64 bit pointer
644
645def PacketLength( params ):
646 len = 0
647 for (name, type, vecSize) in params:
648 if IsPointer(type):
649 size = PointerSize()
650 else:
651 assert string.find(type, "const") == -1
652 size = sizeof(type)
653 len = FixAlignment( len, size ) + size
654 len = WordAlign( len )
655 return len
656
657#======================================================================
658
659__specials = {}
660
661def LoadSpecials( filename ):
662 table = {}
663 try:
664 f = open( filename, "r" )
665 except:
666# try:
667 f = open( sys.argv[2]+"/"+filename, "r")
668# except:
669# __specials[filename] = {}
670# print "%s not present" % filename
671# return {}
672
673 for line in f.readlines():
674 line = string.strip(line)
675 if line == "" or line[0] == '#':
676 continue
677 table[line] = 1
678
679 __specials[filename] = table
680 return table
681
682
683def FindSpecial( table_file, glName ):
684 table = {}
685 filename = table_file + "_special"
686 try:
687 table = __specials[filename]
688 except KeyError:
689 table = LoadSpecials( filename )
690
691 try:
692 if (table[glName] == 1):
693 return 1
694 else:
695 return 0 #should never happen
696 except KeyError:
697 return 0
698
699
700def AllSpecials( table_file ):
701 table = {}
702 filename = table_file + "_special"
703 try:
704 table = __specials[filename]
705 except KeyError:
706 table = LoadSpecials( filename )
707
708 keys = table.keys()
709 keys.sort()
710 return keys
711
712
713def AllSpecials( table_file ):
714 filename = table_file + "_special"
715 table = {}
716 try:
717 table = __specials[filename]
718 except KeyError:
719 table = LoadSpecials(filename)
720
721 ret = table.keys()
722 ret.sort()
723 return ret
724
725
726def NumSpecials( table_file ):
727 filename = table_file + "_special"
728 table = {}
729 try:
730 table = __specials[filename]
731 except KeyError:
732 table = LoadSpecials(filename)
733 return len(table.keys())
734
735def PrintRecord(record):
736 argList = MakeDeclarationString(record.params)
737 if record.category == "Chromium":
738 prefix = "cr"
739 else:
740 prefix = "gl"
741 print '%s %s%s(%s);' % (record.returnType, prefix, record.name, argList )
742 if len(record.props) > 0:
743 print ' /* %s */' % string.join(record.props, ' ')
744
745#ProcessSpecFile("APIspec.txt", PrintRecord)
746
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette