1#!/usr/bin/python3 2# Copyright 2015 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_load_functions_table.py: 7# Code generation for the load function tables used for texture formats. These mappings are 8# not renderer specific. The mappings are done from the GL internal format, to the ANGLE 9# format ID, and then for the specific data type. 10# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 11# 12 13import json, sys 14 15sys.path.append('../..') 16import angle_format 17 18template = """// GENERATED FILE - DO NOT EDIT. 19// Generated by gen_load_functions_table.py using data from load_functions_data.json 20// 21// Copyright 2020 The ANGLE Project Authors. All rights reserved. 22// Use of this source code is governed by a BSD-style license that can be 23// found in the LICENSE file. 24// 25// load_functions_table: 26// Contains the GetLoadFunctionsMap for texture_format_util.h 27// 28 29#include "libANGLE/renderer/load_functions_table.h" 30 31#include "image_util/copyimage.h" 32#include "image_util/generatemip.h" 33#include "image_util/loadimage.h" 34 35using namespace rx; 36 37namespace angle 38{{ 39 40namespace 41{{ 42 43// ES3 image loading functions vary based on: 44// - the GL internal format (supplied to glTex*Image*D) 45// - the GL data type given (supplied to glTex*Image*D) 46// - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D 47// device's capabilities) 48// This map type determines which loading function to use, based on these three parameters. 49// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec. 50void UnimplementedLoadFunction(const ImageLoadContext &context, 51 size_t width, 52 size_t height, 53 size_t depth, 54 const uint8_t *input, 55 size_t inputRowPitch, 56 size_t inputDepthPitch, 57 uint8_t *output, 58 size_t outputRowPitch, 59 size_t outputDepthPitch) 60{{ 61 UNIMPLEMENTED(); 62}} 63 64void UnreachableLoadFunction(const ImageLoadContext &context, 65 size_t width, 66 size_t height, 67 size_t depth, 68 const uint8_t *input, 69 size_t inputRowPitch, 70 size_t inputDepthPitch, 71 uint8_t *output, 72 size_t outputRowPitch, 73 size_t outputDepthPitch) 74{{ 75 UNREACHABLE(); 76}} 77 78{load_functions_data}}} // namespace 79 80LoadFunctionMap GetLoadFunctionsMap(GLenum {internal_format}, FormatID {angle_format}) 81{{ 82 // clang-format off 83 switch ({internal_format}) 84 {{ 85{switch_data} 86 default: 87 break; 88 }} 89 // clang-format on 90 ASSERT(internalFormat == GL_NONE || angleFormat == angle::FormatID::NONE); 91 static LoadFunctionMap emptyLoadFunctionsMap; 92 return emptyLoadFunctionsMap; 93 94}} // GetLoadFunctionsMap 95 96}} // namespace angle 97""" 98 99internal_format_param = 'internalFormat' 100angle_format_param = 'angleFormat' 101angle_format_unknown = 'NONE' 102 103 104def load_functions_name(internal_format, angle_format): 105 return internal_format[3:] + "_to_" + angle_format 106 107 108def unknown_func_name(internal_format): 109 return load_functions_name(internal_format, "default") 110 111 112def get_load_func(func_name, type_functions): 113 snippet = "LoadImageFunctionInfo " + func_name + "(GLenum type)\n" 114 snippet += "{\n" 115 snippet += " switch (type)\n" 116 snippet += " {\n" 117 for gl_type, load_function in sorted(type_functions.items()): 118 snippet += " case " + gl_type + ":\n" 119 requiresConversion = str('LoadToNative<' not in load_function).lower() 120 snippet += " return LoadImageFunctionInfo(" + load_function + ", " + requiresConversion + ");\n" 121 snippet += " default:\n" 122 snippet += " UNREACHABLE();\n" 123 snippet += " return LoadImageFunctionInfo(UnreachableLoadFunction, true);\n" 124 snippet += " }\n" 125 snippet += "}\n" 126 snippet += "\n" 127 128 return snippet 129 130 131def get_unknown_load_func(angle_to_type_map, internal_format): 132 assert angle_format_unknown in angle_to_type_map 133 return get_load_func( 134 unknown_func_name(internal_format), angle_to_type_map[angle_format_unknown]) 135 136 137def parse_json(json_data): 138 table_data = '' 139 load_functions_data = '' 140 for internal_format, angle_to_type_map in sorted(json_data.items()): 141 142 s = ' ' 143 144 table_data += s + 'case ' + internal_format + ':\n' 145 146 do_switch = len(angle_to_type_map) > 1 or list( 147 angle_to_type_map)[0] != angle_format_unknown 148 149 if do_switch: 150 table_data += s + '{\n' 151 s += ' ' 152 table_data += s + 'switch (' + angle_format_param + ')\n' 153 table_data += s + '{\n' 154 s += ' ' 155 156 for angle_format, type_functions in sorted(angle_to_type_map.items()): 157 158 if angle_format == angle_format_unknown: 159 continue 160 161 func_name = load_functions_name(internal_format, angle_format) 162 163 # Main case statements 164 table_data += s + 'case FormatID::' + angle_format + ':\n' 165 table_data += s + ' return ' + func_name + ';\n' 166 167 if angle_format_unknown in angle_to_type_map: 168 for gl_type, load_function in sorted( 169 angle_to_type_map[angle_format_unknown].items()): 170 if gl_type not in type_functions: 171 type_functions[gl_type] = load_function 172 173 load_functions_data += get_load_func(func_name, type_functions) 174 175 if do_switch: 176 table_data += s + 'default:\n' 177 178 has_break_in_switch = False 179 if angle_format_unknown in angle_to_type_map: 180 table_data += s + ' return ' + unknown_func_name(internal_format) + ';\n' 181 load_functions_data += get_unknown_load_func(angle_to_type_map, internal_format) 182 else: 183 has_break_in_switch = True 184 table_data += s + ' break;\n' 185 186 if do_switch: 187 s = s[4:] 188 table_data += s + '}\n' 189 if has_break_in_switch: 190 # If the inner switch contains a break statement, add a break 191 # statement after the switch as well. 192 table_data += s + 'break;\n' 193 s = s[4:] 194 table_data += s + '}\n' 195 196 return table_data, load_functions_data 197 198 199def main(): 200 201 # auto_script parameters. 202 if len(sys.argv) > 1: 203 inputs = ['angle_format.py', 'load_functions_data.json'] 204 outputs = ['load_functions_table_autogen.cpp'] 205 206 if sys.argv[1] == 'inputs': 207 print(','.join(inputs)) 208 elif sys.argv[1] == 'outputs': 209 print(','.join(outputs)) 210 else: 211 print('Invalid script parameters') 212 return 1 213 return 0 214 215 json_data = angle_format.load_json('load_functions_data.json') 216 217 switch_data, load_functions_data = parse_json(json_data) 218 output = template.format( 219 internal_format=internal_format_param, 220 angle_format=angle_format_param, 221 switch_data=switch_data, 222 load_functions_data=load_functions_data) 223 224 with open('load_functions_table_autogen.cpp', 'wt') as out_file: 225 out_file.write(output) 226 out_file.close() 227 return 0 228 229 230if __name__ == '__main__': 231 sys.exit(main()) 232