[chromium] Extract scheduling logic from CCThreadProxy to its own class

https://bugs.webkit.org/show_bug.cgi?id=69049

Patch by James Robinson <jamesr@chromium.org> on 2011-10-04
Reviewed by Kenneth Russell.

Source/WebCore:

This partially extracts the commit/draw scheduling from CCThreadProxy to a separate isolated class. This makes
the commit/draw logic easier to test, understand and extend.

There is one subtle behavior change here to the way that the function formerly known as
CCLayerTreeHost::setNeedsCommitAndRedraw works. Previously, this would trigger a begin frame message, if one
wasn't pending, and then trigger a redraw if one wasn't pending. This was subtly wrong - the intent of that call
is that a redraw should happen after the commit. It isn't useful to draw before the commit occurs. This patch
changes the name of the function to setNeedsCommitThenRedraw and only requests a redraw after a commit occurs.

Covered by new CCSchedulerTest unit tests, CCLayerTreeHostTest unit tests, and compositing/ layout tests.

* WebCore.gypi:
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore::CCLayerTreeHost::initialize):
(WebCore::CCLayerTreeHost::setZoomAnimatorTransform):
(WebCore::CCLayerTreeHost::setNeedsCommitThenRedraw):
(WebCore::CCLayerTreeHost::setViewport):
(WebCore::CCLayerTreeHost::setVisible):
* platform/graphics/chromium/cc/CCLayerTreeHost.h:
* platform/graphics/chromium/cc/CCProxy.h:
* platform/graphics/chromium/cc/CCScheduler.cpp: Added.
(WebCore::CCScheduler::CCScheduler):
(WebCore::CCScheduler::requestCommit):
(WebCore::CCScheduler::requestCommitThenRedraw):
(WebCore::CCScheduler::requestRedraw):
(WebCore::CCScheduler::didCommit):
(WebCore::CCScheduler::didDraw):
* platform/graphics/chromium/cc/CCScheduler.h: Added.
(WebCore::CCSchedulerClient::~CCSchedulerClient):
(WebCore::CCScheduler::create):
(WebCore::CCScheduler::commitPending):
(WebCore::CCScheduler::redrawPending):
(WebCore::CCScheduler::redrawAfterCommit):
* platform/graphics/chromium/cc/CCSingleThreadProxy.cpp:
(WebCore::CCSingleThreadProxy::setNeedsCommitThenRedraw):
(WebCore::CCSingleThreadProxy::setNeedsRedraw):
(WebCore::CCSingleThreadProxy::recreateContextIfNeeded):
(WebCore::CCSingleThreadProxy::doComposite):
* platform/graphics/chromium/cc/CCSingleThreadProxy.h:
* platform/graphics/chromium/cc/CCThreadProxy.cpp:
(WebCore::CCThreadProxySchedulerClient::create):
(WebCore::CCThreadProxySchedulerClient::~CCThreadProxySchedulerClient):
(WebCore::CCThreadProxySchedulerClient::scheduleBeginFrameAndCommit):
(WebCore::CCThreadProxySchedulerClient::scheduleDrawAndPresent):
(WebCore::CCThreadProxySchedulerClient::CCThreadProxySchedulerClient):
(WebCore::CCThreadProxy::CCThreadProxy):
(WebCore::CCThreadProxy::compositeAndReadback):
(WebCore::CCThreadProxy::initializeLayerRenderer):
(WebCore::CCThreadProxy::setNeedsCommit):
(WebCore::CCThreadProxy::setNeedsCommitOnCCThread):
(WebCore::CCThreadProxy::setNeedsCommitThenRedraw):
(WebCore::CCThreadProxy::setNeedsCommitThenRedrawOnCCThread):
(WebCore::CCThreadProxy::setNeedsRedraw):
(WebCore::CCThreadProxy::setNeedsRedrawOnCCThread):
(WebCore::CCThreadProxy::finishAllRenderingOnCCThread):
(WebCore::CCThreadProxy::obtainBeginFrameAndCommitTaskFromCCThread):
(WebCore::CCThreadProxy::createBeginFrameAndCommitTaskOnCCThread):
(WebCore::CCThreadProxy::beginFrameAndCommit):
(WebCore::CCThreadProxy::commitOnCCThread):
(WebCore::CCThreadProxy::drawLayersAndPresentOnCCThread):
(WebCore::CCThreadProxy::initializeImplOnCCThread):
* platform/graphics/chromium/cc/CCThreadProxy.h:

