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