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