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