|  | #!/usr/bin/python3 | 
|  | # | 
|  | # Copyright 2019 The ANGLE Project Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  | # | 
|  | # gen_gl_enum_utils.py: | 
|  | #   Generates GLenum value to string mapping for ANGLE | 
|  | #   NOTE: don't run this script directly. Run scripts/run_code_generation.py. | 
|  |  | 
|  | import sys | 
|  | import os | 
|  |  | 
|  | import registry_xml | 
|  |  | 
|  | template_gl_enums_header = """// GENERATED FILE - DO NOT EDIT. | 
|  | // Generated by {script_name} using data from {data_source_name}. | 
|  | // | 
|  | // Copyright 2019 The ANGLE Project Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  | // | 
|  | // gl_enum_utils_autogen.h: | 
|  | //   mapping of GLenum value to string. | 
|  |  | 
|  | # ifndef LIBANGLE_GL_ENUM_UTILS_AUTOGEN_H_ | 
|  | # define LIBANGLE_GL_ENUM_UTILS_AUTOGEN_H_ | 
|  |  | 
|  | namespace gl | 
|  | {{ | 
|  | enum class GLenumGroup | 
|  | {{ | 
|  | {gl_enum_groups} | 
|  | }}; | 
|  | }}  // namespace gl | 
|  |  | 
|  | # endif  // LIBANGLE_GL_ENUM_UTILS_AUTOGEN_H_ | 
|  | """ | 
|  |  | 
|  | template_gl_enums_source = """// GENERATED FILE - DO NOT EDIT. | 
|  | // Generated by {script_name} using data from {data_source_name}. | 
|  | // | 
|  | // Copyright 2019 The ANGLE Project Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  | // | 
|  | // gl_enum_utils_autogen.cpp: | 
|  | //   mapping of GLenum value to string. | 
|  |  | 
|  | #include "libANGLE/capture/gl_enum_utils_autogen.h" | 
|  |  | 
|  | #include "libANGLE/capture/gl_enum_utils.h" | 
|  |  | 
|  | namespace gl | 
|  | {{ | 
|  | namespace | 
|  | {{ | 
|  | const char *UnknownGLenumToString(unsigned int value) | 
|  | {{ | 
|  | constexpr size_t kBufferSize = 64; | 
|  | static thread_local char sBuffer[kBufferSize]; | 
|  | snprintf(sBuffer, kBufferSize, "0x%04X", value); | 
|  | return sBuffer; | 
|  | }} | 
|  | }}  // anonymous namespace | 
|  |  | 
|  | const char *GLenumToString(GLenumGroup enumGroup, unsigned int value) | 
|  | {{ | 
|  | switch (enumGroup) | 
|  | {{ | 
|  | {gl_enums_value_to_string_table} | 
|  | default: | 
|  | return UnknownGLenumToString(value); | 
|  | }} | 
|  | }} | 
|  | }}  // namespace gl | 
|  |  | 
|  | """ | 
|  |  | 
|  | template_enum_group_case = """case GLenumGroup::{group_name}: {{ | 
|  | switch (value) {{ | 
|  | {inner_group_cases} | 
|  | default: | 
|  | return UnknownGLenumToString(value); | 
|  | }} | 
|  | }} | 
|  | """ | 
|  |  | 
|  | template_enum_value_to_string_case = """case {value}: return {name};""" | 
|  |  | 
|  | exclude_gl_enums = { | 
|  | 'GL_NO_ERROR', 'GL_TIMEOUT_IGNORED', 'GL_INVALID_INDEX', 'GL_VERSION_ES_CL_1_0', | 
|  | 'GL_VERSION_ES_CM_1_1', 'GL_VERSION_ES_CL_1_1' | 
|  | } | 
|  | exclude_gl_enum_groups = {'SpecialNumbers'} | 
|  |  | 
|  |  | 
|  | def dump_value_to_string_mapping(gl_enum_in_groups, exporting_enums): | 
|  | exporting_groups = list() | 
|  | for group_name, inner_mapping in gl_enum_in_groups.items(): | 
|  | string_value_pairs = list(filter(lambda x: x[0] in exporting_enums, inner_mapping.items())) | 
|  | if not string_value_pairs: | 
|  | continue | 
|  |  | 
|  | # sort according values | 
|  | string_value_pairs.sort(key=lambda x: (x[1], x[0])) | 
|  |  | 
|  | # remove all duplicate values from the pairs list | 
|  | # some value may have more than one GLenum mapped to them, such as: | 
|  | #     GL_DRAW_FRAMEBUFFER_BINDING and GL_FRAMEBUFFER_BINDING | 
|  | #     GL_BLEND_EQUATION_RGB and GL_BLEND_EQUATION | 
|  | # it is safe to output either one of them, for simplity here just | 
|  | # choose the shorter one which comes first in the sorted list | 
|  | exporting_string_value_pairs = list() | 
|  | for index, pair in enumerate(string_value_pairs): | 
|  | if index == 0 or pair[1] != string_value_pairs[index - 1][1]: | 
|  | exporting_string_value_pairs.append(pair) | 
|  |  | 
|  | inner_code_block = "\n".join([ | 
|  | template_enum_value_to_string_case.format( | 
|  | value='0x%X' % value, | 
|  | name='"%s"' % name, | 
|  | ) for name, value in exporting_string_value_pairs | 
|  | ]) | 
|  |  | 
|  | exporting_groups.append((group_name, inner_code_block)) | 
|  |  | 
|  | return "\n".join([ | 
|  | template_enum_group_case.format( | 
|  | group_name=group_name, | 
|  | inner_group_cases=inner_code_block, | 
|  | ) for group_name, inner_code_block in sorted(exporting_groups, key=lambda x: x[0]) | 
|  | ]) | 
|  |  | 
|  |  | 
|  | def main(header_output_path, source_output_path): | 
|  | xml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml') | 
|  |  | 
|  | # build a map from GLenum name to its value | 
|  | all_gl_enums = dict() | 
|  | for enums_node in xml.root.findall('enums'): | 
|  | for enum in enums_node.findall('enum'): | 
|  | name = enum.attrib['name'] | 
|  | value = int(enum.attrib['value'], base=16) | 
|  | all_gl_enums[name] = value | 
|  |  | 
|  | # Parse groups of GLenums to build a {group, name} -> value mapping. | 
|  | gl_enum_in_groups = dict() | 
|  | enums_has_group = set() | 
|  | for enums_group_node in xml.root.findall('groups/group'): | 
|  | group_name = enums_group_node.attrib['name'] | 
|  | if group_name in exclude_gl_enum_groups: | 
|  | continue | 
|  |  | 
|  | if group_name not in gl_enum_in_groups: | 
|  | gl_enum_in_groups[group_name] = dict() | 
|  |  | 
|  | for enum_node in enums_group_node.findall('enum'): | 
|  | enum_name = enum_node.attrib['name'] | 
|  | enums_has_group.add(enum_name) | 
|  | gl_enum_in_groups[group_name][enum_name] = all_gl_enums[enum_name] | 
|  |  | 
|  | # Find relevant GLenums according to enabled APIs and extensions. | 
|  | exporting_enums = set() | 
|  | # export all the apis | 
|  | xpath = "./feature[@api='gles2']/require/enum" | 
|  | for enum_tag in xml.root.findall(xpath): | 
|  | enum_name = enum_tag.attrib['name'] | 
|  | if enum_name not in exclude_gl_enums: | 
|  | exporting_enums.add(enum_name) | 
|  |  | 
|  | for extension in registry_xml.supported_extensions: | 
|  | xpath = "./extensions/extension[@name='%s']/require/enum" % extension | 
|  | for enum_tag in xml.root.findall(xpath): | 
|  | enum_name = enum_tag.attrib['name'] | 
|  | if enum_name not in exclude_gl_enums: | 
|  | exporting_enums.add(enum_name) | 
|  |  | 
|  | # For enums that do not have a group, add them to a default group | 
|  | default_group_name = registry_xml.default_enum_group_name | 
|  | gl_enum_in_groups[default_group_name] = dict() | 
|  | default_group = gl_enum_in_groups[default_group_name] | 
|  | for enum_name in exporting_enums: | 
|  | if enum_name not in enums_has_group: | 
|  | default_group[enum_name] = all_gl_enums[enum_name] | 
|  |  | 
|  | # Write GLenum groups into the header file. | 
|  | header_content = template_gl_enums_header.format( | 
|  | script_name=os.path.basename(sys.argv[0]), | 
|  | data_source_name="gl.xml and gl_angle_ext.xml", | 
|  | gl_enum_groups=',\n'.join(sorted(gl_enum_in_groups.keys()))) | 
|  |  | 
|  | header_output_path = registry_xml.script_relative(header_output_path) | 
|  | with open(header_output_path, 'w') as f: | 
|  | f.write(header_content) | 
|  |  | 
|  | # Write mapping to source file | 
|  | gl_enums_value_to_string_table = dump_value_to_string_mapping(gl_enum_in_groups, | 
|  | exporting_enums) | 
|  | source_content = template_gl_enums_source.format( | 
|  | script_name=os.path.basename(sys.argv[0]), | 
|  | data_source_name="gl.xml and gl_angle_ext.xml", | 
|  | gl_enums_value_to_string_table=gl_enums_value_to_string_table, | 
|  | ) | 
|  |  | 
|  | source_output_path = registry_xml.script_relative(source_output_path) | 
|  | with open(source_output_path, 'w') as f: | 
|  | f.write(source_content) | 
|  |  | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | inputs = [ | 
|  | 'gl.xml', | 
|  | 'gl_angle_ext.xml', | 
|  | 'registry_xml.py', | 
|  | ] | 
|  |  | 
|  | gl_enum_utils_autogen_base_path = '../src/libANGLE/capture/gl_enum_utils_autogen' | 
|  | outputs = [ | 
|  | gl_enum_utils_autogen_base_path + '.h', | 
|  | gl_enum_utils_autogen_base_path + '.cpp', | 
|  | ] | 
|  |  | 
|  | if len(sys.argv) > 1: | 
|  | if sys.argv[1] == 'inputs': | 
|  | print(','.join(inputs)) | 
|  | elif sys.argv[1] == 'outputs': | 
|  | print(','.join(outputs)) | 
|  | else: | 
|  | sys.exit( | 
|  | main( | 
|  | registry_xml.script_relative(outputs[0]), | 
|  | registry_xml.script_relative(outputs[1]))) |