Flutter Impeller
gaussian_blur_filter_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_FILTERS_GAUSSIAN_BLUR_FILTER_CONTENTS_H_
6 #define FLUTTER_IMPELLER_ENTITY_CONTENTS_FILTERS_GAUSSIAN_BLUR_FILTER_CONTENTS_H_
7 
8 #include <optional>
13 
14 namespace impeller {
15 
16 // Comes from gaussian.frag.
17 static constexpr int32_t kGaussianBlurMaxKernelSize = 50;
18 
19 static_assert(sizeof(GaussianBlurPipeline::FragmentShader::KernelSamples) ==
20  sizeof(Vector4) * kGaussianBlurMaxKernelSize + sizeof(Vector4));
21 
26  int step_size;
27 };
28 
29 struct KernelSample {
31  float coefficient;
32 };
33 
34 /// A larger mirror of GaussianBlurPipeline::FragmentShader::KernelSamples.
35 ///
36 /// This is a mirror of GaussianBlurPipeline::FragmentShader::KernelSamples that
37 /// can hold 2x the max kernel size since it will get reduced with the lerp
38 /// hack.
39 struct KernelSamples {
40  static constexpr int kMaxKernelSize = kGaussianBlurMaxKernelSize * 2;
43 };
44 
46 
47 /// This will shrink the size of a kernel by roughly half by sampling between
48 /// samples and relying on linear interpolation between the samples.
49 GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(
50  KernelSamples samples);
51 
52 /// Performs a bidirectional Gaussian blur.
53 ///
54 /// This is accomplished by rendering multiple passes in multiple directions.
55 /// Note: This will replace `DirectionalGaussianBlurFilterContents`.
57  public:
58  explicit GaussianBlurFilterContents(Scalar sigma_x,
59  Scalar sigma_y,
60  Entity::TileMode tile_mode,
61  BlurStyle mask_blur_style,
62  const Geometry* mask_geometry = nullptr);
63 
64  Scalar GetSigmaX() const { return sigma_.x; }
65  Scalar GetSigmaY() const { return sigma_.y; }
66 
67  // |FilterContents|
68  std::optional<Rect> GetFilterSourceCoverage(
69  const Matrix& effect_transform,
70  const Rect& output_limit) const override;
71 
72  // |FilterContents|
73  std::optional<Rect> GetFilterCoverage(
74  const FilterInput::Vector& inputs,
75  const Entity& entity,
76  const Matrix& effect_transform) const override;
77 
78  /// Given a sigma (standard deviation) calculate the blur radius (1/2 the
79  /// kernel size).
80  static Scalar CalculateBlurRadius(Scalar sigma);
81 
82  /// Calculate the UV coordinates for rendering the filter_input.
83  /// @param filter_input The FilterInput that should be rendered.
84  /// @param entity The associated entity for the filter_input.
85  /// @param source_rect The rect in source coordinates to convert to uvs.
86  /// @param texture_size The rect to convert in source coordinates.
87  static Quad CalculateUVs(const std::shared_ptr<FilterInput>& filter_input,
88  const Entity& entity,
89  const Rect& source_rect,
90  const ISize& texture_size);
91 
92  /// Calculate the scale factor for the downsample pass given a sigma value.
93  ///
94  /// Visible for testing.
95  static Scalar CalculateScale(Scalar sigma);
96 
97  /// Scales down the sigma value to match Skia's behavior.
98  ///
99  /// effective_blur_radius = CalculateBlurRadius(ScaleSigma(sigma_));
100  ///
101  /// This function was calculated by observing Skia's behavior. Its blur at
102  /// 500 seemed to be 0.15. Since we clamp at 500 I solved the quadratic
103  /// equation that puts the minima there and a f(0)=1.
104  static Scalar ScaleSigma(Scalar sigma);
105 
106  private:
107  // |FilterContents|
108  std::optional<Entity> RenderFilter(
109  const FilterInput::Vector& input_textures,
110  const ContentContext& renderer,
111  const Entity& entity,
112  const Matrix& effect_transform,
113  const Rect& coverage,
114  const std::optional<Rect>& coverage_hint) const override;
115 
116  const Vector2 sigma_ = Vector2(0.0, 0.0);
117  const Entity::TileMode tile_mode_;
118  const BlurStyle mask_blur_style_;
119  const Geometry* mask_geometry_ = nullptr;
120 };
121 
122 } // namespace impeller
123 
124 #endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_FILTERS_GAUSSIAN_BLUR_FILTER_CONTENTS_H_
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:33
GaussianBlurFilterContents(Scalar sigma_x, Scalar sigma_y, Entity::TileMode tile_mode, BlurStyle mask_blur_style, const Geometry *mask_geometry=nullptr)
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...
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...
static Quad CalculateUVs(const std::shared_ptr< FilterInput > &filter_input, const Entity &entity, const Rect &source_rect, const ISize &texture_size)
Point Vector2
Definition: point.h:331
static constexpr int32_t kGaussianBlurMaxKernelSize
float Scalar
Definition: scalar.h:19
KernelSamples GenerateBlurInfo(BlurParameters parameters)
std::array< Point, 4 > Quad
Definition: point.h:332
GaussianBlurPipeline::FragmentShader::KernelSamples LerpHackKernelSamples(KernelSamples parameters)
KernelSample samples[kMaxKernelSize]
A 4x4 matrix using column-major storage.
Definition: matrix.h:37