thread_proxy.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
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/thread_proxy.h" 6 7#include <algorithm> 8#include <string> 9 10#include "base/auto_reset.h" 11#include "base/bind.h" 12#include "base/debug/trace_event.h" 13#include "base/debug/trace_event_synthetic_delay.h" 14#include "base/metrics/histogram.h" 15#include "cc/base/swap_promise.h" 16#include "cc/debug/benchmark_instrumentation.h" 17#include "cc/debug/devtools_instrumentation.h" 18#include "cc/input/input_handler.h" 19#include "cc/output/context_provider.h" 20#include "cc/output/output_surface.h" 21#include "cc/quads/draw_quad.h" 22#include "cc/resources/prioritized_resource_manager.h" 23#include "cc/scheduler/delay_based_time_source.h" 24#include "cc/scheduler/frame_rate_controller.h" 25#include "cc/scheduler/scheduler.h" 26#include "cc/trees/blocking_task_runner.h" 27#include "cc/trees/layer_tree_host.h" 28#include "cc/trees/layer_tree_impl.h" 29#include "ui/gfx/frame_time.h" 30 31namespace { 32 33// Measured in seconds. 34const double kSmoothnessTakesPriorityExpirationDelay = 0.25; 35 36class SwapPromiseChecker { 37 public: 38 explicit SwapPromiseChecker(cc::LayerTreeHost* layer_tree_host) 39 : layer_tree_host_(layer_tree_host) {} 40 41 ~SwapPromiseChecker() { 42 layer_tree_host_->BreakSwapPromises(cc::SwapPromise::COMMIT_FAILS); 43 } 44 45 private: 46 cc::LayerTreeHost* layer_tree_host_; 47}; 48 49} // namespace 50 51namespace cc { 52 53struct ThreadProxy::ReadbackRequest { 54 CompletionEvent completion; 55 bool success; 56 void* pixels; 57 gfx::Rect rect; 58}; 59 60struct ThreadProxy::CommitPendingRequest { 61 CompletionEvent completion; 62 bool commit_pending; 63}; 64 65struct ThreadProxy::SchedulerStateRequest { 66 CompletionEvent completion; 67 scoped_ptr<base::Value> state; 68}; 69 70scoped_ptr<Proxy> ThreadProxy::Create( 71 LayerTreeHost* layer_tree_host, 72 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { 73 return make_scoped_ptr(new ThreadProxy(layer_tree_host, impl_task_runner)) 74 .PassAs<Proxy>(); 75} 76 77ThreadProxy::ThreadProxy( 78 LayerTreeHost* layer_tree_host, 79 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) 80 : Proxy(impl_task_runner), 81 main_thread_only_vars_unsafe_(this, layer_tree_host->id()), 82 main_thread_or_blocked_vars_unsafe_(layer_tree_host), 83 compositor_thread_vars_unsafe_(this, layer_tree_host->id()) { 84 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy"); 85 DCHECK(IsMainThread()); 86 DCHECK(this->layer_tree_host()); 87} 88 89ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy, 90 int layer_tree_host_id) 91 : layer_tree_host_id(layer_tree_host_id), 92 animate_requested(false), 93 commit_requested(false), 94 commit_request_sent_to_impl_thread(false), 95 created_offscreen_context_provider(false), 96 started(false), 97 textures_acquired(true), 98 in_composite_and_readback(false), 99 manage_tiles_pending(false), 100 can_cancel_commit(true), 101 defer_commits(false), 102 weak_factory(proxy) {} 103 104ThreadProxy::MainThreadOnly::~MainThreadOnly() {} 105 106ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread( 107 LayerTreeHost* host) 108 : layer_tree_host(host), 109 commit_waits_for_activation(false), 110 main_thread_inside_commit(false) {} 111 112ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {} 113 114PrioritizedResourceManager* 115ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() { 116 return layer_tree_host->contents_texture_manager(); 117} 118 119ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(ThreadProxy* proxy, 120 int layer_tree_host_id) 121 : layer_tree_host_id(layer_tree_host_id), 122 contents_texture_manager(NULL), 123 begin_main_frame_sent_completion_event(NULL), 124 readback_request(NULL), 125 commit_completion_event(NULL), 126 completion_event_for_commit_held_on_tree_activation(NULL), 127 texture_acquisition_completion_event(NULL), 128 next_frame_is_newly_committed_frame(false), 129 inside_draw(false), 130 input_throttled_until_commit(false), 131 animations_frozen_until_next_draw(false), 132 renew_tree_priority_pending(false), 133 weak_factory(proxy) {} 134 135ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {} 136 137ThreadProxy::~ThreadProxy() { 138 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy"); 139 DCHECK(IsMainThread()); 140 DCHECK(!main().started); 141} 142 143bool ThreadProxy::CompositeAndReadback(void* pixels, const gfx::Rect& rect) { 144 TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback"); 145 DCHECK(IsMainThread()); 146 DCHECK(layer_tree_host()); 147 148 if (main().defer_commits) { 149 TRACE_EVENT0("cc", "CompositeAndReadback_DeferCommit"); 150 return false; 151 } 152 153 if (!layer_tree_host()->InitializeOutputSurfaceIfNeeded()) { 154 TRACE_EVENT_INSTANT0("cc", 155 "CompositeAndReadback_EarlyOut_LR_Uninitialized", 156 TRACE_EVENT_SCOPE_THREAD); 157 return false; 158 } 159 160 // Perform a synchronous commit with an associated readback. 161 ReadbackRequest request; 162 request.rect = rect; 163 request.pixels = pixels; 164 { 165 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 166 CompletionEvent begin_main_frame_sent_completion; 167 Proxy::ImplThreadTaskRunner()->PostTask( 168 FROM_HERE, 169 base::Bind(&ThreadProxy::ForceCommitForReadbackOnImplThread, 170 impl_thread_weak_ptr_, 171 &begin_main_frame_sent_completion, 172 &request)); 173 begin_main_frame_sent_completion.Wait(); 174 } 175 176 main().in_composite_and_readback = true; 177 // This is the forced commit. 178 // Note: The Impl thread also queues a separate BeginMainFrame on the 179 // main thread, which will be called after this CompositeAndReadback 180 // completes, to replace the forced commit. 181 BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState>()); 182 main().in_composite_and_readback = false; 183 184 // Composite and readback requires a second commit to undo any changes 185 // that it made. 186 main().can_cancel_commit = false; 187 188 request.completion.Wait(); 189 return request.success; 190} 191 192void ThreadProxy::ForceCommitForReadbackOnImplThread( 193 CompletionEvent* begin_main_frame_sent_completion, 194 ReadbackRequest* request) { 195 TRACE_EVENT0("cc", "ThreadProxy::ForceCommitForReadbackOnImplThread"); 196 DCHECK(IsImplThread()); 197 DCHECK(!impl().begin_main_frame_sent_completion_event); 198 DCHECK(!impl().readback_request); 199 200 if (!impl().layer_tree_host_impl) { 201 begin_main_frame_sent_completion->Signal(); 202 request->success = false; 203 request->completion.Signal(); 204 return; 205 } 206 207 impl().readback_request = request; 208 209 impl().scheduler->SetNeedsForcedCommitForReadback(); 210 if (impl().scheduler->IsBeginMainFrameSent()) { 211 begin_main_frame_sent_completion->Signal(); 212 return; 213 } 214 215 impl().begin_main_frame_sent_completion_event = 216 begin_main_frame_sent_completion; 217} 218 219void ThreadProxy::FinishAllRendering() { 220 DCHECK(Proxy::IsMainThread()); 221 DCHECK(!main().defer_commits); 222 223 // Make sure all GL drawing is finished on the impl thread. 224 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 225 CompletionEvent completion; 226 Proxy::ImplThreadTaskRunner()->PostTask( 227 FROM_HERE, 228 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread, 229 impl_thread_weak_ptr_, 230 &completion)); 231 completion.Wait(); 232} 233 234bool ThreadProxy::IsStarted() const { 235 DCHECK(Proxy::IsMainThread()); 236 return main().started; 237} 238 239void ThreadProxy::SetLayerTreeHostClientReady() { 240 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady"); 241 Proxy::ImplThreadTaskRunner()->PostTask( 242 FROM_HERE, 243 base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread, 244 impl_thread_weak_ptr_)); 245} 246 247void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() { 248 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread"); 249 impl().scheduler->SetCanStart(); 250} 251 252void ThreadProxy::SetVisible(bool visible) { 253 TRACE_EVENT0("cc", "ThreadProxy::SetVisible"); 254 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 255 256 CompletionEvent completion; 257 Proxy::ImplThreadTaskRunner()->PostTask( 258 FROM_HERE, 259 base::Bind(&ThreadProxy::SetVisibleOnImplThread, 260 impl_thread_weak_ptr_, 261 &completion, 262 visible)); 263 completion.Wait(); 264} 265 266void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion, 267 bool visible) { 268 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread"); 269 impl().layer_tree_host_impl->SetVisible(visible); 270 impl().scheduler->SetVisible(visible); 271 UpdateBackgroundAnimateTicking(); 272 completion->Signal(); 273} 274 275void ThreadProxy::UpdateBackgroundAnimateTicking() { 276 bool should_background_tick = 277 !impl().scheduler->WillDrawIfNeeded() && 278 impl().layer_tree_host_impl->active_tree()->root_layer(); 279 impl().layer_tree_host_impl->UpdateBackgroundAnimateTicking( 280 should_background_tick); 281 if (should_background_tick) 282 impl().animations_frozen_until_next_draw = false; 283} 284 285void ThreadProxy::DoCreateAndInitializeOutputSurface() { 286 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface"); 287 DCHECK(IsMainThread()); 288 289 scoped_ptr<OutputSurface> output_surface = 290 layer_tree_host()->CreateOutputSurface(); 291 292 RendererCapabilities capabilities; 293 bool success = !!output_surface; 294 if (!success) { 295 OnOutputSurfaceInitializeAttempted(false, capabilities); 296 return; 297 } 298 299 scoped_refptr<ContextProvider> offscreen_context_provider; 300 if (main().created_offscreen_context_provider) { 301 offscreen_context_provider = 302 layer_tree_host()->client()->OffscreenContextProvider(); 303 success = !!offscreen_context_provider.get(); 304 if (!success) { 305 OnOutputSurfaceInitializeAttempted(false, capabilities); 306 return; 307 } 308 } 309 310 success = false; 311 { 312 // Make a blocking call to InitializeOutputSurfaceOnImplThread. The results 313 // of that call are pushed into the success and capabilities local 314 // variables. 315 CompletionEvent completion; 316 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 317 318 Proxy::ImplThreadTaskRunner()->PostTask( 319 FROM_HERE, 320 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread, 321 impl_thread_weak_ptr_, 322 &completion, 323 base::Passed(&output_surface), 324 offscreen_context_provider, 325 &success, 326 &capabilities)); 327 completion.Wait(); 328 } 329 330 OnOutputSurfaceInitializeAttempted(success, capabilities); 331} 332 333void ThreadProxy::SetRendererCapabilitiesMainThreadCopy( 334 const RendererCapabilities& capabilities) { 335 main().renderer_capabilities_main_thread_copy = capabilities; 336} 337 338void ThreadProxy::OnOutputSurfaceInitializeAttempted( 339 bool success, 340 const RendererCapabilities& capabilities) { 341 DCHECK(IsMainThread()); 342 DCHECK(layer_tree_host()); 343 344 if (success) { 345 main().renderer_capabilities_main_thread_copy = capabilities; 346 } 347 348 LayerTreeHost::CreateResult result = 349 layer_tree_host()->OnCreateAndInitializeOutputSurfaceAttempted(success); 350 if (result == LayerTreeHost::CreateFailedButTryAgain) { 351 if (!main().output_surface_creation_callback.callback().is_null()) { 352 Proxy::MainThreadTaskRunner()->PostTask( 353 FROM_HERE, main().output_surface_creation_callback.callback()); 354 } 355 } else { 356 main().output_surface_creation_callback.Cancel(); 357 } 358} 359 360void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() { 361 DCHECK(IsMainThread()); 362 if (main().commit_request_sent_to_impl_thread) 363 return; 364 main().commit_request_sent_to_impl_thread = true; 365 Proxy::ImplThreadTaskRunner()->PostTask( 366 FROM_HERE, 367 base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread, 368 impl_thread_weak_ptr_)); 369} 370 371const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const { 372 DCHECK(IsMainThread()); 373 DCHECK(!layer_tree_host()->output_surface_lost()); 374 return main().renderer_capabilities_main_thread_copy; 375} 376 377void ThreadProxy::SetNeedsAnimate() { 378 DCHECK(IsMainThread()); 379 if (main().animate_requested) 380 return; 381 382 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate"); 383 main().animate_requested = true; 384 SendCommitRequestToImplThreadIfNeeded(); 385} 386 387void ThreadProxy::SetNeedsUpdateLayers() { 388 DCHECK(IsMainThread()); 389 390 if (main().commit_request_sent_to_impl_thread) 391 return; 392 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers"); 393 394 SendCommitRequestToImplThreadIfNeeded(); 395} 396 397void ThreadProxy::SetNeedsCommit() { 398 DCHECK(IsMainThread()); 399 // Unconditionally set here to handle SetNeedsCommit calls during a commit. 400 main().can_cancel_commit = false; 401 402 if (main().commit_requested) 403 return; 404 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit"); 405 main().commit_requested = true; 406 407 SendCommitRequestToImplThreadIfNeeded(); 408} 409 410void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() { 411 DCHECK(IsImplThread()); 412 Proxy::MainThreadTaskRunner()->PostTask( 413 FROM_HERE, 414 base::Bind(&ThreadProxy::SetRendererCapabilitiesMainThreadCopy, 415 main_thread_weak_ptr_, 416 impl() 417 .layer_tree_host_impl->GetRendererCapabilities() 418 .MainThreadCapabilities())); 419} 420 421void ThreadProxy::DidLoseOutputSurfaceOnImplThread() { 422 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread"); 423 DCHECK(IsImplThread()); 424 CheckOutputSurfaceStatusOnImplThread(); 425} 426 427void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() { 428 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread"); 429 DCHECK(IsImplThread()); 430 if (!impl().layer_tree_host_impl->IsContextLost()) 431 return; 432 if (ContextProvider* offscreen_contexts = 433 impl().layer_tree_host_impl->offscreen_context_provider()) 434 offscreen_contexts->VerifyContexts(); 435 impl().scheduler->DidLoseOutputSurface(); 436} 437 438void ThreadProxy::OnSwapBuffersCompleteOnImplThread() { 439 TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread"); 440 DCHECK(IsImplThread()); 441 Proxy::MainThreadTaskRunner()->PostTask( 442 FROM_HERE, 443 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_)); 444} 445 446void ThreadProxy::SetNeedsBeginImplFrame(bool enable) { 447 TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginImplFrame", "enable", enable); 448 DCHECK(IsImplThread()); 449 impl().layer_tree_host_impl->SetNeedsBeginImplFrame(enable); 450 UpdateBackgroundAnimateTicking(); 451} 452 453void ThreadProxy::BeginImplFrame(const BeginFrameArgs& args) { 454 TRACE_EVENT0("cc", "ThreadProxy::BeginImplFrame"); 455 DCHECK(IsImplThread()); 456 457 // Sample the frame time now. This time will be used for updating animations 458 // when we draw. 459 impl().layer_tree_host_impl->CurrentFrameTimeTicks(); 460 461 impl().scheduler->BeginImplFrame(args); 462} 463 464void ThreadProxy::OnCanDrawStateChanged(bool can_draw) { 465 TRACE_EVENT1( 466 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw); 467 DCHECK(IsImplThread()); 468 impl().scheduler->SetCanDraw(can_draw); 469 UpdateBackgroundAnimateTicking(); 470} 471 472void ThreadProxy::NotifyReadyToActivate() { 473 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate"); 474 impl().scheduler->NotifyReadyToActivate(); 475} 476 477void ThreadProxy::SetNeedsCommitOnImplThread() { 478 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread"); 479 DCHECK(IsImplThread()); 480 impl().scheduler->SetNeedsCommit(); 481} 482 483void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread( 484 scoped_ptr<AnimationEventsVector> events) { 485 TRACE_EVENT0("cc", 486 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread"); 487 DCHECK(IsImplThread()); 488 Proxy::MainThreadTaskRunner()->PostTask( 489 FROM_HERE, 490 base::Bind(&ThreadProxy::SetAnimationEvents, 491 main_thread_weak_ptr_, 492 base::Passed(&events))); 493} 494 495bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes, 496 int priority_cutoff) { 497 DCHECK(IsImplThread()); 498 499 if (!impl().contents_texture_manager) 500 return false; 501 if (!impl().layer_tree_host_impl->resource_provider()) 502 return false; 503 504 bool reduce_result = 505 impl().contents_texture_manager->ReduceMemoryOnImplThread( 506 limit_bytes, 507 priority_cutoff, 508 impl().layer_tree_host_impl->resource_provider()); 509 if (!reduce_result) 510 return false; 511 512 // The texture upload queue may reference textures that were just purged, 513 // clear them from the queue. 514 if (impl().current_resource_update_controller) { 515 impl() 516 .current_resource_update_controller->DiscardUploadsToEvictedResources(); 517 } 518 return true; 519} 520 521void ThreadProxy::SendManagedMemoryStats() { 522 DCHECK(IsImplThread()); 523 if (!impl().layer_tree_host_impl) 524 return; 525 if (!impl().contents_texture_manager) 526 return; 527 528 // If we are using impl-side painting, then SendManagedMemoryStats is called 529 // directly after the tile manager's manage function, and doesn't need to 530 // interact with main thread's layer tree. 531 if (impl().layer_tree_host_impl->settings().impl_side_painting) 532 return; 533 534 impl().layer_tree_host_impl->SendManagedMemoryStats( 535 impl().contents_texture_manager->MemoryVisibleBytes(), 536 impl().contents_texture_manager->MemoryVisibleAndNearbyBytes(), 537 impl().contents_texture_manager->MemoryUseBytes()); 538} 539 540bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; } 541 542void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) { 543 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw"); 544 DCHECK(IsMainThread()); 545 Proxy::ImplThreadTaskRunner()->PostTask( 546 FROM_HERE, 547 base::Bind(&ThreadProxy::SetNeedsRedrawRectOnImplThread, 548 impl_thread_weak_ptr_, 549 damage_rect)); 550} 551 552void ThreadProxy::SetNextCommitWaitsForActivation() { 553 DCHECK(IsMainThread()); 554 DCHECK(!blocked_main().main_thread_inside_commit); 555 blocked_main().commit_waits_for_activation = true; 556} 557 558void ThreadProxy::SetDeferCommits(bool defer_commits) { 559 DCHECK(IsMainThread()); 560 DCHECK_NE(main().defer_commits, defer_commits); 561 main().defer_commits = defer_commits; 562 563 if (main().defer_commits) 564 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this); 565 else 566 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this); 567 568 if (!main().defer_commits && main().pending_deferred_commit) 569 Proxy::MainThreadTaskRunner()->PostTask( 570 FROM_HERE, 571 base::Bind(&ThreadProxy::BeginMainFrame, 572 main_thread_weak_ptr_, 573 base::Passed(&main().pending_deferred_commit))); 574} 575 576bool ThreadProxy::CommitRequested() const { 577 DCHECK(IsMainThread()); 578 return main().commit_requested; 579} 580 581bool ThreadProxy::BeginMainFrameRequested() const { 582 DCHECK(IsMainThread()); 583 return main().commit_request_sent_to_impl_thread; 584} 585 586void ThreadProxy::SetNeedsRedrawOnImplThread() { 587 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread"); 588 DCHECK(IsImplThread()); 589 impl().scheduler->SetNeedsRedraw(); 590} 591 592void ThreadProxy::SetNeedsManageTilesOnImplThread() { 593 DCHECK(IsImplThread()); 594 impl().scheduler->SetNeedsManageTiles(); 595} 596 597void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) { 598 DCHECK(IsImplThread()); 599 impl().layer_tree_host_impl->SetViewportDamage(damage_rect); 600 SetNeedsRedrawOnImplThread(); 601} 602 603void ThreadProxy::SetSwapUsedIncompleteTileOnImplThread( 604 bool used_incomplete_tile) { 605 DCHECK(IsImplThread()); 606 if (used_incomplete_tile) { 607 TRACE_EVENT_INSTANT0("cc", 608 "ThreadProxy::SetSwapUsedIncompleteTileOnImplThread", 609 TRACE_EVENT_SCOPE_THREAD); 610 } 611 impl().scheduler->SetSwapUsedIncompleteTile(used_incomplete_tile); 612} 613 614void ThreadProxy::DidInitializeVisibleTileOnImplThread() { 615 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread"); 616 DCHECK(IsImplThread()); 617 impl().scheduler->SetNeedsRedraw(); 618} 619 620void ThreadProxy::MainThreadHasStoppedFlinging() { 621 DCHECK(IsMainThread()); 622 Proxy::ImplThreadTaskRunner()->PostTask( 623 FROM_HERE, 624 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread, 625 impl_thread_weak_ptr_)); 626} 627 628void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() { 629 DCHECK(IsImplThread()); 630 impl().layer_tree_host_impl->MainThreadHasStoppedFlinging(); 631} 632 633void ThreadProxy::NotifyInputThrottledUntilCommit() { 634 DCHECK(IsMainThread()); 635 Proxy::ImplThreadTaskRunner()->PostTask( 636 FROM_HERE, 637 base::Bind(&ThreadProxy::SetInputThrottledUntilCommitOnImplThread, 638 impl_thread_weak_ptr_, 639 true)); 640} 641 642void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(bool is_throttled) { 643 DCHECK(IsImplThread()); 644 if (is_throttled == impl().input_throttled_until_commit) 645 return; 646 impl().input_throttled_until_commit = is_throttled; 647 RenewTreePriority(); 648} 649 650LayerTreeHost* ThreadProxy::layer_tree_host() { 651 return blocked_main().layer_tree_host; 652} 653 654const LayerTreeHost* ThreadProxy::layer_tree_host() const { 655 return blocked_main().layer_tree_host; 656} 657 658ThreadProxy::MainThreadOnly& ThreadProxy::main() { 659 DCHECK(IsMainThread()); 660 return main_thread_only_vars_unsafe_; 661} 662const ThreadProxy::MainThreadOnly& ThreadProxy::main() const { 663 DCHECK(IsMainThread()); 664 return main_thread_only_vars_unsafe_; 665} 666 667ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() { 668 DCHECK(IsMainThread() || IsMainThreadBlocked()); 669 return main_thread_or_blocked_vars_unsafe_; 670} 671 672const ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() 673 const { 674 DCHECK(IsMainThread() || IsMainThreadBlocked()); 675 return main_thread_or_blocked_vars_unsafe_; 676} 677 678ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() { 679 DCHECK(IsImplThread()); 680 return compositor_thread_vars_unsafe_; 681} 682 683const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const { 684 DCHECK(IsImplThread()); 685 return compositor_thread_vars_unsafe_; 686} 687 688void ThreadProxy::Start() { 689 DCHECK(IsMainThread()); 690 DCHECK(Proxy::HasImplThread()); 691 692 // Create LayerTreeHostImpl. 693 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 694 CompletionEvent completion; 695 Proxy::ImplThreadTaskRunner()->PostTask( 696 FROM_HERE, 697 base::Bind(&ThreadProxy::InitializeImplOnImplThread, 698 base::Unretained(this), 699 &completion)); 700 completion.Wait(); 701 702 main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr(); 703 704 main().started = true; 705} 706 707void ThreadProxy::Stop() { 708 TRACE_EVENT0("cc", "ThreadProxy::Stop"); 709 DCHECK(IsMainThread()); 710 DCHECK(main().started); 711 712 // Synchronously finishes pending GL operations and deletes the impl. 713 // The two steps are done as separate post tasks, so that tasks posted 714 // by the GL implementation due to the Finish can be executed by the 715 // renderer before shutting it down. 716 { 717 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 718 719 CompletionEvent completion; 720 Proxy::ImplThreadTaskRunner()->PostTask( 721 FROM_HERE, 722 base::Bind(&ThreadProxy::FinishGLOnImplThread, 723 impl_thread_weak_ptr_, 724 &completion)); 725 completion.Wait(); 726 } 727 { 728 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 729 730 CompletionEvent completion; 731 Proxy::ImplThreadTaskRunner()->PostTask( 732 FROM_HERE, 733 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread, 734 impl_thread_weak_ptr_, 735 &completion)); 736 completion.Wait(); 737 } 738 739 main().weak_factory.InvalidateWeakPtrs(); 740 blocked_main().layer_tree_host = NULL; 741 main().started = false; 742} 743 744void ThreadProxy::ForceSerializeOnSwapBuffers() { 745 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 746 CompletionEvent completion; 747 Proxy::ImplThreadTaskRunner()->PostTask( 748 FROM_HERE, 749 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread, 750 impl_thread_weak_ptr_, 751 &completion)); 752 completion.Wait(); 753} 754 755void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread( 756 CompletionEvent* completion) { 757 if (impl().layer_tree_host_impl->renderer()) 758 impl().layer_tree_host_impl->renderer()->DoNoOp(); 759 completion->Signal(); 760} 761 762void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) { 763 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread"); 764 DCHECK(IsImplThread()); 765 impl().layer_tree_host_impl->FinishAllRendering(); 766 completion->Signal(); 767} 768 769void ThreadProxy::ScheduledActionSendBeginMainFrame() { 770 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginMainFrame"); 771 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state( 772 new BeginMainFrameAndCommitState); 773 begin_main_frame_state->monotonic_frame_begin_time = 774 impl().layer_tree_host_impl->CurrentPhysicalTimeTicks(); 775 begin_main_frame_state->scroll_info = 776 impl().layer_tree_host_impl->ProcessScrollDeltas(); 777 778 if (!impl().layer_tree_host_impl->settings().impl_side_painting) { 779 DCHECK_GT(impl().layer_tree_host_impl->memory_allocation_limit_bytes(), 0u); 780 } 781 begin_main_frame_state->memory_allocation_limit_bytes = 782 impl().layer_tree_host_impl->memory_allocation_limit_bytes(); 783 begin_main_frame_state->memory_allocation_priority_cutoff = 784 impl().layer_tree_host_impl->memory_allocation_priority_cutoff(); 785 begin_main_frame_state->evicted_ui_resources = 786 impl().layer_tree_host_impl->EvictedUIResourcesExist(); 787 Proxy::MainThreadTaskRunner()->PostTask( 788 FROM_HERE, 789 base::Bind(&ThreadProxy::BeginMainFrame, 790 main_thread_weak_ptr_, 791 base::Passed(&begin_main_frame_state))); 792 devtools_instrumentation::DidRequestMainThreadFrame( 793 impl().layer_tree_host_id); 794 if (impl().begin_main_frame_sent_completion_event) { 795 impl().begin_main_frame_sent_completion_event->Signal(); 796 impl().begin_main_frame_sent_completion_event = NULL; 797 } 798 impl().timing_history.DidBeginMainFrame(); 799} 800 801void ThreadProxy::BeginMainFrame( 802 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) { 803 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame"); 804 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame"); 805 DCHECK(IsMainThread()); 806 807 if (!layer_tree_host()) 808 return; 809 810 if (main().defer_commits) { 811 main().pending_deferred_commit = begin_main_frame_state.Pass(); 812 layer_tree_host()->DidDeferCommit(); 813 TRACE_EVENT_INSTANT0( 814 "cc", "EarlyOut_DeferCommits", TRACE_EVENT_SCOPE_THREAD); 815 return; 816 } 817 818 // If the commit finishes, LayerTreeHost will transfer its swap promises to 819 // LayerTreeImpl. The destructor of SwapPromiseChecker checks LayerTressHost's 820 // swap promises. 821 SwapPromiseChecker swap_promise_checker(layer_tree_host()); 822 823 // Do not notify the impl thread of commit requests that occur during 824 // the apply/animate/layout part of the BeginMainFrameAndCommit process since 825 // those commit requests will get painted immediately. Once we have done 826 // the paint, main().commit_requested will be set to false to allow new commit 827 // requests to be scheduled. 828 main().commit_requested = true; 829 main().commit_request_sent_to_impl_thread = true; 830 831 // On the other hand, the AnimationRequested flag needs to be cleared 832 // here so that any animation requests generated by the apply or animate 833 // callbacks will trigger another frame. 834 main().animate_requested = false; 835 836 if (!main().in_composite_and_readback && !layer_tree_host()->visible()) { 837 main().commit_requested = false; 838 main().commit_request_sent_to_impl_thread = false; 839 840 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD); 841 bool did_handle = false; 842 Proxy::ImplThreadTaskRunner()->PostTask( 843 FROM_HERE, 844 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread, 845 impl_thread_weak_ptr_, 846 did_handle)); 847 return; 848 } 849 850 if (begin_main_frame_state) { 851 layer_tree_host()->ApplyScrollAndScale( 852 *begin_main_frame_state->scroll_info); 853 } 854 855 layer_tree_host()->WillBeginMainFrame(); 856 857 if (begin_main_frame_state) { 858 layer_tree_host()->UpdateClientAnimations( 859 begin_main_frame_state->monotonic_frame_begin_time); 860 layer_tree_host()->AnimateLayers( 861 begin_main_frame_state->monotonic_frame_begin_time); 862 blocked_main().last_monotonic_frame_begin_time = 863 begin_main_frame_state->monotonic_frame_begin_time; 864 } 865 866 // Unlink any backings that the impl thread has evicted, so that we know to 867 // re-paint them in UpdateLayers. 868 if (blocked_main().contents_texture_manager()) { 869 blocked_main().contents_texture_manager()->UnlinkAndClearEvictedBackings(); 870 871 if (begin_main_frame_state) { 872 blocked_main().contents_texture_manager()->SetMaxMemoryLimitBytes( 873 begin_main_frame_state->memory_allocation_limit_bytes); 874 blocked_main().contents_texture_manager()->SetExternalPriorityCutoff( 875 begin_main_frame_state->memory_allocation_priority_cutoff); 876 } 877 } 878 879 // Recreate all UI resources if there were evicted UI resources when the impl 880 // thread initiated the commit. 881 bool evicted_ui_resources = begin_main_frame_state 882 ? begin_main_frame_state->evicted_ui_resources 883 : false; 884 if (evicted_ui_resources) 885 layer_tree_host()->RecreateUIResources(); 886 887 layer_tree_host()->Layout(); 888 TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame"); 889 890 // Clear the commit flag after updating animations and layout here --- objects 891 // that only layout when painted will trigger another SetNeedsCommit inside 892 // UpdateLayers. 893 main().commit_requested = false; 894 main().commit_request_sent_to_impl_thread = false; 895 bool can_cancel_this_commit = main().can_cancel_commit && 896 !main().in_composite_and_readback && 897 !evicted_ui_resources; 898 main().can_cancel_commit = true; 899 900 scoped_ptr<ResourceUpdateQueue> queue = 901 make_scoped_ptr(new ResourceUpdateQueue); 902 903 bool updated = layer_tree_host()->UpdateLayers(queue.get()); 904 905 // Once single buffered layers are committed, they cannot be modified until 906 // they are drawn by the impl thread. 907 main().textures_acquired = false; 908 909 layer_tree_host()->WillCommit(); 910 911 // Before calling animate, we set main().animate_requested to false. If it is 912 // true now, it means SetNeedAnimate was called again, but during a state when 913 // main().commit_request_sent_to_impl_thread = true. We need to force that 914 // call to happen again now so that the commit request is sent to the impl 915 // thread. 916 if (main().animate_requested) { 917 // Forces SetNeedsAnimate to consider posting a commit task. 918 main().animate_requested = false; 919 SetNeedsAnimate(); 920 } 921 922 if (!updated && can_cancel_this_commit) { 923 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD); 924 bool did_handle = true; 925 Proxy::ImplThreadTaskRunner()->PostTask( 926 FROM_HERE, 927 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread, 928 impl_thread_weak_ptr_, 929 did_handle)); 930 931 // Although the commit is internally aborted, this is because it has been 932 // detected to be a no-op. From the perspective of an embedder, this commit 933 // went through, and input should no longer be throttled, etc. 934 layer_tree_host()->CommitComplete(); 935 layer_tree_host()->DidBeginMainFrame(); 936 return; 937 } 938 939 scoped_refptr<ContextProvider> offscreen_context_provider; 940 if (main().renderer_capabilities_main_thread_copy.using_offscreen_context3d && 941 layer_tree_host()->needs_offscreen_context()) { 942 offscreen_context_provider = 943 layer_tree_host()->client()->OffscreenContextProvider(); 944 if (offscreen_context_provider.get()) 945 main().created_offscreen_context_provider = true; 946 } 947 948 // Notify the impl thread that the main thread is ready to commit. This will 949 // begin the commit process, which is blocking from the main thread's 950 // point of view, but asynchronously performed on the impl thread, 951 // coordinated by the Scheduler. 952 { 953 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit"); 954 955 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 956 957 // This CapturePostTasks should be destroyed before CommitComplete() is 958 // called since that goes out to the embedder, and we want the embedder 959 // to receive its callbacks before that. 960 BlockingTaskRunner::CapturePostTasks blocked; 961 962 CompletionEvent completion; 963 Proxy::ImplThreadTaskRunner()->PostTask( 964 FROM_HERE, 965 base::Bind(&ThreadProxy::StartCommitOnImplThread, 966 impl_thread_weak_ptr_, 967 &completion, 968 queue.release(), 969 offscreen_context_provider)); 970 completion.Wait(); 971 972 RenderingStatsInstrumentation* stats_instrumentation = 973 layer_tree_host()->rendering_stats_instrumentation(); 974 BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent( 975 stats_instrumentation->main_thread_rendering_stats()); 976 stats_instrumentation->AccumulateAndClearMainThreadStats(); 977 } 978 979 layer_tree_host()->CommitComplete(); 980 layer_tree_host()->DidBeginMainFrame(); 981} 982 983void ThreadProxy::StartCommitOnImplThread( 984 CompletionEvent* completion, 985 ResourceUpdateQueue* raw_queue, 986 scoped_refptr<ContextProvider> offscreen_context_provider) { 987 TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread"); 988 DCHECK(!impl().commit_completion_event); 989 DCHECK(IsImplThread() && IsMainThreadBlocked()); 990 DCHECK(impl().scheduler); 991 DCHECK(impl().scheduler->CommitPending()); 992 993 if (!impl().layer_tree_host_impl) { 994 TRACE_EVENT_INSTANT0( 995 "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD); 996 completion->Signal(); 997 return; 998 } 999 1000 // Ideally, we should inform to impl thread when BeginMainFrame is started. 1001 // But, we can avoid a PostTask in here. 1002 impl().scheduler->NotifyBeginMainFrameStarted(); 1003 1004 scoped_ptr<ResourceUpdateQueue> queue(raw_queue); 1005 1006 if (offscreen_context_provider.get()) 1007 offscreen_context_provider->BindToCurrentThread(); 1008 impl().layer_tree_host_impl->SetOffscreenContextProvider( 1009 offscreen_context_provider); 1010 1011 if (impl().contents_texture_manager) { 1012 DCHECK_EQ(impl().contents_texture_manager, 1013 blocked_main().contents_texture_manager()); 1014 } else { 1015 // Cache this pointer that was created on the main thread side to avoid a 1016 // data race between creating it and using it on the compositor thread. 1017 impl().contents_texture_manager = blocked_main().contents_texture_manager(); 1018 } 1019 1020 if (impl().contents_texture_manager) { 1021 if (impl().contents_texture_manager->LinkedEvictedBackingsExist()) { 1022 // Clear any uploads we were making to textures linked to evicted 1023 // resources 1024 queue->ClearUploadsToEvictedResources(); 1025 // Some textures in the layer tree are invalid. Kick off another commit 1026 // to fill them again. 1027 SetNeedsCommitOnImplThread(); 1028 } 1029 1030 impl().contents_texture_manager->PushTexturePrioritiesToBackings(); 1031 } 1032 1033 impl().commit_completion_event = completion; 1034 impl().current_resource_update_controller = ResourceUpdateController::Create( 1035 this, 1036 Proxy::ImplThreadTaskRunner(), 1037 queue.Pass(), 1038 impl().layer_tree_host_impl->resource_provider()); 1039 impl().current_resource_update_controller->PerformMoreUpdates( 1040 impl().scheduler->AnticipatedDrawTime()); 1041} 1042 1043void ThreadProxy::BeginMainFrameAbortedOnImplThread(bool did_handle) { 1044 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread"); 1045 DCHECK(IsImplThread()); 1046 DCHECK(impl().scheduler); 1047 DCHECK(impl().scheduler->CommitPending()); 1048 DCHECK(!impl().layer_tree_host_impl->pending_tree()); 1049 1050 if (did_handle) 1051 SetInputThrottledUntilCommitOnImplThread(false); 1052 impl().layer_tree_host_impl->BeginMainFrameAborted(did_handle); 1053 impl().scheduler->BeginMainFrameAborted(did_handle); 1054} 1055 1056void ThreadProxy::ScheduledActionCommit() { 1057 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit"); 1058 DCHECK(IsImplThread()); 1059 DCHECK(IsMainThreadBlocked()); 1060 DCHECK(impl().commit_completion_event); 1061 DCHECK(impl().current_resource_update_controller); 1062 1063 // Complete all remaining texture updates. 1064 impl().current_resource_update_controller->Finalize(); 1065 impl().current_resource_update_controller.reset(); 1066 1067 if (impl().animations_frozen_until_next_draw) { 1068 impl().animation_freeze_time = 1069 std::max(impl().animation_freeze_time, 1070 blocked_main().last_monotonic_frame_begin_time); 1071 } 1072 1073 blocked_main().main_thread_inside_commit = true; 1074 impl().layer_tree_host_impl->BeginCommit(); 1075 layer_tree_host()->BeginCommitOnImplThread(impl().layer_tree_host_impl.get()); 1076 layer_tree_host()->FinishCommitOnImplThread( 1077 impl().layer_tree_host_impl.get()); 1078 blocked_main().main_thread_inside_commit = false; 1079 1080 bool hold_commit = layer_tree_host()->settings().impl_side_painting && 1081 blocked_main().commit_waits_for_activation; 1082 blocked_main().commit_waits_for_activation = false; 1083 1084 if (hold_commit) { 1085 // For some layer types in impl-side painting, the commit is held until 1086 // the pending tree is activated. It's also possible that the 1087 // pending tree has already activated if there was no work to be done. 1088 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD); 1089 impl().completion_event_for_commit_held_on_tree_activation = 1090 impl().commit_completion_event; 1091 impl().commit_completion_event = NULL; 1092 } else { 1093 impl().commit_completion_event->Signal(); 1094 impl().commit_completion_event = NULL; 1095 } 1096 1097 // Delay this step until afer the main thread has been released as it's 1098 // often a good bit of work to update the tree and prepare the new frame. 1099 impl().layer_tree_host_impl->CommitComplete(); 1100 1101 SetInputThrottledUntilCommitOnImplThread(false); 1102 1103 UpdateBackgroundAnimateTicking(); 1104 1105 impl().next_frame_is_newly_committed_frame = true; 1106 1107 impl().timing_history.DidCommit(); 1108 1109 // SetVisible kicks off the next scheduler action, so this must be last. 1110 impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible()); 1111} 1112 1113void ThreadProxy::ScheduledActionUpdateVisibleTiles() { 1114 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles"); 1115 DCHECK(IsImplThread()); 1116 impl().layer_tree_host_impl->UpdateVisibleTiles(); 1117} 1118 1119void ThreadProxy::ScheduledActionActivatePendingTree() { 1120 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTree"); 1121 DCHECK(IsImplThread()); 1122 impl().layer_tree_host_impl->ActivatePendingTree(); 1123} 1124 1125void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() { 1126 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation"); 1127 DCHECK(IsImplThread()); 1128 Proxy::MainThreadTaskRunner()->PostTask( 1129 FROM_HERE, 1130 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface, 1131 main_thread_weak_ptr_)); 1132} 1133 1134DrawSwapReadbackResult ThreadProxy::DrawSwapReadbackInternal( 1135 bool forced_draw, 1136 bool swap_requested, 1137 bool readback_requested) { 1138 TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap"); 1139 DrawSwapReadbackResult result; 1140 1141 DCHECK(IsImplThread()); 1142 DCHECK(impl().layer_tree_host_impl.get()); 1143 1144 impl().timing_history.DidStartDrawing(); 1145 base::TimeDelta draw_duration_estimate = DrawDurationEstimate(); 1146 base::AutoReset<bool> mark_inside(&impl().inside_draw, true); 1147 1148 // Advance our animations. 1149 base::TimeTicks monotonic_time; 1150 if (impl().animations_frozen_until_next_draw) 1151 monotonic_time = impl().animation_freeze_time; 1152 else 1153 monotonic_time = impl().layer_tree_host_impl->CurrentFrameTimeTicks(); 1154 1155 // TODO(enne): This should probably happen post-animate. 1156 if (impl().layer_tree_host_impl->pending_tree()) 1157 impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties(); 1158 impl().layer_tree_host_impl->Animate(monotonic_time); 1159 1160 // This method is called on a forced draw, regardless of whether we are able 1161 // to produce a frame, as the calling site on main thread is blocked until its 1162 // request completes, and we signal completion here. If CanDraw() is false, we 1163 // will indicate success=false to the caller, but we must still signal 1164 // completion to avoid deadlock. 1165 1166 // We guard PrepareToDraw() with CanDraw() because it always returns a valid 1167 // frame, so can only be used when such a frame is possible. Since 1168 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on 1169 // CanDraw() as well. 1170 1171 bool drawing_for_readback = readback_requested && !!impl().readback_request; 1172 bool can_do_readback = 1173 impl().layer_tree_host_impl->renderer()->CanReadPixels(); 1174 1175 LayerTreeHostImpl::FrameData frame; 1176 bool draw_frame = false; 1177 1178 if (impl().layer_tree_host_impl->CanDraw()) { 1179 if (!drawing_for_readback || can_do_readback) { 1180 // If it is for a readback, make sure we draw the portion being read back. 1181 gfx::Rect readback_rect; 1182 if (drawing_for_readback) 1183 readback_rect = impl().readback_request->rect; 1184 1185 result.draw_result = 1186 impl().layer_tree_host_impl->PrepareToDraw(&frame, readback_rect); 1187 draw_frame = forced_draw || 1188 result.draw_result == DrawSwapReadbackResult::DRAW_SUCCESS; 1189 } else { 1190 result.draw_result = DrawSwapReadbackResult::DRAW_ABORTED_CANT_READBACK; 1191 } 1192 } else { 1193 result.draw_result = DrawSwapReadbackResult::DRAW_ABORTED_CANT_DRAW; 1194 } 1195 1196 if (draw_frame) { 1197 impl().layer_tree_host_impl->DrawLayers( 1198 &frame, impl().scheduler->LastBeginImplFrameTime()); 1199 result.draw_result = DrawSwapReadbackResult::DRAW_SUCCESS; 1200 impl().animations_frozen_until_next_draw = false; 1201 } else if (result.draw_result == 1202 DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS && 1203 !impl().layer_tree_host_impl->settings().impl_side_painting) { 1204 // Without impl-side painting, the animated layer that is checkerboarding 1205 // will continue to checkerboard until the next commit. If this layer 1206 // continues to move during the commit, it may continue to checkerboard 1207 // after the commit since the region rasterized during the commit will not 1208 // match the region that is currently visible; eventually this 1209 // checkerboarding will be displayed when we force a draw. To avoid this, 1210 // we freeze animations until we successfully draw. 1211 impl().animations_frozen_until_next_draw = true; 1212 impl().animation_freeze_time = monotonic_time; 1213 } else { 1214 DCHECK_NE(DrawSwapReadbackResult::DRAW_SUCCESS, result.draw_result); 1215 } 1216 impl().layer_tree_host_impl->DidDrawAllLayers(frame); 1217 1218 bool start_ready_animations = draw_frame; 1219 impl().layer_tree_host_impl->UpdateAnimationState(start_ready_animations); 1220 1221 // Check for a pending CompositeAndReadback. 1222 if (drawing_for_readback) { 1223 DCHECK(!swap_requested); 1224 result.did_readback = false; 1225 if (draw_frame) { 1226 if (!impl().layer_tree_host_impl->IsContextLost()) { 1227 impl().layer_tree_host_impl->Readback(impl().readback_request->pixels, 1228 impl().readback_request->rect); 1229 result.did_readback = true; 1230 } else { 1231 result.draw_result = DrawSwapReadbackResult::DRAW_ABORTED_CONTEXT_LOST; 1232 } 1233 } 1234 impl().readback_request->success = result.did_readback; 1235 impl().readback_request->completion.Signal(); 1236 impl().readback_request = NULL; 1237 } else if (draw_frame) { 1238 DCHECK(swap_requested); 1239 result.did_swap = impl().layer_tree_host_impl->SwapBuffers(frame); 1240 1241 // We don't know if we have incomplete tiles if we didn't actually swap. 1242 if (result.did_swap) { 1243 DCHECK(!frame.has_no_damage); 1244 SetSwapUsedIncompleteTileOnImplThread(frame.contains_incomplete_tile); 1245 } 1246 } 1247 1248 // Tell the main thread that the the newly-commited frame was drawn. 1249 if (impl().next_frame_is_newly_committed_frame) { 1250 impl().next_frame_is_newly_committed_frame = false; 1251 Proxy::MainThreadTaskRunner()->PostTask( 1252 FROM_HERE, 1253 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_)); 1254 } 1255 1256 if (draw_frame) 1257 CheckOutputSurfaceStatusOnImplThread(); 1258 1259 if (result.draw_result == DrawSwapReadbackResult::DRAW_SUCCESS) { 1260 base::TimeDelta draw_duration = impl().timing_history.DidFinishDrawing(); 1261 1262 base::TimeDelta draw_duration_overestimate; 1263 base::TimeDelta draw_duration_underestimate; 1264 if (draw_duration > draw_duration_estimate) 1265 draw_duration_underestimate = draw_duration - draw_duration_estimate; 1266 else 1267 draw_duration_overestimate = draw_duration_estimate - draw_duration; 1268 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration", 1269 draw_duration, 1270 base::TimeDelta::FromMilliseconds(1), 1271 base::TimeDelta::FromMilliseconds(100), 1272 50); 1273 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate", 1274 draw_duration_underestimate, 1275 base::TimeDelta::FromMilliseconds(1), 1276 base::TimeDelta::FromMilliseconds(100), 1277 50); 1278 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate", 1279 draw_duration_overestimate, 1280 base::TimeDelta::FromMilliseconds(1), 1281 base::TimeDelta::FromMilliseconds(100), 1282 50); 1283 } 1284 1285 DCHECK_NE(DrawSwapReadbackResult::INVALID_RESULT, result.draw_result); 1286 return result; 1287} 1288 1289void ThreadProxy::AcquireLayerTextures() { 1290 // Called when the main thread needs to modify a layer texture that is used 1291 // directly by the compositor. 1292 // This method will block until the next compositor draw if there is a 1293 // previously committed frame that is still undrawn. This is necessary to 1294 // ensure that the main thread does not monopolize access to the textures. 1295 DCHECK(IsMainThread()); 1296 1297 if (main().textures_acquired) 1298 return; 1299 1300 TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures"); 1301 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 1302 CompletionEvent completion; 1303 Proxy::ImplThreadTaskRunner()->PostTask( 1304 FROM_HERE, 1305 base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread, 1306 impl_thread_weak_ptr_, 1307 &completion)); 1308 // Block until it is safe to write to layer textures from the main thread. 1309 completion.Wait(); 1310 1311 main().textures_acquired = true; 1312 main().can_cancel_commit = false; 1313} 1314 1315void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread( 1316 CompletionEvent* completion) { 1317 DCHECK(IsImplThread()); 1318 DCHECK(!impl().texture_acquisition_completion_event); 1319 1320 impl().texture_acquisition_completion_event = completion; 1321 impl().scheduler->SetMainThreadNeedsLayerTextures(); 1322} 1323 1324void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() { 1325 DCHECK(impl().texture_acquisition_completion_event); 1326 impl().texture_acquisition_completion_event->Signal(); 1327 impl().texture_acquisition_completion_event = NULL; 1328} 1329 1330void ThreadProxy::ScheduledActionManageTiles() { 1331 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionManageTiles"); 1332 DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting); 1333 impl().layer_tree_host_impl->ManageTiles(); 1334} 1335 1336DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() { 1337 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap"); 1338 1339 // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to 1340 // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should 1341 // never generate this call when it can't draw. 1342 DCHECK(impl().layer_tree_host_impl->CanDraw()); 1343 1344 bool forced_draw = false; 1345 bool swap_requested = true; 1346 bool readback_requested = false; 1347 return DrawSwapReadbackInternal( 1348 forced_draw, swap_requested, readback_requested); 1349} 1350 1351DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndSwapForced() { 1352 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced"); 1353 bool forced_draw = true; 1354 bool swap_requested = true; 1355 bool readback_requested = false; 1356 return DrawSwapReadbackInternal( 1357 forced_draw, swap_requested, readback_requested); 1358} 1359 1360DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndReadback() { 1361 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndReadback"); 1362 bool forced_draw = true; 1363 bool swap_requested = false; 1364 bool readback_requested = true; 1365 return DrawSwapReadbackInternal( 1366 forced_draw, swap_requested, readback_requested); 1367} 1368 1369void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { 1370 if (impl().current_resource_update_controller) 1371 impl().current_resource_update_controller->PerformMoreUpdates(time); 1372} 1373 1374base::TimeDelta ThreadProxy::DrawDurationEstimate() { 1375 return impl().timing_history.DrawDurationEstimate(); 1376} 1377 1378base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() { 1379 return impl().timing_history.BeginMainFrameToCommitDurationEstimate(); 1380} 1381 1382base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() { 1383 return impl().timing_history.CommitToActivateDurationEstimate(); 1384} 1385 1386void ThreadProxy::DidBeginImplFrameDeadline() { 1387 impl().layer_tree_host_impl->ResetCurrentFrameTimeForNextFrame(); 1388} 1389 1390void ThreadProxy::ReadyToFinalizeTextureUpdates() { 1391 DCHECK(IsImplThread()); 1392 impl().scheduler->NotifyReadyToCommit(); 1393} 1394 1395void ThreadProxy::DidCommitAndDrawFrame() { 1396 DCHECK(IsMainThread()); 1397 if (!layer_tree_host()) 1398 return; 1399 layer_tree_host()->DidCommitAndDrawFrame(); 1400} 1401 1402void ThreadProxy::DidCompleteSwapBuffers() { 1403 DCHECK(IsMainThread()); 1404 if (!layer_tree_host()) 1405 return; 1406 layer_tree_host()->DidCompleteSwapBuffers(); 1407} 1408 1409void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) { 1410 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents"); 1411 DCHECK(IsMainThread()); 1412 if (!layer_tree_host()) 1413 return; 1414 layer_tree_host()->SetAnimationEvents(events.Pass()); 1415} 1416 1417void ThreadProxy::CreateAndInitializeOutputSurface() { 1418 TRACE_EVENT0("cc", "ThreadProxy::CreateAndInitializeOutputSurface"); 1419 DCHECK(IsMainThread()); 1420 1421 // Check that output surface has not been recreated by CompositeAndReadback 1422 // after this task is posted but before it is run. 1423 bool has_initialized_output_surface = true; 1424 { 1425 CompletionEvent completion; 1426 Proxy::ImplThreadTaskRunner()->PostTask( 1427 FROM_HERE, 1428 base::Bind(&ThreadProxy::HasInitializedOutputSurfaceOnImplThread, 1429 impl_thread_weak_ptr_, 1430 &completion, 1431 &has_initialized_output_surface)); 1432 completion.Wait(); 1433 } 1434 if (has_initialized_output_surface) 1435 return; 1436 1437 layer_tree_host()->DidLoseOutputSurface(); 1438 main().output_surface_creation_callback.Reset( 1439 base::Bind(&ThreadProxy::DoCreateAndInitializeOutputSurface, 1440 base::Unretained(this))); 1441 main().output_surface_creation_callback.callback().Run(); 1442} 1443 1444void ThreadProxy::HasInitializedOutputSurfaceOnImplThread( 1445 CompletionEvent* completion, 1446 bool* has_initialized_output_surface) { 1447 DCHECK(IsImplThread()); 1448 *has_initialized_output_surface = 1449 impl().scheduler->HasInitializedOutputSurface(); 1450 completion->Signal(); 1451} 1452 1453void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) { 1454 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread"); 1455 DCHECK(IsImplThread()); 1456 impl().layer_tree_host_impl = 1457 layer_tree_host()->CreateLayerTreeHostImpl(this); 1458 const LayerTreeSettings& settings = layer_tree_host()->settings(); 1459 SchedulerSettings scheduler_settings; 1460 scheduler_settings.main_frame_before_draw_enabled = 1461 settings.main_frame_before_draw_enabled; 1462 scheduler_settings.main_frame_before_activation_enabled = 1463 settings.main_frame_before_activation_enabled; 1464 scheduler_settings.impl_side_painting = settings.impl_side_painting; 1465 scheduler_settings.timeout_and_draw_when_animation_checkerboards = 1466 settings.timeout_and_draw_when_animation_checkerboards; 1467 scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ = 1468 settings.maximum_number_of_failed_draws_before_draw_is_forced_; 1469 scheduler_settings.using_synchronous_renderer_compositor = 1470 settings.using_synchronous_renderer_compositor; 1471 scheduler_settings.throttle_frame_production = 1472 settings.throttle_frame_production; 1473 impl().scheduler = Scheduler::Create(this, 1474 scheduler_settings, 1475 impl().layer_tree_host_id, 1476 ImplThreadTaskRunner()); 1477 impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible()); 1478 1479 impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr(); 1480 completion->Signal(); 1481} 1482 1483void ThreadProxy::InitializeOutputSurfaceOnImplThread( 1484 CompletionEvent* completion, 1485 scoped_ptr<OutputSurface> output_surface, 1486 scoped_refptr<ContextProvider> offscreen_context_provider, 1487 bool* success, 1488 RendererCapabilities* capabilities) { 1489 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread"); 1490 DCHECK(IsImplThread()); 1491 DCHECK(IsMainThreadBlocked()); 1492 DCHECK(success); 1493 DCHECK(capabilities); 1494 1495 layer_tree_host()->DeleteContentsTexturesOnImplThread( 1496 impl().layer_tree_host_impl->resource_provider()); 1497 1498 *success = 1499 impl().layer_tree_host_impl->InitializeRenderer(output_surface.Pass()); 1500 1501 if (*success) { 1502 *capabilities = impl() 1503 .layer_tree_host_impl->GetRendererCapabilities() 1504 .MainThreadCapabilities(); 1505 impl().scheduler->DidCreateAndInitializeOutputSurface(); 1506 } else if (offscreen_context_provider.get()) { 1507 if (offscreen_context_provider->BindToCurrentThread()) 1508 offscreen_context_provider->VerifyContexts(); 1509 offscreen_context_provider = NULL; 1510 } 1511 1512 impl().layer_tree_host_impl->SetOffscreenContextProvider( 1513 offscreen_context_provider); 1514 1515 completion->Signal(); 1516} 1517 1518void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) { 1519 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread"); 1520 DCHECK(IsImplThread()); 1521 if (impl().layer_tree_host_impl->resource_provider()) 1522 impl().layer_tree_host_impl->resource_provider()->Finish(); 1523 completion->Signal(); 1524} 1525 1526void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) { 1527 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread"); 1528 DCHECK(IsImplThread()); 1529 layer_tree_host()->DeleteContentsTexturesOnImplThread( 1530 impl().layer_tree_host_impl->resource_provider()); 1531 impl().current_resource_update_controller.reset(); 1532 impl().layer_tree_host_impl->SetNeedsBeginImplFrame(false); 1533 impl().scheduler.reset(); 1534 impl().layer_tree_host_impl.reset(); 1535 impl().weak_factory.InvalidateWeakPtrs(); 1536 impl().contents_texture_manager = NULL; 1537 completion->Signal(); 1538} 1539 1540size_t ThreadProxy::MaxPartialTextureUpdates() const { 1541 return ResourceUpdateController::MaxPartialTextureUpdates(); 1542} 1543 1544ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState() 1545 : memory_allocation_limit_bytes(0), 1546 memory_allocation_priority_cutoff(0), 1547 evicted_ui_resources(false) {} 1548 1549ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {} 1550 1551scoped_ptr<base::Value> ThreadProxy::AsValue() const { 1552 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); 1553 1554 CompletionEvent completion; 1555 { 1556 DebugScopedSetMainThreadBlocked main_thread_blocked( 1557 const_cast<ThreadProxy*>(this)); 1558 Proxy::ImplThreadTaskRunner()->PostTask( 1559 FROM_HERE, 1560 base::Bind(&ThreadProxy::AsValueOnImplThread, 1561 impl_thread_weak_ptr_, 1562 &completion, 1563 state.get())); 1564 completion.Wait(); 1565 } 1566 return state.PassAs<base::Value>(); 1567} 1568 1569void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion, 1570 base::DictionaryValue* state) const { 1571 state->Set("layer_tree_host_impl", 1572 impl().layer_tree_host_impl->AsValue().release()); 1573 completion->Signal(); 1574} 1575 1576bool ThreadProxy::CommitPendingForTesting() { 1577 DCHECK(IsMainThread()); 1578 CommitPendingRequest commit_pending_request; 1579 { 1580 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 1581 Proxy::ImplThreadTaskRunner()->PostTask( 1582 FROM_HERE, 1583 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting, 1584 impl_thread_weak_ptr_, 1585 &commit_pending_request)); 1586 commit_pending_request.completion.Wait(); 1587 } 1588 return commit_pending_request.commit_pending; 1589} 1590 1591void ThreadProxy::CommitPendingOnImplThreadForTesting( 1592 CommitPendingRequest* request) { 1593 DCHECK(IsImplThread()); 1594 if (impl().layer_tree_host_impl->output_surface()) 1595 request->commit_pending = impl().scheduler->CommitPending(); 1596 else 1597 request->commit_pending = false; 1598 request->completion.Signal(); 1599} 1600 1601scoped_ptr<base::Value> ThreadProxy::SchedulerStateAsValueForTesting() { 1602 if (IsImplThread()) 1603 return impl().scheduler->StateAsValue().Pass(); 1604 1605 SchedulerStateRequest scheduler_state_request; 1606 { 1607 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 1608 Proxy::ImplThreadTaskRunner()->PostTask( 1609 FROM_HERE, 1610 base::Bind(&ThreadProxy::SchedulerStateAsValueOnImplThreadForTesting, 1611 impl_thread_weak_ptr_, 1612 &scheduler_state_request)); 1613 scheduler_state_request.completion.Wait(); 1614 } 1615 return scheduler_state_request.state.Pass(); 1616} 1617 1618void ThreadProxy::SchedulerStateAsValueOnImplThreadForTesting( 1619 SchedulerStateRequest* request) { 1620 DCHECK(IsImplThread()); 1621 request->state = impl().scheduler->StateAsValue(); 1622 request->completion.Signal(); 1623} 1624 1625void ThreadProxy::RenewTreePriority() { 1626 DCHECK(IsImplThread()); 1627 bool smoothness_takes_priority = 1628 impl().layer_tree_host_impl->pinch_gesture_active() || 1629 impl().layer_tree_host_impl->IsCurrentlyScrolling() || 1630 impl().layer_tree_host_impl->page_scale_animation_active(); 1631 1632 base::TimeTicks now = impl().layer_tree_host_impl->CurrentPhysicalTimeTicks(); 1633 1634 // Update expiration time if smoothness currently takes priority. 1635 if (smoothness_takes_priority) { 1636 impl().smoothness_takes_priority_expiration_time = 1637 now + base::TimeDelta::FromMilliseconds( 1638 kSmoothnessTakesPriorityExpirationDelay * 1000); 1639 } 1640 1641 // We use the same priority for both trees by default. 1642 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES; 1643 1644 // Smoothness takes priority if expiration time is in the future. 1645 if (impl().smoothness_takes_priority_expiration_time > now) 1646 priority = SMOOTHNESS_TAKES_PRIORITY; 1647 1648 // New content always takes priority when the active tree has 1649 // evicted resources or there is an invalid viewport size. 1650 if (impl().layer_tree_host_impl->active_tree()->ContentsTexturesPurged() || 1651 impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() || 1652 impl().layer_tree_host_impl->EvictedUIResourcesExist() || 1653 impl().input_throttled_until_commit) { 1654 // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active 1655 // tree might be freed. We need to set RequiresHighResToDraw to ensure that 1656 // high res tiles will be required to activate pending tree. 1657 impl().layer_tree_host_impl->active_tree()->SetRequiresHighResToDraw(); 1658 priority = NEW_CONTENT_TAKES_PRIORITY; 1659 } 1660 1661 impl().layer_tree_host_impl->SetTreePriority(priority); 1662 impl().scheduler->SetSmoothnessTakesPriority(priority == 1663 SMOOTHNESS_TAKES_PRIORITY); 1664 1665 // Notify the the client of this compositor via the output surface. 1666 // TODO(epenner): Route this to compositor-thread instead of output-surface 1667 // after GTFO refactor of compositor-thread (http://crbug/170828). 1668 if (impl().layer_tree_host_impl->output_surface()) { 1669 impl() 1670 .layer_tree_host_impl->output_surface() 1671 ->UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY); 1672 } 1673 1674 base::TimeDelta delay = 1675 impl().smoothness_takes_priority_expiration_time - now; 1676 1677 // Need to make sure a delayed task is posted when we have smoothness 1678 // takes priority expiration time in the future. 1679 if (delay <= base::TimeDelta()) 1680 return; 1681 if (impl().renew_tree_priority_pending) 1682 return; 1683 1684 Proxy::ImplThreadTaskRunner()->PostDelayedTask( 1685 FROM_HERE, 1686 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread, 1687 impl_thread_weak_ptr_), 1688 delay); 1689 1690 impl().renew_tree_priority_pending = true; 1691} 1692 1693void ThreadProxy::RenewTreePriorityOnImplThread() { 1694 DCHECK(impl().renew_tree_priority_pending); 1695 impl().renew_tree_priority_pending = false; 1696 1697 RenewTreePriority(); 1698} 1699 1700void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay) { 1701 Proxy::ImplThreadTaskRunner()->PostDelayedTask( 1702 FROM_HERE, 1703 base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread, 1704 impl_thread_weak_ptr_), 1705 delay); 1706} 1707 1708void ThreadProxy::StartScrollbarAnimationOnImplThread() { 1709 impl().layer_tree_host_impl->StartScrollbarAnimation(); 1710} 1711 1712void ThreadProxy::DidActivatePendingTree() { 1713 TRACE_EVENT0("cc", "ThreadProxy::DidActivatePendingTreeOnImplThread"); 1714 DCHECK(IsImplThread()); 1715 DCHECK(!impl().layer_tree_host_impl->pending_tree()); 1716 1717 if (impl().completion_event_for_commit_held_on_tree_activation) { 1718 TRACE_EVENT_INSTANT0( 1719 "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD); 1720 DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting); 1721 impl().completion_event_for_commit_held_on_tree_activation->Signal(); 1722 impl().completion_event_for_commit_held_on_tree_activation = NULL; 1723 } 1724 1725 UpdateBackgroundAnimateTicking(); 1726 1727 impl().timing_history.DidActivatePendingTree(); 1728} 1729 1730void ThreadProxy::DidManageTiles() { 1731 DCHECK(IsImplThread()); 1732 impl().scheduler->DidManageTiles(); 1733} 1734 1735} // namespace cc 1736