Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / main / APIspecutil.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2009 Chia-I Wu <olv@0xlab.org>
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # on the rights to use, copy, modify, merge, publish, distribute, sub
9 # license, and/or sell copies of the Software, and to permit persons to whom
10 # the Software is furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
14 # Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19 # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 # IN THE SOFTWARE.
23 """
24 Minimal apiutil.py interface for use by es_generator.py.
25 """
26
27 import sys
28 import libxml2
29
30 import APIspec
31
32 __spec = {}
33 __functions = {}
34 __aliases = {}
35
36 def _ParseXML(filename, apiname):
37     conversions = {
38         # from           to
39         'GLfloat':  [ 'GLdouble' ],
40         'GLclampf': [ 'GLclampd' ],
41         'GLubyte':  [ 'GLfloat', 'GLdouble' ],
42         'GLint':    [ 'GLfloat', 'GLdouble' ],
43         'GLfixed':  [ 'GLfloat', 'GLdouble' ],
44         'GLclampx': [ 'GLclampf', 'GLclampd' ],
45     }
46
47     doc = libxml2.readFile(filename, None,
48             libxml2.XML_PARSE_DTDLOAD +
49             libxml2.XML_PARSE_DTDVALID +
50             libxml2.XML_PARSE_NOBLANKS)
51     spec = APIspec.Spec(doc)
52     impl = spec.get_impl()
53     api = spec.get_api(apiname)
54     doc.freeDoc()
55
56     __spec["impl"] = impl
57     __spec["api"] = api
58
59     for func in api.functions:
60         alias, need_conv = impl.match(func, conversions)
61         if not alias:
62             # external functions are manually dispatched
63             if not func.is_external:
64                 print >>sys.stderr, "Error: unable to dispatch %s" % func.name
65             alias = func
66             need_conv = False
67
68         __functions[func.name] = func
69         __aliases[func.name] = (alias, need_conv)
70
71
72 def AllSpecials(notused=None):
73     """Return a list of all external functions in the API."""
74     api = __spec["api"]
75
76     specials = []
77     for func in api.functions:
78         if func.is_external:
79             specials.append(func.name)
80
81     return specials
82
83
84 def GetAllFunctions(filename, api):
85     """Return sorted list of all functions in the API."""
86     if not __spec:
87         _ParseXML(filename, api)
88
89     api = __spec["api"]
90     names = []
91     for func in api.functions:
92         names.append(func.name)
93     names.sort()
94     return names
95
96
97 def ReturnType(funcname):
98     """Return the C return type of named function."""
99     func = __functions[funcname]
100     return func.return_type
101
102
103 def Properties(funcname):
104     """Return list of properties of the named GL function."""
105     func = __functions[funcname]
106     return [func.direction]
107
108
109 def _ValidValues(func, param):
110     """Return the valid values of a parameter."""
111     valid_values = []
112     switch = func.checker.switches.get(param.name, [])
113     for desc in switch:
114         # no dependent vector
115         if not desc.checker.switches:
116             for val in desc.values:
117                 valid_values.append((val, None, None, [], desc.error, None))
118             continue
119
120         items = desc.checker.switches.items()
121         if len(items) > 1:
122             print >>sys.stderr, "%s: more than one parameter depend on %s" % \
123                     (func.name, desc.name)
124         dep_name, dep_switch = items[0]
125
126         for dep_desc in dep_switch:
127             if dep_desc.index >= 0 and dep_desc.index != 0:
128                 print >>sys.stderr, "%s: not first element of a vector" % func.name
129             if dep_desc.checker.switches:
130                 print >>sys.stderr, "%s: deep nested dependence" % func.name
131
132             convert = None if dep_desc.convert else "noconvert"
133             for val in desc.values:
134                 valid_values.append((val, dep_desc.size_str, dep_desc.name,
135                                      dep_desc.values, dep_desc.error, convert))
136     return valid_values
137
138
139 def _Conversion(func, src_param):
140     """Return the destination type of the conversion, or None."""
141     alias, need_conv = __aliases[func.name]
142     if need_conv:
143         dst_param = alias.get_param(src_param.name)
144         if src_param.type == dst_param.type:
145             need_conv = False
146     if not need_conv:
147         return (None, "none")
148
149     converts = { True: 0, False: 0 }
150
151     # In Fogx, for example,  pname may be GL_FOG_DENSITY/GL_FOG_START/GL_FOG_END
152     # or GL_FOG_MODE.  In the former three cases, param is not checked and the
153     # default is to convert.
154     if not func.checker.always_check(src_param.name):
155         converts[True] += 1
156
157     for desc in func.checker.flatten(src_param.name):
158         converts[desc.convert] += 1
159         if converts[True] and converts[False]:
160             break
161
162     # it should be "never", "sometimes", and "always"...
163     if converts[False]:
164         if converts[True]:
165             conversion = "some"
166         else:
167             conversion = "none"
168     else:
169         conversion = "all"
170
171     return (dst_param.base_type(), conversion)
172
173
174 def _MaxVecSize(func, param):
175     """Return the largest possible size of a vector."""
176     if not param.is_vector:
177         return 0
178     if param.size:
179         return param.size
180
181     # need to look at all descriptions
182     size = 0
183     for desc in func.checker.flatten(param.name):
184         if desc.size_str and desc.size_str.isdigit():
185             s = int(desc.size_str)
186             if s > size:
187                 size = s
188     if not size:
189         need_conv = __aliases[func.name][1]
190         if need_conv:
191             print >>sys.stderr, \
192                     "Error: unable to dicide the max size of %s in %s" % \
193                     (param.name, func.name)
194     return size
195
196
197 def _ParameterTuple(func, param):
198     """Return a parameter tuple.
199
200     [0] -- parameter name
201     [1] -- parameter type
202     [2] -- max vector size or 0
203     [3] -- dest type the parameter converts to, or None
204     [4] -- valid values
205     [5] -- how often does the conversion happen
206
207     """
208     vec_size = _MaxVecSize(func, param)
209     dst_type, conversion = _Conversion(func, param)
210     valid_values = _ValidValues(func, param)
211
212     return (param.name, param.type, vec_size, dst_type, valid_values, conversion)
213
214
215 def Parameters(funcname):
216     """Return list of tuples of function parameters."""
217     func = __functions[funcname]
218     params = []
219     for param in func.params:
220         params.append(_ParameterTuple(func, param))
221
222     return params
223
224
225 def FunctionPrefix(funcname):
226     """Return function specific prefix."""
227     func = __functions[funcname]
228
229     return func.prefix
230
231
232 def FindParamIndex(params, paramname):
233     """Find the index of a named parameter."""
234     for i in xrange(len(params)):
235         if params[i][0] == paramname:
236             return i
237     return None
238
239
240 def MakeDeclarationString(params):
241     """Return a C-style parameter declaration string."""
242     string = []
243     for p in params:
244         sep = "" if p[1].endswith("*") else " "
245         string.append("%s%s%s" % (p[1], sep, p[0]))
246     if not string:
247         return "void"
248     return ", ".join(string)
249
250
251 def AliasPrefix(funcname):
252     """Return the prefix of the function the named function is an alias of."""
253     alias = __aliases[funcname][0]
254     return alias.prefix
255
256
257 def Alias(funcname):
258     """Return the name of the function the named function is an alias of."""
259     alias, need_conv = __aliases[funcname]
260     return alias.name if not need_conv else None
261
262
263 def ConversionFunction(funcname):
264     """Return the name of the function the named function converts to."""
265     alias, need_conv = __aliases[funcname]
266     return alias.name if need_conv else None
267
268
269 def Categories(funcname):
270     """Return all the categories of the named GL function."""
271     api = __spec["api"]
272     return [api.name]