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