Title: [113241] trunk/Source
Revision
113241
Author
commit-qu...@webkit.org
Date
2012-04-04 14:27:36 -0700 (Wed, 04 Apr 2012)

Log Message

[Chromium] Always skip draw and readback if there is nothing
to draw.
https://bugs.webkit.org/show_bug.cgi?id=82680

This avoids corruption from pushing frames that have no valid
content drawn into them.
Also in addition to checking for non-existing root layers, check
for root layers with no content bounds. It's possible to see those
with kForceCompositing mode for empty documents.

Patch by Daniel Sievers <siev...@chromium.org> on 2012-04-04
Reviewed by James Robinson.

Added CCLayerTreeHostTestEmptyContentsShouldNotDraw.

Source/WebCore:

* platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
(WebCore::CCLayerTreeHostImpl::canDraw):
(WebCore::CCLayerTreeHostImpl::prepareToDraw):
* platform/graphics/chromium/cc/CCThreadProxy.cpp:
(WebCore::CCThreadProxy::scheduledActionDrawAndSwapInternal):

Source/WebKit/chromium:

* tests/CCLayerTreeHostImplTest.cpp:
(WebKitTests::TEST_F):
* tests/CCLayerTreeHostTest.cpp:
(WTF::CCLayerTreeHostTest::doBeginTest):
(WTF):
(CCLayerTreeHostTestEmptyContentsShouldNotDraw):
(WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::CCLayerTreeHostTestEmptyContentsShouldNotDraw):
(WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::beginTest):
(WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::drawLayersOnCCThread):
(WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::didCommitAndDrawFrame):
(WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::afterTest):
(WTF::TEST_F):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (113240 => 113241)


--- trunk/Source/WebCore/ChangeLog	2012-04-04 21:14:48 UTC (rev 113240)
+++ trunk/Source/WebCore/ChangeLog	2012-04-04 21:27:36 UTC (rev 113241)
@@ -1,3 +1,25 @@
+2012-04-04  Daniel Sievers  <siev...@chromium.org>
+
+        [Chromium] Always skip draw and readback if there is nothing
+        to draw.
+        https://bugs.webkit.org/show_bug.cgi?id=82680
+
+        This avoids corruption from pushing frames that have no valid
+        content drawn into them.
+        Also in addition to checking for non-existing root layers, check
+        for root layers with no content bounds. It's possible to see those
+        with kForceCompositing mode for empty documents.
+
+        Reviewed by James Robinson.
+
+        Added CCLayerTreeHostTestEmptyContentsShouldNotDraw.
+
+        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
+        (WebCore::CCLayerTreeHostImpl::canDraw):
+        (WebCore::CCLayerTreeHostImpl::prepareToDraw):
+        * platform/graphics/chromium/cc/CCThreadProxy.cpp:
+        (WebCore::CCThreadProxy::scheduledActionDrawAndSwapInternal):
+
 2012-03-15  Jer Noble  <jer.no...@apple.com>
 
         Full Screen mode should cancel before navigation.

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


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp	2012-04-04 21:14:48 UTC (rev 113240)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp	2012-04-04 21:27:36 UTC (rev 113241)
@@ -141,7 +141,7 @@
 
 bool CCLayerTreeHostImpl::canDraw()
 {
-    if (!rootLayer())
+    if (!rootLayer() || rootLayer()->bounds().isEmpty())
         return false;
     if (viewportSize().isEmpty())
         return false;
@@ -376,9 +376,6 @@
     frame.renderPasses.clear();
     frame.renderSurfaceLayerList.clear();
 
-    if (!rootLayer())
-        return false;
-
     if (!calculateRenderPasses(frame.renderPasses, frame.renderSurfaceLayerList))
         return false;
 

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


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h	2012-04-04 21:14:48 UTC (rev 113240)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h	2012-04-04 21:27:36 UTC (rev 113241)
@@ -88,7 +88,7 @@
     virtual void beginCommit();
     virtual void commitComplete();
     virtual void animate(double monotonicTime, double wallClockTime);
-    // Returns false if problems occured preparing the frame, and we should try to avoid displaying the frame.
+    // Returns false if we should try to avoid displaying the frame, because it has visible checkerboard during an animation.
     virtual bool prepareToDraw(FrameData&);
     virtual void drawLayers(const FrameData&);
 
@@ -102,6 +102,8 @@
     virtual void setFullRootLayerDamage();
 
     // Implementation
+
+    // Returns false if there is no valid root layer and thus no content that can be drawn.
     bool canDraw();
     GraphicsContext3D* context();
 

Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp (113240 => 113241)


--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp	2012-04-04 21:14:48 UTC (rev 113240)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp	2012-04-04 21:27:36 UTC (rev 113241)
@@ -578,7 +578,7 @@
     m_inputHandlerOnImplThread->animate(monotonicTime);
     m_layerTreeHostImpl->animate(monotonicTime, wallClockTime);
     CCLayerTreeHostImpl::FrameData frame;
-    bool drawFrame = m_layerTreeHostImpl->prepareToDraw(frame) || forcedDraw;
+    bool drawFrame = m_layerTreeHostImpl->canDraw() && (m_layerTreeHostImpl->prepareToDraw(frame) || forcedDraw);
     if (drawFrame) {
         m_layerTreeHostImpl->drawLayers(frame);
         result.didDraw = true;
@@ -586,9 +586,9 @@
 
     // Check for a pending compositeAndReadback.
     if (m_readbackRequestOnImplThread) {
-        ASSERT(drawFrame); // This should be a forcedDraw
-        m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect);
-        m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost();
+        if (drawFrame)
+            m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect);
+        m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost() && drawFrame;
         m_readbackRequestOnImplThread->completion.signal();
         m_readbackRequestOnImplThread = 0;
     }
