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