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