Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
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 Get the geometry that this contents will use to render.
55 ///
56 virtual const Geometry* GetGeometry() const = 0;
57
58 //----------------------------------------------------------------------------
59 /// @brief Set the effect transform for this color source.
60 ///
61 /// The effect transform is a transform matrix that is applied to
62 /// the shaded color output and does not impact geometry in any way.
63 ///
64 /// For example: With repeat tiling, any gradient or
65 /// `TiledTextureContents` could be used with an effect transform to
66 /// inexpensively draw an infinite scrolling background pattern.
67 ///
68 void SetEffectTransform(Matrix matrix);
69
70 //----------------------------------------------------------------------------
71 /// @brief Set the inverted effect transform for this color source.
72 ///
73 /// When the effect transform is set via `SetEffectTransform`, the
74 /// value is inverted upon storage. The reason for this is that most
75 /// color sources internally use the inverted transform.
76 ///
77 /// @return The inverse of the transform set by `SetEffectTransform`.
78 ///
79 /// @see `SetEffectTransform`
80 ///
81 const Matrix& GetInverseEffectTransform() const;
82
83 //----------------------------------------------------------------------------
84 /// @brief Set the opacity factor for this color source.
85 ///
86 void SetOpacityFactor(Scalar opacity);
87
88 //----------------------------------------------------------------------------
89 /// @brief Get the opacity factor for this color source.
90 ///
91 /// This value is is factored into the output of the color source in
92 /// addition to opacity information that may be supplied any other
93 /// inputs.
94 ///
95 /// @note If set, the output of this method factors factors in the inherited
96 /// opacity of this `Contents`.
98
99 virtual bool IsSolidColor() const;
100
101 // |Contents|
102 std::optional<Rect> GetCoverage(const Entity& entity) const override;
103
104 // |Contents|
105 void SetInheritedOpacity(Scalar opacity) override;
106
107 template <typename VertexShaderT>
108 static bool DrawGeometry(const Contents* contents,
109 const Geometry* geometry,
110 const ContentContext& renderer,
111 const Entity& entity,
112 RenderPass& pass,
113 const PipelineBuilderCallback& pipeline_callback,
114 typename VertexShaderT::FrameInfo frame_info,
115 const BindFragmentCallback& bind_fragment_callback,
116 bool force_stencil = false,
117 const CreateGeometryCallback& create_geom_callback =
119 auto options = OptionsFromPassAndEntity(pass, entity);
120
121 GeometryResult::Mode geometry_mode = geometry->GetResultMode();
122 bool do_cover_draw = false;
123 Rect cover_area = {};
124
125 bool is_stencil_then_cover =
126 geometry_mode == GeometryResult::Mode::kNonZero ||
127 geometry_mode == GeometryResult::Mode::kEvenOdd;
128 if (!is_stencil_then_cover && force_stencil) {
129 geometry_mode = GeometryResult::Mode::kNonZero;
130 is_stencil_then_cover = true;
131 }
132
133 if (is_stencil_then_cover) {
134 pass.SetStencilReference(0);
135
136 /// Stencil preparation draw.
137
138 GeometryResult stencil_geometry_result =
139 geometry->GetPositionBuffer(renderer, entity, pass);
140 if (stencil_geometry_result.vertex_buffer.vertex_count == 0u) {
141 return true;
142 }
143 pass.SetVertexBuffer(std::move(stencil_geometry_result.vertex_buffer));
144 options.primitive_type = stencil_geometry_result.type;
145
146 options.blend_mode = BlendMode::kDst;
147 switch (stencil_geometry_result.mode) {
149 pass.SetCommandLabel("Stencil preparation (NonZero)");
150 options.stencil_mode =
152 break;
154 pass.SetCommandLabel("Stencil preparation (EvenOdd)");
155 options.stencil_mode =
157 break;
158 default:
159 if (force_stencil) {
160 pass.SetCommandLabel("Stencil preparation (NonZero)");
161 options.stencil_mode =
163 break;
164 }
166 }
167 pass.SetPipeline(renderer.GetClipPipeline(options));
168 ClipPipeline::VertexShader::FrameInfo clip_frame_info;
169 clip_frame_info.depth = entity.GetShaderClipDepth();
170 clip_frame_info.mvp = stencil_geometry_result.transform;
171 ClipPipeline::VertexShader::BindFrameInfo(
172 pass,
173 renderer.GetTransientsDataBuffer().EmplaceUniform(clip_frame_info));
174
175 if (!pass.Draw().ok()) {
176 return false;
177 }
178
179 /// Cover draw.
180
181 options.blend_mode = entity.GetBlendMode();
183 std::optional<Rect> maybe_cover_area = geometry->GetCoverage({});
184 if (!maybe_cover_area.has_value()) {
185 return true;
186 }
187 do_cover_draw = true;
188 cover_area = maybe_cover_area.value();
189 }
190
191 GeometryResult geometry_result;
192 if (do_cover_draw) {
193 FillRectGeometry geom(cover_area);
194 geometry_result = create_geom_callback(renderer, entity, pass, &geom);
195 } else {
196 geometry_result = create_geom_callback(renderer, entity, pass, geometry);
197 }
198
199 if (geometry_result.vertex_buffer.vertex_count == 0u) {
200 return true;
201 }
202 pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));
203 options.primitive_type = geometry_result.type;
204
205 // Enable depth writing for all opaque entities in order to allow
206 // reordering. Opaque entities are coerced to source blending by
207 // `EntityPass::AddEntity`.
208 options.depth_write_enabled = options.blend_mode == BlendMode::kSrc;
209
210 // Take the pre-populated vertex shader uniform struct and set managed
211 // values.
212 frame_info.mvp = geometry_result.transform;
213
214 // If overdraw prevention is requested (like when drawing stroke paths), set
215 // up the depth buffer and depth comparison function to prevent the same
216 // pixel from being painted multiple times.
217 if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw) {
218 options.depth_write_enabled = true;
219 options.depth_compare = CompareFunction::kGreater;
220 }
221 pass.SetStencilReference(0);
222
223 VertexShaderT::BindFrameInfo(
224 pass, renderer.GetTransientsDataBuffer().EmplaceUniform(frame_info));
225
226 // The reason we need to have a callback mechanism here is that this routine
227 // may insert draw calls before the main draw call below. For example, for
228 // sufficiently complex paths we may opt to use stencil-then-cover to avoid
229 // tessellation.
230 if (!bind_fragment_callback(pass)) {
231 return false;
232 }
233
234 pass.SetPipeline(pipeline_callback(options));
235
236 return pass.Draw().ok();
237 }
238
239 protected:
241 const ContentContext& renderer,
242 const Entity& entity,
243 RenderPass& pass,
244 const Geometry* geom) {
245 return geom->GetPositionBuffer(renderer, entity, pass);
246 }
247
248 /// @brief Whether the entity should be treated as non-opaque due to stroke
249 /// geometry requiring alpha for coverage.
251
252 template <typename VertexShaderT>
253 bool DrawGeometry(const ContentContext& renderer,
254 const Entity& entity,
255 RenderPass& pass,
256 const PipelineBuilderCallback& pipeline_callback,
257 typename VertexShaderT::FrameInfo frame_info,
258 const BindFragmentCallback& bind_fragment_callback,
259 bool force_stencil = false,
260 const CreateGeometryCallback& create_geom_callback =
262 //
263 return DrawGeometry<VertexShaderT>(this, //
264 GetGeometry(), //
265 renderer, //
266 entity, //
267 pass, //
268 pipeline_callback, //
269 frame_info, //
270 bind_fragment_callback, //
271 force_stencil, //
272 create_geom_callback);
273 }
274
275 private:
276 Matrix inverse_matrix_;
277 Scalar opacity_ = 1.0;
278 Scalar inherited_opacity_ = 1.0;
279
281
282 ColorSourceContents& operator=(const ColorSourceContents&) = delete;
283};
284
285} // namespace impeller
286
287#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
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
virtual const Geometry * GetGeometry() const =0
Get the geometry that this contents will use to render.
std::function< bool(RenderPass &pass)> BindFragmentCallback
void SetOpacityFactor(Scalar opacity)
Set the opacity factor for this color source.
HostBuffer & GetTransientsDataBuffer() const
Retrieve the current host buffer for transient storage of other non-index data.
PipelineRef GetClipPipeline(ContentContextOptions opts) const
BlendMode GetBlendMode() const
Definition entity.cc:102
float GetShaderClipDepth() const
Definition entity.cc:90
virtual std::optional< Rect > GetCoverage(const Matrix &transform) const =0
The coverage rectangle of this geometry, transformed by the transform argument.
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:89
@ kGreater
Comparison test passes if new_value > current_value.
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