1#!/usr/bin/python 2# Copyright 2016 The ANGLE Project Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5# 6# gen_angle_format_table.py: 7# Code generation for ANGLE format map. 8# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 9# 10 11import angle_format 12from datetime import date 13import json 14import math 15import pprint 16import re 17import sys 18 19template_autogen_h = """// GENERATED FILE - DO NOT EDIT. 20// Generated by {script_name} using data from {data_source_name} 21// 22// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 23// Use of this source code is governed by a BSD-style license that can be 24// found in the LICENSE file. 25// 26// ANGLE format enumeration. 27 28#ifndef LIBANGLE_RENDERER_FORMATID_H_ 29#define LIBANGLE_RENDERER_FORMATID_H_ 30 31#include <cstdint> 32 33namespace angle 34{{ 35 36enum class FormatID 37{{ 38{angle_format_enum} 39}}; 40 41constexpr uint32_t kNumANGLEFormats = {num_angle_formats}; 42 43}} // namespace angle 44 45#endif // LIBANGLE_RENDERER_FORMATID_H_ 46""" 47 48template_autogen_inl = """// GENERATED FILE - DO NOT EDIT. 49// Generated by {script_name} using data from {data_source_name} 50// 51// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved. 52// Use of this source code is governed by a BSD-style license that can be 53// found in the LICENSE file. 54// 55// ANGLE Format table: 56// Queries for typed format information from the ANGLE format enum. 57 58#include "libANGLE/renderer/Format.h" 59 60#include "image_util/copyimage.h" 61#include "image_util/generatemip.h" 62#include "image_util/loadimage.h" 63 64namespace angle 65{{ 66 67static constexpr rx::FastCopyFunctionMap::Entry BGRAEntry = {{angle::FormatID::R8G8B8A8_UNORM, 68 CopyBGRA8ToRGBA8}}; 69static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {{&BGRAEntry, 1}}; 70static constexpr rx::FastCopyFunctionMap NoCopyFunctions; 71 72const Format gFormatInfoTable[] = {{ 73 // clang-format off 74 {{ FormatID::NONE, GL_NONE, GL_NONE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false, gl::VertexAttribType::InvalidEnum }}, 75{angle_format_info_cases} // clang-format on 76}}; 77 78// static 79FormatID Format::InternalFormatToID(GLenum internalFormat) 80{{ 81 switch (internalFormat) 82 {{ 83{angle_format_switch} 84 }} 85}} 86 87const Format *GetFormatInfoTable() 88{{ 89 return gFormatInfoTable; 90}} 91}} // namespace angle 92""" 93 94 95def ceil_int(value, mod): 96 assert mod > 0 and value > 0, 'integer modulation should be larger than 0' 97 return (value + mod - 1) / mod 98 99 100def is_depth_stencil(angle_format): 101 if not 'channels' in angle_format or not angle_format['channels']: 102 return False 103 return 'd' in angle_format['channels'] or 's' in angle_format['channels'] 104 105 106def get_component_suffix(angle_format): 107 if angle_format['componentType'] == 'float': 108 return 'F' 109 if angle_format['componentType'] == 'int' or angle_format['componentType'] == 'snorm': 110 return 'S' 111 return "" 112 113 114def get_channel_struct(angle_format): 115 if 'bits' not in angle_format or angle_format['bits'] is None: 116 return None 117 if 'BLOCK' in angle_format['id']: 118 return None 119 if 'VERTEX' in angle_format['id']: 120 return None 121 122 bits = angle_format['bits'] 123 124 if 'channelStruct' in angle_format: 125 return angle_format['channelStruct'] 126 127 struct_name = '' 128 component_suffix = get_component_suffix(angle_format) 129 130 for channel in angle_format['channels']: 131 if channel == 'r': 132 struct_name += 'R{}'.format(bits['R']) 133 if channel == 'g': 134 struct_name += 'G{}'.format(bits['G']) 135 if channel == 'b': 136 struct_name += 'B{}'.format(bits['B']) 137 if channel == 'a': 138 struct_name += 'A{}'.format(bits['A']) 139 if channel == 'l': 140 struct_name += 'L{}'.format(bits['L']) 141 if channel == 'd': 142 struct_name += 'D{}'.format(bits['D']) + component_suffix 143 if channel == 's': 144 struct_name += 'S{}'.format(bits['S']) 145 if channel == 'x': 146 struct_name += 'X{}'.format(bits['X']) 147 148 if not is_depth_stencil(angle_format): 149 struct_name += component_suffix 150 151 return struct_name 152 153 154def get_mip_generation_function(angle_format): 155 channel_struct = get_channel_struct(angle_format) 156 if is_depth_stencil(angle_format) or channel_struct == None \ 157 or "BLOCK" in angle_format["id"] or "VERTEX" in angle_format["id"]: 158 return 'nullptr' 159 return 'GenerateMip<' + channel_struct + '>' 160 161 162def get_color_read_write_component_type(angle_format): 163 component_type_map = { 164 'uint': 'GLuint', 165 'int': 'GLint', 166 'unorm': 'GLfloat', 167 'snorm': 'GLfloat', 168 'float': 'GLfloat' 169 } 170 return component_type_map[angle_format['componentType']] 171 172 173def get_color_read_function(angle_format): 174 channel_struct = get_channel_struct(angle_format) 175 if channel_struct == None: 176 return 'nullptr' 177 178 if is_depth_stencil(angle_format): 179 return 'ReadDepthStencil<' + channel_struct + '>' 180 181 read_component_type = get_color_read_write_component_type(angle_format) 182 return 'ReadColor<' + channel_struct + ', ' + read_component_type + '>' 183 184 185def get_color_write_function(angle_format): 186 channel_struct = get_channel_struct(angle_format) 187 if channel_struct == None: 188 return 'nullptr' 189 190 if is_depth_stencil(angle_format): 191 return 'WriteDepthStencil<' + channel_struct + '>' 192 193 write_component_type = get_color_read_write_component_type(angle_format) 194 return 'WriteColor<' + channel_struct + ', ' + write_component_type + '>' 195 196 197format_entry_template = """ {{ FormatID::{id}, {glInternalFormat}, {fboImplementationInternalFormat}, {mipGenerationFunction}, {fastCopyFunctions}, {colorReadFunction}, {colorWriteFunction}, {namedComponentType}, {R}, {G}, {B}, {A}, {L}, {D}, {S}, {pixelBytes}, {componentAlignmentMask}, {isBlock}, {isFixed}, {isScaled}, {vertexAttribType} }}, 198""" 199 200 201def get_named_component_type(component_type): 202 if component_type == "snorm": 203 return "GL_SIGNED_NORMALIZED" 204 elif component_type == "unorm": 205 return "GL_UNSIGNED_NORMALIZED" 206 elif component_type == "float": 207 return "GL_FLOAT" 208 elif component_type == "uint": 209 return "GL_UNSIGNED_INT" 210 elif component_type == "int": 211 return "GL_INT" 212 elif component_type == "none": 213 return "GL_NONE" 214 else: 215 raise ValueError("Unknown component type for " + component_type) 216 217 218def get_component_alignment_mask(channels, bits): 219 if channels == None or bits == None: 220 return "std::numeric_limits<GLuint>::max()" 221 bitness = bits[channels[0].upper()] 222 for channel in channels: 223 if channel not in "rgba": 224 return "std::numeric_limits<GLuint>::max()" 225 # Can happen for RGB10A2 formats. 226 if bits[channel.upper()] != bitness: 227 return "std::numeric_limits<GLuint>::max()" 228 component_bytes = (int(bitness) >> 3) 229 230 if component_bytes == 1: 231 return "0" 232 elif component_bytes == 2: 233 return "1" 234 elif component_bytes == 4: 235 return "3" 236 else: 237 # Can happen for 4-bit RGBA. 238 return "std::numeric_limits<GLuint>::max()" 239 240 241def get_vertex_attrib_type(format_id): 242 243 has_u = "_U" in format_id 244 has_s = "_S" in format_id 245 has_float = "_FLOAT" in format_id 246 has_fixed = "_FIXED" in format_id 247 has_r8 = "R8" in format_id 248 has_r16 = "R16" in format_id 249 has_r32 = "R32" in format_id 250 has_r10 = "R10" in format_id 251 has_vertex = "VERTEX" in format_id 252 253 if has_fixed: 254 return "Fixed" 255 256 if has_float: 257 return "HalfFloat" if has_r16 else "Float" 258 259 if has_r8: 260 return "Byte" if has_s else "UnsignedByte" 261 262 if has_r10: 263 if has_vertex: 264 return "Int1010102" if has_s else "UnsignedInt1010102" 265 else: 266 return "Int2101010" if has_s else "UnsignedInt2101010" 267 268 if has_r16: 269 return "Short" if has_s else "UnsignedShort" 270 271 if has_r32: 272 return "Int" if has_s else "UnsignedInt" 273 274 # Many ANGLE formats don't correspond with vertex formats. 275 return "InvalidEnum" 276 277 278def json_to_table_data(format_id, json, angle_to_gl): 279 280 table_data = "" 281 282 parsed = { 283 "id": format_id, 284 "fastCopyFunctions": "NoCopyFunctions", 285 } 286 287 for k, v in json.iteritems(): 288 parsed[k] = v 289 290 if "glInternalFormat" not in parsed: 291 parsed["glInternalFormat"] = angle_to_gl[format_id] 292 293 if "fboImplementationInternalFormat" not in parsed: 294 parsed["fboImplementationInternalFormat"] = parsed["glInternalFormat"] 295 296 if "componentType" not in parsed: 297 parsed["componentType"] = angle_format.get_component_type(format_id) 298 299 if "channels" not in parsed: 300 parsed["channels"] = angle_format.get_channels(format_id) 301 302 if "bits" not in parsed: 303 parsed["bits"] = angle_format.get_bits(format_id) 304 305 # Derived values. 306 parsed["mipGenerationFunction"] = get_mip_generation_function(parsed) 307 parsed["colorReadFunction"] = get_color_read_function(parsed) 308 parsed["colorWriteFunction"] = get_color_write_function(parsed) 309 310 for channel in angle_format.kChannels: 311 if parsed["bits"] != None and channel in parsed["bits"]: 312 parsed[channel] = parsed["bits"][channel] 313 else: 314 parsed[channel] = "0" 315 316 parsed["namedComponentType"] = get_named_component_type(parsed["componentType"]) 317 318 if format_id == "B8G8R8A8_UNORM": 319 parsed["fastCopyFunctions"] = "BGRACopyFunctions" 320 321 is_block = format_id.endswith("_BLOCK") 322 323 pixel_bytes = 0 324 if is_block: 325 assert 'blockPixelBytes' in parsed, \ 326 'Compressed format %s requires its block size to be specified in angle_format_data.json' % \ 327 format_id 328 pixel_bytes = parsed['blockPixelBytes'] 329 else: 330 sum_of_bits = 0 331 for channel in angle_format.kChannels: 332 sum_of_bits += int(parsed[channel]) 333 pixel_bytes = ceil_int(sum_of_bits, 8) 334 parsed["pixelBytes"] = pixel_bytes 335 parsed["componentAlignmentMask"] = get_component_alignment_mask(parsed["channels"], 336 parsed["bits"]) 337 parsed["isBlock"] = "true" if is_block else "false" 338 parsed["isFixed"] = "true" if "FIXED" in format_id else "false" 339 parsed["isScaled"] = "true" if "SCALED" in format_id else "false" 340 341 parsed["vertexAttribType"] = "gl::VertexAttribType::" + get_vertex_attrib_type(format_id) 342 343 return format_entry_template.format(**parsed) 344 345 346def parse_angle_format_table(all_angle, json_data, angle_to_gl): 347 table_data = '' 348 for format_id in sorted(all_angle): 349 if format_id != "NONE": 350 format_info = json_data[format_id] if format_id in json_data else {} 351 table_data += json_to_table_data(format_id, format_info, angle_to_gl) 352 353 return table_data 354 355 356def gen_enum_string(all_angle): 357 enum_data = ' NONE' 358 for format_id in sorted(all_angle): 359 if format_id == 'NONE': 360 continue 361 enum_data += ',\n ' + format_id 362 return enum_data 363 364 365case_template = """ case {gl_format}: 366 return FormatID::{angle_format}; 367""" 368 369 370def gen_map_switch_string(gl_to_angle): 371 switch_data = '' 372 for gl_format in sorted(gl_to_angle.keys()): 373 angle_format = gl_to_angle[gl_format] 374 switch_data += case_template.format(gl_format=gl_format, angle_format=angle_format) 375 switch_data += " default:\n" 376 switch_data += " return FormatID::NONE;" 377 return switch_data 378 379 380def main(): 381 382 # auto_script parameters. 383 if len(sys.argv) > 1: 384 inputs = ['angle_format.py', 'angle_format_data.json', 'angle_format_map.json'] 385 outputs = ['Format_table_autogen.cpp', 'FormatID_autogen.h'] 386 387 if sys.argv[1] == 'inputs': 388 print ','.join(inputs) 389 elif sys.argv[1] == 'outputs': 390 print ','.join(outputs) 391 else: 392 print('Invalid script parameters') 393 return 1 394 return 0 395 396 gl_to_angle = angle_format.load_forward_table('angle_format_map.json') 397 angle_to_gl = angle_format.load_inverse_table('angle_format_map.json') 398 data_source_name = 'angle_format_data.json' 399 json_data = angle_format.load_json(data_source_name) 400 all_angle = angle_to_gl.keys() 401 402 angle_format_cases = parse_angle_format_table(all_angle, json_data, angle_to_gl) 403 switch_data = gen_map_switch_string(gl_to_angle) 404 output_cpp = template_autogen_inl.format( 405 script_name=sys.argv[0], 406 copyright_year=date.today().year, 407 angle_format_info_cases=angle_format_cases, 408 angle_format_switch=switch_data, 409 data_source_name=data_source_name) 410 with open('Format_table_autogen.cpp', 'wt') as out_file: 411 out_file.write(output_cpp) 412 out_file.close() 413 414 enum_data = gen_enum_string(all_angle) 415 num_angle_formats = len(all_angle) 416 output_h = template_autogen_h.format( 417 script_name=sys.argv[0], 418 copyright_year=date.today().year, 419 angle_format_enum=enum_data, 420 data_source_name=data_source_name, 421 num_angle_formats=num_angle_formats) 422 with open('FormatID_autogen.h', 'wt') as out_file: 423 out_file.write(output_h) 424 out_file.close() 425 426 return 0 427 428 429if __name__ == '__main__': 430 sys.exit(main()) 431