// Copyright 2011 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 "config.h"
#include "CCScheduler.h"
#include "TraceEvent.h"
#include
namespace cc {
CCScheduler::CCScheduler(CCSchedulerClient* client, scoped_ptr frameRateController)
: m_client(client)
, m_frameRateController(frameRateController.Pass())
, m_insideProcessScheduledActions(false)
{
ASSERT(m_client);
m_frameRateController->setClient(this);
ASSERT(!m_stateMachine.vsyncCallbackNeeded());
}
CCScheduler::~CCScheduler()
{
m_frameRateController->setActive(false);
}
void CCScheduler::setCanBeginFrame(bool can)
{
m_stateMachine.setCanBeginFrame(can);
processScheduledActions();
}
void CCScheduler::setVisible(bool visible)
{
m_stateMachine.setVisible(visible);
processScheduledActions();
}
void CCScheduler::setCanDraw(bool canDraw)
{
m_stateMachine.setCanDraw(canDraw);
processScheduledActions();
}
void CCScheduler::setNeedsCommit()
{
m_stateMachine.setNeedsCommit();
processScheduledActions();
}
void CCScheduler::setNeedsForcedCommit()
{
m_stateMachine.setNeedsForcedCommit();
processScheduledActions();
}
void CCScheduler::setNeedsRedraw()
{
m_stateMachine.setNeedsRedraw();
processScheduledActions();
}
void CCScheduler::setNeedsForcedRedraw()
{
m_stateMachine.setNeedsForcedRedraw();
processScheduledActions();
}
void CCScheduler::setMainThreadNeedsLayerTextures()
{
m_stateMachine.setMainThreadNeedsLayerTextures();
processScheduledActions();
}
void CCScheduler::beginFrameComplete()
{
TRACE_EVENT0("cc", "CCScheduler::beginFrameComplete");
m_stateMachine.beginFrameComplete();
processScheduledActions();
}
void CCScheduler::beginFrameAborted()
{
TRACE_EVENT0("cc", "CCScheduler::beginFrameAborted");
m_stateMachine.beginFrameAborted();
processScheduledActions();
}
void CCScheduler::setMaxFramesPending(int maxFramesPending)
{
m_frameRateController->setMaxFramesPending(maxFramesPending);
}
void CCScheduler::setSwapBuffersCompleteSupported(bool supported)
{
m_frameRateController->setSwapBuffersCompleteSupported(supported);
}
void CCScheduler::didSwapBuffersComplete()
{
TRACE_EVENT0("cc", "CCScheduler::didSwapBuffersComplete");
m_frameRateController->didFinishFrame();
}
void CCScheduler::didLoseContext()
{
TRACE_EVENT0("cc", "CCScheduler::didLoseContext");
m_frameRateController->didAbortAllPendingFrames();
m_stateMachine.didLoseContext();
processScheduledActions();
}
void CCScheduler::didRecreateContext()
{
TRACE_EVENT0("cc", "CCScheduler::didRecreateContext");
m_stateMachine.didRecreateContext();
processScheduledActions();
}
void CCScheduler::setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval)
{
m_frameRateController->setTimebaseAndInterval(timebase, interval);
}
base::TimeTicks CCScheduler::anticipatedDrawTime()
{
return m_frameRateController->nextTickTime();
}
void CCScheduler::vsyncTick(bool throttled)
{
TRACE_EVENT1("cc", "CCScheduler::vsyncTick", "throttled", throttled);
if (!throttled)
m_stateMachine.didEnterVSync();
processScheduledActions();
if (!throttled)
m_stateMachine.didLeaveVSync();
}
void CCScheduler::processScheduledActions()
{
// We do not allow processScheduledActions to be recursive.
// The top-level call will iteratively execute the next action for us anyway.
if (m_insideProcessScheduledActions)
return;
AutoReset markInside(&m_insideProcessScheduledActions, true);
CCSchedulerStateMachine::Action action = m_stateMachine.nextAction();
while (action != CCSchedulerStateMachine::ACTION_NONE) {
m_stateMachine.updateState(action);
TRACE_EVENT1("cc", "CCScheduler::processScheduledActions()", "action", action);
switch (action) {
case CCSchedulerStateMachine::ACTION_NONE:
break;
case CCSchedulerStateMachine::ACTION_BEGIN_FRAME:
m_client->scheduledActionBeginFrame();
break;
case CCSchedulerStateMachine::ACTION_COMMIT:
m_client->scheduledActionCommit();
break;
case CCSchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: {
CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapIfPossible();
m_stateMachine.didDrawIfPossibleCompleted(result.didDraw);
if (result.didSwap)
m_frameRateController->didBeginFrame();
break;
}
case CCSchedulerStateMachine::ACTION_DRAW_FORCED: {
CCScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapForced();
if (result.didSwap)
m_frameRateController->didBeginFrame();
break;
} case CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION:
m_client->scheduledActionBeginContextRecreation();
break;
case CCSchedulerStateMachine::ACTION_ACQUIRE_LAYER_TEXTURES_FOR_MAIN_THREAD:
m_client->scheduledActionAcquireLayerTexturesForMainThread();
break;
}
action = m_stateMachine.nextAction();
}
// Activate or deactivate the frame rate controller.
m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
m_client->didAnticipatedDrawTimeChange(m_frameRateController->nextTickTime());
}
} // namespace cc