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