1#!/usr/bin/python
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
8#
9
10import json, sys
11from datetime import date
12
13sys.path.append('../..')
14import angle_format
15
16template = """// GENERATED FILE - DO NOT EDIT.
17// Generated by gen_load_functions_table.py using data from load_functions_data.json
18//
19// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved.
20// Use of this source code is governed by a BSD-style license that can be
21// found in the LICENSE file.
22//
23// load_functions_table:
24//   Contains the GetLoadFunctionsMap for texture_format_util.h
25//
26
27#include "libANGLE/renderer/load_functions_table.h"
28
29#include "image_util/copyimage.h"
30#include "image_util/generatemip.h"
31#include "image_util/loadimage.h"
32
33using namespace rx;
34
35namespace angle
36{{
37
38namespace
39{{
40
41// ES3 image loading functions vary based on:
42//    - the GL internal format (supplied to glTex*Image*D)
43//    - the GL data type given (supplied to glTex*Image*D)
44//    - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
45//    device's capabilities)
46// This map type determines which loading function to use, based on these three parameters.
47// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
48void UnimplementedLoadFunction(size_t width,
49                               size_t height,
50                               size_t depth,
51                               const uint8_t *input,
52                               size_t inputRowPitch,
53                               size_t inputDepthPitch,
54                               uint8_t *output,
55                               size_t outputRowPitch,
56                               size_t outputDepthPitch)
57{{
58    UNIMPLEMENTED();
59}}
60
61void UnreachableLoadFunction(size_t width,
62                             size_t height,
63                             size_t depth,
64                             const uint8_t *input,
65                             size_t inputRowPitch,
66                             size_t inputDepthPitch,
67                             uint8_t *output,
68                             size_t outputRowPitch,
69                             size_t outputDepthPitch)
70{{
71    UNREACHABLE();
72}}
73
74{load_functions_data}}}  // namespace
75
76LoadFunctionMap GetLoadFunctionsMap(GLenum {internal_format}, Format::ID {angle_format})
77{{
78    // clang-format off
79    switch ({internal_format})
80    {{
81{switch_data}
82        default:
83        {{
84            static LoadFunctionMap emptyLoadFunctionsMap;
85            return emptyLoadFunctionsMap;
86        }}
87    }}
88    // clang-format on
89
90}}  // GetLoadFunctionsMap
91
92}}  // namespace angle
93"""
94
95internal_format_param = 'internalFormat'
96angle_format_param = 'angleFormat'
97angle_format_unknown = 'NONE'
98
99def load_functions_name(internal_format, angle_format):
100    return internal_format[3:] + "_to_" + angle_format
101
102def unknown_func_name(internal_format):
103    return load_functions_name(internal_format, "default")
104
105def get_load_func(func_name, type_functions):
106    snippet = "LoadImageFunctionInfo " + func_name + "(GLenum type)\n"
107    snippet += "{\n"
108    snippet += "    switch (type)\n"
109    snippet += "    {\n"
110    for gl_type, load_function in sorted(type_functions.iteritems()):
111        snippet += "        case " + gl_type + ":\n"
112        requiresConversion = str('LoadToNative<' not in load_function).lower()
113        snippet += "            return LoadImageFunctionInfo(" + load_function + ", " + requiresConversion + ");\n"
114    snippet += "        default:\n"
115    snippet += "            UNREACHABLE();\n"
116    snippet += "            return LoadImageFunctionInfo(UnreachableLoadFunction, true);\n"
117    snippet += "    }\n"
118    snippet += "}\n"
119    snippet += "\n"
120
121    return snippet
122
123def get_unknown_load_func(angle_to_type_map, internal_format):
124    assert angle_format_unknown in angle_to_type_map
125    return get_load_func(unknown_func_name(internal_format), angle_to_type_map[angle_format_unknown])
126
127def parse_json(json_data):
128    table_data = ''
129    load_functions_data = ''
130    for internal_format, angle_to_type_map in sorted(json_data.iteritems()):
131
132        s = '        '
133
134        table_data += s + 'case ' + internal_format + ':\n'
135
136        do_switch = len(angle_to_type_map) > 1 or angle_to_type_map.keys()[0] != angle_format_unknown
137
138        if do_switch:
139            table_data += s + '{\n'
140            s += '    '
141            table_data += s + 'switch (' + angle_format_param + ')\n'
142            table_data += s + '{\n'
143            s += '    '
144
145        for angle_format, type_functions in sorted(angle_to_type_map.iteritems()):
146
147            if angle_format == angle_format_unknown:
148                continue
149
150            func_name = load_functions_name(internal_format, angle_format)
151
152            # Main case statements
153            table_data += s + 'case Format::ID::' + angle_format + ':\n'
154            table_data += s + '    return ' + func_name + ';\n'
155
156            if angle_format_unknown in angle_to_type_map:
157                for gl_type, load_function in angle_to_type_map[angle_format_unknown].iteritems():
158                    if gl_type not in type_functions:
159                        type_functions[gl_type] = load_function
160
161            load_functions_data += get_load_func(func_name, type_functions)
162
163        if do_switch:
164            table_data += s + 'default:\n'
165
166        if angle_format_unknown in angle_to_type_map:
167            table_data += s + '    return ' + unknown_func_name(internal_format) + ';\n'
168            load_functions_data += get_unknown_load_func(angle_to_type_map, internal_format)
169        else:
170            table_data += s + '    break;\n'
171
172        if do_switch:
173            s = s[4:]
174            table_data += s + '}\n'
175            s = s[4:]
176            table_data += s + '}\n'
177
178    return table_data, load_functions_data
179
180json_data = angle_format.load_json('load_functions_data.json')
181
182switch_data, load_functions_data = parse_json(json_data)
183output = template.format(internal_format = internal_format_param,
184                         angle_format = angle_format_param,
185                         switch_data = switch_data,
186                         load_functions_data = load_functions_data,
187                         copyright_year = date.today().year)
188
189with open('load_functions_table_autogen.cpp', 'wt') as out_file:
190    out_file.write(output)
191    out_file.close()
192