VirtualBox

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

Last change on this file since 50041 was 50041, checked in by vboxsync, 11 years ago

crOpenGL: crOpenGL: 1. workaround point sprite driver bugs; 2. workaround multi-string shader source driver bug; 3. proper GLhandle for OSX; 4. extended dumping; 5. misc fixes

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