blob: 2a8f41acd59e0974c50f9b3abc5cf746d380972e [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 "cc/scheduler.h"
#include "base/auto_reset.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
namespace cc {
Scheduler::Scheduler(SchedulerClient* client, scoped_ptr<FrameRateController> frameRateController)
: m_client(client)
, m_frameRateController(frameRateController.Pass())
, m_insideProcessScheduledActions(false)
{
DCHECK(m_client);
m_frameRateController->setClient(this);
DCHECK(!m_stateMachine.vsyncCallbackNeeded());
}
Scheduler::~Scheduler()
{
m_frameRateController->setActive(false);
}
void Scheduler::setCanBeginFrame(bool can)
{
m_stateMachine.setCanBeginFrame(can);
processScheduledActions();
}
void Scheduler::setVisible(bool visible)
{
m_stateMachine.setVisible(visible);
processScheduledActions();
}
void Scheduler::setCanDraw(bool canDraw)
{
m_stateMachine.setCanDraw(canDraw);
processScheduledActions();
}
void Scheduler::setNeedsCommit()
{
m_stateMachine.setNeedsCommit();
processScheduledActions();
}
void Scheduler::setNeedsForcedCommit()
{
m_stateMachine.setNeedsForcedCommit();
processScheduledActions();
}
void Scheduler::setNeedsRedraw()
{
m_stateMachine.setNeedsRedraw();
processScheduledActions();
}
void Scheduler::setNeedsForcedRedraw()
{
m_stateMachine.setNeedsForcedRedraw();
processScheduledActions();
}
void Scheduler::setMainThreadNeedsLayerTextures()
{
m_stateMachine.setMainThreadNeedsLayerTextures();
processScheduledActions();
}
void Scheduler::beginFrameComplete()
{
TRACE_EVENT0("cc", "Scheduler::beginFrameComplete");
m_stateMachine.beginFrameComplete();
processScheduledActions();
}
void Scheduler::beginFrameAborted()
{
TRACE_EVENT0("cc", "Scheduler::beginFrameAborted");
m_stateMachine.beginFrameAborted();
processScheduledActions();
}
void Scheduler::setMaxFramesPending(int maxFramesPending)
{
m_frameRateController->setMaxFramesPending(maxFramesPending);
}
void Scheduler::setSwapBuffersCompleteSupported(bool supported)
{
m_frameRateController->setSwapBuffersCompleteSupported(supported);
}
void Scheduler::didSwapBuffersComplete()
{
TRACE_EVENT0("cc", "Scheduler::didSwapBuffersComplete");
m_frameRateController->didFinishFrame();
}
void Scheduler::didLoseContext()
{
TRACE_EVENT0("cc", "Scheduler::didLoseContext");
m_frameRateController->didAbortAllPendingFrames();
m_stateMachine.didLoseContext();
processScheduledActions();
}
void Scheduler::didRecreateContext()
{
TRACE_EVENT0("cc", "Scheduler::didRecreateContext");
m_stateMachine.didRecreateContext();
processScheduledActions();
}
void Scheduler::setTimebaseAndInterval(base::TimeTicks timebase, base::TimeDelta interval)
{
m_frameRateController->setTimebaseAndInterval(timebase, interval);
}
base::TimeTicks Scheduler::anticipatedDrawTime()
{
return m_frameRateController->nextTickTime();
}
void Scheduler::vsyncTick(bool throttled)
{
TRACE_EVENT1("cc", "Scheduler::vsyncTick", "throttled", throttled);
if (!throttled)
m_stateMachine.didEnterVSync();
processScheduledActions();
if (!throttled)
m_stateMachine.didLeaveVSync();
}
void Scheduler::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<bool> markInside(&m_insideProcessScheduledActions, true);
SchedulerStateMachine::Action action = m_stateMachine.nextAction();
while (action != SchedulerStateMachine::ACTION_NONE) {
m_stateMachine.updateState(action);
TRACE_EVENT1("cc", "Scheduler::processScheduledActions()", "action", action);
switch (action) {
case SchedulerStateMachine::ACTION_NONE:
break;
case SchedulerStateMachine::ACTION_BEGIN_FRAME:
m_client->scheduledActionBeginFrame();
break;
case SchedulerStateMachine::ACTION_COMMIT:
m_client->scheduledActionCommit();
break;
case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: {
ScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapIfPossible();
m_stateMachine.didDrawIfPossibleCompleted(result.didDraw);
if (result.didSwap)
m_frameRateController->didBeginFrame();
break;
}
case SchedulerStateMachine::ACTION_DRAW_FORCED: {
ScheduledActionDrawAndSwapResult result = m_client->scheduledActionDrawAndSwapForced();
if (result.didSwap)
m_frameRateController->didBeginFrame();
break;
} case SchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION:
m_client->scheduledActionBeginContextRecreation();
break;
case SchedulerStateMachine::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