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 
6 
7 #include <cmath>
8 
14 
15 namespace 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 
38 std::optional<Entity> DirectionalMorphologyFilterContents::RenderFilter(
39  const FilterInput::Vector& inputs,
40  const ContentContext& renderer,
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  entity.GetClipDepth());
64  }
65 
66  auto maybe_input_uvs = input_snapshot->GetCoverageUVs(coverage);
67  if (!maybe_input_uvs.has_value()) {
68  return std::nullopt;
69  }
70  auto input_uvs = maybe_input_uvs.value();
71 
72  //----------------------------------------------------------------------------
73  /// Render to texture.
74  ///
75 
76  ContentContext::SubpassCallback callback = [&](const ContentContext& renderer,
77  RenderPass& pass) {
78  auto& host_buffer = pass.GetTransientsBuffer();
79 
80  VertexBufferBuilder<VS::PerVertexData> vtx_builder;
81  vtx_builder.AddVertices({
82  {Point(0, 0), input_uvs[0]},
83  {Point(1, 0), input_uvs[1]},
84  {Point(0, 1), input_uvs[2]},
85  {Point(1, 1), input_uvs[3]},
86  });
87 
88  VS::FrameInfo frame_info;
89  frame_info.mvp = Matrix::MakeOrthographic(ISize(1, 1));
90  frame_info.texture_sampler_y_coord_scale =
91  input_snapshot->texture->GetYCoordScale();
92 
93  auto transform = entity.GetTransform() * effect_transform.Basis();
94  auto transformed_radius =
95  transform.TransformDirection(direction_ * radius_.radius);
96  auto transformed_texture_vertices =
97  Rect::MakeSize(input_snapshot->texture->GetSize())
98  .GetTransformedPoints(input_snapshot->transform);
99  auto transformed_texture_width =
100  transformed_texture_vertices[0].GetDistance(
101  transformed_texture_vertices[1]);
102  auto transformed_texture_height =
103  transformed_texture_vertices[0].GetDistance(
104  transformed_texture_vertices[2]);
105 
106  FS::FragInfo frag_info;
107  frag_info.radius = std::round(transformed_radius.GetLength());
108  frag_info.morph_type = static_cast<Scalar>(morph_type_);
109  frag_info.uv_offset =
110  input_snapshot->transform.Invert()
111  .TransformDirection(transformed_radius)
112  .Normalize() /
113  Point(transformed_texture_width, transformed_texture_height);
114 
115  Command cmd;
116  DEBUG_COMMAND_INFO(cmd, "Morphology Filter");
117  auto options = OptionsFromPass(pass);
118  options.primitive_type = PrimitiveType::kTriangleStrip;
119  options.blend_mode = BlendMode::kSource;
120  cmd.pipeline = renderer.GetMorphologyFilterPipeline(options);
121  cmd.BindVertices(vtx_builder.CreateVertexBuffer(host_buffer));
122 
123  auto sampler_descriptor = input_snapshot->sampler_descriptor;
124  if (renderer.GetDeviceCapabilities().SupportsDecalSamplerAddressMode()) {
125  sampler_descriptor.width_address_mode = SamplerAddressMode::kDecal;
126  sampler_descriptor.height_address_mode = SamplerAddressMode::kDecal;
127  }
128 
129  FS::BindTextureSampler(
130  cmd, input_snapshot->texture,
131  renderer.GetContext()->GetSamplerLibrary()->GetSampler(
132  sampler_descriptor));
133  VS::BindFrameInfo(cmd, host_buffer.EmplaceUniform(frame_info));
134  FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info));
135 
136  return pass.AddCommand(std::move(cmd));
137  };
138 
139  fml::StatusOr<RenderTarget> render_target = renderer.MakeSubpass(
140  "Directional Morphology Filter", ISize(coverage.GetSize()), callback);
141  if (!render_target.ok()) {
142  return std::nullopt;
143  }
144 
145  SamplerDescriptor sampler_desc;
146  sampler_desc.min_filter = MinMagFilter::kLinear;
147  sampler_desc.mag_filter = MinMagFilter::kLinear;
148 
149  return Entity::FromSnapshot(
150  Snapshot{.texture = render_target.value().GetRenderTargetTexture(),
151  .transform = Matrix::MakeTranslation(coverage.GetOrigin()),
152  .sampler_descriptor = sampler_desc,
153  .opacity = input_snapshot->opacity},
154  entity.GetBlendMode(), entity.GetClipDepth());
155 }
156 
158  const FilterInput::Vector& inputs,
159  const Entity& entity,
160  const Matrix& effect_transform) const {
161  if (inputs.empty()) {
162  return std::nullopt;
163  }
164 
165  auto coverage = inputs[0]->GetCoverage(entity);
166  if (!coverage.has_value()) {
167  return std::nullopt;
168  }
169  auto transform = inputs[0]->GetTransform(entity) * effect_transform.Basis();
170  auto transformed_vector =
171  transform.TransformDirection(direction_ * radius_.radius).Abs();
172 
173  auto origin = coverage->GetOrigin();
174  auto size = Vector2(coverage->GetSize());
175  switch (morph_type_) {
177  origin -= transformed_vector;
178  size += transformed_vector * 2;
179  break;
181  origin += transformed_vector;
182  size -= transformed_vector * 2;
183  break;
184  }
185  if (size.x < 0 || size.y < 0) {
186  return Rect::MakeSize(Size(0, 0));
187  }
188  return Rect::MakeOriginSize(origin, Size(size.x, size.y));
189 }
190 
191 std::optional<Rect>
193  const Matrix& effect_transform,
194  const Rect& output_limit) const {
195  auto transformed_vector =
196  effect_transform.TransformDirection(direction_ * radius_.radius).Abs();
197  switch (morph_type_) {
199  return output_limit.Expand(-transformed_vector);
201  return output_limit.Expand(transformed_vector);
202  }
203 }
204 
205 } // 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:28
impeller::Radius::radius
Scalar radius
Definition: sigma.h:49
contents.h
impeller::FilterContents::MorphType::kErode
@ kErode
impeller::DirectionalMorphologyFilterContents::~DirectionalMorphologyFilterContents
~DirectionalMorphologyFilterContents() override
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Entity::GetTransform
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:49
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::DirectionalMorphologyFilterContents::GetFilterCoverage
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...
Definition: morphology_filter_contents.cc:157
impeller::BlendMode::kSource
@ kSource
formats.h
impeller::Vector2
Point Vector2
Definition: point.h:312
impeller::RenderPipelineT::FragmentShader
FragmentShader_ FragmentShader
Definition: pipeline.h:93
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::TRect::GetOrigin
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified when it was constructed.
Definition: rect.h:154
impeller::DirectionalMorphologyFilterContents::SetRadius
void SetRadius(Radius radius)
Definition: morphology_filter_contents.cc:23
impeller::TPoint::IsZero
constexpr bool IsZero() const
Definition: point.h:229
impeller::Entity
Definition: entity.h:21
impeller::Matrix::Basis
constexpr Matrix Basis() const
The Matrix without its w components (without translation).
Definition: matrix.h:224
morphology_filter_contents.h
impeller::PrimitiveType::kTriangleStrip
@ kTriangleStrip
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
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:48
impeller::TRect::GetTransformedPoints
constexpr std::array< TPoint< T >, 4 > GetTransformedPoints(const Matrix &transform) const
Definition: rect.h:253
impeller::MinMagFilter::kLinear
@ kLinear
impeller::TRect< Scalar >::MakeOriginSize
constexpr static TRect MakeOriginSize(const TPoint< Type > &origin, const TSize< Type > &size)
Definition: rect.h:38
impeller::DirectionalMorphologyFilterContents::DirectionalMorphologyFilterContents
DirectionalMorphologyFilterContents()
impeller::DirectionalMorphologyFilterContents::SetDirection
void SetDirection(Vector2 direction)
Definition: morphology_filter_contents.cc:27
impeller::Entity::GetBlendMode
BlendMode GetBlendMode() const
Definition: entity.cc:105
impeller::ContentContext::SubpassCallback
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
Definition: content_context.h:708
impeller::Matrix::TransformDirection
constexpr Vector4 TransformDirection(const Vector4 &v) const
Definition: matrix.h:433
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:138
impeller::Entity::GetClipDepth
uint32_t GetClipDepth() const
Definition: entity.cc:93
content_context.h
impeller::TRect::GetSize
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle as specified when it was constructed and which may be negative in e...
Definition: rect.h:159
impeller::TRect< Scalar >::MakeSize
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:44
impeller::FilterContents::MorphType::kDilate
@ kDilate
impeller::TPoint< Scalar >
impeller::DirectionalMorphologyFilterContents::GetFilterSourceCoverage
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...
Definition: morphology_filter_contents.cc:192
impeller::Matrix::MakeOrthographic
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition: matrix.h:459
impeller::DirectionalMorphologyFilterContents::SetMorphType
void SetMorphType(MorphType morph_type)
Definition: morphology_filter_contents.cc:34
impeller::FilterInput::Vector
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:33
impeller::Entity::FromSnapshot
static std::optional< Entity > FromSnapshot(const std::optional< Snapshot > &snapshot, BlendMode blend_mode=BlendMode::kSourceOver, uint32_t clip_depth=0)
Create an entity that can be used to render a given snapshot.
Definition: entity.cc:21
impeller::TPoint::Normalize
constexpr TPoint Normalize() const
Definition: point.h:203
impeller::RenderPipelineT::VertexShader
VertexShader_ VertexShader
Definition: pipeline.h:92
impeller
Definition: aiks_context.cc:10
impeller::ContentContext
Definition: content_context.h:332
impeller::TRect
Definition: rect.h:22
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::TRect::Expand
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:373
vertex_buffer_builder.h
impeller::SamplerAddressMode::kDecal
@ kDecal
decal sampling mode is only supported on devices that pass the Capabilities.SupportsDecalSamplerAddre...