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