[Impeller] EntityPass should cover the whole screen for some blend modes (flutter/engine#35157)

This commit is contained in:
magicianA 2022-08-08 10:37:21 +08:00 committed by GitHub
parent 6c71f6341b
commit 84a598832f
5 changed files with 53 additions and 2 deletions

View File

@ -252,6 +252,31 @@ TEST_P(AiksTest, CanRenderRadialGradient) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, BlendModeShouldCoverWholeScreen) {
Canvas canvas;
Paint paint;
paint.color = Color::Red();
canvas.DrawPaint(paint);
paint.blend_mode = Entity::BlendMode::kSourceOver;
canvas.SaveLayer(paint);
paint.color = Color::White();
canvas.DrawRect({100, 100, 400, 400}, paint);
paint.blend_mode = Entity::BlendMode::kSource;
canvas.SaveLayer(paint);
paint.color = Color::Blue();
canvas.DrawRect({200, 200, 200, 200}, paint);
canvas.Restore();
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, CanRenderGroupOpacity) {
Canvas canvas;

View File

@ -42,6 +42,9 @@ std::optional<Rect> Entity::GetCoverage() const {
}
bool Entity::ShouldRender(const ISize& target_size) const {
if (BlendModeShouldCoverWholeScreen(blend_mode_)) {
return true;
}
return contents_->ShouldRender(*this, target_size);
}
@ -73,6 +76,23 @@ Entity::BlendMode Entity::GetBlendMode() const {
return blend_mode_;
}
bool Entity::BlendModeShouldCoverWholeScreen(BlendMode blend_mode) {
switch (blend_mode) {
case BlendMode::kClear:
case BlendMode::kSource:
case BlendMode::kSourceIn:
case BlendMode::kDestinationIn:
case BlendMode::kSourceOut:
case BlendMode::kDestinationOut:
case BlendMode::kDestinationATop:
case BlendMode::kXor:
case BlendMode::kModulate:
return true;
default:
return false;
}
}
bool Entity::Render(const ContentContext& renderer,
RenderPass& parent_pass) const {
if (!contents_) {

View File

@ -121,6 +121,8 @@ class Entity {
bool Render(const ContentContext& renderer, RenderPass& parent_pass) const;
static bool BlendModeShouldCoverWholeScreen(BlendMode blend_mode);
private:
Matrix transformation_;
std::shared_ptr<Contents> contents_;

View File

@ -252,7 +252,10 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
auto subpass_coverage =
GetSubpassCoverage(*subpass, Rect::MakeSize(root_pass_size));
if (subpass->cover_whole_screen) {
subpass_coverage = Rect(
position, Size(pass_context.GetRenderTarget().GetRenderTargetSize()));
}
if (backdrop_contents) {
auto backdrop_coverage = backdrop_contents->GetCoverage(Entity{});
if (backdrop_coverage.has_value()) {
@ -501,6 +504,7 @@ void EntityPass::SetStencilDepth(size_t stencil_depth) {
void EntityPass::SetBlendMode(Entity::BlendMode blend_mode) {
blend_mode_ = blend_mode;
cover_whole_screen = Entity::BlendModeShouldCoverWholeScreen(blend_mode);
}
void EntityPass::SetBackdropFilter(std::optional<BackdropFilterProc> proc) {

View File

@ -114,7 +114,7 @@ class EntityPass {
Matrix xformation_;
size_t stencil_depth_ = 0u;
Entity::BlendMode blend_mode_ = Entity::BlendMode::kSourceOver;
bool cover_whole_screen = false;
/// This flag is set to `true` whenever an entity is added to the pass that
/// requires reading the pass texture during rendering. This can happen in the
/// following scenarios: