Commit bda6e124 authored by Chris Harrelson's avatar Chris Harrelson Committed by Commit Bot

[PE] Fix contents opaque for composited layers in the presence of a foreground layer

The foreground layer paints normal-flow and positive z-index non-composited
children in the presence of a composited negative-z-index-child. In these cases,
we should not consider the normal-flow or positive z-index non-composited children
as contributing to opaqueness of the main graphics layer, since they paint
elsewhere.

Bug: 892137

Change-Id: I7bd6a4eab615881e4ec3931049f292b046202430
Reviewed-on: https://chromium-review.googlesource.com/c/1332699Reviewed-by: default avatarXianzhu Wang <wangxianzhu@chromium.org>
Commit-Queue: Chris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607683}
parent 952b1a87
......@@ -427,6 +427,10 @@ void CompositedLayerMapping::UpdateBackgroundPaintsOntoScrollingContentsLayer(
}
void CompositedLayerMapping::UpdateContentsOpaque() {
// If there is a foreground layer, children paint into that layer and
// not graphics_layer_, and so don't contribute to the opaqueness of the
// latter.
bool should_check_children = !foreground_layer_.get();
if (IsTextureLayerCanvas(GetLayoutObject())) {
CanvasRenderingContext* context =
ToHTMLCanvasElement(GetLayoutObject().GetNode())->RenderingContext();
......@@ -463,13 +467,14 @@ void CompositedLayerMapping::UpdateContentsOpaque() {
// this for solid color backgrounds the answer will be the same.
scrolling_contents_layer_->SetContentsOpaque(
owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
ToLayoutBox(GetLayoutObject()).PhysicalPaddingBoxRect()));
ToLayoutBox(GetLayoutObject()).PhysicalPaddingBoxRect(),
should_check_children));
if (GetLayoutObject().GetBackgroundPaintLocation() &
kBackgroundPaintInGraphicsLayer) {
graphics_layer_->SetContentsOpaque(
owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
CompositedBounds()));
CompositedBounds(), should_check_children));
} else {
// If we only paint the background onto the scrolling contents layer we
// are going to leave a hole in the m_graphicsLayer where the background
......@@ -480,7 +485,8 @@ void CompositedLayerMapping::UpdateContentsOpaque() {
if (HasScrollingLayer())
scrolling_contents_layer_->SetContentsOpaque(false);
graphics_layer_->SetContentsOpaque(
owning_layer_.BackgroundIsKnownToBeOpaqueInRect(CompositedBounds()));
owning_layer_.BackgroundIsKnownToBeOpaqueInRect(
CompositedBounds(), should_check_children));
}
}
}
......
......@@ -2721,4 +2721,53 @@ transform'></div>
squashed->GraphicsLayerBacking()->GetPosition());
}
TEST_F(CompositedLayerMappingTest, ContentsNotOpaqueWithForegroundLayer) {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
SetHtmlInnerHTML(R"HTML(
<style>
div {
width: 100px;
height: 100px;
position: relative;
isolation: isolate;
}
</style>
<div id='target' style='will-change: transform'>
<div style='background: blue; z-index: -1; will-change: transform'></div>
<div style='background: blue'></div>
</div>
)HTML");
PaintLayer* target_layer =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
CompositedLayerMapping* mapping = target_layer->GetCompositedLayerMapping();
EXPECT_TRUE(mapping->ForegroundLayer());
EXPECT_FALSE(mapping->MainGraphicsLayer()->ContentsOpaque());
}
TEST_F(CompositedLayerMappingTest, ContentsOpaque) {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
SetHtmlInnerHTML(R"HTML(
<style>
div {
width: 100px;
height: 100px;
position: relative;
isolation: isolate;
}
</style>
<div id='target' style='will-change: transform'>
<div style='background: blue'></div>
</div>
)HTML");
PaintLayer* target_layer =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
CompositedLayerMapping* mapping = target_layer->GetCompositedLayerMapping();
EXPECT_FALSE(mapping->ForegroundLayer());
EXPECT_TRUE(mapping->MainGraphicsLayer()->ContentsOpaque());
}
} // namespace blink
......@@ -272,7 +272,7 @@ bool CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
(compositing_triggers_ & kViewportConstrainedPositionedTrigger)) &&
(!RuntimeEnabledFeatures::CompositeOpaqueFixedPositionEnabled() ||
!layer->BackgroundIsKnownToBeOpaqueInRect(
LayoutRect(layer->BoundingBoxForCompositing())) ||
LayoutRect(layer->BoundingBoxForCompositing()), true) ||
layer->CompositesWithTransform() || layer->CompositesWithOpacity())) {
return false;
}
......
......@@ -2848,7 +2848,8 @@ bool PaintLayer::CompositesWithOpacity() const {
}
bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
const LayoutRect& local_rect) const {
const LayoutRect& local_rect,
bool should_check_children) const {
if (PaintsWithTransparency(kGlobalPaintNormalPhase))
return false;
......@@ -2880,6 +2881,9 @@ bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
if (GetLayoutObject().BackgroundIsKnownToBeOpaqueInRect(local_rect))
return true;
if (!should_check_children)
return false;
// We can't consult child layers if we clip, since they might cover
// parts of the rect that are clipped out.
if (GetLayoutObject().HasClipRelatedProperty())
......@@ -2913,7 +2917,7 @@ bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
child_layer->ConvertToLayerCoords(this, child_offset);
child_local_rect.MoveBy(-child_offset);
if (child_layer->BackgroundIsKnownToBeOpaqueInRect(child_local_rect))
if (child_layer->BackgroundIsKnownToBeOpaqueInRect(child_local_rect, true))
return true;
}
return false;
......
......@@ -601,7 +601,10 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// Returns true if background phase is painted opaque in the given rect.
// The query rect is given in local coordinates.
bool BackgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const;
// if |should_check_children| is true, checks non-composited stacking children
// recursively to see if they paint opaquely over the rect.
bool BackgroundIsKnownToBeOpaqueInRect(const LayoutRect&,
bool should_check_children) const;
bool ContainsDirtyOverlayScrollbars() const {
return contains_dirty_overlay_scrollbars_;
......
......@@ -2251,7 +2251,8 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
&non_composited_main_thread_scrolling_reasons_) &
kBackgroundPaintInScrollingContents &&
layer->BackgroundIsKnownToBeOpaqueInRect(
ToLayoutBox(layer->GetLayoutObject()).PhysicalPaddingBoxRect()) &&
ToLayoutBox(layer->GetLayoutObject()).PhysicalPaddingBoxRect(),
true) &&
!layer->CompositesWithTransform() && !layer->CompositesWithOpacity();
// TODO(crbug.com/839341): Remove ScrollTimeline check once we support
......@@ -2269,7 +2270,8 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
MainThreadScrollingReason::kHasTransformAndLCDText;
}
if (!layer->BackgroundIsKnownToBeOpaqueInRect(
ToLayoutBox(layer->GetLayoutObject()).PhysicalPaddingBoxRect())) {
ToLayoutBox(layer->GetLayoutObject()).PhysicalPaddingBoxRect(),
true)) {
non_composited_main_thread_scrolling_reasons_ |=
MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText;
}
......
......@@ -23,11 +23,6 @@ class PaintLayerTest : public PaintTestConfigurations, public RenderingTest {
RenderingTest::SetUp();
EnableCompositing();
}
protected:
PaintLayer* GetPaintLayerByElementId(const char* id) {
return ToLayoutBoxModelObject(GetLayoutObjectByElementId(id))->Layer();
}
};
INSTANTIATE_PAINT_TEST_CASE_P(PaintLayerTest);
......@@ -1742,6 +1737,28 @@ TEST_P(PaintLayerTest, HitTestFirstLetterPseudoElementDisplayContents) {
result.InnerPossiblyPseudoNode());
}
TEST_P(PaintLayerTest, BackgroundIsKnownToBeOpaqueInRectChildren) {
SetBodyInnerHTML(R"HTML(
<style>
div {
width: 100px;
height: 100px;
position: relative;
isolation: isolate;
}
</style>
<div id='target'>
<div style='background: blue'></div>
</div>
)HTML");
PaintLayer* target_layer = GetPaintLayerByElementId("target");
EXPECT_TRUE(target_layer->BackgroundIsKnownToBeOpaqueInRect(
LayoutRect(0, 0, 100, 100), true));
EXPECT_FALSE(target_layer->BackgroundIsKnownToBeOpaqueInRect(
LayoutRect(0, 0, 100, 100), false));
}
TEST_P(PaintLayerTest, ChangeAlphaNeedsCompositingInputs) {
SetBodyInnerHTML(R"HTML(
<style>
......
......@@ -21,6 +21,8 @@
namespace blink {
class PaintLayer;
class SingleChildLocalFrameClient final : public EmptyLocalFrameClient {
public:
static SingleChildLocalFrameClient* Create() {
......@@ -111,6 +113,10 @@ class RenderingTest : public PageTestBase, public UseMockScrollbarSettings {
return element ? element->GetLayoutObject() : nullptr;
}
PaintLayer* GetPaintLayerByElementId(const char* id) {
return ToLayoutBoxModelObject(GetLayoutObjectByElementId(id))->Layer();
}
private:
Persistent<LocalFrameClient> local_frame_client_;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment