mesa: Switch to using the Khronos registry for generating enums.
[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 ' uint16_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 STATIC_ASSERT(sizeof(enum_string_table) < (1 << 16));
91
92 elt = bsearch(& nr, enum_string_table_offsets,
93 ARRAY_SIZE(enum_string_table_offsets),
94 sizeof(enum_string_table_offsets[0]),
95 (cfunc) compar_nr);
96
97 if (elt != NULL) {
98 return &enum_string_table[elt->offset];
99 }
100 else {
101 /* this is not re-entrant safe, no big deal here */
102 _mesa_snprintf(token_tmp, sizeof(token_tmp) - 1, "0x%x", nr);
103 token_tmp[sizeof(token_tmp) - 1] = '\\0';
104 return token_tmp;
105 }
106 }
107
108 /**
109 * Primitive names
110 */
111 static const char *prim_names[PRIM_MAX+3] = {
112 "GL_POINTS",
113 "GL_LINES",
114 "GL_LINE_LOOP",
115 "GL_LINE_STRIP",
116 "GL_TRIANGLES",
117 "GL_TRIANGLE_STRIP",
118 "GL_TRIANGLE_FAN",
119 "GL_QUADS",
120 "GL_QUAD_STRIP",
121 "GL_POLYGON",
122 "GL_LINES_ADJACENCY",
123 "GL_LINE_STRIP_ADJACENCY",
124 "GL_TRIANGLES_ADJACENCY",
125 "GL_TRIANGLE_STRIP_ADJACENCY",
126 "GL_PATCHES",
127 "outside begin/end",
128 "unknown state"
129 };
130
131
132 /* Get the name of an enum given that it is a primitive type. Avoids
133 * GL_FALSE/GL_POINTS ambiguity and others.
134 */
135 const char *
136 _mesa_lookup_prim_by_nr(GLuint nr)
137 {
138 if (nr < ARRAY_SIZE(prim_names))
139 return prim_names[nr];
140 else
141 return "invalid mode";
142 }
143
144
145 """
146 return
147
148
149 def printBody(self, xml):
150 self.process_enums(xml)
151
152 sorted_enum_values = sorted(self.enum_table.keys())
153 string_offsets = {}
154 i = 0;
155 print '#if defined(__GNUC__)'
156 print '# define LONGSTRING __extension__'
157 print '#else'
158 print '# define LONGSTRING'
159 print '#endif'
160 print ''
161 print 'LONGSTRING static const char enum_string_table[] = '
162 for enum in sorted_enum_values:
163 (name, pri) = self.enum_table[enum]
164 print ' "%s\\0"' % (name)
165 string_offsets[ enum ] = i
166 i += len(name) + 1
167
168 print ' ;'
169 print ''
170
171
172 print 'static const enum_elt enum_string_table_offsets[%u] =' % (len(self.enum_table))
173 print '{'
174 for enum in sorted_enum_values:
175 (name, pri) = self.enum_table[enum]
176 print ' { %5u, 0x%08X }, /* %s */' % (string_offsets[enum], enum, name)
177 print '};'
178 print ''
179
180 self.print_code()
181 return
182
183 def add_enum_provider(self, name, priority):
184 # Skip some enums, to reduce the diffs from this commit.
185 if name in ['GL_NEXT_BUFFER_NV',
186 # Mesa was choosing GL_LINES for this, which wasn't great.
187 'GL_TRUE',
188 # Old names for things where Mesa was using the new names.
189 'GL_VERTEX_PROGRAM_POINT_SIZE',
190 'GL_MAX_VARYING_FLOATS',
191 'GL_CLIP_PLANE0',
192 'GL_CLIP_PLANE1',
193 'GL_CLIP_PLANE2',
194 'GL_CLIP_PLANE3',
195 'GL_CLIP_PLANE4',
196 'GL_CLIP_PLANE5',
197 'GL_MAX_CLIP_PLANES',
198 'GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS',
199 'GL_FOG_COORDINATE',
200 'GL_CURRENT_FOG_COORDINATE',
201 'GL_COMPARE_R_TO_TEXTURE',
202 # GL 2.0 name when Mesa was using GLES 1.0.
203 'GL_BLEND_EQUATION_RGB',
204 # GL3.x compat names that Mesa was missing.
205 'GL_ALPHA_SNORM',
206 'GL_LUMINANCE_SNORM',
207 'GL_LUMINANCE_ALPHA_SNORM',
208 'GL_INTENSITY_SNORM',
209 'GL_ALPHA8_SNORM',
210 'GL_LUMINANCE8_SNORM',
211 'GL_LUMINANCE8_ALPHA8_SNORM',
212 'GL_INTENSITY8_SNORM',
213 'GL_ALPHA16_SNORM',
214 'GL_LUMINANCE16_SNORM',
215 'GL_LUMINANCE16_ALPHA16_SNORM',
216 'GL_INTENSITY16_SNORM',
217 # ARB_imaging names that Mesa was missing.
218 'GL_COLOR_INDEX1_EXT',
219 'GL_COLOR_INDEX2_EXT',
220 'GL_COLOR_INDEX4_EXT',
221 'GL_COLOR_INDEX8_EXT',
222 'GL_COLOR_INDEX12_EXT',
223 'GL_COLOR_INDEX16_EXT',
224 'GL_CONSTANT_BORDER',
225 'GL_REPLICATE_BORDER',
226 'GL_TABLE_TOO_LARGE',
227 # ARB_texture_view names that Mesa was missing.
228 'GL_TEXTURE_VIEW_MIN_LEVEL',
229 'GL_TEXTURE_VIEW_NUM_LEVELS',
230 'GL_TEXTURE_VIEW_MIN_LAYER',
231 'GL_TEXTURE_VIEW_NUM_LAYERS',
232 # GL4.2 BPTC names that Mesa was missing.
233 'GL_COMPRESSED_RGBA_BPTC_UNORM',
234 'GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM',
235 'GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT',
236 'GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT',
237 # Mesa was choosing the EXT names for these
238 # instead of core.
239 'GL_ALPHA_INTEGER',
240 'GL_PROGRAM_SEPARABLE',
241 'GL_PROGRAM_PIPELINE_BINDING',
242 'GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS',
243 # Mesa was choosing the ARB names for these instead of core.
244 'GL_TEXTURE_CUBE_MAP_ARRAY',
245 'GL_TEXTURE_BINDING_CUBE_MAP_ARRAY',
246 'GL_PROXY_TEXTURE_CUBE_MAP_ARRAY',
247 'GL_SAMPLER_CUBE_MAP_ARRAY',
248 'GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW',
249 'GL_INT_SAMPLER_CUBE_MAP_ARRAY',
250 'GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY',
251 'GL_TRANSFORM_FEEDBACK_PAUSED',
252 'GL_TRANSFORM_FEEDBACK_ACTIVE',
253 'GL_VERTEX_ATTRIB_ARRAY_DIVISOR',
254 # Mesa was choosing the ANGLE names for these
255 # instead of EXT.
256 'GL_COMPRESSED_RGBA_S3TC_DXT3_EXT',
257 'GL_COMPRESSED_RGBA_S3TC_DXT5_EXT',
258 ]:
259 return
260
261 # Mesa didn't know about the second half of this set of enums.
262 m = re.match('GL_COLOR_ATTACHMENT([0-9]*)', name)
263 if m and int(m.group(1)) >= 16:
264 return
265
266 value = self.string_to_int[name]
267
268 # We don't want the weird GL_SKIP_COMPONENTS1_NV enums.
269 if value < 0:
270 return
271 # We don't want the 64-bit GL_TIMEOUT_IGNORED "enums"
272 if value > 0xffffffff:
273 return
274
275 if name.endswith('_BIT'):
276 priority += 100
277
278 if value in self.enum_table:
279 (n, p) = self.enum_table[value]
280 if priority < p:
281 self.enum_table[value] = (name, priority)
282 else:
283 self.enum_table[value] = (name, priority)
284
285 def process_extension(self, extension):
286 # Skip some of the extensions, to reduce the diffs from this commit.
287 extension_name = extension.get('name')
288 whitelist = ['GL_ANGLE_texture_compression_dxt3',
289 'GL_ANGLE_texture_compression_dxt5',
290 'GL_APPLE_flush_buffer_range',
291 'GL_APPLE_object_purgeable',
292 'GL_APPLE_texture_range',
293 'GL_SGIS_texture_color_mask',
294 'GL_SGIX_clipmap',
295 'GL_SGIX_texture_coordinate_clamp',
296 'GL_SGIX_fog_offset',
297 'GL_SGIX_texture_scale_bias',
298 'GL_SGIX_texture_lod_bias',
299 'GL_SGIX_shadow',
300 'GL_APPLE_ycbcr_422']
301 whitelist_only_prefixes = ['GL_APPLE',
302 'GL_ANGLE',
303 'GL_ARM',
304 'GL_DMP',
305 'GL_FJ',
306 'GL_INGR',
307 'GL_IMG_',
308 'GL_MESAX_',
309 'GL_MALI_',
310 'GL_NVX_',
311 'GL_OML_',
312 'GL_OVR_',
313 'GL_PGI_',
314 'GL_QCOM_',
315 'GL_REND_',
316 'GL_SGIS_',
317 'GL_SGIX_',
318 'GL_WIN_',
319 'GL_VIV_']
320
321 for prefix in whitelist_only_prefixes:
322 if extension_name.startswith(prefix):
323 if extension_name not in whitelist:
324 return
325
326 if extension_name in ['GL_ATI_element_array',
327 'GL_ATI_meminfo',
328 'GL_ATI_text_fragment_shader',
329 'GL_ATI_pixel_format_float',
330 'GL_ATI_pn_triangles',
331 'GL_ATI_vertex_array_object',
332 'GL_ATI_vertex_streams',
333 'GL_AMD_blend_minmax_factor',
334 'GL_AMD_compressed_3DC_texture',
335 'GL_AMD_compressed_ATC_texture',
336 'GL_AMD_debug_output',
337 'GL_AMD_depth_clamp_separate',
338 'GL_AMD_gpu_shader_int64',
339 'GL_AMD_query_buffer_object',
340 'GL_AMD_interleaved_elements',
341 'GL_AMD_name_gen_delete',
342 'GL_AMD_occlusion_query_event',
343 'GL_AMD_program_binary_Z400',
344 'GL_AMD_sample_positions',
345 'GL_AMD_sparse_texture',
346 'GL_AMD_stencil_operation_extended',
347 'GL_AMD_transform_feedback4',
348 'GL_AMD_vertex_shader_tessellator',
349 'GL_ARB_bindless_texture',
350 'GL_ARB_cl_event',
351 'GL_ARB_compute_variable_group_size',
352 'GL_ARB_cull_distance',
353 'GL_ARB_enhanced_layouts',
354 'GL_ARB_indirect_parameters',
355 'GL_ARB_internalformat_query2',
356 'GL_ARB_query_buffer_object',
357 'GL_ARB_shading_language_include',
358 'GL_ARB_sparse_buffer',
359 'GL_ARB_sparse_texture',
360 'GL_ARB_texture_compression_bptc',
361 'GL_ARB_texture_mirror_clamp_to_edge',
362 'GL_ARB_texture_view',
363 'GL_ARB_transform_feedback_overflow_query',
364 'GL_EXT_422_pixels',
365 'GL_EXT_bindable_uniform',
366 'GL_EXT_cmyka',
367 'GL_EXT_coordinate_frame',
368 'GL_EXT_debug_label',
369 'GL_EXT_direct_state_access',
370 'GL_EXT_disjoint_timer_query',
371 'GL_EXT_geometry_shader',
372 'GL_EXT_light_texture',
373 'GL_EXT_robustness',
374 'GL_EXT_tessellation_shader',
375 'GL_EXT_texture_compression_latc',
376 'GL_EXT_texture_filter_minmax',
377 'GL_EXT_texture_sRGB_R8',
378 'GL_EXT_texture_sRGB_RG8',
379 'GL_EXT_framebuffer_multisample_blit_scaled',
380 'GL_EXT_multisample',
381 'GL_EXT_multisampled_render_to_texture',
382 'GL_EXT_multiview_draw_buffers',
383 'GL_EXT_pixel_transform',
384 'GL_EXT_primitive_bounding_box',
385 'GL_EXT_pvrtc_sRGB',
386 'GL_EXT_raster_multisample',
387 'GL_EXT_shader_framebuffer_fetch',
388 'GL_EXT_shader_pixel_local_storage',
389 'GL_EXT_sparse_texture',
390 'GL_EXT_stencil_clear_tag',
391 'GL_EXT_tesselation_shader',
392 'GL_EXT_texture_perturb_normal',
393 'GL_EXT_texture_sRGB',
394 'GL_EXT_texture_storage',
395 'GL_EXT_texture_view',
396 'GL_EXT_vertex_shader',
397 'GL_EXT_vertex_weighting',
398 'GL_EXT_x11_sync_object',
399 'GL_EXT_YUV_target',
400 'GL_IBM_cull_vertex',
401 'GL_IBM_static_data',
402 'GL_IBM_vertex_array_lists',
403 'GL_INTEL_map_texture',
404 'GL_INTEL_parallel_arrays',
405 'GL_HP_image_transform',
406 'GL_HP_texture_lighting',
407 'GL_KHR_blend_equation_advanced',
408 'GL_KHR_blend_equation_advanced_coherent',
409 'GL_KHR_robustness',
410 'GL_NV_blend_equation_advanced',
411 'GL_NV_blend_equation_advanced_coherent',
412 'GL_NV_command_list',
413 'GL_NV_compute_program5',
414 'GL_NV_conservative_raster',
415 'GL_NV_coverage_sample',
416 'GL_NV_deep_texture3D',
417 'GL_NV_depth_buffer_float',
418 'GL_NV_depth_nonlinear',
419 'GL_NV_evaluators',
420 'GL_NV_explicit_multisample',
421 'GL_NV_fence',
422 'GL_NV_fill_rectangle',
423 'GL_NV_float_buffer',
424 'GL_NV_fragment_coverage_to_color',
425 'GL_NV_framebuffer_mixed_samples',
426 'GL_NV_framebuffer_multisample_coverage',
427 'GL_NV_geometry_program4',
428 'GL_NV_gpu_program4',
429 'GL_NV_gpu_program5',
430 'GL_NV_gpu_shader5',
431 'GL_NV_internalformat_sample_query',
432 'GL_NV_multisample_coverage',
433 'GL_NV_parameter_buffer_object',
434 'GL_NV_path_rendering',
435 'GL_NV_path_rendering_shared_edge',
436 'GL_NV_pixel_data_range',
437 'GL_NV_present_video',
438 'GL_NV_register_combiners',
439 'GL_NV_register_combiners2',
440 'GL_NV_sample_locations',
441 'GL_NV_shader_buffer_load',
442 'GL_NV_shader_image_load_store',
443 'GL_NV_shader_thread_group',
444 'GL_NV_sRGB_formats',
445 'GL_NV_tessellation_program5',
446 'GL_NV_texgen_emboss',
447 'GL_NV_texture_multisample',
448 'GL_NV_texture_shader',
449 'GL_NV_texture_shader2',
450 'GL_NV_texture_shader3',
451 'GL_NV_transform_feedback',
452 'GL_NV_uniform_buffer_unified_memory',
453 'GL_NV_vertex_array_range',
454 'GL_NV_vertex_array_range2',
455 'GL_NV_vertex_attrib_integer_64bit',
456 'GL_NV_vertex_buffer_unified_memory',
457 'GL_NV_video_capture',
458 'GL_OES_geometry_shader',
459 'GL_OES_primitive_bounding_box',
460 'GL_OES_tessellation_shader',
461 'GL_OES_texture_compression_astc',
462 'GL_OES_texture_view',
463 'GL_SGI_color_table',
464 'GL_SUN_global_alpha',
465 'GL_SUN_triangle_list',
466 'GL_SUNX_constant_data',
467 'GL_EXT_index_func',
468 'GL_EXT_index_array_formats',
469 'GL_EXT_index_material']:
470 return
471
472 if extension.get('name').startswith('GL_ARB_'):
473 extension_prio = 400
474 elif extension.get('name').startswith('GL_EXT_'):
475 extension_prio = 600
476 else:
477 extension_prio = 800
478
479 for enum in extension.findall('require/enum'):
480 self.add_enum_provider(enum.get('name'), extension_prio)
481
482 # Part of 4.4, but Mesa added it early.
483 self.add_enum_provider('GL_MAX_VERTEX_ATTRIB_STRIDE', 44)
484
485 def process_enums(self, xml):
486 # First, process the XML entries that define the hex values
487 # for all of the enum names.
488 for enum in xml.findall('enums/enum'):
489 name = enum.get('name')
490 value = int(enum.get('value'), base=16)
491
492 if name == 'GL_ALL_ATTRIB_BITS':
493 # Khronos XML defines this one as 0xffffffff, but Mesa
494 # has always had the original definition of
495 # 0x000fffff.
496 value = 0x000fffff
497
498 # If the same name ever maps to multiple values, that can
499 # confuse us. GL_ACTIVE_PROGRAM_EXT is OK to lose because
500 # we choose GL_ACTIVE PROGRAM instead.
501 if name in self.string_to_int and name != "GL_ACTIVE_PROGRAM_EXT":
502 print "#error Renumbering {0} from {1} to {2}".format(name, self.string_to_int[name], value)
503
504 self.string_to_int[name] = value
505
506 # Now, process all of the API versions and extensions that
507 # provide enums, so we can decide what name to call any hex
508 # value.
509 for feature in xml.findall('feature'):
510 feature_name = feature.get('name')
511 # Skip some of the extensions, to reduce the diffs from this commit.
512 if feature_name in ['GL_VERSION_4_3',
513 'GL_VERSION_4_4',
514 'GL_VERSION_4_5',
515 'GL_ES_VERSION_3_1']:
516 continue
517
518 # Give priority to the older versions of various symbol
519 # names, since Mesa tended to have the older ones.
520 m = re.match('GL_VERSION_([0-9])_([0-9])', feature_name)
521 if m:
522 feature_prio = int(m.group(1) + m.group(2))
523 else:
524 m = re.match('GL_ES_VERSION_([0-9])_([0-9])', feature_name)
525 if m:
526 feature_prio = int(m.group(1) + m.group(2))
527 else:
528 feature_prio = 200
529
530 for enum in feature.findall('require/enum'):
531 self.add_enum_provider(enum.get('name'), feature_prio)
532
533 for extension in xml.findall('extensions/extension'):
534 self.process_extension(extension)
535
536
537 def _parser():
538 parser = argparse.ArgumentParser()
539 parser.add_argument('-f', '--input_file',
540 required=True,
541 help="Choose an xml file to parse.")
542 return parser.parse_args()
543
544
545 def main():
546 args = _parser()
547 xml = ET.parse(args.input_file)
548
549 printer = PrintGlEnums()
550 printer.Print(xml)
551
552
553 if __name__ == '__main__':
554 main()