// 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. #ifndef CC_SCHEDULER_SCHEDULER_H_ #define CC_SCHEDULER_SCHEDULER_H_ #include #include #include "base/basictypes.h" #include "base/cancelable_callback.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "cc/base/cc_export.h" #include "cc/output/begin_frame_args.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" namespace base { class SingleThreadTaskRunner; } namespace cc { class SchedulerClient { public: virtual void SetNeedsBeginFrame(bool enable) = 0; virtual void WillBeginImplFrame(const BeginFrameArgs& args) = 0; virtual void ScheduledActionSendBeginMainFrame() = 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 ScheduledActionBeginOutputSurfaceCreation() = 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 DidBeginImplFrameDeadline() = 0; protected: virtual ~SchedulerClient() {} }; class CC_EXPORT Scheduler { public: static scoped_ptr Create( SchedulerClient* client, const SchedulerSettings& scheduler_settings, int layer_tree_host_id, const scoped_refptr& impl_task_runner) { return make_scoped_ptr(new Scheduler( client, scheduler_settings, layer_tree_host_id, impl_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 SetCanDraw(bool can_draw); void NotifyReadyToActivate(); void SetNeedsCommit(); void SetNeedsRedraw(); void SetNeedsAnimate(); void SetNeedsManageTiles(); void SetMaxSwapsPending(int max); void DidSwapBuffers(); void SetSwapUsedIncompleteTile(bool used_incomplete_tile); void DidSwapBuffersComplete(); void SetSmoothnessTakesPriority(bool smoothness_takes_priority); void NotifyReadyToCommit(); void BeginMainFrameAborted(bool did_handle); void DidManageTiles(); void DidLoseOutputSurface(); void DidCreateAndInitializeOutputSurface(); bool CommitPending() const { return state_machine_.CommitPending(); } bool RedrawPending() const { return state_machine_.RedrawPending(); } bool ManageTilesPending() const { return state_machine_.ManageTilesPending(); } bool MainThreadIsInHighLatencyMode() const { return state_machine_.MainThreadIsInHighLatencyMode(); } bool BeginImplFrameDeadlinePending() const { return !begin_impl_frame_deadline_task_.IsCancelled(); } bool WillDrawIfNeeded() const; base::TimeTicks AnticipatedDrawTime() const; void NotifyBeginMainFrameStarted(); base::TimeTicks LastBeginImplFrameTime(); base::TimeDelta VSyncInterval() { return vsync_interval_; } base::TimeDelta EstimatedParentDrawTime() { return estimated_parent_draw_time_; } void BeginFrame(const BeginFrameArgs& args); void PostBeginRetroFrame(); void BeginRetroFrame(); void BeginUnthrottledFrame(); void BeginImplFrame(const BeginFrameArgs& args); void OnBeginImplFrameDeadline(); void PollForAnticipatedDrawTriggers(); void PollToAdvanceCommitState(); scoped_ptr AsValue() const; bool IsInsideAction(SchedulerStateMachine::Action action) { return inside_action_ == action; } bool IsBeginMainFrameSent() const; void SetContinuousPainting(bool continuous_painting) { state_machine_.SetContinuousPainting(continuous_painting); } protected: class CC_EXPORT SyntheticBeginFrameSource : public TimeSourceClient { public: SyntheticBeginFrameSource(Scheduler* scheduler, base::SingleThreadTaskRunner* task_runner); 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* begin_retro_frame_args); bool IsActive() const; // TimeSourceClient implementation of OnTimerTick triggers a BeginFrame. virtual void OnTimerTick() OVERRIDE; scoped_ptr AsValue() const; private: BeginFrameArgs CreateSyntheticBeginFrameArgs(base::TimeTicks frame_time); Scheduler* scheduler_; scoped_refptr time_source_; }; Scheduler( SchedulerClient* client, const SchedulerSettings& scheduler_settings, int layer_tree_host_id, const scoped_refptr& impl_task_runner); const SchedulerSettings settings_; SchedulerClient* client_; int layer_tree_host_id_; scoped_refptr impl_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 begin_retro_frame_args_; BeginFrameArgs begin_impl_frame_args_; scoped_ptr 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_; 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(); base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(Scheduler); }; } // namespace cc #endif // CC_SCHEDULER_SCHEDULER_H_