• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3
2# Copyright 2019 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_mtl_format_table.py:
7#  Code generation for Metal format map.
8#  NOTE: don't run this script directly. Run scripts/run_code_generation.py.
9#
10
11import json
12import math
13import pprint
14import re
15import sys
16
17sys.path.append('..')
18import angle_format as angle_format_utils
19
20template_autogen_inl = """// GENERATED FILE - DO NOT EDIT.
21// Generated by {script_name} using data from {data_source_name}
22//
23// Copyright 2020 The ANGLE Project Authors. All rights reserved.
24// Use of this source code is governed by a BSD-style license that can be
25// found in the LICENSE file.
26//
27// Metal Format table:
28//   Conversion from ANGLE format to Metal format.
29
30#import <Metal/Metal.h>
31#include <TargetConditionals.h>
32
33#include "image_util/copyimage.h"
34#include "image_util/generatemip.h"
35#include "image_util/loadimage.h"
36#include "libANGLE/renderer/Format.h"
37#include "libANGLE/renderer/metal/DisplayMtl.h"
38#include "libANGLE/renderer/metal/mtl_format_utils.h"
39
40using namespace angle;
41
42namespace rx
43{{
44namespace mtl
45{{
46
47angle::FormatID Format::MetalToAngleFormatID(MTLPixelFormat formatMtl)
48{{
49    // Actual conversion
50    switch (formatMtl)
51    {{
52{mtl_pixel_format_switch}
53    }}
54}}
55
56void Format::init(const DisplayMtl *display, angle::FormatID intendedFormatId_)
57{{
58    this->intendedFormatId = intendedFormatId_;
59
60    id<MTLDevice> metalDevice = display->getMetalDevice();
61
62    // Actual conversion
63    switch (this->intendedFormatId)
64    {{
65{angle_image_format_switch}
66    }}
67}}
68
69void VertexFormat::init(angle::FormatID angleFormatId, bool tightlyPacked)
70{{
71    this->intendedFormatId = angleFormatId;
72
73    // Actual conversion
74    switch (this->intendedFormatId)
75    {{
76{angle_vertex_format_switch}
77    }}
78}}
79
80void FormatTable::initNativeFormatCapsAutogen(const DisplayMtl *display)
81{{
82    const angle::FeaturesMtl &featuresMtl = display->getFeatures();
83    // Skip auto resolve if either hasDepth/StencilAutoResolve or allowMultisampleStoreAndResolve
84    // feature are disabled.
85    bool supportDepthAutoResolve = featuresMtl.hasDepthAutoResolve.enabled &&
86                                   featuresMtl.allowMultisampleStoreAndResolve.enabled;
87    bool supportStencilAutoResolve = featuresMtl.hasStencilAutoResolve.enabled &&
88                                     featuresMtl.allowMultisampleStoreAndResolve.enabled;
89    bool supportDepthStencilAutoResolve = supportDepthAutoResolve && supportStencilAutoResolve;
90
91    // Source: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
92    {metal_format_caps}
93}}
94
95}}  // namespace mtl
96}}  // namespace rx
97"""
98
99image_format_assign_template1 = """
100            this->metalFormat = {mtl_format};
101            this->actualFormatId = angle::FormatID::{actual_angle_format};
102            this->initFunction = {init_function};
103"""
104
105image_format_assign_template2 = """
106            if ({fallback_condition})
107            {{
108                this->metalFormat = {mtl_format};
109                this->actualFormatId = angle::FormatID::{actual_angle_format};
110                this->initFunction = {init_function};
111            }}
112            else
113            {{
114                this->metalFormat = {mtl_format_fallback};
115                this->actualFormatId = angle::FormatID::{actual_angle_format_fallback};
116                this->initFunction = {init_function_fallback};
117            }}
118"""
119
120case_image_format_template1 = """        case angle::FormatID::{angle_format}:
121            {image_format_assign}
122            this->swizzled = false;
123            break;
124
125"""
126
127case_image_format_template2 = """        case angle::FormatID::{angle_format}:
128#if defined(__IPHONE_13_0) || defined(__MAC_10_15)
129            if (display->getFeatures().hasTextureSwizzle.enabled)
130            {{
131                {image_format_assign_swizzled}
132                this->swizzled = true;
133                this->swizzle  = {mtl_swizzle};
134            }}
135            else
136#endif  // #if defined(__IPHONE_13_0) || defined(__MAC_10_15)
137            {{
138                {image_format_assign_default}
139                this->swizzled = false;
140            }}
141            break;
142
143"""
144
145case_image_mtl_to_angle_template = """        case {mtl_format}:
146            return angle::FormatID::{angle_format};
147"""
148
149case_vertex_format_template1 = """        case angle::FormatID::{angle_format}:
150            this->metalFormat = {mtl_format};
151            this->actualFormatId = angle::FormatID::{actual_angle_format};
152            this->vertexLoadFunction = {vertex_copy_function};
153            this->defaultAlpha = {default_alpha};
154            this->actualSameGLType = {same_gl_type};
155            break;
156
157"""
158
159case_vertex_format_template2 = """        case angle::FormatID::{angle_format}:
160            if (tightlyPacked)
161            {{
162                this->metalFormat = {mtl_format_packed};
163                this->actualFormatId = angle::FormatID::{actual_angle_format_packed};
164                this->vertexLoadFunction = {vertex_copy_function_packed};
165                this->defaultAlpha = {default_alpha_packed};
166                this->actualSameGLType = {same_gl_type_packed};
167            }}
168            else
169            {{
170                this->metalFormat = {mtl_format};
171                this->actualFormatId = angle::FormatID::{actual_angle_format};
172                this->vertexLoadFunction = {vertex_copy_function};
173                this->defaultAlpha = {default_alpha};
174                this->actualSameGLType = {same_gl_type};
175            }}
176            break;
177
178"""
179
180
181# NOTE(hqle): This is a modified version of the get_vertex_copy_function() function in
182# src/libANGLE/renderer/angle_format.py
183# - Return value is a tuple {copy_function, default_alpha_value, have_same_gl_type}.
184def get_vertex_copy_function_and_default_alpha(src_format, dst_format):
185    if dst_format == "NONE":
186        return "nullptr", 0, "false"
187
188    num_channel = len(angle_format_utils.get_channel_tokens(src_format))
189    if num_channel < 1 or num_channel > 4:
190        return "nullptr", 0, "false"
191
192    src_gl_type = angle_format_utils.get_format_gl_type(src_format)
193    dst_gl_type = angle_format_utils.get_format_gl_type(dst_format)
194
195    if src_gl_type == dst_gl_type:
196        if src_format.startswith('R10G10B10A2'):
197            return 'CopyNativeVertexData<GLuint, 1, 1, 0>', 0, "true"
198
199        if src_gl_type == None:
200            return 'nullptr', 0, "true"
201        dst_num_channel = len(angle_format_utils.get_channel_tokens(dst_format))
202        default_alpha = '1'
203
204        if num_channel == dst_num_channel or dst_num_channel < 4:
205            default_alpha = '0'
206        elif 'A16_FLOAT' in dst_format:
207            default_alpha = 'gl::Float16One'
208        elif 'A32_FLOAT' in dst_format:
209            default_alpha = 'gl::Float32One'
210        elif 'NORM' in dst_format:
211            default_alpha = 'std::numeric_limits<%s>::max()' % (src_gl_type)
212
213        return 'CopyNativeVertexData<%s, %d, %d, %s>' % (src_gl_type, num_channel, dst_num_channel,
214                                                         default_alpha), default_alpha, "true"
215
216    if src_format.startswith('R10G10B10A2'):
217        assert 'FLOAT' in dst_format, ('get_vertex_copy_function: can only convert to float,' +
218                                       ' not to ' + dst_format)
219        is_signed = 'true' if 'SINT' in src_format or 'SNORM' in src_format or 'SSCALED' in src_format else 'false'
220        is_normal = 'true' if 'NORM' in src_format else 'false'
221        return 'CopyXYZ10W2ToXYZWFloatVertexData<%s, %s, true, false>' % (is_signed,
222                                                                          is_normal), 0, "false"
223
224    return angle_format_utils.get_vertex_copy_function(src_format, dst_format), 0, "false"
225
226
227# Generate format conversion switch case (generic case)
228def gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map,
229                              assign_gen_func):
230    if isinstance(actual_angle_format_info, dict):
231        default_actual_angle_format = actual_angle_format_info['default']
232        # Check if the format can be override with swizzle feature
233        if 'swizzle' in actual_angle_format_info:
234            swizzle_info = actual_angle_format_info['swizzle']
235            swizzle_channels = swizzle_info[0]
236            swizzled_actual_angle_format = swizzle_info[1]
237            swizzle_map = {
238                'R': 'GL_RED',
239                'G': 'GL_GREEN',
240                'B': 'GL_BLUE',
241                'A': 'GL_ALPHA',
242                '1': 'GL_ONE',
243                '0': 'GL_ZERO',
244            }
245
246            mtl_swizzle_make = '{{{r}, {g}, {b}, {a}}}'.format(
247                r=swizzle_map[swizzle_channels[0:1]],
248                g=swizzle_map[swizzle_channels[1:2]],
249                b=swizzle_map[swizzle_channels[2:3]],
250                a=swizzle_map[swizzle_channels[3:]])
251            return case_image_format_template2.format(
252                angle_format=angle_format,
253                image_format_assign_default=assign_gen_func(default_actual_angle_format,
254                                                            angle_to_mtl_map),
255                image_format_assign_swizzled=assign_gen_func(swizzled_actual_angle_format,
256                                                             angle_to_mtl_map),
257                mtl_swizzle=mtl_swizzle_make)
258        else:
259            # Only default case
260            return gen_image_map_switch_case(angle_format, default_actual_angle_format,
261                                             angle_to_mtl_map, assign_gen_func)
262    else:
263        # Default case
264        return case_image_format_template1.format(
265            angle_format=angle_format,
266            image_format_assign=assign_gen_func(actual_angle_format_info, angle_to_mtl_map))
267
268
269# Generate format conversion switch case (simple case)
270def gen_image_map_switch_simple_case(angle_format, actual_angle_format_info, angle_to_gl,
271                                     angle_to_mtl_map):
272
273    def gen_format_assign_code(actual_angle_format, angle_to_mtl_map):
274        return image_format_assign_template1.format(
275            actual_angle_format=actual_angle_format,
276            mtl_format=angle_to_mtl_map[actual_angle_format],
277            init_function=angle_format_utils.get_internal_format_initializer(
278                angle_to_gl[angle_format], actual_angle_format))
279
280    return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map,
281                                     gen_format_assign_code)
282
283
284# Generate format conversion switch case (Mac case)
285def gen_image_map_switch_mac_case(angle_format, actual_angle_format_info, angle_to_gl,
286                                  angle_to_mtl_map, mac_fallbacks):
287    gl_format = angle_to_gl[angle_format]
288
289    def gen_format_assign_code(actual_angle_format, angle_to_mtl_map):
290        if actual_angle_format in mac_fallbacks:
291            # This format requires fallback when depth24Stencil8PixelFormatSupported flag is false.
292            # Fallback format:
293            actual_angle_format_fallback = mac_fallbacks[actual_angle_format]
294            fallback_condition = "metalDevice.depth24Stencil8PixelFormatSupported && \
295                                 !display->getFeatures().forceD24S8AsUnsupported.enabled"
296            # return if else block:
297            return image_format_assign_template2.format(
298                actual_angle_format=actual_angle_format,
299                mtl_format=angle_to_mtl_map[actual_angle_format],
300                init_function=angle_format_utils.get_internal_format_initializer(
301                    gl_format, actual_angle_format),
302                actual_angle_format_fallback=actual_angle_format_fallback,
303                mtl_format_fallback=angle_to_mtl_map[actual_angle_format_fallback],
304                init_function_fallback=angle_format_utils.get_internal_format_initializer(
305                    gl_format, actual_angle_format_fallback),
306                fallback_condition=fallback_condition)
307        else:
308            # return ordinary block:
309            return image_format_assign_template1.format(
310                actual_angle_format=actual_angle_format,
311                mtl_format=angle_to_mtl_map[actual_angle_format],
312                init_function=angle_format_utils.get_internal_format_initializer(
313                    gl_format, actual_angle_format))
314
315    return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map,
316                                     gen_format_assign_code)
317
318
319# Generate format conversion switch case (non-desktop ES 3.0 case)
320def gen_image_map_switch_es3_case(angle_format, actual_angle_format_info, angle_to_gl,
321                                  angle_to_mtl_map, mac_fallbacks):
322    gl_format = angle_to_gl[angle_format]
323
324    def gen_format_assign_code(actual_angle_format, angle_to_mtl_map):
325        actual_angle_format_fallback = mac_fallbacks[actual_angle_format]
326        return image_format_assign_template2.format(
327            actual_angle_format=actual_angle_format,
328            mtl_format=angle_to_mtl_map[actual_angle_format],
329            init_function=angle_format_utils.get_internal_format_initializer(
330                gl_format, actual_angle_format),
331            actual_angle_format_fallback=actual_angle_format_fallback,
332            mtl_format_fallback=angle_to_mtl_map[actual_angle_format_fallback],
333            init_function_fallback=angle_format_utils.get_internal_format_initializer(
334                gl_format, actual_angle_format_fallback),
335            fallback_condition="display->supportsAppleGPUFamily(1)")
336
337    return gen_image_map_switch_case(angle_format, actual_angle_format_info, angle_to_mtl_map,
338                                     gen_format_assign_code)
339
340
341# Generate format conversion switch case (ASTC LDR/HDR case)
342def gen_image_map_switch_astc_case(angle_format, angle_to_gl, angle_to_mtl_map):
343    gl_format = angle_to_gl[angle_format]
344
345    def gen_format_assign_code(actual_angle_format, angle_to_mtl_map):
346        return image_format_assign_template2.format(
347            actual_angle_format=actual_angle_format,
348            mtl_format=angle_to_mtl_map[actual_angle_format] + "HDR",
349            init_function=angle_format_utils.get_internal_format_initializer(
350                gl_format, actual_angle_format),
351            actual_angle_format_fallback=actual_angle_format,
352            mtl_format_fallback=angle_to_mtl_map[actual_angle_format] + "LDR",
353            init_function_fallback=angle_format_utils.get_internal_format_initializer(
354                gl_format, actual_angle_format),
355            fallback_condition="display->supportsAppleGPUFamily(6)")
356
357    return gen_image_map_switch_case(angle_format, angle_format, angle_to_mtl_map,
358                                     gen_format_assign_code)
359
360
361def gen_image_map_switch_string(image_table, angle_to_gl):
362    angle_override = image_table["override"]
363    mac_override = image_table["override_mac"]
364    mac_override_es3 = image_table["override_mac_es3"]
365    mac_override_bc1 = image_table["override_mac_bc1"]
366    ios_override = image_table["override_ios"]
367    mac_d24s8_fallbacks = image_table["d24s8_fallbacks_mac"]
368    angle_to_mtl = image_table["map"]
369    mac_specific_map = image_table["map_mac"]
370    ios_specific_map = image_table["map_ios"]
371    astc_tpl_map = image_table["map_astc_tpl"]
372
373    # mac_specific_map + angle_to_mtl:
374    mac_angle_to_mtl = mac_specific_map.copy()
375    mac_angle_to_mtl.update(angle_to_mtl)
376    # ios_specific_map + angle_to_mtl
377    ios_angle_to_mtl = ios_specific_map.copy()
378    ios_angle_to_mtl.update(angle_to_mtl)
379
380    switch_data = ''
381
382    def gen_image_map_switch_common_case(angle_format, actual_angle_format):
383        return gen_image_map_switch_simple_case(angle_format, actual_angle_format, angle_to_gl,
384                                                angle_to_mtl)
385
386    # Common case: universally-supported formats + universal overrides
387    for angle_format in sorted(angle_to_mtl.keys()):
388        switch_data += gen_image_map_switch_common_case(angle_format, angle_format)
389    for angle_format in sorted(angle_override.keys()):
390        switch_data += gen_image_map_switch_common_case(angle_format, angle_override[angle_format])
391
392    # Mac GPU case: macOS + Catalyst targets
393    switch_data += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
394    for angle_format in sorted(mac_specific_map.keys()):
395        switch_data += gen_image_map_switch_mac_case(angle_format, angle_format, angle_to_gl,
396                                                     mac_angle_to_mtl, mac_d24s8_fallbacks)
397    for angle_format in sorted(mac_override.keys()):
398        switch_data += gen_image_map_switch_simple_case(angle_format, mac_override[angle_format],
399                                                        angle_to_gl, mac_angle_to_mtl)
400    for angle_format in sorted(mac_override_bc1.keys()):
401        switch_data += gen_image_map_switch_simple_case(angle_format,
402                                                        mac_override_bc1[angle_format],
403                                                        angle_to_gl, mac_angle_to_mtl)
404    switch_data += "#endif\n"
405
406    # Override missing ES 3.0 formats for older macOS SDK or Catalyst
407    switch_data += "#if (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED < 101600)) || \\\n"
408    switch_data += "TARGET_OS_MACCATALYST\n"
409    for angle_format in sorted(mac_override_es3.keys()):
410        switch_data += gen_image_map_switch_simple_case(angle_format,
411                                                        mac_override_es3[angle_format],
412                                                        angle_to_gl, mac_angle_to_mtl)
413    switch_data += "#endif\n"
414
415    # iOS specific
416    switch_data += "#if TARGET_OS_IOS || TARGET_OS_TV\n"
417    for angle_format in sorted(ios_specific_map.keys()):
418        switch_data += gen_image_map_switch_simple_case(angle_format, angle_format, angle_to_gl,
419                                                        ios_specific_map)
420    for angle_format in sorted(ios_override.keys()):
421        switch_data += gen_image_map_switch_simple_case(angle_format, ios_override[angle_format],
422                                                        angle_to_gl, ios_angle_to_mtl)
423    for angle_format in sorted(astc_tpl_map.keys()):
424        switch_data += gen_image_map_switch_astc_case(angle_format, angle_to_gl, astc_tpl_map)
425    switch_data += "#endif\n"
426
427    # Try to support all iOS formats on newer macOS with Apple GPU.
428    switch_data += "#if (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 101600))\n"
429    for angle_format in sorted(ios_specific_map.keys()):
430        if (angle_format in mac_override_es3.keys()):
431            # ETC/EAC or packed 16-bit
432            switch_data += gen_image_map_switch_es3_case(angle_format, angle_format, angle_to_gl,
433                                                         ios_angle_to_mtl, mac_override_es3)
434        else:
435            # ASTC sRGB or PVRTC1
436            switch_data += gen_image_map_switch_simple_case(angle_format, angle_format,
437                                                            angle_to_gl, ios_specific_map)
438    # ASTC LDR or HDR
439    for angle_format in sorted(astc_tpl_map.keys()):
440        switch_data += gen_image_map_switch_astc_case(angle_format, angle_to_gl, astc_tpl_map)
441    switch_data += "#endif\n"
442
443    switch_data += "        default:\n"
444    switch_data += "            this->metalFormat = MTLPixelFormatInvalid;\n"
445    switch_data += "            this->actualFormatId = angle::FormatID::NONE;"
446    return switch_data
447
448
449def gen_image_mtl_to_angle_switch_string(image_table):
450    angle_to_mtl = image_table["map"]
451    mac_specific_map = image_table["map_mac"]
452    ios_specific_map = image_table["map_ios"]
453    astc_tpl_map = image_table["map_astc_tpl"]
454
455    switch_data = ''
456
457    # Common case
458    for angle_format in sorted(angle_to_mtl.keys()):
459        switch_data += case_image_mtl_to_angle_template.format(
460            mtl_format=angle_to_mtl[angle_format], angle_format=angle_format)
461
462    # Mac specific
463    switch_data += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
464    for angle_format in sorted(mac_specific_map.keys()):
465        switch_data += case_image_mtl_to_angle_template.format(
466            mtl_format=mac_specific_map[angle_format], angle_format=angle_format)
467    switch_data += "#endif  // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
468
469    # iOS + macOS 11.0+ specific
470    switch_data += "#if TARGET_OS_IOS || TARGET_OS_TV || (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 101600))\n"
471    for angle_format in sorted(ios_specific_map.keys()):
472        # ETC1_R8G8B8_UNORM_BLOCK is a duplicated of ETC2_R8G8B8_UNORM_BLOCK
473        if angle_format == 'ETC1_R8G8B8_UNORM_BLOCK':
474            continue
475        switch_data += case_image_mtl_to_angle_template.format(
476            mtl_format=ios_specific_map[angle_format], angle_format=angle_format)
477    for angle_format in sorted(astc_tpl_map.keys()):
478        switch_data += case_image_mtl_to_angle_template.format(
479            mtl_format=astc_tpl_map[angle_format] + "LDR", angle_format=angle_format)
480        switch_data += case_image_mtl_to_angle_template.format(
481            mtl_format=astc_tpl_map[angle_format] + "HDR", angle_format=angle_format)
482    switch_data += "#endif  // TARGET_OS_IOS || TARGET_OS_TV || mac 11.0+\n"
483
484    switch_data += "        default:\n"
485    switch_data += "            return angle::FormatID::NONE;\n"
486    return switch_data
487
488
489def gen_vertex_map_switch_case(angle_fmt, actual_angle_fmt, angle_to_mtl_map, override_packed_map):
490    mtl_format = angle_to_mtl_map[actual_angle_fmt]
491    copy_function, default_alpha, same_gl_type = get_vertex_copy_function_and_default_alpha(
492        angle_fmt, actual_angle_fmt)
493
494    if actual_angle_fmt in override_packed_map:
495        # This format has an override when used in tightly packed buffer,
496        # Return if else block
497        angle_fmt_packed = override_packed_map[actual_angle_fmt]
498        mtl_format_packed = angle_to_mtl_map[angle_fmt_packed]
499        copy_function_packed, default_alpha_packed, same_gl_type_packed = get_vertex_copy_function_and_default_alpha(
500            angle_fmt, angle_fmt_packed)
501
502        return case_vertex_format_template2.format(
503            angle_format=angle_fmt,
504            mtl_format_packed=mtl_format_packed,
505            actual_angle_format_packed=angle_fmt_packed,
506            vertex_copy_function_packed=copy_function_packed,
507            default_alpha_packed=default_alpha_packed,
508            same_gl_type_packed=same_gl_type_packed,
509            mtl_format=mtl_format,
510            actual_angle_format=actual_angle_fmt,
511            vertex_copy_function=copy_function,
512            default_alpha=default_alpha,
513            same_gl_type=same_gl_type)
514    else:
515        # This format has no packed buffer's override, return ordinary block.
516        return case_vertex_format_template1.format(
517            angle_format=angle_fmt,
518            mtl_format=mtl_format,
519            actual_angle_format=actual_angle_fmt,
520            vertex_copy_function=copy_function,
521            default_alpha=default_alpha,
522            same_gl_type=same_gl_type)
523
524
525def gen_vertex_map_switch_string(vertex_table):
526    angle_to_mtl = vertex_table["map"]
527    angle_override = vertex_table["override"]
528    override_packed = vertex_table["override_tightly_packed"]
529
530    switch_data = ''
531    for angle_fmt in sorted(angle_to_mtl.keys()):
532        switch_data += gen_vertex_map_switch_case(angle_fmt, angle_fmt, angle_to_mtl,
533                                                  override_packed)
534
535    for angle_fmt in sorted(angle_override.keys()):
536        switch_data += gen_vertex_map_switch_case(angle_fmt, angle_override[angle_fmt],
537                                                  angle_to_mtl, override_packed)
538
539    switch_data += "        default:\n"
540    switch_data += "            this->metalFormat = MTLVertexFormatInvalid;\n"
541    switch_data += "            this->actualFormatId = angle::FormatID::NONE;\n"
542    switch_data += "            this->vertexLoadFunction = nullptr;"
543    switch_data += "            this->defaultAlpha = 0;"
544    switch_data += "            this->actualSameGLType = false;"
545    return switch_data
546
547
548def gen_mtl_format_caps_init_string(map_image):
549    caps = map_image['caps']
550    mac_caps = map_image['caps_mac']
551    ios_caps = map_image['caps_ios']
552    caps_init_str = ''
553
554    def cap_to_param(caps, key):
555        return '/** ' + key + '*/ ' + caps.get(key, 'false')
556
557    def caps_to_cpp(caps_table):
558        init_str = ''
559        for mtl_format in sorted(caps_table.keys()):
560            caps = caps_table[mtl_format]
561            filterable = cap_to_param(caps, 'filterable')
562            writable = cap_to_param(caps, 'writable')
563            colorRenderable = cap_to_param(caps, 'colorRenderable')
564            depthRenderable = cap_to_param(caps, 'depthRenderable')
565            blendable = cap_to_param(caps, 'blendable')
566            multisample = cap_to_param(caps, 'multisample')
567            resolve = cap_to_param(caps, 'resolve')
568
569            init_str += "    setFormatCaps({0}, {1}, {2}, {3}, {4}, {5}, {6}, {7});\n\n".format(
570                mtl_format, filterable, writable, blendable, multisample, resolve, colorRenderable,
571                depthRenderable)
572
573        return init_str
574
575    caps_init_str += caps_to_cpp(caps)
576
577    caps_init_str += "#if TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
578    caps_init_str += caps_to_cpp(mac_caps)
579    caps_init_str += "#endif  // TARGET_OS_OSX || TARGET_OS_MACCATALYST\n"
580
581    caps_init_str += "#if (TARGET_OS_IOS && !TARGET_OS_MACCATALYST) || TARGET_OS_TV || \\\n"
582    caps_init_str += "    (TARGET_OS_OSX && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 101600))\n"
583
584    caps_init_str += caps_to_cpp(ios_caps)
585
586    caps_init_str += "#endif\n"
587
588    return caps_init_str
589
590
591def main():
592    data_source_name = 'mtl_format_map.json'
593    # auto_script parameters.
594    if len(sys.argv) > 1:
595        inputs = ['../angle_format.py', '../angle_format_map.json', data_source_name]
596        outputs = ['mtl_format_table_autogen.mm']
597
598        if sys.argv[1] == 'inputs':
599            print(','.join(inputs))
600        elif sys.argv[1] == 'outputs':
601            print(','.join(outputs))
602        else:
603            print('Invalid script parameters')
604            return 1
605        return 0
606
607    angle_to_gl = angle_format_utils.load_inverse_table('../angle_format_map.json')
608
609    map_json = angle_format_utils.load_json(data_source_name)
610    map_image = map_json["image"]
611    map_vertex = map_json["vertex"]
612
613    image_switch_data = gen_image_map_switch_string(map_image, angle_to_gl)
614    image_mtl_to_angle_switch_data = gen_image_mtl_to_angle_switch_string(map_image)
615
616    vertex_switch_data = gen_vertex_map_switch_string(map_vertex)
617
618    caps_init_str = gen_mtl_format_caps_init_string(map_image)
619
620    output_cpp = template_autogen_inl.format(
621        script_name=sys.argv[0],
622        data_source_name=data_source_name,
623        angle_image_format_switch=image_switch_data,
624        mtl_pixel_format_switch=image_mtl_to_angle_switch_data,
625        angle_vertex_format_switch=vertex_switch_data,
626        metal_format_caps=caps_init_str)
627    with open('mtl_format_table_autogen.mm', 'wt') as out_file:
628        out_file.write(output_cpp)
629        out_file.close()
630
631
632if __name__ == '__main__':
633    sys.exit(main())
634