xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/mtl_format_utils.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
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 // mtl_format_utils.h:
7 //      Declares Format conversion utilities classes that convert from angle formats
8 //      to respective MTLPixelFormat and MTLVertexFormat.
9 //
10 
11 #ifndef LIBANGLE_RENDERER_METAL_MTL_FORMAT_UTILS_H_
12 #define LIBANGLE_RENDERER_METAL_MTL_FORMAT_UTILS_H_
13 
14 #import <Metal/Metal.h>
15 
16 #include <unordered_map>
17 
18 #include "common/angleutils.h"
19 #include "libANGLE/Caps.h"
20 #include "libANGLE/formatutils.h"
21 #include "libANGLE/renderer/copyvertex.h"
22 #include "libANGLE/renderer/renderer_utils.h"
23 
24 namespace rx
25 {
26 class DisplayMtl;
27 
28 namespace mtl
29 {
30 class ContextDevice;
31 
32 struct FormatBase
33 {
34     inline bool operator==(const FormatBase &rhs) const
35     {
36         return intendedFormatId == rhs.intendedFormatId && actualFormatId == rhs.actualFormatId;
37     }
38 
39     inline bool operator!=(const FormatBase &rhs) const { return !((*this) == rhs); }
40 
41     const angle::Format &actualAngleFormat() const;
42     const angle::Format &intendedAngleFormat() const;
43 
44     angle::FormatID actualFormatId   = angle::FormatID::NONE;
45     angle::FormatID intendedFormatId = angle::FormatID::NONE;
46 };
47 
48 struct FormatCaps
49 {
isRenderableFormatCaps50     bool isRenderable() const { return colorRenderable || depthRenderable; }
51 
52     bool filterable           = false;
53     bool writable             = false;
54     bool colorRenderable      = false;
55     bool depthRenderable      = false;
56     bool blendable            = false;
57     bool multisample          = false;  // can be used as MSAA target
58     bool resolve              = false;  // Can be used as resolve target
59     bool compressed           = false;
60     NSUInteger pixelBytes     = 0;
61     NSUInteger pixelBytesMSAA = 0;
62     NSUInteger channels       = 0;
63     uint8_t alignment         = 0;
64 };
65 
66 // Pixel format
67 struct Format : public FormatBase
68 {
69     Format() = default;
70 
71     static angle::FormatID MetalToAngleFormatID(MTLPixelFormat formatMtl);
72 
73     const gl::InternalFormat &intendedInternalFormat() const;
74     const gl::InternalFormat &actualInternalFormat() const;
75 
validFormat76     bool valid() const { return metalFormat != MTLPixelFormatInvalid; }
hasDepthAndStencilBitsFormat77     bool hasDepthAndStencilBits() const
78     {
79         return actualAngleFormat().depthBits && actualAngleFormat().stencilBits;
80     }
hasDepthOrStencilBitsFormat81     bool hasDepthOrStencilBits() const
82     {
83         return actualAngleFormat().depthBits || actualAngleFormat().stencilBits;
84     }
85     bool isPVRTC() const;
86 
getCapsFormat87     const FormatCaps &getCaps() const { return caps; }
88 
89     // Need conversion between source format and this format?
90     bool needConversion(angle::FormatID srcFormatId) const;
91 
92     MTLPixelFormat metalFormat = MTLPixelFormatInvalid;
93 
94     LoadFunctionMap textureLoadFunctions       = nullptr;
95     InitializeTextureDataFunction initFunction = nullptr;
96 
97     FormatCaps caps;
98 
99     bool swizzled = false;
100     std::array<GLenum, 4> swizzle;
101 
102   private:
103     void init(const DisplayMtl *display, angle::FormatID intendedFormatId);
104 
105     friend class FormatTable;
106 };
107 
108 // Vertex format
109 struct VertexFormat : public FormatBase
110 {
111     VertexFormat() = default;
112 
113     MTLVertexFormat metalFormat = MTLVertexFormatInvalid;
114 
115     VertexCopyFunction vertexLoadFunction = nullptr;
116 
117     uint32_t defaultAlpha = 0;
118     // Intended and actual format have same GL type, and possibly only differ in number of
119     // components?
120     bool actualSameGLType = true;
121 
122   private:
123     void init(angle::FormatID angleFormatId, bool tightlyPacked = false);
124 
125     friend class FormatTable;
126 };
127 
128 class FormatTable final : angle::NonCopyable
129 {
130   public:
131     FormatTable()  = default;
132     ~FormatTable() = default;
133 
134     angle::Result initialize(const DisplayMtl *display);
135 
136     void generateTextureCaps(const DisplayMtl *display, gl::TextureCapsMap *capsMapOut);
137 
138     const Format &getPixelFormat(angle::FormatID angleFormatId) const;
139     const FormatCaps &getNativeFormatCaps(MTLPixelFormat mtlFormat) const;
140 
141     // tightlyPacked means this format will be used in a tightly packed vertex buffer.
142     // In that case, it's easier to just convert everything to float to ensure
143     // Metal alignment requirements between 2 elements inside the buffer will be met regardless
144     // of how many components each element has.
145     const VertexFormat &getVertexFormat(angle::FormatID angleFormatId, bool tightlyPacked) const;
146 
getMaxSamples()147     uint32_t getMaxSamples() const { return mMaxSamples; }
148 
149   private:
150     void initNativeFormatCapsAutogen(const DisplayMtl *display);
151     void initNativeFormatCaps(const DisplayMtl *display);
152 
153     void setFormatCaps(MTLPixelFormat formatId,
154                        bool filterable,
155                        bool writable,
156                        bool blendable,
157                        bool multisample,
158                        bool resolve,
159                        bool colorRenderable);
160 
161     void setFormatCaps(MTLPixelFormat formatId,
162                        bool filterable,
163                        bool writable,
164                        bool blendable,
165                        bool multisample,
166                        bool resolve,
167                        bool colorRenderable,
168                        NSUInteger bytesPerChannel,
169                        NSUInteger channels);
170 
171     void setFormatCaps(MTLPixelFormat formatId,
172                        bool filterable,
173                        bool writable,
174                        bool blendable,
175                        bool multisample,
176                        bool resolve,
177                        bool colorRenderable,
178                        bool depthRenderable);
179 
180     void setFormatCaps(MTLPixelFormat formatId,
181                        bool filterable,
182                        bool writable,
183                        bool blendable,
184                        bool multisample,
185                        bool resolve,
186                        bool colorRenderable,
187                        bool depthRenderable,
188                        NSUInteger bytesPerChannel,
189                        NSUInteger channels);
190 
191     void setCompressedFormatCaps(MTLPixelFormat formatId, bool filterable);
192 
193     void adjustFormatCapsForDevice(const mtl::ContextDevice &device,
194                                    MTLPixelFormat id,
195                                    bool supportsiOS2,
196                                    bool supportsiOS4);
197 
198     std::array<Format, angle::kNumANGLEFormats> mPixelFormatTable;
199     angle::HashMap<MTLPixelFormat, FormatCaps> mNativePixelFormatCapsTable;
200     // One for tightly packed buffers, one for general cases.
201     std::array<VertexFormat, angle::kNumANGLEFormats> mVertexFormatTables[2];
202 
203     uint32_t mMaxSamples;
204 };
205 
206 }  // namespace mtl
207 }  // namespace rx
208 
209 #endif /* LIBANGLE_RENDERER_METAL_MTL_FORMAT_UTILS_H_ */
210