• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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