-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Impeller] separate algorithm for computing render target size. #54604
Merged
auto-submit
merged 38 commits into
flutter:main
from
jonahwilliams:render_target_sizing
Aug 31, 2024
Merged
Changes from 4 commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
9d59af1
[Impeller] separate algorithm for computing render target size.
jonahwilliams a935594
++
jonahwilliams 7aa3a48
Update save_layer_utils_unittests.cc
jonahwilliams 54cea5a
nolint.
jonahwilliams e6e56d8
oh boy here we go.
jonahwilliams 98a5d68
cleanups.
jonahwilliams 81ccaa0
remove print.
jonahwilliams 55a6a50
Update save_layer_utils_unittests.cc
jonahwilliams 3591395
dont overwrite save layer bounds.
jonahwilliams a8f0e2c
Merge branch 'render_target_sizing' of github.com:jonahwilliams/engin…
jonahwilliams 1c55cf5
++
jonahwilliams a6f5f21
Update dl_dispatcher.cc
jonahwilliams a646c1b
++
jonahwilliams 8daf291
Merge branch 'main' of github.com:flutter/engine into render_target_s…
jonahwilliams 199a846
++
jonahwilliams b2eb6b9
++
jonahwilliams d347783
++
jonahwilliams 24442e0
flood clip.
jonahwilliams 78b7f60
add flood clip.
jonahwilliams 2a4ac2d
++
jonahwilliams 3eff88b
++
jonahwilliams 04b5be5
Update entity_pass.cc
jonahwilliams 086abb8
Update entity_pass.h
jonahwilliams 4a5f30b
++
jonahwilliams fa3afcc
Merge branch 'render_target_sizing' of github.com:jonahwilliams/engin…
jonahwilliams 4e7a707
partial review feedback.
jonahwilliams e0105d7
more adjustments.
jonahwilliams e8f34ac
oops
jonahwilliams 8a3d1ef
Merge branch 'main' into render_target_sizing
jonahwilliams 24ef59a
Merge branch 'main' into render_target_sizing
jonahwilliams 0cae7a8
flar review.
jonahwilliams ae57e62
Merge branch 'main' of github.com:flutter/engine into render_target_s…
jonahwilliams bc2276e
no bds from caller.
jonahwilliams b3ab833
update comment.
jonahwilliams 334e5e9
++
jonahwilliams 82a6621
++
jonahwilliams 5011b3c
++
jonahwilliams 008b6f9
++
jonahwilliams File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// 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/aiks/save_layer_utils.h" | ||
|
||
#include "impeller/entity/entity.h" | ||
|
||
namespace impeller { | ||
|
||
std::optional<Rect> ComputeSaveLayerCoverage( | ||
Rect content_coverage, | ||
const std::shared_ptr<ImageFilter>& backdrop_filter, | ||
const Paint& paint, | ||
const Matrix& effect_transform, | ||
const Rect& coverage_limit, | ||
bool user_provided_bounds) { | ||
// If the saveLayer is unbounded, the coverage is the same as the | ||
// coverage limit. By default, the coverage limit begins as the screen | ||
// coverage. Either a lack of bounds, or the presence of a backdrop | ||
// effecting paint property indicates that the saveLayer is unbounded. | ||
// The o ne special case is when the input coverage was specified by the | ||
// developer, in this case we still use the content coverage even if the | ||
// saveLayer itself is unbounded. | ||
bool save_layer_is_unbounded = | ||
backdrop_filter != nullptr || | ||
Entity::IsBlendModeDestructive(paint.blend_mode); | ||
|
||
// Otherwise, the save layer is bounded by either its contents or by | ||
// a specified coverage limit. In these cases the coverage value is used | ||
// and intersected with the coverage limit. | ||
Rect input_coverage = (save_layer_is_unbounded && !user_provided_bounds) | ||
? Rect::MakeMaximum() | ||
: content_coverage; | ||
|
||
// The content coverage must be scaled by any image filters present on the | ||
// saveLayer paint. For example, if a saveLayer has a coverage limit of | ||
// 100x100, but it has a Matrix image filter that scales by one half, the | ||
// actual coverage limit is 200x200. | ||
// | ||
// If there is no image filter, then we can assume that the contents have | ||
// absorbed the current transform and thus it has already been incorporated | ||
// into any computed bounds. That is, a canvas scaling transform of 0.5 | ||
// changes the coverage of the contained entities directly and doesnt need to | ||
// be additionally incorporated into the coverage computation here. | ||
if (paint.image_filter) { | ||
std::shared_ptr<FilterContents> image_filter = | ||
paint.image_filter->GetFilterContents(); | ||
std::optional<Rect> source_coverage_limit = | ||
image_filter->GetSourceCoverage(effect_transform, coverage_limit); | ||
if (!source_coverage_limit.has_value()) { | ||
// No intersection with parent coverage limit. | ||
return std::nullopt; | ||
} | ||
return input_coverage.Intersection(source_coverage_limit.value()); | ||
} | ||
|
||
return input_coverage.Intersection(coverage_limit); | ||
} | ||
|
||
} // namespace impeller |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// 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. | ||
|
||
#ifndef FLUTTER_IMPELLER_AIKS_SAVE_LAYER_UTILS_H_ | ||
#define FLUTTER_IMPELLER_AIKS_SAVE_LAYER_UTILS_H_ | ||
|
||
#include <memory> | ||
#include <optional> | ||
|
||
#include "impeller/aiks/image_filter.h" | ||
#include "impeller/aiks/paint.h" | ||
|
||
namespace impeller { | ||
|
||
/// Compute the coverage of the subpass in the subpass coordinate space. | ||
/// | ||
/// A return value of std::nullopt indicates that the coverage is empty or | ||
/// otherwise does not intersect with the parent coverage limit and should | ||
/// be discarded. | ||
std::optional<Rect> ComputeSaveLayerCoverage( | ||
Rect content_coverage, | ||
const std::shared_ptr<ImageFilter>& backdrop_filter, | ||
const Paint& paint, | ||
const Matrix& effect_transform, | ||
const Rect& coverage_limit, | ||
bool user_provided_bounds = false); | ||
|
||
} // namespace impeller | ||
|
||
#endif // FLUTTER_IMPELLER_AIKS_SAVE_LAYER_UTILS_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
// 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/aiks/image_filter.h" | ||
#include "impeller/aiks/save_layer_utils.h" | ||
#include "impeller/geometry/color.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(Rect::MakeLTRB(0, 0, 10, 10), nullptr, {}, {}, | ||
Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
ASSERT_TRUE(coverage.has_value()); | ||
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10)); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, DestructivePaintComputedCoverage) { | ||
// Destructive paint, computed coverage | ||
auto coverage = ComputeSaveLayerCoverage( | ||
Rect::MakeLTRB(0, 0, 10, 10), nullptr, {.blend_mode = BlendMode::kClear}, | ||
{}, Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
ASSERT_TRUE(coverage.has_value()); | ||
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, BackdropFiterComputedCoverage) { | ||
// Backdrop Filter, computed coverage | ||
auto backdrop_filter = | ||
ImageFilter::MakeMatrix(Matrix::MakeScale({2, 2, 1}), {}); | ||
auto coverage = | ||
ComputeSaveLayerCoverage(Rect::MakeLTRB(0, 0, 10, 10), backdrop_filter, | ||
{}, {}, Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
ASSERT_TRUE(coverage.has_value()); | ||
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, ImageFiterComputedCoverage) { | ||
// Backdrop Filter, computed coverage | ||
auto image_filter = ImageFilter::MakeMatrix(Matrix::MakeScale({2, 2, 1}), {}); | ||
auto coverage = ComputeSaveLayerCoverage( | ||
Rect::MakeLTRB(0, 0, 10, 10), nullptr, {.image_filter = image_filter}, {}, | ||
Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
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 = ImageFilter::MakeMatrix(Matrix::MakeScale({2, 2, 1}), {}); | ||
auto coverage = ComputeSaveLayerCoverage( | ||
Rect::MakeLTRB(0, 0, 10, 10), nullptr, {.image_filter = image_filter}, {}, | ||
Rect::MakeLTRB(0, 0, 5, 5)); | ||
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 = | ||
ImageFilter::MakeMatrix(Matrix::MakeScale({0.5, 0.5, 1}), {}); | ||
auto coverage = ComputeSaveLayerCoverage( | ||
Rect::MakeLTRB(0, 0, 10, 10), nullptr, {.image_filter = image_filter}, {}, | ||
Rect::MakeLTRB(0, 0, 5, 5)); | ||
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(Rect::MakeLTRB(200, 200, 210, 210), nullptr, {}, | ||
{}, Rect::MakeLTRB(0, 0, 100, 100)); | ||
EXPECT_FALSE(coverage.has_value()); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, DisjointCoverageTransformedByImageFilter) { | ||
// Coverage disjoint from parent coverage but transformed into parent space | ||
// with image filter. | ||
auto image_filter = | ||
ImageFilter::MakeMatrix(Matrix::MakeTranslation({-200, -200, 0}), {}); | ||
auto coverage = ComputeSaveLayerCoverage( | ||
Rect::MakeLTRB(200, 200, 210, 210), nullptr, | ||
{.image_filter = image_filter}, {}, Rect::MakeLTRB(0, 0, 100, 100)); | ||
ASSERT_TRUE(coverage.has_value()); | ||
// Is this the right value? should it actually be (0, 0, 10, 10)? | ||
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(200, 200, 210, 210)); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, DisjointCoverageNotTransformedByCTM) { | ||
// Coverage disjoint from parent coverage. CTM does not impact lack of | ||
// intersection as it has already been "absorbed" by child coverage. | ||
Matrix ctm = Matrix::MakeTranslation({-200, -200, 0}); | ||
auto coverage = | ||
ComputeSaveLayerCoverage(Rect::MakeLTRB(200, 200, 210, 210), nullptr, {}, | ||
ctm, Rect::MakeLTRB(0, 0, 100, 100)); | ||
ASSERT_FALSE(coverage.has_value()); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, BasicEmptyCoverage) { | ||
auto coverage = | ||
ComputeSaveLayerCoverage(Rect::MakeLTRB(0, 0, 0, 0), nullptr, {}, {}, | ||
Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
ASSERT_FALSE(coverage.has_value()); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, ImageFilterEmptyCoverage) { | ||
// Empty coverage with Image Filter | ||
auto image_filter = | ||
ImageFilter::MakeMatrix(Matrix::MakeTranslation({-200, -200, 0}), {}); | ||
auto coverage = ComputeSaveLayerCoverage(Rect::MakeLTRB(0, 0, 0, 0), nullptr, | ||
{.image_filter = image_filter}, {}, | ||
Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
ASSERT_FALSE(coverage.has_value()); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, BackdropFilterEmptyCoverage) { | ||
// Empty coverage with Image Filter | ||
auto image_filter = | ||
ImageFilter::MakeMatrix(Matrix::MakeTranslation({-200, -200, 0}), {}); | ||
auto coverage = | ||
ComputeSaveLayerCoverage(Rect::MakeLTRB(0, 0, 0, 0), image_filter, {}, {}, | ||
Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
ASSERT_TRUE(coverage.has_value()); | ||
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 2400, 1800)); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, DestructivePaintUserSpecifiedBounds) { | ||
// user specified bounds override clip flooding. | ||
auto coverage = ComputeSaveLayerCoverage( | ||
Rect::MakeLTRB(0, 0, 10, 10), nullptr, {.blend_mode = BlendMode::kClear}, | ||
{}, Rect::MakeLTRB(0, 0, 2400, 1800), | ||
/*user_provided_bounds=*/true); | ||
ASSERT_TRUE(coverage.has_value()); | ||
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10)); | ||
} | ||
|
||
TEST(SaveLayerUtilsTest, BackdropFilterUserSpecifiedBounds) { | ||
// user specified bounds override clip flooding. | ||
auto backdrop_filter = | ||
ImageFilter::MakeMatrix(Matrix::MakeScale({2, 2, 1}), {}); | ||
auto coverage = ComputeSaveLayerCoverage( | ||
Rect::MakeLTRB(0, 0, 10, 10), backdrop_filter, {}, {}, | ||
Rect::MakeLTRB(0, 0, 2400, 1800), /*user_provided_bounds=*/true); | ||
ASSERT_TRUE(coverage.has_value()); | ||
EXPECT_EQ(coverage.value(), Rect::MakeLTRB(0, 0, 10, 10)); | ||
} | ||
|
||
} // namespace testing | ||
} // namespace impeller | ||
|
||
// NOLINTEND(bugprone-unchecked-optional-access) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is dead code. Did you forget to push the entity_pass.cc changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I didn't change entity pass itself, just staged this separately. I could do that too though, if you'd like
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do. It would be helpful to see user_provided_bounds being used in context.