| // Copyright 2016 The Chromium 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 "core/HTMLNames.h" |
| #include "core/frame/FrameView.h" |
| #include "core/layout/LayoutTestHelper.h" |
| #include "core/layout/LayoutView.h" |
| #include "core/paint/PaintLayer.h" |
| #include "platform/graphics/GraphicsLayer.h" |
| #include "platform/graphics/paint/RasterInvalidationTracking.h" |
| #include "platform/testing/RuntimeEnabledFeaturesTestHelpers.h" |
| |
| namespace blink { |
| |
| class BoxPaintInvalidatorTest : public ::testing::WithParamInterface<bool>, |
| private ScopedRootLayerScrollingForTest, |
| public RenderingTest { |
| public: |
| BoxPaintInvalidatorTest() |
| : ScopedRootLayerScrollingForTest(GetParam()), |
| RenderingTest(SingleChildFrameLoaderClient::create()) {} |
| |
| protected: |
| const RasterInvalidationTracking* getRasterInvalidationTracking() const { |
| // TODO(wangxianzhu): Test SPv2. |
| return layoutView() |
| .layer() |
| ->graphicsLayerBacking() |
| ->getRasterInvalidationTracking(); |
| } |
| |
| private: |
| void SetUp() override { |
| RenderingTest::SetUp(); |
| enableCompositing(); |
| setBodyInnerHTML( |
| "<style>" |
| " body {" |
| " margin: 0;" |
| " height: 0;" |
| " }" |
| " ::-webkit-scrollbar { display: none }" |
| " #target {" |
| " width: 50px;" |
| " height: 100px;" |
| " transform-origin: 0 0;" |
| " }" |
| " .border {" |
| " border-width: 20px 10px;" |
| " border-style: solid;" |
| " border-color: red;" |
| " }" |
| " .local-background {" |
| " background-attachment: local;" |
| " overflow: scroll;" |
| " }" |
| " .gradient {" |
| " background-image: linear-gradient(blue, yellow)" |
| " }" |
| "</style>" |
| "<div id='target' class='border'></div>"); |
| } |
| }; |
| |
| INSTANTIATE_TEST_CASE_P(All, BoxPaintInvalidatorTest, ::testing::Bool()); |
| |
| TEST_P(BoxPaintInvalidatorTest, IncrementalInvalidationExpand) { |
| document().view()->setTracksPaintInvalidations(true); |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 200px"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto& rasterInvalidations = |
| getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(2u, rasterInvalidations.size()); |
| EXPECT_EQ(IntRect(60, 0, 60, 240), rasterInvalidations[0].rect); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[0].reason); |
| EXPECT_EQ(IntRect(0, 120, 120, 120), rasterInvalidations[1].rect); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[1].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, IncrementalInvalidationShrink) { |
| document().view()->setTracksPaintInvalidations(true); |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::styleAttr, "width: 20px; height: 80px"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto& rasterInvalidations = |
| getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(2u, rasterInvalidations.size()); |
| EXPECT_EQ(IntRect(30, 0, 40, 140), rasterInvalidations[0].rect); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[0].reason); |
| EXPECT_EQ(IntRect(0, 100, 70, 40), rasterInvalidations[1].rect); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[1].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, IncrementalInvalidationMixed) { |
| document().view()->setTracksPaintInvalidations(true); |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 80px"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto& rasterInvalidations = |
| getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(2u, rasterInvalidations.size()); |
| EXPECT_EQ(IntRect(60, 0, 60, 120), rasterInvalidations[0].rect); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[0].reason); |
| EXPECT_EQ(IntRect(0, 100, 70, 40), rasterInvalidations[1].rect); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[1].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, SubpixelVisualRectChagne) { |
| ScopedSlimmingPaintInvalidationForTest scopedSlimmingPaintInvalidation(true); |
| |
| Element* target = document().getElementById("target"); |
| |
| // Should do full invalidation if new geometry has subpixels. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, "width: 100.6px; height: 70.3px"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto* rasterInvalidations = |
| &getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(2u, rasterInvalidations->size()); |
| EXPECT_EQ(IntRect(0, 0, 70, 140), (*rasterInvalidations)[0].rect); |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, (*rasterInvalidations)[0].reason); |
| EXPECT_EQ(IntRect(0, 0, 121, 111), (*rasterInvalidations)[1].rect); |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, (*rasterInvalidations)[1].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| |
| // Should do full invalidation if old geometry has subpixels. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, "width: 50px; height: 100px"); |
| document().view()->updateAllLifecyclePhases(); |
| rasterInvalidations = |
| &getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(2u, rasterInvalidations->size()); |
| EXPECT_EQ(IntRect(0, 0, 121, 111), (*rasterInvalidations)[0].rect); |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, (*rasterInvalidations)[0].reason); |
| EXPECT_EQ(IntRect(0, 0, 70, 140), (*rasterInvalidations)[1].rect); |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, (*rasterInvalidations)[1].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, SubpixelChangeWithoutVisualRectChange) { |
| ScopedSlimmingPaintInvalidationForTest scopedSlimmingPaintInvalidation(true); |
| |
| Element* target = document().getElementById("target"); |
| LayoutObject* targetObject = target->layoutObject(); |
| EXPECT_EQ(LayoutRect(0, 0, 70, 140), targetObject->previousVisualRect()); |
| |
| // Should do full invalidation if new geometry has subpixels even if the paint |
| // invalidation rect doesn't change. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, |
| "margin-top: 0.6px; width: 50px; height: 99.3px"); |
| document().view()->updateAllLifecyclePhases(); |
| EXPECT_EQ(LayoutRect(0, 0, 70, 140), targetObject->previousVisualRect()); |
| const auto* rasterInvalidations = |
| &getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(1u, rasterInvalidations->size()); |
| EXPECT_EQ(IntRect(0, 0, 70, 140), (*rasterInvalidations)[0].rect); |
| EXPECT_EQ(PaintInvalidationLocationChange, (*rasterInvalidations)[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, |
| "margin-top: 0.6px; width: 49.3px; height: 98.5px"); |
| document().view()->updateAllLifecyclePhases(); |
| EXPECT_EQ(LayoutRect(0, 0, 70, 140), targetObject->previousVisualRect()); |
| rasterInvalidations = |
| &getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(1u, rasterInvalidations->size()); |
| EXPECT_EQ(IntRect(0, 0, 70, 140), (*rasterInvalidations)[0].rect); |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, (*rasterInvalidations)[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, ResizeRotated) { |
| ScopedSlimmingPaintInvalidationForTest scopedSlimmingPaintInvalidation(true); |
| |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::styleAttr, "transform: rotate(45deg)"); |
| document().view()->updateAllLifecyclePhases(); |
| |
| // Should do full invalidation a rotated object is resized. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, |
| "transform: rotate(45deg); width: 200px"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto* rasterInvalidations = |
| &getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(1u, rasterInvalidations->size()); |
| EXPECT_EQ(IntRect(-99, 0, 255, 255), (*rasterInvalidations)[0].rect); |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, (*rasterInvalidations)[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, ResizeRotatedChild) { |
| ScopedSlimmingPaintInvalidationForTest scopedSlimmingPaintInvalidation(true); |
| |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::styleAttr, |
| "transform: rotate(45deg); width: 200px"); |
| target->setInnerHTML( |
| "<div id=child style='width: 50px; height: 50px; background: " |
| "red'></div>"); |
| document().view()->updateAllLifecyclePhases(); |
| Element* child = document().getElementById("child"); |
| |
| // Should do full invalidation a rotated object is resized. |
| document().view()->setTracksPaintInvalidations(true); |
| child->setAttribute(HTMLNames::styleAttr, |
| "width: 100px; height: 50px; background: red"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto* rasterInvalidations = |
| &getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(1u, rasterInvalidations->size()); |
| EXPECT_EQ(IntRect(-43, 21, 107, 107), (*rasterInvalidations)[0].rect); |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, (*rasterInvalidations)[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, CompositedLayoutViewResize) { |
| enableCompositing(); |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::classAttr, ""); |
| target->setAttribute(HTMLNames::styleAttr, "height: 2000px"); |
| document().view()->updateAllLifecyclePhases(); |
| |
| // Resize the content. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, "height: 3000px"); |
| document().view()->updateAllLifecyclePhases(); |
| if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| // For now in RootLayerScrolling mode root background is invalidated and |
| // painted on the container layer. No invalidation because the changed part |
| // is clipped. |
| // TODO(skobes): Treat LayoutView in the same way as normal objects having |
| // background-attachment: local. crbug.com/568847. |
| // TODO(wangxianzhu): Temporary for crbug.com/680745. |
| // EXPECT_FALSE(layoutView() |
| // .layer() |
| // ->graphicsLayerBacking() |
| // ->getRasterInvalidationTracking()); |
| EXPECT_EQ(1u, layoutView() |
| .layer() |
| ->graphicsLayerBacking() |
| ->getRasterInvalidationTracking() |
| ->trackedRasterInvalidations.size()); |
| } else { |
| const auto& rasterInvalidations = |
| getRasterInvalidationTracking()->trackedRasterInvalidations; |
| // TODO(wangxianzhu): Temporary for crbug.com/680745. |
| // ASSERT_EQ(1u, rasterInvalidations.size()); |
| ASSERT_EQ(2u, rasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 2000, 800, 1000), rasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(&layoutView()), |
| rasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[0].reason); |
| } |
| document().view()->setTracksPaintInvalidations(false); |
| |
| // Resize the viewport. No paint invalidation. |
| document().view()->setTracksPaintInvalidations(true); |
| document().view()->resize(800, 1000); |
| document().view()->updateAllLifecyclePhases(); |
| EXPECT_FALSE(getRasterInvalidationTracking()); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, CompositedLayoutViewGradientResize) { |
| enableCompositing(); |
| document().body()->setAttribute(HTMLNames::classAttr, "gradient"); |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::classAttr, ""); |
| target->setAttribute(HTMLNames::styleAttr, "height: 2000px"); |
| document().view()->updateAllLifecyclePhases(); |
| |
| // Resize the content. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, "height: 3000px"); |
| document().view()->updateAllLifecyclePhases(); |
| if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| // For now in RootLayerScrolling mode root background is invalidated and |
| // painted on the container layer. |
| // TODO(skobes): Treat LayoutView in the same way as normal objects having |
| // background-attachment: local. crbug.com/568847. |
| const auto& rasterInvalidations = layoutView() |
| .layer() |
| ->graphicsLayerBacking(&layoutView()) |
| ->getRasterInvalidationTracking() |
| ->trackedRasterInvalidations; |
| ASSERT_EQ(1u, rasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 0, 800, 600), rasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(&layoutView()), |
| rasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationLayoutOverflowBoxChange, |
| rasterInvalidations[0].reason); |
| } else { |
| const auto& rasterInvalidations = |
| getRasterInvalidationTracking()->trackedRasterInvalidations; |
| // TODO(wangxianzhu): Temporary for crbug.com/680745. |
| // ASSERT_EQ(1u, rasterInvalidations.size()); |
| ASSERT_EQ(2u, rasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 0, 800, 3000), rasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(&layoutView()), |
| rasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationLayoutOverflowBoxChange, |
| rasterInvalidations[0].reason); |
| } |
| document().view()->setTracksPaintInvalidations(false); |
| |
| // Resize the viewport. No paint invalidation. |
| document().view()->setTracksPaintInvalidations(true); |
| document().view()->resize(800, 1000); |
| document().view()->updateAllLifecyclePhases(); |
| EXPECT_FALSE(getRasterInvalidationTracking()); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, NonCompositedLayoutViewResize) { |
| setBodyInnerHTML( |
| "<style>" |
| " body { margin: 0 }" |
| " iframe { display: block; width: 100px; height: 100px; border: none; }" |
| "</style>" |
| "<iframe id='iframe'></iframe>"); |
| setChildFrameHTML( |
| "<style>" |
| " ::-webkit-scrollbar { display: none }" |
| " body { margin: 0; background: green; height: 0 }" |
| "</style>" |
| "<div id='content' style='width: 200px; height: 200px'></div>"); |
| document().view()->updateAllLifecyclePhases(); |
| Element* iframe = document().getElementById("iframe"); |
| Element* content = childDocument().getElementById("content"); |
| EXPECT_EQ(layoutView(), |
| content->layoutObject()->containerForPaintInvalidation()); |
| |
| // Resize the content. |
| document().view()->setTracksPaintInvalidations(true); |
| content->setAttribute(HTMLNames::styleAttr, "height: 500px"); |
| document().view()->updateAllLifecyclePhases(); |
| // No invalidation because the changed part of layout overflow is clipped. |
| // TODO(wangxianzhu): Temporary for crbug.com/680745. |
| // EXPECT_FALSE(getRasterInvalidationTracking()); |
| EXPECT_EQ(1u, |
| getRasterInvalidationTracking()->trackedRasterInvalidations.size()); |
| document().view()->setTracksPaintInvalidations(false); |
| |
| // Resize the iframe. |
| document().view()->setTracksPaintInvalidations(true); |
| iframe->setAttribute(HTMLNames::styleAttr, "height: 200px"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto& rasterInvalidations = |
| getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(2u, rasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 100, 100, 100), rasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(iframe->layoutObject()), |
| rasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[0].reason); |
| EXPECT_EQ( |
| static_cast<const DisplayItemClient*>(content->layoutObject()->view()), |
| rasterInvalidations[1].client); |
| if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| // TODO(skobes): Treat LayoutView in the same way as normal objects having |
| // background-attachment: local. crbug.com/568847. |
| EXPECT_EQ(IntRect(0, 0, 100, 200), rasterInvalidations[1].rect); |
| EXPECT_EQ(PaintInvalidationFull, rasterInvalidations[1].reason); |
| } else { |
| EXPECT_EQ(IntRect(0, 100, 100, 100), rasterInvalidations[1].rect); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[1].reason); |
| } |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, NonCompositedLayoutViewGradientResize) { |
| setBodyInnerHTML( |
| "<style>" |
| " body { margin: 0 }" |
| " iframe { display: block; width: 100px; height: 100px; border: none; }" |
| "</style>" |
| "<iframe id='iframe'></iframe>"); |
| setChildFrameHTML( |
| "<style>" |
| " ::-webkit-scrollbar { display: none }" |
| " body {" |
| " margin: 0;" |
| " height: 0;" |
| " background-image: linear-gradient(blue, yellow);" |
| " }" |
| "</style>" |
| "<div id='content' style='width: 200px; height: 200px'></div>"); |
| document().view()->updateAllLifecyclePhases(); |
| Element* iframe = document().getElementById("iframe"); |
| Element* content = childDocument().getElementById("content"); |
| LayoutView* frameLayoutView = content->layoutObject()->view(); |
| EXPECT_EQ(layoutView(), |
| content->layoutObject()->containerForPaintInvalidation()); |
| |
| // Resize the content. |
| document().view()->setTracksPaintInvalidations(true); |
| content->setAttribute(HTMLNames::styleAttr, "height: 500px"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto* rasterInvalidations = |
| &getRasterInvalidationTracking()->trackedRasterInvalidations; |
| // TODO(wangxianzhu): Temporary for crbug.com/680745. |
| // ASSERT_EQ(1u, rasterInvalidations->size()); |
| ASSERT_EQ(2u, rasterInvalidations->size()); |
| EXPECT_EQ(IntRect(0, 0, 100, 100), (*rasterInvalidations)[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(frameLayoutView), |
| (*rasterInvalidations)[0].client); |
| EXPECT_EQ(PaintInvalidationLayoutOverflowBoxChange, |
| (*rasterInvalidations)[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| |
| // Resize the iframe. |
| document().view()->setTracksPaintInvalidations(true); |
| iframe->setAttribute(HTMLNames::styleAttr, "height: 200px"); |
| document().view()->updateAllLifecyclePhases(); |
| rasterInvalidations = |
| &getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(2u, rasterInvalidations->size()); |
| EXPECT_EQ(IntRect(0, 100, 100, 100), (*rasterInvalidations)[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(iframe->layoutObject()), |
| (*rasterInvalidations)[0].client); |
| EXPECT_EQ(PaintInvalidationIncremental, (*rasterInvalidations)[0].reason); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(frameLayoutView), |
| (*rasterInvalidations)[1].client); |
| EXPECT_EQ(IntRect(0, 0, 100, 200), (*rasterInvalidations)[1].rect); |
| if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { |
| // TODO(skobes): Treat LayoutView in the same way as normal objects having |
| // background-attachment: local. crbug.com/568847. |
| EXPECT_EQ(PaintInvalidationFull, (*rasterInvalidations)[1].reason); |
| } else { |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, |
| (*rasterInvalidations)[1].reason); |
| } |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, CompositedBackgroundAttachmentLocalResize) { |
| enableCompositing(); |
| |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::classAttr, "border local-background"); |
| target->setAttribute(HTMLNames::styleAttr, "will-change: transform"); |
| target->setInnerHTML( |
| "<div id=child style='width: 500px; height: 500px'></div>", |
| ASSERT_NO_EXCEPTION); |
| Element* child = document().getElementById("child"); |
| document().view()->updateAllLifecyclePhases(); |
| |
| // Resize the content. |
| document().view()->setTracksPaintInvalidations(true); |
| child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px"); |
| document().view()->updateAllLifecyclePhases(); |
| LayoutBoxModelObject* targetObj = |
| toLayoutBoxModelObject(target->layoutObject()); |
| GraphicsLayer* containerLayer = |
| targetObj->layer()->graphicsLayerBacking(targetObj); |
| GraphicsLayer* contentsLayer = targetObj->layer()->graphicsLayerBacking(); |
| // No invalidation on the container layer. |
| EXPECT_FALSE(containerLayer->getRasterInvalidationTracking()); |
| // Incremental invalidation of background on contents layer. |
| const auto& contentsRasterInvalidations = |
| contentsLayer->getRasterInvalidationTracking() |
| ->trackedRasterInvalidations; |
| ASSERT_EQ(1u, contentsRasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 500, 500, 500), contentsRasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(target->layoutObject()), |
| contentsRasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationBackgroundOnScrollingContentsLayer, |
| contentsRasterInvalidations[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| |
| // Resize the container. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, |
| "will-change: transform; height: 200px"); |
| document().view()->updateAllLifecyclePhases(); |
| // No invalidation on the contents layer. |
| EXPECT_FALSE(contentsLayer->getRasterInvalidationTracking()); |
| // Incremental invalidation on the container layer. |
| const auto& containerRasterInvalidations = |
| containerLayer->getRasterInvalidationTracking() |
| ->trackedRasterInvalidations; |
| ASSERT_EQ(1u, containerRasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 120, 70, 120), containerRasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(target->layoutObject()), |
| containerRasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationIncremental, |
| containerRasterInvalidations[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, |
| CompositedBackgroundAttachmentLocalGradientResize) { |
| enableCompositing(); |
| |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::classAttr, |
| "border local-background gradient"); |
| target->setAttribute(HTMLNames::styleAttr, "will-change: transform"); |
| target->setInnerHTML( |
| "<div id='child' style='width: 500px; height: 500px'></div>", |
| ASSERT_NO_EXCEPTION); |
| Element* child = document().getElementById("child"); |
| document().view()->updateAllLifecyclePhases(); |
| |
| // Resize the content. |
| document().view()->setTracksPaintInvalidations(true); |
| child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px"); |
| document().view()->updateAllLifecyclePhases(); |
| LayoutBoxModelObject* targetObj = |
| toLayoutBoxModelObject(target->layoutObject()); |
| GraphicsLayer* containerLayer = |
| targetObj->layer()->graphicsLayerBacking(targetObj); |
| GraphicsLayer* contentsLayer = targetObj->layer()->graphicsLayerBacking(); |
| // No invalidation on the container layer. |
| EXPECT_FALSE(containerLayer->getRasterInvalidationTracking()); |
| // Full invalidation of background on contents layer because the gradient |
| // background is resized. |
| const auto& contentsRasterInvalidations = |
| contentsLayer->getRasterInvalidationTracking() |
| ->trackedRasterInvalidations; |
| ASSERT_EQ(1u, contentsRasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 0, 500, 1000), contentsRasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(target->layoutObject()), |
| contentsRasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationBackgroundOnScrollingContentsLayer, |
| contentsRasterInvalidations[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| |
| // Resize the container. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, |
| "will-change: transform; height: 200px"); |
| document().view()->updateAllLifecyclePhases(); |
| EXPECT_FALSE(contentsLayer->getRasterInvalidationTracking()); |
| // Full invalidation on the container layer. |
| const auto& containerRasterInvalidations = |
| containerLayer->getRasterInvalidationTracking() |
| ->trackedRasterInvalidations; |
| ASSERT_EQ(1u, containerRasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 0, 70, 240), containerRasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(target->layoutObject()), |
| containerRasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationBorderBoxChange, |
| containerRasterInvalidations[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| TEST_P(BoxPaintInvalidatorTest, NonCompositedBackgroundAttachmentLocalResize) { |
| Element* target = document().getElementById("target"); |
| target->setAttribute(HTMLNames::classAttr, "border local-background"); |
| target->setInnerHTML( |
| "<div id=child style='width: 500px; height: 500px'></div>", |
| ASSERT_NO_EXCEPTION); |
| Element* child = document().getElementById("child"); |
| document().view()->updateAllLifecyclePhases(); |
| EXPECT_EQ(&layoutView(), |
| &target->layoutObject()->containerForPaintInvalidation()); |
| |
| // Resize the content. |
| document().view()->setTracksPaintInvalidations(true); |
| child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px"); |
| document().view()->updateAllLifecyclePhases(); |
| // No invalidation because the changed part is invisible. |
| EXPECT_FALSE(getRasterInvalidationTracking()); |
| |
| // Resize the container. |
| document().view()->setTracksPaintInvalidations(true); |
| target->setAttribute(HTMLNames::styleAttr, "height: 200px"); |
| document().view()->updateAllLifecyclePhases(); |
| const auto& rasterInvalidations = |
| getRasterInvalidationTracking()->trackedRasterInvalidations; |
| ASSERT_EQ(1u, rasterInvalidations.size()); |
| EXPECT_EQ(IntRect(0, 120, 70, 120), rasterInvalidations[0].rect); |
| EXPECT_EQ(static_cast<const DisplayItemClient*>(target->layoutObject()), |
| rasterInvalidations[0].client); |
| EXPECT_EQ(PaintInvalidationIncremental, rasterInvalidations[0].reason); |
| document().view()->setTracksPaintInvalidations(false); |
| } |
| |
| } // namespace blink |