Chromium Code Reviews| 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 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 57 SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE), | 57 SchedulerStateMachine::BEGIN_IMPL_FRAME_DEADLINE_MODE_NONE), |
| 58 begin_impl_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), | 58 begin_impl_frame_tracker_(BEGINFRAMETRACKER_FROM_HERE), |
| 59 state_machine_(settings), | 59 state_machine_(settings), |
| 60 inside_process_scheduled_actions_(false), | 60 inside_process_scheduled_actions_(false), |
| 61 inside_action_(SchedulerStateMachine::ACTION_NONE), | 61 inside_action_(SchedulerStateMachine::ACTION_NONE), |
| 62 weak_factory_(this) { | 62 weak_factory_(this) { |
| 63 TRACE_EVENT1("cc", "Scheduler::Scheduler", "settings", settings_.AsValue()); | 63 TRACE_EVENT1("cc", "Scheduler::Scheduler", "settings", settings_.AsValue()); |
| 64 DCHECK(client_); | 64 DCHECK(client_); |
| 65 DCHECK(!state_machine_.BeginFrameNeeded()); | 65 DCHECK(!state_machine_.BeginFrameNeeded()); |
| 66 | 66 |
| 67 begin_retro_frame_closure_ = | |
| 68 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | |
| 69 begin_impl_frame_deadline_closure_ = base::Bind( | 67 begin_impl_frame_deadline_closure_ = base::Bind( |
| 70 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 68 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
| 71 | 69 |
| 72 SetBeginFrameSource(begin_frame_source); | 70 SetBeginFrameSource(begin_frame_source); |
| 73 ProcessScheduledActions(); | 71 ProcessScheduledActions(); |
| 74 } | 72 } |
| 75 | 73 |
| 76 Scheduler::~Scheduler() { | 74 Scheduler::~Scheduler() { |
| 77 SetBeginFrameSource(nullptr); | 75 SetBeginFrameSource(nullptr); |
| 78 } | 76 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 compositor_timing_history_->WillPrepareTiles(); | 191 compositor_timing_history_->WillPrepareTiles(); |
| 194 } | 192 } |
| 195 | 193 |
| 196 void Scheduler::DidPrepareTiles() { | 194 void Scheduler::DidPrepareTiles() { |
| 197 compositor_timing_history_->DidPrepareTiles(); | 195 compositor_timing_history_->DidPrepareTiles(); |
| 198 state_machine_.DidPrepareTiles(); | 196 state_machine_.DidPrepareTiles(); |
| 199 } | 197 } |
| 200 | 198 |
| 201 void Scheduler::DidLoseOutputSurface() { | 199 void Scheduler::DidLoseOutputSurface() { |
| 202 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 200 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
| 203 begin_retro_frame_args_.clear(); | |
| 204 begin_retro_frame_task_.Cancel(); | |
| 205 state_machine_.DidLoseOutputSurface(); | 201 state_machine_.DidLoseOutputSurface(); |
| 206 UpdateCompositorTimingHistoryRecordingEnabled(); | 202 UpdateCompositorTimingHistoryRecordingEnabled(); |
| 207 ProcessScheduledActions(); | 203 ProcessScheduledActions(); |
| 208 } | 204 } |
| 209 | 205 |
| 210 void Scheduler::DidCreateAndInitializeOutputSurface() { | 206 void Scheduler::DidCreateAndInitializeOutputSurface() { |
| 211 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 207 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
| 212 DCHECK(!observing_begin_frame_source_); | 208 DCHECK(!observing_begin_frame_source_); |
| 213 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | 209 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| 214 state_machine_.DidCreateAndInitializeOutputSurface(); | 210 state_machine_.DidCreateAndInitializeOutputSurface(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 if (begin_frame_source_) | 243 if (begin_frame_source_) |
| 248 begin_frame_source_->AddObserver(this); | 244 begin_frame_source_->AddObserver(this); |
| 249 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, | 245 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, |
| 250 true); | 246 true); |
| 251 } else if (state_machine_.begin_impl_frame_state() == | 247 } else if (state_machine_.begin_impl_frame_state() == |
| 252 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { | 248 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { |
| 253 // Call RemoveObserver in between frames only. | 249 // Call RemoveObserver in between frames only. |
| 254 observing_begin_frame_source_ = false; | 250 observing_begin_frame_source_ = false; |
| 255 if (begin_frame_source_) | 251 if (begin_frame_source_) |
| 256 begin_frame_source_->RemoveObserver(this); | 252 begin_frame_source_->RemoveObserver(this); |
| 253 missed_begin_frame_task_.Cancel(); | |
| 257 BeginImplFrameNotExpectedSoon(); | 254 BeginImplFrameNotExpectedSoon(); |
| 258 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, | 255 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, |
| 259 false); | 256 false); |
| 260 } | 257 } |
| 261 } | 258 } |
| 262 | |
| 263 PostBeginRetroFrameIfNeeded(); | |
| 264 } | 259 } |
| 265 | 260 |
| 266 void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) { | 261 void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) { |
| 267 if (state_machine_.begin_frame_source_paused() == paused) | 262 if (state_machine_.begin_frame_source_paused() == paused) |
| 268 return; | 263 return; |
| 269 TRACE_EVENT_INSTANT1("cc", "Scheduler::SetBeginFrameSourcePaused", | 264 TRACE_EVENT_INSTANT1("cc", "Scheduler::SetBeginFrameSourcePaused", |
| 270 TRACE_EVENT_SCOPE_THREAD, "paused", paused); | 265 TRACE_EVENT_SCOPE_THREAD, "paused", paused); |
| 271 state_machine_.SetBeginFrameSourcePaused(paused); | 266 state_machine_.SetBeginFrameSourcePaused(paused); |
| 272 ProcessScheduledActions(); | 267 ProcessScheduledActions(); |
| 273 } | 268 } |
| 274 | 269 |
| 275 // BeginFrame is the mechanism that tells us that now is a good time to start | 270 // BeginFrame is the mechanism that tells us that now is a good time to start |
| 276 // making a frame. Usually this means that user input for the frame is complete. | 271 // making a frame. Usually this means that user input for the frame is complete. |
| 277 // If the scheduler is busy, we queue the BeginFrame to be handled later as | 272 // If the scheduler is busy, we queue the BeginFrame to be handled later as |
| 278 // a BeginRetroFrame. | 273 // a BeginRetroFrame. |
| 279 bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { | 274 bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { |
| 280 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); | 275 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); |
| 281 | 276 |
| 277 if (!state_machine_.BeginFrameNeeded()) { | |
| 278 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrameDropped", | |
| 279 TRACE_EVENT_SCOPE_THREAD); | |
| 280 return false; | |
| 281 } | |
| 282 | |
| 282 // Trace this begin frame time through the Chrome stack | 283 // Trace this begin frame time through the Chrome stack |
| 283 TRACE_EVENT_FLOW_BEGIN0( | 284 TRACE_EVENT_FLOW_BEGIN0( |
| 284 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", | 285 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", |
| 285 args.frame_time.ToInternalValue()); | 286 args.frame_time.ToInternalValue()); |
| 286 | 287 |
| 287 // TODO(brianderson): Adjust deadline in the DisplayScheduler. | 288 // TODO(brianderson): Adjust deadline in the DisplayScheduler. |
| 288 BeginFrameArgs adjusted_args(args); | 289 BeginFrameArgs adjusted_args(args); |
| 289 adjusted_args.deadline -= EstimatedParentDrawTime(); | 290 adjusted_args.deadline -= EstimatedParentDrawTime(); |
| 290 | 291 |
| 291 if (settings_.using_synchronous_renderer_compositor) { | 292 if (settings_.using_synchronous_renderer_compositor) { |
| 292 BeginImplFrameSynchronous(adjusted_args); | 293 BeginImplFrameSynchronous(adjusted_args); |
| 293 return true; | 294 return true; |
| 294 } | 295 } |
| 295 | 296 |
| 296 // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has | 297 // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has |
| 297 // sent us the last BeginFrame we have missed. As we might not be able to | 298 // sent us the last BeginFrame we have missed. As we might not be able to |
| 298 // actually make rendering for this call, handle it like a "retro frame". | 299 // actually make rendering for this call, handle it like a "retro frame". |
| 299 // TODO(brainderson): Add a test for this functionality ASAP! | 300 // TODO(brainderson): Add a test for this functionality ASAP! |
| 300 if (adjusted_args.type == BeginFrameArgs::MISSED) { | 301 if (adjusted_args.type == BeginFrameArgs::MISSED) { |
| 301 begin_retro_frame_args_.push_back(adjusted_args); | 302 DCHECK(missed_begin_frame_task_.IsCancelled()); |
| 302 PostBeginRetroFrameIfNeeded(); | 303 missed_begin_frame_task_.Reset(base::Bind( |
| 304 &Scheduler::BeginImplFrameWithDeadline, base::Unretained(this), args)); | |
|
enne (OOO)
2016/09/09 17:40:27
Why args and not adjusted_args? (Just trying to un
sunnyps
2016/09/09 21:21:54
This was a mistake. Thanks for catching this!
| |
| 305 task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback()); | |
| 303 return true; | 306 return true; |
| 304 } | 307 } |
| 305 | 308 |
| 306 bool should_defer_begin_frame = | 309 BeginImplFrameWithDeadline(adjusted_args); |
| 307 !begin_retro_frame_args_.empty() || | |
| 308 !begin_retro_frame_task_.IsCancelled() || | |
| 309 !observing_begin_frame_source_ || | |
| 310 (state_machine_.begin_impl_frame_state() != | |
| 311 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | |
| 312 | |
| 313 if (should_defer_begin_frame) { | |
| 314 begin_retro_frame_args_.push_back(adjusted_args); | |
| 315 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginFrame deferred", | |
| 316 TRACE_EVENT_SCOPE_THREAD); | |
| 317 // Queuing the frame counts as "using it", so we need to return true. | |
| 318 } else { | |
| 319 BeginImplFrameWithDeadline(adjusted_args); | |
| 320 } | |
| 321 return true; | 310 return true; |
| 322 } | 311 } |
| 323 | 312 |
| 324 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { | 313 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { |
| 325 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); | 314 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); |
| 326 ProcessScheduledActions(); | 315 ProcessScheduledActions(); |
| 327 } | 316 } |
| 328 | 317 |
| 329 void Scheduler::OnDrawForOutputSurface(bool resourceless_software_draw) { | 318 void Scheduler::OnDrawForOutputSurface(bool resourceless_software_draw) { |
| 330 DCHECK(settings_.using_synchronous_renderer_compositor); | 319 DCHECK(settings_.using_synchronous_renderer_compositor); |
| 331 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 320 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
| 332 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 321 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 333 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | 322 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| 334 | 323 |
| 335 state_machine_.SetResourcelessSoftwareDraw(resourceless_software_draw); | 324 state_machine_.SetResourcelessSoftwareDraw(resourceless_software_draw); |
| 336 state_machine_.OnBeginImplFrameDeadline(); | 325 state_machine_.OnBeginImplFrameDeadline(); |
| 337 ProcessScheduledActions(); | 326 ProcessScheduledActions(); |
| 338 | 327 |
| 339 state_machine_.OnBeginImplFrameIdle(); | 328 state_machine_.OnBeginImplFrameIdle(); |
| 340 ProcessScheduledActions(); | 329 ProcessScheduledActions(); |
| 341 state_machine_.SetResourcelessSoftwareDraw(false); | 330 state_machine_.SetResourcelessSoftwareDraw(false); |
| 342 } | 331 } |
| 343 | 332 |
| 344 // BeginRetroFrame is called for BeginFrames that we've deferred because | |
| 345 // the scheduler was in the middle of processing a previous BeginFrame. | |
| 346 void Scheduler::BeginRetroFrame() { | |
| 347 TRACE_EVENT0("cc,benchmark", "Scheduler::BeginRetroFrame"); | |
| 348 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
| 349 DCHECK(!begin_retro_frame_args_.empty()); | |
| 350 DCHECK(!begin_retro_frame_task_.IsCancelled()); | |
| 351 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | |
| 352 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | |
| 353 | |
| 354 begin_retro_frame_task_.Cancel(); | |
| 355 | |
| 356 // Discard expired BeginRetroFrames | |
| 357 // Today, we should always end up with at most one un-expired BeginRetroFrame | |
| 358 // because deadlines will not be greater than the next frame time. We don't | |
| 359 // DCHECK though because some systems don't always have monotonic timestamps. | |
| 360 // TODO(brianderson): In the future, long deadlines could result in us not | |
| 361 // draining the queue if we don't catch up. If we consistently can't catch | |
| 362 // up, our fallback should be to lower our frame rate. | |
| 363 base::TimeTicks now = Now(); | |
| 364 | |
| 365 while (!begin_retro_frame_args_.empty()) { | |
| 366 const BeginFrameArgs& args = begin_retro_frame_args_.front(); | |
| 367 base::TimeTicks expiration_time = args.deadline; | |
| 368 if (now <= expiration_time) | |
| 369 break; | |
| 370 TRACE_EVENT_INSTANT2( | |
| 371 "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD, | |
| 372 "expiration_time - now", (expiration_time - now).InMillisecondsF(), | |
| 373 "BeginFrameArgs", begin_retro_frame_args_.front().AsValue()); | |
| 374 begin_retro_frame_args_.pop_front(); | |
| 375 if (begin_frame_source_) | |
| 376 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); | |
| 377 } | |
| 378 | |
| 379 if (begin_retro_frame_args_.empty()) { | |
| 380 TRACE_EVENT_INSTANT0("cc", "Scheduler::BeginRetroFrames all expired", | |
| 381 TRACE_EVENT_SCOPE_THREAD); | |
| 382 } else { | |
| 383 BeginFrameArgs front = begin_retro_frame_args_.front(); | |
| 384 begin_retro_frame_args_.pop_front(); | |
| 385 BeginImplFrameWithDeadline(front); | |
| 386 } | |
| 387 } | |
| 388 | |
| 389 // There could be a race between the posted BeginRetroFrame and a new | |
| 390 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame | |
| 391 // will check if there is a pending BeginRetroFrame to ensure we handle | |
| 392 // BeginFrames in FIFO order. | |
| 393 void Scheduler::PostBeginRetroFrameIfNeeded() { | |
| 394 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | |
| 395 "Scheduler::PostBeginRetroFrameIfNeeded", "state", AsValue()); | |
| 396 if (!observing_begin_frame_source_) | |
| 397 return; | |
| 398 | |
| 399 if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled()) | |
| 400 return; | |
| 401 | |
| 402 // begin_retro_frame_args_ should always be empty for the | |
| 403 // synchronous compositor. | |
| 404 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
| 405 | |
| 406 if (state_machine_.begin_impl_frame_state() != | |
| 407 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) | |
| 408 return; | |
| 409 | |
| 410 begin_retro_frame_task_.Reset(begin_retro_frame_closure_); | |
| 411 | |
| 412 task_runner_->PostTask(FROM_HERE, begin_retro_frame_task_.callback()); | |
| 413 } | |
| 414 | |
| 415 void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { | 333 void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { |
| 416 bool main_thread_is_in_high_latency_mode = | 334 bool main_thread_is_in_high_latency_mode = |
| 417 state_machine_.main_thread_missed_last_deadline(); | 335 state_machine_.main_thread_missed_last_deadline(); |
| 418 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", | 336 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", |
| 419 args.AsValue(), "main_thread_missed_last_deadline", | 337 args.AsValue(), "main_thread_missed_last_deadline", |
| 420 main_thread_is_in_high_latency_mode); | 338 main_thread_is_in_high_latency_mode); |
| 421 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 339 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| 422 "MainThreadLatency", main_thread_is_in_high_latency_mode); | 340 "MainThreadLatency", main_thread_is_in_high_latency_mode); |
| 423 | 341 |
| 342 if (state_machine_.begin_impl_frame_state() != | |
| 343 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { | |
|
brianderson
2016/09/09 07:35:58
Is it possible to reach this point in all begin_im
brianderson
2016/09/09 22:25:37
I double checked and I don't think we can get here
sunnyps
2016/09/09 22:35:42
Sorry, I missed this in my last patch. Done now.
| |
| 344 OnBeginImplFrameDeadline(); | |
| 345 } | |
| 346 | |
| 424 BeginFrameArgs adjusted_args = args; | 347 BeginFrameArgs adjusted_args = args; |
| 348 | |
| 349 // Cancel the missed begin frame task in case the BFS sends a normal begin | |
| 350 // frame before the missed frame task runs. This should be done after |args| | |
| 351 // is copied because destroying the task also destroys the storage for |args|. | |
| 352 missed_begin_frame_task_.Cancel(); | |
| 353 | |
| 425 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); | 354 adjusted_args.deadline -= compositor_timing_history_->DrawDurationEstimate(); |
| 426 adjusted_args.deadline -= kDeadlineFudgeFactor; | 355 adjusted_args.deadline -= kDeadlineFudgeFactor; |
| 427 | 356 |
| 428 base::TimeDelta bmf_start_to_activate = | 357 base::TimeDelta bmf_start_to_activate = |
| 429 compositor_timing_history_ | 358 compositor_timing_history_ |
| 430 ->BeginMainFrameStartToCommitDurationEstimate() + | 359 ->BeginMainFrameStartToCommitDurationEstimate() + |
| 431 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + | 360 compositor_timing_history_->CommitToReadyToActivateDurationEstimate() + |
| 432 compositor_timing_history_->ActivateDurationEstimate(); | 361 compositor_timing_history_->ActivateDurationEstimate(); |
| 433 | 362 |
| 434 base::TimeDelta bmf_to_activate_estimate_critical = | 363 base::TimeDelta bmf_to_activate_estimate_critical = |
| 435 bmf_start_to_activate + | 364 bmf_start_to_activate + |
| 436 compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate(); | 365 compositor_timing_history_->BeginMainFrameQueueDurationCriticalEstimate(); |
| 437 | 366 |
| 438 state_machine_.SetCriticalBeginMainFrameToActivateIsFast( | 367 state_machine_.SetCriticalBeginMainFrameToActivateIsFast( |
| 439 bmf_to_activate_estimate_critical < args.interval); | 368 bmf_to_activate_estimate_critical < adjusted_args.interval); |
| 440 | 369 |
| 441 // Update the BeginMainFrame args now that we know whether the main | 370 // Update the BeginMainFrame args now that we know whether the main |
| 442 // thread will be on the critical path or not. | 371 // thread will be on the critical path or not. |
| 443 begin_main_frame_args_ = adjusted_args; | 372 begin_main_frame_args_ = adjusted_args; |
| 444 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); | 373 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); |
| 445 | 374 |
| 446 base::TimeDelta bmf_to_activate_estimate = bmf_to_activate_estimate_critical; | 375 base::TimeDelta bmf_to_activate_estimate = bmf_to_activate_estimate_critical; |
| 447 if (!begin_main_frame_args_.on_critical_path) { | 376 if (!begin_main_frame_args_.on_critical_path) { |
| 448 bmf_to_activate_estimate = | 377 bmf_to_activate_estimate = |
| 449 bmf_start_to_activate + | 378 bmf_start_to_activate + |
| 450 compositor_timing_history_ | 379 compositor_timing_history_ |
| 451 ->BeginMainFrameQueueDurationNotCriticalEstimate(); | 380 ->BeginMainFrameQueueDurationNotCriticalEstimate(); |
| 452 } | 381 } |
| 453 | 382 |
| 454 bool can_activate_before_deadline = | 383 bool can_activate_before_deadline = |
| 455 CanBeginMainFrameAndActivateBeforeDeadline(adjusted_args, | 384 CanBeginMainFrameAndActivateBeforeDeadline(adjusted_args, |
| 456 bmf_to_activate_estimate); | 385 bmf_to_activate_estimate); |
| 457 | 386 |
| 458 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) { | 387 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) { |
| 459 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", | 388 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", |
| 460 TRACE_EVENT_SCOPE_THREAD); | 389 TRACE_EVENT_SCOPE_THREAD); |
| 461 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 390 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
| 462 } else if (ShouldRecoverImplLatency(adjusted_args, | 391 } else if (ShouldRecoverImplLatency(adjusted_args, |
| 463 can_activate_before_deadline)) { | 392 can_activate_before_deadline)) { |
| 464 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", | 393 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", |
| 465 TRACE_EVENT_SCOPE_THREAD); | 394 TRACE_EVENT_SCOPE_THREAD); |
| 466 if (begin_frame_source_) | 395 if (begin_frame_source_) |
| 467 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); | 396 begin_frame_source_->DidFinishFrame(this, 0); |
| 468 return; | 397 return; |
| 469 } | 398 } |
| 470 | 399 |
| 471 BeginImplFrame(adjusted_args); | 400 BeginImplFrame(adjusted_args); |
| 472 } | 401 } |
| 473 | 402 |
| 474 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { | 403 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { |
| 475 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", | 404 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", |
| 476 args.AsValue()); | 405 args.AsValue()); |
| 477 | 406 |
| 478 // The main thread currently can't commit before we draw with the | 407 // The main thread currently can't commit before we draw with the |
| 479 // synchronous compositor, so never consider the BeginMainFrame fast. | 408 // synchronous compositor, so never consider the BeginMainFrame fast. |
| 480 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false); | 409 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false); |
| 481 begin_main_frame_args_ = args; | 410 begin_main_frame_args_ = args; |
| 482 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); | 411 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); |
| 483 | 412 |
| 484 BeginImplFrame(args); | 413 BeginImplFrame(args); |
| 485 compositor_timing_history_->WillFinishImplFrame( | 414 compositor_timing_history_->WillFinishImplFrame( |
| 486 state_machine_.needs_redraw()); | 415 state_machine_.needs_redraw()); |
| 487 FinishImplFrame(); | 416 FinishImplFrame(); |
| 488 } | 417 } |
| 489 | 418 |
| 490 void Scheduler::FinishImplFrame() { | 419 void Scheduler::FinishImplFrame() { |
| 491 state_machine_.OnBeginImplFrameIdle(); | 420 state_machine_.OnBeginImplFrameIdle(); |
| 492 ProcessScheduledActions(); | 421 ProcessScheduledActions(); |
| 493 | 422 |
| 494 client_->DidFinishImplFrame(); | 423 client_->DidFinishImplFrame(); |
| 495 if (begin_frame_source_) | 424 if (begin_frame_source_) |
| 496 begin_frame_source_->DidFinishFrame(this, begin_retro_frame_args_.size()); | 425 begin_frame_source_->DidFinishFrame(this, 0); |
| 497 begin_impl_frame_tracker_.Finish(); | 426 begin_impl_frame_tracker_.Finish(); |
| 498 } | 427 } |
| 499 | 428 |
| 500 // BeginImplFrame starts a compositor frame that will wait up until a deadline | 429 // BeginImplFrame starts a compositor frame that will wait up until a deadline |
| 501 // for a BeginMainFrame+activation to complete before it times out and draws | 430 // for a BeginMainFrame+activation to complete before it times out and draws |
| 502 // any asynchronous animation and scroll/pinch updates. | 431 // any asynchronous animation and scroll/pinch updates. |
| 503 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 432 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { |
| 504 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 433 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
| 505 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 434 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 506 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | 435 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 715 state_machine_.AsValueInto(state.get()); | 644 state_machine_.AsValueInto(state.get()); |
| 716 state->EndDictionary(); | 645 state->EndDictionary(); |
| 717 | 646 |
| 718 state->BeginDictionary("scheduler_state"); | 647 state->BeginDictionary("scheduler_state"); |
| 719 state->SetBoolean("throttle_frame_production_", | 648 state->SetBoolean("throttle_frame_production_", |
| 720 settings_.throttle_frame_production); | 649 settings_.throttle_frame_production); |
| 721 state->SetDouble("estimated_parent_draw_time_ms", | 650 state->SetDouble("estimated_parent_draw_time_ms", |
| 722 estimated_parent_draw_time_.InMillisecondsF()); | 651 estimated_parent_draw_time_.InMillisecondsF()); |
| 723 state->SetBoolean("observing_begin_frame_source", | 652 state->SetBoolean("observing_begin_frame_source", |
| 724 observing_begin_frame_source_); | 653 observing_begin_frame_source_); |
| 725 state->SetInteger("begin_retro_frame_args", | |
| 726 static_cast<int>(begin_retro_frame_args_.size())); | |
| 727 state->SetBoolean("begin_retro_frame_task", | |
|
brianderson
2016/09/09 07:35:58
Add a trace for the new missed task?
sunnyps
2016/09/09 21:21:54
Done.
| |
| 728 !begin_retro_frame_task_.IsCancelled()); | |
| 729 state->SetBoolean("begin_impl_frame_deadline_task", | 654 state->SetBoolean("begin_impl_frame_deadline_task", |
| 730 !begin_impl_frame_deadline_task_.IsCancelled()); | 655 !begin_impl_frame_deadline_task_.IsCancelled()); |
| 731 state->SetString("inside_action", | 656 state->SetString("inside_action", |
| 732 SchedulerStateMachine::ActionToString(inside_action_)); | 657 SchedulerStateMachine::ActionToString(inside_action_)); |
| 733 | 658 |
| 734 state->BeginDictionary("begin_impl_frame_args"); | 659 state->BeginDictionary("begin_impl_frame_args"); |
| 735 begin_impl_frame_tracker_.AsValueInto(now, state.get()); | 660 begin_impl_frame_tracker_.AsValueInto(now, state.get()); |
| 736 state->EndDictionary(); | 661 state->EndDictionary(); |
| 737 | 662 |
| 738 state->SetString("begin_impl_frame_deadline_mode_", | 663 state->SetString("begin_impl_frame_deadline_mode_", |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 818 } | 743 } |
| 819 | 744 |
| 820 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 745 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
| 821 return (state_machine_.begin_main_frame_state() == | 746 return (state_machine_.begin_main_frame_state() == |
| 822 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || | 747 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || |
| 823 state_machine_.begin_main_frame_state() == | 748 state_machine_.begin_main_frame_state() == |
| 824 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); | 749 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); |
| 825 } | 750 } |
| 826 | 751 |
| 827 } // namespace cc | 752 } // namespace cc |
| OLD | NEW |