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