Flutter Engine
The 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"
15
16namespace impeller {
17
18//------------------------------------------------------------------------------
19/// Color sources are geometry-ignostic `Contents` capable of shading any area
20/// defined by an `impeller::Geometry`. Conceptually,
21/// `impeller::ColorSourceContents` implement a particular color shading
22/// behavior.
23///
24/// This separation of concerns between geometry and color source output allows
25/// Impeller to handle most possible draw combinations in a consistent way.
26/// For example: There are color sources for handling solid colors, gradients,
27/// textures, custom runtime effects, and even 3D scenes.
28///
29/// There are some special rendering exceptions that deviate from this pattern
30/// and cross geometry and color source concerns, such as text atlas and image
31/// atlas rendering. Special `Contents` exist for rendering these behaviors
32/// which don't implement `ColorSourceContents`.
33///
34/// @see `impeller::Geometry`
35///
37 public:
39
41
42 //----------------------------------------------------------------------------
43 /// @brief Set the geometry that this contents will use to render.
44 ///
45 void SetGeometry(std::shared_ptr<Geometry> geometry);
46
47 //----------------------------------------------------------------------------
48 /// @brief Get the geometry that this contents will use to render.
49 ///
50 const std::shared_ptr<Geometry>& GetGeometry() const;
51
52 //----------------------------------------------------------------------------
53 /// @brief Set the effect transform for this color source.
54 ///
55 /// The effect transform is a transform matrix that is applied to
56 /// the shaded color output and does not impact geometry in any way.
57 ///
58 /// For example: With repeat tiling, any gradient or
59 /// `TiledTextureContents` could be used with an effect transform to
60 /// inexpensively draw an infinite scrolling background pattern.
61 ///
62 void SetEffectTransform(Matrix matrix);
63
64 //----------------------------------------------------------------------------
65 /// @brief Set the inverted effect transform for this color source.
66 ///
67 /// When the effect transform is set via `SetEffectTransform`, the
68 /// value is inverted upon storage. The reason for this is that most
69 /// color sources internally use the inverted transform.
70 ///
71 /// @return The inverse of the transform set by `SetEffectTransform`.
72 ///
73 /// @see `SetEffectTransform`
74 ///
75 const Matrix& GetInverseEffectTransform() const;
76
77 //----------------------------------------------------------------------------
78 /// @brief Set the opacity factor for this color source.
79 ///
80 void SetOpacityFactor(Scalar opacity);
81
82 //----------------------------------------------------------------------------
83 /// @brief Get the opacity factor for this color source.
84 ///
85 /// This value is is factored into the output of the color source in
86 /// addition to opacity information that may be supplied any other
87 /// inputs.
88 ///
89 /// @note If set, the output of this method factors factors in the inherited
90 /// opacity of this `Contents`.
91 ///
92 /// @see `Contents::CanInheritOpacity`
93 ///
95
96 virtual bool IsSolidColor() const;
97
98 // |Contents|
99 std::optional<Rect> GetCoverage(const Entity& entity) const override;
100
101 // |Contents|
102 bool CanInheritOpacity(const Entity& entity) const override;
103
104 // |Contents|
105 void SetInheritedOpacity(Scalar opacity) override;
106
107 protected:
108 using BindFragmentCallback = std::function<bool(RenderPass& pass)>;
109 using PipelineBuilderMethod = std::shared_ptr<Pipeline<PipelineDescriptor>> (
112 std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>(
114
115 template <typename VertexShaderT>
116 bool DrawGeometry(const ContentContext& renderer,
117 const Entity& entity,
118 RenderPass& pass,
119 const PipelineBuilderCallback& pipeline_callback,
120 typename VertexShaderT::FrameInfo frame_info,
121 const BindFragmentCallback& bind_fragment_callback) const {
122 auto options = OptionsFromPassAndEntity(pass, entity);
123
124 GeometryResult::Mode geometry_mode = GetGeometry()->GetResultMode();
125 Geometry& geometry = *GetGeometry();
126
127 const bool is_stencil_then_cover =
128 geometry_mode == GeometryResult::Mode::kNonZero ||
129 geometry_mode == GeometryResult::Mode::kEvenOdd;
130 if (is_stencil_then_cover) {
131 pass.SetStencilReference(0);
132
133 /// Stencil preparation draw.
134
135 GeometryResult stencil_geometry_result =
136 GetGeometry()->GetPositionBuffer(renderer, entity, pass);
137 if (stencil_geometry_result.vertex_buffer.vertex_count == 0u) {
138 return true;
139 }
140 pass.SetVertexBuffer(std::move(stencil_geometry_result.vertex_buffer));
141 options.primitive_type = stencil_geometry_result.type;
142
143 options.blend_mode = BlendMode::kDestination;
144 switch (stencil_geometry_result.mode) {
146 pass.SetCommandLabel("Stencil preparation (NonZero)");
147 options.stencil_mode =
149 break;
151 pass.SetCommandLabel("Stencil preparation (EvenOdd)");
152 options.stencil_mode =
154 break;
155 default:
157 }
158 pass.SetPipeline(renderer.GetClipPipeline(options));
159 ClipPipeline::VertexShader::FrameInfo clip_frame_info;
160 clip_frame_info.depth = entity.GetShaderClipDepth();
161 clip_frame_info.mvp = stencil_geometry_result.transform;
162 ClipPipeline::VertexShader::BindFrameInfo(
163 pass, renderer.GetTransientsBuffer().EmplaceUniform(clip_frame_info));
164
165 if (!pass.Draw().ok()) {
166 return false;
167 }
168
169 /// Cover draw.
170
171 options.blend_mode = entity.GetBlendMode();
173 std::optional<Rect> maybe_cover_area = GetGeometry()->GetCoverage({});
174 if (!maybe_cover_area.has_value()) {
175 return true;
176 }
177 geometry = RectGeometry(maybe_cover_area.value());
178 }
179
180 GeometryResult geometry_result =
181 geometry.GetPositionBuffer(renderer, entity, pass);
182 if (geometry_result.vertex_buffer.vertex_count == 0u) {
183 return true;
184 }
185 pass.SetVertexBuffer(std::move(geometry_result.vertex_buffer));
186 options.primitive_type = geometry_result.type;
187
188 // Take the pre-populated vertex shader uniform struct and set managed
189 // values.
190 frame_info.mvp = geometry_result.transform;
191
192 // If overdraw prevention is enabled (like when drawing stroke paths), we
193 // increment the stencil buffer as we draw, preventing overlapping fragments
194 // from drawing. Afterwards, we need to append another draw call to clean up
195 // the stencil buffer (happens below in this method).
196 if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw) {
197 options.stencil_mode =
199 }
200 pass.SetStencilReference(0);
201
202 VertexShaderT::BindFrameInfo(
203 pass, renderer.GetTransientsBuffer().EmplaceUniform(frame_info));
204
205 // The reason we need to have a callback mechanism here is that this routine
206 // may insert draw calls before the main draw call below. For example, for
207 // sufficiently complex paths we may opt to use stencil-then-cover to avoid
208 // tessellation.
209 if (!bind_fragment_callback(pass)) {
210 return false;
211 }
212
213 pass.SetPipeline(pipeline_callback(options));
214
215 if (!pass.Draw().ok()) {
216 return false;
217 }
218
219 // If we performed overdraw prevention, a subsection of the clip heightmap
220 // was incremented by 1 in order to self-clip. So simply append a clip
221 // restore to clean it up.
222 if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw) {
223 auto restore = ClipRestoreContents();
224 restore.SetRestoreCoverage(GetCoverage(entity));
225 Entity restore_entity = entity.Clone();
226 return restore.Render(renderer, restore_entity, pass);
227 }
228 return true;
229 }
230
231 private:
232 std::shared_ptr<Geometry> geometry_;
233 Matrix inverse_matrix_;
234 Scalar opacity_ = 1.0;
235 Scalar inherited_opacity_ = 1.0;
236
238
239 ColorSourceContents& operator=(const ColorSourceContents&) = delete;
240};
241
242} // namespace impeller
243
244#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.
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.
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.
bool DrawGeometry(const ContentContext &renderer, const Entity &entity, RenderPass &pass, const PipelineBuilderCallback &pipeline_callback, typename VertexShaderT::FrameInfo frame_info, const BindFragmentCallback &bind_fragment_callback) const
const std::shared_ptr< Geometry > & GetGeometry() const
Get the geometry that this contents will use to render.
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:195
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.
virtual void SetStencilReference(uint32_t value)
virtual void SetPipeline(const std::shared_ptr< Pipeline< PipelineDescriptor > > &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:109
float Scalar
Definition scalar.h:18
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition contents.cc:35
PrimitiveType type
Definition geometry.h:35
VertexBuffer vertex_buffer
Definition geometry.h:36
A 4x4 matrix using column-major storage.
Definition matrix.h:37