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