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 and 120 'LoadCompressedToNative<' not in load_function).lower() 121 snippet += " return LoadImageFunctionInfo(" + load_function + ", " + requiresConversion + ");\n" 122 snippet += " default:\n" 123 snippet += " UNREACHABLE();\n" 124 snippet += " return LoadImageFunctionInfo(UnreachableLoadFunction, true);\n" 125 snippet += " }\n" 126 snippet += "}\n" 127 snippet += "\n" 128 129 return snippet 130 131 132def get_unknown_load_func(angle_to_type_map, internal_format): 133 assert angle_format_unknown in angle_to_type_map 134 return get_load_func( 135 unknown_func_name(internal_format), angle_to_type_map[angle_format_unknown]) 136 137 138def parse_json(json_data): 139 table_data = '' 140 load_functions_data = '' 141 for internal_format, angle_to_type_map in sorted(json_data.items()): 142 143 s = ' ' 144 145 table_data += s + 'case ' + internal_format + ':\n' 146 147 do_switch = len(angle_to_type_map) > 1 or list( 148 angle_to_type_map)[0] != angle_format_unknown 149 150 if do_switch: 151 table_data += s + '{\n' 152 s += ' ' 153 table_data += s + 'switch (' + angle_format_param + ')\n' 154 table_data += s + '{\n' 155 s += ' ' 156 157 for angle_format, type_functions in sorted(angle_to_type_map.items()): 158 159 if angle_format == angle_format_unknown: 160 continue 161 162 func_name = load_functions_name(internal_format, angle_format) 163 164 # Main case statements 165 table_data += s + 'case FormatID::' + angle_format + ':\n' 166 table_data += s + ' return ' + func_name + ';\n' 167 168 if angle_format_unknown in angle_to_type_map: 169 for gl_type, load_function in sorted( 170 angle_to_type_map[angle_format_unknown].items()): 171 if gl_type not in type_functions: 172 type_functions[gl_type] = load_function 173 174 load_functions_data += get_load_func(func_name, type_functions) 175 176 if do_switch: 177 table_data += s + 'default:\n' 178 179 has_break_in_switch = False 180 if angle_format_unknown in angle_to_type_map: 181 table_data += s + ' return ' + unknown_func_name(internal_format) + ';\n' 182 load_functions_data += get_unknown_load_func(angle_to_type_map, internal_format) 183 else: 184 has_break_in_switch = True 185 table_data += s + ' break;\n' 186 187 if do_switch: 188 s = s[4:] 189 table_data += s + '}\n' 190 if has_break_in_switch: 191 # If the inner switch contains a break statement, add a break 192 # statement after the switch as well. 193 table_data += s + 'break;\n' 194 s = s[4:] 195 table_data += s + '}\n' 196 197 return table_data, load_functions_data 198 199 200def main(): 201 202 # auto_script parameters. 203 if len(sys.argv) > 1: 204 inputs = ['angle_format.py', 'load_functions_data.json'] 205 outputs = ['load_functions_table_autogen.cpp'] 206 207 if sys.argv[1] == 'inputs': 208 print(','.join(inputs)) 209 elif sys.argv[1] == 'outputs': 210 print(','.join(outputs)) 211 else: 212 print('Invalid script parameters') 213 return 1 214 return 0 215 216 json_data = angle_format.load_json('load_functions_data.json') 217 218 switch_data, load_functions_data = parse_json(json_data) 219 output = template.format( 220 internal_format=internal_format_param, 221 angle_format=angle_format_param, 222 switch_data=switch_data, 223 load_functions_data=load_functions_data) 224 225 with open('load_functions_table_autogen.cpp', 'wt') as out_file: 226 out_file.write(output) 227 out_file.close() 228 return 0 229 230 231if __name__ == '__main__': 232 sys.exit(main()) 233