| Flutter Impeller |

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
5 #include "impeller/entity/contents/filters/morphology_filter_contents.h"
6
7 #include <cmath>
8
9 #include "impeller/entity/contents/content_context.h"
10 #include "impeller/entity/contents/contents.h"
11 #include "impeller/renderer/render_pass.h"
12 #include "impeller/renderer/sampler_library.h"
13
14 namespace impeller {
15
16 DirectionalMorphologyFilterContents::DirectionalMorphologyFilterContents() =
17 default;
18
19 DirectionalMorphologyFilterContents::~DirectionalMorphologyFilterContents() =
20 default;
21
22 void DirectionalMorphologyFilterContents::SetRadius(Radius radius) {
23 radius_ = radius;
24 }
25
26 void DirectionalMorphologyFilterContents::SetDirection(Vector2 direction) {
27 direction_ = direction.Normalize();
28 if (direction_.IsZero()) {
29 direction_ = Vector2(0, 1);
30 }
31 }
32
33 void DirectionalMorphologyFilterContents::SetMorphType(MorphType morph_type) {
34 morph_type_ = morph_type;
35 }
36
37 std::optional<Entity> DirectionalMorphologyFilterContents::RenderFilter(
38 const FilterInput::Vector& inputs,
39 const ContentContext& renderer,
40 const Entity& entity,
41 const Matrix& effect_transform,
42 const Rect& coverage,
43 const std::optional<Rect>& coverage_hint) const {
44 using VS = MorphologyFilterPipeline::VertexShader;
45 using FS = MorphologyFilterPipeline::FragmentShader;
46
47 //----------------------------------------------------------------------------
48 /// Handle inputs.
49 ///
50
51 if (inputs.empty()) {
52 return std::nullopt;
53 }
54
55 auto input_snapshot = inputs[0]->GetSnapshot("Morphology", renderer, entity);
56 if (!input_snapshot.has_value()) {
57 return std::nullopt;
58 }
59
60 if (radius_.radius < kEhCloseEnough) {
61 return Entity::FromSnapshot(input_snapshot.value(), entity.GetBlendMode(),
62 entity.GetStencilDepth());
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 = pass.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(1, 1), input_uvs[3]},
84 {Point(0, 0), input_uvs[0]},
85 {Point(1, 1), input_uvs[3]},
86 {Point(0, 1), input_uvs[2]},
87 });
88
89 auto vtx_buffer = vtx_builder.CreateVertexBuffer(host_buffer);
90
91 VS::FrameInfo frame_info;
92 frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
93 frame_info.texture_sampler_y_coord_scale =
94 input_snapshot->texture->GetYCoordScale();
95
96 auto transform = entity.GetTransformation() * effect_transform.Basis();
97 auto transformed_radius =
98 transform.TransformDirection(direction_ * radius_.radius);
99 auto transformed_texture_vertices =
100 Rect(Size(input_snapshot->texture->GetSize()))
101 .GetTransformedPoints(input_snapshot->transform);
102 auto transformed_texture_width =
103 transformed_texture_vertices[0].GetDistance(
104 transformed_texture_vertices[1]);
105 auto transformed_texture_height =
106 transformed_texture_vertices[0].GetDistance(
107 transformed_texture_vertices[2]);
108
109 FS::FragInfo frag_info;
110 frag_info.radius = std::round(transformed_radius.GetLength());
111 frag_info.morph_type = static_cast<Scalar>(morph_type_);
112 frag_info.uv_offset =
113 input_snapshot->transform.Invert()
114 .TransformDirection(transformed_radius)
115 .Normalize() /
116 Point(transformed_texture_width, transformed_texture_height);
117
118 Command cmd;
119 DEBUG_COMMAND_INFO(cmd, "Morphology Filter");
120 auto options = OptionsFromPass(pass);
121 options.blend_mode = BlendMode::kSource;
122 cmd.pipeline = renderer.GetMorphologyFilterPipeline(options);
123 cmd.BindVertices(vtx_buffer);
124
125 auto sampler_descriptor = input_snapshot->sampler_descriptor;
126 if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
127 sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
128 sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
129 }
130
131 FS::BindTextureSampler(
132 cmd, input_snapshot->texture,
133 renderer.GetContext()->GetSamplerLibrary()->GetSampler(
134 sampler_descriptor));
135 VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
136 FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
137
138 return pass.AddCommand(std::move(cmd));
139 };
140
141 auto out_texture = renderer.MakeSubpass("Directional Morphology Filter",
142 ISize(coverage.size), callback);
143 if (!out_texture) {
144 return std::nullopt;
145 }
146
147 SamplerDescriptor sampler_desc;
148 sampler_desc.min_filter = MinMagFilter::kLinear;
149 sampler_desc.mag_filter = MinMagFilter::kLinear;
150
151 return Entity::FromSnapshot(
152 Snapshot{.texture = out_texture,
153 .transform = Matrix::MakeTranslation(coverage.origin),
154 .sampler_descriptor = sampler_desc,
155 .opacity = input_snapshot->opacity},
156 entity.GetBlendMode(), entity.GetStencilDepth());
157 }
158
159 std::optional<Rect> DirectionalMorphologyFilterContents::GetFilterCoverage(
160 const FilterInput::Vector& inputs,
161 const Entity& entity,
162 const Matrix& effect_transform) const {
163 if (inputs.empty()) {
164 return std::nullopt;
165 }
166
167 auto coverage = inputs[0]->GetCoverage(entity);
168 if (!coverage.has_value()) {
169 return std::nullopt;
170 }
171 auto transform = inputs[0]->GetTransform(entity) * effect_transform.Basis();
172 auto transformed_vector =
173 transform.TransformDirection(direction_ * radius_.radius).Abs();
174
175 auto origin = coverage->origin;
176 auto size = Vector2(coverage->size);
177 switch (morph_type_) {
178 case FilterContents::MorphType::kDilate:
179 origin -= transformed_vector;
180 size += transformed_vector * 2;
181 break;
182 case FilterContents::MorphType::kErode:
183 origin += transformed_vector;
184 size -= transformed_vector * 2;
185 break;
186 }
187 if (size.x < 0 || size.y < 0) {
188 return Rect::MakeSize(Size(0, 0));
189 }
190 return Rect(origin, Size(size.x, size.y));
191 }
192
193 } // namespace impeller
impeller::OptionsFromPass
ContentContextOptions OptionsFromPass(const RenderPass &pass)
Definition: contents.cc:20
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:31
impeller::Radius::radius
Scalar radius
Definition: sigma.h:48
contents.h
impeller::Entity::GetStencilDepth
uint32_t GetStencilDepth() const
Definition: entity.cc:93
impeller::TRect::size
TSize< Type > size
Definition: rect.h:24
impeller::FilterContents::MorphType::kErode
@ kErode
impeller::DirectionalMorphologyFilterContents::~DirectionalMorphologyFilterContents
~DirectionalMorphologyFilterContents() override
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::Entity::FromSnapshot
static std::optional< Entity > FromSnapshot(const std::optional< Snapshot > &snapshot, BlendMode blend_mode=BlendMode::kSourceOver, uint32_t stencil_depth=0)
Create an entity that can be used to render a given snapshot.
Definition: entity.cc:21
sampler_library.h
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:55
impeller::DirectionalMorphologyFilterContents::GetFilterCoverage
std::optional< Rect > GetFilterCoverage(const FilterInput::Vector &inputs, const Entity &entity, const Matrix &effect_transform) const override
Definition: morphology_filter_contents.cc:159
impeller::Vector2
Point Vector2
Definition: point.h:310
impeller::RenderPipelineT::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:91
impeller::Size
TSize< Scalar > Size
Definition: size.h:135
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:94
impeller::DirectionalMorphologyFilterContents::SetRadius
void SetRadius(Radius radius)
Definition: morphology_filter_contents.cc:22
impeller::Entity::GetTransformation
const Matrix & GetTransformation() const
Definition: entity.cc:49
impeller::TPoint::IsZero
constexpr bool IsZero() const
Definition: point.h:227
impeller::Entity
Definition: entity.h:21
impeller::Matrix::Basis
constexpr Matrix Basis() const
Definition: matrix.h:222
morphology_filter_contents.h
impeller::Point
TPoint< Scalar > Point
Definition: point.h:306
render_pass.h
impeller::Radius
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition: sigma.h:47
impeller::TRect::GetTransformedPoints
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
Definition: rect.h:193
impeller::MinMagFilter::kLinear
@ kLinear
impeller::TRect::origin
TPoint< Type > origin
Definition: rect.h:23
impeller::DirectionalMorphologyFilterContents::DirectionalMorphologyFilterContents
DirectionalMorphologyFilterContents()
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:306
impeller::DirectionalMorphologyFilterContents::SetDirection
void SetDirection(Vector2 direction)
Definition: morphology_filter_contents.cc:26
impeller::Entity::GetBlendMode
BlendMode GetBlendMode() const
Definition: entity.cc:105
impeller::ContentContext::SubpassCallback
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
Definition: content_context.h:703
impeller::Matrix::TransformDirection
constexpr Vector4 TransformDirection(const Vector4 &v) const
Definition: matrix.h:431
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:136
content_context.h
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:52
impeller::FilterContents::MorphType::kDilate
@ kDilate
impeller::TPoint< Scalar >
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:448
impeller::DirectionalMorphologyFilterContents::SetMorphType
void SetMorphType(MorphType morph_type)
Definition: morphology_filter_contents.cc:33
impeller::FilterInput::Vector
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:32
impeller::TPoint::Normalize
constexpr TPoint Normalize() const
Definition: point.h:201
impeller::RenderPipelineT::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:90
impeller
Definition: aiks_context.cc:10
impeller::ContentContext
Definition: content_context.h:344
impeller::TRect
Definition: rect.h:20
impeller::BlendMode::kSource
@ kSource
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:36
impeller::SamplerAddressMode::kDecal
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...