Source/WebKit/chromium:

Adds some unit tests for the new CCScheduler class. Since the class is very simple today, the tests are
similarly quite simple.

* WebKit.gypi:
* src/WebViewImpl.cpp:
(WebKit::WebViewImpl::setRootLayerNeedsDisplay):
* tests/CCLayerTreeHostTest.cpp:
(WTF::CCLayerTreeHostTest::postSetNeedsCommitThenRedrawToMainThread):
(WTF::CCLayerTreeHostTest::dispatchSetNeedsCommitThenRedraw):
(WTF::CCLayerTreeHostTestShortlived2::beginTest):
(WTF::CCLayerTreeHostTestCommitingWithContinuousRedraw::beginTest):
(WTF::CCLayerTreeHostTestCommitingWithContinuousRedraw::drawLayersOnCCThread):
(WTF::CCLayerTreeHostTestSetNeedsCommit1::beginTest):
(WTF::CCLayerTreeHostTestSetNeedsCommit2::beginTest):
(WTF::CCLayerTreeHostTestSetNeedsCommit2::drawLayersOnCCThread):
(WTF::CCLayerTreeHostTestSetNeedsRedraw::beginTest):
* tests/CCSchedulerTest.cpp: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96655 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 76b3be74
2011-10-04 James Robinson <jamesr@chromium.org>
[chromium] Extract scheduling logic from CCThreadProxy to its own class
https://bugs.webkit.org/show_bug.cgi?id=69049
Reviewed by Kenneth Russell.
This partially extracts the commit/draw scheduling from CCThreadProxy to a separate isolated class. This makes
the commit/draw logic easier to test, understand and extend.
There is one subtle behavior change here to the way that the function formerly known as
CCLayerTreeHost::setNeedsCommitAndRedraw works. Previously, this would trigger a begin frame message, if one
wasn't pending, and then trigger a redraw if one wasn't pending. This was subtly wrong - the intent of that call
is that a redraw should happen after the commit. It isn't useful to draw before the commit occurs. This patch
changes the name of the function to setNeedsCommitThenRedraw and only requests a redraw after a commit occurs.
Covered by new CCSchedulerTest unit tests, CCLayerTreeHostTest unit tests, and compositing/ layout tests.
* WebCore.gypi:
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore::CCLayerTreeHost::initialize):
(WebCore::CCLayerTreeHost::setZoomAnimatorTransform):
(WebCore::CCLayerTreeHost::setNeedsCommitThenRedraw):
(WebCore::CCLayerTreeHost::setViewport):
(WebCore::CCLayerTreeHost::setVisible):
* platform/graphics/chromium/cc/CCLayerTreeHost.h:
* platform/graphics/chromium/cc/CCProxy.h:
* platform/graphics/chromium/cc/CCScheduler.cpp: Added.
(WebCore::CCScheduler::CCScheduler):
(WebCore::CCScheduler::requestCommit):
(WebCore::CCScheduler::requestCommitThenRedraw):
(WebCore::CCScheduler::requestRedraw):
(WebCore::CCScheduler::didCommit):
(WebCore::CCScheduler::didDraw):
* platform/graphics/chromium/cc/CCScheduler.h: Added.
(WebCore::CCSchedulerClient::~CCSchedulerClient):
(WebCore::CCScheduler::create):
(WebCore::CCScheduler::commitPending):
(WebCore::CCScheduler::redrawPending):
(WebCore::CCScheduler::redrawAfterCommit):
* platform/graphics/chromium/cc/CCSingleThreadProxy.cpp:
(WebCore::CCSingleThreadProxy::setNeedsCommitThenRedraw):
(WebCore::CCSingleThreadProxy::setNeedsRedraw):
(WebCore::CCSingleThreadProxy::recreateContextIfNeeded):
(WebCore::CCSingleThreadProxy::doComposite):
* platform/graphics/chromium/cc/CCSingleThreadProxy.h:
* platform/graphics/chromium/cc/CCThreadProxy.cpp:
(WebCore::CCThreadProxySchedulerClient::create):
(WebCore::CCThreadProxySchedulerClient::~CCThreadProxySchedulerClient):
(WebCore::CCThreadProxySchedulerClient::scheduleBeginFrameAndCommit):
(WebCore::CCThreadProxySchedulerClient::scheduleDrawAndPresent):
(WebCore::CCThreadProxySchedulerClient::CCThreadProxySchedulerClient):
(WebCore::CCThreadProxy::CCThreadProxy):
(WebCore::CCThreadProxy::compositeAndReadback):
(WebCore::CCThreadProxy::initializeLayerRenderer):
(WebCore::CCThreadProxy::setNeedsCommit):
(WebCore::CCThreadProxy::setNeedsCommitOnCCThread):
(WebCore::CCThreadProxy::setNeedsCommitThenRedraw):
(WebCore::CCThreadProxy::setNeedsCommitThenRedrawOnCCThread):
(WebCore::CCThreadProxy::setNeedsRedraw):
(WebCore::CCThreadProxy::setNeedsRedrawOnCCThread):
(WebCore::CCThreadProxy::finishAllRenderingOnCCThread):
(WebCore::CCThreadProxy::obtainBeginFrameAndCommitTaskFromCCThread):
(WebCore::CCThreadProxy::createBeginFrameAndCommitTaskOnCCThread):
(WebCore::CCThreadProxy::beginFrameAndCommit):
(WebCore::CCThreadProxy::commitOnCCThread):
(WebCore::CCThreadProxy::drawLayersAndPresentOnCCThread):
(WebCore::CCThreadProxy::initializeImplOnCCThread):
* platform/graphics/chromium/cc/CCThreadProxy.h:
2011-10-04 Alexey Proskuryakov <ap@apple.com>
https://bugs.webkit.org/show_bug.cgi?id=67774
......@@ -3498,10 +3498,10 @@
'platform/graphics/chromium/cc/CCLayerSorter.h',
'platform/graphics/chromium/cc/CCLayerTilingData.cpp',
'platform/graphics/chromium/cc/CCLayerTilingData.h',
'platform/graphics/chromium/cc/CCLayerTreeHost.cpp',
'platform/graphics/chromium/cc/CCLayerTreeHost.h',
'platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp',
'platform/graphics/chromium/cc/CCLayerTreeHostCommon.h',
'platform/graphics/chromium/cc/CCLayerTreeHost.cpp',
'platform/graphics/chromium/cc/CCLayerTreeHost.h',
'platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp',
'platform/graphics/chromium/cc/CCLayerTreeHostImpl.h',
'platform/graphics/chromium/cc/CCMainThread.cpp',
......@@ -3509,15 +3509,17 @@
'platform/graphics/chromium/cc/CCMainThreadTask.h',
'platform/graphics/chromium/cc/CCPluginLayerImpl.cpp',
'platform/graphics/chromium/cc/CCPluginLayerImpl.h',
'platform/graphics/chromium/cc/CCProxy.h',
'platform/graphics/chromium/cc/CCProxy.cpp',
'platform/graphics/chromium/cc/CCSingleThreadProxy.h',
'platform/graphics/chromium/cc/CCSingleThreadProxy.cpp',
'platform/graphics/chromium/cc/CCProxy.h',
'platform/graphics/chromium/cc/CCRenderSurface.cpp',
'platform/graphics/chromium/cc/CCRenderSurface.h',
'platform/graphics/chromium/cc/CCScheduler.cpp',
'platform/graphics/chromium/cc/CCScheduler.h',
'platform/graphics/chromium/cc/CCSingleThreadProxy.cpp',
'platform/graphics/chromium/cc/CCSingleThreadProxy.h',
'platform/graphics/chromium/cc/CCThread.h',
'platform/graphics/chromium/cc/CCThreadProxy.h',
'platform/graphics/chromium/cc/CCThreadProxy.cpp',
'platform/graphics/chromium/cc/CCThreadProxy.h',
'platform/graphics/chromium/cc/CCThreadTask.h',
'platform/graphics/chromium/cc/CCTiledLayerImpl.cpp',
'platform/graphics/chromium/cc/CCTiledLayerImpl.h',
......
......@@ -60,6 +60,7 @@ CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, PassRefPtr<Layer
bool CCLayerTreeHost::initialize()
{
TRACE_EVENT("CCLayerTreeHost::initialize", this, 0);
if (m_settings.enableCompositorThread) {
// Accelerated Painting is not supported in threaded mode. Turn it off.
m_settings.acceleratePainting = false;
......@@ -78,8 +79,7 @@ bool CCLayerTreeHost::initialize()
// Update m_settings based on capabilities that we got back from the renderer.
m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting;
// We changed the root layer. Tell the proxy a commit is needed.
m_proxy->setNeedsCommitAndRedraw();
setNeedsCommitThenRedraw();
m_contentsTextureManager = TextureManager::create(TextureManager::highLimitBytes(), m_proxy->layerRendererCapabilities().maxTextureSize);
return true;
......@@ -196,14 +196,14 @@ void CCLayerTreeHost::setZoomAnimatorTransform(const TransformationMatrix& zoom)
m_zoomAnimatorTransform = zoom;
if (zoomChanged)
setNeedsCommitAndRedraw();
setNeedsCommitThenRedraw();
}
void CCLayerTreeHost::setNeedsCommitAndRedraw()
void CCLayerTreeHost::setNeedsCommitThenRedraw()
{
#if USE(THREADED_COMPOSITING)
TRACE_EVENT("CCLayerTreeHost::setNeedsRedraw", this, 0);
m_proxy->setNeedsCommitAndRedraw();
TRACE_EVENT("CCLayerTreeHost::setNeedsCommitThenRedraw", this, 0);
m_proxy->setNeedsCommitThenRedraw();
#else
m_client->scheduleComposite();
#endif
......@@ -221,14 +221,14 @@ void CCLayerTreeHost::setNeedsRedraw()
void CCLayerTreeHost::setViewport(const IntSize& viewportSize)
{
m_viewportSize = viewportSize;
setNeedsCommitAndRedraw();
setNeedsCommitThenRedraw();
}
void CCLayerTreeHost::setVisible(bool visible)
{
m_visible = visible;
if (visible)
m_proxy->setNeedsCommitAndRedraw();
setNeedsCommitThenRedraw();
else {
m_contentsTextureManager->reduceMemoryToLimit(TextureManager::lowLimitBytes());
m_contentsTextureManager->unprotectAllTextures();
......
......@@ -135,7 +135,7 @@ public:
// Test-only hook
void loseCompositorContext(int numTimes);
void setNeedsCommitAndRedraw();
void setNeedsCommitThenRedraw();
void setNeedsRedraw();
LayerChromium* rootLayer() { return m_rootLayer.get(); }
......
......@@ -63,7 +63,7 @@ public:
virtual const LayerRendererCapabilities& layerRendererCapabilities() const = 0;
virtual void setNeedsCommit() = 0;
virtual void setNeedsCommitAndRedraw() = 0;
virtual void setNeedsCommitThenRedraw() = 0;
virtual void setNeedsRedraw() = 0;
virtual void start() = 0; // Must be called before using the proxy.
......
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "cc/CCScheduler.h"
namespace WebCore {
CCScheduler::CCScheduler(CCSchedulerClient* client)
: m_client(client)
, m_commitPending(false)
, m_redrawPending(false)
{
ASSERT(m_client);
}
void CCScheduler::requestCommit()
{
if (m_commitPending)
return;
m_commitPending = true;
m_client->scheduleBeginFrameAndCommit();
}
void CCScheduler::requestRedraw()
{
if (m_redrawPending)
return;
m_redrawPending = true;
m_client->scheduleDrawAndPresent();
}
void CCScheduler::didCommit()
{
m_commitPending = false;
}
void CCScheduler::didDraw()
{
m_redrawPending = false;
}
}
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CCScheduler_h
#define CCScheduler_h
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
namespace WebCore {
class CCThread;
class CCSchedulerClient {
public:
virtual void scheduleBeginFrameAndCommit() = 0;
virtual void scheduleDrawAndPresent() = 0;
protected:
virtual ~CCSchedulerClient() { }
};
class CCScheduler {
WTF_MAKE_NONCOPYABLE(CCScheduler);
public:
static PassOwnPtr<CCScheduler> create(CCSchedulerClient* client)
{
return adoptPtr(new CCScheduler(client));
}
void requestCommit();
void requestRedraw();
void didCommit();
void didDraw();
bool commitPending() const { return m_commitPending; }
bool redrawPending() const { return m_redrawPending; }
private:
explicit CCScheduler(CCSchedulerClient*);
CCSchedulerClient* m_client;
bool m_commitPending;
bool m_redrawPending;
};
}
#endif // CCScheduler_h
......@@ -156,7 +156,7 @@ void CCSingleThreadProxy::setNeedsCommit()
m_layerTreeHost->commitComplete();
}
void CCSingleThreadProxy::setNeedsCommitAndRedraw()
void CCSingleThreadProxy::setNeedsCommitThenRedraw()
{
ASSERT(CCProxy::isMainThread());
#if !USE(THREADED_COMPOSITING)
......@@ -171,7 +171,7 @@ void CCSingleThreadProxy::setNeedsRedraw()
{
// FIXME: Once we move render_widget scheduling into this class, we can
// treat redraw requests more efficiently than commitAndRedraw requests.
setNeedsCommitAndRedraw();
setNeedsCommitThenRedraw();
}
void CCSingleThreadProxy::stop()
......@@ -233,7 +233,7 @@ bool CCSingleThreadProxy::recreateContextIfNeeded()
// in the context-lost machinery.
m_numFailedRecreateAttempts++;
if (m_numFailedRecreateAttempts < 5) {
setNeedsCommitAndRedraw();
setNeedsCommitThenRedraw();
return false;
}
......@@ -276,7 +276,7 @@ bool CCSingleThreadProxy::doComposite()
// and request a repaint yet again.
m_graphicsContextLost = true;
m_numFailedRecreateAttempts = 0;
setNeedsCommitAndRedraw();
setNeedsCommitThenRedraw();
return false;
}
}
......
......@@ -48,7 +48,7 @@ public:
virtual const LayerRendererCapabilities& layerRendererCapabilities() const;
virtual void loseCompositorContext(int numTimes);
virtual void setNeedsCommit();
virtual void setNeedsCommitAndRedraw();
virtual void setNeedsCommitThenRedraw();
virtual void setNeedsRedraw();
virtual void start();
virtual void stop();
......
......@@ -30,6 +30,7 @@
#include "TraceEvent.h"
#include "cc/CCLayerTreeHost.h"
#include "cc/CCMainThreadTask.h"
#include "cc/CCScheduler.h"
#include "cc/CCThreadTask.h"
#include <wtf/CurrentTime.h>
#include <wtf/MainThread.h>
......@@ -48,6 +49,33 @@ void CCThreadProxy::setThread(CCThread* ccThread)
#endif
}
class CCThreadProxySchedulerClient : public CCSchedulerClient {
public:
static PassOwnPtr<CCThreadProxySchedulerClient> create(CCThreadProxy* proxy)
{
return adoptPtr(new CCThreadProxySchedulerClient(proxy));
}
virtual ~CCThreadProxySchedulerClient() { }
virtual void scheduleBeginFrameAndCommit()
{
CCMainThread::postTask(m_proxy->createBeginFrameAndCommitTaskOnCCThread());
}
virtual void scheduleDrawAndPresent()
{
m_proxy->drawLayersAndPresentOnCCThread();
}
private:
explicit CCThreadProxySchedulerClient(CCThreadProxy* proxy)
{
m_proxy = proxy;
}
CCThreadProxy* m_proxy;
};
PassOwnPtr<CCProxy> CCThreadProxy::create(CCLayerTreeHost* layerTreeHost)
{
return adoptPtr(new CCThreadProxy(layerTreeHost));
......@@ -59,9 +87,6 @@ CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost)
, m_started(false)
, m_lastExecutedBeginFrameAndCommitSequenceNumber(-1)
, m_numBeginFrameAndCommitsIssuedOnCCThread(0)
, m_beginFrameAndCommitPendingOnCCThread(false)
, m_drawTaskPostedOnCCThread(false)
, m_redrawRequestedOnCCThread(false)
{
TRACE_EVENT("CCThreadProxy::CCThreadProxy", this, 0);
ASSERT(isMainThread());
......@@ -76,6 +101,7 @@ CCThreadProxy::~CCThreadProxy()
bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
{
TRACE_EVENT("CCThreadPRoxy::compositeAndReadback", this, 0);
ASSERT(isMainThread());
ASSERT(m_layerTreeHost);
......@@ -142,6 +168,7 @@ bool CCThreadProxy::isStarted() const
bool CCThreadProxy::initializeLayerRenderer()
{
TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0);
RefPtr<GraphicsContext3D> context = m_layerTreeHost->createLayerTreeHostContext3D();
if (!context)
return false;
......@@ -183,33 +210,35 @@ void CCThreadProxy::setNeedsCommit()
TRACE_EVENT("CCThreadProxy::setNeedsCommit", this, 0);
m_commitRequested = true;
s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::updateSchedulerStateOnCCThread, m_commitRequested, true));
s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnCCThread));
}
void CCThreadProxy::setNeedsCommitAndRedraw()
void CCThreadProxy::setNeedsCommitThenRedraw()
{
ASSERT(isMainThread());
if (m_commitRequested)
return;
m_commitRequested = true;
m_redrawAfterCommit = true;
setNeedsCommit();
}
TRACE_EVENT("CCThreadProxy::setNeedsCommitAndRedraw", this, 0);
s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::updateSchedulerStateOnCCThread, m_commitRequested, true));
void CCThreadProxy::setNeedsCommitOnCCThread()
{
ASSERT(isImplThread());
TRACE_EVENT("CCThreadProxy::setNeedsCommitOnCCThread", this, 0);
m_schedulerOnCCThread->requestCommit();
}
void CCThreadProxy::setNeedsRedraw()
{
ASSERT(isMainThread());
if (m_commitRequested) // Implies that a commit is in flight.
return;
// Unlike setNeedsCommit that tracks whether a commit message has been sent,
// setNeedsRedraw always sends a message to the compositor thread. This is
// because the compositor thread can draw without telling the main
// thread. This should not be much of a problem because calls to
// setNeedsRedraw messages are uncommon (only triggered by WM_PAINT/etc),
// compared to setNeedsCommitAndRedraw messages.
TRACE_EVENT("CCThreadProxy::setNeedsRedraw", this, 0);
s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::updateSchedulerStateOnCCThread, false, true));
s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsRedrawOnCCThread));
}
void CCThreadProxy::setNeedsRedrawOnCCThread()
{
ASSERT(isImplThread());
TRACE_EVENT("CCThreadProxy::setNeedsRedrawOnCCThread", this, 0);
m_schedulerOnCCThread->requestRedraw();
}
void CCThreadProxy::start()
......@@ -244,11 +273,10 @@ void CCThreadProxy::finishAllRenderingOnCCThread(CCCompletionEvent* completion)
{
TRACE_EVENT("CCThreadProxy::finishAllRenderingOnCCThread", this, 0);
ASSERT(isImplThread());
ASSERT(!m_beginFrameAndCommitPendingOnCCThread);
if (m_redrawRequestedOnCCThread) {
if (m_schedulerOnCCThread->redrawPending()) {
drawLayersOnCCThread();
m_layerTreeHostImpl->present();
m_redrawRequestedOnCCThread = false;
m_schedulerOnCCThread->didDraw();
}
m_layerTreeHostImpl->finishAllRendering();
completion->signal();
......@@ -266,7 +294,6 @@ PassOwnPtr<CCMainThread::Task> CCThreadProxy::createBeginFrameAndCommitTaskOnCCT
TRACE_EVENT("CCThreadProxy::createBeginFrameAndCommitTaskOnCCThread", this, 0);
ASSERT(isImplThread());
double frameBeginTime = currentTime();
m_beginFrameAndCommitPendingOnCCThread = true;
// NOTE, it is possible to receieve a request for a
// beginFrameAndCommitOnCCThread from finishAllRendering while a
......@@ -328,6 +355,10 @@ void CCThreadProxy::beginFrameAndCommit(int sequenceNumber, double frameBeginTim
m_layerTreeHost->commitComplete();
if (m_redrawAfterCommit)
setNeedsRedraw();
m_redrawAfterCommit = false;
ASSERT(m_lastExecutedBeginFrameAndCommitSequenceNumber == sequenceNumber);
}
......@@ -335,8 +366,7 @@ void CCThreadProxy::commitOnCCThread(CCCompletionEvent* completion)
{
TRACE_EVENT("CCThreadProxy::beginFrameAndCommitOnCCThread", this, 0);
ASSERT(isImplThread());
ASSERT(m_beginFrameAndCommitPendingOnCCThread);
m_beginFrameAndCommitPendingOnCCThread = false;
ASSERT(m_schedulerOnCCThread->commitPending());
if (!m_layerTreeHostImpl) {
completion->signal();
return;
......@@ -347,19 +377,7 @@ void CCThreadProxy::commitOnCCThread(CCCompletionEvent* completion)
completion->signal();
if (m_redrawRequestedOnCCThread)
scheduleDrawTaskOnCCThread();
}
void CCThreadProxy::scheduleDrawTaskOnCCThread()
{
ASSERT(isImplThread());
if (m_drawTaskPostedOnCCThread)
return;
TRACE_EVENT("CCThreadProxy::scheduleDrawTaskOnCCThread", this, 0);
ASSERT(m_layerTreeHostImpl);
m_drawTaskPostedOnCCThread = true;
s_ccThread->postTask(createCCThreadTask(this, &CCThreadProxy::drawLayersAndPresentOnCCThread));
m_schedulerOnCCThread->didCommit();
}
void CCThreadProxy::drawLayersAndPresentOnCCThread()
......@@ -371,8 +389,7 @@ void CCThreadProxy::drawLayersAndPresentOnCCThread()
drawLayersOnCCThread();
m_layerTreeHostImpl->present();
m_redrawRequestedOnCCThread = false;
m_drawTaskPostedOnCCThread = false;
m_schedulerOnCCThread->didDraw();
}
void CCThreadProxy::drawLayersOnCCThread()
......@@ -385,30 +402,13 @@ void CCThreadProxy::drawLayersOnCCThread()
ASSERT(!m_layerTreeHostImpl->isContextLost());
}
void CCThreadProxy::updateSchedulerStateOnCCThread(bool commitRequested, bool redrawRequested)
{
TRACE_EVENT("CCThreadProxy::updateSchedulerStateOnCCThread", this, 0);
ASSERT(isImplThread());
ASSERT(m_layerTreeHostImpl);
// FIXME: use CCScheduler to decide when to manage the conversion of this
// commit request into an actual createBeginFrameAndCommitTaskOnCCThread call.
m_redrawRequestedOnCCThread |= redrawRequested;
if (commitRequested && !m_beginFrameAndCommitPendingOnCCThread) {
CCMainThread::postTask(createBeginFrameAndCommitTaskOnCCThread());
return;
}
// If no commit is pending, but a redraw is requested, then post a redraw right away
if (m_redrawRequestedOnCCThread)
scheduleDrawTaskOnCCThread();
}
void CCThreadProxy::initializeImplOnCCThread(CCCompletionEvent* completion)
{
TRACE_EVENT("CCThreadProxy::initializeImplOnCCThread", this, 0);
ASSERT(isImplThread());
m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl();
m_schedulerClientOnCCThread = CCThreadProxySchedulerClient::create(this);
m_schedulerOnCCThread = CCScheduler::create(m_schedulerClientOnCCThread.get());
completion->signal();
}
......
......@@ -34,9 +34,12 @@
namespace WebCore {
class CCLayerTreeHost;
class CCScheduler;
class CCThread;
class CCThreadProxySchedulerClient;
class CCThreadProxy : public CCProxy {
friend class CCThreadProxySchedulerClient;
public:
static void setThread(CCThread*);
......@@ -53,7 +56,7 @@ public:
virtual const LayerRendererCapabilities& layerRendererCapabilities() const;
virtual void loseCompositorContext(int numTimes);
virtual void setNeedsCommit();
virtual void setNeedsCommitAndRedraw();
virtual void setNeedsCommitThenRedraw();
virtual void setNeedsRedraw();
virtual void start();
virtual void stop();
......@@ -75,12 +78,13 @@ private:
void initializeImplOnCCThread(CCCompletionEvent*);
void initializeLayerRendererOnCCThread(GraphicsContext3D*, CCCompletionEvent*, bool* initializeSucceeded, LayerRendererCapabilities*);
void setNeedsCommitOnCCThread();
void updateSchedulerStateOnCCThread(bool commitRequested, bool redrawRequested);
void setNeedsRedrawOnCCThread();
void setNeedsCommitThenRedrawOnCCThread();
void layerTreeHostClosedOnCCThread(CCCompletionEvent*);
void scheduleDrawTaskOnCCThread();
// Accessed on main thread only.
bool m_commitRequested;
bool m_redrawAfterCommit;
CCLayerTreeHost* m_layerTreeHost;
LayerRendererCapabilities m_layerRendererCapabilitiesMainThreadCopy;