Title: [119867] trunk/Source
Revision
119867
Author
[email protected]
Date
2012-06-08 14:37:33 -0700 (Fri, 08 Jun 2012)

Log Message

[chromium] Skip willDraw() and didDraw() on fully occluded layers
https://bugs.webkit.org/show_bug.cgi?id=88435

Reviewed by Adrienne Walker.

Source/WebCore:

Current willDraw() is called on all layers with non-empty
visibleLayerRect and non-empty scissorRect. This excludes
layers outside the viewport, but does not exclude occluded
layers. We add a check for occlusion to calculateRenderPasses
in order to avoid willDraw() when it will be culled anyway.

We prevent didDraw() from being called for occluded layers, for
which we did not call didDraw() by holding a vector of layers
for which we did call willDraw(). This lets us avoid storing a
flag on the layers, or computing occlusion again in
didDrawAllLayers.

Unit test: CCLayerTreeHostImplTest.willDrawNotCalledOnOccludedLayer

* platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
(WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
(WebCore::CCLayerTreeHostImpl::prepareToDraw):
(WebCore::CCLayerTreeHostImpl::didDrawAllLayers):
* platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
(FrameData):
(CCLayerTreeHostImpl):

Source/WebKit/chromium:

* tests/CCLayerTreeHostImplTest.cpp:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (119866 => 119867)


--- trunk/Source/WebCore/ChangeLog	2012-06-08 21:37:01 UTC (rev 119866)
+++ trunk/Source/WebCore/ChangeLog	2012-06-08 21:37:33 UTC (rev 119867)
@@ -1,3 +1,32 @@
+2012-06-08  Dana Jansens  <[email protected]>
+
+        [chromium] Skip willDraw() and didDraw() on fully occluded layers
+        https://bugs.webkit.org/show_bug.cgi?id=88435
+
+        Reviewed by Adrienne Walker.
+
+        Current willDraw() is called on all layers with non-empty
+        visibleLayerRect and non-empty scissorRect. This excludes
+        layers outside the viewport, but does not exclude occluded
+        layers. We add a check for occlusion to calculateRenderPasses
+        in order to avoid willDraw() when it will be culled anyway.
+
+        We prevent didDraw() from being called for occluded layers, for
+        which we did not call didDraw() by holding a vector of layers
+        for which we did call willDraw(). This lets us avoid storing a
+        flag on the layers, or computing occlusion again in
+        didDrawAllLayers.
+
+        Unit test: CCLayerTreeHostImplTest.willDrawNotCalledOnOccludedLayer
+
+        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
+        (WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
+        (WebCore::CCLayerTreeHostImpl::prepareToDraw):
+        (WebCore::CCLayerTreeHostImpl::didDrawAllLayers):
+        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
+        (FrameData):
+        (CCLayerTreeHostImpl):
+
 2012-06-08  Antonio Gomes  <[email protected]>
 
         EventHandler shouldn't schedule the fake mousemove event timer when scrolling on devices that don't have a mouse

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp (119866 => 119867)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp	2012-06-08 21:37:01 UTC (rev 119866)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp	2012-06-08 21:37:33 UTC (rev 119867)
@@ -261,13 +261,8 @@
     }
 }
 
-static inline bool shouldDrawLayer(CCLayerImpl* layer)
+bool CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList, CCLayerList& willDrawLayers)
 {
-    return !layer->visibleLayerRect().isEmpty() && !layer->scissorRect().isEmpty();
-}
-
-bool CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLayerList& renderSurfaceLayerList)
-{
     ASSERT(passes.isEmpty());
 
     calculateRenderSurfaceLayerList(renderSurfaceLayerList);
@@ -310,8 +305,10 @@
         if (it.representsContributingRenderSurface() && !it->renderSurface()->scissorRect().isEmpty()) {
             CCRenderPass* contributingRenderPass = surfacePassMap.get(it->renderSurface());
             pass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker);
-        } else if (it.representsItself() && shouldDrawLayer(*it)) {
+        } else if (it.representsItself() && !occlusionTracker.occluded(*it, it->visibleLayerRect()) && !it->visibleLayerRect().isEmpty() && !it->scissorRect().isEmpty()) {
             it->willDraw(m_layerRenderer.get(), context());
+            willDrawLayers.append(*it);
+
             pass->appendQuadsForLayer(*it, &occlusionTracker, hadMissingTiles);
         }
 
@@ -384,8 +381,9 @@
 
     frame.renderPasses.clear();
     frame.renderSurfaceLayerList.clear();
+    frame.willDrawLayers.clear();
 
-    if (!calculateRenderPasses(frame.renderPasses, frame.renderSurfaceLayerList))
+    if (!calculateRenderPasses(frame.renderPasses, frame.renderSurfaceLayerList, frame.willDrawLayers))
         return false;
 
     // If we return true, then we expect drawLayers() to be called before this function is called again.
