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