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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 195 compositor_timing_history_->WillPrepareTiles(); | 193 compositor_timing_history_->WillPrepareTiles(); |
| 196 } | 194 } |
| 197 | 195 |
| 198 void Scheduler::DidPrepareTiles() { | 196 void Scheduler::DidPrepareTiles() { |
| 199 compositor_timing_history_->DidPrepareTiles(); | 197 compositor_timing_history_->DidPrepareTiles(); |
| 200 state_machine_.DidPrepareTiles(); | 198 state_machine_.DidPrepareTiles(); |
| 201 } | 199 } |
| 202 | 200 |
| 203 void Scheduler::DidLoseOutputSurface() { | 201 void Scheduler::DidLoseOutputSurface() { |
| 204 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 202 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
| 205 begin_retro_frame_args_.clear(); | |
| 206 begin_retro_frame_task_.Cancel(); | |
| 207 state_machine_.DidLoseOutputSurface(); | 203 state_machine_.DidLoseOutputSurface(); |
| 208 UpdateCompositorTimingHistoryRecordingEnabled(); | 204 UpdateCompositorTimingHistoryRecordingEnabled(); |
| 209 ProcessScheduledActions(); | 205 ProcessScheduledActions(); |
| 210 } | 206 } |
| 211 | 207 |
| 212 void Scheduler::DidCreateAndInitializeOutputSurface() { | 208 void Scheduler::DidCreateAndInitializeOutputSurface() { |
| 213 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 209 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
| 214 DCHECK(!observing_begin_frame_source_); | 210 DCHECK(!observing_begin_frame_source_); |
| 215 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | 211 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| 216 state_machine_.DidCreateAndInitializeOutputSurface(); | 212 state_machine_.DidCreateAndInitializeOutputSurface(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 254 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { | 250 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { |
| 255 // Call RemoveObserver in between frames only. | 251 // Call RemoveObserver in between frames only. |
| 256 observing_begin_frame_source_ = false; | 252 observing_begin_frame_source_ = false; |
| 257 if (begin_frame_source_) | 253 if (begin_frame_source_) |
| 258 begin_frame_source_->RemoveObserver(this); | 254 begin_frame_source_->RemoveObserver(this); |
| 259 BeginImplFrameNotExpectedSoon(); | 255 BeginImplFrameNotExpectedSoon(); |
| 260 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, | 256 devtools_instrumentation::NeedsBeginFrameChanged(layer_tree_host_id_, |
| 261 false); | 257 false); |
| 262 } | 258 } |
| 263 } | 259 } |
| 264 | |
| 265 PostBeginRetroFrameIfNeeded(); | |
| 266 } | 260 } |
| 267 | 261 |
| 268 void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) { | 262 void Scheduler::OnBeginFrameSourcePausedChanged(bool paused) { |
| 269 if (state_machine_.begin_frame_source_paused() == paused) | 263 if (state_machine_.begin_frame_source_paused() == paused) |
| 270 return; | 264 return; |
| 271 TRACE_EVENT_INSTANT1("cc", "Scheduler::SetBeginFrameSourcePaused", | 265 TRACE_EVENT_INSTANT1("cc", "Scheduler::SetBeginFrameSourcePaused", |
| 272 TRACE_EVENT_SCOPE_THREAD, "paused", paused); | 266 TRACE_EVENT_SCOPE_THREAD, "paused", paused); |
| 273 state_machine_.SetBeginFrameSourcePaused(paused); | 267 state_machine_.SetBeginFrameSourcePaused(paused); |
| 274 ProcessScheduledActions(); | 268 ProcessScheduledActions(); |
| 275 } | 269 } |
| 276 | 270 |
| 271 const BeginFrameArgs& Scheduler::LastUsedBeginFrameArgs() const { | |
| 272 return begin_impl_frame_tracker_.DangerousMethodCurrentOrLast(); | |
| 273 } | |
| 274 | |
| 277 // BeginFrame is the mechanism that tells us that now is a good time to start | 275 // BeginFrame is the mechanism that tells us that now is a good time to start |
| 278 // making a frame. Usually this means that user input for the frame is complete. | 276 // making a frame. Usually this means that user input for the frame is complete. |
| 279 // If the scheduler is busy, we queue the BeginFrame to be handled later as | 277 void Scheduler::OnBeginFrame(const BeginFrameArgs& args) { |
| 280 // a BeginRetroFrame. | 278 if (!observing_begin_frame_source_ || |
| 281 bool Scheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { | 279 state_machine_.begin_impl_frame_state() != |
| 280 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) { | |
| 281 return; | |
| 282 } | |
| 283 | |
| 282 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); | 284 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginFrame", "args", args.AsValue()); |
| 283 | 285 |
| 284 // Trace this begin frame time through the Chrome stack | 286 // Trace this begin frame time through the Chrome stack |
| 285 TRACE_EVENT_FLOW_BEGIN0( | 287 TRACE_EVENT_FLOW_BEGIN0( |
| 286 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", | 288 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames"), "BeginFrameArgs", |
| 287 args.frame_time.ToInternalValue()); | 289 args.frame_time.ToInternalValue()); |
| 288 | 290 |
| 289 // TODO(brianderson): Adjust deadline in the DisplayScheduler. | 291 // TODO(brianderson): Adjust deadline in the DisplayScheduler. |
| 290 BeginFrameArgs adjusted_args(args); | 292 BeginFrameArgs adjusted_args(args); |
| 291 adjusted_args.deadline -= EstimatedParentDrawTime(); | 293 adjusted_args.deadline -= EstimatedParentDrawTime(); |
| 292 | 294 |
| 293 // Deliver BeginFrames to children. | 295 // Deliver BeginFrames to children. |
| 294 // TODO(brianderson): Move this responsibility to the DisplayScheduler. | 296 // TODO(brianderson): Move this responsibility to the DisplayScheduler. |
| 295 if (state_machine_.children_need_begin_frames()) | 297 if (state_machine_.children_need_begin_frames()) |
| 296 client_->SendBeginFramesToChildren(adjusted_args); | 298 client_->SendBeginFramesToChildren(adjusted_args); |
| 297 | 299 |
| 298 if (settings_.using_synchronous_renderer_compositor) { | 300 if (settings_.using_synchronous_renderer_compositor) { |
| 299 BeginImplFrameSynchronous(adjusted_args); | 301 BeginImplFrameSynchronous(adjusted_args); |
| 300 return true; | |
| 301 } | |
| 302 | |
| 303 // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has | |
| 304 // sent us the last BeginFrame we have missed. As we might not be able to | |
| 305 // actually make rendering for this call, handle it like a "retro frame". | |
| 306 // TODO(brainderson): Add a test for this functionality ASAP! | |
| 307 if (adjusted_args.type == BeginFrameArgs::MISSED) { | |
|
enne (OOO)
2016/04/18 21:30:38
The removal of this might break https://codereview
| |
| 308 begin_retro_frame_args_.push_back(adjusted_args); | |
| 309 PostBeginRetroFrameIfNeeded(); | |
| 310 return true; | |
| 311 } | |
| 312 | |
| 313 bool should_defer_begin_frame = | |
| 314 !begin_retro_frame_args_.empty() || | |
| 315 !begin_retro_frame_task_.IsCancelled() || | |
| 316 !observing_begin_frame_source_ || | |
| 317 (state_machine_.begin_impl_frame_state() != | |
| 318 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | |
| 319 | |
| 320 if (should_defer_begin_frame) { | |
| 321 begin_retro_frame_args_.push_back(adjusted_args); | |
| 322 TRACE_EVENT_INSTANT0( | |
| 323 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); | |
| 324 // Queuing the frame counts as "using it", so we need to return true. | |
| 325 } else { | 302 } else { |
| 326 BeginImplFrameWithDeadline(adjusted_args); | 303 BeginImplFrameWithDeadline(adjusted_args); |
| 327 } | 304 } |
| 328 return true; | |
| 329 } | 305 } |
| 330 | 306 |
| 331 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { | 307 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { |
| 332 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); | 308 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); |
| 333 ProcessScheduledActions(); | 309 ProcessScheduledActions(); |
| 334 } | 310 } |
| 335 | 311 |
| 336 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { | 312 void Scheduler::SetVideoNeedsBeginFrames(bool video_needs_begin_frames) { |
| 337 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); | 313 state_machine_.SetVideoNeedsBeginFrames(video_needs_begin_frames); |
| 338 ProcessScheduledActions(); | 314 ProcessScheduledActions(); |
| 339 } | 315 } |
| 340 | 316 |
| 341 void Scheduler::OnDrawForOutputSurface(bool resourceless_software_draw) { | 317 void Scheduler::OnDrawForOutputSurface(bool resourceless_software_draw) { |
| 342 DCHECK(settings_.using_synchronous_renderer_compositor); | 318 DCHECK(settings_.using_synchronous_renderer_compositor); |
| 343 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 319 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
| 344 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 320 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 345 DCHECK(!BeginImplFrameDeadlinePending()); | 321 DCHECK(!BeginImplFrameDeadlinePending()); |
| 346 | 322 |
| 347 state_machine_.SetResourcelessSoftareDraw(resourceless_software_draw); | 323 state_machine_.SetResourcelessSoftareDraw(resourceless_software_draw); |
| 348 state_machine_.OnBeginImplFrameDeadline(); | 324 state_machine_.OnBeginImplFrameDeadline(); |
| 349 ProcessScheduledActions(); | 325 ProcessScheduledActions(); |
| 350 | 326 |
| 351 state_machine_.OnBeginImplFrameIdle(); | 327 state_machine_.OnBeginImplFrameIdle(); |
| 352 ProcessScheduledActions(); | 328 ProcessScheduledActions(); |
| 353 state_machine_.SetResourcelessSoftareDraw(false); | 329 state_machine_.SetResourcelessSoftareDraw(false); |
| 354 } | 330 } |
| 355 | 331 |
| 356 // BeginRetroFrame is called for BeginFrames that we've deferred because | |
| 357 // the scheduler was in the middle of processing a previous BeginFrame. | |
| 358 void Scheduler::BeginRetroFrame() { | |
| 359 TRACE_EVENT0("cc,benchmark", "Scheduler::BeginRetroFrame"); | |
| 360 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
| 361 DCHECK(!begin_retro_frame_args_.empty()); | |
| 362 DCHECK(!begin_retro_frame_task_.IsCancelled()); | |
| 363 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | |
| 364 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | |
| 365 | |
| 366 begin_retro_frame_task_.Cancel(); | |
| 367 | |
| 368 // Discard expired BeginRetroFrames | |
| 369 // Today, we should always end up with at most one un-expired BeginRetroFrame | |
| 370 // because deadlines will not be greater than the next frame time. We don't | |
| 371 // DCHECK though because some systems don't always have monotonic timestamps. | |
| 372 // TODO(brianderson): In the future, long deadlines could result in us not | |
| 373 // draining the queue if we don't catch up. If we consistently can't catch | |
| 374 // up, our fallback should be to lower our frame rate. | |
| 375 base::TimeTicks now = Now(); | |
| 376 | |
| 377 while (!begin_retro_frame_args_.empty()) { | |
| 378 const BeginFrameArgs& args = begin_retro_frame_args_.front(); | |
| 379 base::TimeTicks expiration_time = args.deadline; | |
| 380 if (now <= expiration_time) | |
| 381 break; | |
| 382 TRACE_EVENT_INSTANT2( | |
| 383 "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD, | |
| 384 "expiration_time - now", (expiration_time - now).InMillisecondsF(), | |
| 385 "BeginFrameArgs", begin_retro_frame_args_.front().AsValue()); | |
| 386 begin_retro_frame_args_.pop_front(); | |
| 387 if (begin_frame_source_) | |
| 388 begin_frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | |
| 389 } | |
| 390 | |
| 391 if (begin_retro_frame_args_.empty()) { | |
| 392 TRACE_EVENT_INSTANT0("cc", | |
| 393 "Scheduler::BeginRetroFrames all expired", | |
| 394 TRACE_EVENT_SCOPE_THREAD); | |
| 395 } else { | |
| 396 BeginFrameArgs front = begin_retro_frame_args_.front(); | |
| 397 begin_retro_frame_args_.pop_front(); | |
| 398 BeginImplFrameWithDeadline(front); | |
| 399 } | |
| 400 } | |
| 401 | |
| 402 // There could be a race between the posted BeginRetroFrame and a new | |
| 403 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame | |
| 404 // will check if there is a pending BeginRetroFrame to ensure we handle | |
| 405 // BeginFrames in FIFO order. | |
| 406 void Scheduler::PostBeginRetroFrameIfNeeded() { | |
| 407 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | |
| 408 "Scheduler::PostBeginRetroFrameIfNeeded", | |
| 409 "state", | |
| 410 AsValue()); | |
| 411 if (!observing_begin_frame_source_) | |
| 412 return; | |
| 413 | |
| 414 if (begin_retro_frame_args_.empty() || !begin_retro_frame_task_.IsCancelled()) | |
| 415 return; | |
| 416 | |
| 417 // begin_retro_frame_args_ should always be empty for the | |
| 418 // synchronous compositor. | |
| 419 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
| 420 | |
| 421 if (state_machine_.begin_impl_frame_state() != | |
| 422 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) | |
| 423 return; | |
| 424 | |
| 425 begin_retro_frame_task_.Reset(begin_retro_frame_closure_); | |
| 426 | |
| 427 task_runner_->PostTask(FROM_HERE, begin_retro_frame_task_.callback()); | |
| 428 } | |
| 429 | |
| 430 void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { | 332 void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { |
| 431 bool main_thread_is_in_high_latency_mode = | 333 bool main_thread_is_in_high_latency_mode = |
| 432 state_machine_.main_thread_missed_last_deadline(); | 334 state_machine_.main_thread_missed_last_deadline(); |
| 433 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", | 335 TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", |
| 434 args.AsValue(), "main_thread_missed_last_deadline", | 336 args.AsValue(), "main_thread_missed_last_deadline", |
| 435 main_thread_is_in_high_latency_mode); | 337 main_thread_is_in_high_latency_mode); |
| 436 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 338 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| 437 "MainThreadLatency", main_thread_is_in_high_latency_mode); | 339 "MainThreadLatency", main_thread_is_in_high_latency_mode); |
| 438 | 340 |
| 439 BeginFrameArgs adjusted_args = args; | 341 BeginFrameArgs adjusted_args = args; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 bmf_to_activate_estimate); | 373 bmf_to_activate_estimate); |
| 472 | 374 |
| 473 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) { | 375 if (ShouldRecoverMainLatency(adjusted_args, can_activate_before_deadline)) { |
| 474 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", | 376 TRACE_EVENT_INSTANT0("cc", "SkipBeginMainFrameToReduceLatency", |
| 475 TRACE_EVENT_SCOPE_THREAD); | 377 TRACE_EVENT_SCOPE_THREAD); |
| 476 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | 378 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); |
| 477 } else if (ShouldRecoverImplLatency(adjusted_args, | 379 } else if (ShouldRecoverImplLatency(adjusted_args, |
| 478 can_activate_before_deadline)) { | 380 can_activate_before_deadline)) { |
| 479 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", | 381 TRACE_EVENT_INSTANT0("cc", "SkipBeginImplFrameToReduceLatency", |
| 480 TRACE_EVENT_SCOPE_THREAD); | 382 TRACE_EVENT_SCOPE_THREAD); |
| 481 if (begin_frame_source_) | |
| 482 begin_frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | |
| 483 return; | 383 return; |
| 484 } | 384 } |
| 485 | 385 |
| 486 BeginImplFrame(adjusted_args); | 386 BeginImplFrame(adjusted_args); |
| 487 | |
| 488 // The deadline will be scheduled in ProcessScheduledActions. | |
| 489 state_machine_.OnBeginImplFrameDeadlinePending(); | |
| 490 ProcessScheduledActions(); | |
| 491 } | 387 } |
| 492 | 388 |
| 493 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { | 389 void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { |
| 494 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", | 390 TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", |
| 495 args.AsValue()); | 391 args.AsValue()); |
| 496 | 392 |
| 497 // The main thread currently can't commit before we draw with the | 393 // The main thread currently can't commit before we draw with the |
| 498 // synchronous compositor, so never consider the BeginMainFrame fast. | 394 // synchronous compositor, so never consider the BeginMainFrame fast. |
| 499 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false); | 395 state_machine_.SetCriticalBeginMainFrameToActivateIsFast(false); |
| 500 begin_main_frame_args_ = args; | 396 begin_main_frame_args_ = args; |
| 501 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); | 397 begin_main_frame_args_.on_critical_path = !ImplLatencyTakesPriority(); |
| 502 | 398 |
| 503 BeginImplFrame(args); | 399 BeginImplFrame(args); |
| 504 compositor_timing_history_->WillFinishImplFrame( | 400 compositor_timing_history_->WillFinishImplFrame( |
| 505 state_machine_.needs_redraw()); | 401 state_machine_.needs_redraw()); |
| 506 FinishImplFrame(); | 402 FinishImplFrame(); |
| 507 } | 403 } |
| 508 | 404 |
| 509 void Scheduler::FinishImplFrame() { | 405 void Scheduler::FinishImplFrame() { |
| 510 state_machine_.OnBeginImplFrameIdle(); | 406 state_machine_.OnBeginImplFrameIdle(); |
| 511 ProcessScheduledActions(); | 407 ProcessScheduledActions(); |
| 512 | 408 |
| 409 begin_impl_frame_tracker_.Finish(); | |
| 410 | |
| 513 client_->DidFinishImplFrame(); | 411 client_->DidFinishImplFrame(); |
| 412 | |
| 514 if (begin_frame_source_) | 413 if (begin_frame_source_) |
| 515 begin_frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | 414 begin_frame_source_->DidFinishFrame(this); |
| 516 begin_impl_frame_tracker_.Finish(); | |
| 517 } | 415 } |
| 518 | 416 |
| 519 // BeginImplFrame starts a compositor frame that will wait up until a deadline | 417 // BeginImplFrame starts a compositor frame that will wait up until a deadline |
| 520 // for a BeginMainFrame+activation to complete before it times out and draws | 418 // for a BeginMainFrame+activation to complete before it times out and draws |
| 521 // any asynchronous animation and scroll/pinch updates. | 419 // any asynchronous animation and scroll/pinch updates. |
| 522 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | 420 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { |
| 523 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | 421 DCHECK_EQ(state_machine_.begin_impl_frame_state(), |
| 524 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | 422 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); |
| 525 DCHECK(!BeginImplFrameDeadlinePending()); | 423 DCHECK(!BeginImplFrameDeadlinePending()); |
| 526 DCHECK(state_machine_.HasInitializedOutputSurface()); | 424 DCHECK(state_machine_.HasInitializedOutputSurface()); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 654 TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", | 552 TRACE_EVENT1("cc", "Scheduler::SetDeferCommits", |
| 655 "defer_commits", | 553 "defer_commits", |
| 656 defer_commits); | 554 defer_commits); |
| 657 state_machine_.SetDeferCommits(defer_commits); | 555 state_machine_.SetDeferCommits(defer_commits); |
| 658 ProcessScheduledActions(); | 556 ProcessScheduledActions(); |
| 659 } | 557 } |
| 660 | 558 |
| 661 void Scheduler::ProcessScheduledActions() { | 559 void Scheduler::ProcessScheduledActions() { |
| 662 // We do not allow ProcessScheduledActions to be recursive. | 560 // We do not allow ProcessScheduledActions to be recursive. |
| 663 // The top-level call will iteratively execute the next action for us anyway. | 561 // The top-level call will iteratively execute the next action for us anyway. |
| 664 if (inside_process_scheduled_actions_) | 562 if (!inside_process_scheduled_actions_) { |
| 665 return; | 563 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
| 564 SchedulerStateMachine::Action action; | |
| 565 do { | |
| 566 action = state_machine_.NextAction(); | |
| 567 PerformAction(action); | |
| 568 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | |
| 569 "SchedulerStateMachine", "state", AsValue()); | |
| 570 } while (action != SchedulerStateMachine::ACTION_NONE); | |
| 571 } | |
| 572 SetupNextBeginFrameIfNeeded(); | |
| 573 ScheduleBeginImplFrameDeadlineIfNeeded(); | |
| 574 } | |
| 666 | 575 |
| 667 base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); | 576 void Scheduler::PerformAction(SchedulerStateMachine::Action action) { |
| 668 | 577 base::AutoReset<SchedulerStateMachine::Action> mark_inside_action( |
| 669 SchedulerStateMachine::Action action; | 578 &inside_action_, action); |
| 670 do { | 579 switch (action) { |
| 671 action = state_machine_.NextAction(); | 580 case SchedulerStateMachine::ACTION_NONE: |
| 672 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 581 break; |
| 673 "SchedulerStateMachine", | 582 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: |
| 674 "state", | 583 compositor_timing_history_->WillBeginMainFrame( |
| 675 AsValue()); | 584 begin_main_frame_args_.on_critical_path, |
| 676 base::AutoReset<SchedulerStateMachine::Action> | 585 begin_main_frame_args_.frame_time); |
| 677 mark_inside_action(&inside_action_, action); | 586 state_machine_.WillSendBeginMainFrame(); |
| 678 switch (action) { | 587 // TODO(brianderson): Pass begin_main_frame_args_ directly to client. |
| 679 case SchedulerStateMachine::ACTION_NONE: | 588 client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_); |
| 680 break; | 589 break; |
| 681 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: | 590 case SchedulerStateMachine::ACTION_COMMIT: { |
| 682 compositor_timing_history_->WillBeginMainFrame( | 591 // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is |
| 683 begin_main_frame_args_.on_critical_path, | 592 // fixed. |
| 684 begin_main_frame_args_.frame_time); | 593 tracked_objects::ScopedTracker tracking_profile4( |
| 685 state_machine_.WillSendBeginMainFrame(); | 594 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 686 // TODO(brianderson): Pass begin_main_frame_args_ directly to client. | 595 "461509 Scheduler::ProcessScheduledActions4")); |
| 687 client_->ScheduledActionSendBeginMainFrame(begin_main_frame_args_); | 596 bool commit_has_no_updates = false; |
| 688 break; | 597 state_machine_.WillCommit(commit_has_no_updates); |
| 689 case SchedulerStateMachine::ACTION_COMMIT: { | 598 client_->ScheduledActionCommit(); |
| 690 // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is | 599 break; |
| 691 // fixed. | |
| 692 tracked_objects::ScopedTracker tracking_profile4( | |
| 693 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 694 "461509 Scheduler::ProcessScheduledActions4")); | |
| 695 bool commit_has_no_updates = false; | |
| 696 state_machine_.WillCommit(commit_has_no_updates); | |
| 697 client_->ScheduledActionCommit(); | |
| 698 break; | |
| 699 } | |
| 700 case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE: | |
| 701 compositor_timing_history_->WillActivate(); | |
| 702 state_machine_.WillActivate(); | |
| 703 client_->ScheduledActionActivateSyncTree(); | |
| 704 compositor_timing_history_->DidActivate(); | |
| 705 break; | |
| 706 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: { | |
| 707 // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is | |
| 708 // fixed. | |
| 709 tracked_objects::ScopedTracker tracking_profile6( | |
| 710 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 711 "461509 Scheduler::ProcessScheduledActions6")); | |
| 712 DrawAndSwapIfPossible(); | |
| 713 break; | |
| 714 } | |
| 715 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: | |
| 716 DrawAndSwapForced(); | |
| 717 break; | |
| 718 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: { | |
| 719 // No action is actually performed, but this allows the state machine to | |
| 720 // drain the pipeline without actually drawing. | |
| 721 state_machine_.AbortDrawAndSwap(); | |
| 722 compositor_timing_history_->DrawAborted(); | |
| 723 break; | |
| 724 } | |
| 725 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | |
| 726 state_machine_.WillBeginOutputSurfaceCreation(); | |
| 727 client_->ScheduledActionBeginOutputSurfaceCreation(); | |
| 728 break; | |
| 729 case SchedulerStateMachine::ACTION_PREPARE_TILES: | |
| 730 state_machine_.WillPrepareTiles(); | |
| 731 client_->ScheduledActionPrepareTiles(); | |
| 732 break; | |
| 733 case SchedulerStateMachine::ACTION_INVALIDATE_OUTPUT_SURFACE: { | |
| 734 state_machine_.WillInvalidateOutputSurface(); | |
| 735 client_->ScheduledActionInvalidateOutputSurface(); | |
| 736 break; | |
| 737 } | |
| 738 } | 600 } |
| 739 } while (action != SchedulerStateMachine::ACTION_NONE); | 601 case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE: |
| 740 | 602 compositor_timing_history_->WillActivate(); |
| 741 ScheduleBeginImplFrameDeadlineIfNeeded(); | 603 state_machine_.WillActivate(); |
| 742 SetupNextBeginFrameIfNeeded(); | 604 client_->ScheduledActionActivateSyncTree(); |
| 605 compositor_timing_history_->DidActivate(); | |
| 606 break; | |
| 607 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: { | |
| 608 // TODO(robliao): Remove ScopedTracker below once crbug.com/461509 is | |
| 609 // fixed. | |
| 610 tracked_objects::ScopedTracker tracking_profile6( | |
| 611 FROM_HERE_WITH_EXPLICIT_FUNCTION( | |
| 612 "461509 Scheduler::ProcessScheduledActions6")); | |
| 613 DrawAndSwapIfPossible(); | |
| 614 break; | |
| 615 } | |
| 616 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: | |
| 617 DrawAndSwapForced(); | |
| 618 break; | |
| 619 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: { | |
| 620 // No action is actually performed, but this allows the state machine | |
| 621 // to | |
| 622 // drain the pipeline without actually drawing. | |
| 623 state_machine_.AbortDrawAndSwap(); | |
| 624 compositor_timing_history_->DrawAborted(); | |
| 625 break; | |
| 626 } | |
| 627 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | |
| 628 state_machine_.WillBeginOutputSurfaceCreation(); | |
| 629 client_->ScheduledActionBeginOutputSurfaceCreation(); | |
| 630 break; | |
| 631 case SchedulerStateMachine::ACTION_PREPARE_TILES: | |
| 632 state_machine_.WillPrepareTiles(); | |
| 633 client_->ScheduledActionPrepareTiles(); | |
| 634 break; | |
| 635 case SchedulerStateMachine::ACTION_INVALIDATE_OUTPUT_SURFACE: { | |
| 636 state_machine_.WillInvalidateOutputSurface(); | |
| 637 client_->ScheduledActionInvalidateOutputSurface(); | |
| 638 break; | |
| 639 } | |
| 640 } | |
| 743 } | 641 } |
| 744 | 642 |
| 745 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> | 643 std::unique_ptr<base::trace_event::ConvertableToTraceFormat> |
| 746 Scheduler::AsValue() const { | 644 Scheduler::AsValue() const { |
| 747 std::unique_ptr<base::trace_event::TracedValue> state( | 645 std::unique_ptr<base::trace_event::TracedValue> state( |
| 748 new base::trace_event::TracedValue()); | 646 new base::trace_event::TracedValue()); |
| 749 AsValueInto(state.get()); | 647 AsValueInto(state.get()); |
| 750 return std::move(state); | 648 return std::move(state); |
| 751 } | 649 } |
| 752 | 650 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 768 state->EndDictionary(); | 666 state->EndDictionary(); |
| 769 } | 667 } |
| 770 | 668 |
| 771 state->BeginDictionary("scheduler_state"); | 669 state->BeginDictionary("scheduler_state"); |
| 772 state->SetBoolean("throttle_frame_production_", | 670 state->SetBoolean("throttle_frame_production_", |
| 773 settings_.throttle_frame_production); | 671 settings_.throttle_frame_production); |
| 774 state->SetDouble("estimated_parent_draw_time_ms", | 672 state->SetDouble("estimated_parent_draw_time_ms", |
| 775 estimated_parent_draw_time_.InMillisecondsF()); | 673 estimated_parent_draw_time_.InMillisecondsF()); |
| 776 state->SetBoolean("observing_begin_frame_source", | 674 state->SetBoolean("observing_begin_frame_source", |
| 777 observing_begin_frame_source_); | 675 observing_begin_frame_source_); |
| 778 state->SetInteger("begin_retro_frame_args", | |
| 779 static_cast<int>(begin_retro_frame_args_.size())); | |
| 780 state->SetBoolean("begin_retro_frame_task", | |
| 781 !begin_retro_frame_task_.IsCancelled()); | |
| 782 state->SetBoolean("begin_impl_frame_deadline_task", | 676 state->SetBoolean("begin_impl_frame_deadline_task", |
| 783 !begin_impl_frame_deadline_task_.IsCancelled()); | 677 !begin_impl_frame_deadline_task_.IsCancelled()); |
| 784 state->SetString("inside_action", | 678 state->SetString("inside_action", |
| 785 SchedulerStateMachine::ActionToString(inside_action_)); | 679 SchedulerStateMachine::ActionToString(inside_action_)); |
| 786 | 680 |
| 787 state->BeginDictionary("begin_impl_frame_args"); | 681 state->BeginDictionary("begin_impl_frame_args"); |
| 788 begin_impl_frame_tracker_.AsValueInto(now, state); | 682 begin_impl_frame_tracker_.AsValueInto(now, state); |
| 789 state->EndDictionary(); | 683 state->EndDictionary(); |
| 790 | 684 |
| 791 state->SetString("begin_impl_frame_deadline_mode_", | 685 state->SetString("begin_impl_frame_deadline_mode_", |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 869 } | 763 } |
| 870 | 764 |
| 871 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 765 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
| 872 return (state_machine_.begin_main_frame_state() == | 766 return (state_machine_.begin_main_frame_state() == |
| 873 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || | 767 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_SENT || |
| 874 state_machine_.begin_main_frame_state() == | 768 state_machine_.begin_main_frame_state() == |
| 875 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); | 769 SchedulerStateMachine::BEGIN_MAIN_FRAME_STATE_STARTED); |
| 876 } | 770 } |
| 877 | 771 |
| 878 } // namespace cc | 772 } // namespace cc |
| OLD | NEW |