[Impeller] Add 1 pixel border to snapshots of Contents (flutter/engine#42277)

Everything in Impeller is theoretically treated as if being drawn to
layers of infinite size. Without this change, there's a coverage leak
that occurs in some filters due to the customizable sampling mode. I
should be able to get rid of this 1 pixel padding by refactoring the way
we do sampling in the filter inputs (we already have most of this
infrastructure in place), but this is a correct, safe, and
not-that-expensive solution for the time being.
This commit is contained in:
Brandon DeRosier 2023-05-24 09:46:46 -07:00 committed by GitHub
parent 3a4677a6d7
commit d6a717c958
3 changed files with 56 additions and 3 deletions

View File

@ -64,13 +64,20 @@ std::optional<Snapshot> Contents::RenderToSnapshot(
bool msaa_enabled,
const std::string& label) const {
auto coverage = GetCoverage(entity);
if (coverage_limit.has_value()) {
coverage = coverage->Intersection(*coverage_limit);
}
if (!coverage.has_value()) {
return std::nullopt;
}
// Pad Contents snapshots with 1 pixel borders to ensure correct sampling
// behavior. Not doing so results in a coverage leak for filters that support
// customizing the input sampling mode. Snapshots of contents should be
// theoretically treated as infinite size just like layers.
coverage = coverage->Expand(1);
if (coverage_limit.has_value()) {
coverage = coverage->Intersection(*coverage_limit);
}
auto texture = renderer.MakeSubpass(
label, ISize::Ceil(coverage->size),
[&contents = *this, &entity, &coverage](const ContentContext& renderer,

View File

@ -1783,6 +1783,34 @@ TEST(GeometryTest, RectMakePointBounds) {
}
}
TEST(GeometryTest, RectExpand) {
{
auto a = Rect::MakeLTRB(100, 100, 200, 200);
auto b = a.Expand(1);
auto expected = Rect::MakeLTRB(99, 99, 201, 201);
ASSERT_RECT_NEAR(b, expected);
}
{
auto a = Rect::MakeLTRB(100, 100, 200, 200);
auto b = a.Expand(-1);
auto expected = Rect::MakeLTRB(101, 101, 199, 199);
ASSERT_RECT_NEAR(b, expected);
}
{
auto a = Rect::MakeLTRB(100, 100, 200, 200);
auto b = a.Expand(1, 2, 3, 4);
auto expected = Rect::MakeLTRB(99, 98, 203, 204);
ASSERT_RECT_NEAR(b, expected);
}
{
auto a = Rect::MakeLTRB(100, 100, 200, 200);
auto b = a.Expand(-1, -2, -3, -4);
auto expected = Rect::MakeLTRB(101, 102, 197, 196);
ASSERT_RECT_NEAR(b, expected);
}
}
TEST(GeometryTest, RectGetPositive) {
{
Rect r{100, 200, 300, 400};

View File

@ -252,6 +252,24 @@ struct TRect {
return TRect(origin.x + offset.x, origin.y + offset.y, size.width,
size.height);
}
/// @brief Returns a rectangle with expanded edges. Negative expansion
/// results in shrinking.
constexpr TRect<T> Expand(T left, T top, T right, T bottom) {
return TRect(origin.x - left, //
origin.y - top, //
size.width + left + right, //
size.height + top + bottom);
}
/// @brief Returns a rectangle with expanded edges in all directions.
/// Negative expansion results in shrinking.
constexpr TRect<T> Expand(T amount) {
return TRect(origin.x - amount, //
origin.y - amount, //
size.width + amount * 2, //
size.height + amount * 2);
}
};
using Rect = TRect<Scalar>;