[Impeller] Improved documentation of the gaussian blur. (#47283)
Just trying to capture some of my thoughts as I look into some blur
bugs.
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide] and the [C++,
Objective-C, Java style guides].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I added new tests to check the change I am making or feature I am
adding, or the PR is [test-exempt]. See [testing the engine] for
instructions on writing and running engine tests.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I signed the [CLA].
- [x] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-new channel
on [Discord].
<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[C++, Objective-C, Java style guides]:
https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
[testing the engine]:
https://github.com/flutter/flutter/wiki/Testing-the-engine
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index c31a993..01c5954 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1837,10 +1837,10 @@
ORIGIN: ../../../flutter/impeller/entity/contents/filters/color_filter_contents.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/filters/color_matrix_filter_contents.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/filters/color_matrix_filter_contents.h + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/filters/filter_contents.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/filters/filter_contents.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/contents_filter_input.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/contents_filter_input.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc + ../../../flutter/LICENSE
@@ -4618,10 +4618,10 @@
FILE: ../../../flutter/impeller/entity/contents/filters/color_filter_contents.h
FILE: ../../../flutter/impeller/entity/contents/filters/color_matrix_filter_contents.cc
FILE: ../../../flutter/impeller/entity/contents/filters/color_matrix_filter_contents.h
+FILE: ../../../flutter/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc
+FILE: ../../../flutter/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h
FILE: ../../../flutter/impeller/entity/contents/filters/filter_contents.cc
FILE: ../../../flutter/impeller/entity/contents/filters/filter_contents.h
-FILE: ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
-FILE: ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents.h
FILE: ../../../flutter/impeller/entity/contents/filters/inputs/contents_filter_input.cc
FILE: ../../../flutter/impeller/entity/contents/filters/inputs/contents_filter_input.h
FILE: ../../../flutter/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc
diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn
index b82162b..fbf674c 100644
--- a/impeller/entity/BUILD.gn
+++ b/impeller/entity/BUILD.gn
@@ -158,10 +158,10 @@
"contents/filters/color_filter_contents.h",
"contents/filters/color_matrix_filter_contents.cc",
"contents/filters/color_matrix_filter_contents.h",
+ "contents/filters/directional_gaussian_blur_filter_contents.cc",
+ "contents/filters/directional_gaussian_blur_filter_contents.h",
"contents/filters/filter_contents.cc",
"contents/filters/filter_contents.h",
- "contents/filters/gaussian_blur_filter_contents.cc",
- "contents/filters/gaussian_blur_filter_contents.h",
"contents/filters/inputs/contents_filter_input.cc",
"contents/filters/inputs/contents_filter_input.h",
"contents/filters/inputs/filter_contents_filter_input.cc",
diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc
similarity index 99%
rename from impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
rename to impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc
index bd954d8..7aad9e8 100644
--- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc
+++ b/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h"
+#include "impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h"
#include <cmath>
#include <utility>
diff --git a/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h b/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h
new file mode 100644
index 0000000..2fbf984
--- /dev/null
+++ b/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h
@@ -0,0 +1,101 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <memory>
+#include <optional>
+#include "impeller/entity/contents/filters/filter_contents.h"
+#include "impeller/entity/contents/filters/inputs/filter_input.h"
+
+namespace impeller {
+
+/// A gaussian blur filter that performs the work for one dimension of a
+/// multi-dimensional Gaussian blur.
+///
+/// This filter takes a snapshot of its provided FilterInput, creates a new
+/// render pass and blurs the contents. Two of these are chained together to
+/// perform a full 2D blur effect.
+///
+/// Example:
+///
+/// Input Pass 1
+/// +-------------+ +-----+
+/// | | | |
+/// | | | | Pass 2
+/// | | | | +----+
+/// | | | | | |
+/// | | -> | | -> | |
+/// | | | | | |
+/// | | | | +----+
+/// | | | | 87x102
+/// +-------------+ +-----+
+/// 586x678 97x678
+///
+/// The math for determining how much of the input should be processed for a
+/// given sigma (aka radius) is found in `Sigma::operator Radius`. The math for
+/// determining how much to scale down the input based on the radius is inside
+/// the curve function in this implementation.
+///
+/// See also:
+/// - `FilterContents::MakeGaussianBlur`
+/// - //flutter/impeller/entity/shaders/gaussian_blur/gaussian_blur.glsl
+///
+class DirectionalGaussianBlurFilterContents final : public FilterContents {
+ public:
+ DirectionalGaussianBlurFilterContents();
+
+ ~DirectionalGaussianBlurFilterContents() override;
+
+ /// Set sigma (stddev) used for 'direction_'.
+ void SetSigma(Sigma sigma);
+
+ /// Set sigma (stddev) used for direction 90 degrees from 'direction_'.
+ /// Not used if `!is_second_pass_`.
+ void SetSecondarySigma(Sigma sigma);
+
+ void SetDirection(Vector2 direction);
+
+ void SetBlurStyle(BlurStyle blur_style);
+
+ void SetTileMode(Entity::TileMode tile_mode);
+
+ /// Determines if this filter represents the second pass in a chained
+ /// 2D gaussian blur.
+ /// If `is_second_pass_ == true` then the `secondary_sigma_` is used to
+ /// determine the blur radius in the 90 degree rotation of direction_. Its
+ /// output aspect-ratio will closely match the FilterInput snapshot at the
+ /// beginning of the chain.
+ void SetIsSecondPass(bool is_second_pass);
+
+ // |FilterContents|
+ std::optional<Rect> GetFilterCoverage(
+ const FilterInput::Vector& inputs,
+ const Entity& entity,
+ const Matrix& effect_transform) const override;
+
+ private:
+ // |FilterContents|
+ std::optional<Entity> RenderFilter(
+ const FilterInput::Vector& input_textures,
+ const ContentContext& renderer,
+ const Entity& entity,
+ const Matrix& effect_transform,
+ const Rect& coverage,
+ const std::optional<Rect>& coverage_hint) const override;
+ Sigma blur_sigma_;
+ Sigma secondary_blur_sigma_;
+ Vector2 blur_direction_;
+ BlurStyle blur_style_ = BlurStyle::kNormal;
+ Entity::TileMode tile_mode_ = Entity::TileMode::kDecal;
+ bool is_second_pass_ = false;
+
+ DirectionalGaussianBlurFilterContents(
+ const DirectionalGaussianBlurFilterContents&) = delete;
+
+ DirectionalGaussianBlurFilterContents& operator=(
+ const DirectionalGaussianBlurFilterContents&) = delete;
+};
+
+} // namespace impeller
diff --git a/impeller/entity/contents/filters/filter_contents.cc b/impeller/entity/contents/filters/filter_contents.cc
index c5e2ae2..617a2a6 100644
--- a/impeller/entity/contents/filters/filter_contents.cc
+++ b/impeller/entity/contents/filters/filter_contents.cc
@@ -16,7 +16,7 @@
#include "impeller/core/formats.h"
#include "impeller/entity/contents/content_context.h"
#include "impeller/entity/contents/filters/border_mask_blur_filter_contents.h"
-#include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h"
+#include "impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
#include "impeller/entity/contents/filters/local_matrix_filter_contents.h"
#include "impeller/entity/contents/filters/matrix_filter_contents.h"
diff --git a/impeller/entity/contents/filters/filter_contents.h b/impeller/entity/contents/filters/filter_contents.h
index 9ff5e30..f61d726 100644
--- a/impeller/entity/contents/filters/filter_contents.h
+++ b/impeller/entity/contents/filters/filter_contents.h
@@ -31,6 +31,8 @@
enum class MorphType { kDilate, kErode };
+ /// Creates a gaussian blur that operates in one direction.
+ /// See also: `MakeGaussianBlur`
static std::shared_ptr<FilterContents> MakeDirectionalGaussianBlur(
FilterInput::Ref input,
Sigma sigma,
@@ -40,6 +42,8 @@
bool is_second_pass = false,
Sigma secondary_sigma = {});
+ /// Creates a gaussian blur that operates in 2 dimensions.
+ /// See also: `MakeDirectionalGaussianBlur`
static std::shared_ptr<FilterContents> MakeGaussianBlur(
const FilterInput::Ref& input,
Sigma sigma_x,
diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.h b/impeller/entity/contents/filters/gaussian_blur_filter_contents.h
deleted file mode 100644
index cdd46d4..0000000
--- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#pragma once
-
-#include <memory>
-#include <optional>
-#include "impeller/entity/contents/filters/filter_contents.h"
-#include "impeller/entity/contents/filters/inputs/filter_input.h"
-
-namespace impeller {
-
-class DirectionalGaussianBlurFilterContents final : public FilterContents {
- public:
- DirectionalGaussianBlurFilterContents();
-
- ~DirectionalGaussianBlurFilterContents() override;
-
- void SetSigma(Sigma sigma);
-
- void SetSecondarySigma(Sigma sigma);
-
- void SetDirection(Vector2 direction);
-
- void SetBlurStyle(BlurStyle blur_style);
-
- void SetTileMode(Entity::TileMode tile_mode);
-
- void SetIsSecondPass(bool is_second_pass);
-
- // |FilterContents|
- std::optional<Rect> GetFilterCoverage(
- const FilterInput::Vector& inputs,
- const Entity& entity,
- const Matrix& effect_transform) const override;
-
- private:
- // |FilterContents|
- std::optional<Entity> RenderFilter(
- const FilterInput::Vector& input_textures,
- const ContentContext& renderer,
- const Entity& entity,
- const Matrix& effect_transform,
- const Rect& coverage,
- const std::optional<Rect>& coverage_hint) const override;
- Sigma blur_sigma_;
- Sigma secondary_blur_sigma_;
- Vector2 blur_direction_;
- BlurStyle blur_style_ = BlurStyle::kNormal;
- Entity::TileMode tile_mode_ = Entity::TileMode::kDecal;
- bool is_second_pass_ = false;
-
- DirectionalGaussianBlurFilterContents(
- const DirectionalGaussianBlurFilterContents&) = delete;
-
- DirectionalGaussianBlurFilterContents& operator=(
- const DirectionalGaussianBlurFilterContents&) = delete;
-};
-
-} // namespace impeller
diff --git a/impeller/geometry/matrix.h b/impeller/geometry/matrix.h
index 8a1f791..53214b2 100644
--- a/impeller/geometry/matrix.h
+++ b/impeller/geometry/matrix.h
@@ -219,6 +219,7 @@
// clang-format on
}
+ /// The Matrix without its `w` components (without translation).
constexpr Matrix Basis() const {
// clang-format off
return Matrix(