1#!/usr/bin/python
2# Copyright 2017 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_uniform_type_table.py:
7#  Code generation for OpenGL uniform type info tables.
8#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
9
10from datetime import date
11
12import sys
13
14all_uniform_types = [
15    "GL_NONE", "GL_BOOL", "GL_BOOL_VEC2", "GL_BOOL_VEC3", "GL_BOOL_VEC4", "GL_FLOAT",
16    "GL_FLOAT_MAT2", "GL_FLOAT_MAT2x3", "GL_FLOAT_MAT2x4", "GL_FLOAT_MAT3", "GL_FLOAT_MAT3x2",
17    "GL_FLOAT_MAT3x4", "GL_FLOAT_MAT4", "GL_FLOAT_MAT4x2", "GL_FLOAT_MAT4x3", "GL_FLOAT_VEC2",
18    "GL_FLOAT_VEC3", "GL_FLOAT_VEC4", "GL_IMAGE_2D", "GL_IMAGE_2D_ARRAY", "GL_IMAGE_3D",
19    "GL_IMAGE_CUBE", "GL_INT", "GL_INT_IMAGE_2D", "GL_INT_IMAGE_2D_ARRAY", "GL_INT_IMAGE_3D",
20    "GL_INT_IMAGE_CUBE", "GL_INT_SAMPLER_2D", "GL_INT_SAMPLER_2D_ARRAY",
21    "GL_INT_SAMPLER_2D_MULTISAMPLE", "GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY", "GL_INT_SAMPLER_3D",
22    "GL_INT_SAMPLER_CUBE", "GL_INT_VEC2", "GL_INT_VEC3", "GL_INT_VEC4", "GL_SAMPLER_2D",
23    "GL_SAMPLER_2D_ARRAY", "GL_SAMPLER_2D_ARRAY_SHADOW", "GL_SAMPLER_2D_MULTISAMPLE",
24    "GL_SAMPLER_2D_MULTISAMPLE_ARRAY", "GL_SAMPLER_2D_RECT_ANGLE", "GL_SAMPLER_2D_SHADOW",
25    "GL_SAMPLER_3D", "GL_SAMPLER_CUBE", "GL_SAMPLER_CUBE_SHADOW", "GL_SAMPLER_EXTERNAL_OES",
26    "GL_UNSIGNED_INT", "GL_UNSIGNED_INT_ATOMIC_COUNTER", "GL_UNSIGNED_INT_IMAGE_2D",
27    "GL_UNSIGNED_INT_IMAGE_2D_ARRAY", "GL_UNSIGNED_INT_IMAGE_3D", "GL_UNSIGNED_INT_IMAGE_CUBE",
28    "GL_UNSIGNED_INT_SAMPLER_2D", "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY",
29    "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE", "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY",
30    "GL_UNSIGNED_INT_SAMPLER_3D", "GL_UNSIGNED_INT_SAMPLER_CUBE", "GL_UNSIGNED_INT_VEC2",
31    "GL_UNSIGNED_INT_VEC3", "GL_UNSIGNED_INT_VEC4", "GL_SAMPLER_VIDEO_IMAGE_WEBGL"
32]
33
34# Uniform texture types. Be wary of substrings finding the wrong types.
35# e.g. with 2D_MULTISAMPLE/2D_ARRAY and 2D.
36texture_types = {
37    "2D": "2D",
38    "2D_ARRAY": "2D_ARRAY",
39    "2D_ARRAY_SHADOW": "2D_ARRAY",
40    "2D_MULTISAMPLE": "2D_MULTISAMPLE",
41    "2D_MULTISAMPLE_ARRAY": "2D_MULTISAMPLE_ARRAY",
42    "2D_RECT_ANGLE": "2D",
43    "2D_SHADOW": "2D",
44    "3D": "3D",
45    "CUBE": "CUBE_MAP",
46    "CUBE_SHADOW": "CUBE_MAP",
47    "EXTERNAL_OES": "EXTERNAL_OES",
48    "RECT": "RECTANGLE",
49    "VIDEO_IMAGE_WEBGL": "VIDEO_IMAGE_WEBGL",
50}
51
52template_cpp = """// GENERATED FILE - DO NOT EDIT.
53// Generated by {script_name}.
54//
55// Copyright {copyright_year} The ANGLE Project Authors. All rights reserved.
56// Use of this source code is governed by a BSD-style license that can be
57// found in the LICENSE file.
58//
59// Uniform type info table:
60//   Metadata about a particular uniform format, indexed by GL type.
61
62#include <array>
63#include "common/utilities.h"
64
65using namespace angle;
66
67namespace gl
68{{
69
70namespace
71{{
72constexpr std::array<UniformTypeInfo, {total_count}> kInfoTable =
73{{{{
74{uniform_type_info_data}
75}}}};
76
77size_t GetTypeInfoIndex(GLenum uniformType)
78{{
79    switch (uniformType)
80    {{
81{uniform_type_index_cases}
82        default:
83            UNREACHABLE();
84            return 0;
85    }}
86}}
87}}  // anonymous namespace
88
89const UniformTypeInfo &GetUniformTypeInfo(GLenum uniformType)
90{{
91    ASSERT(kInfoTable[GetTypeInfoIndex(uniformType)].type == uniformType);
92    return kInfoTable[GetTypeInfoIndex(uniformType)];
93}}
94
95}}  // namespace gl
96"""
97
98type_info_data_template = """{{{type}, {component_type}, {texture_type}, {transposed_type}, {bool_type}, {sampler_format}, {rows}, {columns}, {components}, {component_size}, {internal_size}, {external_size}, {is_sampler}, {is_matrix}, {is_image}, {glsl_asfloat} }}"""
99type_index_case_template = """case {enum_value}: return {index_value};"""
100
101
102def cpp_bool(value):
103    return "true" if value else "false"
104
105
106def get_component_type(uniform_type):
107    if uniform_type.find("GL_BOOL") == 0:
108        return "GL_BOOL"
109    elif uniform_type.find("GL_FLOAT") == 0:
110        return "GL_FLOAT"
111    elif uniform_type.find("GL_INT") == 0:
112        return "GL_INT"
113    elif uniform_type.find("GL_UNSIGNED_INT") == 0:
114        return "GL_UNSIGNED_INT"
115    elif uniform_type == "GL_NONE":
116        return "GL_NONE"
117    else:
118        return "GL_INT"
119
120
121def get_texture_type(uniform_type):
122    for sampler_type, tex_type in texture_types.items():
123        if uniform_type.endswith(sampler_type):
124            return "GL_TEXTURE_" + tex_type
125    return "GL_NONE"
126
127
128def get_transposed_type(uniform_type):
129    if "_MAT" in uniform_type:
130        if "x" in uniform_type:
131            return "GL_FLOAT_MAT" + uniform_type[-1] + "x" + uniform_type[uniform_type.find("_MAT")
132                                                                          + 4]
133        else:
134            return uniform_type
135    else:
136        return "GL_NONE"
137
138
139def get_bool_type(uniform_type):
140    if uniform_type == "GL_INT" or uniform_type == "GL_UNSIGNED_INT" or uniform_type == "GL_FLOAT":
141        return "GL_BOOL"
142    elif "_VEC" in uniform_type:
143        return "GL_BOOL_VEC" + uniform_type[-1]
144    else:
145        return "GL_NONE"
146
147
148def get_sampler_format(uniform_type):
149    if not "_SAMPLER_" in uniform_type:
150        return "SamplerFormat::InvalidEnum"
151    elif "_SHADOW" in uniform_type:
152        return "SamplerFormat::Shadow"
153    elif "GL_UNSIGNED_INT_SAMPLER_" in uniform_type:
154        return "SamplerFormat::Unsigned"
155    elif "GL_INT_SAMPLER_" in uniform_type:
156        return "SamplerFormat::Signed"
157    else:
158        return "SamplerFormat::Float"
159
160
161def get_rows(uniform_type):
162    if uniform_type == "GL_NONE":
163        return "0"
164    elif "_MAT" in uniform_type:
165        return uniform_type[-1]
166    else:
167        return "1"
168
169
170def get_columns(uniform_type):
171    if uniform_type == "GL_NONE":
172        return "0"
173    elif "_VEC" in uniform_type:
174        return uniform_type[-1]
175    elif "_MAT" in uniform_type:
176        return uniform_type[uniform_type.find("_MAT") + 4]
177    else:
178        return "1"
179
180
181def get_components(uniform_type):
182    return str(int(get_rows(uniform_type)) * int(get_columns(uniform_type)))
183
184
185def get_component_size(uniform_type):
186    component_type = get_component_type(uniform_type)
187    if component_type == "GL_BOOL":
188        return "sizeof(GLint)"
189    elif component_type == "GL_FLOAT":
190        return "sizeof(GLfloat)"
191    elif component_type == "GL_INT":
192        return "sizeof(GLint)"
193    elif component_type == "GL_UNSIGNED_INT":
194        return "sizeof(GLuint)"
195    elif component_type == "GL_NONE":
196        return "0"
197    else:
198        raise "Invalid component type: " + component_type
199
200
201def get_internal_size(uniform_type):
202    return get_component_size(uniform_type) + " * " + str(int(get_rows(uniform_type)) * 4)
203
204
205def get_external_size(uniform_type):
206    return get_component_size(uniform_type) + " * " + get_components(uniform_type)
207
208
209def get_is_sampler(uniform_type):
210    return cpp_bool("_SAMPLER_" in uniform_type)
211
212
213def get_is_matrix(uniform_type):
214    return cpp_bool("_MAT" in uniform_type)
215
216
217def get_is_image(uniform_type):
218    return cpp_bool("_VIDEO_" not in uniform_type and "_IMAGE_" in uniform_type)
219
220
221def get_glsl_asfloat(uniform_type):
222    component_type = get_component_type(uniform_type)
223    if component_type == "GL_BOOL":
224        return '""'
225    elif component_type == "GL_FLOAT":
226        return '""'
227    elif component_type == "GL_INT":
228        return '"intBitsToFloat"'
229    elif component_type == "GL_UNSIGNED_INT":
230        return '"uintBitsToFloat"'
231    elif component_type == "GL_NONE":
232        return '""'
233    else:
234        raise "Invalid component type: " + component_type
235
236
237def gen_type_info(uniform_type):
238    return type_info_data_template.format(
239        type=uniform_type,
240        component_type=get_component_type(uniform_type),
241        texture_type=get_texture_type(uniform_type),
242        transposed_type=get_transposed_type(uniform_type),
243        bool_type=get_bool_type(uniform_type),
244        sampler_format=get_sampler_format(uniform_type),
245        rows=get_rows(uniform_type),
246        columns=get_columns(uniform_type),
247        components=get_components(uniform_type),
248        component_size=get_component_size(uniform_type),
249        internal_size=get_internal_size(uniform_type),
250        external_size=get_external_size(uniform_type),
251        is_sampler=get_is_sampler(uniform_type),
252        is_matrix=get_is_matrix(uniform_type),
253        is_image=get_is_image(uniform_type),
254        glsl_asfloat=get_glsl_asfloat(uniform_type))
255
256
257def gen_type_index_case(index, uniform_type):
258    return "case " + uniform_type + ": return " + str(index) + ";"
259
260
261def main():
262
263    # auto_script parameters.
264    if len(sys.argv) > 1:
265        inputs = []
266        outputs = ['uniform_type_info_autogen.cpp']
267
268        if sys.argv[1] == 'inputs':
269            print ','.join(inputs)
270        elif sys.argv[1] == 'outputs':
271            print ','.join(outputs)
272        else:
273            print('Invalid script parameters')
274            return 1
275        return 0
276
277    uniform_type_info_data = ",\n".join(
278        [gen_type_info(uniform_type) for uniform_type in all_uniform_types])
279    uniform_type_index_cases = "\n".join([
280        gen_type_index_case(index, uniform_type)
281        for index, uniform_type in enumerate(all_uniform_types)
282    ])
283
284    with open('uniform_type_info_autogen.cpp', 'wt') as out_file:
285        output_cpp = template_cpp.format(
286            script_name=sys.argv[0],
287            copyright_year=date.today().year,
288            total_count=len(all_uniform_types),
289            uniform_type_info_data=uniform_type_info_data,
290            uniform_type_index_cases=uniform_type_index_cases)
291        out_file.write(output_cpp)
292        out_file.close()
293    return 0
294
295
296if __name__ == '__main__':
297    sys.exit(main())
298