Flutter Engine
 
Loading...
Searching...
No Matches
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"
17
18namespace impeller {
19
20//------------------------------------------------------------------------------
21/// Color sources are geometry-ignostic `Contents` capable of shading any area
22/// defined by an `impeller::Geometry`. Conceptually,
23/// `impeller::ColorSourceContents` implement a particular color shading
24/// behavior.
25///
26/// This separation of concerns between geometry and color source output allows
27/// Impeller to handle most possible draw combinations in a consistent way.
28/// For example: There are color sources for handling solid colors, gradients,
29/// textures, custom runtime effects, and even 3D scenes.
30///
31/// There are some special rendering exceptions that deviate from this pattern
32/// and cross geometry and color source concerns, such as text atlas and image
33/// atlas rendering. Special `Contents` exist for rendering these behaviors
34/// which don't implement `ColorSourceContents`.
35///
36/// @see `impeller::Geometry`
37///
39 public:
40 using BindFragmentCallback = std::function<bool(RenderPass& pass)>;
42 std::function<PipelineRef(ContentContextOptions)>;
44 std::function<GeometryResult(const ContentContext& renderer,
45 const Entity& entity,
46 RenderPass& pass,
47 const Geometry* geom)>;
48
50
52
53 //----------------------------------------------------------------------------
54 /// @brief Set the geometry that this contents will use to render.
55 ///
56 void SetGeometry(const Geometry* geometry);
57
58 //----------------------------------------------------------------------------
59 /// @brief Get the geometry that this contents will use to render.
60 ///
61 const Geometry* GetGeometry() const;
62
63 //----------------------------------------------------------------------------
64 /// @brief Set the effect transform for this color source.
65 ///
66 /// The effect transform is a transform matrix that is applied to
67 /// the shaded color output and does not impact geometry in any way.
68 ///
69 /// For example: With repeat tiling, any gradient or
70 /// `TiledTextureContents` could be used with an effect transform to
71 /// inexpensively draw an infinite scrolling background pattern.
72 ///
73 void SetEffectTransform(Matrix matrix);
74
75 //----------------------------------------------------------------------------
76 /// @brief Set the inverted effect transform for this color source.
77 ///
78 /// When the effect transform is set via `SetEffectTransform`, the
79 /// value is inverted upon storage. The reason for this is that most
80 /// color sources internally use the inverted transform.
81 ///
82 /// @return The inverse of the transform set by `SetEffectTransform`.
83 ///
84 /// @see `SetEffectTransform`
85 ///
86 const Matrix& GetInverseEffectTransform() const;
87
88 //----------------------------------------------------------------------------
89 /// @brief Set the opacity factor for this color source.
90 ///
91 void SetOpacityFactor(Scalar opacity);
92
93 //----------------------------------------------------------------------------
94 /// @brief Get the opacity factor for this color source.
95 ///
96 /// This value is is factored into the output of the color source in
97 /// addition to opacity information that may be supplied any other
98 /// inputs.
99 ///
100 /// @note If set, the output of this method factors factors in the inherited
101 /// opacity of this `Contents`.
102 Scalar GetOpacityFactor() const;
103
104 virtual bool IsSolidColor() const;
105
106 // |Contents|
107 std::optional<Rect> GetCoverage(const Entity& entity) const override;
108
109 // |Contents|
110 void SetInheritedOpacity(Scalar opacity) override;
111
112 template <typename VertexShaderT>
113 static bool DrawGeometry(const Contents* contents,
114 const Geometry* geometry,
115 const ContentContext& renderer,
116 const Entity& entity,
117 RenderPass& pass,
118 const PipelineBuilderCallback& pipeline_callback,
119 typename VertexShaderT::FrameInfo frame_info,
120 const BindFragmentCallback& bind_fragment_callback,
121 bool force_stencil = false,
122 const CreateGeometryCallback& create_geom_callback =
124 auto options = OptionsFromPassAndEntity(pass, entity);
125
126 GeometryResult::Mode geometry_mode = geometry->GetResultMode();
127 bool do_cover_draw = false;
128 Rect cover_area = {};
129
130 bool is_stencil_then_cover =
131 geometry_mode == GeometryResult::Mode::kNonZero ||
132 geometry_mode == GeometryResult::Mode::kEvenOdd;
133 if (!is_stencil_then_cover && force_stencil) {
134 geometry_mode = GeometryResult::Mode::kNonZero;
135 is_stencil_then_cover = true;
136 }
137
138 if (is_stencil_then_cover) {
139 pass.SetStencilReference(0);
140
141 /// Stencil preparation draw.
142
143 GeometryResult stencil_geometry_result =
144 geometry->GetPositionBuffer(renderer, entity, pass);
145 if (stencil_geometry_result.vertex_buffer.vertex_count == 0u) {
146 return true;
147 }
148 pass.SetVertexBuffer(std::move(stencil_geometry_result.vertex_buffer));
149 options.primitive_type = stencil_geometry_result.type;
150
151 options.blend_mode = BlendMode::kDst;
152 switch (stencil_geometry_result.mode) {
154 pass.SetCommandLabel("Stencil preparation (NonZero)");
155 options.stencil_mode =
157 break;
159 pass.SetCommandLabel("Stencil preparation (EvenOdd)");
160 options.stencil_mode =
162 break;
163 default:
164 if (force_stencil) {
165 pass.SetCommandLabel("Stencil preparation (NonZero)");
166 options.stencil_mode =
168 break;
169 }
171 }
172 pass.SetPipeline(renderer.GetClipPipeline(options));
173 ClipPipeline::VertexShader::FrameInfo clip_frame_info;
174 clip_frame_info.depth = entity.GetShaderClipDepth();
175 clip_frame_info.mvp = stencil_geometry_result.transform;
176 ClipPipeline::VertexShader::BindFrameInfo(
177 pass,
178 renderer.GetTransientsDataBuffer().EmplaceUniform(clip_frame_info));
179
180 if (!pass.Draw().ok()) {
181 return false;
182 }
183
184 /// Cover draw.
185
186 options.blend_mode = entity.GetBlendMode();
188 std::optional<Rect> maybe_cover_area = geometry->GetCoverage({});
189 if (!maybe_cover_area.has_value()) {
190 return true;
191 }
192 do_cover_draw = true;
193 cover_area = maybe_cover_area.value();
194 }
195
196 GeometryResult geometry_result;
197 if (do_cover_draw) {
198 FillRectGeometry geom(cover_area);
199 geometry_result = create_geom_callback(renderer, entity, pass, &geom);
200 } else {
201 geometry_result = create_geom_callback(renderer, entity, pass, geometry);
202 }
203
204 if (geometry_result.vertex_buffer.vertex_count == 0u) {
205 return true;
206 }
207 pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));
208 options.primitive_type = geometry_result.type;
209
210 // Enable depth writing for all opaque entities in order to allow
211 // reordering. Opaque entities are coerced to source blending by
212 // `EntityPass::AddEntity`.
213 options.depth_write_enabled = options.blend_mode == BlendMode::kSrc;
214
215 // Take the pre-populated vertex shader uniform struct and set managed
216 // values.
217 frame_info.mvp = geometry_result.transform;
218
219 // If overdraw prevention is enabled (like when drawing stroke paths), we
220 // increment the stencil buffer as we draw, preventing overlapping fragments
221 // from drawing. Afterwards, we need to append another draw call to clean up
222 // the stencil buffer (happens below in this method). This can be skipped
223 // for draws that are fully opaque or use src blend mode.
224 if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw &&
225 options.blend_mode != BlendMode::kSrc) {
226 options.stencil_mode =
228 }
229 pass.SetStencilReference(0);
230
231 VertexShaderT::BindFrameInfo(
232 pass, renderer.GetTransientsDataBuffer().EmplaceUniform(frame_info));
233
234 // The reason we need to have a callback mechanism here is that this routine
235 // may insert draw calls before the main draw call below. For example, for
236 // sufficiently complex paths we may opt to use stencil-then-cover to avoid
237 // tessellation.
238 if (!bind_fragment_callback(pass)) {
239 return false;
240 }
241
242 pass.SetPipeline(pipeline_callback(options));
243
244 if (!pass.Draw().ok()) {
245 return false;
246 }
247
248 // If we performed overdraw prevention, a subsection of the clip heightmap
249 // was incremented by 1 in order to self-clip. So simply append a clip
250 // restore to clean it up.
251 if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw &&
252 options.blend_mode != BlendMode::kSrc) {
253 return RenderClipRestore(renderer, pass, entity.GetClipDepth(),
254 contents->GetCoverage(entity));
255 }
256 return true;
257 }
258
259 protected:
261 const ContentContext& renderer,
262 const Entity& entity,
263 RenderPass& pass,
264 const Geometry* geom) {
265 return geom->GetPositionBuffer(renderer, entity, pass);
266 }
267
268 /// @brief Whether the entity should be treated as non-opaque due to stroke
269 /// geometry requiring alpha for coverage.
271
272 template <typename VertexShaderT>
273 bool DrawGeometry(const ContentContext& renderer,
274 const Entity& entity,
275 RenderPass& pass,
276 const PipelineBuilderCallback& pipeline_callback,
277 typename VertexShaderT::FrameInfo frame_info,
278 const BindFragmentCallback& bind_fragment_callback,
279 bool force_stencil = false,
280 const CreateGeometryCallback& create_geom_callback =
282 //
283 return DrawGeometry<VertexShaderT>(this, //
284 GetGeometry(), //
285 renderer, //
286 entity, //
287 pass, //
288 pipeline_callback, //
289 frame_info, //
290 bind_fragment_callback, //
291 force_stencil, //
292 create_geom_callback);
293 }
294
295 private:
296 const Geometry* geometry_ = nullptr;
297 Matrix inverse_matrix_;
298 Scalar opacity_ = 1.0;
299 Scalar inherited_opacity_ = 1.0;
300
302
303 ColorSourceContents& operator=(const ColorSourceContents&) = delete;
304};
305
306} // namespace impeller
307
308#endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_COLOR_SOURCE_CONTENTS_H_
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
const Geometry * GetGeometry() const
Get the geometry that this contents will use to render.
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< GeometryResult(const ContentContext &renderer, const Entity &entity, RenderPass &pass, const Geometry *geom)> CreateGeometryCallback
static GeometryResult DefaultCreateGeometryCallback(const ContentContext &renderer, const Entity &entity, RenderPass &pass, const Geometry *geom)
bool AppliesAlphaForStrokeCoverage(const Matrix &transform) const
Whether the entity should be treated as non-opaque due to stroke geometry requiring alpha for coverag...
void SetEffectTransform(Matrix matrix)
Set the effect transform for this color source.
const Matrix & GetInverseEffectTransform() const
Set the inverted effect transform for this color source.
static bool DrawGeometry(const Contents *contents, const Geometry *geometry, 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)
std::function< PipelineRef(ContentContextOptions)> PipelineBuilderCallback
std::function< bool(RenderPass &pass)> BindFragmentCallback
void SetOpacityFactor(Scalar opacity)
Set the opacity factor for this color source.
void SetGeometry(const Geometry *geometry)
Set the geometry that this contents will use to render.
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
PipelineRef GetClipPipeline(ContentContextOptions opts) const
virtual std::optional< Rect > GetCoverage(const Entity &entity) const =0
Get the area of the render pass that will be affected when this contents is rendered.
BlendMode GetBlendMode() const
Definition entity.cc:101
uint32_t GetClipDepth() const
Definition entity.cc:84
float GetShaderClipDepth() const
Definition entity.cc:88
virtual std::optional< Rect > GetCoverage(const Matrix &transform) const =0
virtual GeometryResult::Mode GetResultMode() const
Definition geometry.cc:58
virtual GeometryResult GetPositionBuffer(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const =0
BufferView EmplaceUniform(const UniformType &uniform)
Emplace uniform data onto the host buffer. Ensure that backend specific uniform alignment requirement...
Definition host_buffer.h:47
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition render_pass.h:30
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
virtual void SetStencilReference(uint32_t value)
virtual void SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
virtual fml::Status Draw()
Record the currently pending command.
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
#define FML_UNREACHABLE()
Definition logging.h:128
float Scalar
Definition scalar.h:19
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
Definition pipeline.h:88
bool RenderClipRestore(const ContentContext &renderer, RenderPass &pass, uint32_t clip_depth, std::optional< Rect > restore_coverage)
Render a restore clip.
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition contents.cc:34
PrimitiveType type
Definition geometry.h:37
VertexBuffer vertex_buffer
Definition geometry.h:38
A 4x4 matrix using column-major storage.
Definition matrix.h:37