Flutter Engine
The Flutter Engine
morphology_filter_contents.cc
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
6
7#include <cmath>
8
14
15namespace impeller {
16
18 default;
19
21 default;
22
24 radius_ = radius;
25}
26
28 direction_ = direction.Normalize();
29 if (direction_.IsZero()) {
30 direction_ = Vector2(0, 1);
31 }
32}
33
35 morph_type_ = morph_type;
36}
37
38std::optional<Entity> DirectionalMorphologyFilterContents::RenderFilter(
41 const Entity& entity,
42 const Matrix& effect_transform,
43 const Rect& coverage,
44 const std::optional<Rect>& coverage_hint) const {
47
48 //----------------------------------------------------------------------------
49 /// Handle inputs.
50 ///
51
52 if (inputs.empty()) {
53 return std::nullopt;
54 }
55
56 auto input_snapshot = inputs[0]->GetSnapshot("Morphology", renderer, entity);
57 if (!input_snapshot.has_value()) {
58 return std::nullopt;
59 }
60
61 if (radius_.radius < kEhCloseEnough) {
62 return Entity::FromSnapshot(input_snapshot.value(), entity.GetBlendMode());
63 }
64
65 auto maybe_input_uvs = input_snapshot->GetCoverageUVs(coverage);
66 if (!maybe_input_uvs.has_value()) {
67 return std::nullopt;
68 }
69 auto input_uvs = maybe_input_uvs.value();
70
71 //----------------------------------------------------------------------------
72 /// Render to texture.
73 ///
74
75 ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
76 RenderPass& pass) {
77 auto& host_buffer = renderer.GetTransientsBuffer();
78
79 VertexBufferBuilder<VS::PerVertexData> vtx_builder;
80 vtx_builder.AddVertices({
81 {Point(0, 0), input_uvs[0]},
82 {Point(1, 0), input_uvs[1]},
83 {Point(0, 1), input_uvs[2]},
84 {Point(1, 1), input_uvs[3]},
85 });
86
87 VS::FrameInfo frame_info;
88 frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
89 frame_info.texture_sampler_y_coord_scale =
90 input_snapshot->texture->GetYCoordScale();
91
92 auto transform = entity.GetTransform() * effect_transform.Basis();
93 auto transformed_radius =
94 transform.TransformDirection(direction_ * radius_.radius);
95 auto transformed_texture_vertices =
96 Rect::MakeSize(input_snapshot->texture->GetSize())
97 .GetTransformedPoints(input_snapshot->transform);
98 auto transformed_texture_width =
99 transformed_texture_vertices[0].GetDistance(
100 transformed_texture_vertices[1]);
101 auto transformed_texture_height =
102 transformed_texture_vertices[0].GetDistance(
103 transformed_texture_vertices[2]);
104
105 FS::FragInfo frag_info;
106 frag_info.radius = std::round(transformed_radius.GetLength());
107 frag_info.morph_type = static_cast<Scalar>(morph_type_);
108 frag_info.uv_offset =
109 input_snapshot->transform.Invert()
110 .TransformDirection(transformed_radius)
111 .Normalize() /
112 Point(transformed_texture_width, transformed_texture_height);
113
114 pass.SetCommandLabel("Morphology Filter");
115 auto options = OptionsFromPass(pass);
116 options.primitive_type = PrimitiveType::kTriangleStrip;
117 options.blend_mode = BlendMode::kSource;
118 pass.SetPipeline(renderer.GetMorphologyFilterPipeline(options));
119 pass.SetVertexBuffer(vtx_builder.CreateVertexBuffer(host_buffer));
120
121 auto sampler_descriptor = input_snapshot->sampler_descriptor;
122 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
123 sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
124 sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
125 }
126
127 FS::BindTextureSampler(
128 pass, input_snapshot->texture,
129 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
130 sampler_descriptor));
131 VS::BindFrameInfo(pass, host_buffer.EmplaceUniform(frame_info));
132 FS::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info));
133
134 return pass.Draw().ok();
135 };
136 std::shared_ptr<CommandBuffer> command_buffer =
137 renderer.GetContext()->CreateCommandBuffer();
138 if (command_buffer == nullptr) {
139 return std::nullopt;
140 }
141
142 fml::StatusOr<RenderTarget> render_target =
143 renderer.MakeSubpass("Directional Morphology Filter",
144 ISize(coverage.GetSize()), command_buffer, callback);
145 if (!render_target.ok()) {
146 return std::nullopt;
147 }
148 if (!renderer.GetContext()
149 ->GetCommandQueue()
150 ->Submit(/*buffers=*/{std::move(command_buffer)})
151 .ok()) {
152 return std::nullopt;
153 }
154
155 SamplerDescriptor sampler_desc;
156 sampler_desc.min_filter = MinMagFilter::kLinear;
157 sampler_desc.mag_filter = MinMagFilter::kLinear;
158
160 Snapshot{.texture = render_target.value().GetRenderTargetTexture(),
162 .sampler_descriptor = sampler_desc,
163 .opacity = input_snapshot->opacity},
164 entity.GetBlendMode());
165}
166
169 const Entity& entity,
170 const Matrix& effect_transform) const {
171 if (inputs.empty()) {
172 return std::nullopt;
173 }
174
175 auto coverage = inputs[0]->GetCoverage(entity);
176 if (!coverage.has_value()) {
177 return std::nullopt;
178 }
179 auto transform = inputs[0]->GetTransform(entity) * effect_transform.Basis();
180 auto transformed_vector =
181 transform.TransformDirection(direction_ * radius_.radius).Abs();
182
183 auto origin = coverage->GetOrigin();
184 auto size = Vector2(coverage->GetSize());
185 switch (morph_type_) {
187 origin -= transformed_vector;
188 size += transformed_vector * 2;
189 break;
191 origin += transformed_vector;
192 size -= transformed_vector * 2;
193 break;
194 }
195 if (size.x < 0 || size.y < 0) {
196 return Rect::MakeSize(Size(0, 0));
197 }
198 return Rect::MakeOriginSize(origin, Size(size.x, size.y));
199}
200
201std::optional<Rect>
203 const Matrix& effect_transform,
204 const Rect& output_limit) const {
205 auto transformed_vector =
206 effect_transform.TransformDirection(direction_ * radius_.radius).Abs();
207 switch (morph_type_) {
209 return output_limit.Expand(-transformed_vector);
211 return output_limit.Expand(transformed_vector);
212 }
213}
214
215} // namespace impeller
const char * options
static void round(SkPoint *p)
const T & value() const
Definition: status_or.h:77
bool ok() const
Definition: status_or.h:75
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
std::optional< Rect > GetFilterCoverage(const FilterInput::Vector &inputs, const Entity &entity, const Matrix &effect_transform) const override
Internal utility method for |GetLocalCoverage| that computes the output coverage of this filter acros...
std::optional< Rect > GetFilterSourceCoverage(const Matrix &effect_transform, const Rect &output_limit) const override
Internal utility method for |GetSourceCoverage| that computes the inverse effect of this transform on...
static Entity FromSnapshot(const Snapshot &snapshot, BlendMode blend_mode=BlendMode::kSourceOver)
Create an entity that can be used to render a given snapshot.
Definition: entity.cc:22
BlendMode GetBlendMode() const
Definition: entity.cc:119
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:46
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:33
FragmentShader_ FragmentShader
Definition: pipeline.h:107
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Point Vector2
Definition: point.h:326
float Scalar
Definition: scalar.h:18
constexpr float kEhCloseEnough
Definition: constants.h:56
SolidFillVertexShader VS
TPoint< Scalar > Point
Definition: point.h:322
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...
TSize< Scalar > Size
Definition: size.h:137
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:19
ISize64 ISize
Definition: size.h:140
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:497
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
constexpr Matrix Basis() const
The Matrix without its w components (without translation).
Definition: matrix.h:229
constexpr Vector4 TransformDirection(const Vector4 &v) const
Definition: matrix.h:471
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition: sigma.h:48
Scalar radius
Definition: sigma.h:49
constexpr TPoint Normalize() const
Definition: point.h:208
constexpr bool IsZero() const
Definition: point.h:240
static constexpr TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
Definition: rect.h:140
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
Definition: rect.h:417
static constexpr TRect MakeSize(const TSize< U > &size)
Definition: rect.h:146
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition: rect.h:605