Commit 5786cd24 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Fix render surface occlusion with pixel-moving filters

We have been correctly ignoring occlusion from outside of the subtree
of a pixel-moving filter in the stack of OcclusionTracker (which leads
to correct occlusion inside of the subtree), but when we get the
occlusion of a render surface, previously we returned the current
occlusion of the parent render surface even if the current render
surface has pixel-moving filter, causing the render surface incorrectly
occluded.

Now add a flag in the stack indicating that the render surface doesn't
inherit parent occlusion, and
OcclusionTracker::GetCurrentOcclusionForContributingSurface() should
not return the parent occlusion when the flag is set.

Bug: 1040288
Change-Id: I505b079d62186a404b1be1c83c6cbccc89c10b8f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1994102Reviewed-by: default avatarweiliangc <weiliangc@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#730215}
parent 33633af4
......@@ -37,7 +37,7 @@ Occlusion OcclusionTracker::GetCurrentOcclusionForLayer(
Occlusion OcclusionTracker::GetCurrentOcclusionForContributingSurface(
const gfx::Transform& draw_transform) const {
DCHECK(!stack_.empty());
if (stack_.size() < 2)
if (stack_.size() < 2 || stack_.back().ignores_parent_occlusion)
return Occlusion();
// A contributing surface doesn't get occluded by things inside its own
// surface, so only things outside the surface can occlude it. That occlusion
......@@ -49,10 +49,12 @@ Occlusion OcclusionTracker::GetCurrentOcclusionForContributingSurface(
const RenderSurfaceImpl*
OcclusionTracker::OcclusionSurfaceForContributingSurface() const {
if (stack_.size() < 2 || stack_.back().ignores_parent_occlusion)
return nullptr;
// A contributing surface doesn't get occluded by things inside its own
// surface, so only things outside the surface can occlude it. That occlusion
// is found just below the top of the stack (if it exists).
return (stack_.size() < 2) ? nullptr : stack_[stack_.size() - 2].target;
return stack_[stack_.size() - 2].target;
}
void OcclusionTracker::EnterLayer(
......@@ -162,8 +164,10 @@ void OcclusionTracker::EnterRenderTarget(
!entering_unoccluded_subtree &&
have_transform_from_screen_to_new_target &&
!entering_root_target;
if (!copy_outside_occlusion_forward)
if (!copy_outside_occlusion_forward) {
stack_.back().ignores_parent_occlusion = true;
return;
}
size_t last_index = stack_.size() - 1;
gfx::Transform old_target_to_new_target_transform(
......
......@@ -64,6 +64,7 @@ class CC_EXPORT OcclusionTracker {
const RenderSurfaceImpl* target;
SimpleEnclosedRegion occlusion_from_outside_target;
SimpleEnclosedRegion occlusion_from_inside_target;
bool ignores_parent_occlusion = false;
};
// The stack holds occluded regions for subtrees in the
......
......@@ -992,6 +992,63 @@ class OcclusionTrackerTestFilters : public OcclusionTrackerTest {
ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFilters)
class OcclusionTrackerTestFiltersRenderSurfaceOcclusion
: public OcclusionTrackerTest {
protected:
using OcclusionTrackerTest::OcclusionTrackerTest;
void RunMyTest() override {
TestContentLayerImpl* parent = CreateRoot(gfx::Size(500, 500));
TestContentLayerImpl* blur_layer = CreateDrawingSurface(
parent, gfx::Transform(), gfx::PointF(100.f, 100.f), gfx::Size(50, 50),
true);
TestContentLayerImpl* opacity_layer = CreateDrawingSurface(
parent, gfx::Transform(), gfx::PointF(200.f, 100.f), gfx::Size(50, 50),
true);
// This layer fully covers the layer bounds of the above filtered layers,
// but not the blur filter extent of |blur_layer|.
TestContentLayerImpl* occluding_layer =
CreateDrawingLayer(parent, gfx::Transform(), gfx::PointF(100.f, 100.f),
gfx::Size(300, 100), true);
FilterOperations filters;
filters.Append(FilterOperation::CreateBlurFilter(10.f));
GetEffectNode(blur_layer)->filters = filters;
filters.Clear();
filters.Append(FilterOperation::CreateOpacityFilter(0.5f));
GetEffectNode(opacity_layer)->filters = filters;
CalcDrawEtc();
TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000));
ASSERT_NO_FATAL_FAILURE(VisitLayer(occluding_layer, &occlusion));
// The render surface of |opacity_layer| (which has a filter that doesn't
// move pixels) is occluded by |occluding_layer|.
ASSERT_NO_FATAL_FAILURE(VisitLayer(opacity_layer, &occlusion));
ASSERT_NO_FATAL_FAILURE(
EnterContributingSurface(opacity_layer, &occlusion));
EXPECT_EQ(gfx::Rect(),
occlusion.UnoccludedSurfaceContentRect(
opacity_layer, gfx::Rect(opacity_layer->bounds())));
ASSERT_NO_FATAL_FAILURE(
LeaveContributingSurface(opacity_layer, &occlusion));
// The render surface of |blur_layer| (which has a filter that moves pixels)
// is not occluded by |occluding_layer|.
ASSERT_NO_FATAL_FAILURE(VisitLayer(blur_layer, &occlusion));
ASSERT_NO_FATAL_FAILURE(EnterContributingSurface(blur_layer, &occlusion));
EXPECT_EQ(gfx::Rect(blur_layer->bounds()),
occlusion.UnoccludedSurfaceContentRect(
blur_layer, gfx::Rect(blur_layer->bounds())));
ASSERT_NO_FATAL_FAILURE(LeaveContributingSurface(blur_layer, &occlusion));
}
};
ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFiltersRenderSurfaceOcclusion)
class OcclusionTrackerTestOpaqueContentsRegionEmpty
: public OcclusionTrackerTest {
protected:
......
......@@ -57,8 +57,6 @@ virtual/android/url-bar/bottom-and-top-fixed-sticks-to-top.html [ Crash ]
virtual/android/url-bar/bottom-fixed-adjusted-when-showing-url-bar.html [ Crash ]
# Composited filters are not working.
crbug.com/1008501 compositing/culling/filter-occlusion-blur-large.html [ Failure ]
crbug.com/1008501 compositing/culling/filter-occlusion-blur.html [ Failure ]
crbug.com/1008501 compositing/reflections/deeply-nested-reflections.html [ Failure ]
# Wrong contentsOpaque or background color.
......
......@@ -10,8 +10,6 @@
will-change: transform;
}
.yellow-parent {
width: 800px;
height: 800px;
-webkit-filter: blur(10px);
}
.centered {
......
......@@ -6,8 +6,6 @@
will-change: transform;
}
.yellow-parent {
width: 600px;
height: 600px;
-webkit-filter: blur(10px);
}
.centered {
......
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