Flutter Impeller
color_source_contents.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_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_
6 #define FLUTTER_IMPELLER_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_
7 
8 #include "fml/logging.h"
15 
16 namespace impeller {
17 
18 //------------------------------------------------------------------------------
19 /// Color sources are geometry-ignostic `Contents` capable of shading any area
20 /// defined by an `impeller::Geometry`. Conceptually,
21 /// `impeller::ColorSourceContents` implement a particular color shading
22 /// behavior.
23 ///
24 /// This separation of concerns between geometry and color source output allows
25 /// Impeller to handle most possible draw combinations in a consistent way.
26 /// For example: There are color sources for handling solid colors, gradients,
27 /// textures, custom runtime effects, and even 3D scenes.
28 ///
29 /// There are some special rendering exceptions that deviate from this pattern
30 /// and cross geometry and color source concerns, such as text atlas and image
31 /// atlas rendering. Special `Contents` exist for rendering these behaviors
32 /// which don't implement `ColorSourceContents`.
33 ///
34 /// @see `impeller::Geometry`
35 ///
36 class ColorSourceContents : public Contents {
37  public:
39 
40  ~ColorSourceContents() override;
41 
42  //----------------------------------------------------------------------------
43  /// @brief Set the geometry that this contents will use to render.
44  ///
45  void SetGeometry(std::shared_ptr<Geometry> geometry);
46 
47  //----------------------------------------------------------------------------
48  /// @brief Get the geometry that this contents will use to render.
49  ///
50  const std::shared_ptr<Geometry>& GetGeometry() const;
51 
52  //----------------------------------------------------------------------------
53  /// @brief Set the effect transform for this color source.
54  ///
55  /// The effect transform is a transform matrix that is applied to
56  /// the shaded color output and does not impact geometry in any way.
57  ///
58  /// For example: With repeat tiling, any gradient or
59  /// `TiledTextureContents` could be used with an effect transform to
60  /// inexpensively draw an infinite scrolling background pattern.
61  ///
62  void SetEffectTransform(Matrix matrix);
63 
64  //----------------------------------------------------------------------------
65  /// @brief Set the inverted effect transform for this color source.
66  ///
67  /// When the effect transform is set via `SetEffectTransform`, the
68  /// value is inverted upon storage. The reason for this is that most
69  /// color sources internally use the inverted transform.
70  ///
71  /// @return The inverse of the transform set by `SetEffectTransform`.
72  ///
73  /// @see `SetEffectTransform`
74  ///
75  const Matrix& GetInverseEffectTransform() const;
76 
77  //----------------------------------------------------------------------------
78  /// @brief Set the opacity factor for this color source.
79  ///
80  void SetOpacityFactor(Scalar opacity);
81 
82  //----------------------------------------------------------------------------
83  /// @brief Get the opacity factor for this color source.
84  ///
85  /// This value is is factored into the output of the color source in
86  /// addition to opacity information that may be supplied any other
87  /// inputs.
88  ///
89  /// @note If set, the output of this method factors factors in the inherited
90  /// opacity of this `Contents`.
91  ///
92  /// @see `Contents::CanInheritOpacity`
93  ///
94  Scalar GetOpacityFactor() const;
95 
96  virtual bool IsSolidColor() const;
97 
98  // |Contents|
99  std::optional<Rect> GetCoverage(const Entity& entity) const override;
100 
101  // |Contents|
102  bool CanInheritOpacity(const Entity& entity) const override;
103 
104  // |Contents|
105  void SetInheritedOpacity(Scalar opacity) override;
106 
107  protected:
108  using BindFragmentCallback = std::function<bool(RenderPass& pass)>;
109  using PipelineBuilderMethod = std::shared_ptr<Pipeline<PipelineDescriptor>> (
112  std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>(
114 
115  template <typename VertexShaderT>
116  bool DrawGeometry(const ContentContext& renderer,
117  const Entity& entity,
118  RenderPass& pass,
119  const PipelineBuilderCallback& pipeline_callback,
120  typename VertexShaderT::FrameInfo frame_info,
121  const BindFragmentCallback& bind_fragment_callback,
122  bool enable_uvs = false,
123  Rect texture_coverage = {},
124  const Matrix& effect_transform = {}) const {
125  auto options = OptionsFromPassAndEntity(pass, entity);
126 
127  GeometryResult::Mode geometry_mode = GetGeometry()->GetResultMode();
128  Geometry& geometry = *GetGeometry();
129 
130  const bool is_stencil_then_cover =
131  geometry_mode == GeometryResult::Mode::kNonZero ||
132  geometry_mode == GeometryResult::Mode::kEvenOdd;
133  if (is_stencil_then_cover) {
134  pass.SetStencilReference(0);
135 
136  /// Stencil preparation draw.
137 
138  GeometryResult stencil_geometry_result =
139  GetGeometry()->GetPositionBuffer(renderer, entity, pass);
140  if (stencil_geometry_result.vertex_buffer.vertex_count == 0u) {
141  return true;
142  }
143  pass.SetVertexBuffer(std::move(stencil_geometry_result.vertex_buffer));
144  options.primitive_type = stencil_geometry_result.type;
145 
146  options.blend_mode = BlendMode::kDestination;
147  switch (stencil_geometry_result.mode) {
149  pass.SetCommandLabel("Stencil preparation (NonZero)");
150  options.stencil_mode =
152  break;
154  pass.SetCommandLabel("Stencil preparation (EvenOdd)");
155  options.stencil_mode =
157  break;
158  default:
159  FML_UNREACHABLE();
160  }
161  pass.SetPipeline(renderer.GetClipPipeline(options));
162  ClipPipeline::VertexShader::FrameInfo clip_frame_info;
163  clip_frame_info.depth = entity.GetShaderClipDepth();
164  clip_frame_info.mvp = stencil_geometry_result.transform;
165  ClipPipeline::VertexShader::BindFrameInfo(
166  pass, renderer.GetTransientsBuffer().EmplaceUniform(clip_frame_info));
167 
168  if (!pass.Draw().ok()) {
169  return false;
170  }
171 
172  /// Cover draw.
173 
174  options.blend_mode = entity.GetBlendMode();
176  std::optional<Rect> maybe_cover_area = GetGeometry()->GetCoverage({});
177  if (!maybe_cover_area.has_value()) {
178  return true;
179  }
180  geometry = RectGeometry(maybe_cover_area.value());
181  }
182 
183  GeometryResult geometry_result =
184  enable_uvs
185  ? geometry.GetPositionUVBuffer(texture_coverage, effect_transform,
186  renderer, entity, pass)
187  : geometry.GetPositionBuffer(renderer, entity, pass);
188  if (geometry_result.vertex_buffer.vertex_count == 0u) {
189  return true;
190  }
191  pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));
192  options.primitive_type = geometry_result.type;
193 
194  // Take the pre-populated vertex shader uniform struct and set managed
195  // values.
196  frame_info.mvp = geometry_result.transform;
197 
198  // If overdraw prevention is enabled (like when drawing stroke paths), we
199  // increment the stencil buffer as we draw, preventing overlapping fragments
200  // from drawing. Afterwards, we need to append another draw call to clean up
201  // the stencil buffer (happens below in this method).
202  if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw) {
203  options.stencil_mode =
205  }
207  pass.SetStencilReference(0);
208  } else {
209  pass.SetStencilReference(entity.GetClipDepth());
210  }
211 
212  VertexShaderT::BindFrameInfo(
213  pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
214 
215  // The reason we need to have a callback mechanism here is that this routine
216  // may insert draw calls before the main draw call below. For example, for
217  // sufficiently complex paths we may opt to use stencil-then-cover to avoid
218  // tessellation.
219  if (!bind_fragment_callback(pass)) {
220  return false;
221  }
222 
223  pass.SetPipeline(pipeline_callback(options));
224 
225  if (!pass.Draw().ok()) {
226  return false;
227  }
228 
229  // If we performed overdraw prevention, a subsection of the clip heightmap
230  // was incremented by 1 in order to self-clip. So simply append a clip
231  // restore to clean it up.
232  if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw) {
233  auto restore = ClipRestoreContents();
234  restore.SetRestoreCoverage(GetCoverage(entity));
236  Entity restore_entity = entity.Clone();
237  restore_entity.SetClipDepth(0);
238  return restore.Render(renderer, restore_entity, pass);
239  } else {
240  return restore.Render(renderer, entity, pass);
241  }
242  }
243  return true;
244  }
245 
246  private:
247  std::shared_ptr<Geometry> geometry_;
248  Matrix inverse_matrix_;
249  Scalar opacity_ = 1.0;
250  Scalar inherited_opacity_ = 1.0;
251 
252  ColorSourceContents(const ColorSourceContents&) = delete;
253 
254  ColorSourceContents& operator=(const ColorSourceContents&) = delete;
255 };
256 
257 } // namespace impeller
258 
259 #endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_
impeller::ColorSourceContents::PipelineBuilderCallback
std::function< std::shared_ptr< Pipeline< PipelineDescriptor > >(ContentContextOptions)> PipelineBuilderCallback
Definition: color_source_contents.h:113
impeller::Entity::SetClipDepth
void SetClipDepth(uint32_t clip_depth)
Definition: entity.cc:101
impeller::ColorSourceContents::GetOpacityFactor
Scalar GetOpacityFactor() const
Get the opacity factor for this color source.
Definition: color_source_contents.cc:28
contents.h
impeller::ColorSourceContents::IsSolidColor
virtual bool IsSolidColor() const
Definition: color_source_contents.cc:40
impeller::ColorSourceContents::SetInheritedOpacity
void SetInheritedOpacity(Scalar opacity) override
Inherit the provided opacity.
Definition: color_source_contents.cc:53
impeller::Entity::GetShaderClipDepth
float GetShaderClipDepth() const
Definition: entity.cc:117
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::ColorSourceContents::SetGeometry
void SetGeometry(std::shared_ptr< Geometry > geometry)
Set the geometry that this contents will use to render.
Definition: color_source_contents.cc:16
impeller::ColorSourceContents::SetEffectTransform
void SetEffectTransform(Matrix matrix)
Set the effect transform for this color source.
Definition: color_source_contents.cc:32
impeller::ColorSourceContents::DrawGeometry
bool DrawGeometry(const ContentContext &renderer, const Entity &entity, RenderPass &pass, const PipelineBuilderCallback &pipeline_callback, typename VertexShaderT::FrameInfo frame_info, const BindFragmentCallback &bind_fragment_callback, bool enable_uvs=false, Rect texture_coverage={}, const Matrix &effect_transform={}) const
Definition: color_source_contents.h:116
impeller::BlendMode::kDestination
@ kDestination
impeller::ContentContext::GetClipPipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > GetClipPipeline(ContentContextOptions opts) const
Definition: content_context.h:566
impeller::RenderPass::SetVertexBuffer
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
Definition: render_pass.cc:123
impeller::ColorSourceContents::GetGeometry
const std::shared_ptr< Geometry > & GetGeometry() const
Get the geometry that this contents will use to render.
Definition: color_source_contents.cc:20
impeller::ColorSourceContents::CanInheritOpacity
bool CanInheritOpacity(const Entity &entity) const override
Whether or not this contents can accept the opacity peephole optimization.
Definition: color_source_contents.cc:49
rect_geometry.h
impeller::ColorSourceContents::ColorSourceContents
ColorSourceContents()
impeller::ContentContextOptions::StencilMode::kStencilEvenOddFill
@ kStencilEvenOddFill
impeller::GeometryResult::Mode::kEvenOdd
@ kEvenOdd
impeller::RenderPass::SetCommandLabel
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
Definition: render_pass.cc:97
impeller::GeometryResult::Mode
Mode
Definition: geometry.h:21
impeller::RenderPass::Draw
virtual fml::Status Draw()
Record the currently pending command.
Definition: render_pass.cc:127
impeller::ContentContext::kEnableStencilThenCover
static constexpr bool kEnableStencilThenCover
Definition: content_context.h:411
matrix.h
impeller::Entity
Definition: entity.h:21
impeller::OptionsFromPassAndEntity
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition: contents.cc:37
impeller::ColorSourceContents::~ColorSourceContents
~ColorSourceContents() override
impeller::ContentContextOptions::StencilMode::kLegacyClipIncrement
@ kLegacyClipIncrement
Increment the stencil heightmap.
impeller::ContentContextOptions::StencilMode::kStencilNonZeroFill
@ kStencilNonZeroFill
geometry.h
clip_contents.h
impeller::RenderPass::SetStencilReference
virtual void SetStencilReference(uint32_t value)
Definition: render_pass.cc:103
impeller::Entity::GetBlendMode
BlendMode GetBlendMode() const
Definition: entity.cc:134
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:33
impeller::Entity::GetClipDepth
uint32_t GetClipDepth() const
Definition: entity.cc:105
impeller::ColorSourceContents::PipelineBuilderMethod
std::shared_ptr< Pipeline< PipelineDescriptor > >(impeller::ContentContext::*)(ContentContextOptions) const PipelineBuilderMethod
Definition: color_source_contents.h:110
content_context.h
impeller::ColorSourceContents::GetCoverage
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
Definition: color_source_contents.cc:44
impeller::ColorSourceContents::BindFragmentCallback
std::function< bool(RenderPass &pass)> BindFragmentCallback
Definition: color_source_contents.h:108
impeller::Entity::Clone
Entity Clone() const
Definition: entity.cc:210
impeller::HostBuffer::EmplaceUniform
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
Definition: host_buffer.h:50
impeller::GeometryResult::Mode::kPreventOverdraw
@ kPreventOverdraw
impeller::RenderPass::SetPipeline
virtual void SetPipeline(const std::shared_ptr< Pipeline< PipelineDescriptor >> &pipeline)
The pipeline to use for this command.
Definition: render_pass.cc:92
impeller::ContentContextOptions::StencilMode::kCoverCompare
@ kCoverCompare
impeller::ColorSourceContents::SetOpacityFactor
void SetOpacityFactor(Scalar opacity)
Set the opacity factor for this color source.
Definition: color_source_contents.cc:24
impeller::Contents
Definition: contents.h:34
impeller::ColorSourceContents
Definition: color_source_contents.h:36
impeller::ContentContextOptions
Definition: content_context.h:288
impeller
Definition: aiks_blur_unittests.cc:20
impeller::ContentContext
Definition: content_context.h:392
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::ColorSourceContents::GetInverseEffectTransform
const Matrix & GetInverseEffectTransform() const
Set the inverted effect transform for this color source.
Definition: color_source_contents.cc:36
impeller::ContentContext::GetTransientsBuffer
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
Definition: content_context.h:833
impeller::GeometryResult::Mode::kNonZero
@ kNonZero