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