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