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