mesa: add KHR_no_error support for gl*Samplers()
[mesa.git] / src / mapi / glapi / gen / gl_enums.py
1
2 # (C) Copyright Zack Rusin 2005. All Rights Reserved.
3 # Copyright (C) 2015 Intel Corporation
4 # Copyright (C) 2015 Broadcom Corporation
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 # Zack Rusin <zack@kde.org>
27
28 import argparse
29
30 import license
31 import gl_XML
32 import xml.etree.ElementTree as ET
33 import sys, getopt
34 import re
35
36 class PrintGlEnums(gl_XML.gl_print_base):
37
38 def __init__(self):
39 gl_XML.gl_print_base.__init__(self)
40
41 self.name = "gl_enums.py (from Mesa)"
42 self.license = license.bsd_license_template % ( \
43 """Copyright (C) 1999-2005 Brian Paul All Rights Reserved.""", "BRIAN PAUL")
44 # Mapping from enum value to (name, priority) tuples.
45 self.enum_table = {}
46 # Mapping from enum name to value
47 self.string_to_int = {}
48
49
50 def printRealHeader(self):
51 print '#include "main/glheader.h"'
52 print '#include "main/enums.h"'
53 print '#include "main/imports.h"'
54 print '#include "main/mtypes.h"'
55 print ''
56 print 'typedef struct PACKED {'
57 print ' uint32_t offset;'
58 print ' int n;'
59 print '} enum_elt;'
60 print ''
61 return
62
63 def print_code(self):
64 print """
65 typedef int (*cfunc)(const void *, const void *);
66
67 /**
68 * Compare a key enum value to an element in the \c enum_string_table_offsets array.
69 *
70 * \c bsearch always passes the key as the first parameter and the pointer
71 * to the array element as the second parameter. We can elimiate some
72 * extra work by taking advantage of that fact.
73 *
74 * \param a Pointer to the desired enum name.
75 * \param b Pointer into the \c enum_string_table_offsets array.
76 */
77 static int compar_nr( const int *a, enum_elt *b )
78 {
79 return a[0] - b->n;
80 }
81
82
83 static char token_tmp[20];
84
85 /**
86 * This function always returns a string. If the number is a valid enum, it
87 * returns the enum name. Otherwise, it returns a numeric string.
88 */
89 const char *
90 _mesa_enum_to_string(int nr)
91 {
92 enum_elt *elt;
93
94 elt = bsearch(& nr, enum_string_table_offsets,
95 ARRAY_SIZE(enum_string_table_offsets),
96 sizeof(enum_string_table_offsets[0]),
97 (cfunc) compar_nr);
98
99 if (elt != NULL) {
100 return &enum_string_table[elt->offset];
101 }
102 else {
103 /* this is not re-entrant safe, no big deal here */
104 _mesa_snprintf(token_tmp, sizeof(token_tmp) - 1, "0x%x", nr);
105 token_tmp[sizeof(token_tmp) - 1] = '\\0';
106 return token_tmp;
107 }
108 }
109
110 /**
111 * Primitive names
112 */
113 static const char *prim_names[PRIM_MAX+3] = {
114 "GL_POINTS",
115 "GL_LINES",
116 "GL_LINE_LOOP",
117 "GL_LINE_STRIP",
118 "GL_TRIANGLES",
119 "GL_TRIANGLE_STRIP",
120 "GL_TRIANGLE_FAN",
121 "GL_QUADS",
122 "GL_QUAD_STRIP",
123 "GL_POLYGON",
124 "GL_LINES_ADJACENCY",
125 "GL_LINE_STRIP_ADJACENCY",
126 "GL_TRIANGLES_ADJACENCY",
127 "GL_TRIANGLE_STRIP_ADJACENCY",
128 "GL_PATCHES",
129 "outside begin/end",
130 "unknown state"
131 };
132
133
134 /* Get the name of an enum given that it is a primitive type. Avoids
135 * GL_FALSE/GL_POINTS ambiguity and others.
136 */
137 const char *
138 _mesa_lookup_prim_by_nr(GLuint nr)
139 {
140 if (nr < ARRAY_SIZE(prim_names))
141 return prim_names[nr];
142 else
143 return "invalid mode";
144 }
145
146
147 """
148 return
149
150
151 def printBody(self, xml):
152 self.process_enums(xml)
153
154 sorted_enum_values = sorted(self.enum_table.keys())
155 string_offsets = {}
156 i = 0;
157 print '#if defined(__GNUC__)'
158 print '# define LONGSTRING __extension__'
159 print '#else'
160 print '# define LONGSTRING'
161 print '#endif'
162 print ''
163 print 'LONGSTRING static const char enum_string_table[] = {'
164 # We express the very long concatenation of enum strings as an array
165 # of characters rather than as a string literal to work-around MSVC's
166 # 65535 character limit.
167 for enum in sorted_enum_values:
168 (name, pri) = self.enum_table[enum]
169 print " ",
170 for ch in name:
171 print "'%c'," % ch,
172 print "'\\0',"
173
174 string_offsets[ enum ] = i
175 i += len(name) + 1
176
177 print '};'
178 print ''
179
180
181 print 'static const enum_elt enum_string_table_offsets[%u] =' % (len(self.enum_table))
182 print '{'
183 for enum in sorted_enum_values:
184 (name, pri) = self.enum_table[enum]
185 print ' { %5u, 0x%08X }, /* %s */' % (string_offsets[enum], enum, name)
186 print '};'
187 print ''
188
189 self.print_code()
190 return
191
192 def add_enum_provider(self, name, priority):
193 value = self.string_to_int[name]
194
195 # We don't want the weird GL_SKIP_COMPONENTS1_NV enums.
196 if value < 0:
197 return
198 # We don't want the 64-bit GL_TIMEOUT_IGNORED "enums"
199 if value > 0xffffffff:
200 return
201
202 # We don't want bitfields in the enum-to-string table --
203 # individual bits have so many names, it's pointless. Note
204 # that we check for power-of-two, since some getters have
205 # "_BITS" in their name, but none have a power-of-two enum
206 # number.
207 if not (value & (value - 1)) and '_BIT' in name:
208 return
209
210 # Also drop the GL_*_ATTRIB_BITS bitmasks.
211 if value == 0xffffffff:
212 return
213
214 if value in self.enum_table:
215 (n, p) = self.enum_table[value]
216 if priority < p:
217 self.enum_table[value] = (name, priority)
218 else:
219 self.enum_table[value] = (name, priority)
220
221 def process_extension(self, extension):
222 if extension.get('name').startswith('GL_ARB_'):
223 extension_prio = 400
224 elif extension.get('name').startswith('GL_EXT_'):
225 extension_prio = 600
226 else:
227 extension_prio = 800
228
229 for enum in extension.findall('require/enum'):
230 self.add_enum_provider(enum.get('name'), extension_prio)
231
232 def process_enums(self, xml):
233 # First, process the XML entries that define the hex values
234 # for all of the enum names.
235 for enum in xml.findall('enums/enum'):
236 name = enum.get('name')
237 value = int(enum.get('value'), base=16)
238
239 # If the same name ever maps to multiple values, that can
240 # confuse us. GL_ACTIVE_PROGRAM_EXT is OK to lose because
241 # we choose GL_ACTIVE PROGRAM instead.
242 if name in self.string_to_int and name != "GL_ACTIVE_PROGRAM_EXT":
243 print "#error Renumbering {0} from {1} to {2}".format(name, self.string_to_int[name], value)
244
245 self.string_to_int[name] = value
246
247 # Now, process all of the API versions and extensions that
248 # provide enums, so we can decide what name to call any hex
249 # value.
250 for feature in xml.findall('feature'):
251 feature_name = feature.get('name')
252
253 # When an enum gets renamed in a newer version (generally
254 # because of some generalization of the functionality),
255 # prefer the newer name. Also, prefer desktop GL names to
256 # ES.
257 m = re.match('GL_VERSION_([0-9])_([0-9])', feature_name)
258 if m:
259 feature_prio = 100 - int(m.group(1) + m.group(2))
260 else:
261 m = re.match('GL_ES_VERSION_([0-9])_([0-9])', feature_name)
262 if m:
263 feature_prio = 200 - int(m.group(1) + m.group(2))
264 else:
265 feature_prio = 200
266
267 for enum in feature.findall('require/enum'):
268 self.add_enum_provider(enum.get('name'), feature_prio)
269
270 for extension in xml.findall('extensions/extension'):
271 self.process_extension(extension)
272
273
274 def _parser():
275 parser = argparse.ArgumentParser()
276 parser.add_argument('-f', '--input_file',
277 required=True,
278 help="Choose an xml file to parse.")
279 return parser.parse_args()
280
281
282 def main():
283 args = _parser()
284 xml = ET.parse(args.input_file)
285
286 printer = PrintGlEnums()
287 printer.Print(xml)
288
289
290 if __name__ == '__main__':
291 main()