diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index dc1f98f635e79..0fcc0e5822cf5 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1201,6 +1201,8 @@ ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/filter_contents ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/filter_input.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/filter_input.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/placeholder_filter_input.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/texture_filter_input.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/filters/inputs/texture_filter_input.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc + ../../../flutter/LICENSE @@ -3903,6 +3905,8 @@ FILE: ../../../flutter/impeller/entity/contents/filters/inputs/filter_contents_f FILE: ../../../flutter/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h FILE: ../../../flutter/impeller/entity/contents/filters/inputs/filter_input.cc FILE: ../../../flutter/impeller/entity/contents/filters/inputs/filter_input.h +FILE: ../../../flutter/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc +FILE: ../../../flutter/impeller/entity/contents/filters/inputs/placeholder_filter_input.h FILE: ../../../flutter/impeller/entity/contents/filters/inputs/texture_filter_input.cc FILE: ../../../flutter/impeller/entity/contents/filters/inputs/texture_filter_input.h FILE: ../../../flutter/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 8495a37a60a47..a09b7f965d4f0 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -175,6 +175,8 @@ impeller_component("entity") { "contents/filters/inputs/filter_contents_filter_input.h", "contents/filters/inputs/filter_input.cc", "contents/filters/inputs/filter_input.h", + "contents/filters/inputs/placeholder_filter_input.cc", + "contents/filters/inputs/placeholder_filter_input.h", "contents/filters/inputs/texture_filter_input.cc", "contents/filters/inputs/texture_filter_input.h", "contents/filters/linear_to_srgb_filter_contents.cc", diff --git a/impeller/entity/contents/filters/filter_contents.cc b/impeller/entity/contents/filters/filter_contents.cc index 36bb7bfecd419..91ef1f0aaffc8 100644 --- a/impeller/entity/contents/filters/filter_contents.cc +++ b/impeller/entity/contents/filters/filter_contents.cc @@ -277,4 +277,23 @@ Matrix FilterContents::GetTransform(const Matrix& parent_transform) const { return parent_transform * GetLocalTransform(parent_transform); } +bool FilterContents::IsLeaf() const { + for (auto& input : inputs_) { + if (!input->IsLeaf()) { + return false; + } + } + return true; +} + +void FilterContents::SetLeafInputs(const FilterInput::Vector& inputs) { + if (IsLeaf()) { + inputs_ = inputs; + return; + } + for (auto& input : inputs_) { + input->SetLeafInputs(inputs); + } +} + } // namespace impeller diff --git a/impeller/entity/contents/filters/filter_contents.h b/impeller/entity/contents/filters/filter_contents.h index 270277d1d1359..739f6531207a6 100644 --- a/impeller/entity/contents/filters/filter_contents.h +++ b/impeller/entity/contents/filters/filter_contents.h @@ -133,6 +133,15 @@ class FilterContents : public Contents { Matrix GetTransform(const Matrix& parent_transform) const; + /// @brief Returns `true` if this filter does not have any `FilterInput` + /// children. + bool IsLeaf() const; + + /// @brief Replaces the leaf of all leaf `FilterContents` with a new set + /// of `inputs`. + /// @see `FilterContents::IsLeaf` + void SetLeafInputs(const FilterInput::Vector& inputs); + private: virtual std::optional GetFilterCoverage( const FilterInput::Vector& inputs, diff --git a/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc b/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc index c1960a16406ee..5861247b962b1 100644 --- a/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc +++ b/impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc @@ -58,4 +58,13 @@ void FilterContentsFilterInput::PopulateGlyphAtlas( filter_->PopulateGlyphAtlas(lazy_glyph_atlas, scale); } +bool FilterContentsFilterInput::IsLeaf() const { + return false; +} + +void FilterContentsFilterInput::SetLeafInputs( + const FilterInput::Vector& inputs) { + filter_->SetLeafInputs(inputs); +} + } // namespace impeller diff --git a/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h b/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h index a4daf41066f6c..a10a5e5afe65e 100644 --- a/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h +++ b/impeller/entity/contents/filters/inputs/filter_contents_filter_input.h @@ -36,8 +36,14 @@ class FilterContentsFilterInput final : public FilterInput { const std::shared_ptr& lazy_glyph_atlas, Scalar scale) override; + // |FilterInput| + bool IsLeaf() const override; + + // |FilterInput| + void SetLeafInputs(const FilterInput::Vector& inputs) override; + private: - FilterContentsFilterInput(std::shared_ptr filter); + explicit FilterContentsFilterInput(std::shared_ptr filter); std::shared_ptr filter_; mutable std::optional snapshot_; diff --git a/impeller/entity/contents/filters/inputs/filter_input.cc b/impeller/entity/contents/filters/inputs/filter_input.cc index 8b9b10daca475..612a1f7221e35 100644 --- a/impeller/entity/contents/filters/inputs/filter_input.cc +++ b/impeller/entity/contents/filters/inputs/filter_input.cc @@ -11,6 +11,7 @@ #include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/filters/inputs/contents_filter_input.h" #include "impeller/entity/contents/filters/inputs/filter_contents_filter_input.h" +#include "impeller/entity/contents/filters/inputs/placeholder_filter_input.h" #include "impeller/entity/contents/filters/inputs/texture_filter_input.h" namespace impeller { @@ -32,6 +33,11 @@ FilterInput::Ref FilterInput::Make(Variant input, bool msaa_enabled) { return Make(*texture, Matrix()); } + if (auto rect = std::get_if(&input)) { + return std::shared_ptr( + new PlaceholderFilterInput(*rect)); + } + FML_UNREACHABLE(); } @@ -70,4 +76,10 @@ void FilterInput::PopulateGlyphAtlas( FilterInput::~FilterInput() = default; +bool FilterInput::IsLeaf() const { + return true; +} + +void FilterInput::SetLeafInputs(const FilterInput::Vector& inputs) {} + } // namespace impeller diff --git a/impeller/entity/contents/filters/inputs/filter_input.h b/impeller/entity/contents/filters/inputs/filter_input.h index 019c2acf914a9..3e84f1e76133b 100644 --- a/impeller/entity/contents/filters/inputs/filter_input.h +++ b/impeller/entity/contents/filters/inputs/filter_input.h @@ -32,7 +32,8 @@ class FilterInput { using Vector = std::vector; using Variant = std::variant, std::shared_ptr, - std::shared_ptr>; + std::shared_ptr, + Rect>; virtual ~FilterInput(); @@ -67,6 +68,15 @@ class FilterInput { virtual void PopulateGlyphAtlas( const std::shared_ptr& lazy_glyph_atlas, Scalar scale); + + /// @brief Returns `true` unless this input is a `FilterInput`, which may + /// take other inputs. + virtual bool IsLeaf() const; + + /// @brief Replaces the inputs of all leaf `FilterContents` with a new set + /// of `inputs`. + /// @see `FilterInput::IsLeaf` + virtual void SetLeafInputs(const FilterInput::Vector& inputs); }; } // namespace impeller diff --git a/impeller/entity/contents/filters/inputs/filter_input_unittests.cc b/impeller/entity/contents/filters/inputs/filter_input_unittests.cc index 0471a1ab64800..1f3d55fbc9849 100644 --- a/impeller/entity/contents/filters/inputs/filter_input_unittests.cc +++ b/impeller/entity/contents/filters/inputs/filter_input_unittests.cc @@ -5,8 +5,10 @@ #include #include "flutter/testing/testing.h" #include "gtest/gtest.h" +#include "impeller/entity/contents/filters/color_filter_contents.h" #include "impeller/entity/contents/filters/inputs/filter_input.h" #include "impeller/entity/entity.h" +#include "impeller/geometry/color.h" #include "impeller/geometry/geometry_asserts.h" namespace impeller { @@ -25,5 +27,41 @@ TEST(FilterInputTest, CanSetLocalTransformForTexture) { Matrix::MakeTranslation({1.0, 2.0, 0.0})); } +TEST(FilterInputTest, IsLeaf) { + std::shared_ptr leaf = + ColorFilterContents::MakeBlend(BlendMode::kSource, {}); + ASSERT_TRUE(leaf->IsLeaf()); + + auto base = ColorFilterContents::MakeMatrixFilter( + FilterInput::Make(leaf), Matrix(), {}, Matrix(), false); + + ASSERT_TRUE(leaf->IsLeaf()); + ASSERT_FALSE(base->IsLeaf()); +} + +TEST(FilterInputTest, SetCoverageInputs) { + std::shared_ptr leaf = + ColorFilterContents::MakeBlend(BlendMode::kSource, {}); + ASSERT_TRUE(leaf->IsLeaf()); + + auto base = ColorFilterContents::MakeMatrixFilter( + FilterInput::Make(leaf), Matrix(), {}, Matrix(), false); + + { + auto result = base->GetCoverage({}); + ASSERT_FALSE(result.has_value()); + } + + auto coverage_rect = Rect::MakeLTRB(100, 100, 200, 200); + base->SetLeafInputs(FilterInput::Make({coverage_rect})); + + { + auto result = base->GetCoverage({}); + ASSERT_TRUE(result.has_value()); + // NOLINTNEXTLINE(bugprone-unchecked-optional-access) + ASSERT_RECT_NEAR(result.value(), coverage_rect); + } +} + } // namespace testing } // namespace impeller diff --git a/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc b/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc new file mode 100644 index 0000000000000..5cc22d886ad16 --- /dev/null +++ b/impeller/entity/contents/filters/inputs/placeholder_filter_input.cc @@ -0,0 +1,40 @@ +// 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. + +#include "impeller/entity/contents/filters/inputs/placeholder_filter_input.h" + +#include +#include + +#include "impeller/base/strings.h" + +namespace impeller { + +PlaceholderFilterInput::PlaceholderFilterInput(Rect coverage_rect) + : coverage_rect_(coverage_rect) {} + +PlaceholderFilterInput::~PlaceholderFilterInput() = default; + +FilterInput::Variant PlaceholderFilterInput::GetInput() const { + return coverage_rect_; +} + +std::optional PlaceholderFilterInput::GetSnapshot( + const std::string& label, + const ContentContext& renderer, + const Entity& entity, + std::optional coverage_limit) const { + return std::nullopt; +} + +std::optional PlaceholderFilterInput::GetCoverage( + const Entity& entity) const { + return coverage_rect_; +} + +void PlaceholderFilterInput::PopulateGlyphAtlas( + const std::shared_ptr& lazy_glyph_atlas, + Scalar scale) {} + +} // namespace impeller diff --git a/impeller/entity/contents/filters/inputs/placeholder_filter_input.h b/impeller/entity/contents/filters/inputs/placeholder_filter_input.h new file mode 100644 index 0000000000000..09d5be61f1a6a --- /dev/null +++ b/impeller/entity/contents/filters/inputs/placeholder_filter_input.h @@ -0,0 +1,41 @@ +// 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 "impeller/entity/contents/filters/inputs/filter_input.h" + +namespace impeller { + +class PlaceholderFilterInput final : public FilterInput { + public: + explicit PlaceholderFilterInput(Rect coverage); + + ~PlaceholderFilterInput() override; + + // |FilterInput| + Variant GetInput() const override; + + // |FilterInput| + std::optional GetSnapshot( + const std::string& label, + const ContentContext& renderer, + const Entity& entity, + std::optional coverage_limit) const override; + + // |FilterInput| + std::optional GetCoverage(const Entity& entity) const override; + + // |FilterInput| + void PopulateGlyphAtlas( + const std::shared_ptr& lazy_glyph_atlas, + Scalar scale) override; + + private: + Rect coverage_rect_; + + friend FilterInput; +}; + +} // namespace impeller