@@ -436,13 +434,8 @@
 
 void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
 {
-    typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
-
-    CCLayerIteratorType end = CCLayerIteratorType::end(&frame.renderSurfaceLayerList);
-    for (CCLayerIteratorType it = CCLayerIteratorType::begin(&frame.renderSurfaceLayerList); it != end; ++it) {
-        if (it.representsItself() && shouldDrawLayer(*it))
-            it->didDraw();
-    }
+    for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
+        frame.willDrawLayers[i]->didDraw();
 }
 
 void CCLayerTreeHostImpl::finishAllRendering()

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h (119866 => 119867)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h	2012-06-08 21:37:01 UTC (rev 119866)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h	2012-06-08 21:37:33 UTC (rev 119867)
@@ -87,6 +87,7 @@
     struct FrameData {
         CCRenderPassList renderPasses;
         CCLayerList renderSurfaceLayerList;
+        CCLayerList willDrawLayers;
     };
 
     // Virtual for testing.
@@ -200,7 +201,7 @@
     // Returns false if the frame should not be displayed. This function should
     // only be called from prepareToDraw, as didDrawAllLayers must be called
     // if this helper function is called.
-    bool calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList);
+    bool calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList, CCLayerList& willDrawLayers);
     void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector*, bool& didAnimate, bool& needsAnimateLayers);
     void setBackgroundTickingEnabled(bool);
     IntSize contentSize() const;

Modified: trunk/Source/WebKit/chromium/ChangeLog (119866 => 119867)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-06-08 21:37:01 UTC (rev 119866)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-06-08 21:37:33 UTC (rev 119867)
@@ -1,3 +1,12 @@
+2012-06-08  Dana Jansens  <[email protected]>
+
+        [chromium] Skip willDraw() and didDraw() on fully occluded layers
+        https://bugs.webkit.org/show_bug.cgi?id=88435
+
+        Reviewed by Adrienne Walker.
+
+        * tests/CCLayerTreeHostImplTest.cpp:
+
 2012-06-08  James Robinson  <[email protected]>
 
         [chromium] Clean up some unnecessary LayerChromium.h includes

Modified: trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp (119866 => 119867)


--- trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp	2012-06-08 21:37:01 UTC (rev 119866)
+++ trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp	2012-06-08 21:37:33 UTC (rev 119867)
@@ -468,7 +468,12 @@
     {
         setAnchorPoint(FloatPoint(0, 0));
         setBounds(IntSize(10, 10));
+        setContentBounds(IntSize(10, 10));
         setDrawsContent(true);
+        setSkipsDraw(false);
+
+        OwnPtr<CCLayerTilingData> tiler = CCLayerTilingData::create(IntSize(100, 100), CCLayerTilingData::HasBorderTexels);
+        setTilingData(*tiler.get());
     }
 
 private:
@@ -521,6 +526,42 @@
     EXPECT_FALSE(layer->visibleLayerRect().isEmpty());
 }
 
+TEST_F(CCLayerTreeHostImplTest, willDrawNotCalledOnOccludedLayer)
+{
+    // Make the viewport large so that we can have large layers that get considered for occlusion (small layers do not).
+    IntSize bigSize(1000, 1000);
+    m_hostImpl->setViewportSize(bigSize);
+
+    m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
+    DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
+
+    root->addChild(DidDrawCheckLayer::create(1));
+    DidDrawCheckLayer* occludedLayer = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
+
+    root->addChild(DidDrawCheckLayer::create(2));
+    DidDrawCheckLayer* topLayer = static_cast<DidDrawCheckLayer*>(root->children()[1].get());
+    // This layer covers the occludedLayer above. Make this layer large so it can occlude.
+    topLayer->setBounds(bigSize);
+    topLayer->setContentBounds(bigSize);
+    topLayer->setOpaque(true);
+
+    CCLayerTreeHostImpl::FrameData frame;
+
+    EXPECT_FALSE(occludedLayer->willDrawCalled());
+    EXPECT_FALSE(occludedLayer->didDrawCalled());
+    EXPECT_FALSE(topLayer->willDrawCalled());
+    EXPECT_FALSE(topLayer->didDrawCalled());
+
+    EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
+    m_hostImpl->drawLayers(frame);
+    m_hostImpl->didDrawAllLayers(frame);
+
+    EXPECT_FALSE(occludedLayer->willDrawCalled());
+    EXPECT_FALSE(occludedLayer->didDrawCalled());
+    EXPECT_TRUE(topLayer->willDrawCalled());
+    EXPECT_TRUE(topLayer->didDrawCalled());
+}
+
 TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
 {
     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to