#!/usr/bin/python # Copyright 2016 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_angle_format_table.py: # Code generation for ANGLE format map. # import angle_format from datetime import date import json import math import pprint import re import sys template_autogen_h = """// GENERATED FILE - DO NOT EDIT. // Generated by gen_angle_format_table.py using data from angle_format_data.json // // Copyright {copyright_year} 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. // // ANGLE format enumeration. namespace angle {{ enum class Format::ID {{ {angle_format_enum} }}; }} // namespace angle """ template_autogen_cpp = """// GENERATED FILE - DO NOT EDIT. // Generated by gen_angle_format_table.py using data from angle_format_data.json // // Copyright {copyright_year} 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. // // ANGLE Format table: // Queries for typed format information from the ANGLE format enum. #include "libANGLE/renderer/Format.h" #include "image_util/copyimage.h" #include "image_util/generatemip.h" #include "image_util/loadimage.h" namespace angle {{ // static const Format &Format::Get(ID id) {{ // clang-format off switch (id) {{ {angle_format_info_cases} default: UNREACHABLE(); break; }} // clang-format on static const Format noneInfo(ID::NONE, GL_NONE, GL_NONE, nullptr, nullptr); return noneInfo; }} }} // namespace angle """ def get_channel_struct(angle_format): if 'bits' not in angle_format or angle_format['bits'] is None: return None if 'BLOCK' in angle_format['id']: return None bits = angle_format['bits'] if 'D' in bits or 'S' in bits: return None if 'channelStruct' in angle_format: return angle_format['channelStruct'] struct_name = '' for channel in angle_format['channels']: if channel == 'r': struct_name += 'R{}'.format(bits['R']) if channel == 'g': struct_name += 'G{}'.format(bits['G']) if channel == 'b': struct_name += 'B{}'.format(bits['B']) if channel == 'a': struct_name += 'A{}'.format(bits['A']) if channel == 'l': struct_name += 'L{}'.format(bits['L']) if angle_format['componentType'] == 'float': struct_name += 'F' if angle_format['componentType'] == 'int' or angle_format['componentType'] == 'snorm': struct_name += 'S' return struct_name def get_mip_generation_function(angle_format): channel_struct = get_channel_struct(angle_format) if channel_struct == None or "BLOCK" in angle_format["id"]: return 'nullptr' return 'GenerateMip<' + channel_struct + '>' def get_color_read_function(angle_format): channel_struct = get_channel_struct(angle_format) if channel_struct == None: return 'nullptr' component_type_map = { 'uint': 'GLuint', 'int': 'GLint', 'unorm': 'GLfloat', 'snorm': 'GLfloat', 'float': 'GLfloat' } return 'ReadColor<' + channel_struct + ', '+ component_type_map[angle_format['componentType']] + '>' format_entry_template = """{space}{{ {space} static const Format info(ID::{id}, {space} {glInternalFormat}, {space} {fboImplementationInternalFormat}, {space} {mipGenerationFunction}, {space} {colorReadFunction}); {space} return info; {space}}} """ def get_component_type(format_id): if "SNORM" in format_id: return "snorm" elif "UNORM" in format_id: return "unorm" elif "FLOAT" in format_id: return "float" elif "UINT" in format_id: return "uint" elif "SINT" in format_id: return "int" elif format_id == "NONE": return "none" elif "SRGB" in format_id: return "unorm" else: raise ValueError("Unknown component type for " + format_id) def get_channel_tokens(format_id): r = re.compile(r'([ABDGLRS][\d]+)') return filter(r.match, r.split(format_id)) def get_channels(format_id): channels = '' tokens = get_channel_tokens(format_id) if len(tokens) == 0: return None for token in tokens: channels += token[0].lower() return channels def get_bits(format_id): bits = {} tokens = get_channel_tokens(format_id) if len(tokens) == 0: return None for token in tokens: bits[token[0]] = int(token[1:]) return bits def json_to_table_data(format_id, json, angle_to_gl): table_data = "" parsed = { "space": " ", "id": format_id, } for k, v in json.iteritems(): parsed[k] = v if "glInternalFormat" not in parsed: parsed["glInternalFormat"] = angle_to_gl[format_id] if "fboImplementationInternalFormat" not in parsed: parsed["fboImplementationInternalFormat"] = parsed["glInternalFormat"] if "componentType" not in parsed: parsed["componentType"] = get_component_type(format_id) if "channels" not in parsed: parsed["channels"] = get_channels(format_id) if "bits" not in parsed: parsed["bits"] = get_bits(format_id) # Derived values. parsed["mipGenerationFunction"] = get_mip_generation_function(parsed) parsed["colorReadFunction"] = get_color_read_function(parsed) return format_entry_template.format(**parsed) def parse_json_into_angle_format_switch_string(all_angle, json_data, angle_to_gl): table_data = '' for format_id in sorted(all_angle): format_info = json_data[format_id] if format_id in json_data else {} table_data += ' case ID::' + format_id + ':\n' table_data += json_to_table_data(format_id, format_info, angle_to_gl) return table_data def gen_enum_string(all_angle): enum_data = ' NONE' for format_id in sorted(all_angle): if format_id == 'NONE': continue enum_data += ',\n ' + format_id return enum_data gl_to_angle = angle_format.load_forward_table('angle_format_map.json') angle_to_gl = angle_format.load_inverse_table('angle_format_map.json') json_data = angle_format.load_json('angle_format_data.json') all_angle = angle_to_gl.keys() angle_format_cases = parse_json_into_angle_format_switch_string( all_angle, json_data, angle_to_gl) output_cpp = template_autogen_cpp.format( copyright_year=date.today().year, angle_format_info_cases=angle_format_cases) with open('Format_autogen.cpp', 'wt') as out_file: out_file.write(output_cpp) out_file.close() enum_data = gen_enum_string(all_angle) output_h = template_autogen_h.format( copyright_year=date.today().year, angle_format_enum=enum_data) with open('Format_ID_autogen.inl', 'wt') as out_file: out_file.write(output_h) out_file.close()