#ifndef CC_SCHEDULER_SCHEDULER_H_
#define CC_SCHEDULER_SCHEDULER_H_
+#include <deque>
#include <string>
#include "base/basictypes.h"
#include "base/time/time.h"
#include "cc/base/cc_export.h"
#include "cc/output/begin_frame_args.h"
-#include "cc/scheduler/draw_swap_readback_result.h"
+#include "cc/scheduler/delay_based_time_source.h"
+#include "cc/scheduler/draw_result.h"
#include "cc/scheduler/scheduler_settings.h"
#include "cc/scheduler/scheduler_state_machine.h"
-#include "cc/trees/layer_tree_host.h"
-namespace cc {
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
+class SingleThreadTaskRunner;
+}
-class Thread;
+namespace cc {
class SchedulerClient {
public:
- virtual void SetNeedsBeginImplFrame(bool enable) = 0;
+ virtual void SetNeedsBeginFrame(bool enable) = 0;
+ virtual void WillBeginImplFrame(const BeginFrameArgs& args) = 0;
virtual void ScheduledActionSendBeginMainFrame() = 0;
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapIfPossible() = 0;
- virtual DrawSwapReadbackResult ScheduledActionDrawAndSwapForced() = 0;
- virtual DrawSwapReadbackResult ScheduledActionDrawAndReadback() = 0;
+ virtual DrawResult ScheduledActionDrawAndSwapIfPossible() = 0;
+ virtual DrawResult ScheduledActionDrawAndSwapForced() = 0;
+ virtual void ScheduledActionAnimate() = 0;
virtual void ScheduledActionCommit() = 0;
virtual void ScheduledActionUpdateVisibleTiles() = 0;
- virtual void ScheduledActionActivatePendingTree() = 0;
+ virtual void ScheduledActionActivateSyncTree() = 0;
virtual void ScheduledActionBeginOutputSurfaceCreation() = 0;
- virtual void ScheduledActionAcquireLayerTexturesForMainThread() = 0;
virtual void ScheduledActionManageTiles() = 0;
virtual void DidAnticipatedDrawTimeChange(base::TimeTicks time) = 0;
virtual base::TimeDelta DrawDurationEstimate() = 0;
virtual base::TimeDelta BeginMainFrameToCommitDurationEstimate() = 0;
virtual base::TimeDelta CommitToActivateDurationEstimate() = 0;
- virtual void PostBeginImplFrameDeadline(const base::Closure& closure,
- base::TimeTicks deadline) = 0;
virtual void DidBeginImplFrameDeadline() = 0;
protected:
static scoped_ptr<Scheduler> Create(
SchedulerClient* client,
const SchedulerSettings& scheduler_settings,
- int layer_tree_host_id) {
- return make_scoped_ptr(
- new Scheduler(client, scheduler_settings, layer_tree_host_id));
+ int layer_tree_host_id,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
+ return make_scoped_ptr(new Scheduler(
+ client, scheduler_settings, layer_tree_host_id, task_runner));
}
virtual ~Scheduler();
+ const SchedulerSettings& settings() const { return settings_; }
+
+ void CommitVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval);
+ void SetEstimatedParentDrawTime(base::TimeDelta draw_time);
+
void SetCanStart();
void SetVisible(bool visible);
void SetNeedsCommit();
- // Like SetNeedsCommit(), but ensures a commit will definitely happen even if
- // we are not visible. Will eventually result in a forced draw internally.
- void SetNeedsForcedCommitForReadback();
-
void SetNeedsRedraw();
- void SetNeedsManageTiles();
+ void SetNeedsAnimate();
- void SetMainThreadNeedsLayerTextures();
+ void SetNeedsManageTiles();
+ void SetMaxSwapsPending(int max);
+ void DidSwapBuffers();
void SetSwapUsedIncompleteTile(bool used_incomplete_tile);
+ void DidSwapBuffersComplete();
- void SetSmoothnessTakesPriority(bool smoothness_takes_priority);
+ void SetImplLatencyTakesPriority(bool impl_latency_takes_priority);
- void FinishCommit();
+ void NotifyReadyToCommit();
void BeginMainFrameAborted(bool did_handle);
void DidManageTiles();
void DidLoseOutputSurface();
void DidCreateAndInitializeOutputSurface();
- bool HasInitializedOutputSurface() const {
- return state_machine_.HasInitializedOutputSurface();
+
+ // Tests do not want to shut down until all possible BeginMainFrames have
+ // occured to prevent flakiness.
+ bool MainFrameForTestingWillHappen() const {
+ return state_machine_.CommitPending() ||
+ state_machine_.CouldSendBeginMainFrame();
}
bool CommitPending() const { return state_machine_.CommitPending(); }
bool MainThreadIsInHighLatencyMode() const {
return state_machine_.MainThreadIsInHighLatencyMode();
}
+ bool BeginImplFrameDeadlinePending() const {
+ return !begin_impl_frame_deadline_task_.IsCancelled();
+ }
bool WillDrawIfNeeded() const;
- base::TimeTicks AnticipatedDrawTime();
+ base::TimeTicks AnticipatedDrawTime() const;
+
+ void NotifyBeginMainFrameStarted();
base::TimeTicks LastBeginImplFrameTime();
- void BeginImplFrame(const BeginFrameArgs& args);
- void OnBeginImplFrameDeadline();
- void PollForAnticipatedDrawTriggers();
+ void BeginFrame(const BeginFrameArgs& args);
- scoped_ptr<base::Value> StateAsValue() {
- return state_machine_.AsValue().Pass();
- }
+ scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+ void AsValueInto(base::debug::TracedValue* state) const;
- bool IsInsideAction(SchedulerStateMachine::Action action) {
- return inside_action_ == action;
+ void SetContinuousPainting(bool continuous_painting) {
+ state_machine_.SetContinuousPainting(continuous_painting);
}
- private:
+ protected:
+ class CC_EXPORT SyntheticBeginFrameSource : public TimeSourceClient {
+ public:
+ SyntheticBeginFrameSource(Scheduler* scheduler,
+ scoped_refptr<DelayBasedTimeSource> time_source);
+ virtual ~SyntheticBeginFrameSource();
+
+ // Updates the phase and frequency of the timer.
+ void CommitVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval);
+
+ // Activates future BeginFrames and, if activating, pushes the most
+ // recently missed BeginFrame to the back of a retroactive queue.
+ void SetNeedsBeginFrame(bool needs_begin_frame,
+ std::deque<BeginFrameArgs>* begin_retro_frame_args);
+
+ bool IsActive() const;
+
+ // TimeSourceClient implementation of OnTimerTick triggers a BeginFrame.
+ virtual void OnTimerTick() OVERRIDE;
+
+ void AsValueInto(base::debug::TracedValue* dict) const;
+
+ private:
+ BeginFrameArgs CreateSyntheticBeginFrameArgs(base::TimeTicks frame_time);
+
+ Scheduler* scheduler_;
+ scoped_refptr<DelayBasedTimeSource> time_source_;
+ };
+
Scheduler(SchedulerClient* client,
const SchedulerSettings& scheduler_settings,
- int layer_tree_host_id);
+ int layer_tree_host_id,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
- void PostBeginImplFrameDeadline(base::TimeTicks deadline);
- void SetupNextBeginImplFrameIfNeeded();
- void ActivatePendingTree();
- void DrawAndSwapIfPossible();
- void DrawAndSwapForced();
- void DrawAndReadback();
- void ProcessScheduledActions();
-
- bool CanCommitAndActivateBeforeDeadline() const;
- void AdvanceCommitStateIfPossible();
+ virtual base::TimeTicks Now() const;
const SchedulerSettings settings_;
SchedulerClient* client_;
int layer_tree_host_id_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ base::TimeDelta vsync_interval_;
+ base::TimeDelta estimated_parent_draw_time_;
+
+ bool last_set_needs_begin_frame_;
+ bool begin_unthrottled_frame_posted_;
+ bool begin_retro_frame_posted_;
+ std::deque<BeginFrameArgs> begin_retro_frame_args_;
+ BeginFrameArgs begin_impl_frame_args_;
- bool last_set_needs_begin_impl_frame_;
- BeginFrameArgs last_begin_impl_frame_args_;
- base::CancelableClosure begin_impl_frame_deadline_closure_;
- base::CancelableClosure poll_for_draw_triggers_closure_;
- base::RepeatingTimer<Scheduler> advance_commit_state_timer_;
+ scoped_ptr<SyntheticBeginFrameSource> synthetic_begin_frame_source_;
+
+ base::Closure begin_retro_frame_closure_;
+ base::Closure begin_unthrottled_frame_closure_;
+
+ base::Closure begin_impl_frame_deadline_closure_;
+ base::Closure poll_for_draw_triggers_closure_;
+ base::Closure advance_commit_state_closure_;
+ base::CancelableClosure begin_impl_frame_deadline_task_;
+ base::CancelableClosure poll_for_draw_triggers_task_;
+ base::CancelableClosure advance_commit_state_task_;
SchedulerStateMachine state_machine_;
bool inside_process_scheduled_actions_;
SchedulerStateMachine::Action inside_action_;
+ base::TimeDelta VSyncInterval() { return vsync_interval_; }
+
+ private:
+ base::TimeTicks AdjustedBeginImplFrameDeadline(
+ const BeginFrameArgs& args,
+ base::TimeDelta draw_duration_estimate) const;
+ void ScheduleBeginImplFrameDeadline(base::TimeTicks deadline);
+ void SetupNextBeginFrameIfNeeded();
+ void PostBeginRetroFrameIfNeeded();
+ void SetupNextBeginFrameWhenVSyncThrottlingEnabled(bool needs_begin_frame);
+ void SetupNextBeginFrameWhenVSyncThrottlingDisabled(bool needs_begin_frame);
+ void SetupPollingMechanisms(bool needs_begin_frame);
+ void DrawAndSwapIfPossible();
+ void ProcessScheduledActions();
+ bool CanCommitAndActivateBeforeDeadline() const;
+ void AdvanceCommitStateIfPossible();
+ bool IsBeginMainFrameSentOrStarted() const;
+ void SetupSyntheticBeginFrames();
+ void BeginRetroFrame();
+ void BeginUnthrottledFrame();
+ void BeginImplFrame(const BeginFrameArgs& args);
+ void OnBeginImplFrameDeadline();
+ void PollForAnticipatedDrawTriggers();
+ void PollToAdvanceCommitState();
+
+ base::TimeDelta EstimatedParentDrawTime() {
+ return estimated_parent_draw_time_;
+ }
+
+ bool IsInsideAction(SchedulerStateMachine::Action action) {
+ return inside_action_ == action;
+ }
+
base::WeakPtrFactory<Scheduler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Scheduler);