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