@@ -598,7 +598,6 @@
 
     // Process any finish request
     if (m_finishAllRenderingCompletionEventOnImplThread) {
-        ASSERT(drawFrame); // This should be a forcedDraw
         m_layerTreeHostImpl->finishAllRendering();
         m_finishAllRenderingCompletionEventOnImplThread->signal();
         m_finishAllRenderingCompletionEventOnImplThread = 0;
@@ -610,7 +609,6 @@
         m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::didCommitAndDrawFrame));
     }
 
-    ASSERT(drawFrame || (!drawFrame && !forcedDraw));
     return result;
 }
 

Modified: trunk/Source/WebKit/chromium/ChangeLog (113240 => 113241)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-04-04 21:14:48 UTC (rev 113240)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-04-04 21:27:36 UTC (rev 113241)
@@ -1,3 +1,32 @@
+2012-04-04  Daniel Sievers  <siev...@chromium.org>
+
+        [Chromium] Always skip draw and readback if there is nothing
+        to draw.
+        https://bugs.webkit.org/show_bug.cgi?id=82680
+
+        This avoids corruption from pushing frames that have no valid
+        content drawn into them.
+        Also in addition to checking for non-existing root layers, check
+        for root layers with no content bounds. It's possible to see those
+        with kForceCompositing mode for empty documents.
+
+        Reviewed by James Robinson.
+
+        Added CCLayerTreeHostTestEmptyContentsShouldNotDraw.
+
+        * tests/CCLayerTreeHostImplTest.cpp:
+        (WebKitTests::TEST_F):
+        * tests/CCLayerTreeHostTest.cpp:
+        (WTF::CCLayerTreeHostTest::doBeginTest):
+        (WTF):
+        (CCLayerTreeHostTestEmptyContentsShouldNotDraw):
+        (WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::CCLayerTreeHostTestEmptyContentsShouldNotDraw):
+        (WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::beginTest):
+        (WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::drawLayersOnCCThread):
+        (WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::didCommitAndDrawFrame):
+        (WTF::CCLayerTreeHostTestEmptyContentsShouldNotDraw::afterTest):
+        (WTF::TEST_F):
+
 2012-04-04  Mark Pilgrim  <pilg...@chromium.org>
 
         Call histogramCustomCounts directly

Modified: trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp (113240 => 113241)


--- trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp	2012-04-04 21:14:48 UTC (rev 113240)
+++ trunk/Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp	2012-04-04 21:27:36 UTC (rev 113241)
@@ -248,6 +248,7 @@
     m_hostImpl->initializeLayerRenderer(createContext());
 
     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
+    root->setBounds(IntSize(1, 1));
     root->setScrollable(true);
     root->setScrollPosition(IntPoint(0, 0));
     root->setMaxScrollPosition(IntSize(100, 100));

Modified: trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp (113240 => 113241)


--- trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp	2012-04-04 21:14:48 UTC (rev 113240)
+++ trunk/Source/WebKit/chromium/tests/CCLayerTreeHostTest.cpp	2012-04-04 21:27:36 UTC (rev 113241)
@@ -532,6 +532,10 @@
     m_client = MockLayerTreeHostClient::create(this);
 
     RefPtr<LayerChromium> rootLayer = LayerChromium::create();
+
+    // Only non-empty root layers will cause drawing to happen.
+    rootLayer->setBounds(IntSize(1, 1));
+
     m_layerTreeHost = MockLayerTreeHost::create(this, m_client.get(), rootLayer, m_settings);
     ASSERT_TRUE(m_layerTreeHost);
     rootLayer->setLayerTreeHost(m_layerTreeHost.get());
@@ -821,6 +825,56 @@
     runTestThreaded();
 }
 
+// If the root layer has no content bounds, we should see a commit, but should not be
+// pushing any frames as the contents will be undefined. Regardless, forced draws need
+// to always signal completion.
+class CCLayerTreeHostTestEmptyContentsShouldNotDraw : public CCLayerTreeHostTestThreadOnly {
+public:
+    CCLayerTreeHostTestEmptyContentsShouldNotDraw()
+        : m_numCommits(0)
+    {
+    }
+
+    virtual void beginTest()
+    {
+    }
+
+    virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
+    {
+        // Only the initial draw should bring us here.
+        EXPECT_FALSE(impl->rootLayer()->bounds().isEmpty());
+    }
+
+    virtual void didCommitAndDrawFrame()
+    {
+        m_numCommits++;
+        if (m_numCommits == 1) {
+            // Put an empty root layer.
+            RefPtr<LayerChromium> rootLayer = LayerChromium::create();
+            m_layerTreeHost->setRootLayer(rootLayer);
+
+            OwnArrayPtr<char> pixels(adoptArrayPtr(new char[4]));
+            m_layerTreeHost->compositeAndReadback(static_cast<void*>(pixels.get()), IntRect(0, 0, 1, 1));
+        } else if (m_numCommits == 2) {
+            m_layerTreeHost->setNeedsCommit();
+            m_layerTreeHost->finishAllRendering();
+            endTest();
+        }
+    }
+
+    virtual void afterTest()
+    {
+    }
+
+private:
+    int m_numCommits;
+};
+
+TEST_F(CCLayerTreeHostTestEmptyContentsShouldNotDraw, runMultiThread)
+{
+    runTestThreaded();
+}
+
 // A compositeAndReadback while invisible should force a normal commit without assertion.
 class CCLayerTreeHostTestCompositeAndReadbackWhileInvisible : public CCLayerTreeHostTestThreadOnly {
 public:
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to