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