2 # (C) Copyright Zack Rusin 2005. All Rights Reserved.
3 # Copyright (C) 2015 Intel Corporation
4 # Copyright (C) 2015 Broadcom Corporation
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:
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
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
26 # Zack Rusin <zack@kde.org>
28 from __future__
import print_function
34 import xml
.etree
.ElementTree
as ET
38 class PrintGlEnums(gl_XML
.gl_print_base
):
41 gl_XML
.gl_print_base
.__init
__(self
)
43 self
.name
= "gl_enums.py (from Mesa)"
44 self
.license
= license
.bsd_license_template
% ( \
45 """Copyright (C) 1999-2005 Brian Paul All Rights Reserved.""", "BRIAN PAUL")
46 # Mapping from enum value to (name, priority) tuples.
48 # Mapping from enum name to value
49 self
.string_to_int
= {}
52 def printRealHeader(self
):
53 print('#include "main/glheader.h"')
54 print('#include "main/enums.h"')
55 print('#include "util/imports.h"')
56 print('#include "main/mtypes.h"')
58 print('typedef struct PACKED {')
59 print(' uint32_t offset;')
67 typedef int (*cfunc)(const void *, const void *);
70 * Compare a key enum value to an element in the \c enum_string_table_offsets array.
72 * \c bsearch always passes the key as the first parameter and the pointer
73 * to the array element as the second parameter. We can elimiate some
74 * extra work by taking advantage of that fact.
76 * \param a Pointer to the desired enum name.
77 * \param b Pointer into the \c enum_string_table_offsets array.
79 static int compar_nr( const int *a, enum_elt *b )
85 static char token_tmp[20];
88 * This function always returns a string. If the number is a valid enum, it
89 * returns the enum name. Otherwise, it returns a numeric string.
92 _mesa_enum_to_string(int nr)
96 elt = bsearch(& nr, enum_string_table_offsets,
97 ARRAY_SIZE(enum_string_table_offsets),
98 sizeof(enum_string_table_offsets[0]),
102 return &enum_string_table[elt->offset];
105 /* this is not re-entrant safe, no big deal here */
106 _mesa_snprintf(token_tmp, sizeof(token_tmp) - 1, "0x%x", nr);
107 token_tmp[sizeof(token_tmp) - 1] = '\\0';
115 static const char *prim_names[PRIM_MAX+3] = {
126 "GL_LINES_ADJACENCY",
127 "GL_LINE_STRIP_ADJACENCY",
128 "GL_TRIANGLES_ADJACENCY",
129 "GL_TRIANGLE_STRIP_ADJACENCY",
136 /* Get the name of an enum given that it is a primitive type. Avoids
137 * GL_FALSE/GL_POINTS ambiguity and others.
140 _mesa_lookup_prim_by_nr(GLuint nr)
142 if (nr < ARRAY_SIZE(prim_names))
143 return prim_names[nr];
145 return "invalid mode";
153 def printBody(self
, xml
):
154 self
.process_enums(xml
)
156 sorted_enum_values
= sorted(self
.enum_table
.keys())
159 print('#if defined(__GNUC__)')
160 print('# define LONGSTRING __extension__')
162 print('# define LONGSTRING')
165 print('LONGSTRING static const char enum_string_table[] = {')
166 # We express the very long concatenation of enum strings as an array
167 # of characters rather than as a string literal to work-around MSVC's
168 # 65535 character limit.
169 for enum
in sorted_enum_values
:
170 (name
, pri
) = self
.enum_table
[enum
]
173 print("'%c'," % ch
, end
=' ')
176 string_offsets
[ enum
] = i
183 print('static const enum_elt enum_string_table_offsets[%u] =' % (len(self
.enum_table
)))
185 for enum
in sorted_enum_values
:
186 (name
, pri
) = self
.enum_table
[enum
]
187 print(' { %5u, 0x%08X }, /* %s */' % (string_offsets
[enum
], enum
, name
))
194 def add_enum_provider(self
, name
, priority
):
195 value
= self
.string_to_int
[name
]
197 # We don't want the weird GL_SKIP_COMPONENTS1_NV enums.
200 # We don't want the 64-bit GL_TIMEOUT_IGNORED "enums"
201 if value
> 0xffffffff:
204 # We don't want bitfields in the enum-to-string table --
205 # individual bits have so many names, it's pointless. Note
206 # that we check for power-of-two, since some getters have
207 # "_BITS" in their name, but none have a power-of-two enum
209 if not (value
& (value
- 1)) and '_BIT' in name
:
212 # Also drop the GL_*_ATTRIB_BITS bitmasks.
213 if value
== 0xffffffff:
216 if value
in self
.enum_table
:
217 (n
, p
) = self
.enum_table
[value
]
219 self
.enum_table
[value
] = (name
, priority
)
221 self
.enum_table
[value
] = (name
, priority
)
223 def process_extension(self
, extension
):
224 if extension
.get('name').startswith('GL_ARB_'):
226 elif extension
.get('name').startswith('GL_EXT_'):
231 for enum
in extension
.findall('require/enum'):
232 self
.add_enum_provider(enum
.get('name'), extension_prio
)
234 def process_enums(self
, xml
):
235 # First, process the XML entries that define the hex values
236 # for all of the enum names.
237 for enum
in xml
.findall('enums/enum'):
238 name
= enum
.get('name')
239 value
= int(enum
.get('value'), base
=16)
241 # If the same name ever maps to multiple values, that can
242 # confuse us. GL_ACTIVE_PROGRAM_EXT is OK to lose because
243 # we choose GL_ACTIVE PROGRAM instead.
244 if name
in self
.string_to_int
and name
!= "GL_ACTIVE_PROGRAM_EXT":
245 print("#error Renumbering {0} from {1} to {2}".format(name
, self
.string_to_int
[name
], value
))
247 self
.string_to_int
[name
] = value
249 # Now, process all of the API versions and extensions that
250 # provide enums, so we can decide what name to call any hex
252 for feature
in xml
.findall('feature'):
253 feature_name
= feature
.get('name')
255 # When an enum gets renamed in a newer version (generally
256 # because of some generalization of the functionality),
257 # prefer the newer name. Also, prefer desktop GL names to
259 m
= re
.match('GL_VERSION_([0-9])_([0-9])', feature_name
)
261 feature_prio
= 100 - int(m
.group(1) + m
.group(2))
263 m
= re
.match('GL_ES_VERSION_([0-9])_([0-9])', feature_name
)
265 feature_prio
= 200 - int(m
.group(1) + m
.group(2))
269 for enum
in feature
.findall('require/enum'):
270 self
.add_enum_provider(enum
.get('name'), feature_prio
)
272 for extension
in xml
.findall('extensions/extension'):
273 self
.process_extension(extension
)
277 parser
= argparse
.ArgumentParser()
278 parser
.add_argument('-f', '--input_file',
280 help="Choose an xml file to parse.")
281 return parser
.parse_args()
286 xml
= ET
.parse(args
.input_file
)
288 printer
= PrintGlEnums()
292 if __name__
== '__main__':