Flutter Engine
The Flutter Engine
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
17namespace 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///
38 public:
40
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 ///
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 ///
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:
110 using PipelineBuilderMethod = std::shared_ptr<Pipeline<PipelineDescriptor>> (
113 std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>(
117 const Entity& entity,
118 RenderPass& pass,
119 const Geometry& geom)>;
120
123 const Entity& entity,
124 RenderPass& pass,
125 const Geometry& geom) {
126 return geom.GetPositionBuffer(renderer, entity, pass);
127 }
128
129 template <typename VertexShaderT>
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 }
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
266
267 ColorSourceContents& operator=(const ColorSourceContents&) = delete;
268};
269
270} // namespace impeller
271
272#endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_
const char * options
bool ok() const
Definition: status.h:71
void SetInheritedOpacity(Scalar opacity) override
Inherit the provided opacity.
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
Scalar GetOpacityFactor() const
Get the opacity factor for this color source.
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.
std::function< std::shared_ptr< Pipeline< PipelineDescriptor > >(ContentContextOptions)> PipelineBuilderCallback
std::shared_ptr< Pipeline< PipelineDescriptor > >(impeller::ContentContext::*)(ContentContextOptions) const PipelineBuilderMethod
void SetEffectTransform(Matrix matrix)
Set the effect transform for this color source.
bool CanInheritOpacity(const Entity &entity) const override
Whether or not this contents can accept the opacity peephole optimization.
std::function< GeometryResult(const ContentContext &renderer, const Entity &entity, RenderPass &pass, const Geometry &geom)> CreateGeometryCallback
const Matrix & GetInverseEffectTransform() const
Set the inverted effect transform for this color source.
std::function< bool(RenderPass &pass)> BindFragmentCallback
void SetOpacityFactor(Scalar opacity)
Set the opacity factor for this color source.
void SetGeometry(std::shared_ptr< Geometry > geometry)
Set the geometry that this contents will use to render.
const std::shared_ptr< Geometry > & GetGeometry() const
Get the geometry that this contents will use to render.
static GeometryResult DefaultCreateGeometryCallback(const ContentContext &renderer, const Entity &entity, RenderPass &pass, const Geometry &geom)
BlendMode GetBlendMode() const
Definition: entity.cc:119
bool Render(const ContentContext &renderer, RenderPass &parent_pass) const
Definition: entity.cc:173
Entity Clone() const
Definition: entity.cc:191
float GetShaderClipDepth() const
Definition: entity.cc:106
virtual GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const =0
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:33
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
Definition: render_pass.cc:123
virtual void SetStencilReference(uint32_t value)
Definition: render_pass.cc:103
virtual void SetPipeline(const std::shared_ptr< Pipeline< PipelineDescriptor > > &pipeline)
The pipeline to use for this command.
Definition: render_pass.cc:92
virtual fml::Status Draw()
Record the currently pending command.
Definition: render_pass.cc:127
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
Definition: render_pass.cc:97
#define FML_UNREACHABLE()
Definition: logging.h:109
Dart_NativeFunction function
Definition: fuchsia.cc:51
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
float Scalar
Definition: scalar.h:18
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition: contents.cc:34
PrimitiveType type
Definition: geometry.h:35
VertexBuffer vertex_buffer
Definition: geometry.h:36
A 4x4 matrix using column-major storage.
Definition: matrix.h:37