| OLD | NEW |
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/scheduler/scheduler.h" | 5 #include "cc/scheduler/scheduler.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include "base/auto_reset.h" | 8 #include "base/auto_reset.h" |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "cc/debug/devtools_instrumentation.h" | 11 #include "cc/debug/devtools_instrumentation.h" |
| 12 #include "cc/debug/traced_value.h" | 12 #include "cc/debug/traced_value.h" |
| 13 #include "cc/scheduler/delay_based_time_source.h" | 13 #include "cc/scheduler/delay_based_time_source.h" |
| 14 #include "cc/scheduler/frame_source.h" |
| 14 #include "ui/gfx/frame_time.h" | 15 #include "ui/gfx/frame_time.h" |
| 15 | 16 |
| 16 namespace cc { | 17 namespace cc { |
| 17 | 18 |
| 18 class SyntheticBeginFrameSource : public TimeSourceClient { | |
| 19 public: | |
| 20 SyntheticBeginFrameSource(Scheduler* scheduler, | |
| 21 base::SingleThreadTaskRunner* task_runner) | |
| 22 : scheduler_(scheduler) { | |
| 23 if (gfx::FrameTime::TimestampsAreHighRes()) { | |
| 24 time_source_ = DelayBasedTimeSourceHighRes::Create( | |
| 25 scheduler_->VSyncInterval(), task_runner); | |
| 26 } else { | |
| 27 time_source_ = DelayBasedTimeSource::Create(scheduler_->VSyncInterval(), | |
| 28 task_runner); | |
| 29 } | |
| 30 time_source_->SetClient(this); | |
| 31 } | |
| 32 | |
| 33 virtual ~SyntheticBeginFrameSource() {} | |
| 34 | |
| 35 // Updates the phase and frequency of the timer. | |
| 36 void CommitVSyncParameters(base::TimeTicks timebase, | |
| 37 base::TimeDelta interval) { | |
| 38 time_source_->SetTimebaseAndInterval(timebase, interval); | |
| 39 } | |
| 40 | |
| 41 // Activates future BeginFrames and, if activating, pushes the most | |
| 42 // recently missed BeginFrame to the back of a retroactive queue. | |
| 43 void SetNeedsBeginFrame(bool needs_begin_frame, | |
| 44 std::deque<BeginFrameArgs>* begin_retro_frame_args) { | |
| 45 base::TimeTicks missed_tick_time = | |
| 46 time_source_->SetActive(needs_begin_frame); | |
| 47 if (!missed_tick_time.is_null()) { | |
| 48 begin_retro_frame_args->push_back( | |
| 49 CreateSyntheticBeginFrameArgs(missed_tick_time)); | |
| 50 } | |
| 51 } | |
| 52 | |
| 53 // TimeSourceClient implementation of OnTimerTick triggers a BeginFrame. | |
| 54 virtual void OnTimerTick() OVERRIDE { | |
| 55 BeginFrameArgs begin_frame_args( | |
| 56 CreateSyntheticBeginFrameArgs(time_source_->LastTickTime())); | |
| 57 scheduler_->BeginFrame(begin_frame_args); | |
| 58 } | |
| 59 | |
| 60 private: | |
| 61 BeginFrameArgs CreateSyntheticBeginFrameArgs(base::TimeTicks frame_time) { | |
| 62 base::TimeTicks deadline = | |
| 63 time_source_->NextTickTime() - scheduler_->EstimatedParentDrawTime(); | |
| 64 return BeginFrameArgs::Create( | |
| 65 frame_time, deadline, scheduler_->VSyncInterval()); | |
| 66 } | |
| 67 | |
| 68 Scheduler* scheduler_; | |
| 69 scoped_refptr<TimeSource> time_source_; | |
| 70 }; | |
| 71 | |
| 72 Scheduler::Scheduler( | 19 Scheduler::Scheduler( |
| 73 SchedulerClient* client, | 20 SchedulerClient* client, |
| 74 const SchedulerSettings& scheduler_settings, | 21 const SchedulerSettings& scheduler_settings, |
| 75 int layer_tree_host_id, | 22 int layer_tree_host_id, |
| 23 BeginFrameSource* external_frame_source, |
| 76 const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner) | 24 const scoped_refptr<base::SingleThreadTaskRunner>& impl_task_runner) |
| 77 : settings_(scheduler_settings), | 25 : settings_(scheduler_settings), |
| 78 client_(client), | 26 client_(client), |
| 79 layer_tree_host_id_(layer_tree_host_id), | 27 layer_tree_host_id_(layer_tree_host_id), |
| 80 impl_task_runner_(impl_task_runner), | 28 impl_task_runner_(impl_task_runner), |
| 81 vsync_interval_(BeginFrameArgs::DefaultInterval()), | |
| 82 last_set_needs_begin_frame_(false), | |
| 83 begin_unthrottled_frame_posted_(false), | |
| 84 begin_retro_frame_posted_(false), | 29 begin_retro_frame_posted_(false), |
| 85 state_machine_(scheduler_settings), | 30 state_machine_(scheduler_settings), |
| 86 inside_process_scheduled_actions_(false), | 31 inside_process_scheduled_actions_(false), |
| 87 inside_action_(SchedulerStateMachine::ACTION_NONE), | 32 inside_action_(SchedulerStateMachine::ACTION_NONE), |
| 88 weak_factory_(this) { | 33 weak_factory_(this) { |
| 89 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 34 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| 90 "Scheduler::Scheduler", | 35 "Scheduler::Scheduler", |
| 91 "settings", | 36 "settings", |
| 92 ToTrace(settings_)); | 37 ToTrace(settings_)); |
| 93 DCHECK(client_); | 38 DCHECK(client_); |
| 94 DCHECK(!state_machine_.BeginFrameNeeded()); | 39 DCHECK(!state_machine_.BeginFrameNeeded()); |
| 95 if (settings_.main_frame_before_activation_enabled) { | 40 if (settings_.main_frame_before_activation_enabled) { |
| 96 DCHECK(settings_.main_frame_before_draw_enabled); | 41 DCHECK(settings_.main_frame_before_draw_enabled); |
| 97 } | 42 } |
| 98 | 43 |
| 99 begin_retro_frame_closure_ = | 44 begin_retro_frame_closure_ = |
| 100 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 45 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); |
| 101 begin_unthrottled_frame_closure_ = | |
| 102 base::Bind(&Scheduler::BeginUnthrottledFrame, weak_factory_.GetWeakPtr()); | |
| 103 begin_impl_frame_deadline_closure_ = base::Bind( | 46 begin_impl_frame_deadline_closure_ = base::Bind( |
| 104 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 47 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
| 105 poll_for_draw_triggers_closure_ = base::Bind( | 48 poll_for_draw_triggers_closure_ = base::Bind( |
| 106 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); | 49 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
| 107 advance_commit_state_closure_ = base::Bind( | 50 advance_commit_state_closure_ = base::Bind( |
| 108 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); | 51 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
| 109 | 52 |
| 110 if (!settings_.begin_frame_scheduling_enabled) { | 53 scoped_ptr<BeginFrameSource> primary_frame_source; |
| 111 SetupSyntheticBeginFrames(); | 54 |
| 55 if (!settings_.throttle_frame_production) { |
| 56 TRACE_EVENT0("cc", "Scheduler::Scheduler() BackToBackBeginFrameSource"); |
| 57 primary_frame_source = scoped_ptr<BeginFrameSource>( |
| 58 new BackToBackBeginFrameSource(this, impl_task_runner_)); |
| 59 } else if (settings_.begin_frame_scheduling_enabled) { |
| 60 TRACE_EVENT0("cc", "Scheduler::Scheduler() ProxyBeginFrameSource"); |
| 61 primary_frame_source = scoped_ptr<BeginFrameSource>( |
| 62 new ProxyBeginFrameSource(this, external_frame_source)); |
| 63 } else { |
| 64 TRACE_EVENT0("cc", "Scheduler::Scheduler() SyntheticBeginFrameSource"); |
| 65 primary_frame_source = |
| 66 scoped_ptr<BeginFrameSource>(new SyntheticBeginFrameSource( |
| 67 this, impl_task_runner_, BeginFrameArgs::DefaultInterval())); |
| 112 } | 68 } |
| 69 scoped_ptr<BeginFrameSource> background_frame_source( |
| 70 new SyntheticBeginFrameSource( |
| 71 this, impl_task_runner_, base::TimeDelta::FromSeconds(1))); |
| 72 |
| 73 frame_source_ = scoped_ptr<DualBeginFrameSource>(new DualBeginFrameSource( |
| 74 this, primary_frame_source.Pass(), background_frame_source.Pass())); |
| 113 } | 75 } |
| 114 | 76 |
| 115 Scheduler::~Scheduler() { | 77 Scheduler::~Scheduler() { |
| 116 if (synthetic_begin_frame_source_) { | 78 frame_source_->SetGenerateFrames(false); |
| 117 synthetic_begin_frame_source_->SetNeedsBeginFrame(false, | |
| 118 &begin_retro_frame_args_); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 void Scheduler::SetupSyntheticBeginFrames() { | |
| 123 DCHECK(!synthetic_begin_frame_source_); | |
| 124 synthetic_begin_frame_source_.reset( | |
| 125 new SyntheticBeginFrameSource(this, impl_task_runner_.get())); | |
| 126 } | 79 } |
| 127 | 80 |
| 128 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 81 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
| 129 base::TimeDelta interval) { | 82 base::TimeDelta interval) { |
| 130 // TODO(brianderson): We should not be receiving 0 intervals. | 83 frame_source_->SetTimeBaseAndInterval(timebase, interval); |
| 131 if (interval == base::TimeDelta()) | |
| 132 interval = BeginFrameArgs::DefaultInterval(); | |
| 133 vsync_interval_ = interval; | |
| 134 if (!settings_.begin_frame_scheduling_enabled) | |
| 135 synthetic_begin_frame_source_->CommitVSyncParameters(timebase, interval); | |
| 136 } | 84 } |
| 137 | 85 |
| 138 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { | 86 void Scheduler::SetEstimatedParentDrawTime(base::TimeDelta draw_time) { |
| 139 estimated_parent_draw_time_ = draw_time; | 87 estimated_parent_draw_time_ = draw_time; |
| 140 } | 88 } |
| 141 | 89 |
| 142 void Scheduler::SetCanStart() { | 90 void Scheduler::SetCanStart() { |
| 143 state_machine_.SetCanStart(); | 91 state_machine_.SetCanStart(); |
| 144 ProcessScheduledActions(); | 92 ProcessScheduledActions(); |
| 145 } | 93 } |
| 146 | 94 |
| 147 void Scheduler::SetVisible(bool visible) { | 95 void Scheduler::SetVisible(bool visible) { |
| 148 state_machine_.SetVisible(visible); | 96 state_machine_.SetVisible(visible); |
| 97 if (visible) { |
| 98 frame_source_->SwitchSource(frame_source_->SourceForeground()); |
| 99 } else { |
| 100 frame_source_->SwitchSource(frame_source_->SourceBackground()); |
| 101 } |
| 149 ProcessScheduledActions(); | 102 ProcessScheduledActions(); |
| 150 } | 103 } |
| 151 | 104 |
| 152 void Scheduler::SetCanDraw(bool can_draw) { | 105 void Scheduler::SetCanDraw(bool can_draw) { |
| 153 state_machine_.SetCanDraw(can_draw); | 106 state_machine_.SetCanDraw(can_draw); |
| 154 ProcessScheduledActions(); | 107 ProcessScheduledActions(); |
| 155 } | 108 } |
| 156 | 109 |
| 157 void Scheduler::NotifyReadyToActivate() { | 110 void Scheduler::NotifyReadyToActivate() { |
| 158 state_machine_.NotifyReadyToActivate(); | 111 state_machine_.NotifyReadyToActivate(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 ProcessScheduledActions(); | 174 ProcessScheduledActions(); |
| 222 } | 175 } |
| 223 | 176 |
| 224 void Scheduler::DidManageTiles() { | 177 void Scheduler::DidManageTiles() { |
| 225 state_machine_.DidManageTiles(); | 178 state_machine_.DidManageTiles(); |
| 226 } | 179 } |
| 227 | 180 |
| 228 void Scheduler::DidLoseOutputSurface() { | 181 void Scheduler::DidLoseOutputSurface() { |
| 229 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 182 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
| 230 state_machine_.DidLoseOutputSurface(); | 183 state_machine_.DidLoseOutputSurface(); |
| 231 last_set_needs_begin_frame_ = false; | 184 frame_source_->SetGenerateFrames(false); |
| 232 begin_retro_frame_args_.clear(); | 185 begin_retro_frame_args_.clear(); |
| 233 ProcessScheduledActions(); | 186 ProcessScheduledActions(); |
| 234 } | 187 } |
| 235 | 188 |
| 236 void Scheduler::DidCreateAndInitializeOutputSurface() { | 189 void Scheduler::DidCreateAndInitializeOutputSurface() { |
| 237 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 190 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
| 238 DCHECK(!last_set_needs_begin_frame_); | 191 DCHECK(!frame_source_->IsGeneratingFrames()); |
| 239 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | 192 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| 240 state_machine_.DidCreateAndInitializeOutputSurface(); | 193 state_machine_.DidCreateAndInitializeOutputSurface(); |
| 241 ProcessScheduledActions(); | 194 ProcessScheduledActions(); |
| 242 } | 195 } |
| 243 | 196 |
| 244 void Scheduler::NotifyBeginMainFrameStarted() { | 197 void Scheduler::NotifyBeginMainFrameStarted() { |
| 245 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); | 198 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); |
| 246 state_machine_.NotifyBeginMainFrameStarted(); | 199 state_machine_.NotifyBeginMainFrameStarted(); |
| 247 } | 200 } |
| 248 | 201 |
| 249 base::TimeTicks Scheduler::AnticipatedDrawTime() const { | 202 base::TimeTicks Scheduler::AnticipatedDrawTime() const { |
| 250 if (!last_set_needs_begin_frame_ || | 203 if (!frame_source_->IsGeneratingFrames() || |
| 251 begin_impl_frame_args_.interval <= base::TimeDelta()) | 204 begin_impl_frame_args_.interval <= base::TimeDelta()) |
| 252 return base::TimeTicks(); | 205 return base::TimeTicks(); |
| 253 | 206 |
| 254 base::TimeTicks now = gfx::FrameTime::Now(); | 207 base::TimeTicks now = gfx::FrameTime::Now(); |
| 255 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, | 208 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, |
| 256 begin_impl_frame_args_.deadline); | 209 begin_impl_frame_args_.deadline); |
| 257 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); | 210 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); |
| 258 return timebase + (begin_impl_frame_args_.interval * intervals); | 211 return timebase + (begin_impl_frame_args_.interval * intervals); |
| 259 } | 212 } |
| 260 | 213 |
| 261 base::TimeTicks Scheduler::LastBeginImplFrameTime() { | 214 base::TimeTicks Scheduler::LastBeginImplFrameTime() { |
| 262 return begin_impl_frame_args_.frame_time; | 215 return begin_impl_frame_args_.frame_time; |
| 263 } | 216 } |
| 264 | 217 |
| 265 void Scheduler::SetupNextBeginFrameIfNeeded() { | 218 void Scheduler::SetupNextBeginFrameIfNeeded() { |
| 266 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); | 219 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); |
| 267 | 220 |
| 268 if (settings_.throttle_frame_production) { | 221 bool at_end_of_deadline = |
| 269 SetupNextBeginFrameWhenVSyncThrottlingEnabled(needs_begin_frame); | 222 (state_machine_.begin_impl_frame_state() == |
| 270 } else { | 223 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) || |
| 271 SetupNextBeginFrameWhenVSyncThrottlingDisabled(needs_begin_frame); | 224 (state_machine_.begin_impl_frame_state() == |
| 225 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 226 |
| 227 bool should_call_set_needs_begin_frame = |
| 228 // Always request the BeginFrame immediately if it wasn't needed before. |
| 229 needs_begin_frame || |
| 230 // Only stop requesting BeginFrames after a deadline. |
| 231 (!needs_begin_frame && at_end_of_deadline); |
| 232 |
| 233 if (should_call_set_needs_begin_frame) { |
| 234 frame_source_->SetGenerateFrames(needs_begin_frame); |
| 272 } | 235 } |
| 236 |
| 237 // TODO(mithro): Use pending frames properly. |
| 238 if (at_end_of_deadline) |
| 239 frame_source_->PendingFrames(0); |
| 240 |
| 241 PostBeginRetroFrameIfNeeded(); |
| 273 SetupPollingMechanisms(needs_begin_frame); | 242 SetupPollingMechanisms(needs_begin_frame); |
| 274 } | 243 } |
| 275 | 244 |
| 276 // When we are throttling frame production, we request BeginFrames | |
| 277 // from the OutputSurface. | |
| 278 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingEnabled( | |
| 279 bool needs_begin_frame) { | |
| 280 bool at_end_of_deadline = | |
| 281 state_machine_.begin_impl_frame_state() == | |
| 282 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE; | |
| 283 | |
| 284 bool should_call_set_needs_begin_frame = | |
| 285 // Always request the BeginFrame immediately if it wasn't needed before. | |
| 286 (needs_begin_frame && !last_set_needs_begin_frame_) || | |
| 287 // Only stop requesting BeginFrames after a deadline. | |
| 288 (!needs_begin_frame && last_set_needs_begin_frame_ && at_end_of_deadline); | |
| 289 | |
| 290 if (should_call_set_needs_begin_frame) { | |
| 291 if (settings_.begin_frame_scheduling_enabled) { | |
| 292 client_->SetNeedsBeginFrame(needs_begin_frame); | |
| 293 } else { | |
| 294 synthetic_begin_frame_source_->SetNeedsBeginFrame( | |
| 295 needs_begin_frame, &begin_retro_frame_args_); | |
| 296 } | |
| 297 last_set_needs_begin_frame_ = needs_begin_frame; | |
| 298 } | |
| 299 | |
| 300 PostBeginRetroFrameIfNeeded(); | |
| 301 } | |
| 302 | |
| 303 // When we aren't throttling frame production, we initiate a BeginFrame | |
| 304 // as soon as one is needed. | |
| 305 void Scheduler::SetupNextBeginFrameWhenVSyncThrottlingDisabled( | |
| 306 bool needs_begin_frame) { | |
| 307 last_set_needs_begin_frame_ = needs_begin_frame; | |
| 308 | |
| 309 if (!needs_begin_frame || begin_unthrottled_frame_posted_) | |
| 310 return; | |
| 311 | |
| 312 if (state_machine_.begin_impl_frame_state() != | |
| 313 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE && | |
| 314 state_machine_.begin_impl_frame_state() != | |
| 315 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE) { | |
| 316 return; | |
| 317 } | |
| 318 | |
| 319 begin_unthrottled_frame_posted_ = true; | |
| 320 impl_task_runner_->PostTask(FROM_HERE, begin_unthrottled_frame_closure_); | |
| 321 } | |
| 322 | |
| 323 // BeginUnthrottledFrame is used when we aren't throttling frame production. | |
| 324 // This will usually be because VSync is disabled. | |
| 325 void Scheduler::BeginUnthrottledFrame() { | |
| 326 DCHECK(!settings_.throttle_frame_production); | |
| 327 DCHECK(begin_retro_frame_args_.empty()); | |
| 328 | |
| 329 base::TimeTicks now = gfx::FrameTime::Now(); | |
| 330 base::TimeTicks deadline = now + vsync_interval_; | |
| 331 | |
| 332 BeginFrameArgs begin_frame_args = | |
| 333 BeginFrameArgs::Create(now, deadline, vsync_interval_); | |
| 334 BeginImplFrame(begin_frame_args); | |
| 335 | |
| 336 begin_unthrottled_frame_posted_ = false; | |
| 337 } | |
| 338 | |
| 339 // We may need to poll when we can't rely on BeginFrame to advance certain | 245 // We may need to poll when we can't rely on BeginFrame to advance certain |
| 340 // state or to avoid deadlock. | 246 // state or to avoid deadlock. |
| 341 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { | 247 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { |
| 342 bool needs_advance_commit_state_timer = false; | 248 bool needs_advance_commit_state_timer = false; |
| 343 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but | 249 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but |
| 344 // aren't expecting any more BeginFrames. This should only be needed by | 250 // aren't expecting any more BeginFrames. This should only be needed by |
| 345 // the synchronous compositor when BeginFrameNeeded is false. | 251 // the synchronous compositor when BeginFrameNeeded is false. |
| 346 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { | 252 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { |
| 347 DCHECK(!state_machine_.SupportsProactiveBeginFrame()); | 253 DCHECK(!state_machine_.SupportsProactiveBeginFrame()); |
| 348 DCHECK(!needs_begin_frame); | 254 DCHECK(!needs_begin_frame); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 advance_commit_state_task_.Cancel(); | 290 advance_commit_state_task_.Cancel(); |
| 385 } | 291 } |
| 386 } | 292 } |
| 387 | 293 |
| 388 // BeginFrame is the mechanism that tells us that now is a good time to start | 294 // BeginFrame is the mechanism that tells us that now is a good time to start |
| 389 // making a frame. Usually this means that user input for the frame is complete. | 295 // making a frame. Usually this means that user input for the frame is complete. |
| 390 // If the scheduler is busy, we queue the BeginFrame to be handled later as | 296 // If the scheduler is busy, we queue the BeginFrame to be handled later as |
| 391 // a BeginRetroFrame. | 297 // a BeginRetroFrame. |
| 392 void Scheduler::BeginFrame(const BeginFrameArgs& args) { | 298 void Scheduler::BeginFrame(const BeginFrameArgs& args) { |
| 393 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", ToTrace(args)); | 299 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", ToTrace(args)); |
| 394 DCHECK(settings_.throttle_frame_production); | 300 |
| 301 BeginFrameArgs adjusted_args(args); |
| 302 adjusted_args.deadline -= EstimatedParentDrawTime(); |
| 395 | 303 |
| 396 bool should_defer_begin_frame; | 304 bool should_defer_begin_frame; |
| 397 if (settings_.using_synchronous_renderer_compositor) { | 305 if (settings_.using_synchronous_renderer_compositor) { |
| 398 should_defer_begin_frame = false; | 306 should_defer_begin_frame = false; |
| 399 } else { | 307 } else { |
| 400 should_defer_begin_frame = | 308 should_defer_begin_frame = |
| 401 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || | 309 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || |
| 402 !last_set_needs_begin_frame_ || | 310 !frame_source_->IsGeneratingFrames() || |
| 403 (state_machine_.begin_impl_frame_state() != | 311 (state_machine_.begin_impl_frame_state() != |
| 404 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 312 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 405 } | 313 } |
| 406 | 314 |
| 407 if (should_defer_begin_frame) { | 315 if (should_defer_begin_frame) { |
| 408 begin_retro_frame_args_.push_back(args); | 316 begin_retro_frame_args_.push_back(adjusted_args); |
| 409 TRACE_EVENT_INSTANT0( | 317 TRACE_EVENT_INSTANT1("cc", |
| 410 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); | 318 "Scheduler::BeginFrame deferred", |
| 319 TRACE_EVENT_SCOPE_THREAD, |
| 320 "args", |
| 321 ToTrace(adjusted_args)); |
| 411 return; | 322 return; |
| 412 } | 323 } |
| 413 | 324 |
| 414 BeginImplFrame(args); | 325 BeginImplFrame(adjusted_args); |
| 415 } | 326 } |
| 416 | 327 |
| 417 // BeginRetroFrame is called for BeginFrames that we've deferred because | 328 // BeginRetroFrame is called for BeginFrames that we've deferred because |
| 418 // the scheduler was in the middle of processing a previous BeginFrame. | 329 // the scheduler was in the middle of processing a previous BeginFrame. |
| 419 void Scheduler::BeginRetroFrame() { | 330 void Scheduler::BeginRetroFrame() { |
| 420 TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame"); | 331 TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame"); |
| 421 DCHECK(!settings_.using_synchronous_renderer_compositor); | 332 DCHECK(!settings_.using_synchronous_renderer_compositor); |
| 422 DCHECK(begin_retro_frame_posted_); | 333 DCHECK(begin_retro_frame_posted_); |
| 423 begin_retro_frame_posted_ = false; | 334 begin_retro_frame_posted_ = false; |
| 424 | 335 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 435 // draining the queue if we don't catch up. If we consistently can't catch | 346 // draining the queue if we don't catch up. If we consistently can't catch |
| 436 // up, our fallback should be to lower our frame rate. | 347 // up, our fallback should be to lower our frame rate. |
| 437 base::TimeTicks now = gfx::FrameTime::Now(); | 348 base::TimeTicks now = gfx::FrameTime::Now(); |
| 438 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | 349 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); |
| 439 while (!begin_retro_frame_args_.empty() && | 350 while (!begin_retro_frame_args_.empty() && |
| 440 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), | 351 now > AdjustedBeginImplFrameDeadline(begin_retro_frame_args_.front(), |
| 441 draw_duration_estimate)) { | 352 draw_duration_estimate)) { |
| 442 TRACE_EVENT1("cc", | 353 TRACE_EVENT1("cc", |
| 443 "Scheduler::BeginRetroFrame discarding", | 354 "Scheduler::BeginRetroFrame discarding", |
| 444 "frame_time", | 355 "frame_time", |
| 445 begin_retro_frame_args_.front().frame_time); | 356 ToTrace(begin_retro_frame_args_.front())); |
| 446 begin_retro_frame_args_.pop_front(); | 357 begin_retro_frame_args_.pop_front(); |
| 447 } | 358 } |
| 448 | 359 |
| 449 if (begin_retro_frame_args_.empty()) { | 360 if (begin_retro_frame_args_.empty()) { |
| 450 DCHECK(settings_.throttle_frame_production); | |
| 451 TRACE_EVENT_INSTANT0("cc", | 361 TRACE_EVENT_INSTANT0("cc", |
| 452 "Scheduler::BeginRetroFrames all expired", | 362 "Scheduler::BeginRetroFrames all expired", |
| 453 TRACE_EVENT_SCOPE_THREAD); | 363 TRACE_EVENT_SCOPE_THREAD); |
| 454 } else { | 364 } else { |
| 455 BeginImplFrame(begin_retro_frame_args_.front()); | 365 BeginImplFrame(begin_retro_frame_args_.front()); |
| 456 begin_retro_frame_args_.pop_front(); | 366 begin_retro_frame_args_.pop_front(); |
| 457 } | 367 } |
| 458 } | 368 } |
| 459 | 369 |
| 460 // There could be a race between the posted BeginRetroFrame and a new | 370 // There could be a race between the posted BeginRetroFrame and a new |
| 461 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame | 371 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame |
| 462 // will check if there is a pending BeginRetroFrame to ensure we handle | 372 // will check if there is a pending BeginRetroFrame to ensure we handle |
| 463 // BeginFrames in FIFO order. | 373 // BeginFrames in FIFO order. |
| 464 void Scheduler::PostBeginRetroFrameIfNeeded() { | 374 void Scheduler::PostBeginRetroFrameIfNeeded() { |
| 465 if (!last_set_needs_begin_frame_) | 375 if (!frame_source_->IsGeneratingFrames()) |
| 466 return; | 376 return; |
| 467 | 377 |
| 468 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) | 378 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) |
| 469 return; | 379 return; |
| 470 | 380 |
| 471 // begin_retro_frame_args_ should always be empty for the | 381 // begin_retro_frame_args_ should always be empty for the |
| 472 // synchronous compositor. | 382 // synchronous compositor. |
| 473 DCHECK(!settings_.using_synchronous_renderer_compositor); | 383 DCHECK(!settings_.using_synchronous_renderer_compositor); |
| 474 | 384 |
| 475 if (state_machine_.begin_impl_frame_state() != | 385 if (state_machine_.begin_impl_frame_state() != |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 } | 574 } |
| 665 } | 575 } |
| 666 | 576 |
| 667 bool Scheduler::WillDrawIfNeeded() const { | 577 bool Scheduler::WillDrawIfNeeded() const { |
| 668 return !state_machine_.PendingDrawsShouldBeAborted(); | 578 return !state_machine_.PendingDrawsShouldBeAborted(); |
| 669 } | 579 } |
| 670 | 580 |
| 671 scoped_ptr<base::Value> Scheduler::AsValue() const { | 581 scoped_ptr<base::Value> Scheduler::AsValue() const { |
| 672 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); | 582 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); |
| 673 state->Set("state_machine", state_machine_.AsValue().release()); | 583 state->Set("state_machine", state_machine_.AsValue().release()); |
| 584 state->Set("frame_source", |
| 585 frame_source_->BeginFrameSourceAsValue().release()); |
| 674 | 586 |
| 675 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue); | 587 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue); |
| 676 scheduler_state->SetDouble( | 588 scheduler_state->SetDouble( |
| 677 "time_until_anticipated_draw_time_ms", | 589 "time_until_anticipated_draw_time_ms", |
| 678 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF()); | 590 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF()); |
| 679 scheduler_state->SetDouble("vsync_interval_ms", | |
| 680 vsync_interval_.InMillisecondsF()); | |
| 681 scheduler_state->SetDouble("estimated_parent_draw_time_ms", | 591 scheduler_state->SetDouble("estimated_parent_draw_time_ms", |
| 682 estimated_parent_draw_time_.InMillisecondsF()); | 592 estimated_parent_draw_time_.InMillisecondsF()); |
| 683 scheduler_state->SetBoolean("last_set_needs_begin_frame_", | 593 scheduler_state->SetBoolean("last_set_needs_begin_frame_", |
| 684 last_set_needs_begin_frame_); | 594 frame_source_->IsGeneratingFrames()); |
| 685 scheduler_state->SetBoolean("begin_unthrottled_frame_posted_", | |
| 686 begin_unthrottled_frame_posted_); | |
| 687 scheduler_state->SetBoolean("begin_retro_frame_posted_", | 595 scheduler_state->SetBoolean("begin_retro_frame_posted_", |
| 688 begin_retro_frame_posted_); | 596 begin_retro_frame_posted_); |
| 689 scheduler_state->SetInteger("begin_retro_frame_args_", | 597 scheduler_state->SetInteger("begin_retro_frame_args_", |
| 690 begin_retro_frame_args_.size()); | 598 begin_retro_frame_args_.size()); |
| 691 scheduler_state->SetBoolean("begin_impl_frame_deadline_task_", | 599 scheduler_state->SetBoolean("begin_impl_frame_deadline_task_", |
| 692 !begin_impl_frame_deadline_task_.IsCancelled()); | 600 !begin_impl_frame_deadline_task_.IsCancelled()); |
| 693 scheduler_state->SetBoolean("poll_for_draw_triggers_task_", | 601 scheduler_state->SetBoolean("poll_for_draw_triggers_task_", |
| 694 !poll_for_draw_triggers_task_.IsCancelled()); | 602 !poll_for_draw_triggers_task_.IsCancelled()); |
| 695 scheduler_state->SetBoolean("advance_commit_state_task_", | 603 scheduler_state->SetBoolean("advance_commit_state_task_", |
| 696 !advance_commit_state_task_.IsCancelled()); | 604 !advance_commit_state_task_.IsCancelled()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 } | 640 } |
| 733 | 641 |
| 734 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 642 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
| 735 return (state_machine_.commit_state() == | 643 return (state_machine_.commit_state() == |
| 736 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 644 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
| 737 state_machine_.commit_state() == | 645 state_machine_.commit_state() == |
| 738 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 646 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
| 739 } | 647 } |
| 740 | 648 |
| 741 } // namespace cc | 649 } // namespace cc |
| OLD | NEW |