Flutter Impeller
paint.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/aiks/paint.h"
6 
7 #include <memory>
8 
15 
16 namespace impeller {
17 
18 /// A color matrix which inverts colors.
19 // clang-format off
21  .array = {
22  -1.0, 0, 0, 1.0, 0, //
23  0, -1.0, 0, 1.0, 0, //
24  0, 0, -1.0, 1.0, 0, //
25  1.0, 1.0, 1.0, 1.0, 0 //
26  }
27 };
28 // clang-format on
29 
30 std::shared_ptr<Contents> Paint::CreateContentsForGeometry(
31  const std::shared_ptr<Geometry>& geometry) const {
32  auto contents = color_source.GetContents(*this);
33 
34  // Attempt to apply the color filter on the CPU first.
35  // Note: This is not just an optimization; some color sources rely on
36  // CPU-applied color filters to behave properly.
38  bool needs_color_filter = !!color_filter;
39  if (color_filter &&
40  contents->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
41  needs_color_filter = false;
42  }
43 
44  contents->SetGeometry(geometry);
45  if (mask_blur_descriptor.has_value()) {
46  // If there's a mask blur and we need to apply the color filter on the GPU,
47  // we need to be careful to only apply the color filter to the source
48  // colors. CreateMaskBlur is able to handle this case.
49  return mask_blur_descriptor->CreateMaskBlur(
50  contents, needs_color_filter ? color_filter : nullptr);
51  }
52 
53  return contents;
54 }
55 
56 std::shared_ptr<Contents> Paint::WithFilters(
57  std::shared_ptr<Contents> input) const {
58  input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
59  auto image_filter =
61  if (image_filter) {
62  input = image_filter;
63  }
64  return input;
65 }
66 
67 std::shared_ptr<Contents> Paint::WithFiltersForSubpassTarget(
68  std::shared_ptr<Contents> input,
69  const Matrix& effect_transform) const {
70  auto image_filter =
71  WithImageFilter(input, effect_transform,
73  if (image_filter) {
74  input = image_filter;
75  }
76  input = WithColorFilter(input, ColorFilterContents::AbsorbOpacity::kYes);
77  return input;
78 }
79 
80 std::shared_ptr<Contents> Paint::WithMaskBlur(std::shared_ptr<Contents> input,
81  bool is_solid_color,
82  const Matrix& ctm) const {
83  if (mask_blur_descriptor.has_value()) {
84  input = mask_blur_descriptor->CreateMaskBlur(FilterInput::Make(input),
85  is_solid_color, ctm);
86  }
87  return input;
88 }
89 
90 std::shared_ptr<FilterContents> Paint::WithImageFilter(
91  const FilterInput::Variant& input,
92  const Matrix& effect_transform,
93  Entity::RenderingMode rendering_mode) const {
94  if (!image_filter) {
95  return nullptr;
96  }
97  auto filter = image_filter->WrapInput(FilterInput::Make(input));
98  filter->SetRenderingMode(rendering_mode);
99  filter->SetEffectTransform(effect_transform);
100  return filter;
101 }
102 
103 std::shared_ptr<Contents> Paint::WithColorFilter(
104  std::shared_ptr<Contents> input,
105  ColorFilterContents::AbsorbOpacity absorb_opacity) const {
106  // Image input types will directly set their color filter,
107  // if any. See `TiledTextureContents.SetColorFilter`.
109  return input;
110  }
111 
112  auto color_filter = GetColorFilter();
113  if (!color_filter) {
114  return input;
115  }
116 
117  // Attempt to apply the color filter on the CPU first.
118  // Note: This is not just an optimization; some color sources rely on
119  // CPU-applied color filters to behave properly.
120  if (input->ApplyColorFilter(color_filter->GetCPUColorFilterProc())) {
121  return input;
122  }
123  return color_filter->WrapWithGPUColorFilter(FilterInput::Make(input),
124  absorb_opacity);
125 }
126 
127 std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
128  std::shared_ptr<TextureContents> texture_contents) const {
131  texture_contents->SetSourceRect(
132  texture_contents->GetSourceRect().Expand(expand_amount, expand_amount));
133  auto mask = std::make_shared<SolidColorContents>();
134  mask->SetColor(Color::White());
135  std::optional<Rect> coverage = texture_contents->GetCoverage({});
136  std::shared_ptr<Geometry> geometry;
137  if (coverage) {
138  texture_contents->SetDestinationRect(
139  coverage.value().Expand(expand_amount, expand_amount));
140  geometry = Geometry::MakeRect(coverage.value());
141  }
142  mask->SetGeometry(geometry);
143  auto descriptor = texture_contents->GetSamplerDescriptor();
144  texture_contents->SetSamplerDescriptor(descriptor);
145  std::shared_ptr<FilterContents> blurred_mask =
148  geometry);
149 
152  {FilterInput::Make(blurred_mask), FilterInput::Make(texture_contents)});
153 }
154 
155 std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
156  std::shared_ptr<ColorSourceContents> color_source_contents,
157  const std::shared_ptr<ColorFilter>& color_filter) const {
158  // If it's a solid color and there is no color filter, then we can just get
159  // away with doing one Gaussian blur.
160  if (color_source_contents->IsSolidColor() && !color_filter) {
162  FilterInput::Make(color_source_contents), sigma, sigma,
163  Entity::TileMode::kDecal, style, color_source_contents->GetGeometry());
164  }
165 
166  /// 1. Create an opaque white mask of the original geometry.
167 
168  auto mask = std::make_shared<SolidColorContents>();
169  mask->SetColor(Color::White());
170  mask->SetGeometry(color_source_contents->GetGeometry());
171 
172  /// 2. Blur the mask.
173 
174  auto blurred_mask = FilterContents::MakeGaussianBlur(
175  FilterInput::Make(mask), sigma, sigma, Entity::TileMode::kDecal, style,
176  color_source_contents->GetGeometry());
177 
178  /// 3. Replace the geometry of the original color source with a rectangle that
179  /// covers the full region of the blurred mask. Note that geometry is in
180  /// local bounds.
181 
182  auto expanded_local_bounds = blurred_mask->GetCoverage({});
183  if (!expanded_local_bounds.has_value()) {
184  expanded_local_bounds = Rect();
185  }
186  color_source_contents->SetGeometry(
187  Geometry::MakeRect(*expanded_local_bounds));
188  std::shared_ptr<Contents> color_contents = color_source_contents;
189 
190  /// 4. Apply the user set color filter on the GPU, if applicable.
191 
192  if (color_filter) {
193  color_contents = color_filter->WrapWithGPUColorFilter(
194  FilterInput::Make(color_source_contents),
196  }
197 
198  /// 5. Composite the color source with the blurred mask.
199 
202  {FilterInput::Make(blurred_mask), FilterInput::Make(color_contents)});
203 }
204 
205 std::shared_ptr<FilterContents> Paint::MaskBlurDescriptor::CreateMaskBlur(
206  const FilterInput::Ref& input,
207  bool is_solid_color,
208  const Matrix& ctm) const {
209  Vector2 blur_sigma(sigma.sigma, sigma.sigma);
210  if (!respect_ctm) {
211  blur_sigma /= Vector2(ctm.GetBasisX().Length(), ctm.GetBasisY().Length());
212  }
213  if (is_solid_color) {
214  return FilterContents::MakeGaussianBlur(input, Sigma(blur_sigma.x),
215  Sigma(blur_sigma.y),
217  }
218  return FilterContents::MakeBorderMaskBlur(input, Sigma(blur_sigma.x),
219  Sigma(blur_sigma.y), style);
220 }
221 
222 std::shared_ptr<ColorFilter> Paint::GetColorFilter() const {
223  if (invert_colors && color_filter) {
225  return ColorFilter::MakeComposed(filter, color_filter);
226  }
227  if (invert_colors) {
229  }
230  if (color_filter) {
231  return color_filter;
232  }
233  return nullptr;
234 }
235 
236 bool Paint::HasColorFilter() const {
237  return !!color_filter || invert_colors;
238 }
239 
240 } // namespace impeller
impeller::Sigma::sigma
Scalar sigma
Definition: sigma.h:33
impeller::ColorSource::GetContents
std::shared_ptr< ColorSourceContents > GetContents(const Paint &paint) const
Definition: color_source.cc:264
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::Scalar
float Scalar
Definition: scalar.h:18
solid_color_contents.h
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::Paint::MaskBlurDescriptor::sigma
Sigma sigma
Definition: paint.h:50
impeller::Entity::TileMode::kDecal
@ kDecal
impeller::ColorFilter::MakeComposed
static std::shared_ptr< ColorFilter > MakeComposed(const std::shared_ptr< ColorFilter > &outer, const std::shared_ptr< ColorFilter > &inner)
Definition: color_filter.cc:40
impeller::Paint::MaskBlurDescriptor::style
FilterContents::BlurStyle style
Definition: paint.h:49
impeller::FilterInput::Ref
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
impeller::Vector2
Point Vector2
Definition: point.h:326
impeller::Paint::MaskBlurDescriptor::CreateMaskBlur
std::shared_ptr< FilterContents > CreateMaskBlur(std::shared_ptr< ColorSourceContents > color_source_contents, const std::shared_ptr< ColorFilter > &color_filter) const
Definition: paint.cc:155
gaussian_blur_filter_contents.h
impeller::GaussianBlurFilterContents::CalculateBlurRadius
static Scalar CalculateBlurRadius(Scalar sigma)
Definition: gaussian_blur_filter_contents.cc:768
impeller::Paint::color_source
ColorSource color_source
Definition: paint.h:69
impeller::Paint::color_filter
std::shared_ptr< ColorFilter > color_filter
Definition: paint.h:80
impeller::kColorInversion
constexpr ColorMatrix kColorInversion
A color matrix which inverts colors.
Definition: paint.cc:20
filter_contents.h
color_source_contents.h
impeller::Paint::GetColorFilter
std::shared_ptr< ColorFilter > GetColorFilter() const
Definition: paint.cc:222
impeller::Paint::style
Style style
Definition: paint.h:75
impeller::ColorMatrix::array
Scalar array[20]
Definition: color.h:118
geometry.h
impeller::Color::White
static constexpr Color White()
Definition: color.h:266
impeller::Sigma
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
impeller::Entity::RenderingMode::kDirect
@ kDirect
impeller::FilterInput::Variant
std::variant< std::shared_ptr< FilterContents >, std::shared_ptr< Contents >, std::shared_ptr< Texture >, Rect > Variant
Definition: filter_input.h:37
impeller::Vector3::Length
constexpr Scalar Length() const
Definition: vector.h:47
impeller::Rect
TRect< Scalar > Rect
Definition: rect.h:769
impeller::FilterContents::MakeBorderMaskBlur
static std::shared_ptr< FilterContents > MakeBorderMaskBlur(FilterInput::Ref input, Sigma sigma_x, Sigma sigma_y, BlurStyle blur_style=BlurStyle::kNormal)
Definition: filter_contents.cc:49
color_filter_contents.h
impeller::TPoint::x
Type x
Definition: point.h:30
impeller::ColorFilter::MakeMatrix
static std::shared_ptr< ColorFilter > MakeMatrix(ColorMatrix color_matrix)
Definition: color_filter.cc:28
impeller::Paint::WithMaskBlur
std::shared_ptr< Contents > WithMaskBlur(std::shared_ptr< Contents > input, bool is_solid_color, const Matrix &ctm) const
Definition: paint.cc:80
impeller::Geometry::MakeRect
static std::shared_ptr< Geometry > MakeRect(const Rect &rect)
Definition: geometry.cc:89
impeller::ColorSource::Type::kImage
@ kImage
impeller::Paint::WithImageFilter
std::shared_ptr< FilterContents > WithImageFilter(const FilterInput::Variant &input, const Matrix &effect_transform, Entity::RenderingMode rendering_mode) const
Definition: paint.cc:90
impeller::Entity::RenderingMode::kSubpassPrependSnapshotTransform
@ kSubpassPrependSnapshotTransform
impeller::TPoint< Scalar >
impeller::Paint::invert_colors
bool invert_colors
Definition: paint.h:77
impeller::BlendMode::kSourceIn
@ kSourceIn
paint.h
impeller::Paint::HasColorFilter
bool HasColorFilter() const
Whether this paint has a color filter that can apply opacity.
Definition: paint.cc:236
impeller::Entity::RenderingMode
RenderingMode
Definition: entity.h:27
impeller::ColorFilterContents::AbsorbOpacity::kYes
@ kYes
impeller::ColorMatrix
Definition: color.h:117
impeller::ColorFilterContents::MakeBlend
static std::shared_ptr< ColorFilterContents > MakeBlend(BlendMode blend_mode, FilterInput::Vector inputs, std::optional< Color > foreground_color=std::nullopt)
the [inputs] are expected to be in the order of dst, src.
Definition: color_filter_contents.cc:17
impeller::ColorFilterContents::AbsorbOpacity
AbsorbOpacity
Definition: color_filter_contents.h:14
impeller::Matrix::GetBasisY
constexpr Vector3 GetBasisY() const
Definition: matrix.h:307
impeller
Definition: aiks_blend_unittests.cc:18
impeller::Paint::mask_blur_descriptor
std::optional< MaskBlurDescriptor > mask_blur_descriptor
Definition: paint.h:81
impeller::Matrix::GetBasisX
constexpr Vector3 GetBasisX() const
Definition: matrix.h:305
impeller::Paint::WithFilters
std::shared_ptr< Contents > WithFilters(std::shared_ptr< Contents > input) const
Wrap this paint's configured filters to the given contents.
Definition: paint.cc:56
impeller::ColorSource::GetType
Type GetType() const
Definition: color_source.cc:260
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Paint::WithFiltersForSubpassTarget
std::shared_ptr< Contents > WithFiltersForSubpassTarget(std::shared_ptr< Contents > input, const Matrix &effect_transform=Matrix()) const
Wrap this paint's configured filters to the given contents of subpass target.
Definition: paint.cc:67
impeller::Paint::CreateContentsForGeometry
std::shared_ptr< Contents > CreateContentsForGeometry(const std::shared_ptr< Geometry > &geometry) const
Definition: paint.cc:30
impeller::Paint::image_filter
std::shared_ptr< ImageFilter > image_filter
Definition: paint.h:79
impeller::GaussianBlurFilterContents::ScaleSigma
static Scalar ScaleSigma(Scalar sigma)
Definition: gaussian_blur_filter_contents.cc:788
impeller::FilterContents::MakeGaussianBlur
static std::shared_ptr< FilterContents > MakeGaussianBlur(const FilterInput::Ref &input, Sigma sigma_x, Sigma sigma_y, Entity::TileMode tile_mode=Entity::TileMode::kDecal, BlurStyle mask_blur_style=BlurStyle::kNormal, const std::shared_ptr< Geometry > &mask_geometry=nullptr)
Definition: filter_contents.cc:36