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