VirtualBox

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

Last change on this file since 78493 was 78116, checked in by vboxsync, 6 years ago

GuestHost/OpenGL,HostServices/SharedOpenGL: Updates bugref:9407

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