1# Copyright 2018 The ANGLE Project Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4# 5# gen_packed_gl_enums.py: 6# Code generation for the packed enums. 7# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 8 9import datetime, json, os, sys 10from collections import namedtuple 11from collections import OrderedDict 12 13Enum = namedtuple('Enum', ['name', 'values', 'max_value']) 14EnumValue = namedtuple('EnumValue', ['name', 'gl_name', 'value']) 15 16Generators = [ 17 { 18 'json': 'packed_gl_enums.json', 19 'output': 'PackedGLEnums', 20 'namespace': 'gl', 21 'enum_type': 'GLenum', 22 }, 23 { 24 'json': 'packed_egl_enums.json', 25 'output': 'PackedEGLEnums', 26 'namespace': 'egl', 27 'enum_type': 'EGLenum', 28 }, 29] 30 31 32def load_enums(path): 33 with open(path) as map_file: 34 enums_dict = json.loads(map_file.read(), object_pairs_hook=OrderedDict) 35 36 enums = [] 37 for (enum_name, value_list) in enums_dict.iteritems(): 38 39 values = [] 40 i = 0 41 42 for (value_name, value_gl_name) in value_list.iteritems(): 43 values.append(EnumValue(value_name, value_gl_name, i)) 44 i += 1 45 46 assert (i < 255) # This makes sure enums fit in the uint8_t 47 enums.append(Enum(enum_name, values, i)) 48 49 enums.sort(key=lambda enum: enum.name) 50 return enums 51 52 53def generate_include_guard(path): 54 return path.replace(".", "_").upper() 55 56 57def header_name_from_cpp_name(path): 58 return path.replace(".cpp", ".h") 59 60 61header_template = """// GENERATED FILE - DO NOT EDIT. 62// Generated by {script_name} using data from {data_source_name}. 63// 64// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 65// Use of this source code is governed by a BSD-style license that can be 66// found in the LICENSE file. 67// 68// {file_name}: 69// Declares ANGLE-specific enums classes for {api_enum_name}s and functions operating 70// on them. 71 72#ifndef COMMON_{include_guard}_ 73#define COMMON_{include_guard}_ 74 75#include <angle_gl.h> 76#include <EGL/egl.h> 77#include <EGL/eglext.h> 78 79#include <cstdint> 80#include <ostream> 81 82namespace {namespace} 83{{ 84 85template<typename Enum> 86Enum From{api_enum_name}({api_enum_name} from); 87{content} 88}} // namespace {namespace} 89 90#endif // COMMON_{include_guard}_ 91""" 92 93enum_declaration_template = """ 94enum class {enum_name} : uint8_t 95{{ 96{value_declarations} 97 98 InvalidEnum = {max_value}, 99 EnumCount = {max_value}, 100}}; 101 102template <> 103{enum_name} From{api_enum_name}<{enum_name}>({api_enum_name} from); 104{api_enum_name} To{api_enum_name}({enum_name} from); 105std::ostream &operator<<(std::ostream &os, {enum_name} value); 106""" 107 108 109def write_header(enums, path_prefix, file_name, data_source_name, namespace, api_enum_name): 110 content = [''] 111 112 for enum in enums: 113 value_declarations = [] 114 for value in enum.values: 115 value_declarations.append(' ' + value.name + ' = ' + str(value.value) + ',') 116 117 content.append( 118 enum_declaration_template.format( 119 enum_name=enum.name, 120 max_value=str(enum.max_value), 121 value_declarations='\n'.join(value_declarations), 122 api_enum_name=api_enum_name)) 123 124 header = header_template.format( 125 content=''.join(content), 126 copyright_year=datetime.date.today().year, 127 data_source_name=data_source_name, 128 script_name=sys.argv[0], 129 file_name=file_name, 130 include_guard=generate_include_guard(file_name), 131 namespace=namespace, 132 api_enum_name=api_enum_name) 133 134 with (open(path_prefix + file_name, 'wt')) as f: 135 f.write(header) 136 137 138cpp_template = """// GENERATED FILE - DO NOT EDIT. 139// Generated by {script_name} using data from {data_source_name}. 140// 141// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 142// Use of this source code is governed by a BSD-style license that can be 143// found in the LICENSE file. 144// 145// {file_name}: 146// Implements ANGLE-specific enums classes for {api_enum_name}s and functions operating 147// on them. 148 149#include "common/debug.h" 150#include "common/{header_name}" 151 152namespace {namespace} 153{{ 154{content} 155}} // namespace {namespace} 156""" 157 158enum_implementation_template = """ 159template <> 160{enum_name} From{api_enum_name}<{enum_name}>({api_enum_name} from) 161{{ 162 switch (from) 163 {{ 164{from_glenum_cases} 165 default: 166 return {enum_name}::InvalidEnum; 167 }} 168}} 169 170{api_enum_name} To{api_enum_name}({enum_name} from) 171{{ 172 switch (from) 173 {{ 174{to_glenum_cases} 175 default: 176 UNREACHABLE(); 177 return 0; 178 }} 179}} 180 181std::ostream &operator<<(std::ostream &os, {enum_name} value) 182{{ 183 switch (value) 184 {{ 185{ostream_cases} 186 default: 187 os << "GL_INVALID_ENUM"; 188 break; 189 }} 190 return os; 191}} 192""" 193 194 195def write_cpp(enums, path_prefix, file_name, data_source_name, namespace, api_enum_name): 196 content = [''] 197 198 for enum in enums: 199 from_glenum_cases = [] 200 to_glenum_cases = [] 201 ostream_cases = [] 202 for value in enum.values: 203 qualified_name = enum.name + '::' + value.name 204 from_glenum_cases.append(' case ' + value.gl_name + ':\n return ' + 205 qualified_name + ';') 206 to_glenum_cases.append(' case ' + qualified_name + ':\n return ' + 207 value.gl_name + ';') 208 ostream_cases.append(' case ' + qualified_name + ':\n os << "' + 209 value.gl_name + '";\n break;') 210 211 content.append( 212 enum_implementation_template.format( 213 enum_name=enum.name, 214 from_glenum_cases='\n'.join(from_glenum_cases), 215 max_value=str(enum.max_value), 216 to_glenum_cases='\n'.join(to_glenum_cases), 217 api_enum_name=api_enum_name, 218 ostream_cases='\n'.join(ostream_cases))) 219 220 cpp = cpp_template.format( 221 content=''.join(content), 222 copyright_year=datetime.date.today().year, 223 data_source_name=data_source_name, 224 script_name=sys.argv[0], 225 file_name=file_name, 226 header_name=header_name_from_cpp_name(file_name), 227 namespace=namespace, 228 api_enum_name=api_enum_name) 229 230 with (open(path_prefix + file_name, 'wt')) as f: 231 f.write(cpp) 232 233 234def main(): 235 236 # auto_script parameters. 237 if len(sys.argv) > 1: 238 inputs = [] 239 outputs = [] 240 for generator in Generators: 241 inputs += [generator['json']] 242 outputs += [ 243 generator['output'] + '_autogen.cpp', 244 generator['output'] + '_autogen.h', 245 ] 246 247 if sys.argv[1] == 'inputs': 248 print ','.join(inputs) 249 elif sys.argv[1] == 'outputs': 250 print ','.join(outputs) 251 else: 252 print('Invalid script parameters') 253 return 1 254 return 0 255 256 path_prefix = os.path.dirname(os.path.realpath(__file__)) + os.path.sep 257 258 for generator in Generators: 259 json_file = generator['json'] 260 output_file = generator['output'] 261 namespace = generator['namespace'] 262 enum_type = generator['enum_type'] 263 enums = load_enums(path_prefix + json_file) 264 write_header(enums, path_prefix, output_file + '_autogen.h', json_file, namespace, 265 enum_type) 266 write_cpp(enums, path_prefix, output_file + '_autogen.cpp', json_file, namespace, 267 enum_type) 268 return 0 269 270 271if __name__ == '__main__': 272 sys.exit(main()) 273