xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/metal/TextureMtl.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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