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