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