| 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"
9 #include "impeller/entity/contents/clip_contents.h"
10 #include "impeller/entity/contents/content_context.h"
11 #include "impeller/entity/contents/contents.h"
12 #include "impeller/entity/geometry/geometry.h"
13 #include "impeller/entity/geometry/rect_geometry.h"
14 #include "impeller/geometry/matrix.h"
15 #include "impeller/renderer/render_pass.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:
39 ColorSourceContents();
40
41 ~ColorSourceContents() override;
42
43 //----------------------------------------------------------------------------
44 /// @brief Set the geometry that this contents will use to render.
45 ///
46 void SetGeometry(const Geometry* geometry);
47
48 //----------------------------------------------------------------------------
49 /// @brief Get the geometry that this contents will use to render.
50 ///
51 const 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 Scalar GetOpacityFactor() const;
93
94 virtual bool IsSolidColor() const;
95
96 // |Contents|
97 std::optional<Rect> GetCoverage(const Entity& entity) const override;
98
99 // |Contents|
100 void SetInheritedOpacity(Scalar opacity) override;
101
102 protected:
103 using BindFragmentCallback = std::function<bool(RenderPass& pass)>;
104 using PipelineBuilderMethod = std::shared_ptr<Pipeline<PipelineDescriptor>> (
105 impeller::ContentContext::*)(ContentContextOptions) const;
106 using PipelineBuilderCallback =
107 std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>(
108 ContentContextOptions)>;
109 using CreateGeometryCallback =
110 std::function<GeometryResult(const ContentContext& renderer,
111 const Entity& entity,
112 RenderPass& pass,
113 const Geometry* geom)>;
114
115 static GeometryResult DefaultCreateGeometryCallback(
116 const ContentContext& renderer,
117 const Entity& entity,
118 RenderPass& pass,
119 const Geometry* geom) {
120 return geom->GetPositionBuffer(renderer, entity, pass);
121 }
122
123 /// @brief Whether the entity should be treated as non-opaque due to stroke
124 /// geometry requiring alpha for coverage.
125 bool AppliesAlphaForStrokeCoverage(const Matrix& transform) const;
126
127 template <typename VertexShaderT>
128 bool DrawGeometry(const ContentContext& renderer,
129 const Entity& entity,
130 RenderPass& pass,
131 const PipelineBuilderCallback& pipeline_callback,
132 typename VertexShaderT::FrameInfo frame_info,
133 const BindFragmentCallback& bind_fragment_callback,
134 bool force_stencil = false,
135 const CreateGeometryCallback& create_geom_callback =
136 DefaultCreateGeometryCallback) const {
137 auto options = OptionsFromPassAndEntity(pass, entity);
138
139 GeometryResult::Mode geometry_mode = GetGeometry()->GetResultMode();
140 bool do_cover_draw = false;
141 Rect cover_area = {};
142
143 bool is_stencil_then_cover =
144 geometry_mode == GeometryResult::Mode::kNonZero ||
145 geometry_mode == GeometryResult::Mode::kEvenOdd;
146 if (!is_stencil_then_cover && force_stencil) {
147 geometry_mode = GeometryResult::Mode::kNonZero;
148 is_stencil_then_cover = true;
149 }
150
151 if (is_stencil_then_cover) {
152 pass.SetStencilReference(0);
153
154 /// Stencil preparation draw.
155
156 GeometryResult stencil_geometry_result =
157 GetGeometry()->GetPositionBuffer(renderer, entity, pass);
158 if (stencil_geometry_result.vertex_buffer.vertex_count == 0u) {
159 return true;
160 }
161 pass.SetVertexBuffer(std::move(stencil_geometry_result.vertex_buffer));
162 options.primitive_type = stencil_geometry_result.type;
163
164 options.blend_mode = BlendMode::kDestination;
165 switch (stencil_geometry_result.mode) {
166 case GeometryResult::Mode::kNonZero:
167 pass.SetCommandLabel("Stencil preparation (NonZero)");
168 options.stencil_mode =
169 ContentContextOptions::StencilMode::kStencilNonZeroFill;
170 break;
171 case GeometryResult::Mode::kEvenOdd:
172 pass.SetCommandLabel("Stencil preparation (EvenOdd)");
173 options.stencil_mode =
174 ContentContextOptions::StencilMode::kStencilEvenOddFill;
175 break;
176 default:
177 if (force_stencil) {
178 pass.SetCommandLabel("Stencil preparation (NonZero)");
179 options.stencil_mode =
180 ContentContextOptions::StencilMode::kStencilNonZeroFill;
181 break;
182 }
183 FML_UNREACHABLE();
184 }
185 pass.SetPipeline(renderer.GetClipPipeline(options));
186 ClipPipeline::VertexShader::FrameInfo clip_frame_info;
187 clip_frame_info.depth = entity.GetShaderClipDepth();
188 clip_frame_info.mvp = stencil_geometry_result.transform;
189 ClipPipeline::VertexShader::BindFrameInfo(
190 pass, renderer.GetTransientsBuffer().EmplaceUniform(clip_frame_info));
191
192 if (!pass.Draw().ok()) {
193 return false;
194 }
195
196 /// Cover draw.
197
198 options.blend_mode = entity.GetBlendMode();
199 options.stencil_mode = ContentContextOptions::StencilMode::kCoverCompare;
200 std::optional<Rect> maybe_cover_area = GetGeometry()->GetCoverage({});
201 if (!maybe_cover_area.has_value()) {
202 return true;
203 }
204 do_cover_draw = true;
205 cover_area = maybe_cover_area.value();
206 }
207
208 GeometryResult geometry_result;
209 if (do_cover_draw) {
210 RectGeometry geom(cover_area);
211 geometry_result = create_geom_callback(renderer, entity, pass, &geom);
212 } else {
213 geometry_result =
214 create_geom_callback(renderer, entity, pass, GetGeometry());
215 }
216
217 if (geometry_result.vertex_buffer.vertex_count == 0u) {
218 return true;
219 }
220 pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));
221 options.primitive_type = geometry_result.type;
222
223 // Enable depth writing for all opaque entities in order to allow
224 // reordering. Opaque entities are coerced to source blending by
225 // `EntityPass::AddEntity`.
226 options.depth_write_enabled = options.blend_mode == BlendMode::kSource;
227
228 // Take the pre-populated vertex shader uniform struct and set managed
229 // values.
230 frame_info.mvp = geometry_result.transform;
231
232 // If overdraw prevention is enabled (like when drawing stroke paths), we
233 // increment the stencil buffer as we draw, preventing overlapping fragments
234 // from drawing. Afterwards, we need to append another draw call to clean up
235 // the stencil buffer (happens below in this method).
236 if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw) {
237 options.stencil_mode =
238 ContentContextOptions::StencilMode::kOverdrawPreventionIncrement;
239 }
240 pass.SetStencilReference(0);
241
242 VertexShaderT::BindFrameInfo(
243 pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
244
245 // The reason we need to have a callback mechanism here is that this routine
246 // may insert draw calls before the main draw call below. For example, for
247 // sufficiently complex paths we may opt to use stencil-then-cover to avoid
248 // tessellation.
249 if (!bind_fragment_callback(pass)) {
250 return false;
251 }
252
253 pass.SetPipeline(pipeline_callback(options));
254
255 if (!pass.Draw().ok()) {
256 return false;
257 }
258
259 // If we performed overdraw prevention, a subsection of the clip heightmap
260 // was incremented by 1 in order to self-clip. So simply append a clip
261 // restore to clean it up.
262 if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw) {
263 auto restore = ClipRestoreContents();
264 restore.SetRestoreCoverage(GetCoverage(entity));
265 Entity restore_entity = entity.Clone();
266 return restore.Render(renderer, restore_entity, pass);
267 }
268 return true;
269 }
270
271 private:
272 const Geometry* geometry_ = nullptr;
273 Matrix inverse_matrix_;
274 Scalar opacity_ = 1.0;
275 Scalar inherited_opacity_ = 1.0;
276
277 ColorSourceContents(const ColorSourceContents&) = delete;
278
279 ColorSourceContents& operator=(const ColorSourceContents&) = delete;
280 };
281
282 } // namespace impeller
283
284 #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:108
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:49
impeller::Entity::GetShaderClipDepth
float GetShaderClipDepth() const
Definition: entity.cc:99
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::ColorSourceContents::SetEffectTransform
void SetEffectTransform(Matrix matrix)
Set the effect transform for this color source.
Definition: color_source_contents.cc:32
geometry.h
impeller::ContentContextOptions::StencilMode::kOverdrawPreventionIncrement
@ kOverdrawPreventionIncrement
impeller::Geometry::GetCoverage
virtual std::optional< Rect > GetCoverage(const Matrix &transform) const =0
impeller::BlendMode::kSource
@ kSource
impeller::BlendMode::kDestination
@ kDestination
impeller::ContentContext::GetClipPipeline
std::shared_ptr< Pipeline< PipelineDescriptor > > GetClipPipeline(ContentContextOptions opts) const
Definition: content_context.h:492
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::DefaultCreateGeometryCallback
static GeometryResult DefaultCreateGeometryCallback(const ContentContext &renderer, const Entity &entity, RenderPass &pass, const Geometry *geom)
Definition: color_source_contents.h:115
rect_geometry.h
impeller::Geometry::GetResultMode
virtual GeometryResult::Mode GetResultMode() const
Definition: geometry.cc:56
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:27
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:156
impeller::ColorSourceContents::SetGeometry
void SetGeometry(const Geometry *geometry)
Set the geometry that this contents will use to render.
Definition: color_source_contents.cc:16
impeller::GeometryResult::type
PrimitiveType type
Definition: geometry.h:42
impeller::Geometry::GetPositionBuffer
virtual GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const =0
transform
Matrix transform
Definition: gaussian_blur_filter_contents.cc:213
impeller::ContentContextOptions::StencilMode::kStencilNonZeroFill
@ kStencilNonZeroFill
impeller::RectGeometry
Definition: rect_geometry.h:12
impeller::GeometryResult
Definition: geometry.h:26
clip_contents.h
impeller::ColorSourceContents::CreateGeometryCallback
std::function< GeometryResult(const ContentContext &renderer, const Entity &entity, RenderPass &pass, const Geometry *geom)> CreateGeometryCallback
Definition: color_source_contents.h:113
impeller::RenderPass::SetStencilReference
virtual void SetStencilReference(uint32_t value)
Definition: render_pass.cc:103
impeller::ClipRestoreContents
Definition: clip_contents.h:49
impeller::Entity::GetBlendMode
BlendMode GetBlendMode() const
Definition: entity.cc:112
impeller::ColorSourceContents::GetGeometry
const Geometry * GetGeometry() const
Get the geometry that this contents will use to render.
Definition: color_source_contents.cc:20
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:105
impeller::GeometryResult::transform
Matrix transform
Definition: geometry.h:44
content_context.h
impeller::Geometry
Definition: geometry.h:55
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:128
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:103
impeller::Entity::Clone
Entity Clone() const
Definition: entity.cc:170
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::AppliesAlphaForStrokeCoverage
bool AppliesAlphaForStrokeCoverage(const Matrix &transform) const
Whether the entity should be treated as non-opaque due to stroke geometry requiring alpha for coverag...
Definition: color_source_contents.cc:53
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:43
impeller::Contents
Definition: contents.h:31
impeller::ColorSourceContents
Definition: color_source_contents.h:37
impeller::ContentContextOptions
Definition: content_context.h:254
impeller
Definition: allocation.cc:12
impeller::ContentContext
Definition: content_context.h:366
impeller::TRect< Scalar >
impeller::GeometryResult::mode
Mode mode
Definition: geometry.h:45
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:753
impeller::GeometryResult::Mode::kNonZero
@ kNonZero