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(size_t width, 51 size_t height, 52 size_t depth, 53 const uint8_t *input, 54 size_t inputRowPitch, 55 size_t inputDepthPitch, 56 uint8_t *output, 57 size_t outputRowPitch, 58 size_t outputDepthPitch) 59{{ 60 UNIMPLEMENTED(); 61}} 62 63void UnreachableLoadFunction(size_t width, 64 size_t height, 65 size_t depth, 66 const uint8_t *input, 67 size_t inputRowPitch, 68 size_t inputDepthPitch, 69 uint8_t *output, 70 size_t outputRowPitch, 71 size_t outputDepthPitch) 72{{ 73 UNREACHABLE(); 74}} 75 76{load_functions_data}}} // namespace 77 78LoadFunctionMap GetLoadFunctionsMap(GLenum {internal_format}, FormatID {angle_format}) 79{{ 80 // clang-format off 81 switch ({internal_format}) 82 {{ 83{switch_data} 84 default: 85 break; 86 }} 87 // clang-format on 88 ASSERT(internalFormat == GL_NONE || angleFormat == angle::FormatID::NONE); 89 static LoadFunctionMap emptyLoadFunctionsMap; 90 return emptyLoadFunctionsMap; 91 92}} // GetLoadFunctionsMap 93 94}} // namespace angle 95""" 96 97internal_format_param = 'internalFormat' 98angle_format_param = 'angleFormat' 99angle_format_unknown = 'NONE' 100 101 102def load_functions_name(internal_format, angle_format): 103 return internal_format[3:] + "_to_" + angle_format 104 105 106def unknown_func_name(internal_format): 107 return load_functions_name(internal_format, "default") 108 109 110def get_load_func(func_name, type_functions): 111 snippet = "LoadImageFunctionInfo " + func_name + "(GLenum type)\n" 112 snippet += "{\n" 113 snippet += " switch (type)\n" 114 snippet += " {\n" 115 for gl_type, load_function in sorted(type_functions.items()): 116 snippet += " case " + gl_type + ":\n" 117 requiresConversion = str('LoadToNative<' not in load_function).lower() 118 snippet += " return LoadImageFunctionInfo(" + load_function + ", " + requiresConversion + ");\n" 119 snippet += " default:\n" 120 snippet += " UNREACHABLE();\n" 121 snippet += " return LoadImageFunctionInfo(UnreachableLoadFunction, true);\n" 122 snippet += " }\n" 123 snippet += "}\n" 124 snippet += "\n" 125 126 return snippet 127 128 129def get_unknown_load_func(angle_to_type_map, internal_format): 130 assert angle_format_unknown in angle_to_type_map 131 return get_load_func( 132 unknown_func_name(internal_format), angle_to_type_map[angle_format_unknown]) 133 134 135def parse_json(json_data): 136 table_data = '' 137 load_functions_data = '' 138 for internal_format, angle_to_type_map in sorted(json_data.items()): 139 140 s = ' ' 141 142 table_data += s + 'case ' + internal_format + ':\n' 143 144 do_switch = len(angle_to_type_map) > 1 or list( 145 angle_to_type_map)[0] != angle_format_unknown 146 147 if do_switch: 148 table_data += s + '{\n' 149 s += ' ' 150 table_data += s + 'switch (' + angle_format_param + ')\n' 151 table_data += s + '{\n' 152 s += ' ' 153 154 for angle_format, type_functions in sorted(angle_to_type_map.items()): 155 156 if angle_format == angle_format_unknown: 157 continue 158 159 func_name = load_functions_name(internal_format, angle_format) 160 161 # Main case statements 162 table_data += s + 'case FormatID::' + angle_format + ':\n' 163 table_data += s + ' return ' + func_name + ';\n' 164 165 if angle_format_unknown in angle_to_type_map: 166 for gl_type, load_function in sorted( 167 angle_to_type_map[angle_format_unknown].items()): 168 if gl_type not in type_functions: 169 type_functions[gl_type] = load_function 170 171 load_functions_data += get_load_func(func_name, type_functions) 172 173 if do_switch: 174 table_data += s + 'default:\n' 175 176 has_break_in_switch = False 177 if angle_format_unknown in angle_to_type_map: 178 table_data += s + ' return ' + unknown_func_name(internal_format) + ';\n' 179 load_functions_data += get_unknown_load_func(angle_to_type_map, internal_format) 180 else: 181 has_break_in_switch = True 182 table_data += s + ' break;\n' 183 184 if do_switch: 185 s = s[4:] 186 table_data += s + '}\n' 187 if has_break_in_switch: 188 # If the inner switch contains a break statement, add a break 189 # statement after the switch as well. 190 table_data += s + 'break;\n' 191 s = s[4:] 192 table_data += s + '}\n' 193 194 return table_data, load_functions_data 195 196 197def main(): 198 199 # auto_script parameters. 200 if len(sys.argv) > 1: 201 inputs = ['angle_format.py', 'load_functions_data.json'] 202 outputs = ['load_functions_table_autogen.cpp'] 203 204 if sys.argv[1] == 'inputs': 205 print(','.join(inputs)) 206 elif sys.argv[1] == 'outputs': 207 print(','.join(outputs)) 208 else: 209 print('Invalid script parameters') 210 return 1 211 return 0 212 213 json_data = angle_format.load_json('load_functions_data.json') 214 215 switch_data, load_functions_data = parse_json(json_data) 216 output = template.format( 217 internal_format=internal_format_param, 218 angle_format=angle_format_param, 219 switch_data=switch_data, 220 load_functions_data=load_functions_data) 221 222 with open('load_functions_table_autogen.cpp', 'wt') as out_file: 223 out_file.write(output) 224 out_file.close() 225 return 0 226 227 228if __name__ == '__main__': 229 sys.exit(main()) 230