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