// 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