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 3 // found in the LICENSE file. 4 5 #include "cc/trees/single_thread_proxy.h" 6 7 #include "base/auto_reset.h" 8 #include "base/debug/trace_event.h" 9 #include "cc/debug/benchmark_instrumentation.h" 10 #include "cc/output/context_provider.h" 11 #include "cc/output/output_surface.h" 12 #include "cc/quads/draw_quad.h" 13 #include "cc/resources/prioritized_resource_manager.h" 14 #include "cc/resources/resource_update_controller.h" 15 #include "cc/trees/blocking_task_runner.h" 16 #include "cc/trees/layer_tree_host.h" 17 #include "cc/trees/layer_tree_host_single_thread_client.h" 18 #include "cc/trees/layer_tree_impl.h" 19 #include "cc/trees/scoped_abort_remaining_swap_promises.h" 20 #include "ui/gfx/frame_time.h" 21 22 namespace cc { 23 24 scoped_ptr<Proxy> SingleThreadProxy::Create( 25 LayerTreeHost* layer_tree_host, 26 LayerTreeHostSingleThreadClient* client, 27 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) { 28 return make_scoped_ptr( 29 new SingleThreadProxy(layer_tree_host, client, main_task_runner)) 30 .PassAs<Proxy>(); 31 } 32 33 SingleThreadProxy::SingleThreadProxy( 34 LayerTreeHost* layer_tree_host, 35 LayerTreeHostSingleThreadClient* client, 36 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) 37 : Proxy(main_task_runner, NULL), 38 layer_tree_host_(layer_tree_host), 39 client_(client), 40 timing_history_(layer_tree_host->rendering_stats_instrumentation()), 41 next_frame_is_newly_committed_frame_(false), 42 inside_draw_(false), 43 defer_commits_(false), 44 commit_was_deferred_(false), 45 commit_requested_(false), 46 weak_factory_(this) { 47 TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy"); 48 DCHECK(Proxy::IsMainThread()); 49 DCHECK(layer_tree_host); 50 51 // Impl-side painting not supported without threaded compositing. 52 CHECK(!layer_tree_host->settings().impl_side_painting) 53 << "Threaded compositing must be enabled to use impl-side painting."; 54 } 55 56 void SingleThreadProxy::Start() { 57 DebugScopedSetImplThread impl(this); 58 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this); 59 } 60 61 SingleThreadProxy::~SingleThreadProxy() { 62 TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy"); 63 DCHECK(Proxy::IsMainThread()); 64 // Make sure Stop() got called or never Started. 65 DCHECK(!layer_tree_host_impl_); 66 } 67 68 void SingleThreadProxy::FinishAllRendering() { 69 TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering"); 70 DCHECK(Proxy::IsMainThread()); 71 { 72 DebugScopedSetImplThread impl(this); 73 layer_tree_host_impl_->FinishAllRendering(); 74 } 75 } 76 77 bool SingleThreadProxy::IsStarted() const { 78 DCHECK(Proxy::IsMainThread()); 79 return layer_tree_host_impl_; 80 } 81 82 void SingleThreadProxy::SetLayerTreeHostClientReady() { 83 TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady"); 84 // Scheduling is controlled by the embedder in the single thread case, so 85 // nothing to do. 86 DCHECK(Proxy::IsMainThread()); 87 DebugScopedSetImplThread impl(this); 88 if (layer_tree_host_->settings().single_thread_proxy_scheduler && 89 !scheduler_on_impl_thread_) { 90 SchedulerSettings scheduler_settings(layer_tree_host_->settings()); 91 scheduler_on_impl_thread_ = Scheduler::Create(this, 92 scheduler_settings, 93 layer_tree_host_->id(), 94 MainThreadTaskRunner()); 95 scheduler_on_impl_thread_->SetCanStart(); 96 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); 97 } 98 } 99 100 void SingleThreadProxy::SetVisible(bool visible) { 101 TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible"); 102 DebugScopedSetImplThread impl(this); 103 layer_tree_host_impl_->SetVisible(visible); 104 if (scheduler_on_impl_thread_) 105 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); 106 // Changing visibility could change ShouldComposite(). 107 UpdateBackgroundAnimateTicking(); 108 } 109 110 void SingleThreadProxy::RequestNewOutputSurface() { 111 DCHECK(Proxy::IsMainThread()); 112 DCHECK(layer_tree_host_->output_surface_lost()); 113 layer_tree_host_->RequestNewOutputSurface(); 114 } 115 116 void SingleThreadProxy::SetOutputSurface( 117 scoped_ptr<OutputSurface> output_surface) { 118 DCHECK(Proxy::IsMainThread()); 119 DCHECK(layer_tree_host_->output_surface_lost()); 120 renderer_capabilities_for_main_thread_ = RendererCapabilities(); 121 122 bool success = !!output_surface; 123 if (success) { 124 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 125 DebugScopedSetImplThread impl(this); 126 layer_tree_host_->DeleteContentsTexturesOnImplThread( 127 layer_tree_host_impl_->resource_provider()); 128 success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass()); 129 } 130 131 layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success); 132 133 if (success) { 134 if (scheduler_on_impl_thread_) 135 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface(); 136 } else if (Proxy::MainThreadTaskRunner()) { 137 MainThreadTaskRunner()->PostTask( 138 FROM_HERE, 139 base::Bind(&SingleThreadProxy::RequestNewOutputSurface, 140 weak_factory_.GetWeakPtr())); 141 } 142 } 143 144 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const { 145 DCHECK(Proxy::IsMainThread()); 146 DCHECK(!layer_tree_host_->output_surface_lost()); 147 return renderer_capabilities_for_main_thread_; 148 } 149 150 void SingleThreadProxy::SetNeedsAnimate() { 151 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate"); 152 DCHECK(Proxy::IsMainThread()); 153 client_->ScheduleAnimation(); 154 SetNeedsCommit(); 155 } 156 157 void SingleThreadProxy::SetNeedsUpdateLayers() { 158 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers"); 159 DCHECK(Proxy::IsMainThread()); 160 SetNeedsCommit(); 161 } 162 163 void SingleThreadProxy::DoCommit(const BeginFrameArgs& begin_frame_args) { 164 TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit"); 165 DCHECK(Proxy::IsMainThread()); 166 layer_tree_host_->WillBeginMainFrame(); 167 layer_tree_host_->BeginMainFrame(begin_frame_args); 168 layer_tree_host_->AnimateLayers(begin_frame_args.frame_time); 169 layer_tree_host_->Layout(); 170 commit_requested_ = false; 171 172 if (PrioritizedResourceManager* contents_texture_manager = 173 layer_tree_host_->contents_texture_manager()) { 174 contents_texture_manager->UnlinkAndClearEvictedBackings(); 175 contents_texture_manager->SetMaxMemoryLimitBytes( 176 layer_tree_host_impl_->memory_allocation_limit_bytes()); 177 contents_texture_manager->SetExternalPriorityCutoff( 178 layer_tree_host_impl_->memory_allocation_priority_cutoff()); 179 } 180 181 scoped_ptr<ResourceUpdateQueue> queue = 182 make_scoped_ptr(new ResourceUpdateQueue); 183 184 layer_tree_host_->UpdateLayers(queue.get()); 185 186 layer_tree_host_->WillCommit(); 187 188 // Commit immediately. 189 { 190 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 191 DebugScopedSetImplThread impl(this); 192 193 // This CapturePostTasks should be destroyed before CommitComplete() is 194 // called since that goes out to the embedder, and we want the embedder 195 // to receive its callbacks before that. 196 BlockingTaskRunner::CapturePostTasks blocked( 197 blocking_main_thread_task_runner()); 198 199 layer_tree_host_impl_->BeginCommit(); 200 201 if (PrioritizedResourceManager* contents_texture_manager = 202 layer_tree_host_->contents_texture_manager()) { 203 contents_texture_manager->PushTexturePrioritiesToBackings(); 204 } 205 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get()); 206 207 scoped_ptr<ResourceUpdateController> update_controller = 208 ResourceUpdateController::Create( 209 NULL, 210 MainThreadTaskRunner(), 211 queue.Pass(), 212 layer_tree_host_impl_->resource_provider()); 213 update_controller->Finalize(); 214 215 if (layer_tree_host_impl_->EvictedUIResourcesExist()) 216 layer_tree_host_->RecreateUIResources(); 217 218 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get()); 219 220 layer_tree_host_impl_->CommitComplete(); 221 222 UpdateBackgroundAnimateTicking(); 223 224 #if DCHECK_IS_ON 225 // In the single-threaded case, the scale and scroll deltas should never be 226 // touched on the impl layer tree. 227 scoped_ptr<ScrollAndScaleSet> scroll_info = 228 layer_tree_host_impl_->ProcessScrollDeltas(); 229 DCHECK(!scroll_info->scrolls.size()); 230 DCHECK_EQ(1.f, scroll_info->page_scale_delta); 231 #endif 232 233 RenderingStatsInstrumentation* stats_instrumentation = 234 layer_tree_host_->rendering_stats_instrumentation(); 235 benchmark_instrumentation::IssueMainThreadRenderingStatsEvent( 236 stats_instrumentation->main_thread_rendering_stats()); 237 stats_instrumentation->AccumulateAndClearMainThreadStats(); 238 } 239 layer_tree_host_->CommitComplete(); 240 layer_tree_host_->DidBeginMainFrame(); 241 timing_history_.DidCommit(); 242 243 next_frame_is_newly_committed_frame_ = true; 244 } 245 246 void SingleThreadProxy::SetNeedsCommit() { 247 DCHECK(Proxy::IsMainThread()); 248 DebugScopedSetImplThread impl(this); 249 client_->ScheduleComposite(); 250 if (scheduler_on_impl_thread_) 251 scheduler_on_impl_thread_->SetNeedsCommit(); 252 commit_requested_ = true; 253 } 254 255 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) { 256 TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw"); 257 DCHECK(Proxy::IsMainThread()); 258 DebugScopedSetImplThread impl(this); 259 client_->ScheduleComposite(); 260 SetNeedsRedrawRectOnImplThread(damage_rect); 261 } 262 263 void SingleThreadProxy::SetNextCommitWaitsForActivation() { 264 // There is no activation here other than commit. So do nothing. 265 DCHECK(Proxy::IsMainThread()); 266 } 267 268 void SingleThreadProxy::SetDeferCommits(bool defer_commits) { 269 DCHECK(Proxy::IsMainThread()); 270 // Deferring commits only makes sense if there's a scheduler. 271 if (!scheduler_on_impl_thread_) 272 return; 273 if (defer_commits_ == defer_commits) 274 return; 275 276 if (defer_commits) 277 TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this); 278 else 279 TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this); 280 281 defer_commits_ = defer_commits; 282 if (!defer_commits_ && commit_was_deferred_) { 283 commit_was_deferred_ = false; 284 BeginMainFrame(); 285 } 286 } 287 288 bool SingleThreadProxy::CommitRequested() const { 289 DCHECK(Proxy::IsMainThread()); 290 return commit_requested_; 291 } 292 293 bool SingleThreadProxy::BeginMainFrameRequested() const { 294 DCHECK(Proxy::IsMainThread()); 295 // If there is no scheduler, then there can be no pending begin frame, 296 // as all frames are all manually initiated by the embedder of cc. 297 if (!scheduler_on_impl_thread_) 298 return false; 299 return commit_requested_; 300 } 301 302 size_t SingleThreadProxy::MaxPartialTextureUpdates() const { 303 return std::numeric_limits<size_t>::max(); 304 } 305 306 void SingleThreadProxy::Stop() { 307 TRACE_EVENT0("cc", "SingleThreadProxy::stop"); 308 DCHECK(Proxy::IsMainThread()); 309 { 310 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 311 DebugScopedSetImplThread impl(this); 312 313 BlockingTaskRunner::CapturePostTasks blocked( 314 blocking_main_thread_task_runner()); 315 layer_tree_host_->DeleteContentsTexturesOnImplThread( 316 layer_tree_host_impl_->resource_provider()); 317 scheduler_on_impl_thread_.reset(); 318 layer_tree_host_impl_.reset(); 319 } 320 layer_tree_host_ = NULL; 321 } 322 323 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) { 324 TRACE_EVENT1( 325 "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw); 326 DCHECK(Proxy::IsImplThread()); 327 UpdateBackgroundAnimateTicking(); 328 if (scheduler_on_impl_thread_) 329 scheduler_on_impl_thread_->SetCanDraw(can_draw); 330 } 331 332 void SingleThreadProxy::NotifyReadyToActivate() { 333 // Impl-side painting only. 334 NOTREACHED(); 335 } 336 337 void SingleThreadProxy::SetNeedsRedrawOnImplThread() { 338 client_->ScheduleComposite(); 339 if (scheduler_on_impl_thread_) 340 scheduler_on_impl_thread_->SetNeedsRedraw(); 341 } 342 343 void SingleThreadProxy::SetNeedsAnimateOnImplThread() { 344 SetNeedsRedrawOnImplThread(); 345 } 346 347 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() { 348 // Impl-side painting only. 349 NOTREACHED(); 350 } 351 352 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread( 353 const gfx::Rect& damage_rect) { 354 layer_tree_host_impl_->SetViewportDamage(damage_rect); 355 SetNeedsRedrawOnImplThread(); 356 } 357 358 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() { 359 // Impl-side painting only. 360 NOTREACHED(); 361 } 362 363 void SingleThreadProxy::SetNeedsCommitOnImplThread() { 364 client_->ScheduleComposite(); 365 if (scheduler_on_impl_thread_) 366 scheduler_on_impl_thread_->SetNeedsCommit(); 367 } 368 369 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread( 370 scoped_ptr<AnimationEventsVector> events) { 371 TRACE_EVENT0( 372 "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread"); 373 DCHECK(Proxy::IsImplThread()); 374 DebugScopedSetMainThread main(this); 375 layer_tree_host_->SetAnimationEvents(events.Pass()); 376 } 377 378 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread( 379 size_t limit_bytes, 380 int priority_cutoff) { 381 DCHECK(IsImplThread()); 382 PrioritizedResourceManager* contents_texture_manager = 383 layer_tree_host_->contents_texture_manager(); 384 385 ResourceProvider* resource_provider = 386 layer_tree_host_impl_->resource_provider(); 387 388 if (!contents_texture_manager || !resource_provider) 389 return false; 390 391 return contents_texture_manager->ReduceMemoryOnImplThread( 392 limit_bytes, priority_cutoff, resource_provider); 393 } 394 395 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; } 396 397 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() { 398 DCHECK(IsImplThread()); 399 renderer_capabilities_for_main_thread_ = 400 layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities(); 401 } 402 403 void SingleThreadProxy::DidManageTiles() { 404 // Impl-side painting only. 405 NOTREACHED(); 406 } 407 408 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() { 409 TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread"); 410 { 411 DebugScopedSetMainThread main(this); 412 // This must happen before we notify the scheduler as it may try to recreate 413 // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE. 414 layer_tree_host_->DidLoseOutputSurface(); 415 } 416 client_->DidAbortSwapBuffers(); 417 if (scheduler_on_impl_thread_) 418 scheduler_on_impl_thread_->DidLoseOutputSurface(); 419 } 420 421 void SingleThreadProxy::DidSwapBuffersOnImplThread() { 422 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread"); 423 if (scheduler_on_impl_thread_) 424 scheduler_on_impl_thread_->DidSwapBuffers(); 425 client_->DidPostSwapBuffers(); 426 } 427 428 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() { 429 TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread"); 430 if (scheduler_on_impl_thread_) 431 scheduler_on_impl_thread_->DidSwapBuffersComplete(); 432 layer_tree_host_->DidCompleteSwapBuffers(); 433 } 434 435 void SingleThreadProxy::BeginFrame(const BeginFrameArgs& args) { 436 TRACE_EVENT0("cc", "SingleThreadProxy::BeginFrame"); 437 if (scheduler_on_impl_thread_) 438 scheduler_on_impl_thread_->BeginFrame(args); 439 } 440 441 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) { 442 TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately"); 443 DCHECK(Proxy::IsMainThread()); 444 DCHECK(!layer_tree_host_->output_surface_lost()); 445 446 BeginFrameArgs begin_frame_args = BeginFrameArgs::Create( 447 frame_begin_time, base::TimeTicks(), BeginFrameArgs::DefaultInterval()); 448 DoCommit(begin_frame_args); 449 450 LayerTreeHostImpl::FrameData frame; 451 DoComposite(frame_begin_time, &frame); 452 } 453 454 void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const { 455 // The following line casts away const modifiers because it is just 456 // setting debug state. We still want the AsValue() function and its 457 // call chain to be const throughout. 458 DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this)); 459 460 state->BeginDictionary("layer_tree_host_impl"); 461 layer_tree_host_impl_->AsValueInto(state); 462 state->EndDictionary(); 463 } 464 465 void SingleThreadProxy::ForceSerializeOnSwapBuffers() { 466 { 467 DebugScopedSetImplThread impl(this); 468 if (layer_tree_host_impl_->renderer()) { 469 DCHECK(!layer_tree_host_->output_surface_lost()); 470 layer_tree_host_impl_->renderer()->DoNoOp(); 471 } 472 } 473 } 474 475 bool SingleThreadProxy::SupportsImplScrolling() const { 476 return false; 477 } 478 479 bool SingleThreadProxy::ShouldComposite() const { 480 DCHECK(Proxy::IsImplThread()); 481 return layer_tree_host_impl_->visible() && 482 layer_tree_host_impl_->CanDraw(); 483 } 484 485 void SingleThreadProxy::UpdateBackgroundAnimateTicking() { 486 DCHECK(Proxy::IsImplThread()); 487 layer_tree_host_impl_->UpdateBackgroundAnimateTicking( 488 !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer()); 489 } 490 491 DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time, 492 LayerTreeHostImpl::FrameData* frame) { 493 TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite"); 494 DCHECK(!layer_tree_host_->output_surface_lost()); 495 496 { 497 DebugScopedSetImplThread impl(this); 498 base::AutoReset<bool> mark_inside(&inside_draw_, true); 499 500 // We guard PrepareToDraw() with CanDraw() because it always returns a valid 501 // frame, so can only be used when such a frame is possible. Since 502 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on 503 // CanDraw() as well. 504 if (!ShouldComposite()) { 505 UpdateBackgroundAnimateTicking(); 506 return DRAW_ABORTED_CANT_DRAW; 507 } 508 509 timing_history_.DidStartDrawing(); 510 511 layer_tree_host_impl_->Animate( 512 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time); 513 UpdateBackgroundAnimateTicking(); 514 515 layer_tree_host_impl_->PrepareToDraw(frame); 516 layer_tree_host_impl_->DrawLayers(frame, frame_begin_time); 517 layer_tree_host_impl_->DidDrawAllLayers(*frame); 518 519 bool start_ready_animations = true; 520 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations); 521 522 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame(); 523 524 timing_history_.DidFinishDrawing(); 525 } 526 527 { 528 DebugScopedSetImplThread impl(this); 529 530 // This CapturePostTasks should be destroyed before 531 // DidCommitAndDrawFrame() is called since that goes out to the 532 // embedder, 533 // and we want the embedder to receive its callbacks before that. 534 // NOTE: This maintains consistent ordering with the ThreadProxy since 535 // the DidCommitAndDrawFrame() must be post-tasked from the impl thread 536 // there as the main thread is not blocked, so any posted tasks inside 537 // the swap buffers will execute first. 538 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 539 540 BlockingTaskRunner::CapturePostTasks blocked( 541 blocking_main_thread_task_runner()); 542 layer_tree_host_impl_->SwapBuffers(*frame); 543 } 544 DidCommitAndDrawFrame(); 545 546 return DRAW_SUCCESS; 547 } 548 549 void SingleThreadProxy::DidCommitAndDrawFrame() { 550 if (next_frame_is_newly_committed_frame_) { 551 DebugScopedSetMainThread main(this); 552 next_frame_is_newly_committed_frame_ = false; 553 layer_tree_host_->DidCommitAndDrawFrame(); 554 } 555 } 556 557 bool SingleThreadProxy::MainFrameWillHappenForTesting() { 558 return false; 559 } 560 561 void SingleThreadProxy::SetNeedsBeginFrame(bool enable) { 562 layer_tree_host_impl_->SetNeedsBeginFrame(enable); 563 } 564 565 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) { 566 layer_tree_host_impl_->WillBeginImplFrame(args); 567 } 568 569 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() { 570 TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame"); 571 // Although this proxy is single-threaded, it's problematic to synchronously 572 // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame. This 573 // could cause a commit to occur in between a series of SetNeedsCommit calls 574 // (i.e. property modifications) causing some to fall on one frame and some to 575 // fall on the next. Doing it asynchronously instead matches the semantics of 576 // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a 577 // synchronous commit. 578 MainThreadTaskRunner()->PostTask( 579 FROM_HERE, 580 base::Bind(&SingleThreadProxy::BeginMainFrame, 581 weak_factory_.GetWeakPtr())); 582 } 583 584 void SingleThreadProxy::BeginMainFrame() { 585 if (defer_commits_) { 586 DCHECK(!commit_was_deferred_); 587 commit_was_deferred_ = true; 588 layer_tree_host_->DidDeferCommit(); 589 return; 590 } 591 592 // This checker assumes NotifyReadyToCommit below causes a synchronous commit. 593 ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_); 594 595 if (!layer_tree_host_->visible()) { 596 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD); 597 BeginMainFrameAbortedOnImplThread(); 598 return; 599 } 600 601 if (layer_tree_host_->output_surface_lost()) { 602 TRACE_EVENT_INSTANT0( 603 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD); 604 BeginMainFrameAbortedOnImplThread(); 605 return; 606 } 607 608 timing_history_.DidBeginMainFrame(); 609 610 DCHECK(scheduler_on_impl_thread_); 611 scheduler_on_impl_thread_->NotifyBeginMainFrameStarted(); 612 scheduler_on_impl_thread_->NotifyReadyToCommit(); 613 } 614 615 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread() { 616 DebugScopedSetImplThread impl(this); 617 DCHECK(scheduler_on_impl_thread_->CommitPending()); 618 DCHECK(!layer_tree_host_impl_->pending_tree()); 619 620 // TODO(enne): SingleThreadProxy does not support cancelling commits yet so 621 // did_handle is always false. 622 bool did_handle = false; 623 layer_tree_host_impl_->BeginMainFrameAborted(did_handle); 624 scheduler_on_impl_thread_->BeginMainFrameAborted(did_handle); 625 } 626 627 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() { 628 DebugScopedSetImplThread impl(this); 629 LayerTreeHostImpl::FrameData frame; 630 return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time, 631 &frame); 632 } 633 634 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() { 635 NOTREACHED(); 636 return INVALID_RESULT; 637 } 638 639 void SingleThreadProxy::ScheduledActionCommit() { 640 DebugScopedSetMainThread main(this); 641 DoCommit(layer_tree_host_impl_->CurrentBeginFrameArgs()); 642 } 643 644 void SingleThreadProxy::ScheduledActionAnimate() { 645 TRACE_EVENT0("cc", "ScheduledActionAnimate"); 646 layer_tree_host_impl_->Animate( 647 layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time); 648 } 649 650 void SingleThreadProxy::ScheduledActionUpdateVisibleTiles() { 651 // Impl-side painting only. 652 NOTREACHED(); 653 } 654 655 void SingleThreadProxy::ScheduledActionActivateSyncTree() { 656 } 657 658 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() { 659 DebugScopedSetMainThread main(this); 660 DCHECK(scheduler_on_impl_thread_); 661 // If possible, create the output surface in a post task. Synchronously 662 // creating the output surface makes tests more awkward since this differs 663 // from the ThreadProxy behavior. However, sometimes there is no 664 // task runner. 665 if (Proxy::MainThreadTaskRunner()) { 666 MainThreadTaskRunner()->PostTask( 667 FROM_HERE, 668 base::Bind(&SingleThreadProxy::RequestNewOutputSurface, 669 weak_factory_.GetWeakPtr())); 670 } else { 671 RequestNewOutputSurface(); 672 } 673 } 674 675 void SingleThreadProxy::ScheduledActionManageTiles() { 676 // Impl-side painting only. 677 NOTREACHED(); 678 } 679 680 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { 681 } 682 683 base::TimeDelta SingleThreadProxy::DrawDurationEstimate() { 684 return timing_history_.DrawDurationEstimate(); 685 } 686 687 base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() { 688 return timing_history_.BeginMainFrameToCommitDurationEstimate(); 689 } 690 691 base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() { 692 return timing_history_.CommitToActivateDurationEstimate(); 693 } 694 695 void SingleThreadProxy::DidBeginImplFrameDeadline() { 696 layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame(); 697 } 698 699 } // namespace cc 700