| 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/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 primary_frame_source_(NULL), | 83 primary_frame_source_(NULL), |
| 84 background_frame_source_(NULL), | 84 background_frame_source_(NULL), |
| 85 primary_frame_source_internal_(external_begin_frame_source.Pass()), | 85 primary_frame_source_internal_(external_begin_frame_source.Pass()), |
| 86 background_frame_source_internal_(), | 86 background_frame_source_internal_(), |
| 87 vsync_observer_(NULL), | 87 vsync_observer_(NULL), |
| 88 settings_(scheduler_settings), | 88 settings_(scheduler_settings), |
| 89 client_(client), | 89 client_(client), |
| 90 layer_tree_host_id_(layer_tree_host_id), | 90 layer_tree_host_id_(layer_tree_host_id), |
| 91 task_runner_(task_runner), | 91 task_runner_(task_runner), |
| 92 power_monitor_(power_monitor), | 92 power_monitor_(power_monitor), |
| 93 begin_retro_frame_posted_(false), | 93 begin_frame_process_posted_(false), |
| 94 state_machine_(scheduler_settings), | 94 state_machine_(scheduler_settings), |
| 95 inside_process_scheduled_actions_(false), | 95 inside_process_scheduled_actions_(false), |
| 96 inside_action_(SchedulerStateMachine::ACTION_NONE), | 96 inside_action_(SchedulerStateMachine::ACTION_NONE), |
| 97 weak_factory_(this) { | 97 weak_factory_(this) { |
| 98 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | 98 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), |
| 99 "Scheduler::Scheduler", | 99 "Scheduler::Scheduler", |
| 100 "settings", | 100 "settings", |
| 101 settings_.AsValue()); | 101 settings_.AsValue()); |
| 102 DCHECK(client_); | 102 DCHECK(client_); |
| 103 DCHECK(!state_machine_.BeginFrameNeeded()); | 103 DCHECK(!state_machine_.BeginFrameNeeded()); |
| 104 | 104 |
| 105 begin_retro_frame_closure_ = | 105 begin_frame_process_closure_ = |
| 106 base::Bind(&Scheduler::BeginRetroFrame, weak_factory_.GetWeakPtr()); | 106 base::Bind(&Scheduler::ProcessBeginFrames, weak_factory_.GetWeakPtr()); |
| 107 begin_impl_frame_deadline_closure_ = base::Bind( | 107 begin_impl_frame_deadline_closure_ = base::Bind( |
| 108 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); | 108 &Scheduler::OnBeginImplFrameDeadline, weak_factory_.GetWeakPtr()); |
| 109 poll_for_draw_triggers_closure_ = base::Bind( | 109 poll_for_draw_triggers_closure_ = base::Bind( |
| 110 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); | 110 &Scheduler::PollForAnticipatedDrawTriggers, weak_factory_.GetWeakPtr()); |
| 111 advance_commit_state_closure_ = base::Bind( | 111 advance_commit_state_closure_ = base::Bind( |
| 112 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); | 112 &Scheduler::PollToAdvanceCommitState, weak_factory_.GetWeakPtr()); |
| 113 | 113 |
| 114 frame_source_ = BeginFrameSourceMultiplexer::Create(); | 114 frame_source_ = BeginFrameSourceMultiplexer::Create(); |
| 115 frame_source_->AddObserver(this); | 115 frame_source_->AddObserver(this); |
| 116 | 116 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 } | 152 } |
| 153 } | 153 } |
| 154 | 154 |
| 155 void Scheduler::TeardownPowerMonitoring() { | 155 void Scheduler::TeardownPowerMonitoring() { |
| 156 if (settings_.disable_hi_res_timer_tasks_on_battery) { | 156 if (settings_.disable_hi_res_timer_tasks_on_battery) { |
| 157 DCHECK(power_monitor_); | 157 DCHECK(power_monitor_); |
| 158 power_monitor_->RemoveObserver(this); | 158 power_monitor_->RemoveObserver(this); |
| 159 } | 159 } |
| 160 } | 160 } |
| 161 | 161 |
| 162 void Scheduler::OnPowerStateChange(bool on_battery_power) { | |
| 163 DCHECK(settings_.disable_hi_res_timer_tasks_on_battery); | |
| 164 state_machine_.SetImplLatencyTakesPriorityOnBattery(on_battery_power); | |
| 165 } | |
| 166 | |
| 167 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, | 162 void Scheduler::CommitVSyncParameters(base::TimeTicks timebase, |
| 168 base::TimeDelta interval) { | 163 base::TimeDelta interval) { |
| 169 // TODO(brianderson): We should not be receiving 0 intervals. | 164 // TODO(brianderson): We should not be receiving 0 intervals. |
| 170 if (interval == base::TimeDelta()) | 165 if (interval == base::TimeDelta()) |
| 171 interval = BeginFrameArgs::DefaultInterval(); | 166 interval = BeginFrameArgs::DefaultInterval(); |
| 172 | 167 |
| 173 if (vsync_observer_) | 168 if (vsync_observer_) |
| 174 vsync_observer_->OnUpdateVSyncParameters(timebase, interval); | 169 vsync_observer_->OnUpdateVSyncParameters(timebase, interval); |
| 175 } | 170 } |
| 176 | 171 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 if (!inside_process_scheduled_actions_) { | 237 if (!inside_process_scheduled_actions_) { |
| 243 DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE); | 238 DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE); |
| 244 } | 239 } |
| 245 } | 240 } |
| 246 | 241 |
| 247 void Scheduler::DidSwapBuffersComplete() { | 242 void Scheduler::DidSwapBuffersComplete() { |
| 248 state_machine_.DidSwapBuffersComplete(); | 243 state_machine_.DidSwapBuffersComplete(); |
| 249 ProcessScheduledActions(); | 244 ProcessScheduledActions(); |
| 250 } | 245 } |
| 251 | 246 |
| 252 void Scheduler::SetImplLatencyTakesPriority(bool impl_latency_takes_priority) { | |
| 253 state_machine_.SetImplLatencyTakesPriority(impl_latency_takes_priority); | |
| 254 ProcessScheduledActions(); | |
| 255 } | |
| 256 | |
| 257 void Scheduler::NotifyReadyToCommit() { | 247 void Scheduler::NotifyReadyToCommit() { |
| 258 TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit"); | 248 TRACE_EVENT0("cc", "Scheduler::NotifyReadyToCommit"); |
| 259 state_machine_.NotifyReadyToCommit(); | 249 state_machine_.NotifyReadyToCommit(); |
| 260 ProcessScheduledActions(); | 250 ProcessScheduledActions(); |
| 261 } | 251 } |
| 262 | 252 |
| 263 void Scheduler::BeginMainFrameAborted(bool did_handle) { | 253 void Scheduler::BeginMainFrameAborted(bool did_handle) { |
| 264 TRACE_EVENT0("cc", "Scheduler::BeginMainFrameAborted"); | 254 TRACE_EVENT0("cc", "Scheduler::BeginMainFrameAborted"); |
| 265 state_machine_.BeginMainFrameAborted(did_handle); | 255 state_machine_.BeginMainFrameAborted(did_handle); |
| 266 ProcessScheduledActions(); | 256 ProcessScheduledActions(); |
| 267 } | 257 } |
| 268 | 258 |
| 269 void Scheduler::DidManageTiles() { | 259 void Scheduler::DidManageTiles() { |
| 270 state_machine_.DidManageTiles(); | 260 state_machine_.DidManageTiles(); |
| 271 } | 261 } |
| 272 | 262 |
| 273 void Scheduler::DidLoseOutputSurface() { | 263 void Scheduler::DidLoseOutputSurface() { |
| 274 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); | 264 TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
| 275 state_machine_.DidLoseOutputSurface(); | 265 state_machine_.DidLoseOutputSurface(); |
| 276 if (frame_source_->NeedsBeginFrames()) | 266 if (frame_source_->NeedsBeginFrames()) |
| 277 frame_source_->SetNeedsBeginFrames(false); | 267 frame_source_->SetNeedsBeginFrames(false); |
| 278 begin_retro_frame_args_.clear(); | 268 pending_begin_frame_args_.clear(); |
| 279 ProcessScheduledActions(); | 269 ProcessScheduledActions(); |
| 280 } | 270 } |
| 281 | 271 |
| 282 void Scheduler::DidCreateAndInitializeOutputSurface() { | 272 void Scheduler::DidCreateAndInitializeOutputSurface() { |
| 283 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); | 273 TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
| 284 DCHECK(!frame_source_->NeedsBeginFrames()); | 274 DCHECK(!frame_source_->NeedsBeginFrames()); |
| 285 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); | 275 DCHECK(begin_impl_frame_deadline_task_.IsCancelled()); |
| 276 |
| 286 state_machine_.DidCreateAndInitializeOutputSurface(); | 277 state_machine_.DidCreateAndInitializeOutputSurface(); |
| 287 ProcessScheduledActions(); | 278 ProcessScheduledActions(); |
| 279 |
| 280 // We want to start the first commit ASAP, so we post the LastBeginFrameArgs |
| 281 // onto the retro queue and process it. |
| 282 BeginFrameArgs missed = frame_source_->LastBeginFrameArgs(); |
| 283 missed.type = BeginFrameArgs::MISSED; |
| 284 // Adjust the deadline |
| 285 //missed.deadline = XXXXX |
| 286 OnBeginFrame(missed); |
| 288 } | 287 } |
| 289 | 288 |
| 290 void Scheduler::NotifyBeginMainFrameStarted() { | 289 void Scheduler::NotifyBeginMainFrameStarted() { |
| 291 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); | 290 TRACE_EVENT0("cc", "Scheduler::NotifyBeginMainFrameStarted"); |
| 292 state_machine_.NotifyBeginMainFrameStarted(); | 291 state_machine_.NotifyBeginMainFrameStarted(); |
| 293 } | 292 } |
| 294 | 293 |
| 295 base::TimeTicks Scheduler::AnticipatedDrawTime() const { | |
| 296 if (!frame_source_->NeedsBeginFrames() || | |
| 297 begin_impl_frame_args_.interval <= base::TimeDelta()) | |
| 298 return base::TimeTicks(); | |
| 299 | |
| 300 base::TimeTicks now = Now(); | |
| 301 base::TimeTicks timebase = std::max(begin_impl_frame_args_.frame_time, | |
| 302 begin_impl_frame_args_.deadline); | |
| 303 int64 intervals = 1 + ((now - timebase) / begin_impl_frame_args_.interval); | |
| 304 return timebase + (begin_impl_frame_args_.interval * intervals); | |
| 305 } | |
| 306 | |
| 307 base::TimeTicks Scheduler::LastBeginImplFrameTime() { | |
| 308 return begin_impl_frame_args_.frame_time; | |
| 309 } | |
| 310 | |
| 311 void Scheduler::SetupNextBeginFrameIfNeeded() { | 294 void Scheduler::SetupNextBeginFrameIfNeeded() { |
| 312 if (!task_runner_.get()) | 295 if (!task_runner_.get()) |
| 313 return; | 296 return; |
| 314 | 297 |
| 315 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); | 298 bool needs_begin_frame = state_machine_.BeginFrameNeeded(); |
| 316 | 299 |
| 317 bool at_end_of_deadline = | 300 bool at_end_of_deadline = |
| 318 (state_machine_.begin_impl_frame_state() == | 301 (state_machine_.begin_impl_frame_state() == |
| 319 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); | 302 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE); |
| 320 | 303 |
| 321 bool should_call_set_needs_begin_frame = | 304 bool should_call_set_needs_begin_frame = |
| 322 // Always request the BeginFrame immediately if it wasn't needed before. | 305 // Always request the BeginFrame immediately if it wasn't needed before. |
| 323 (needs_begin_frame && !frame_source_->NeedsBeginFrames()) || | 306 (needs_begin_frame && !frame_source_->NeedsBeginFrames()) || |
| 324 // Only stop requesting BeginFrames after a deadline. | 307 // Only stop requesting BeginFrames after a deadline. |
| 325 (!needs_begin_frame && frame_source_->NeedsBeginFrames() && | 308 (!needs_begin_frame && frame_source_->NeedsBeginFrames() && |
| 326 at_end_of_deadline); | 309 at_end_of_deadline); |
| 327 | 310 |
| 328 if (should_call_set_needs_begin_frame) { | 311 if (should_call_set_needs_begin_frame) { |
| 329 frame_source_->SetNeedsBeginFrames(needs_begin_frame); | 312 frame_source_->SetNeedsBeginFrames(needs_begin_frame); |
| 330 } | 313 } |
| 331 | 314 |
| 332 if (at_end_of_deadline) { | 315 if (at_end_of_deadline) { |
| 333 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | 316 frame_source_->DidFinishFrame(pending_begin_frame_args_.size()); |
| 334 } | 317 } |
| 335 | 318 |
| 336 PostBeginRetroFrameIfNeeded(); | |
| 337 SetupPollingMechanisms(needs_begin_frame); | 319 SetupPollingMechanisms(needs_begin_frame); |
| 338 } | 320 } |
| 339 | 321 |
| 340 // We may need to poll when we can't rely on BeginFrame to advance certain | 322 // We may need to poll when we can't rely on BeginFrame to advance certain |
| 341 // state or to avoid deadlock. | 323 // state or to avoid deadlock. |
| 342 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { | 324 void Scheduler::SetupPollingMechanisms(bool needs_begin_frame) { |
| 343 bool needs_advance_commit_state_timer = false; | 325 bool needs_advance_commit_state_timer = false; |
| 344 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but | 326 // Setup PollForAnticipatedDrawTriggers if we need to monitor state but |
| 345 // aren't expecting any more BeginFrames. This should only be needed by | 327 // aren't expecting any more BeginFrames. This should only be needed by |
| 346 // the synchronous compositor when BeginFrameNeeded is false. | 328 // the synchronous compositor when BeginFrameNeeded is false. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 advance_commit_state_task_.Reset(advance_commit_state_closure_); | 361 advance_commit_state_task_.Reset(advance_commit_state_closure_); |
| 380 task_runner_->PostDelayedTask(FROM_HERE, | 362 task_runner_->PostDelayedTask(FROM_HERE, |
| 381 advance_commit_state_task_.callback(), | 363 advance_commit_state_task_.callback(), |
| 382 begin_impl_frame_args_.interval * 2); | 364 begin_impl_frame_args_.interval * 2); |
| 383 } | 365 } |
| 384 } else { | 366 } else { |
| 385 advance_commit_state_task_.Cancel(); | 367 advance_commit_state_task_.Cancel(); |
| 386 } | 368 } |
| 387 } | 369 } |
| 388 | 370 |
| 371 base::TimeDelta Scheduler::TimeForDrawing() { |
| 372 return EstimatedParentDrawTime() + client_->DrawDurationEstimate(); |
| 373 } |
| 374 |
| 375 base::TimeTicks Scheduler::CalculateDeadline(base::TimeTicks now, const BeginFra
meArgs& args) { |
| 376 // Synchronous renderer should doesn't use deadlines. |
| 377 if (settings_.using_synchronous_renderer_compositor) { |
| 378 return base::TimeTicks(); |
| 379 } |
| 380 |
| 381 base::TimeTicks deadline = args.deadline; |
| 382 |
| 383 // Decrease the deadline enough to give drawing enough time to happen. |
| 384 deadline -= TimeForDrawing(); |
| 385 |
| 386 if (false) { //is_low_end()) { |
| 387 // On low end devices, if we start main thread rendering it can stave us |
| 388 // of CPU. Hence, if we don't think the main will make this frame we should |
| 389 // run the impl tasks right now. |
| 390 base::TimeTicks main_thread_time = |
| 391 client_->BeginMainFrameToCommitDurationEstimate() + |
| 392 client_->CommitToActivateDurationEstimate(); |
| 393 |
| 394 if (now + main_thread_time > deadline) { |
| 395 deadline = now; |
| 396 } |
| 397 } |
| 398 |
| 399 return deadline; |
| 400 } |
| 401 |
| 389 // BeginFrame is the mechanism that tells us that now is a good time to start | 402 // BeginFrame is the mechanism that tells us that now is a good time to start |
| 390 // making a frame. Usually this means that user input for the frame is complete. | 403 // making a frame. Usually this means that user input for the frame is complete. |
| 391 // If the scheduler is busy, we queue the BeginFrame to be handled later as | |
| 392 // a BeginRetroFrame. | |
| 393 bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) { | 404 bool Scheduler::OnBeginFrameMixInDelegate(const BeginFrameArgs& args) { |
| 394 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); | 405 TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue()); |
| 395 | 406 |
| 407 // Push the BeginFrame onto a queue for processing. |
| 408 begin_retro_frame_args.push_back(args); |
| 409 |
| 410 // If we aren't already processing frames, start processing now. |
| 411 if (state_machine_.begin_impl_frame_state() == SchedulerStateMachine::BEGIN_IM
PL_FRAME_STATE_IDLE) { |
| 412 ProcessBeginFrames(nullptr); |
| 413 // Otherwise, post a task to process the frames after the current processing |
| 414 // is finished. |
| 415 } else if (!begin_frame_process_posted_) { |
| 416 begin_frame_process_posted_ = true; |
| 417 task_runner_->PostTask(FROM_HERE, begin_frame_process_closure_, &begin_frame
_process_posted_); |
| 418 } |
| 419 |
| 420 return true; |
| 421 } |
| 422 |
| 423 void Scheduler::ProcessBeginFrames(bool* clear_posted) { |
| 424 DCHECK(!begin_retro_frame_args.empty()); |
| 425 |
| 426 if (clear_posted) { |
| 427 *clear_posted = false; |
| 428 } |
| 429 |
| 430 // Capture now to use for all the deadline calculations |
| 431 base::TimeTicks now = Now(); |
| 432 |
| 433 // If we have multiple frames to process, discard anything which we can't |
| 434 // make it's deadline. |
| 435 while (pending_begin_frame_args_.size() > 1) { |
| 436 const BeginFrameArgs& args = pending_begin_frame_args_.front(); |
| 437 |
| 438 base::TimeTicks deadline = CalculateDeadline(now, args); |
| 439 if (now >= deadline) { |
| 440 TRACE_EVENT_INSTANT2( |
| 441 "cc", "Scheduler::BeginFrame discarding", TRACE_EVENT_SCOPE_THREAD, |
| 442 "expiration_time - now", (deadline - now).InMillisecondsF(), |
| 443 "BeginFrameArgs", args.AsValue()); |
| 444 pending_begin_frame_args_.pop_front(); |
| 445 frame_source_->DidFinishFrame(pending_begin_frame_args_.size()); |
| 446 } |
| 447 } |
| 448 |
| 449 // Process the head of the queue. |
| 450 BeginFrameArgs front_args = pending_begin_frame_args_.front(); |
| 451 pending_begin_frame_args_.pop_front(); |
| 452 front_args.deadline = CalculateDeadline(now, front_args); |
| 453 BeginImplFrame(now, front_args); |
| 454 } |
| 455 |
| 456 |
| 457 void Scheduler::BeginImplFrame(base::TimeTicks now, const BeginFrameArgs& args)
{ |
| 458 // Clear any pending impl frame deadline |
| 459 begin_impl_frame_deadline_task_.Cancel(); |
| 460 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); |
| 461 |
| 462 // TODO(mithro): ????? |
| 396 // Deliver BeginFrames to children. | 463 // Deliver BeginFrames to children. |
| 397 if (settings_.forward_begin_frames_to_children && | 464 if (settings_.forward_begin_frames_to_children && |
| 398 state_machine_.children_need_begin_frames()) { | 465 state_machine_.children_need_begin_frames()) { |
| 399 BeginFrameArgs adjusted_args_for_children(args); | 466 BeginFrameArgs adjusted_args_for_children(args); |
| 400 // Adjust a deadline for child schedulers. | 467 // Adjust a deadline for child schedulers. |
| 401 // TODO(simonhong): Once we have commitless update, we can get rid of | 468 // TODO(simonhong): Once we have commitless update, we can get rid of |
| 402 // BeginMainFrameToCommitDurationEstimate() + | 469 // BeginMainFrameToCommitDurationEstimate() + |
| 403 // CommitToActivateDurationEstimate(). | 470 // CommitToActivateDurationEstimate(). |
| 404 adjusted_args_for_children.deadline -= | 471 adjusted_args_for_children.deadline -= |
| 405 (client_->BeginMainFrameToCommitDurationEstimate() + | 472 (client_->BeginMainFrameToCommitDurationEstimate() + |
| 406 client_->CommitToActivateDurationEstimate() + | 473 client_->CommitToActivateDurationEstimate() + |
| 407 client_->DrawDurationEstimate() + EstimatedParentDrawTime()); | 474 TimeForDrawing()); |
| 408 client_->SendBeginFramesToChildren(adjusted_args_for_children); | 475 client_->SendBeginFramesToChildren(adjusted_args_for_children); |
| 409 } | 476 } |
| 410 | 477 |
| 411 // We have just called SetNeedsBeginFrame(true) and the BeginFrameSource has | 478 // Start the ImplFrame |
| 412 // sent us the last BeginFrame we have missed. As we might not be able to | 479 client_->BeginImplFrame(args); |
| 413 // actually make rendering for this call, handle it like a "retro frame". | 480 |
| 414 // TODO(brainderson): Add a test for this functionality ASAP! | 481 // If we are asked to schedule a deadline in the past, just run the deadline |
| 415 if (args.type == BeginFrameArgs::MISSED) { | 482 // right now. |
| 416 begin_retro_frame_args_.push_back(args); | 483 if (now >= args.deadline) { |
| 417 PostBeginRetroFrameIfNeeded(); | 484 OnBeginImplFrameDeadline(); |
| 418 return true; | 485 return; |
| 419 } | 486 } |
| 420 | 487 |
| 421 BeginFrameArgs adjusted_args(args); | 488 // Else post a task for the deadline |
| 422 adjusted_args.deadline -= EstimatedParentDrawTime(); | |
| 423 | |
| 424 bool should_defer_begin_frame; | |
| 425 if (settings_.using_synchronous_renderer_compositor) { | |
| 426 should_defer_begin_frame = false; | |
| 427 } else { | |
| 428 should_defer_begin_frame = | |
| 429 !begin_retro_frame_args_.empty() || begin_retro_frame_posted_ || | |
| 430 !frame_source_->NeedsBeginFrames() || | |
| 431 (state_machine_.begin_impl_frame_state() != | |
| 432 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | |
| 433 } | |
| 434 | |
| 435 if (should_defer_begin_frame) { | |
| 436 begin_retro_frame_args_.push_back(adjusted_args); | |
| 437 TRACE_EVENT_INSTANT0( | |
| 438 "cc", "Scheduler::BeginFrame deferred", TRACE_EVENT_SCOPE_THREAD); | |
| 439 // Queuing the frame counts as "using it", so we need to return true. | |
| 440 } else { | |
| 441 BeginImplFrame(adjusted_args); | |
| 442 } | |
| 443 return true; | |
| 444 } | |
| 445 | |
| 446 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { | |
| 447 DCHECK(settings_.forward_begin_frames_to_children); | |
| 448 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); | |
| 449 DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE); | |
| 450 } | |
| 451 | |
| 452 // BeginRetroFrame is called for BeginFrames that we've deferred because | |
| 453 // the scheduler was in the middle of processing a previous BeginFrame. | |
| 454 void Scheduler::BeginRetroFrame() { | |
| 455 TRACE_EVENT0("cc", "Scheduler::BeginRetroFrame"); | |
| 456 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
| 457 DCHECK(begin_retro_frame_posted_); | |
| 458 begin_retro_frame_posted_ = false; | |
| 459 | |
| 460 // If there aren't any retroactive BeginFrames, then we've lost the | |
| 461 // OutputSurface and should abort. | |
| 462 if (begin_retro_frame_args_.empty()) | |
| 463 return; | |
| 464 | |
| 465 // Discard expired BeginRetroFrames | |
| 466 // Today, we should always end up with at most one un-expired BeginRetroFrame | |
| 467 // because deadlines will not be greater than the next frame time. We don't | |
| 468 // DCHECK though because some systems don't always have monotonic timestamps. | |
| 469 // TODO(brianderson): In the future, long deadlines could result in us not | |
| 470 // draining the queue if we don't catch up. If we consistently can't catch | |
| 471 // up, our fallback should be to lower our frame rate. | |
| 472 base::TimeTicks now = Now(); | |
| 473 | |
| 474 while (!begin_retro_frame_args_.empty()) { | |
| 475 const BeginFrameArgs& args = begin_retro_frame_args_.front(); | |
| 476 base::TimeTicks expiration_time = args.frame_time + args.interval; | |
| 477 if (now <= expiration_time) | |
| 478 break; | |
| 479 TRACE_EVENT_INSTANT2( | |
| 480 "cc", "Scheduler::BeginRetroFrame discarding", TRACE_EVENT_SCOPE_THREAD, | |
| 481 "expiration_time - now", (expiration_time - now).InMillisecondsF(), | |
| 482 "BeginFrameArgs", begin_retro_frame_args_.front().AsValue()); | |
| 483 begin_retro_frame_args_.pop_front(); | |
| 484 frame_source_->DidFinishFrame(begin_retro_frame_args_.size()); | |
| 485 } | |
| 486 | |
| 487 if (begin_retro_frame_args_.empty()) { | |
| 488 TRACE_EVENT_INSTANT0("cc", | |
| 489 "Scheduler::BeginRetroFrames all expired", | |
| 490 TRACE_EVENT_SCOPE_THREAD); | |
| 491 } else { | |
| 492 BeginFrameArgs front = begin_retro_frame_args_.front(); | |
| 493 begin_retro_frame_args_.pop_front(); | |
| 494 BeginImplFrame(front); | |
| 495 } | |
| 496 } | |
| 497 | |
| 498 // There could be a race between the posted BeginRetroFrame and a new | |
| 499 // BeginFrame arriving via the normal mechanism. Scheduler::BeginFrame | |
| 500 // will check if there is a pending BeginRetroFrame to ensure we handle | |
| 501 // BeginFrames in FIFO order. | |
| 502 void Scheduler::PostBeginRetroFrameIfNeeded() { | |
| 503 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | |
| 504 "Scheduler::PostBeginRetroFrameIfNeeded", | |
| 505 "state", | |
| 506 AsValue()); | |
| 507 if (!frame_source_->NeedsBeginFrames()) | |
| 508 return; | |
| 509 | |
| 510 if (begin_retro_frame_args_.empty() || begin_retro_frame_posted_) | |
| 511 return; | |
| 512 | |
| 513 // begin_retro_frame_args_ should always be empty for the | |
| 514 // synchronous compositor. | |
| 515 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
| 516 | |
| 517 if (state_machine_.begin_impl_frame_state() != | |
| 518 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE) | |
| 519 return; | |
| 520 | |
| 521 begin_retro_frame_posted_ = true; | |
| 522 task_runner_->PostTask(FROM_HERE, begin_retro_frame_closure_); | |
| 523 } | |
| 524 | |
| 525 // BeginImplFrame starts a compositor frame that will wait up until a deadline | |
| 526 // for a BeginMainFrame+activation to complete before it times out and draws | |
| 527 // any asynchronous animation and scroll/pinch updates. | |
| 528 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { | |
| 529 bool main_thread_is_in_high_latency_mode = | |
| 530 state_machine_.MainThreadIsInHighLatencyMode(); | |
| 531 TRACE_EVENT2("cc", | |
| 532 "Scheduler::BeginImplFrame", | |
| 533 "args", | |
| 534 args.AsValue(), | |
| 535 "main_thread_is_high_latency", | |
| 536 main_thread_is_in_high_latency_mode); | |
| 537 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | |
| 538 "MainThreadLatency", | |
| 539 main_thread_is_in_high_latency_mode); | |
| 540 DCHECK_EQ(state_machine_.begin_impl_frame_state(), | |
| 541 SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); | |
| 542 DCHECK(state_machine_.HasInitializedOutputSurface()); | |
| 543 | |
| 544 advance_commit_state_task_.Cancel(); | |
| 545 | |
| 546 base::TimeDelta draw_duration_estimate = client_->DrawDurationEstimate(); | |
| 547 begin_impl_frame_args_ = args; | |
| 548 begin_impl_frame_args_.deadline -= draw_duration_estimate; | |
| 549 | |
| 550 if (!state_machine_.impl_latency_takes_priority() && | |
| 551 main_thread_is_in_high_latency_mode && | |
| 552 CanCommitAndActivateBeforeDeadline()) { | |
| 553 state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); | |
| 554 } | |
| 555 | |
| 556 client_->WillBeginImplFrame(begin_impl_frame_args_); | |
| 557 state_machine_.OnBeginImplFrame(begin_impl_frame_args_); | |
| 558 devtools_instrumentation::DidBeginFrame(layer_tree_host_id_); | |
| 559 | |
| 560 ProcessScheduledActions(); | |
| 561 | |
| 562 state_machine_.OnBeginImplFrameDeadlinePending(); | |
| 563 | |
| 564 if (settings_.using_synchronous_renderer_compositor) { | |
| 565 // The synchronous renderer compositor has to make its GL calls | |
| 566 // within this call. | |
| 567 // TODO(brianderson): Have the OutputSurface initiate the deadline tasks | |
| 568 // so the synchronous renderer compositor can take advantage of splitting | |
| 569 // up the BeginImplFrame and deadline as well. | |
| 570 OnBeginImplFrameDeadline(); | |
| 571 } else { | |
| 572 ScheduleBeginImplFrameDeadline( | |
| 573 AdjustedBeginImplFrameDeadline(args, draw_duration_estimate)); | |
| 574 } | |
| 575 } | |
| 576 | |
| 577 base::TimeTicks Scheduler::AdjustedBeginImplFrameDeadline( | |
| 578 const BeginFrameArgs& args, | |
| 579 base::TimeDelta draw_duration_estimate) const { | |
| 580 // The synchronous compositor does not post a deadline task. | |
| 581 DCHECK(!settings_.using_synchronous_renderer_compositor); | |
| 582 if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { | |
| 583 // We are ready to draw a new active tree immediately. | |
| 584 // We don't use Now() here because it's somewhat expensive to call. | |
| 585 return base::TimeTicks(); | |
| 586 } else if (state_machine_.needs_redraw()) { | |
| 587 // We have an animation or fast input path on the impl thread that wants | |
| 588 // to draw, so don't wait too long for a new active tree. | |
| 589 return args.deadline - draw_duration_estimate; | |
| 590 } else { | |
| 591 // The impl thread doesn't have anything it wants to draw and we are just | |
| 592 // waiting for a new active tree, so post the deadline for the next | |
| 593 // expected BeginImplFrame start. This allows us to draw immediately when | |
| 594 // there is a new active tree, instead of waiting for the next | |
| 595 // BeginImplFrame. | |
| 596 // TODO(brianderson): Handle long deadlines (that are past the next frame's | |
| 597 // frame time) properly instead of using this hack. | |
| 598 return args.frame_time + args.interval; | |
| 599 } | |
| 600 } | |
| 601 | |
| 602 void Scheduler::ScheduleBeginImplFrameDeadline(base::TimeTicks deadline) { | |
| 603 TRACE_EVENT1( | |
| 604 "cc", "Scheduler::ScheduleBeginImplFrameDeadline", "deadline", deadline); | |
| 605 | |
| 606 begin_impl_frame_deadline_task_.Cancel(); | |
| 607 begin_impl_frame_deadline_task_.Reset(begin_impl_frame_deadline_closure_); | |
| 608 | |
| 609 base::TimeDelta delta = deadline - Now(); | |
| 610 if (delta <= base::TimeDelta()) | |
| 611 delta = base::TimeDelta(); | |
| 612 task_runner_->PostDelayedTask( | 489 task_runner_->PostDelayedTask( |
| 613 FROM_HERE, begin_impl_frame_deadline_task_.callback(), delta); | 490 FROM_HERE, begin_impl_frame_deadline_task_.callback(), now - deadline); |
| 614 } | 491 } |
| 615 | 492 |
| 616 void Scheduler::OnBeginImplFrameDeadline() { | 493 void Scheduler::OnBeginImplFrameDeadline() { |
| 617 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); | 494 TRACE_EVENT0("cc", "Scheduler::OnBeginImplFrameDeadline"); |
| 618 begin_impl_frame_deadline_task_.Cancel(); | 495 begin_impl_frame_deadline_task_.Cancel(); |
| 619 | 496 |
| 497 last_begin_impl_frame_args_ = current_begin_impl_frame_args_; |
| 498 |
| 620 // We split the deadline actions up into two phases so the state machine | 499 // We split the deadline actions up into two phases so the state machine |
| 621 // has a chance to trigger actions that should occur durring and after | 500 // has a chance to trigger actions that should occur during and after the |
| 622 // the deadline separately. For example: | 501 // deadline separately. For example: |
| 623 // * Sending the BeginMainFrame will not occur after the deadline in | 502 // * Sending the BeginMainFrame will not occur after the deadline in |
| 624 // order to wait for more user-input before starting the next commit. | 503 // order to wait for more user-input before starting the next commit. |
| 625 // * Creating a new OuputSurface will not occur during the deadline in | 504 // * Creating a new OuputSurface will not occur during the deadline in |
| 626 // order to allow the state machine to "settle" first. | 505 // order to allow the state machine to "settle" first. |
| 627 state_machine_.OnBeginImplFrameDeadline(); | 506 state_machine_.OnBeginImplFrameDeadline(); |
| 628 ProcessScheduledActions(); | 507 ProcessScheduledActions(); |
| 629 state_machine_.OnBeginImplFrameIdle(); | 508 state_machine_.OnBeginImplFrameIdle(); |
| 630 ProcessScheduledActions(); | 509 ProcessScheduledActions(); |
| 631 | 510 |
| 632 client_->DidBeginImplFrameDeadline(); | 511 client_->DidBeginImplFrameDeadline(); |
| 633 } | 512 } |
| 634 | 513 |
| 514 void Scheduler::DidActivateSyncTree() { |
| 515 // Main frame is committed and activated |
| 516 last_main_frame_args_ = current_main_frame_args_; |
| 517 current_main_frame_args_ = BeginFrameArgs(); |
| 518 } |
| 519 |
| 520 BeginFrameArgs Scheduler::GetBeginMainFrameArgs() { |
| 521 // Did the previous main frame meet the deadline? |
| 522 bool last_main_frame_meet_deadline = (last_main_frame_args_.frame_time == last
_impl_frame_args_.frame_time); |
| 523 |
| 524 BeginFrameArgs args(current_impl_frame_args_); |
| 525 // We aren't inside an active impl frame deadline, so we use the values of |
| 526 // the last impl frame. |
| 527 // TODO(mithro): This includes deadline adjustment for draw time which could |
| 528 // instead be given to the main frame. |
| 529 if (!args.is_valid()) { |
| 530 args = last_impl_frame_args_; |
| 531 } |
| 532 |
| 533 // Do we think the main frame can make the deadline? |
| 534 base::TimeDelta main_thread_time = |
| 535 client_->BeginMainFrameToCommitDurationEstimate() + |
| 536 client_->CommitToActivateDurationEstimate(); |
| 537 if (now + main_thread_time <= args.deadline) { |
| 538 // If we think the BeginMainFrame will make the deadline, we should |
| 539 // definitely go ahead. |
| 540 return args; |
| 541 } |
| 542 |
| 543 base::TimeDelta will_missed_deadline_by = now + main_thread_time - args.deadli
ne; |
| 544 |
| 545 /* |
| 546 // If we think the BeginMainFrame will only miss by a little and we made the |
| 547 // last deadline, we are going to give it a go and see if we actually miss. |
| 548 // This exists because our estimates are rough and there is jitter in the |
| 549 // system. |
| 550 bool close_deadline_miss = (will_missed_deadline_by / base::TimeDelta::FromMil
liseconds(1)) == 0; |
| 551 if (last_main_frame_meet_deadline && close_deadline_miss) { |
| 552 return args; |
| 553 } |
| 554 */ |
| 555 |
| 556 // Otherwise, we don't think the BeginMainFrame will make the deadline and |
| 557 // have already missed the last frame. What we do depends on if we think |
| 558 // sending a BeginMainFrame now will effect the next frame's ability to meet |
| 559 // the deadline. |
| 560 |
| 561 // Work out what percentage of an normal interval the main thread rendering |
| 562 // will take. |
| 563 base::TimeDelta time_for_rendering = args.interval - (EstimatedParentDrawTime(
) + client_->DrawDurationEstimate()); |
| 564 double main_percentage_of_rendering_time = main_thread_time.InMillisecondsF()
/ time_for_rendering.InMillisecondsF(); |
| 565 |
| 566 if (main_percentage_of_rendering_time < 0.5) { |
| 567 // As the main thread can render twice a frame, starting rendering is |
| 568 // unlikely to cause us to miss the next frame. Let's try and catch the |
| 569 // main thread up to the impl thread to help with latency. |
| 570 // We keep the expired deadline so main thread knows it not to run any |
| 571 // unimportant tasks. It will have time after we catch back up. |
| 572 return args; |
| 573 } |
| 574 |
| 575 if (main_percentage_of_rendering_time > 1.0) { |
| 576 // Values greater than 1.0 mean the main thread will never make a normal |
| 577 // deadline. |
| 578 |
| 579 // If we could meet 50% of the interval, then we assume that we will do |
| 580 // that and start rendering ASAP. |
| 581 if (main_percentage_of_rendering_time < 2.0) { |
| 582 // Adjust the deadline to the next deadline we think the main thread will |
| 583 // probably make. |
| 584 while (args.deadline + time_for_rendering >= now) { |
| 585 args.deadline += args.interval; |
| 586 } |
| 587 return args; |
| 588 } |
| 589 |
| 590 // If the main thread isn't even going to make 50% frame rate, just target |
| 591 // throughput and render as fast as we can. We clear the deadline to inform |
| 592 // the main thread that we are targeting throughput and want to minimize |
| 593 // context switches. |
| 594 args.deadline = base::TimeTicks(); |
| 595 return args; |
| 596 } |
| 597 |
| 598 // If main_percentage_of_rendering_time is between 0.5 and 1.0, then if we |
| 599 // start rendering too late it will break the next frame too. However, we |
| 600 // have to be careful we don't drop *every* main frame on the floor. |
| 601 |
| 602 // If we are missing the deadline by the "slack" in the next frame, then we |
| 603 // should go ahead. |
| 604 base::TimeDelta slack_in_next_frame = time_for_rendering - main_thread_time; |
| 605 if (will_miss_deadline_by < slack_in_next_frame) { |
| 606 // We don't adjust the deadline because we want this main frame to return |
| 607 // as early as possible to give the next main frame as much chance as |
| 608 // possible. |
| 609 return args; |
| 610 } |
| 611 |
| 612 if (last_main_frame_meet_deadline == DROPPED) { |
| 613 // Drop this main frame to allow the next main frame to start as soon as |
| 614 // the BeginFrame message occurs. |
| 615 return args; |
| 616 } else { |
| 617 return BeginFrameArgs(); |
| 618 } |
| 619 } |
| 620 |
| 621 void Scheduler::SetChildrenNeedBeginFrames(bool children_need_begin_frames) { |
| 622 DCHECK(settings_.forward_begin_frames_to_children); |
| 623 state_machine_.SetChildrenNeedBeginFrames(children_need_begin_frames); |
| 624 DCHECK_EQ(state_machine_.NextAction(), SchedulerStateMachine::ACTION_NONE); |
| 625 } |
| 626 |
| 627 |
| 635 void Scheduler::PollForAnticipatedDrawTriggers() { | 628 void Scheduler::PollForAnticipatedDrawTriggers() { |
| 636 TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers"); | 629 TRACE_EVENT0("cc", "Scheduler::PollForAnticipatedDrawTriggers"); |
| 637 poll_for_draw_triggers_task_.Cancel(); | 630 poll_for_draw_triggers_task_.Cancel(); |
| 638 state_machine_.DidEnterPollForAnticipatedDrawTriggers(); | 631 state_machine_.DidEnterPollForAnticipatedDrawTriggers(); |
| 639 ProcessScheduledActions(); | 632 ProcessScheduledActions(); |
| 640 state_machine_.DidLeavePollForAnticipatedDrawTriggers(); | 633 state_machine_.DidLeavePollForAnticipatedDrawTriggers(); |
| 641 } | 634 } |
| 642 | 635 |
| 643 void Scheduler::PollToAdvanceCommitState() { | 636 void Scheduler::PollToAdvanceCommitState() { |
| 644 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); | 637 TRACE_EVENT0("cc", "Scheduler::PollToAdvanceCommitState"); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 672 state_machine_.UpdateState(action); | 665 state_machine_.UpdateState(action); |
| 673 base::AutoReset<SchedulerStateMachine::Action> | 666 base::AutoReset<SchedulerStateMachine::Action> |
| 674 mark_inside_action(&inside_action_, action); | 667 mark_inside_action(&inside_action_, action); |
| 675 switch (action) { | 668 switch (action) { |
| 676 case SchedulerStateMachine::ACTION_NONE: | 669 case SchedulerStateMachine::ACTION_NONE: |
| 677 break; | 670 break; |
| 678 case SchedulerStateMachine::ACTION_ANIMATE: | 671 case SchedulerStateMachine::ACTION_ANIMATE: |
| 679 client_->ScheduledActionAnimate(); | 672 client_->ScheduledActionAnimate(); |
| 680 break; | 673 break; |
| 681 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: | 674 case SchedulerStateMachine::ACTION_SEND_BEGIN_MAIN_FRAME: |
| 675 |
| 676 // FIXME:!!!!!!! |
| 677 BeginFrameArgs args = GetBeginMainFrameArgs(); |
| 678 if (!args.IsValid()) |
| 679 continue; |
| 680 current_main_frame_args_ = args; |
| 681 // FIXME:!!!!!!! |
| 682 |
| 682 client_->ScheduledActionSendBeginMainFrame(); | 683 client_->ScheduledActionSendBeginMainFrame(); |
| 683 break; | 684 break; |
| 684 case SchedulerStateMachine::ACTION_COMMIT: | 685 case SchedulerStateMachine::ACTION_COMMIT: |
| 685 client_->ScheduledActionCommit(); | 686 client_->ScheduledActionCommit(); |
| 686 break; | 687 break; |
| 687 case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE: | 688 case SchedulerStateMachine::ACTION_ACTIVATE_SYNC_TREE: |
| 688 client_->ScheduledActionActivateSyncTree(); | 689 client_->ScheduledActionActivateSyncTree(); |
| 689 break; | 690 break; |
| 690 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: | 691 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: |
| 691 DrawAndSwapIfPossible(); | 692 DrawAndSwapIfPossible(); |
| 692 break; | 693 break; |
| 693 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: | 694 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: |
| 694 client_->ScheduledActionDrawAndSwapForced(); | 695 client_->ScheduledActionDrawAndSwapForced(); |
| 695 break; | 696 break; |
| 696 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: | 697 case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: |
| 697 // No action is actually performed, but this allows the state machine to | 698 // No action is actually performed, but this allows the state machine to |
| 698 // advance out of its waiting to draw state without actually drawing. | 699 // advance out of its waiting to draw state without actually drawing. |
| 699 break; | 700 break; |
| 700 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: | 701 case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
| 701 client_->ScheduledActionBeginOutputSurfaceCreation(); | 702 client_->ScheduledActionBeginOutputSurfaceCreation(); |
| 702 break; | 703 break; |
| 703 case SchedulerStateMachine::ACTION_MANAGE_TILES: | 704 case SchedulerStateMachine::ACTION_MANAGE_TILES: |
| 704 client_->ScheduledActionManageTiles(); | 705 client_->ScheduledActionManageTiles(); |
| 705 break; | 706 break; |
| 706 } | 707 } |
| 707 } while (action != SchedulerStateMachine::ACTION_NONE); | 708 } while (action != SchedulerStateMachine::ACTION_NONE); |
| 708 | 709 |
| 709 SetupNextBeginFrameIfNeeded(); | 710 SetupNextBeginFrameIfNeeded(); |
| 710 client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); | |
| 711 | |
| 712 if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { | 711 if (state_machine_.ShouldTriggerBeginImplFrameDeadlineEarly()) { |
| 713 DCHECK(!settings_.using_synchronous_renderer_compositor); | 712 DCHECK(!settings_.using_synchronous_renderer_compositor); |
| 714 ScheduleBeginImplFrameDeadline(base::TimeTicks()); | 713 OnBeginImplFrameDeadline(); |
| 715 } | 714 } |
| 716 } | 715 } |
| 717 | 716 |
| 718 bool Scheduler::WillDrawIfNeeded() const { | 717 bool Scheduler::WillDrawIfNeeded() const { |
| 719 return !state_machine_.PendingDrawsShouldBeAborted(); | 718 return !state_machine_.PendingDrawsShouldBeAborted(); |
| 720 } | 719 } |
| 721 | 720 |
| 722 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() | 721 scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue() |
| 723 const { | 722 const { |
| 724 scoped_refptr<base::debug::TracedValue> state = | 723 scoped_refptr<base::debug::TracedValue> state = |
| (...skipping 18 matching lines...) Expand all Loading... |
| 743 state->EndDictionary(); | 742 state->EndDictionary(); |
| 744 } | 743 } |
| 745 | 744 |
| 746 state->BeginDictionary("scheduler_state"); | 745 state->BeginDictionary("scheduler_state"); |
| 747 state->SetDouble("time_until_anticipated_draw_time_ms", | 746 state->SetDouble("time_until_anticipated_draw_time_ms", |
| 748 (AnticipatedDrawTime() - Now()).InMillisecondsF()); | 747 (AnticipatedDrawTime() - Now()).InMillisecondsF()); |
| 749 state->SetDouble("estimated_parent_draw_time_ms", | 748 state->SetDouble("estimated_parent_draw_time_ms", |
| 750 estimated_parent_draw_time_.InMillisecondsF()); | 749 estimated_parent_draw_time_.InMillisecondsF()); |
| 751 state->SetBoolean("last_set_needs_begin_frame_", | 750 state->SetBoolean("last_set_needs_begin_frame_", |
| 752 frame_source_->NeedsBeginFrames()); | 751 frame_source_->NeedsBeginFrames()); |
| 753 state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_); | 752 state->SetBoolean("begin_frame_process_posted_", begin_frame_process_posted_); |
| 754 state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size()); | 753 state->SetInteger("pending_begin_frame_args_", pending_begin_frame_args_.size(
)); |
| 755 state->SetBoolean("begin_impl_frame_deadline_task_", | 754 state->SetBoolean("begin_impl_frame_deadline_task_", |
| 756 !begin_impl_frame_deadline_task_.IsCancelled()); | 755 !begin_impl_frame_deadline_task_.IsCancelled()); |
| 757 state->SetBoolean("poll_for_draw_triggers_task_", | 756 state->SetBoolean("poll_for_draw_triggers_task_", |
| 758 !poll_for_draw_triggers_task_.IsCancelled()); | 757 !poll_for_draw_triggers_task_.IsCancelled()); |
| 759 state->SetBoolean("advance_commit_state_task_", | 758 state->SetBoolean("advance_commit_state_task_", |
| 760 !advance_commit_state_task_.IsCancelled()); | 759 !advance_commit_state_task_.IsCancelled()); |
| 761 state->BeginDictionary("begin_impl_frame_args"); | 760 state->BeginDictionary("begin_impl_frame_args"); |
| 762 begin_impl_frame_args_.AsValueInto(state); | 761 begin_impl_frame_args_.AsValueInto(state); |
| 763 state->EndDictionary(); | 762 state->EndDictionary(); |
| 764 | 763 |
| 765 state->EndDictionary(); | 764 state->EndDictionary(); |
| 766 | 765 |
| 767 state->BeginDictionary("client_state"); | 766 state->BeginDictionary("client_state"); |
| 768 state->SetDouble("draw_duration_estimate_ms", | 767 state->SetDouble("draw_duration_estimate_ms", |
| 769 client_->DrawDurationEstimate().InMillisecondsF()); | 768 client_->DrawDurationEstimate().InMillisecondsF()); |
| 770 state->SetDouble( | 769 state->SetDouble( |
| 771 "begin_main_frame_to_commit_duration_estimate_ms", | 770 "begin_main_frame_to_commit_duration_estimate_ms", |
| 772 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); | 771 client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF()); |
| 773 state->SetDouble( | 772 state->SetDouble( |
| 774 "commit_to_activate_duration_estimate_ms", | 773 "commit_to_activate_duration_estimate_ms", |
| 775 client_->CommitToActivateDurationEstimate().InMillisecondsF()); | 774 client_->CommitToActivateDurationEstimate().InMillisecondsF()); |
| 776 state->EndDictionary(); | 775 state->EndDictionary(); |
| 777 } | 776 } |
| 778 | 777 |
| 779 bool Scheduler::CanCommitAndActivateBeforeDeadline() const { | |
| 780 // Check if the main thread computation and commit can be finished before the | |
| 781 // impl thread's deadline. | |
| 782 base::TimeTicks estimated_draw_time = | |
| 783 begin_impl_frame_args_.frame_time + | |
| 784 client_->BeginMainFrameToCommitDurationEstimate() + | |
| 785 client_->CommitToActivateDurationEstimate(); | |
| 786 | |
| 787 TRACE_EVENT2( | |
| 788 TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), | |
| 789 "CanCommitAndActivateBeforeDeadline", | |
| 790 "time_left_after_drawing_ms", | |
| 791 (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(), | |
| 792 "state", | |
| 793 AsValue()); | |
| 794 | |
| 795 return estimated_draw_time < begin_impl_frame_args_.deadline; | |
| 796 } | |
| 797 | |
| 798 bool Scheduler::IsBeginMainFrameSentOrStarted() const { | 778 bool Scheduler::IsBeginMainFrameSentOrStarted() const { |
| 799 return (state_machine_.commit_state() == | 779 return (state_machine_.commit_state() == |
| 800 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || | 780 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_SENT || |
| 801 state_machine_.commit_state() == | 781 state_machine_.commit_state() == |
| 802 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); | 782 SchedulerStateMachine::COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED); |
| 803 } | 783 } |
| 804 | 784 |
| 805 } // namespace cc | 785 } // namespace cc |
| OLD | NEW |