Commit f7c52d8a authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Layer with blend mode without render surface should not occlude

The previous OcculusionTracker logic assumed that any exotic blend
mode created a render surface, and skipped occlusion for blend mode
only when applying occlusion of render surfaces.

However, the new mask layer mechanism using kDstIn blend mode doesn't
always create a render surface for the mask layer, so we need to skip
occlusion for such mask layers. Previously an opaque mask layer would
mistakenly occlude the masked layer. This didn't actually happen
because we had never set contents_opaque for a mask layer, even if it
was opaque. However, this will happen with a more sophisticated layer
opaqueness detector (crrev.com/c/2113806).

Change-Id: I6f9f8d6c521553c62bcaff2d31d4f2f4778b1317
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2115696Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#752539}
parent fe5c3752
...@@ -351,6 +351,17 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) { ...@@ -351,6 +351,17 @@ void OcclusionTracker::MarkOccludedBehindLayer(const LayerImpl* layer) {
if (opaque_layer_region.IsEmpty()) if (opaque_layer_region.IsEmpty())
return; return;
// If the blend mode is not kSrcOver and the effect doesn't have a render
// surface, then the layer should not occlude. An example of this would
// otherwise be wrong is that this layer is a non-render-surface mask layer
// with kDstIn blend mode.
const auto* effect_node =
layer->layer_tree_impl()->property_trees()->effect_tree.Node(
layer->effect_tree_index());
if (!effect_node->HasRenderSurface() &&
effect_node->blend_mode != SkBlendMode::kSrcOver)
return;
DCHECK(layer->visible_layer_rect().Contains(opaque_layer_region.bounds())); DCHECK(layer->visible_layer_rect().Contains(opaque_layer_region.bounds()));
gfx::Transform draw_transform = layer->DrawTransform(); gfx::Transform draw_transform = layer->DrawTransform();
......
...@@ -1830,10 +1830,11 @@ class OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded ...@@ -1830,10 +1830,11 @@ class OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded
ALL_OCCLUSIONTRACKER_TEST( ALL_OCCLUSIONTRACKER_TEST(
OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded) OcclusionTrackerTestReduceOcclusionWhenBkgdFilterIsPartiallyOccluded)
class OcclusionTrackerTestBlendModeDoesNotOcclude class OcclusionTrackerTestRenderSurfaceBlendModeDoesNotOcclude
: public OcclusionTrackerTest { : public OcclusionTrackerTest {
protected: protected:
explicit OcclusionTrackerTestBlendModeDoesNotOcclude(bool opaque_layers) explicit OcclusionTrackerTestRenderSurfaceBlendModeDoesNotOcclude(
bool opaque_layers)
: OcclusionTrackerTest(opaque_layers) {} : OcclusionTrackerTest(opaque_layers) {}
void RunMyTest() override { void RunMyTest() override {
TestContentLayerImpl* parent = this->CreateRoot(gfx::Size(100, 100)); TestContentLayerImpl* parent = this->CreateRoot(gfx::Size(100, 100));
...@@ -1875,7 +1876,39 @@ class OcclusionTrackerTestBlendModeDoesNotOcclude ...@@ -1875,7 +1876,39 @@ class OcclusionTrackerTestBlendModeDoesNotOcclude
} }
}; };
ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestBlendModeDoesNotOcclude) ALL_OCCLUSIONTRACKER_TEST(
OcclusionTrackerTestRenderSurfaceBlendModeDoesNotOcclude)
class OcclusionTrackerTestNonRenderSurfaceBlendModeDoesNotOcclude
: public OcclusionTrackerTest {
protected:
explicit OcclusionTrackerTestNonRenderSurfaceBlendModeDoesNotOcclude(
bool opaque_layers)
: OcclusionTrackerTest(opaque_layers) {}
void RunMyTest() override {
TestContentLayerImpl* parent = CreateRoot(gfx::Size(100, 100));
LayerImpl* top_layer =
CreateDrawingSurface(parent, this->identity_matrix,
gfx::PointF(10.f, 12.f), gfx::Size(20, 22), true);
LayerImpl* blend_mode_layer =
CreateDrawingLayer(top_layer, this->identity_matrix,
gfx::PointF(0.f, 0.f), gfx::Size(100, 100), true);
// Create an effect node with kDstIn blend mode without a render surface.
CreateEffectNode(blend_mode_layer).blend_mode = SkBlendMode::kDstIn;
this->CalcDrawEtc();
TestOcclusionTrackerWithClip occlusion(gfx::Rect(0, 0, 1000, 1000));
ASSERT_NO_FATAL_FAILURE(this->VisitLayer(blend_mode_layer, &occlusion));
// |blend_mode_layer| doesn't occlude because it has a blend mode without a
// render surface.
EXPECT_EQ(gfx::Rect(), occlusion.occlusion_from_inside_target().bounds());
EXPECT_EQ(gfx::Rect(), occlusion.occlusion_from_outside_target().bounds());
}
};
ALL_OCCLUSIONTRACKER_TEST(
OcclusionTrackerTestNonRenderSurfaceBlendModeDoesNotOcclude)
class OcclusionTrackerTestMinimumTrackingSize : public OcclusionTrackerTest { class OcclusionTrackerTestMinimumTrackingSize : public OcclusionTrackerTest {
protected: protected:
......
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