Flutter Impeller
texture_gles.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_TEXTURE_GLES_H_
6 #define FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_TEXTURE_GLES_H_
7 
8 #include <array>
9 #include <bitset>
10 
11 #include "fml/logging.h"
13 #include "impeller/core/texture.h"
17 
18 namespace impeller {
19 
20 class TextureGLES final : public Texture,
21  public BackendCast<TextureGLES, Texture> {
22  public:
23  enum class Type {
24  kTexture,
28  };
29 
30  //----------------------------------------------------------------------------
31  /// @brief Create a texture by wrapping an external framebuffer object
32  /// whose lifecycle is owned by the caller.
33  ///
34  /// This is useful for creating a render target for the default
35  /// window managed framebuffer.
36  ///
37  /// @param[in] reactor The reactor
38  /// @param[in] desc The description
39  /// @param[in] fbo The fbo
40  ///
41  /// @return If a texture representation of the framebuffer could be
42  /// created.
43  ///
44  static std::shared_ptr<TextureGLES> WrapFBO(
45  std::shared_ptr<ReactorGLES> reactor,
46  TextureDescriptor desc,
47  GLuint fbo);
48 
49  //----------------------------------------------------------------------------
50  /// @brief Create a texture by wrapping an external OpenGL texture
51  /// handle. Ownership of the texture handle is assumed by the
52  /// reactor.
53  ///
54  /// @param[in] reactor The reactor
55  /// @param[in] desc The description
56  /// @param[in] external_handle The external handle
57  ///
58  /// @return If a texture representation of the framebuffer could be
59  /// created.
60  ///
61  static std::shared_ptr<TextureGLES> WrapTexture(
62  std::shared_ptr<ReactorGLES> reactor,
63  TextureDescriptor desc,
64  HandleGLES external_handle);
65 
66  //----------------------------------------------------------------------------
67  /// @brief Create a "texture" that is never expected to be bound/unbound
68  /// explicitly or initialized in any way. It only exists to setup
69  /// a render pass description.
70  ///
71  /// @param[in] reactor The reactor
72  /// @param[in] desc The description
73  ///
74  /// @return If a texture placeholder could be created.
75  ///
76  static std::shared_ptr<TextureGLES> CreatePlaceholder(
77  std::shared_ptr<ReactorGLES> reactor,
78  TextureDescriptor desc);
79 
80  TextureGLES(std::shared_ptr<ReactorGLES> reactor,
81  TextureDescriptor desc,
82  bool threadsafe = false);
83 
84  // |Texture|
85  bool IsValid() const override;
86 
87  std::optional<GLuint> GetGLHandle() const;
88 
89  [[nodiscard]] bool Bind();
90 
91  [[nodiscard]] bool GenerateMipmap();
92 
93  enum class AttachmentType {
94  kColor0,
95  kDepth,
96  kStencil,
97  };
98  [[nodiscard]] bool SetAsFramebufferAttachment(GLenum target,
99  AttachmentType attachment_type,
100  uint32_t mip_level = 0,
101  uint32_t slice = 0);
102 
103  Type GetType() const;
104 
105  bool IsWrapped() const;
106 
107  /// @brief Reset the internal texture state so that the reactor will not free
108  /// the associated handle.
109  void Leak();
110 
111  std::optional<GLuint> GetFBO() const;
112 
113  //----------------------------------------------------------------------------
114  /// @brief Indicates that all texture storage has already been allocated
115  /// and contents initialized.
116  ///
117  /// This is similar to calling `MarkSliceInitialized` with all
118  /// slices.
119  ///
120  /// @see MarkSliceInitialized.
121  ///
123 
124  //----------------------------------------------------------------------------
125  /// @brief Indicates that a specific texture slice has been initialized.
126  ///
127  /// @param[in] slice The slice to mark as being initialized.
128  ///
129  void MarkSliceInitialized(size_t slice);
130 
131  bool IsSliceInitialized(size_t slice) const;
132 
133  //----------------------------------------------------------------------------
134  /// @brief Indicates that storage for `mip_level` of `slice` has been
135  /// allocated by a `glTexImage2D` call (or equivalent).
136  ///
137  /// GLES raises `GL_INVALID_OPERATION` when `glTexSubImage2D`
138  /// targets a level that has not been previously defined, so
139  /// every per-level upload must check this first and allocate
140  /// on demand.
141  ///
142  /// @param[in] slice The slice (cubemap face for cubemaps, otherwise
143  /// always 0).
144  /// @param[in] mip_level The mip level whose storage was allocated.
145  ///
146  void MarkSliceMipLevelInitialized(size_t slice, size_t mip_level);
147 
148  bool IsSliceMipLevelInitialized(size_t slice, size_t mip_level) const;
149 
150  //----------------------------------------------------------------------------
151  /// @brief Attach a sync fence to this texture that will be waited on
152  /// before encoding a rendering operation that references it.
153  ///
154  /// @param[in] fence A handle to a sync fence.
155  ///
156  void SetFence(HandleGLES fence);
157 
158  /// Store the FBO object for recycling in the 2D renderer.
159  ///
160  /// The color0 texture used by the 2D renderer will use this texture
161  /// object to store the associated FBO the first time it is used.
162  void SetCachedFBO(HandleGLES fbo);
163 
164  /// Retrieve the cached FBO object, or a dead handle if there is no object.
165  const HandleGLES& GetCachedFBO() const;
166 
167  /// Records the subresource the cached FBO is currently bound to.
168  void SetCachedFBOSubresource(uint32_t mip_level, uint32_t slice);
169 
170  /// Whether the cached FBO is currently bound to `(mip_level, slice)`. When
171  /// false, the FBO must be re-attached before use.
172  bool CachedFBOMatchesSubresource(uint32_t mip_level, uint32_t slice) const;
173 
174  // Visible for testing.
175  std::optional<HandleGLES> GetSyncFence() const;
176 
177  // visible for testing
178  Type ComputeTypeForBinding(GLenum target) const;
179 
180  private:
181  std::shared_ptr<ReactorGLES> reactor_;
182  const Type type_;
183  UniqueHandleGLES handle_;
184  UniqueHandleGLES fence_;
185  // Tracks which `(slice, mip_level)` pairs have had their storage allocated
186  // by a `glTexImage2D` call. Allocation is performed lazily on first write
187  // to a level so the only-renders-then-mipmaps path (Impeller's snapshot
188  // pipeline) keeps its single base-level allocation, and per-level uploads
189  // only pay for the levels they actually touch.
190  //
191  // Sized for up to 6 cubemap faces × 16 mip levels (covers a 32k base
192  // dimension); requested levels above this are simply not tracked.
193  static constexpr size_t kMaxTrackedMipLevels = 16;
194  std::array<std::bitset<kMaxTrackedMipLevels>, 6> slice_mip_initialized_ = {};
195  const bool is_wrapped_;
196  const std::optional<GLuint> wrapped_fbo_;
197  UniqueHandleGLES cached_fbo_;
198  uint32_t cached_fbo_mip_level_ = 0;
199  uint32_t cached_fbo_slice_ = 0;
200  bool is_valid_ = false;
201 
202  TextureGLES(std::shared_ptr<ReactorGLES> reactor,
203  TextureDescriptor desc,
204  bool threadsafe,
205  std::optional<GLuint> fbo,
206  std::optional<HandleGLES> external_handle);
207 
208  // |Texture|
209  void SetLabel(std::string_view label) override;
210 
211  // |Texture|
212  void SetLabel(std::string_view label, std::string_view trailing) override;
213 
214  // |Texture|
215  bool OnSetContents(const uint8_t* contents,
216  size_t length,
217  size_t slice) override;
218 
219  // |Texture|
220  bool OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
221  size_t slice) override;
222 
223  // |Texture|
224  ISize GetSize() const override;
225 
226  void InitializeContentsIfNecessary();
227 
228  // Allocates storage for `(slice, mip_level)` if it has not been allocated
229  // yet, so the subresource can be attached to a framebuffer. Returns false on
230  // failure.
231  bool EnsureSliceMipLevelStorage(size_t slice, size_t mip_level);
232 
233  TextureGLES(const TextureGLES&) = delete;
234 
235  TextureGLES& operator=(const TextureGLES&) = delete;
236 };
237 
238 } // namespace impeller
239 
240 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_TEXTURE_GLES_H_
Represents a handle to an underlying OpenGL object. Unlike OpenGL object handles, these handles can b...
Definition: handle_gles.h:42
void MarkSliceInitialized(size_t slice)
Indicates that a specific texture slice has been initialized.
static std::shared_ptr< TextureGLES > WrapFBO(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc, GLuint fbo)
Create a texture by wrapping an external framebuffer object whose lifecycle is owned by the caller.
Definition: texture_gles.cc:95
void MarkContentsInitialized()
Indicates that all texture storage has already been allocated and contents initialized.
const HandleGLES & GetCachedFBO() const
Retrieve the cached FBO object, or a dead handle if there is no object.
std::optional< HandleGLES > GetSyncFence() const
bool IsSliceMipLevelInitialized(size_t slice, size_t mip_level) const
bool CachedFBOMatchesSubresource(uint32_t mip_level, uint32_t slice) const
bool IsSliceInitialized(size_t slice) const
void SetCachedFBOSubresource(uint32_t mip_level, uint32_t slice)
Records the subresource the cached FBO is currently bound to.
void MarkSliceMipLevelInitialized(size_t slice, size_t mip_level)
Indicates that storage for mip_level of slice has been allocated by a glTexImage2D call (or equivalen...
bool IsValid() const override
void SetFence(HandleGLES fence)
Attach a sync fence to this texture that will be waited on before encoding a rendering operation that...
void Leak()
Reset the internal texture state so that the reactor will not free the associated handle.
void SetCachedFBO(HandleGLES fbo)
TextureGLES(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc, bool threadsafe=false)
static std::shared_ptr< TextureGLES > CreatePlaceholder(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc)
Create a "texture" that is never expected to be bound/unbound explicitly or initialized in any way....
bool SetAsFramebufferAttachment(GLenum target, AttachmentType attachment_type, uint32_t mip_level=0, uint32_t slice=0)
std::optional< GLuint > GetFBO() const
Type ComputeTypeForBinding(GLenum target) const
std::optional< GLuint > GetGLHandle() const
static std::shared_ptr< TextureGLES > WrapTexture(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc, HandleGLES external_handle)
Create a texture by wrapping an external OpenGL texture handle. Ownership of the texture handle is as...
bool IsWrapped() const
A unique handle to an OpenGL object. The collection of this handle scheduled the destruction of the a...
ISize64 ISize
Definition: size.h:162
std::shared_ptr< ReactorGLES > reactor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...