blob: 5139204d7c2affd790ef91c37017c52cd96a233b [file] [log] [blame]
// 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 "flutter/testing/testing.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/save_layer_utils.h"
// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
// NOLINTBEGIN(bugprone-unchecked-optional-access)
namespace impeller {
namespace testing {
using SaveLayerUtilsTest = ::testing::Test;
TEST(SaveLayerUtilsTest, SimplePaintComputedCoverage) {
// Basic Case, simple paint, computed coverage
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/nullptr //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
}
TEST(SaveLayerUtilsTest, BackdropFiterComputedCoverage) {
// Backdrop Filter, computed coverage
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/nullptr,
/*flood_output_coverage=*/false, //
/*flood_input_coverage=*/true //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
}
TEST(SaveLayerUtilsTest, ImageFiterComputedCoverage) {
// Image Filter, computed coverage
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/image_filter //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
}
TEST(SaveLayerUtilsTest,
ImageFiterSmallScaleComputedCoverageLargerThanBoundsLimit) {
// Image Filter scaling large, computed coverage is larger than bounds limit.
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 5, 5), //
/*image_filter=*/image_filter //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2.5, 2.5));
}
TEST(SaveLayerUtilsTest,
ImageFiterLargeScaleComputedCoverageLargerThanBoundsLimit) {
// Image Filter scaling small, computed coverage is larger than bounds limit.
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeScale({0.5, 0.5, 1}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 10, 10), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 5, 5), //
/*image_filter=*/image_filter //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
}
TEST(SaveLayerUtilsTest, DisjointCoverage) {
// No intersection in coverage
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/nullptr //
);
EXPECT_FALSE(coverage.has_value());
}
TEST(SaveLayerUtilsTest, DisjointCoverageTransformedByImageFilter) {
// Coverage disjoint from parent coverage but transformed into parent space
// with image filter.
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeTranslation({-200, -200, 0}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/image_filter //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(200, 200, 210, 210));
}
TEST(SaveLayerUtilsTest, DisjointCoveragTransformedByCTM) {
// Coverage disjoint from parent coverage.
Matrix ctm = Matrix::MakeTranslation({-200, -200, 0});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(200, 200, 210, 210), //
/*effect_transform=*/ctm, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/nullptr //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10));
}
TEST(SaveLayerUtilsTest, BasicEmptyCoverage) {
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/nullptr //
);
ASSERT_FALSE(coverage.has_value());
}
TEST(SaveLayerUtilsTest, ImageFilterEmptyCoverage) {
// Empty coverage with Image Filter
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeTranslation({-200, -200, 0}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/image_filter //
);
ASSERT_FALSE(coverage.has_value());
}
TEST(SaveLayerUtilsTest, BackdropFilterEmptyCoverage) {
// Empty coverage with backdrop filter.
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/nullptr, //
/*flood_output_coverage=*/true //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
}
TEST(SaveLayerUtilsTest, FloodInputCoverage) {
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/nullptr, //
/*flood_output_coverage=*/false, //
/*flood_input_coverage=*/true //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800));
}
TEST(SaveLayerUtilsTest, FloodInputCoverageWithImageFilter) {
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeScale({0.5, 0.5, 1}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/image_filter, //
/*flood_output_coverage=*/false, //
/*flood_input_coverage=*/true //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 4800, 3600));
}
TEST(SaveLayerUtilsTest,
FloodInputCoverageWithImageFilterWithNoCoverageProducesNoCoverage) {
// Even if we flood the input coverage due to a bdf, we can still cull out the
// layer if the image filter results in no coverage.
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeScale({1, 1, 0}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 0, 0), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 2400, 1800), //
/*image_filter=*/image_filter, //
/*flood_output_coverage=*/false, //
/*flood_input_coverage=*/true //
);
ASSERT_FALSE(coverage.has_value());
}
TEST(
SaveLayerUtilsTest,
CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageSmallerWithImageFilter) {
// Create an image filter that slightly shrinks the coverage limit
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeScale({1.1, 1.1, 1}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/image_filter //
);
ASSERT_TRUE(coverage.has_value());
// The transfomed coverage limit is ((0, 0), (90.9091, 90.9091)).
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
}
TEST(
SaveLayerUtilsTest,
CoverageLimitIgnoredIfIntersectedValueIsCloseToActualCoverageLargerWithImageFilter) {
// Create an image filter that slightly stretches the coverage limit. Even
// without the special logic for using the original content coverage, we
// verify that we don't introduce any artifacts from the intersection.
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeScale({0.9, 0.9, 1}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/image_filter //
);
ASSERT_TRUE(coverage.has_value());
// The transfomed coverage limit is ((0, 0), (111.111, 111.111)).
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
}
TEST(SaveLayerUtilsTest,
CoverageLimitRespectedIfSubstantiallyDifferentFromContentCoverge) {
auto image_filter = FilterContents::MakeMatrixFilter(
FilterInput::Make(Rect()), Matrix::MakeScale({2, 2, 1}), {});
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 1000, 1000), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/image_filter //
);
ASSERT_TRUE(coverage.has_value());
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
}
TEST(SaveLayerUtilsTest, RoundUpCoverageWhenCloseToCoverageLimit) {
// X varies, translation is performed on coverage.
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 90, 90), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/nullptr //
);
ASSERT_TRUE(coverage.has_value());
// Size that matches coverage limit
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 100, 100));
}
TEST(SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitWidth) {
// X varies, translation is performed on coverage.
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 50, 90), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/nullptr //
);
ASSERT_TRUE(coverage.has_value());
// Size that matches coverage limit
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 90));
}
TEST(SaveLayerUtilsTest, DontRoundUpCoverageWhenNotCloseToCoverageLimitHeight) {
// X varies, translation is performed on coverage.
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 90, 50), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/nullptr //
);
ASSERT_TRUE(coverage.has_value());
// Size that matches coverage limit
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 90, 50));
}
TEST(SaveLayerUtilsTest,
DontRoundUpCoverageWhenNotCloseToCoverageLimitWidthHeight) {
// X varies, translation is performed on coverage.
auto coverage = ComputeSaveLayerCoverage(
/*content_coverage=*/Rect::MakeLTRB(0, 0, 50, 50), //
/*effect_transform=*/{}, //
/*coverage_limit=*/Rect::MakeLTRB(0, 0, 100, 100), //
/*image_filter=*/nullptr //
);
ASSERT_TRUE(coverage.has_value());
// Size that matches coverage limit
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 50, 50));
}
} // namespace testing
} // namespace impeller
// NOLINTEND(bugprone-unchecked-optional-access)