VirtualBox

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

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

OpenGL: compile/warning fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 17.6 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"):
356 return ''
357 elif (cat == '1.3' or
358 cat == '1.4' or
359 cat == '1.5' or
360 cat == '2.0' or
361 cat == '2.1'):
362 # i.e. OpenGL 1.3 or 1.4 or 1.5
363 return "OPENGL_VERSION_" + string.replace(cat, ".", "_")
364 else:
365 assert cat != ''
366 return string.replace(cat, "GL_", "")
367
368
369def CanCompile(funcName):
370 """Return 1 if the function can be compiled into display lists, else 0."""
371 props = Properties(funcName)
372 if ("nolist" in props or
373 "get" in props or
374 "setclient" in props):
375 return 0
376 else:
377 return 1
378
379def HasChromiumProperty(funcName, propertyList):
380 """Return 1 if the function or any alias has any property in the
381 propertyList"""
382 for funcAlias in [funcName, NonVectorFunction(funcName), VectorFunction(funcName)]:
383 if funcAlias:
384 props = ChromiumProps(funcAlias)
385 for p in propertyList:
386 if p in props:
387 return 1
388 return 0
389
390def CanPack(funcName):
391 """Return 1 if the function can be packed, else 0."""
392 return HasChromiumProperty(funcName, ['pack', 'extpack', 'expandpack'])
393
394def HasPackOpcode(funcName):
395 """Return 1 if the function has a true pack opcode"""
396 return HasChromiumProperty(funcName, ['pack', 'extpack'])
397
398def SetsState(funcName):
399 """Return 1 if the function sets server-side state, else 0."""
400 props = Properties(funcName)
401
402 # Exceptions. The first set of these functions *do* have
403 # server-side state-changing effects, but will be missed
404 # by the general query, because they either render (e.g.
405 # Bitmap) or do not compile into display lists (e.g. all the others).
406 #
407 # The second set do *not* have server-side state-changing
408 # effects, despite the fact that they do not render
409 # and can be compiled. They are control functions
410 # that are not trackable via state.
411 if funcName in ['Bitmap', 'DeleteTextures', 'FeedbackBuffer',
412 'RenderMode', 'BindBufferARB', 'DeleteFencesNV']:
413 return 1
414 elif funcName in ['ExecuteProgramNV']:
415 return 0
416
417 # All compilable functions that do not render and that do
418 # not set or use client-side state (e.g. DrawArrays, et al.), set
419 # server-side state.
420 if CanCompile(funcName) and "render" not in props and "useclient" not in props and "setclient" not in props:
421 return 1
422
423 # All others don't set server-side state.
424 return 0
425
426def SetsClientState(funcName):
427 """Return 1 if the function sets client-side state, else 0."""
428 props = Properties(funcName)
429 if "setclient" in props:
430 return 1
431 return 0
432
433def SetsTrackedState(funcName):
434 """Return 1 if the function sets state that is tracked by
435 the state tracker, else 0."""
436 # These functions set state, but aren't tracked by the state
437 # tracker for various reasons:
438 # - because the state tracker doesn't manage display lists
439 # (e.g. CallList and CallLists)
440 # - because the client doesn't have information about what
441 # the server supports, so the function has to go to the
442 # server (e.g. CompressedTexImage calls)
443 # - because they require a round-trip to the server (e.g.
444 # the CopyTexImage calls, SetFenceNV, TrackMatrixNV)
445 if funcName in [
446 'CopyTexImage1D', 'CopyTexImage2D',
447 'CopyTexSubImage1D', 'CopyTexSubImage2D', 'CopyTexSubImage3D',
448 'CallList', 'CallLists',
449 'CompressedTexImage1DARB', 'CompressedTexSubImage1DARB',
450 'CompressedTexImage2DARB', 'CompressedTexSubImage2DARB',
451 'CompressedTexImage3DARB', 'CompressedTexSubImage3DARB',
452 'SetFenceNV'
453 ]:
454 return 0
455
456 # Anything else that affects client-side state is trackable.
457 if SetsClientState(funcName):
458 return 1
459
460 # Anything else that doesn't set state at all is certainly
461 # not trackable.
462 if not SetsState(funcName):
463 return 0
464
465 # Per-vertex state isn't tracked the way other state is
466 # tracked, so it is specifically excluded.
467 if "pervertex" in Properties(funcName):
468 return 0
469
470 # Everything else is fine
471 return 1
472
473def UsesClientState(funcName):
474 """Return 1 if the function uses client-side state, else 0."""
475 props = Properties(funcName)
476 if "pixelstore" in props or "useclient" in props:
477 return 1
478 return 0
479
480def IsQuery(funcName):
481 """Return 1 if the function returns information to the user, else 0."""
482 props = Properties(funcName)
483 if "get" in props:
484 return 1
485 return 0
486
487def FuncGetsState(funcName):
488 """Return 1 if the function gets GL state, else 0."""
489 d = GetFunctionDict()
490 props = Properties(funcName)
491 if "get" in props:
492 return 1
493 else:
494 return 0
495
496def IsPointer(dataType):
497 """Determine if the datatype is a pointer. Return 1 or 0."""
498 if string.find(dataType, "*") == -1:
499 return 0
500 else:
501 return 1
502
503
504def PointerType(pointerType):
505 """Return the type of a pointer.
506 Ex: PointerType('const GLubyte *') = 'GLubyte'
507 """
508 t = string.split(pointerType, ' ')
509 if t[0] == "const":
510 t[0] = t[1]
511 return t[0]
512
513
514
515
516def OpcodeName(funcName):
517 """Return the C token for the opcode for the given function."""
518 return "CR_" + string.upper(funcName) + "_OPCODE"
519
520
521def ExtendedOpcodeName(funcName):
522 """Return the C token for the extended opcode for the given function."""
523 return "CR_" + string.upper(funcName) + "_EXTEND_OPCODE"
524
525
526
527
528#======================================================================
529
530def MakeCallString(params):
531 """Given a list of (name, type, vectorSize) parameters, make a C-style
532 formal parameter string.
533 Ex return: 'index, x, y, z'.
534 """
535 result = ''
536 i = 1
537 n = len(params)
538 for (name, type, vecSize) in params:
539 result += name
540 if i < n:
541 result = result + ', '
542 i += 1
543 #endfor
544 return result
545#enddef
546
547
548def MakeDeclarationString(params):
549 """Given a list of (name, type, vectorSize) parameters, make a C-style
550 parameter declaration string.
551 Ex return: 'GLuint index, GLfloat x, GLfloat y, GLfloat z'.
552 """
553 n = len(params)
554 if n == 0:
555 return 'void'
556 else:
557 result = ''
558 i = 1
559 for (name, type, vecSize) in params:
560 result = result + type + ' ' + name
561 if i < n:
562 result = result + ', '
563 i += 1
564 #endfor
565 return result
566 #endif
567#enddef
568
569
570def MakePrototypeString(params):
571 """Given a list of (name, type, vectorSize) parameters, make a C-style
572 parameter prototype string (types only).
573 Ex return: 'GLuint, GLfloat, GLfloat, GLfloat'.
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
583 # see if we need a comma separator
584 if i < n:
585 result = result + ', '
586 i += 1
587 #endfor
588 return result
589 #endif
590#enddef
591
592
593#======================================================================
594
595__lengths = {
596 'GLbyte': 1,
597 'GLubyte': 1,
598 'GLshort': 2,
599 'GLushort': 2,
600 'GLint': 4,
601 'GLuint': 4,
602 'GLfloat': 4,
603 'GLclampf': 4,
604 'GLdouble': 8,
605 'GLclampd': 8,
606 'GLenum': 4,
607 'GLboolean': 1,
608 'GLsizei': 4,
609 'GLbitfield': 4,
610 'void': 0, # XXX why?
611 'int': 4,
612 'GLintptrARB': 4, # XXX or 8 bytes?
613 'GLsizeiptrARB': 4, # XXX or 8 bytes?
614 'GLhandleARB': 4,
615 'GLcharARB': 1,
616 'uintptr_t': 4
617}
618
619def sizeof(type):
620 """Return size of C datatype, in bytes."""
621 if not type in __lengths.keys():
622 print >>sys.stderr, "%s not in lengths!" % type
623 return __lengths[type]
624
625
626#======================================================================
627align_types = 1
628
629def FixAlignment( pos, alignment ):
630 # if we want double-alignment take word-alignment instead,
631 # yes, this is super-lame, but we know what we are doing
632 if alignment > 4:
633 alignment = 4
634 if align_types and alignment and ( pos % alignment ):
635 pos += alignment - ( pos % alignment )
636 return pos
637
638def WordAlign( pos ):
639 return FixAlignment( pos, 4 )
640
641def PointerSize():
642 return 8 # Leave room for a 64 bit pointer
643
644def PacketLength( params ):
645 len = 0
646 for (name, type, vecSize) in params:
647 if IsPointer(type):
648 size = PointerSize()
649 else:
650 assert string.find(type, "const") == -1
651 size = sizeof(type)
652 len = FixAlignment( len, size ) + size
653 len = WordAlign( len )
654 return len
655
656#======================================================================
657
658__specials = {}
659
660def LoadSpecials( filename ):
661 table = {}
662 try:
663 f = open( filename, "r" )
664 except:
665# try:
666 f = open( sys.argv[2]+"/"+filename, "r")
667# except:
668# __specials[filename] = {}
669# print "%s not present" % filename
670# return {}
671
672 for line in f.readlines():
673 line = string.strip(line)
674 if line == "" or line[0] == '#':
675 continue
676 table[line] = 1
677
678 __specials[filename] = table
679 return table
680
681
682def FindSpecial( table_file, glName ):
683 table = {}
684 filename = table_file + "_special"
685 try:
686 table = __specials[filename]
687 except KeyError:
688 table = LoadSpecials( filename )
689
690 try:
691 if (table[glName] == 1):
692 return 1
693 else:
694 return 0 #should never happen
695 except KeyError:
696 return 0
697
698
699def AllSpecials( table_file ):
700 table = {}
701 filename = table_file + "_special"
702 try:
703 table = __specials[filename]
704 except KeyError:
705 table = LoadSpecials( filename )
706
707 keys = table.keys()
708 keys.sort()
709 return keys
710
711
712def AllSpecials( table_file ):
713 filename = table_file + "_special"
714 table = {}
715 try:
716 table = __specials[filename]
717 except KeyError:
718 table = LoadSpecials(filename)
719
720 ret = table.keys()
721 ret.sort()
722 return ret
723
724
725def NumSpecials( table_file ):
726 filename = table_file + "_special"
727 table = {}
728 try:
729 table = __specials[filename]
730 except KeyError:
731 table = LoadSpecials(filename)
732 return len(table.keys())
733
734def PrintRecord(record):
735 argList = MakeDeclarationString(record.params)
736 if record.category == "Chromium":
737 prefix = "cr"
738 else:
739 prefix = "gl"
740 print '%s %s%s(%s);' % (record.returnType, prefix, record.name, argList )
741 if len(record.props) > 0:
742 print ' /* %s */' % string.join(record.props, ' ')
743
744#ProcessSpecFile("APIspec.txt", PrintRecord)
745
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