thread_proxy.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 "base/auto_reset.h" 8#include "base/bind.h" 9#include "base/debug/trace_event.h" 10#include "cc/base/thread.h" 11#include "cc/input/input_handler.h" 12#include "cc/output/context_provider.h" 13#include "cc/output/output_surface.h" 14#include "cc/quads/draw_quad.h" 15#include "cc/resources/prioritized_resource_manager.h" 16#include "cc/scheduler/delay_based_time_source.h" 17#include "cc/scheduler/frame_rate_controller.h" 18#include "cc/scheduler/scheduler.h" 19#include "cc/trees/layer_tree_host.h" 20#include "cc/trees/layer_tree_impl.h" 21 22namespace { 23 24// Measured in seconds. 25const double kContextRecreationTickRate = 0.03; 26 27// Measured in seconds. 28const double kSmoothnessTakesPriorityExpirationDelay = 0.25; 29 30} // namespace 31 32namespace cc { 33 34scoped_ptr<Proxy> ThreadProxy::Create(LayerTreeHost* layer_tree_host, 35 scoped_ptr<Thread> impl_thread) { 36 return make_scoped_ptr( 37 new ThreadProxy(layer_tree_host, impl_thread.Pass())).PassAs<Proxy>(); 38} 39 40ThreadProxy::ThreadProxy(LayerTreeHost* layer_tree_host, 41 scoped_ptr<Thread> impl_thread) 42 : Proxy(impl_thread.Pass()), 43 animate_requested_(false), 44 commit_requested_(false), 45 commit_request_sent_to_impl_thread_(false), 46 created_offscreen_context_provider_(false), 47 layer_tree_host_(layer_tree_host), 48 renderer_initialized_(false), 49 started_(false), 50 textures_acquired_(true), 51 in_composite_and_readback_(false), 52 manage_tiles_pending_(false), 53 weak_factory_on_impl_thread_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 54 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 55 begin_frame_completion_event_on_impl_thread_(NULL), 56 readback_request_on_impl_thread_(NULL), 57 commit_completion_event_on_impl_thread_(NULL), 58 completion_event_for_commit_held_on_tree_activation_(NULL), 59 texture_acquisition_completion_event_on_impl_thread_(NULL), 60 next_frame_is_newly_committed_frame_on_impl_thread_(false), 61 render_vsync_enabled_(layer_tree_host->settings().render_vsync_enabled), 62 inside_draw_(false), 63 defer_commits_(false), 64 renew_tree_priority_on_impl_thread_pending_(false) { 65 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy"); 66 DCHECK(IsMainThread()); 67} 68 69ThreadProxy::~ThreadProxy() { 70 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy"); 71 DCHECK(IsMainThread()); 72 DCHECK(!started_); 73} 74 75bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) { 76 TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback"); 77 DCHECK(IsMainThread()); 78 DCHECK(layer_tree_host_); 79 DCHECK(!defer_commits_); 80 81 if (!layer_tree_host_->InitializeRendererIfNeeded()) { 82 TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized"); 83 return false; 84 } 85 86 // Perform a synchronous commit. 87 { 88 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 89 CompletionEvent begin_frame_completion; 90 Proxy::ImplThread()->PostTask( 91 base::Bind(&ThreadProxy::ForceBeginFrameOnImplThread, 92 impl_thread_weak_ptr_, 93 &begin_frame_completion)); 94 begin_frame_completion.Wait(); 95 } 96 in_composite_and_readback_ = true; 97 BeginFrame(scoped_ptr<BeginFrameAndCommitState>()); 98 in_composite_and_readback_ = false; 99 100 // Perform a synchronous readback. 101 ReadbackRequest request; 102 request.rect = rect; 103 request.pixels = pixels; 104 { 105 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 106 Proxy::ImplThread()->PostTask( 107 base::Bind(&ThreadProxy::RequestReadbackOnImplThread, 108 impl_thread_weak_ptr_, 109 &request)); 110 request.completion.Wait(); 111 } 112 return request.success; 113} 114 115void ThreadProxy::RequestReadbackOnImplThread(ReadbackRequest* request) { 116 DCHECK(Proxy::IsImplThread()); 117 DCHECK(!readback_request_on_impl_thread_); 118 if (!layer_tree_host_impl_) { 119 request->success = false; 120 request->completion.Signal(); 121 return; 122 } 123 124 readback_request_on_impl_thread_ = request; 125 scheduler_on_impl_thread_->SetNeedsRedraw(); 126 scheduler_on_impl_thread_->SetNeedsForcedRedraw(); 127} 128 129void ThreadProxy::StartPageScaleAnimation(gfx::Vector2d target_offset, 130 bool use_anchor, 131 float scale, 132 base::TimeDelta duration) { 133 DCHECK(Proxy::IsMainThread()); 134 Proxy::ImplThread()->PostTask( 135 base::Bind(&ThreadProxy::RequestStartPageScaleAnimationOnImplThread, 136 impl_thread_weak_ptr_, 137 target_offset, 138 use_anchor, 139 scale, 140 duration)); 141} 142 143void ThreadProxy::RequestStartPageScaleAnimationOnImplThread( 144 gfx::Vector2d target_offset, 145 bool use_anchor, 146 float scale, 147 base::TimeDelta duration) { 148 DCHECK(Proxy::IsImplThread()); 149 if (layer_tree_host_impl_) { 150 layer_tree_host_impl_->StartPageScaleAnimation( 151 target_offset, use_anchor, scale, base::TimeTicks::Now(), duration); 152 } 153} 154 155void ThreadProxy::FinishAllRendering() { 156 DCHECK(Proxy::IsMainThread()); 157 DCHECK(!defer_commits_); 158 159 // Make sure all GL drawing is finished on the impl thread. 160 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 161 CompletionEvent completion; 162 Proxy::ImplThread()->PostTask( 163 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread, 164 impl_thread_weak_ptr_, 165 &completion)); 166 completion.Wait(); 167} 168 169bool ThreadProxy::IsStarted() const { 170 DCHECK(Proxy::IsMainThread()); 171 return started_; 172} 173 174bool ThreadProxy::InitializeOutputSurface() { 175 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurface"); 176 scoped_ptr<OutputSurface> context = layer_tree_host_->CreateOutputSurface(); 177 if (!context) 178 return false; 179 180 Proxy::ImplThread()->PostTask( 181 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread, 182 impl_thread_weak_ptr_, 183 base::Passed(&context))); 184 return true; 185} 186 187void ThreadProxy::SetSurfaceReady() { 188 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReady"); 189 Proxy::ImplThread()->PostTask(base::Bind( 190 &ThreadProxy::SetSurfaceReadyOnImplThread, impl_thread_weak_ptr_)); 191} 192 193void ThreadProxy::SetSurfaceReadyOnImplThread() { 194 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReadyOnImplThread"); 195 scheduler_on_impl_thread_->SetCanBeginFrame(true); 196} 197 198void ThreadProxy::SetVisible(bool visible) { 199 TRACE_EVENT0("cc", "ThreadProxy::SetVisible"); 200 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 201 CompletionEvent completion; 202 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::SetVisibleOnImplThread, 203 impl_thread_weak_ptr_, 204 &completion, 205 visible)); 206 completion.Wait(); 207} 208 209void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion, 210 bool visible) { 211 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread"); 212 layer_tree_host_impl_->SetVisible(visible); 213 scheduler_on_impl_thread_->SetVisible(visible); 214 completion->Signal(); 215} 216 217bool ThreadProxy::InitializeRenderer() { 218 TRACE_EVENT0("cc", "ThreadProxy::InitializeRenderer"); 219 // Make a blocking call to InitializeRendererOnImplThread. The results of that 220 // call are pushed into the initialize_succeeded and capabilities local 221 // variables. 222 CompletionEvent completion; 223 bool initialize_succeeded = false; 224 RendererCapabilities capabilities; 225 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 226 Proxy::ImplThread()->PostTask( 227 base::Bind(&ThreadProxy::InitializeRendererOnImplThread, 228 impl_thread_weak_ptr_, 229 &completion, 230 &initialize_succeeded, 231 &capabilities)); 232 completion.Wait(); 233 234 if (initialize_succeeded) { 235 renderer_initialized_ = true; 236 renderer_capabilities_main_thread_copy_ = capabilities; 237 } 238 return initialize_succeeded; 239} 240 241bool ThreadProxy::RecreateOutputSurface() { 242 TRACE_EVENT0("cc", "ThreadProxy::RecreateOutputSurface"); 243 DCHECK(IsMainThread()); 244 245 // Try to create the surface. 246 scoped_ptr<OutputSurface> output_surface = 247 layer_tree_host_->CreateOutputSurface(); 248 if (!output_surface) 249 return false; 250 scoped_refptr<cc::ContextProvider> offscreen_context_provider; 251 if (created_offscreen_context_provider_) { 252 offscreen_context_provider = layer_tree_host_->client()-> 253 OffscreenContextProviderForCompositorThread(); 254 if (!offscreen_context_provider) 255 return false; 256 } 257 258 // Make a blocking call to RecreateOutputSurfaceOnImplThread. The results of 259 // that call are pushed into the recreate_succeeded and capabilities local 260 // variables. 261 CompletionEvent completion; 262 bool recreate_succeeded = false; 263 RendererCapabilities capabilities; 264 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 265 Proxy::ImplThread()->PostTask( 266 base::Bind(&ThreadProxy::RecreateOutputSurfaceOnImplThread, 267 impl_thread_weak_ptr_, 268 &completion, 269 base::Passed(&output_surface), 270 offscreen_context_provider, 271 &recreate_succeeded, 272 &capabilities)); 273 completion.Wait(); 274 275 if (recreate_succeeded) 276 renderer_capabilities_main_thread_copy_ = capabilities; 277 return recreate_succeeded; 278} 279 280const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const { 281 DCHECK(renderer_initialized_); 282 return renderer_capabilities_main_thread_copy_; 283} 284 285void ThreadProxy::SetNeedsAnimate() { 286 DCHECK(IsMainThread()); 287 if (animate_requested_) 288 return; 289 290 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate"); 291 animate_requested_ = true; 292 293 if (commit_request_sent_to_impl_thread_) 294 return; 295 commit_request_sent_to_impl_thread_ = true; 296 Proxy::ImplThread()->PostTask(base::Bind( 297 &ThreadProxy::SetNeedsCommitOnImplThread, impl_thread_weak_ptr_)); 298} 299 300void ThreadProxy::SetNeedsCommit() { 301 DCHECK(IsMainThread()); 302 if (commit_requested_) 303 return; 304 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit"); 305 commit_requested_ = true; 306 307 if (commit_request_sent_to_impl_thread_) 308 return; 309 commit_request_sent_to_impl_thread_ = true; 310 Proxy::ImplThread()->PostTask(base::Bind( 311 &ThreadProxy::SetNeedsCommitOnImplThread, impl_thread_weak_ptr_)); 312} 313 314void ThreadProxy::DidLoseOutputSurfaceOnImplThread() { 315 DCHECK(IsImplThread()); 316 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread"); 317 Proxy::ImplThread()->PostTask( 318 base::Bind(&ThreadProxy::CheckOutputSurfaceStatusOnImplThread, 319 impl_thread_weak_ptr_)); 320} 321 322void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() { 323 DCHECK(IsImplThread()); 324 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread"); 325 if (!layer_tree_host_impl_->IsContextLost()) 326 return; 327 if (cc::ContextProvider* offscreen_contexts = layer_tree_host_impl_-> 328 resource_provider()->offscreen_context_provider()) 329 offscreen_contexts->VerifyContexts(); 330 scheduler_on_impl_thread_->DidLoseOutputSurface(); 331} 332 333void ThreadProxy::OnSwapBuffersCompleteOnImplThread() { 334 DCHECK(IsImplThread()); 335 TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread"); 336 scheduler_on_impl_thread_->DidSwapBuffersComplete(); 337 Proxy::MainThread()->PostTask( 338 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_)); 339} 340 341void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase, 342 base::TimeDelta interval) { 343 DCHECK(IsImplThread()); 344 TRACE_EVENT2("cc", 345 "ThreadProxy::OnVSyncParametersChanged", 346 "timebase", 347 (timebase - base::TimeTicks()).InMilliseconds(), 348 "interval", 349 interval.InMilliseconds()); 350 scheduler_on_impl_thread_->SetTimebaseAndInterval(timebase, interval); 351} 352 353void ThreadProxy::OnCanDrawStateChanged(bool can_draw) { 354 DCHECK(IsImplThread()); 355 TRACE_EVENT1( 356 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw); 357 scheduler_on_impl_thread_->SetCanDraw(can_draw); 358} 359 360void ThreadProxy::OnHasPendingTreeStateChanged(bool has_pending_tree) { 361 DCHECK(IsImplThread()); 362 TRACE_EVENT1("cc", 363 "ThreadProxy::OnHasPendingTreeStateChanged", 364 "has_pending_tree", 365 has_pending_tree); 366 scheduler_on_impl_thread_->SetHasPendingTree(has_pending_tree); 367} 368 369void ThreadProxy::SetNeedsCommitOnImplThread() { 370 DCHECK(IsImplThread()); 371 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread"); 372 scheduler_on_impl_thread_->SetNeedsCommit(); 373} 374 375void ThreadProxy::SetNeedsManageTilesOnImplThread() { 376 if (manage_tiles_pending_) 377 return; 378 Proxy::ImplThread()->PostTask( 379 base::Bind(&ThreadProxy::ManageTilesOnImplThread, impl_thread_weak_ptr_)); 380 manage_tiles_pending_ = true; 381} 382 383void ThreadProxy::ManageTilesOnImplThread() { 384 // TODO(nduca): If needed, move this into CCSchedulerStateMachine. 385 manage_tiles_pending_ = false; 386 if (layer_tree_host_impl_) 387 layer_tree_host_impl_->ManageTiles(); 388} 389 390void ThreadProxy::SetNeedsForcedCommitOnImplThread() { 391 DCHECK(IsImplThread()); 392 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsForcedCommitOnImplThread"); 393 scheduler_on_impl_thread_->SetNeedsForcedCommit(); 394} 395 396void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread( 397 scoped_ptr<AnimationEventsVector> events, 398 base::Time wall_clock_time) { 399 DCHECK(IsImplThread()); 400 TRACE_EVENT0("cc", 401 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread"); 402 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::SetAnimationEvents, 403 main_thread_weak_ptr_, 404 base::Passed(&events), 405 wall_clock_time)); 406} 407 408bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes, 409 int priority_cutoff) { 410 DCHECK(IsImplThread()); 411 412 if (!layer_tree_host_->contents_texture_manager()) 413 return false; 414 415 bool reduce_result = layer_tree_host_->contents_texture_manager()-> 416 ReduceMemoryOnImplThread(limit_bytes, 417 priority_cutoff, 418 layer_tree_host_impl_->resource_provider()); 419 if (!reduce_result) 420 return false; 421 422 // The texture upload queue may reference textures that were just purged, 423 // clear them from the queue. 424 if (current_resource_update_controller_on_impl_thread_) { 425 current_resource_update_controller_on_impl_thread_-> 426 DiscardUploadsToEvictedResources(); 427 } 428 return true; 429} 430 431void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() { 432 DCHECK(IsImplThread()); 433 434 if (!layer_tree_host_->contents_texture_manager()) 435 return; 436 437 layer_tree_host_->contents_texture_manager()->ReduceWastedMemoryOnImplThread( 438 layer_tree_host_impl_->resource_provider()); 439} 440 441void ThreadProxy::SendManagedMemoryStats() { 442 DCHECK(IsImplThread()); 443 if (!layer_tree_host_impl_) 444 return; 445 if (!layer_tree_host_->contents_texture_manager()) 446 return; 447 448 // If we are using impl-side painting, then SendManagedMemoryStats is called 449 // directly after the tile manager's manage function, and doesn't need to 450 // interact with main thread's layer tree. 451 if (layer_tree_host_->settings().impl_side_painting) 452 return; 453 454 layer_tree_host_impl_->SendManagedMemoryStats( 455 layer_tree_host_->contents_texture_manager()->MemoryVisibleBytes(), 456 layer_tree_host_->contents_texture_manager()-> 457 MemoryVisibleAndNearbyBytes(), 458 layer_tree_host_->contents_texture_manager()->MemoryUseBytes()); 459} 460 461bool ThreadProxy::IsInsideDraw() { return inside_draw_; } 462 463void ThreadProxy::SetNeedsRedraw() { 464 DCHECK(IsMainThread()); 465 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw"); 466 Proxy::ImplThread()->PostTask(base::Bind( 467 &ThreadProxy::SetFullRootLayerDamageOnImplThread, impl_thread_weak_ptr_)); 468 Proxy::ImplThread()->PostTask(base::Bind( 469 &ThreadProxy::SetNeedsRedrawOnImplThread, impl_thread_weak_ptr_)); 470} 471 472void ThreadProxy::SetDeferCommits(bool defer_commits) { 473 DCHECK(IsMainThread()); 474 DCHECK_NE(defer_commits_, defer_commits); 475 defer_commits_ = defer_commits; 476 477 if (defer_commits_) 478 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this); 479 else 480 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this); 481 482 if (!defer_commits_ && pending_deferred_commit_) 483 Proxy::MainThread()->PostTask( 484 base::Bind(&ThreadProxy::BeginFrame, 485 main_thread_weak_ptr_, 486 base::Passed(&pending_deferred_commit_))); 487} 488 489bool ThreadProxy::CommitRequested() const { 490 DCHECK(IsMainThread()); 491 return commit_requested_; 492} 493 494void ThreadProxy::SetNeedsRedrawOnImplThread() { 495 DCHECK(IsImplThread()); 496 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread"); 497 scheduler_on_impl_thread_->SetNeedsRedraw(); 498} 499 500void ThreadProxy::DidSwapUseIncompleteTileOnImplThread() { 501 DCHECK(IsImplThread()); 502 TRACE_EVENT0("cc", "ThreadProxy::DidSwapUseIncompleteTileOnImplThread"); 503 scheduler_on_impl_thread_->DidSwapUseIncompleteTile(); 504} 505 506void ThreadProxy::DidInitializeVisibleTileOnImplThread() { 507 DCHECK(IsImplThread()); 508 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread"); 509 scheduler_on_impl_thread_->SetNeedsRedraw(); 510} 511 512void ThreadProxy::MainThreadHasStoppedFlinging() { 513 if (input_handler_on_impl_thread_) 514 input_handler_on_impl_thread_->MainThreadHasStoppedFlinging(); 515} 516 517void ThreadProxy::Start() { 518 DCHECK(IsMainThread()); 519 DCHECK(Proxy::ImplThread()); 520 // Create LayerTreeHostImpl. 521 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 522 CompletionEvent completion; 523 scoped_ptr<InputHandler> handler = layer_tree_host_->CreateInputHandler(); 524 Proxy::ImplThread()->PostTask( 525 base::Bind(&ThreadProxy::InitializeImplOnImplThread, 526 base::Unretained(this), 527 &completion, 528 handler.release())); 529 completion.Wait(); 530 531 main_thread_weak_ptr_ = weak_factory_.GetWeakPtr(); 532 533 started_ = true; 534} 535 536void ThreadProxy::Stop() { 537 TRACE_EVENT0("cc", "ThreadProxy::Stop"); 538 DCHECK(IsMainThread()); 539 DCHECK(started_); 540 541 // Synchronously deletes the impl. 542 { 543 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 544 545 CompletionEvent completion; 546 Proxy::ImplThread()->PostTask( 547 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread, 548 impl_thread_weak_ptr_, 549 &completion)); 550 completion.Wait(); 551 } 552 553 weak_factory_.InvalidateWeakPtrs(); 554 555 DCHECK(!layer_tree_host_impl_.get()); // verify that the impl deleted. 556 layer_tree_host_ = NULL; 557 started_ = false; 558} 559 560void ThreadProxy::ForceSerializeOnSwapBuffers() { 561 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 562 CompletionEvent completion; 563 Proxy::ImplThread()->PostTask( 564 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread, 565 impl_thread_weak_ptr_, 566 &completion)); 567 completion.Wait(); 568} 569 570void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread( 571 CompletionEvent* completion) { 572 if (renderer_initialized_) 573 layer_tree_host_impl_->renderer()->DoNoOp(); 574 completion->Signal(); 575} 576 577void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) { 578 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread"); 579 DCHECK(IsImplThread()); 580 layer_tree_host_impl_->FinishAllRendering(); 581 completion->Signal(); 582} 583 584void ThreadProxy::ForceBeginFrameOnImplThread(CompletionEvent* completion) { 585 TRACE_EVENT0("cc", "ThreadProxy::ForceBeginFrameOnImplThread"); 586 DCHECK(!begin_frame_completion_event_on_impl_thread_); 587 588 SetNeedsForcedCommitOnImplThread(); 589 if (scheduler_on_impl_thread_->CommitPending()) { 590 completion->Signal(); 591 return; 592 } 593 594 begin_frame_completion_event_on_impl_thread_ = completion; 595} 596 597void ThreadProxy::ScheduledActionBeginFrame() { 598 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginFrame"); 599 scoped_ptr<BeginFrameAndCommitState> begin_frame_state( 600 new BeginFrameAndCommitState); 601 begin_frame_state->monotonic_frame_begin_time = base::TimeTicks::Now(); 602 begin_frame_state->scroll_info = layer_tree_host_impl_->ProcessScrollDeltas(); 603 begin_frame_state->impl_transform = 604 layer_tree_host_impl_->active_tree()->ImplTransform(); 605 DCHECK_GT(layer_tree_host_impl_->memory_allocation_limit_bytes(), 0u); 606 begin_frame_state->memory_allocation_limit_bytes = 607 layer_tree_host_impl_->memory_allocation_limit_bytes(); 608 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::BeginFrame, 609 main_thread_weak_ptr_, 610 base::Passed(&begin_frame_state))); 611 612 if (begin_frame_completion_event_on_impl_thread_) { 613 begin_frame_completion_event_on_impl_thread_->Signal(); 614 begin_frame_completion_event_on_impl_thread_ = NULL; 615 } 616} 617 618void ThreadProxy::BeginFrame( 619 scoped_ptr<BeginFrameAndCommitState> begin_frame_state) { 620 TRACE_EVENT0("cc", "ThreadProxy::BeginFrame"); 621 DCHECK(IsMainThread()); 622 if (!layer_tree_host_) 623 return; 624 625 if (defer_commits_) { 626 pending_deferred_commit_ = begin_frame_state.Pass(); 627 layer_tree_host_->DidDeferCommit(); 628 TRACE_EVENT0("cc", "EarlyOut_DeferCommits"); 629 return; 630 } 631 632 // Do not notify the impl thread of commit requests that occur during 633 // the apply/animate/layout part of the BeginFrameAndCommit process since 634 // those commit requests will get painted immediately. Once we have done 635 // the paint, commit_requested_ will be set to false to allow new commit 636 // requests to be scheduled. 637 commit_requested_ = true; 638 commit_request_sent_to_impl_thread_ = true; 639 640 // On the other hand, the AnimationRequested flag needs to be cleared 641 // here so that any animation requests generated by the apply or animate 642 // callbacks will trigger another frame. 643 animate_requested_ = false; 644 645 if (begin_frame_state) { 646 layer_tree_host_->ApplyScrollAndScale(*begin_frame_state->scroll_info); 647 layer_tree_host_->SetImplTransform(begin_frame_state->impl_transform); 648 } 649 650 if (!in_composite_and_readback_ && !layer_tree_host_->visible()) { 651 commit_requested_ = false; 652 commit_request_sent_to_impl_thread_ = false; 653 654 TRACE_EVENT0("cc", "EarlyOut_NotVisible"); 655 Proxy::ImplThread()->PostTask(base::Bind( 656 &ThreadProxy::BeginFrameAbortedOnImplThread, impl_thread_weak_ptr_)); 657 return; 658 } 659 660 layer_tree_host_->WillBeginFrame(); 661 662 if (begin_frame_state) { 663 layer_tree_host_->UpdateAnimations( 664 begin_frame_state->monotonic_frame_begin_time); 665 } 666 667 // Unlink any backings that the impl thread has evicted, so that we know to 668 // re-paint them in UpdateLayers. 669 if (layer_tree_host_->contents_texture_manager()) { 670 layer_tree_host_->contents_texture_manager()-> 671 UnlinkAndClearEvictedBackings(); 672 } 673 674 layer_tree_host_->Layout(); 675 676 // Clear the commit flag after updating animations and layout here --- objects 677 // that only layout when painted will trigger another SetNeedsCommit inside 678 // UpdateLayers. 679 commit_requested_ = false; 680 commit_request_sent_to_impl_thread_ = false; 681 682 if (!layer_tree_host_->InitializeRendererIfNeeded()) { 683 TRACE_EVENT0("cc", "EarlyOut_InitializeFailed"); 684 return; 685 } 686 687 scoped_ptr<ResourceUpdateQueue> queue = 688 make_scoped_ptr(new ResourceUpdateQueue); 689 layer_tree_host_->UpdateLayers( 690 queue.get(), 691 begin_frame_state ? begin_frame_state->memory_allocation_limit_bytes 692 : 0u); 693 694 // Once single buffered layers are committed, they cannot be modified until 695 // they are drawn by the impl thread. 696 textures_acquired_ = false; 697 698 layer_tree_host_->WillCommit(); 699 // Before applying scrolls and calling animate, we set animate_requested_ to 700 // false. If it is true now, it means SetNeedAnimate was called again, but 701 // during a state when commit_request_sent_to_impl_thread_ = true. We need to 702 // force that call to happen again now so that the commit request is sent to 703 // the impl thread. 704 if (animate_requested_) { 705 // Forces SetNeedsAnimate to consider posting a commit task. 706 animate_requested_ = false; 707 SetNeedsAnimate(); 708 } 709 710 scoped_refptr<cc::ContextProvider> offscreen_context_provider; 711 if (renderer_capabilities_main_thread_copy_.using_offscreen_context3d && 712 layer_tree_host_->needs_offscreen_context()) { 713 offscreen_context_provider = layer_tree_host_->client()-> 714 OffscreenContextProviderForCompositorThread(); 715 if (offscreen_context_provider) 716 created_offscreen_context_provider_ = true; 717 } 718 719 // Notify the impl thread that the BeginFrame has completed. This will 720 // begin the commit process, which is blocking from the main thread's 721 // point of view, but asynchronously performed on the impl thread, 722 // coordinated by the Scheduler. 723 { 724 TRACE_EVENT0("cc", "commit"); 725 726 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 727 728 RenderingStatsInstrumentation* stats_instrumentation = 729 layer_tree_host_->rendering_stats_instrumentation(); 730 base::TimeTicks start_time = stats_instrumentation->StartRecording(); 731 732 CompletionEvent completion; 733 Proxy::ImplThread()->PostTask( 734 base::Bind(&ThreadProxy::BeginFrameCompleteOnImplThread, 735 impl_thread_weak_ptr_, 736 &completion, 737 queue.release(), 738 offscreen_context_provider)); 739 completion.Wait(); 740 741 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time); 742 stats_instrumentation->AddCommit(duration); 743 } 744 745 layer_tree_host_->CommitComplete(); 746 layer_tree_host_->DidBeginFrame(); 747} 748 749void ThreadProxy::BeginFrameCompleteOnImplThread( 750 CompletionEvent* completion, 751 ResourceUpdateQueue* raw_queue, 752 scoped_refptr<cc::ContextProvider> offscreen_context_provider) { 753 scoped_ptr<ResourceUpdateQueue> queue(raw_queue); 754 755 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameCompleteOnImplThread"); 756 DCHECK(!commit_completion_event_on_impl_thread_); 757 DCHECK(IsImplThread() && IsMainThreadBlocked()); 758 DCHECK(scheduler_on_impl_thread_); 759 DCHECK(scheduler_on_impl_thread_->CommitPending()); 760 761 if (!layer_tree_host_impl_) { 762 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree"); 763 completion->Signal(); 764 return; 765 } 766 767 if (offscreen_context_provider) 768 offscreen_context_provider->BindToCurrentThread(); 769 layer_tree_host_impl_->resource_provider()-> 770 set_offscreen_context_provider(offscreen_context_provider); 771 772 if (layer_tree_host_->contents_texture_manager()-> 773 LinkedEvictedBackingsExist()) { 774 // Clear any uploads we were making to textures linked to evicted 775 // resources 776 queue->ClearUploadsToEvictedResources(); 777 // Some textures in the layer tree are invalid. Kick off another commit 778 // to fill them again. 779 SetNeedsCommitOnImplThread(); 780 } 781 782 layer_tree_host_->contents_texture_manager()-> 783 PushTexturePrioritiesToBackings(); 784 785 current_resource_update_controller_on_impl_thread_ = 786 ResourceUpdateController::Create( 787 this, 788 Proxy::ImplThread(), 789 queue.Pass(), 790 layer_tree_host_impl_->resource_provider()); 791 current_resource_update_controller_on_impl_thread_->PerformMoreUpdates( 792 scheduler_on_impl_thread_->AnticipatedDrawTime()); 793 794 commit_completion_event_on_impl_thread_ = completion; 795} 796 797void ThreadProxy::BeginFrameAbortedOnImplThread() { 798 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedOnImplThread"); 799 DCHECK(IsImplThread()); 800 DCHECK(scheduler_on_impl_thread_); 801 DCHECK(scheduler_on_impl_thread_->CommitPending()); 802 803 scheduler_on_impl_thread_->BeginFrameAborted(); 804} 805 806void ThreadProxy::ScheduledActionCommit() { 807 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit"); 808 DCHECK(IsImplThread()); 809 DCHECK(commit_completion_event_on_impl_thread_); 810 DCHECK(current_resource_update_controller_on_impl_thread_); 811 812 // Complete all remaining texture updates. 813 current_resource_update_controller_on_impl_thread_->Finalize(); 814 current_resource_update_controller_on_impl_thread_.reset(); 815 816 layer_tree_host_impl_->BeginCommit(); 817 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get()); 818 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get()); 819 layer_tree_host_impl_->CommitComplete(); 820 821 next_frame_is_newly_committed_frame_on_impl_thread_ = true; 822 823 if (layer_tree_host_->settings().impl_side_painting && 824 layer_tree_host_->BlocksPendingCommit()) { 825 // For some layer types in impl-side painting, the commit is held until 826 // the pending tree is activated. 827 TRACE_EVENT_INSTANT0("cc", "HoldCommit"); 828 completion_event_for_commit_held_on_tree_activation_ = 829 commit_completion_event_on_impl_thread_; 830 commit_completion_event_on_impl_thread_ = NULL; 831 } else { 832 commit_completion_event_on_impl_thread_->Signal(); 833 commit_completion_event_on_impl_thread_ = NULL; 834 } 835 836 // SetVisible kicks off the next scheduler action, so this must be last. 837 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); 838} 839 840void ThreadProxy::ScheduledActionCheckForCompletedTileUploads() { 841 DCHECK(IsImplThread()); 842 TRACE_EVENT0("cc", 843 "ThreadProxy::ScheduledActionCheckForCompletedTileUploads"); 844 layer_tree_host_impl_->CheckForCompletedTileUploads(); 845} 846 847void ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded() { 848 DCHECK(IsImplThread()); 849 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded"); 850 layer_tree_host_impl_->ActivatePendingTreeIfNeeded(); 851} 852 853void ThreadProxy::ScheduledActionBeginContextRecreation() { 854 DCHECK(IsImplThread()); 855 Proxy::MainThread()->PostTask( 856 base::Bind(&ThreadProxy::BeginContextRecreation, main_thread_weak_ptr_)); 857} 858 859ScheduledActionDrawAndSwapResult 860ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) { 861 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap"); 862 863 base::AutoReset<bool> mark_inside(&inside_draw_, true); 864 865 ScheduledActionDrawAndSwapResult result; 866 result.did_draw = false; 867 result.did_swap = false; 868 DCHECK(IsImplThread()); 869 DCHECK(layer_tree_host_impl_.get()); 870 if (!layer_tree_host_impl_) 871 return result; 872 873 DCHECK(layer_tree_host_impl_->renderer()); 874 if (!layer_tree_host_impl_->renderer()) 875 return result; 876 877 // FIXME: compute the frame display time more intelligently 878 base::TimeTicks monotonic_time = base::TimeTicks::Now(); 879 base::Time wall_clock_time = base::Time::Now(); 880 881 if (input_handler_on_impl_thread_) 882 input_handler_on_impl_thread_->Animate(monotonic_time); 883 884 layer_tree_host_impl_->ActivatePendingTreeIfNeeded(); 885 layer_tree_host_impl_->Animate(monotonic_time, wall_clock_time); 886 887 // This method is called on a forced draw, regardless of whether we are able 888 // to produce a frame, as the calling site on main thread is blocked until its 889 // request completes, and we signal completion here. If canDraw() is false, we 890 // will indicate success=false to the caller, but we must still signal 891 // completion to avoid deadlock. 892 893 // We guard prepareToDraw() with canDraw() because it always returns a valid 894 // frame, so can only be used when such a frame is possible. Since 895 // drawLayers() depends on the result of prepareToDraw(), it is guarded on 896 // canDraw() as well. 897 898 LayerTreeHostImpl::FrameData frame; 899 bool draw_frame = 900 layer_tree_host_impl_->CanDraw() && 901 (layer_tree_host_impl_->PrepareToDraw(&frame) || forced_draw); 902 if (draw_frame) { 903 layer_tree_host_impl_->DrawLayers( 904 &frame, 905 scheduler_on_impl_thread_->LastVSyncTime()); 906 result.did_draw= true; 907 } 908 layer_tree_host_impl_->DidDrawAllLayers(frame); 909 910 // Check for tree activation. 911 if (completion_event_for_commit_held_on_tree_activation_ && 912 !layer_tree_host_impl_->pending_tree()) { 913 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation"); 914 DCHECK(layer_tree_host_impl_->settings().impl_side_painting); 915 completion_event_for_commit_held_on_tree_activation_->Signal(); 916 completion_event_for_commit_held_on_tree_activation_ = NULL; 917 } 918 919 // Check for a pending CompositeAndReadback. 920 if (readback_request_on_impl_thread_) { 921 readback_request_on_impl_thread_->success = false; 922 if (draw_frame) { 923 layer_tree_host_impl_->Readback(readback_request_on_impl_thread_->pixels, 924 readback_request_on_impl_thread_->rect); 925 readback_request_on_impl_thread_->success = 926 !layer_tree_host_impl_->IsContextLost(); 927 } 928 readback_request_on_impl_thread_->completion.Signal(); 929 readback_request_on_impl_thread_ = NULL; 930 } else if (draw_frame) { 931 result.did_swap = layer_tree_host_impl_->SwapBuffers(); 932 933 if (frame.contains_incomplete_tile) 934 DidSwapUseIncompleteTileOnImplThread(); 935 } 936 937 // Tell the main thread that the the newly-commited frame was drawn. 938 if (next_frame_is_newly_committed_frame_on_impl_thread_) { 939 next_frame_is_newly_committed_frame_on_impl_thread_ = false; 940 Proxy::MainThread()->PostTask( 941 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_)); 942 } 943 944 if (draw_frame) 945 CheckOutputSurfaceStatusOnImplThread(); 946 947 layer_tree_host_impl_->BeginNextFrame(); 948 949 return result; 950} 951 952void ThreadProxy::AcquireLayerTextures() { 953 // Called when the main thread needs to modify a layer texture that is used 954 // directly by the compositor. 955 // This method will block until the next compositor draw if there is a 956 // previously committed frame that is still undrawn. This is necessary to 957 // ensure that the main thread does not monopolize access to the textures. 958 DCHECK(IsMainThread()); 959 960 if (textures_acquired_) 961 return; 962 963 TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures"); 964 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 965 CompletionEvent completion; 966 Proxy::ImplThread()->PostTask( 967 base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread, 968 impl_thread_weak_ptr_, 969 &completion)); 970 // Block until it is safe to write to layer textures from the main thread. 971 completion.Wait(); 972 973 textures_acquired_ = true; 974} 975 976void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread( 977 CompletionEvent* completion) { 978 DCHECK(IsImplThread()); 979 DCHECK(!texture_acquisition_completion_event_on_impl_thread_); 980 981 texture_acquisition_completion_event_on_impl_thread_ = completion; 982 scheduler_on_impl_thread_->SetMainThreadNeedsLayerTextures(); 983} 984 985void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() { 986 DCHECK(texture_acquisition_completion_event_on_impl_thread_); 987 texture_acquisition_completion_event_on_impl_thread_->Signal(); 988 texture_acquisition_completion_event_on_impl_thread_ = NULL; 989} 990 991ScheduledActionDrawAndSwapResult 992ThreadProxy::ScheduledActionDrawAndSwapIfPossible() { 993 return ScheduledActionDrawAndSwapInternal(false); 994} 995 996ScheduledActionDrawAndSwapResult 997ThreadProxy::ScheduledActionDrawAndSwapForced() { 998 return ScheduledActionDrawAndSwapInternal(true); 999} 1000 1001void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) { 1002 if (layer_tree_host_impl_) 1003 layer_tree_host_impl_->SetAnticipatedDrawTime(time); 1004 1005 if (current_resource_update_controller_on_impl_thread_) 1006 current_resource_update_controller_on_impl_thread_->PerformMoreUpdates(time); 1007} 1008 1009void ThreadProxy::ReadyToFinalizeTextureUpdates() { 1010 DCHECK(IsImplThread()); 1011 scheduler_on_impl_thread_->BeginFrameComplete(); 1012} 1013 1014void ThreadProxy::DidCommitAndDrawFrame() { 1015 DCHECK(IsMainThread()); 1016 if (!layer_tree_host_) 1017 return; 1018 layer_tree_host_->DidCommitAndDrawFrame(); 1019} 1020 1021void ThreadProxy::DidCompleteSwapBuffers() { 1022 DCHECK(IsMainThread()); 1023 if (!layer_tree_host_) 1024 return; 1025 layer_tree_host_->DidCompleteSwapBuffers(); 1026} 1027 1028void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events, 1029 base::Time wall_clock_time) { 1030 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents"); 1031 DCHECK(IsMainThread()); 1032 if (!layer_tree_host_) 1033 return; 1034 layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time); 1035} 1036 1037void ThreadProxy::BeginContextRecreation() { 1038 TRACE_EVENT0("cc", "ThreadProxy::BeginContextRecreation"); 1039 DCHECK(IsMainThread()); 1040 layer_tree_host_->DidLoseOutputSurface(); 1041 output_surface_recreation_callback_.Reset(base::Bind( 1042 &ThreadProxy::TryToRecreateOutputSurface, base::Unretained(this))); 1043 Proxy::MainThread()->PostTask(output_surface_recreation_callback_.callback()); 1044} 1045 1046void ThreadProxy::TryToRecreateOutputSurface() { 1047 DCHECK(IsMainThread()); 1048 DCHECK(layer_tree_host_); 1049 LayerTreeHost::RecreateResult result = 1050 layer_tree_host_->RecreateOutputSurface(); 1051 if (result == LayerTreeHost::RecreateFailedButTryAgain) 1052 Proxy::MainThread()->PostTask( 1053 output_surface_recreation_callback_.callback()); 1054 else if (result == LayerTreeHost::RecreateSucceeded) 1055 output_surface_recreation_callback_.Cancel(); 1056} 1057 1058void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion, 1059 InputHandler* handler) { 1060 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread"); 1061 DCHECK(IsImplThread()); 1062 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this); 1063 const base::TimeDelta display_refresh_interval = 1064 base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond / 1065 60); 1066 scoped_ptr<FrameRateController> frame_rate_controller; 1067 if (render_vsync_enabled_) { 1068 frame_rate_controller.reset( 1069 new FrameRateController(DelayBasedTimeSource::Create( 1070 display_refresh_interval, Proxy::ImplThread()))); 1071 } else { 1072 frame_rate_controller.reset(new FrameRateController(Proxy::ImplThread())); 1073 } 1074 SchedulerSettings scheduler_settings; 1075 scheduler_settings.impl_side_painting = 1076 layer_tree_host_->settings().impl_side_painting; 1077 scheduler_on_impl_thread_ = Scheduler::Create(this, 1078 frame_rate_controller.Pass(), 1079 scheduler_settings); 1080 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); 1081 1082 input_handler_on_impl_thread_ = scoped_ptr<InputHandler>(handler); 1083 if (input_handler_on_impl_thread_) 1084 input_handler_on_impl_thread_->BindToClient(layer_tree_host_impl_.get()); 1085 1086 impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr(); 1087 completion->Signal(); 1088} 1089 1090void ThreadProxy::InitializeOutputSurfaceOnImplThread( 1091 scoped_ptr<OutputSurface> output_surface) { 1092 TRACE_EVENT0("cc", "ThreadProxy::InitializeContextOnImplThread"); 1093 DCHECK(IsImplThread()); 1094 output_surface_before_initialization_on_impl_thread_ = output_surface.Pass(); 1095} 1096 1097void ThreadProxy::InitializeRendererOnImplThread( 1098 CompletionEvent* completion, 1099 bool* initialize_succeeded, 1100 RendererCapabilities* capabilities) { 1101 TRACE_EVENT0("cc", "ThreadProxy::InitializeRendererOnImplThread"); 1102 DCHECK(IsImplThread()); 1103 DCHECK(output_surface_before_initialization_on_impl_thread_.get()); 1104 *initialize_succeeded = layer_tree_host_impl_->InitializeRenderer( 1105 output_surface_before_initialization_on_impl_thread_.Pass()); 1106 if (*initialize_succeeded) { 1107 *capabilities = layer_tree_host_impl_->GetRendererCapabilities(); 1108 scheduler_on_impl_thread_->SetSwapBuffersCompleteSupported( 1109 capabilities->using_swap_complete_callback); 1110 1111 int max_frames_pending = layer_tree_host_impl_->output_surface()-> 1112 capabilities().max_frames_pending; 1113 if (max_frames_pending <= 0) 1114 max_frames_pending = FrameRateController::DEFAULT_MAX_FRAMES_PENDING; 1115 if (layer_tree_host_impl_->output_surface()->capabilities(). 1116 has_parent_compositor) 1117 max_frames_pending = 1; 1118 scheduler_on_impl_thread_->SetMaxFramesPending(max_frames_pending); 1119 } 1120 1121 completion->Signal(); 1122} 1123 1124void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) { 1125 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread"); 1126 DCHECK(IsImplThread()); 1127 layer_tree_host_->DeleteContentsTexturesOnImplThread( 1128 layer_tree_host_impl_->resource_provider()); 1129 input_handler_on_impl_thread_.reset(); 1130 layer_tree_host_impl_.reset(); 1131 scheduler_on_impl_thread_.reset(); 1132 weak_factory_on_impl_thread_.InvalidateWeakPtrs(); 1133 completion->Signal(); 1134} 1135 1136void ThreadProxy::SetFullRootLayerDamageOnImplThread() { 1137 DCHECK(IsImplThread()); 1138 layer_tree_host_impl_->SetFullRootLayerDamage(); 1139} 1140 1141size_t ThreadProxy::MaxPartialTextureUpdates() const { 1142 return ResourceUpdateController::MaxPartialTextureUpdates(); 1143} 1144 1145void ThreadProxy::RecreateOutputSurfaceOnImplThread( 1146 CompletionEvent* completion, 1147 scoped_ptr<OutputSurface> output_surface, 1148 scoped_refptr<cc::ContextProvider> offscreen_context_provider, 1149 bool* recreate_succeeded, 1150 RendererCapabilities* capabilities) { 1151 TRACE_EVENT0("cc", "ThreadProxy::RecreateOutputSurfaceOnImplThread"); 1152 DCHECK(IsImplThread()); 1153 1154 layer_tree_host_->DeleteContentsTexturesOnImplThread( 1155 layer_tree_host_impl_->resource_provider()); 1156 *recreate_succeeded = 1157 layer_tree_host_impl_->InitializeRenderer(output_surface.Pass()); 1158 if (offscreen_context_provider) 1159 offscreen_context_provider->BindToCurrentThread(); 1160 1161 if (*recreate_succeeded) { 1162 *capabilities = layer_tree_host_impl_->GetRendererCapabilities(); 1163 layer_tree_host_impl_->resource_provider()-> 1164 set_offscreen_context_provider(offscreen_context_provider); 1165 scheduler_on_impl_thread_->DidRecreateOutputSurface(); 1166 } else if (offscreen_context_provider) { 1167 offscreen_context_provider->VerifyContexts(); 1168 } 1169 completion->Signal(); 1170} 1171 1172ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState() 1173 : memory_allocation_limit_bytes(0) {} 1174 1175ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {} 1176 1177scoped_ptr<base::Value> ThreadProxy::AsValue() const { 1178 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); 1179 1180 CompletionEvent completion; 1181 { 1182 DebugScopedSetMainThreadBlocked main_thread_blocked( 1183 const_cast<ThreadProxy*>(this)); 1184 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::AsValueOnImplThread, 1185 impl_thread_weak_ptr_, 1186 &completion, 1187 state.get())); 1188 completion.Wait(); 1189 } 1190 return state.PassAs<base::Value>(); 1191} 1192 1193void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion, 1194 base::DictionaryValue* state) const { 1195 state->Set("layer_tree_host_impl", 1196 layer_tree_host_impl_->AsValue().release()); 1197 completion->Signal(); 1198} 1199 1200bool ThreadProxy::CommitPendingForTesting() { 1201 DCHECK(IsMainThread()); 1202 CommitPendingRequest commit_pending_request; 1203 { 1204 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 1205 Proxy::ImplThread()->PostTask( 1206 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting, 1207 impl_thread_weak_ptr_, 1208 &commit_pending_request)); 1209 commit_pending_request.completion.Wait(); 1210 } 1211 return commit_pending_request.commit_pending; 1212} 1213 1214void ThreadProxy::CommitPendingOnImplThreadForTesting( 1215 CommitPendingRequest* request) { 1216 DCHECK(IsImplThread()); 1217 if (layer_tree_host_impl_->output_surface()) 1218 request->commit_pending = scheduler_on_impl_thread_->CommitPending(); 1219 else 1220 request->commit_pending = false; 1221 request->completion.Signal(); 1222} 1223 1224skia::RefPtr<SkPicture> ThreadProxy::CapturePicture() { 1225 DCHECK(IsMainThread()); 1226 CompletionEvent completion; 1227 skia::RefPtr<SkPicture> picture; 1228 { 1229 DebugScopedSetMainThreadBlocked main_thread_blocked(this); 1230 Proxy::ImplThread()->PostTask( 1231 base::Bind(&ThreadProxy::CapturePictureOnImplThread, 1232 impl_thread_weak_ptr_, 1233 &completion, 1234 &picture)); 1235 completion.Wait(); 1236 } 1237 return picture; 1238} 1239 1240void ThreadProxy::CapturePictureOnImplThread(CompletionEvent* completion, 1241 skia::RefPtr<SkPicture>* picture) { 1242 DCHECK(IsImplThread()); 1243 *picture = layer_tree_host_impl_->CapturePicture(); 1244 completion->Signal(); 1245} 1246 1247void ThreadProxy::RenewTreePriority() { 1248 bool smoothness_takes_priority = 1249 layer_tree_host_impl_->pinch_gesture_active() || 1250 layer_tree_host_impl_->CurrentlyScrollingLayer() || 1251 layer_tree_host_impl_->page_scale_animation_active(); 1252 1253 // Update expiration time if smoothness currently takes priority. 1254 if (smoothness_takes_priority) { 1255 smoothness_takes_priority_expiration_time_ = 1256 base::TimeTicks::Now() + 1257 base::TimeDelta::FromMilliseconds( 1258 kSmoothnessTakesPriorityExpirationDelay * 1000); 1259 } 1260 1261 // We use the same priority for both trees by default. 1262 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES; 1263 1264 // Smoothness takes priority if expiration time is in the future. 1265 if (smoothness_takes_priority_expiration_time_ > base::TimeTicks::Now()) 1266 priority = SMOOTHNESS_TAKES_PRIORITY; 1267 1268 // New content always takes priority when the active tree has 1269 // evicted resources or there is an invalid viewport size. 1270 if (layer_tree_host_impl_->active_tree()->ContentsTexturesPurged() || 1271 layer_tree_host_impl_->active_tree()->ViewportSizeInvalid()) 1272 priority = NEW_CONTENT_TAKES_PRIORITY; 1273 1274 layer_tree_host_impl_->SetTreePriority(priority); 1275 1276 // Notify the the client of this compositor via the output surface. 1277 // TODO(epenner): Route this to compositor-thread instead of output-surface 1278 // after GTFO refactor of compositor-thread (http://crbug/170828). 1279 if (layer_tree_host_impl_->output_surface()) { 1280 layer_tree_host_impl_->output_surface()-> 1281 UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY); 1282 } 1283 1284 base::TimeDelta delay = 1285 smoothness_takes_priority_expiration_time_ - base::TimeTicks::Now(); 1286 1287 // Need to make sure a delayed task is posted when we have smoothness 1288 // takes priority expiration time in the future. 1289 if (delay <= base::TimeDelta()) 1290 return; 1291 if (renew_tree_priority_on_impl_thread_pending_) 1292 return; 1293 1294 Proxy::ImplThread()->PostDelayedTask( 1295 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread, 1296 weak_factory_on_impl_thread_.GetWeakPtr()), 1297 delay); 1298 1299 renew_tree_priority_on_impl_thread_pending_ = true; 1300} 1301 1302void ThreadProxy::RenewTreePriorityOnImplThread() { 1303 DCHECK(renew_tree_priority_on_impl_thread_pending_); 1304 renew_tree_priority_on_impl_thread_pending_ = false; 1305 1306 RenewTreePriority(); 1307} 1308 1309void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay) { 1310 Proxy::ImplThread()->PostDelayedTask( 1311 base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread, 1312 impl_thread_weak_ptr_), 1313 delay); 1314} 1315 1316void ThreadProxy::StartScrollbarAnimationOnImplThread() { 1317 layer_tree_host_impl_->StartScrollbarAnimation(base::TimeTicks::Now()); 1318} 1319 1320} // namespace cc 1321