Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/mapi/new/genCommon.py
4560 views
1
#!/usr/bin/env python
2
3
# (C) Copyright 2015, NVIDIA CORPORATION.
4
# All Rights Reserved.
5
#
6
# Permission is hereby granted, free of charge, to any person obtaining a
7
# copy of this software and associated documentation files (the "Software"),
8
# to deal in the Software without restriction, including without limitation
9
# on the rights to use, copy, modify, merge, publish, distribute, sub
10
# license, and/or sell copies of the Software, and to permit persons to whom
11
# the Software is furnished to do so, subject to the following conditions:
12
#
13
# The above copyright notice and this permission notice (including the next
14
# paragraph) shall be included in all copies or substantial portions of the
15
# Software.
16
#
17
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20
# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
# IN THE SOFTWARE.
24
#
25
# Authors:
26
# Kyle Brenneman <[email protected]>
27
28
import collections
29
import re
30
import sys
31
import xml.etree.ElementTree as etree
32
33
import os
34
GLAPI = os.path.join(os.path.dirname(__file__), "..", "glapi", "gen")
35
sys.path.insert(0, GLAPI)
36
import static_data
37
38
MAPI_TABLE_NUM_DYNAMIC = 4096
39
40
_LIBRARY_FEATURE_NAMES = {
41
# libGL and libGLdiapatch both include every function.
42
"gl" : None,
43
"gldispatch" : None,
44
"opengl" : frozenset(( "GL_VERSION_1_0", "GL_VERSION_1_1",
45
"GL_VERSION_1_2", "GL_VERSION_1_3", "GL_VERSION_1_4", "GL_VERSION_1_5",
46
"GL_VERSION_2_0", "GL_VERSION_2_1", "GL_VERSION_3_0", "GL_VERSION_3_1",
47
"GL_VERSION_3_2", "GL_VERSION_3_3", "GL_VERSION_4_0", "GL_VERSION_4_1",
48
"GL_VERSION_4_2", "GL_VERSION_4_3", "GL_VERSION_4_4", "GL_VERSION_4_5",
49
)),
50
"glesv1" : frozenset(("GL_VERSION_ES_CM_1_0", "GL_OES_point_size_array")),
51
"glesv2" : frozenset(("GL_ES_VERSION_2_0", "GL_ES_VERSION_3_0",
52
"GL_ES_VERSION_3_1", "GL_ES_VERSION_3_2",
53
)),
54
}
55
56
def getFunctions(xmlFiles):
57
"""
58
Reads an XML file and returns all of the functions defined in it.
59
60
xmlFile should be the path to Khronos's gl.xml file. The return value is a
61
sequence of FunctionDesc objects, ordered by slot number.
62
"""
63
roots = [ etree.parse(xmlFile).getroot() for xmlFile in xmlFiles ]
64
return getFunctionsFromRoots(roots)
65
66
def getFunctionsFromRoots(roots):
67
functions = {}
68
for root in roots:
69
for func in _getFunctionList(root):
70
functions[func.name] = func
71
functions = functions.values()
72
73
# Sort the function list by name.
74
functions = sorted(functions, key=lambda f: f.name)
75
76
# Lookup for fixed offset/slot functions and use it if available.
77
# Assign a slot number to each function. This isn't strictly necessary,
78
# since you can just look at the index in the list, but it makes it easier
79
# to include the slot when formatting output.
80
81
next_slot = 0
82
for i in range(len(functions)):
83
name = functions[i].name[2:]
84
85
if name in static_data.offsets:
86
functions[i] = functions[i]._replace(slot=static_data.offsets[name])
87
elif not name.endswith("ARB") and name + "ARB" in static_data.offsets:
88
functions[i] = functions[i]._replace(slot=static_data.offsets[name + "ARB"])
89
elif not name.endswith("EXT") and name + "EXT" in static_data.offsets:
90
functions[i] = functions[i]._replace(slot=static_data.offsets[name + "EXT"])
91
else:
92
functions[i] = functions[i]._replace(slot=next_slot)
93
next_slot += 1
94
95
return functions
96
97
def getExportNamesFromRoots(target, roots):
98
"""
99
Goes through the <feature> tags from gl.xml and returns a set of OpenGL
100
functions that a library should export.
101
102
target should be one of "gl", "gldispatch", "opengl", "glesv1", or
103
"glesv2".
104
"""
105
featureNames = _LIBRARY_FEATURE_NAMES[target]
106
if featureNames is None:
107
return set(func.name for func in getFunctionsFromRoots(roots))
108
109
names = set()
110
for root in roots:
111
features = []
112
for featElem in root.findall("feature"):
113
if featElem.get("name") in featureNames:
114
features.append(featElem)
115
for featElem in root.findall("extensions/extension"):
116
if featElem.get("name") in featureNames:
117
features.append(featElem)
118
for featElem in features:
119
for commandElem in featElem.findall("require/command"):
120
names.add(commandElem.get("name"))
121
return names
122
123
class FunctionArg(collections.namedtuple("FunctionArg", "type name")):
124
@property
125
def dec(self):
126
"""
127
Returns a "TYPE NAME" string, suitable for a function prototype.
128
"""
129
rv = str(self.type)
130
if not rv.endswith("*"):
131
rv += " "
132
rv += self.name
133
return rv
134
135
class FunctionDesc(collections.namedtuple("FunctionDesc", "name rt args slot")):
136
def hasReturn(self):
137
"""
138
Returns true if the function returns a value.
139
"""
140
return (self.rt != "void")
141
142
@property
143
def decArgs(self):
144
"""
145
Returns a string with the types and names of the arguments, as you
146
would use in a function declaration.
147
"""
148
if not self.args:
149
return "void"
150
else:
151
return ", ".join(arg.dec for arg in self.args)
152
153
@property
154
def callArgs(self):
155
"""
156
Returns a string with the names of the arguments, as you would use in a
157
function call.
158
"""
159
return ", ".join(arg.name for arg in self.args)
160
161
@property
162
def basename(self):
163
assert self.name.startswith("gl")
164
return self.name[2:]
165
166
def _getFunctionList(root):
167
for elem in root.findall("commands/command"):
168
yield _parseCommandElem(elem)
169
170
def _parseCommandElem(elem):
171
protoElem = elem.find("proto")
172
(rt, name) = _parseProtoElem(protoElem)
173
174
args = []
175
for ch in elem.findall("param"):
176
# <param> tags have the same format as a <proto> tag.
177
args.append(FunctionArg(*_parseProtoElem(ch)))
178
func = FunctionDesc(name, rt, tuple(args), slot=None)
179
180
return func
181
182
def _parseProtoElem(elem):
183
# If I just remove the tags and string the text together, I'll get valid C code.
184
text = _flattenText(elem)
185
text = text.strip()
186
m = re.match(r"^(.+)\b(\w+)(?:\s*\[\s*(\d*)\s*\])?$", text, re.S)
187
if m:
188
typename = _fixupTypeName(m.group(1))
189
name = m.group(2)
190
if m.group(3):
191
# HACK: glPathGlyphIndexRangeNV defines an argument like this:
192
# GLuint baseAndCount[2]
193
# Convert it to a pointer and hope for the best.
194
typename += "*"
195
return (typename, name)
196
else:
197
raise ValueError("Can't parse element %r -> %r" % (elem, text))
198
199
def _flattenText(elem):
200
"""
201
Returns the text in an element and all child elements, with the tags
202
removed.
203
"""
204
text = ""
205
if elem.text is not None:
206
text = elem.text
207
for ch in elem:
208
text += _flattenText(ch)
209
if ch.tail is not None:
210
text += ch.tail
211
return text
212
213
def _fixupTypeName(typeName):
214
"""
215
Converts a typename into a more consistent format.
216
"""
217
218
rv = typeName.strip()
219
220
# Replace "GLvoid" with just plain "void".
221
rv = re.sub(r"\bGLvoid\b", "void", rv)
222
223
# Remove the vendor suffixes from types that have a suffix-less version.
224
rv = re.sub(r"\b(GLhalf|GLintptr|GLsizeiptr|GLint64|GLuint64)(?:ARB|EXT|NV|ATI)\b", r"\1", rv)
225
226
rv = re.sub(r"\bGLDEBUGPROCKHR\b", "GLDEBUGPROC", rv)
227
228
# Clear out any leading and trailing whitespace.
229
rv = rv.strip()
230
231
# Remove any whitespace before a '*'
232
rv = re.sub(r"\s+\*", r"*", rv)
233
234
# Change "foo*" to "foo *"
235
rv = re.sub(r"([^\*])\*", r"\1 *", rv)
236
237
# Condense all whitespace into a single space.
238
rv = re.sub(r"\s+", " ", rv)
239
240
return rv
241
242
243