| 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" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 last_set_needs_begin_impl_frame_(false), | 26 last_set_needs_begin_impl_frame_(false), |
| 27 state_machine_(scheduler_settings), | 27 state_machine_(scheduler_settings), |
| 28 inside_process_scheduled_actions_(false), | 28 inside_process_scheduled_actions_(false), |
| 29 inside_action_(SchedulerStateMachine::ACTION_NONE), | 29 inside_action_(SchedulerStateMachine::ACTION_NONE), |
| 30 weak_factory_(this) { | 30 weak_factory_(this) { |
| 31 DCHECK(client_); | 31 DCHECK(client_); |
| 32 DCHECK(!state_machine_.BeginImplFrameNeeded()); | 32 DCHECK(!state_machine_.BeginImplFrameNeeded()); |
| 33 if (settings_.main_frame_before_activation_enabled) { | 33 if (settings_.main_frame_before_activation_enabled) { |
| 34 DCHECK(settings_.main_frame_before_draw_enabled); | 34 DCHECK(settings_.main_frame_before_draw_enabled); |
| 35 } | 35 } |
| 36 |
| 37 begin_impl_frame_deadline_closure_ = base::Bind( |
| 38 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
| 39 poll_for_draw_triggers_closure_ = base::Bind( |
| 40 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
| 41 advance_commit_state_closure_ = base::Bind( |
| 42 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
| 36 } | 43 } |
| 37 | 44 |
| 38 Scheduler::~Scheduler() {} | 45 Scheduler::~Scheduler() {} |
| 39 | 46 |
| 40 void Scheduler::SetCanStart() { | 47 void Scheduler::SetCanStart() { |
| 41 state_machine_.SetCanStart(); | 48 state_machine_.SetCanStart(); |
| 42 ProcessScheduledActions(); | 49 ProcessScheduledActions(); |
| 43 } | 50 } |
| 44 | 51 |
| 45 void Scheduler::SetVisible(bool visible) { | 52 void Scheduler::SetVisible(bool visible) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 void Scheduler::DidLoseOutputSurface() { | 123 void Scheduler::DidLoseOutputSurface() { |
| 117 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 124 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
| 118 state_machine_.DidLoseOutputSurface(); | 125 state_machine_.DidLoseOutputSurface(); |
| 119 last_set_needs_begin_impl_frame_ = false; | 126 last_set_needs_begin_impl_frame_ = false; |
| 120 ProcessScheduledActions(); | 127 ProcessScheduledActions(); |
| 121 } | 128 } |
| 122 | 129 |
| 123 void Scheduler::DidCreateAndInitializeOutputSurface() { | 130 void Scheduler::DidCreateAndInitializeOutputSurface() { |
| 124 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 131 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
| 125 DCHECK(!last_set_needs_begin_impl_frame_); | 132 DCHECK(!last_set_needs_begin_impl_frame_); |
| 126 DCHECK(begin_impl_frame_deadline_closure_.IsCancelled()); | 133 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| 127 state_machine_.DidCreateAndInitializeOutputSurface(); | 134 state_machine_.DidCreateAndInitializeOutputSurface(); |
| 128 ProcessScheduledActions(); | 135 ProcessScheduledActions(); |
| 129 } | 136 } |
| 130 | 137 |
| 131 void Scheduler::NotifyBeginMainFrameStarted() { | 138 void Scheduler::NotifyBeginMainFrameStarted() { |
| 132 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); | 139 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); |
| 133 state_machine_.NotifyBeginMainFrameStarted(); | 140 state_machine_.NotifyBeginMainFrameStarted(); |
| 134 } | 141 } |
| 135 | 142 |
| 136 base::TimeTicks Scheduler::AnticipatedDrawTime() const { | 143 base::TimeTicks Scheduler::AnticipatedDrawTime() const { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 last_set_needs_begin_impl_frame_ = needs_begin_impl_frame; | 177 last_set_needs_begin_impl_frame_ = needs_begin_impl_frame; |
| 171 } | 178 } |
| 172 | 179 |
| 173 bool needs_advance_commit_state_timer = false; | 180 bool needs_advance_commit_state_timer = false; |
| 174 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but | 181 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but |
| 175 // aren't expecting any more BeginImplFrames. This should only be needed by | 182 // aren't expecting any more BeginImplFrames. This should only be needed by |
| 176 // the synchronous compositor when BeginImplFrameNeeded is false. | 183 // the synchronous compositor when BeginImplFrameNeeded is false. |
| 177 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { | 184 if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) { |
| 178 DCHECK(!state_machine_.SupportsProactiveBeginImplFrame()); | 185 DCHECK(!state_machine_.SupportsProactiveBeginImplFrame()); |
| 179 DCHECK(!needs_begin_impl_frame); | 186 DCHECK(!needs_begin_impl_frame); |
| 180 if (poll_for_draw_triggers_closure_.IsCancelled()) { | 187 if (poll_for_draw_triggers_task_.IsCancelled()) { |
| 181 poll_for_draw_triggers_closure_.Reset( | 188 poll_for_draw_triggers_task_.Reset(poll_for_draw_triggers_closure_); |
| 182 base::Bind(&Scheduler::PollForAnticipatedDrawTriggers, | |
| 183 weak_factory_.GetWeakPtr())); | |
| 184 base::TimeDelta delay = last_begin_impl_frame_args_.IsValid() | 189 base::TimeDelta delay = last_begin_impl_frame_args_.IsValid() |
| 185 ? last_begin_impl_frame_args_.interval | 190 ? last_begin_impl_frame_args_.interval |
| 186 : BeginFrameArgs::DefaultInterval(); | 191 : BeginFrameArgs::DefaultInterval(); |
| 187 impl_task_runner_->PostDelayedTask( | 192 impl_task_runner_->PostDelayedTask( |
| 188 FROM_HERE, poll_for_draw_triggers_closure_.callback(), delay); | 193 FROM_HERE, poll_for_draw_triggers_task_.callback(), delay); |
| 189 } | 194 } |
| 190 } else { | 195 } else { |
| 191 poll_for_draw_triggers_closure_.Cancel(); | 196 poll_for_draw_triggers_task_.Cancel(); |
| 192 | 197 |
| 193 // At this point we'd prefer to advance through the commit flow by | 198 // At this point we'd prefer to advance through the commit flow by |
| 194 // drawing a frame, however it's possible that the frame rate controller | 199 // drawing a frame, however it's possible that the frame rate controller |
| 195 // will not give us a BeginImplFrame until the commit completes. See | 200 // will not give us a BeginImplFrame until the commit completes. See |
| 196 // crbug.com/317430 for an example of a swap ack being held on commit. Thus | 201 // crbug.com/317430 for an example of a swap ack being held on commit. Thus |
| 197 // we set a repeating timer to poll on ProcessScheduledActions until we | 202 // we set a repeating timer to poll on ProcessScheduledActions until we |
| 198 // successfully reach BeginImplFrame. Synchronous compositor does not use | 203 // successfully reach BeginImplFrame. Synchronous compositor does not use |
| 199 // frame rate controller or have the circular wait in the bug. | 204 // frame rate controller or have the circular wait in the bug. |
| 200 if (IsBeginMainFrameSentOrStarted() && | 205 if (IsBeginMainFrameSentOrStarted() && |
| 201 !settings_.using_synchronous_renderer_compositor) { | 206 !settings_.using_synchronous_renderer_compositor) { |
| 202 needs_advance_commit_state_timer = true; | 207 needs_advance_commit_state_timer = true; |
| 203 } | 208 } |
| 204 } | 209 } |
| 205 | 210 |
| 206 if (needs_advance_commit_state_timer) { | 211 if (needs_advance_commit_state_timer) { |
| 207 if (advance_commit_state_closure_.IsCancelled() && | 212 if (advance_commit_state_task_.IsCancelled() && |
| 208 last_begin_impl_frame_args_.IsValid()) { | 213 last_begin_impl_frame_args_.IsValid()) { |
| 209 // Since we'd rather get a BeginImplFrame by the normal mechanism, we | 214 // Since we'd rather get a BeginImplFrame by the normal mechanism, we |
| 210 // set the interval to twice the interval from the previous frame. | 215 // set the interval to twice the interval from the previous frame. |
| 211 advance_commit_state_closure_.Reset(base::Bind( | 216 advance_commit_state_task_.Reset(advance_commit_state_closure_); |
| 212 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr())); | |
| 213 impl_task_runner_->PostDelayedTask( | 217 impl_task_runner_->PostDelayedTask( |
| 214 FROM_HERE, | 218 FROM_HERE, |
| 215 advance_commit_state_closure_.callback(), | 219 advance_commit_state_task_.callback(), |
| 216 last_begin_impl_frame_args_.interval * 2); | 220 last_begin_impl_frame_args_.interval * 2); |
| 217 } | 221 } |
| 218 } else { | 222 } else { |
| 219 advance_commit_state_closure_.Cancel(); | 223 advance_commit_state_task_.Cancel(); |
| 220 } | 224 } |
| 221 } | 225 } |
| 222 | 226 |
| 223 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 227 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { |
| 224 TRACE_EVENT0("cc", "Scheduler::BeginImplFrame"); | 228 TRACE_EVENT0("cc", "Scheduler::BeginImplFrame"); |
| 225 DCHECK(state_machine_.begin_impl_frame_state() == | 229 DCHECK(state_machine_.begin_impl_frame_state() == |
| 226 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 230 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 227 DCHECK(state_machine_.HasInitializedOutputSurface()); | 231 DCHECK(state_machine_.HasInitializedOutputSurface()); |
| 228 | 232 |
| 229 advance_commit_state_closure_.Cancel(); | 233 advance_commit_state_task_.Cancel(); |
| 230 | 234 |
| 231 last_begin_impl_frame_args_ = args; | 235 last_begin_impl_frame_args_ = args; |
| 232 last_begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); | 236 last_begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); |
| 233 | 237 |
| 234 if (!state_machine_.smoothness_takes_priority() && | 238 if (!state_machine_.smoothness_takes_priority() && |
| 235 state_machine_.MainThreadIsInHighLatencyMode() && | 239 state_machine_.MainThreadIsInHighLatencyMode() && |
| 236 CanCommitAndActivateBeforeDeadline()) { | 240 CanCommitAndActivateBeforeDeadline()) { |
| 237 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 241 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
| 238 } | 242 } |
| 239 | 243 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { | 281 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { |
| 278 if (settings_.using_synchronous_renderer_compositor) { | 282 if (settings_.using_synchronous_renderer_compositor) { |
| 279 // The synchronous renderer compositor has to make its GL calls | 283 // The synchronous renderer compositor has to make its GL calls |
| 280 // within this call. | 284 // within this call. |
| 281 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | 285 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks |
| 282 // so the sychronous renderer compositor can take advantage of splitting | 286 // so the sychronous renderer compositor can take advantage of splitting |
| 283 // up the BeginImplFrame and deadline as well. | 287 // up the BeginImplFrame and deadline as well. |
| 284 OnBeginImplFrameDeadline(); | 288 OnBeginImplFrameDeadline(); |
| 285 return; | 289 return; |
| 286 } | 290 } |
| 287 begin_impl_frame_deadline_closure_.Cancel(); | 291 begin_impl_frame_deadline_task_.Cancel(); |
| 288 begin_impl_frame_deadline_closure_.Reset( | 292 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
| 289 base::Bind(&Scheduler::OnBeginImplFrameDeadline, | |
| 290 weak_factory_.GetWeakPtr())); | |
| 291 | 293 |
| 292 base::TimeDelta delta = deadline - gfx::FrameTime::Now(); | 294 base::TimeDelta delta = deadline - gfx::FrameTime::Now(); |
| 293 if (delta <= base::TimeDelta()) | 295 if (delta <= base::TimeDelta()) |
| 294 delta = base::TimeDelta(); | 296 delta = base::TimeDelta(); |
| 295 impl_task_runner_->PostDelayedTask( | 297 impl_task_runner_->PostDelayedTask( |
| 296 FROM_HERE, begin_impl_frame_deadline_closure_.callback(), delta); | 298 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); |
| 297 } | 299 } |
| 298 | 300 |
| 299 void Scheduler::OnBeginImplFrameDeadline() { | 301 void Scheduler::OnBeginImplFrameDeadline() { |
| 300 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); | 302 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); |
| 301 begin_impl_frame_deadline_closure_.Cancel(); | 303 begin_impl_frame_deadline_task_.Cancel(); |
| 302 | 304 |
| 303 // We split the deadline actions up into two phases so the state machine | 305 // We split the deadline actions up into two phases so the state machine |
| 304 // has a chance to trigger actions that should occur durring and after | 306 // has a chance to trigger actions that should occur durring and after |
| 305 // the deadline separately. For example: | 307 // the deadline separately. For example: |
| 306 // * Sending the BeginMainFrame will not occur after the deadline in | 308 // * Sending the BeginMainFrame will not occur after the deadline in |
| 307 // order to wait for more user-input before starting the next commit. | 309 // order to wait for more user-input before starting the next commit. |
| 308 // * Creating a new OuputSurface will not occur during the deadline in | 310 // * Creating a new OuputSurface will not occur during the deadline in |
| 309 // order to allow the state machine to "settle" first. | 311 // order to allow the state machine to "settle" first. |
| 310 state_machine_.OnBeginImplFrameDeadline(); | 312 state_machine_.OnBeginImplFrameDeadline(); |
| 311 ProcessScheduledActions(); | 313 ProcessScheduledActions(); |
| 312 state_machine_.OnBeginImplFrameIdle(); | 314 state_machine_.OnBeginImplFrameIdle(); |
| 313 ProcessScheduledActions(); | 315 ProcessScheduledActions(); |
| 314 | 316 |
| 315 client_->DidBeginImplFrameDeadline(); | 317 client_->DidBeginImplFrameDeadline(); |
| 316 } | 318 } |
| 317 | 319 |
| 318 void Scheduler::PollForAnticipatedDrawTriggers() { | 320 void Scheduler::PollForAnticipatedDrawTriggers() { |
| 319 TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers"); | 321 TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers"); |
| 320 poll_for_draw_triggers_closure_.Cancel(); | 322 poll_for_draw_triggers_task_.Cancel(); |
| 321 state_machine_.DidEnterPollForAnticipatedDrawTriggers(); | 323 state_machine_.DidEnterPollForAnticipatedDrawTriggers(); |
| 322 ProcessScheduledActions(); | 324 ProcessScheduledActions(); |
| 323 state_machine_.DidLeavePollForAnticipatedDrawTriggers(); | 325 state_machine_.DidLeavePollForAnticipatedDrawTriggers(); |
| 324 } | 326 } |
| 325 | 327 |
| 326 void Scheduler::PollToAdvanceCommitState() { | 328 void Scheduler::PollToAdvanceCommitState() { |
| 327 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); | 329 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); |
| 328 advance_commit_state_closure_.Cancel(); | 330 advance_commit_state_task_.Cancel(); |
| 329 ProcessScheduledActions(); | 331 ProcessScheduledActions(); |
| 330 } | 332 } |
| 331 | 333 |
| 332 bool Scheduler::IsBeginMainFrameSent() const { | 334 bool Scheduler::IsBeginMainFrameSent() const { |
| 333 return state_machine_.commit_state() == | 335 return state_machine_.commit_state() == |
| 334 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT; | 336 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT; |
| 335 } | 337 } |
| 336 | 338 |
| 337 void Scheduler::DrawAndSwapIfPossible() { | 339 void Scheduler::DrawAndSwapIfPossible() { |
| 338 DrawSwapReadbackResult result = | 340 DrawSwapReadbackResult result = |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 scoped_ptr<base::Value> Scheduler::StateAsValue() const { | 426 scoped_ptr<base::Value> Scheduler::StateAsValue() const { |
| 425 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); | 427 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); |
| 426 state->Set("state_machine", state_machine_.AsValue().release()); | 428 state->Set("state_machine", state_machine_.AsValue().release()); |
| 427 | 429 |
| 428 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue); | 430 scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue); |
| 429 scheduler_state->SetDouble( | 431 scheduler_state->SetDouble( |
| 430 "time_until_anticipated_draw_time_ms", | 432 "time_until_anticipated_draw_time_ms", |
| 431 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF()); | 433 (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF()); |
| 432 scheduler_state->SetBoolean("last_set_needs_begin_impl_frame_", | 434 scheduler_state->SetBoolean("last_set_needs_begin_impl_frame_", |
| 433 last_set_needs_begin_impl_frame_); | 435 last_set_needs_begin_impl_frame_); |
| 434 scheduler_state->SetBoolean( | 436 scheduler_state->SetBoolean("begin_impl_frame_deadline_task_", |
| 435 "begin_impl_frame_deadline_closure_", | 437 !begin_impl_frame_deadline_task_.IsCancelled()); |
| 436 !begin_impl_frame_deadline_closure_.IsCancelled()); | 438 scheduler_state->SetBoolean("poll_for_draw_triggers_task_", |
| 437 scheduler_state->SetBoolean("poll_for_draw_triggers_closure_", | 439 !poll_for_draw_triggers_task_.IsCancelled()); |
| 438 !poll_for_draw_triggers_closure_.IsCancelled()); | 440 scheduler_state->SetBoolean("advance_commit_state_task_", |
| 439 scheduler_state->SetBoolean("advance_commit_state_closure_", | 441 !advance_commit_state_task_.IsCancelled()); |
| 440 !advance_commit_state_closure_.IsCancelled()); | |
| 441 state->Set("scheduler_state", scheduler_state.release()); | 442 state->Set("scheduler_state", scheduler_state.release()); |
| 442 | 443 |
| 443 scoped_ptr<base::DictionaryValue> client_state(new base::DictionaryValue); | 444 scoped_ptr<base::DictionaryValue> client_state(new base::DictionaryValue); |
| 444 client_state->SetDouble("draw_duration_estimate_ms", | 445 client_state->SetDouble("draw_duration_estimate_ms", |
| 445 client_->DrawDurationEstimate().InMillisecondsF()); | 446 client_->DrawDurationEstimate().InMillisecondsF()); |
| 446 client_state->SetDouble( | 447 client_state->SetDouble( |
| 447 "begin_main_frame_to_commit_duration_estimate_ms", | 448 "begin_main_frame_to_commit_duration_estimate_ms", |
| 448 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); | 449 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); |
| 449 client_state->SetDouble( | 450 client_state->SetDouble( |
| 450 "commit_to_activate_duration_estimate_ms", | 451 "commit_to_activate_duration_estimate_ms", |
| (...skipping 22 matching lines...) Expand all Loading... |
| 473 } | 474 } |
| 474 | 475 |
| 475 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 476 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
| 476 return (state_machine_.commit_state() == | 477 return (state_machine_.commit_state() == |
| 477 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 478 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
| 478 state_machine_.commit_state() == | 479 state_machine_.commit_state() == |
| 479 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 480 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
| 480 } | 481 } |
| 481 | 482 |
| 482 } // namespace cc | 483 } // namespace cc |
| OLD | NEW |