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 // TextureMtl.h: 7 // Defines the class interface for TextureMtl, implementing TextureImpl. 8 // 9 10 #ifndef LIBANGLE_RENDERER_METAL_TEXTUREMTL_H_ 11 #define LIBANGLE_RENDERER_METAL_TEXTUREMTL_H_ 12 13 #include <map> 14 15 #include "common/PackedEnums.h" 16 #include "libANGLE/renderer/TextureImpl.h" 17 #include "libANGLE/renderer/metal/RenderTargetMtl.h" 18 #include "libANGLE/renderer/metal/SurfaceMtl.h" 19 #include "libANGLE/renderer/metal/mtl_command_buffer.h" 20 #include "libANGLE/renderer/metal/mtl_context_device.h" 21 #include "libANGLE/renderer/metal/mtl_resources.h" 22 namespace rx 23 { 24 25 // structure represents one image definition of a texture created by glTexImage* call. 26 struct ImageDefinitionMtl 27 { 28 mtl::TextureRef image; 29 angle::FormatID formatID = angle::FormatID::NONE; 30 }; 31 32 class TextureMtl : public TextureImpl 33 { 34 public: 35 using TextureViewVector = std::vector<mtl::TextureRef>; 36 using LayerLevelTextureViewVector = std::vector<TextureViewVector>; 37 38 TextureMtl(const gl::TextureState &state); 39 // Texture view 40 TextureMtl(const TextureMtl &mtl, GLenum format); 41 ~TextureMtl() override; 42 void onDestroy(const gl::Context *context) override; 43 44 angle::Result setImage(const gl::Context *context, 45 const gl::ImageIndex &index, 46 GLenum internalFormat, 47 const gl::Extents &size, 48 GLenum format, 49 GLenum type, 50 const gl::PixelUnpackState &unpack, 51 gl::Buffer *unpackBuffer, 52 const uint8_t *pixels) override; 53 angle::Result setSubImage(const gl::Context *context, 54 const gl::ImageIndex &index, 55 const gl::Box &area, 56 GLenum format, 57 GLenum type, 58 const gl::PixelUnpackState &unpack, 59 gl::Buffer *unpackBuffer, 60 const uint8_t *pixels) override; 61 62 angle::Result setCompressedImage(const gl::Context *context, 63 const gl::ImageIndex &index, 64 GLenum internalFormat, 65 const gl::Extents &size, 66 const gl::PixelUnpackState &unpack, 67 size_t imageSize, 68 const uint8_t *pixels) override; 69 angle::Result setCompressedSubImage(const gl::Context *context, 70 const gl::ImageIndex &index, 71 const gl::Box &area, 72 GLenum format, 73 const gl::PixelUnpackState &unpack, 74 size_t imageSize, 75 const uint8_t *pixels) override; 76 77 angle::Result copyImage(const gl::Context *context, 78 const gl::ImageIndex &index, 79 const gl::Rectangle &sourceArea, 80 GLenum internalFormat, 81 gl::Framebuffer *source) override; 82 angle::Result copySubImage(const gl::Context *context, 83 const gl::ImageIndex &index, 84 const gl::Offset &destOffset, 85 const gl::Rectangle &sourceArea, 86 gl::Framebuffer *source) override; 87 88 angle::Result copyTexture(const gl::Context *context, 89 const gl::ImageIndex &index, 90 GLenum internalFormat, 91 GLenum type, 92 GLint sourceLevel, 93 bool unpackFlipY, 94 bool unpackPremultiplyAlpha, 95 bool unpackUnmultiplyAlpha, 96 const gl::Texture *source) override; 97 angle::Result copySubTexture(const gl::Context *context, 98 const gl::ImageIndex &index, 99 const gl::Offset &destOffset, 100 GLint sourceLevel, 101 const gl::Box &sourceBox, 102 bool unpackFlipY, 103 bool unpackPremultiplyAlpha, 104 bool unpackUnmultiplyAlpha, 105 const gl::Texture *source) override; 106 107 angle::Result copyCompressedTexture(const gl::Context *context, 108 const gl::Texture *source) override; 109 110 angle::Result setStorage(const gl::Context *context, 111 gl::TextureType type, 112 size_t levels, 113 GLenum internalFormat, 114 const gl::Extents &size) override; 115 116 angle::Result setStorageExternalMemory(const gl::Context *context, 117 gl::TextureType type, 118 size_t levels, 119 GLenum internalFormat, 120 const gl::Extents &size, 121 gl::MemoryObject *memoryObject, 122 GLuint64 offset, 123 GLbitfield createFlags, 124 GLbitfield usageFlags, 125 const void *imageCreateInfoPNext) override; 126 127 angle::Result setStorageMultisample(const gl::Context *context, 128 gl::TextureType type, 129 GLsizei samples, 130 GLint internalFormat, 131 const gl::Extents &size, 132 bool fixedSampleLocations) override; 133 134 angle::Result setEGLImageTarget(const gl::Context *context, 135 gl::TextureType type, 136 egl::Image *image) override; 137 138 angle::Result setImageExternal(const gl::Context *context, 139 gl::TextureType type, 140 egl::Stream *stream, 141 const egl::Stream::GLTextureDescription &desc) override; 142 143 angle::Result generateMipmap(const gl::Context *context) override; 144 145 angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) override; 146 147 angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override; 148 angle::Result releaseTexImage(const gl::Context *context) override; 149 150 angle::Result getAttachmentRenderTarget(const gl::Context *context, 151 GLenum binding, 152 const gl::ImageIndex &imageIndex, 153 GLsizei samples, 154 FramebufferAttachmentRenderTarget **rtOut) override; 155 156 angle::Result syncState(const gl::Context *context, 157 const gl::Texture::DirtyBits &dirtyBits, 158 gl::Command source) override; 159 160 angle::Result initializeContents(const gl::Context *context, 161 GLenum binding, 162 const gl::ImageIndex &imageIndex) override; 163 164 // The texture's data is initially initialized and stored in an array 165 // of images through glTexImage*/glCopyTex* calls. During draw calls, the caller must make sure 166 // the actual texture is created by calling this method to transfer the stored images data 167 // to the actual texture. 168 angle::Result ensureNativeStorageCreated(const gl::Context *context); 169 170 angle::Result bindToShader(const gl::Context *context, 171 mtl::RenderCommandEncoder *cmdEncoder, 172 gl::ShaderType shaderType, 173 gl::Sampler *sampler, /** nullable */ 174 int textureSlotIndex, 175 int samplerSlotIndex); 176 177 angle::Result bindToShaderImage(const gl::Context *context, 178 mtl::RenderCommandEncoder *cmdEncoder, 179 gl::ShaderType shaderType, 180 int textureSlotIndex, 181 int level, 182 int layer, 183 GLenum format); 184 getFormat()185 const mtl::Format &getFormat() const { return mFormat; } 186 187 private: 188 void deallocateNativeStorage(bool keepImages, bool keepSamplerStateAndFormat = false); 189 angle::Result createNativeStorage(const gl::Context *context, 190 gl::TextureType type, 191 GLuint mips, 192 GLuint samples, 193 const gl::Extents &size); 194 angle::Result onBaseMaxLevelsChanged(const gl::Context *context); 195 angle::Result ensureSamplerStateCreated(const gl::Context *context); 196 // Ensure image at given index is created: 197 angle::Result ensureImageCreated(const gl::Context *context, const gl::ImageIndex &index); 198 // Ensure all image views at all faces/levels are retained. 199 void retainImageDefinitions(); 200 mtl::TextureRef createImageViewFromTextureStorage(GLuint cubeFaceOrZero, GLuint glLevel); 201 angle::Result createViewFromBaseToMaxLevel(); 202 angle::Result ensureLevelViewsWithinBaseMaxCreated(); 203 angle::Result checkForEmulatedChannels(const gl::Context *context, 204 const mtl::Format &mtlFormat, 205 const mtl::TextureRef &texture); 206 mtl::TextureRef &getImage(const gl::ImageIndex &imageIndex); 207 ImageDefinitionMtl &getImageDefinition(const gl::ImageIndex &imageIndex); 208 angle::Result getRenderTarget(ContextMtl *context, 209 const gl::ImageIndex &imageIndex, 210 GLsizei implicitSamples, 211 RenderTargetMtl **renderTargetOut); 212 mtl::TextureRef &getImplicitMSTexture(const gl::ImageIndex &imageIndex); 213 214 angle::Result setStorageImpl(const gl::Context *context, 215 gl::TextureType type, 216 GLuint mips, 217 GLuint samples, 218 const mtl::Format &mtlFormat, 219 const gl::Extents &size); 220 221 angle::Result redefineImage(const gl::Context *context, 222 const gl::ImageIndex &index, 223 const mtl::Format &mtlFormat, 224 const gl::Extents &size); 225 226 angle::Result setImageImpl(const gl::Context *context, 227 const gl::ImageIndex &index, 228 const gl::InternalFormat &dstFormatInfo, 229 const gl::Extents &size, 230 GLenum srcFormat, 231 GLenum srcType, 232 const gl::PixelUnpackState &unpack, 233 gl::Buffer *unpackBuffer, 234 const uint8_t *pixels); 235 angle::Result setSubImageImpl(const gl::Context *context, 236 const gl::ImageIndex &index, 237 const gl::Box &area, 238 const gl::InternalFormat &formatInfo, 239 GLenum type, 240 const gl::PixelUnpackState &unpack, 241 gl::Buffer *unpackBuffer, 242 const uint8_t *pixels); 243 244 angle::Result copySubImageImpl(const gl::Context *context, 245 const gl::ImageIndex &index, 246 const gl::Offset &destOffset, 247 const gl::Rectangle &sourceArea, 248 const gl::InternalFormat &internalFormat, 249 const FramebufferMtl *source, 250 const RenderTargetMtl *sourceRtt); 251 angle::Result copySubImageWithDraw(const gl::Context *context, 252 const gl::ImageIndex &index, 253 const gl::Offset &destOffset, 254 const gl::Rectangle &sourceArea, 255 const gl::InternalFormat &internalFormat, 256 const FramebufferMtl *source, 257 const RenderTargetMtl *sourceRtt); 258 angle::Result copySubImageCPU(const gl::Context *context, 259 const gl::ImageIndex &index, 260 const gl::Offset &destOffset, 261 const gl::Rectangle &sourceArea, 262 const gl::InternalFormat &internalFormat, 263 const FramebufferMtl *source, 264 const RenderTargetMtl *sourceRtt); 265 266 angle::Result copySubTextureImpl(const gl::Context *context, 267 const gl::ImageIndex &index, 268 const gl::Offset &destOffset, 269 const gl::InternalFormat &internalFormat, 270 GLint sourceLevel, 271 const gl::Box &sourceBox, 272 bool unpackFlipY, 273 bool unpackPremultiplyAlpha, 274 bool unpackUnmultiplyAlpha, 275 const gl::Texture *source); 276 277 angle::Result copySubTextureWithDraw(const gl::Context *context, 278 const gl::ImageIndex &index, 279 const gl::Offset &destOffset, 280 const gl::InternalFormat &internalFormat, 281 const mtl::MipmapNativeLevel &sourceNativeLevel, 282 const gl::Box &sourceBox, 283 const angle::Format &sourceAngleFormat, 284 bool unpackFlipY, 285 bool unpackPremultiplyAlpha, 286 bool unpackUnmultiplyAlpha, 287 const mtl::TextureRef &sourceTexture); 288 289 angle::Result copySubTextureCPU(const gl::Context *context, 290 const gl::ImageIndex &index, 291 const gl::Offset &destOffset, 292 const gl::InternalFormat &internalFormat, 293 const mtl::MipmapNativeLevel &sourceNativeLevel, 294 const gl::Box &sourceBox, 295 const angle::Format &sourceAngleFormat, 296 bool unpackFlipY, 297 bool unpackPremultiplyAlpha, 298 bool unpackUnmultiplyAlpha, 299 const mtl::TextureRef &sourceTexture); 300 301 // Copy data to texture's per array's slice/cube's face. NOTE: This function doesn't upload 302 // data to 3D texture's z layer. Metal treats 3D texture's z layer & array texture's slice 303 // differently. For array/cube texture, it is only possible to upload to one slice at a time. 304 angle::Result setPerSliceSubImage(const gl::Context *context, 305 int slice, 306 const MTLRegion &mtlArea, 307 const gl::InternalFormat &internalFormat, 308 GLenum type, 309 const angle::Format &pixelsAngleFormat, 310 size_t pixelsRowPitch, 311 size_t pixelsDepthPitch, 312 gl::Buffer *unpackBuffer, 313 const uint8_t *pixels, 314 const mtl::TextureRef &image); 315 316 // Convert pixels to suported format before uploading to texture 317 angle::Result convertAndSetPerSliceSubImage(const gl::Context *context, 318 int slice, 319 const MTLRegion &mtlArea, 320 const gl::InternalFormat &internalFormat, 321 GLenum type, 322 const angle::Format &pixelsAngleFormat, 323 size_t pixelsRowPitch, 324 size_t pixelsDepthPitch, 325 gl::Buffer *unpackBuffer, 326 const uint8_t *pixels, 327 const mtl::TextureRef &image); 328 329 angle::Result generateMipmapCPU(const gl::Context *context); 330 331 bool needsFormatViewForPixelLocalStorage(const ShPixelLocalStorageOptions &) const; 332 bool isImmutableOrPBuffer() const; 333 334 mtl::Format mFormat; 335 egl::Surface *mBoundSurface = nullptr; 336 class NativeTextureWrapper; 337 class NativeTextureWrapperWithViewSupport; 338 // The real texture used by Metal. 339 // For non-immutable texture, this usually contains levels from (GL base level -> GL max level). 340 // For immutable texture, this contains levels allocated with glTexStorage which could be 341 // outside (GL base level -> GL max level) range. 342 std::unique_ptr<NativeTextureWrapperWithViewSupport> mNativeTextureStorage; 343 // The view of mNativeTextureStorage from (GL base level -> GL max level) 344 std::unique_ptr<NativeTextureWrapper> mViewFromBaseToMaxLevel; 345 id<MTLSamplerState> mMetalSamplerState = nil; 346 347 // Number of slices 348 uint32_t mSlices = 1; 349 350 // Stored images array defined by glTexImage/glCopy*. 351 // Once the images array is complete, they will be transferred to real texture object. 352 // NOTE: 353 // - For Cube map, there will be at most 6 entries in the map table, one for each face. This is 354 // because the Cube map's image is defined per face & per level. 355 // - For other texture types, there will be only one entry in the map table. All other textures 356 // except Cube map has texture image defined per level (all slices included). 357 // - The second dimension is indexed by GL level. 358 std::map<int, gl::TexLevelArray<ImageDefinitionMtl>> mTexImageDefs; 359 // 1st index = image index, 2nd index = samples count. 360 std::map<gl::ImageIndex, gl::RenderToTextureImageMap<RenderTargetMtl>> mRenderTargets; 361 std::map<gl::ImageIndex, gl::RenderToTextureImageMap<mtl::TextureRef>> mImplicitMSTextures; 362 363 // Lazily populated 2D views for shader storage images. 364 // May have different formats than the original texture. 365 // Indexed by format, then layer, then level. 366 std::map<MTLPixelFormat, LayerLevelTextureViewVector> mShaderImageViews; 367 368 // Mipmap views are indexed from (base GL level -> max GL level): 369 mtl::NativeTexLevelArray mLevelViewsWithinBaseMax; 370 371 // The swizzled or stencil view used for shader sampling. 372 mtl::TextureRef mSwizzleStencilSamplingView; 373 }; 374 375 } // namespace rx 376 377 #endif /* LIBANGLE_RENDERER_METAL_TEXTUREMTL_H_ */ 378