blob: 78fcca892e3c7c60150ff9d367ce9bbe6296942a [file] [log] [blame]
// 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"
namespace cc {
CCScheduler::CCScheduler(CCSchedulerClient* client, PassOwnPtr<CCFrameRateController> frameRateController)
: m_client(client)
, m_frameRateController(frameRateController)
, m_updateResourcesCompletePending(false)
{
ASSERT(m_client);
m_frameRateController->setClient(this);
m_frameRateController->setActive(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);
// Defer processScheduleActions so we don't recurse and commit/draw
// multiple frames. We can call processScheduledActions directly
// once it is no longer re-entrant.
m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
}
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(bool hasResourceUpdates)
{
TRACE_EVENT0("cc", "CCScheduler::beginFrameComplete");
m_stateMachine.beginFrameComplete(hasResourceUpdates);
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);
}
void CCScheduler::vsyncTick()
{
TRACE_EVENT0("cc", "CCScheduler::vsyncTick");
m_stateMachine.didEnterVSync();
processScheduledActions();
m_stateMachine.didLeaveVSync();
// Allow resource updates until next vsync tick.
if (m_updateResourcesCompletePending)
m_client->scheduledActionUpdateMoreResources(m_frameRateController->nextTickTimeIfActivated());
}
void CCScheduler::updateResourcesComplete()
{
TRACE_EVENT0("cc", "CCScheduler::updateResourcesComplete");
m_stateMachine.updateResourcesComplete();
m_updateResourcesCompletePending = false;
processScheduledActions();
}
void CCScheduler::processScheduledActions()
{
// Early out so we don't spam TRACE_EVENTS with useless processScheduledActions.
if (m_stateMachine.nextAction() == CCSchedulerStateMachine::ACTION_NONE) {
m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
return;
}
// This function can re-enter itself. For example, draw may call
// setNeedsCommit. Proceeed with caution.
CCSchedulerStateMachine::Action action;
do {
action = m_stateMachine.nextAction();
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_BEGIN_UPDATE_RESOURCES:
ASSERT(!m_updateResourcesCompletePending);
m_client->scheduledActionUpdateMoreResources(m_frameRateController->nextTickTimeIfActivated());
m_updateResourcesCompletePending = true;
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;
}
} while (action != CCSchedulerStateMachine::ACTION_NONE);
// Activate or deactivate the frame rate controller.
m_frameRateController->setActive(m_stateMachine.vsyncCallbackNeeded());
}
}