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>
32 import xml
.etree
.ElementTree
as ET
36 class PrintGlEnums(gl_XML
.gl_print_base
):
39 gl_XML
.gl_print_base
.__init
__(self
)
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.
46 # Mapping from enum name to value
47 self
.string_to_int
= {}
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"'
56 print 'typedef struct PACKED {'
57 print ' uint32_t offset;'
65 typedef int (*cfunc)(const void *, const void *);
68 * Compare a key enum value to an element in the \c enum_string_table_offsets array.
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.
74 * \param a Pointer to the desired enum name.
75 * \param b Pointer into the \c enum_string_table_offsets array.
77 static int compar_nr( const int *a, enum_elt *b )
83 static char token_tmp[20];
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.
90 _mesa_enum_to_string(int nr)
94 elt = bsearch(& nr, enum_string_table_offsets,
95 ARRAY_SIZE(enum_string_table_offsets),
96 sizeof(enum_string_table_offsets[0]),
100 return &enum_string_table[elt->offset];
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';
113 static const char *prim_names[PRIM_MAX+3] = {
124 "GL_LINES_ADJACENCY",
125 "GL_LINE_STRIP_ADJACENCY",
126 "GL_TRIANGLES_ADJACENCY",
127 "GL_TRIANGLE_STRIP_ADJACENCY",
134 /* Get the name of an enum given that it is a primitive type. Avoids
135 * GL_FALSE/GL_POINTS ambiguity and others.
138 _mesa_lookup_prim_by_nr(GLuint nr)
140 if (nr < ARRAY_SIZE(prim_names))
141 return prim_names[nr];
143 return "invalid mode";
151 def printBody(self
, xml
):
152 self
.process_enums(xml
)
154 sorted_enum_values
= sorted(self
.enum_table
.keys())
157 print '#if defined(__GNUC__)'
158 print '# define LONGSTRING __extension__'
160 print '# define LONGSTRING'
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
]
174 string_offsets
[ enum
] = i
181 print 'static const enum_elt enum_string_table_offsets[%u] =' % (len(self
.enum_table
))
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
)
192 def add_enum_provider(self
, name
, priority
):
193 value
= self
.string_to_int
[name
]
195 # We don't want the weird GL_SKIP_COMPONENTS1_NV enums.
198 # We don't want the 64-bit GL_TIMEOUT_IGNORED "enums"
199 if value
> 0xffffffff:
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
207 if not (value
& (value
- 1)) and '_BIT' in name
:
210 # Also drop the GL_*_ATTRIB_BITS bitmasks.
211 if value
== 0xffffffff:
214 if value
in self
.enum_table
:
215 (n
, p
) = self
.enum_table
[value
]
217 self
.enum_table
[value
] = (name
, priority
)
219 self
.enum_table
[value
] = (name
, priority
)
221 def process_extension(self
, extension
):
222 if extension
.get('name').startswith('GL_ARB_'):
224 elif extension
.get('name').startswith('GL_EXT_'):
229 for enum
in extension
.findall('require/enum'):
230 self
.add_enum_provider(enum
.get('name'), extension_prio
)
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)
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
)
245 self
.string_to_int
[name
] = value
247 # Now, process all of the API versions and extensions that
248 # provide enums, so we can decide what name to call any hex
250 for feature
in xml
.findall('feature'):
251 feature_name
= feature
.get('name')
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
257 m
= re
.match('GL_VERSION_([0-9])_([0-9])', feature_name
)
259 feature_prio
= 100 - int(m
.group(1) + m
.group(2))
261 m
= re
.match('GL_ES_VERSION_([0-9])_([0-9])', feature_name
)
263 feature_prio
= 200 - int(m
.group(1) + m
.group(2))
267 for enum
in feature
.findall('require/enum'):
268 self
.add_enum_provider(enum
.get('name'), feature_prio
)
270 for extension
in xml
.findall('extensions/extension'):
271 self
.process_extension(extension
)
275 parser
= argparse
.ArgumentParser()
276 parser
.add_argument('-f', '--input_file',
278 help="Choose an xml file to parse.")
279 return parser
.parse_args()
284 xml
= ET
.parse(args
.input_file
)
286 printer
= PrintGlEnums()
290 if __name__
== '__main__':