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/single_thread_proxy.h"
      6 
      7 #include "base/auto_reset.h"
      8 #include "base/debug/trace_event.h"
      9 #include "cc/debug/benchmark_instrumentation.h"
     10 #include "cc/output/context_provider.h"
     11 #include "cc/output/output_surface.h"
     12 #include "cc/quads/draw_quad.h"
     13 #include "cc/resources/prioritized_resource_manager.h"
     14 #include "cc/resources/resource_update_controller.h"
     15 #include "cc/trees/blocking_task_runner.h"
     16 #include "cc/trees/layer_tree_host.h"
     17 #include "cc/trees/layer_tree_host_single_thread_client.h"
     18 #include "cc/trees/layer_tree_impl.h"
     19 #include "cc/trees/scoped_abort_remaining_swap_promises.h"
     20 #include "ui/gfx/frame_time.h"
     21 
     22 namespace cc {
     23 
     24 scoped_ptr<Proxy> SingleThreadProxy::Create(
     25     LayerTreeHost* layer_tree_host,
     26     LayerTreeHostSingleThreadClient* client,
     27     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) {
     28   return make_scoped_ptr(
     29              new SingleThreadProxy(layer_tree_host, client, main_task_runner))
     30       .PassAs<Proxy>();
     31 }
     32 
     33 SingleThreadProxy::SingleThreadProxy(
     34     LayerTreeHost* layer_tree_host,
     35     LayerTreeHostSingleThreadClient* client,
     36     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
     37     : Proxy(main_task_runner, NULL),
     38       layer_tree_host_(layer_tree_host),
     39       client_(client),
     40       timing_history_(layer_tree_host->rendering_stats_instrumentation()),
     41       next_frame_is_newly_committed_frame_(false),
     42       inside_draw_(false),
     43       defer_commits_(false),
     44       commit_was_deferred_(false),
     45       commit_requested_(false),
     46       weak_factory_(this) {
     47   TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
     48   DCHECK(Proxy::IsMainThread());
     49   DCHECK(layer_tree_host);
     50 
     51   // Impl-side painting not supported without threaded compositing.
     52   CHECK(!layer_tree_host->settings().impl_side_painting)
     53       << "Threaded compositing must be enabled to use impl-side painting.";
     54 }
     55 
     56 void SingleThreadProxy::Start() {
     57   DebugScopedSetImplThread impl(this);
     58   layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
     59 }
     60 
     61 SingleThreadProxy::~SingleThreadProxy() {
     62   TRACE_EVENT0("cc", "SingleThreadProxy::~SingleThreadProxy");
     63   DCHECK(Proxy::IsMainThread());
     64   // Make sure Stop() got called or never Started.
     65   DCHECK(!layer_tree_host_impl_);
     66 }
     67 
     68 void SingleThreadProxy::FinishAllRendering() {
     69   TRACE_EVENT0("cc", "SingleThreadProxy::FinishAllRendering");
     70   DCHECK(Proxy::IsMainThread());
     71   {
     72     DebugScopedSetImplThread impl(this);
     73     layer_tree_host_impl_->FinishAllRendering();
     74   }
     75 }
     76 
     77 bool SingleThreadProxy::IsStarted() const {
     78   DCHECK(Proxy::IsMainThread());
     79   return layer_tree_host_impl_;
     80 }
     81 
     82 void SingleThreadProxy::SetLayerTreeHostClientReady() {
     83   TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
     84   // Scheduling is controlled by the embedder in the single thread case, so
     85   // nothing to do.
     86   DCHECK(Proxy::IsMainThread());
     87   DebugScopedSetImplThread impl(this);
     88   if (layer_tree_host_->settings().single_thread_proxy_scheduler &&
     89       !scheduler_on_impl_thread_) {
     90     SchedulerSettings scheduler_settings(layer_tree_host_->settings());
     91     scheduler_on_impl_thread_ = Scheduler::Create(this,
     92                                                   scheduler_settings,
     93                                                   layer_tree_host_->id(),
     94                                                   MainThreadTaskRunner());
     95     scheduler_on_impl_thread_->SetCanStart();
     96     scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
     97   }
     98 }
     99 
    100 void SingleThreadProxy::SetVisible(bool visible) {
    101   TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible");
    102   DebugScopedSetImplThread impl(this);
    103   layer_tree_host_impl_->SetVisible(visible);
    104   if (scheduler_on_impl_thread_)
    105     scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
    106   // Changing visibility could change ShouldComposite().
    107   UpdateBackgroundAnimateTicking();
    108 }
    109 
    110 void SingleThreadProxy::RequestNewOutputSurface() {
    111   DCHECK(Proxy::IsMainThread());
    112   DCHECK(layer_tree_host_->output_surface_lost());
    113   layer_tree_host_->RequestNewOutputSurface();
    114 }
    115 
    116 void SingleThreadProxy::SetOutputSurface(
    117     scoped_ptr<OutputSurface> output_surface) {
    118   DCHECK(Proxy::IsMainThread());
    119   DCHECK(layer_tree_host_->output_surface_lost());
    120   renderer_capabilities_for_main_thread_ = RendererCapabilities();
    121 
    122   bool success = !!output_surface;
    123   if (success) {
    124     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
    125     DebugScopedSetImplThread impl(this);
    126     layer_tree_host_->DeleteContentsTexturesOnImplThread(
    127         layer_tree_host_impl_->resource_provider());
    128     success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
    129   }
    130 
    131   layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
    132 
    133   if (success) {
    134     if (scheduler_on_impl_thread_)
    135       scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
    136   } else if (Proxy::MainThreadTaskRunner()) {
    137     MainThreadTaskRunner()->PostTask(
    138         FROM_HERE,
    139         base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
    140                    weak_factory_.GetWeakPtr()));
    141   }
    142 }
    143 
    144 const RendererCapabilities& SingleThreadProxy::GetRendererCapabilities() const {
    145   DCHECK(Proxy::IsMainThread());
    146   DCHECK(!layer_tree_host_->output_surface_lost());
    147   return renderer_capabilities_for_main_thread_;
    148 }
    149 
    150 void SingleThreadProxy::SetNeedsAnimate() {
    151   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
    152   DCHECK(Proxy::IsMainThread());
    153   client_->ScheduleAnimation();
    154   SetNeedsCommit();
    155 }
    156 
    157 void SingleThreadProxy::SetNeedsUpdateLayers() {
    158   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
    159   DCHECK(Proxy::IsMainThread());
    160   SetNeedsCommit();
    161 }
    162 
    163 void SingleThreadProxy::DoCommit(const BeginFrameArgs& begin_frame_args) {
    164   TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
    165   DCHECK(Proxy::IsMainThread());
    166   layer_tree_host_->WillBeginMainFrame();
    167   layer_tree_host_->BeginMainFrame(begin_frame_args);
    168   layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
    169   layer_tree_host_->Layout();
    170   commit_requested_ = false;
    171 
    172   if (PrioritizedResourceManager* contents_texture_manager =
    173           layer_tree_host_->contents_texture_manager()) {
    174     contents_texture_manager->UnlinkAndClearEvictedBackings();
    175     contents_texture_manager->SetMaxMemoryLimitBytes(
    176         layer_tree_host_impl_->memory_allocation_limit_bytes());
    177     contents_texture_manager->SetExternalPriorityCutoff(
    178         layer_tree_host_impl_->memory_allocation_priority_cutoff());
    179   }
    180 
    181   scoped_ptr<ResourceUpdateQueue> queue =
    182       make_scoped_ptr(new ResourceUpdateQueue);
    183 
    184   layer_tree_host_->UpdateLayers(queue.get());
    185 
    186   layer_tree_host_->WillCommit();
    187 
    188   // Commit immediately.
    189   {
    190     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
    191     DebugScopedSetImplThread impl(this);
    192 
    193     // This CapturePostTasks should be destroyed before CommitComplete() is
    194     // called since that goes out to the embedder, and we want the embedder
    195     // to receive its callbacks before that.
    196     BlockingTaskRunner::CapturePostTasks blocked(
    197         blocking_main_thread_task_runner());
    198 
    199     layer_tree_host_impl_->BeginCommit();
    200 
    201     if (PrioritizedResourceManager* contents_texture_manager =
    202         layer_tree_host_->contents_texture_manager()) {
    203       contents_texture_manager->PushTexturePrioritiesToBackings();
    204     }
    205     layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
    206 
    207     scoped_ptr<ResourceUpdateController> update_controller =
    208         ResourceUpdateController::Create(
    209             NULL,
    210             MainThreadTaskRunner(),
    211             queue.Pass(),
    212             layer_tree_host_impl_->resource_provider());
    213     update_controller->Finalize();
    214 
    215     if (layer_tree_host_impl_->EvictedUIResourcesExist())
    216       layer_tree_host_->RecreateUIResources();
    217 
    218     layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
    219 
    220     layer_tree_host_impl_->CommitComplete();
    221 
    222     UpdateBackgroundAnimateTicking();
    223 
    224 #if DCHECK_IS_ON
    225     // In the single-threaded case, the scale and scroll deltas should never be
    226     // touched on the impl layer tree.
    227     scoped_ptr<ScrollAndScaleSet> scroll_info =
    228         layer_tree_host_impl_->ProcessScrollDeltas();
    229     DCHECK(!scroll_info->scrolls.size());
    230     DCHECK_EQ(1.f, scroll_info->page_scale_delta);
    231 #endif
    232 
    233     RenderingStatsInstrumentation* stats_instrumentation =
    234         layer_tree_host_->rendering_stats_instrumentation();
    235     benchmark_instrumentation::IssueMainThreadRenderingStatsEvent(
    236         stats_instrumentation->main_thread_rendering_stats());
    237     stats_instrumentation->AccumulateAndClearMainThreadStats();
    238   }
    239   layer_tree_host_->CommitComplete();
    240   layer_tree_host_->DidBeginMainFrame();
    241   timing_history_.DidCommit();
    242 
    243   next_frame_is_newly_committed_frame_ = true;
    244 }
    245 
    246 void SingleThreadProxy::SetNeedsCommit() {
    247   DCHECK(Proxy::IsMainThread());
    248   DebugScopedSetImplThread impl(this);
    249   client_->ScheduleComposite();
    250   if (scheduler_on_impl_thread_)
    251     scheduler_on_impl_thread_->SetNeedsCommit();
    252   commit_requested_ = true;
    253 }
    254 
    255 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
    256   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
    257   DCHECK(Proxy::IsMainThread());
    258   DebugScopedSetImplThread impl(this);
    259   client_->ScheduleComposite();
    260   SetNeedsRedrawRectOnImplThread(damage_rect);
    261 }
    262 
    263 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
    264   // There is no activation here other than commit. So do nothing.
    265   DCHECK(Proxy::IsMainThread());
    266 }
    267 
    268 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
    269   DCHECK(Proxy::IsMainThread());
    270   // Deferring commits only makes sense if there's a scheduler.
    271   if (!scheduler_on_impl_thread_)
    272     return;
    273   if (defer_commits_ == defer_commits)
    274     return;
    275 
    276   if (defer_commits)
    277     TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
    278   else
    279     TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
    280 
    281   defer_commits_ = defer_commits;
    282   if (!defer_commits_ && commit_was_deferred_) {
    283     commit_was_deferred_ = false;
    284     BeginMainFrame();
    285   }
    286 }
    287 
    288 bool SingleThreadProxy::CommitRequested() const {
    289   DCHECK(Proxy::IsMainThread());
    290   return commit_requested_;
    291 }
    292 
    293 bool SingleThreadProxy::BeginMainFrameRequested() const {
    294   DCHECK(Proxy::IsMainThread());
    295   // If there is no scheduler, then there can be no pending begin frame,
    296   // as all frames are all manually initiated by the embedder of cc.
    297   if (!scheduler_on_impl_thread_)
    298     return false;
    299   return commit_requested_;
    300 }
    301 
    302 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
    303   return std::numeric_limits<size_t>::max();
    304 }
    305 
    306 void SingleThreadProxy::Stop() {
    307   TRACE_EVENT0("cc", "SingleThreadProxy::stop");
    308   DCHECK(Proxy::IsMainThread());
    309   {
    310     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
    311     DebugScopedSetImplThread impl(this);
    312 
    313     BlockingTaskRunner::CapturePostTasks blocked(
    314         blocking_main_thread_task_runner());
    315     layer_tree_host_->DeleteContentsTexturesOnImplThread(
    316         layer_tree_host_impl_->resource_provider());
    317     scheduler_on_impl_thread_.reset();
    318     layer_tree_host_impl_.reset();
    319   }
    320   layer_tree_host_ = NULL;
    321 }
    322 
    323 void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
    324   TRACE_EVENT1(
    325       "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
    326   DCHECK(Proxy::IsImplThread());
    327   UpdateBackgroundAnimateTicking();
    328   if (scheduler_on_impl_thread_)
    329     scheduler_on_impl_thread_->SetCanDraw(can_draw);
    330 }
    331 
    332 void SingleThreadProxy::NotifyReadyToActivate() {
    333   // Impl-side painting only.
    334   NOTREACHED();
    335 }
    336 
    337 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
    338   client_->ScheduleComposite();
    339   if (scheduler_on_impl_thread_)
    340     scheduler_on_impl_thread_->SetNeedsRedraw();
    341 }
    342 
    343 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
    344   SetNeedsRedrawOnImplThread();
    345 }
    346 
    347 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
    348   // Impl-side painting only.
    349   NOTREACHED();
    350 }
    351 
    352 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
    353     const gfx::Rect& damage_rect) {
    354   layer_tree_host_impl_->SetViewportDamage(damage_rect);
    355   SetNeedsRedrawOnImplThread();
    356 }
    357 
    358 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
    359   // Impl-side painting only.
    360   NOTREACHED();
    361 }
    362 
    363 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
    364   client_->ScheduleComposite();
    365   if (scheduler_on_impl_thread_)
    366     scheduler_on_impl_thread_->SetNeedsCommit();
    367 }
    368 
    369 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
    370     scoped_ptr<AnimationEventsVector> events) {
    371   TRACE_EVENT0(
    372       "cc", "SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
    373   DCHECK(Proxy::IsImplThread());
    374   DebugScopedSetMainThread main(this);
    375   layer_tree_host_->SetAnimationEvents(events.Pass());
    376 }
    377 
    378 bool SingleThreadProxy::ReduceContentsTextureMemoryOnImplThread(
    379     size_t limit_bytes,
    380     int priority_cutoff) {
    381   DCHECK(IsImplThread());
    382   PrioritizedResourceManager* contents_texture_manager =
    383       layer_tree_host_->contents_texture_manager();
    384 
    385   ResourceProvider* resource_provider =
    386       layer_tree_host_impl_->resource_provider();
    387 
    388   if (!contents_texture_manager || !resource_provider)
    389     return false;
    390 
    391   return contents_texture_manager->ReduceMemoryOnImplThread(
    392       limit_bytes, priority_cutoff, resource_provider);
    393 }
    394 
    395 bool SingleThreadProxy::IsInsideDraw() { return inside_draw_; }
    396 
    397 void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
    398   DCHECK(IsImplThread());
    399   renderer_capabilities_for_main_thread_ =
    400       layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
    401 }
    402 
    403 void SingleThreadProxy::DidManageTiles() {
    404   // Impl-side painting only.
    405   NOTREACHED();
    406 }
    407 
    408 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
    409   TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
    410   {
    411     DebugScopedSetMainThread main(this);
    412     // This must happen before we notify the scheduler as it may try to recreate
    413     // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
    414     layer_tree_host_->DidLoseOutputSurface();
    415   }
    416   client_->DidAbortSwapBuffers();
    417   if (scheduler_on_impl_thread_)
    418     scheduler_on_impl_thread_->DidLoseOutputSurface();
    419 }
    420 
    421 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
    422   TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
    423   if (scheduler_on_impl_thread_)
    424     scheduler_on_impl_thread_->DidSwapBuffers();
    425   client_->DidPostSwapBuffers();
    426 }
    427 
    428 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
    429   TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
    430   if (scheduler_on_impl_thread_)
    431     scheduler_on_impl_thread_->DidSwapBuffersComplete();
    432   layer_tree_host_->DidCompleteSwapBuffers();
    433 }
    434 
    435 void SingleThreadProxy::BeginFrame(const BeginFrameArgs& args) {
    436   TRACE_EVENT0("cc", "SingleThreadProxy::BeginFrame");
    437   if (scheduler_on_impl_thread_)
    438     scheduler_on_impl_thread_->BeginFrame(args);
    439 }
    440 
    441 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
    442   TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately");
    443   DCHECK(Proxy::IsMainThread());
    444   DCHECK(!layer_tree_host_->output_surface_lost());
    445 
    446   BeginFrameArgs begin_frame_args = BeginFrameArgs::Create(
    447       frame_begin_time, base::TimeTicks(), BeginFrameArgs::DefaultInterval());
    448   DoCommit(begin_frame_args);
    449 
    450   LayerTreeHostImpl::FrameData frame;
    451   DoComposite(frame_begin_time, &frame);
    452 }
    453 
    454 void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
    455   // The following line casts away const modifiers because it is just
    456   // setting debug state. We still want the AsValue() function and its
    457   // call chain to be const throughout.
    458   DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
    459 
    460   state->BeginDictionary("layer_tree_host_impl");
    461   layer_tree_host_impl_->AsValueInto(state);
    462   state->EndDictionary();
    463 }
    464 
    465 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
    466   {
    467     DebugScopedSetImplThread impl(this);
    468     if (layer_tree_host_impl_->renderer()) {
    469       DCHECK(!layer_tree_host_->output_surface_lost());
    470       layer_tree_host_impl_->renderer()->DoNoOp();
    471     }
    472   }
    473 }
    474 
    475 bool SingleThreadProxy::SupportsImplScrolling() const {
    476   return false;
    477 }
    478 
    479 bool SingleThreadProxy::ShouldComposite() const {
    480   DCHECK(Proxy::IsImplThread());
    481   return layer_tree_host_impl_->visible() &&
    482          layer_tree_host_impl_->CanDraw();
    483 }
    484 
    485 void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
    486   DCHECK(Proxy::IsImplThread());
    487   layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
    488       !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
    489 }
    490 
    491 DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
    492                                           LayerTreeHostImpl::FrameData* frame) {
    493   TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
    494   DCHECK(!layer_tree_host_->output_surface_lost());
    495 
    496   {
    497     DebugScopedSetImplThread impl(this);
    498     base::AutoReset<bool> mark_inside(&inside_draw_, true);
    499 
    500     // We guard PrepareToDraw() with CanDraw() because it always returns a valid
    501     // frame, so can only be used when such a frame is possible. Since
    502     // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
    503     // CanDraw() as well.
    504     if (!ShouldComposite()) {
    505       UpdateBackgroundAnimateTicking();
    506       return DRAW_ABORTED_CANT_DRAW;
    507     }
    508 
    509     timing_history_.DidStartDrawing();
    510 
    511     layer_tree_host_impl_->Animate(
    512         layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
    513     UpdateBackgroundAnimateTicking();
    514 
    515     layer_tree_host_impl_->PrepareToDraw(frame);
    516     layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
    517     layer_tree_host_impl_->DidDrawAllLayers(*frame);
    518 
    519     bool start_ready_animations = true;
    520     layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
    521 
    522     layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
    523 
    524     timing_history_.DidFinishDrawing();
    525   }
    526 
    527   {
    528     DebugScopedSetImplThread impl(this);
    529 
    530     // This CapturePostTasks should be destroyed before
    531     // DidCommitAndDrawFrame() is called since that goes out to the
    532     // embedder,
    533     // and we want the embedder to receive its callbacks before that.
    534     // NOTE: This maintains consistent ordering with the ThreadProxy since
    535     // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
    536     // there as the main thread is not blocked, so any posted tasks inside
    537     // the swap buffers will execute first.
    538     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
    539 
    540     BlockingTaskRunner::CapturePostTasks blocked(
    541         blocking_main_thread_task_runner());
    542     layer_tree_host_impl_->SwapBuffers(*frame);
    543   }
    544   DidCommitAndDrawFrame();
    545 
    546   return DRAW_SUCCESS;
    547 }
    548 
    549 void SingleThreadProxy::DidCommitAndDrawFrame() {
    550   if (next_frame_is_newly_committed_frame_) {
    551     DebugScopedSetMainThread main(this);
    552     next_frame_is_newly_committed_frame_ = false;
    553     layer_tree_host_->DidCommitAndDrawFrame();
    554   }
    555 }
    556 
    557 bool SingleThreadProxy::MainFrameWillHappenForTesting() {
    558   return false;
    559 }
    560 
    561 void SingleThreadProxy::SetNeedsBeginFrame(bool enable) {
    562   layer_tree_host_impl_->SetNeedsBeginFrame(enable);
    563 }
    564 
    565 void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
    566   layer_tree_host_impl_->WillBeginImplFrame(args);
    567 }
    568 
    569 void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
    570   TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
    571   // Although this proxy is single-threaded, it's problematic to synchronously
    572   // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame.  This
    573   // could cause a commit to occur in between a series of SetNeedsCommit calls
    574   // (i.e. property modifications) causing some to fall on one frame and some to
    575   // fall on the next.  Doing it asynchronously instead matches the semantics of
    576   // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
    577   // synchronous commit.
    578   MainThreadTaskRunner()->PostTask(
    579       FROM_HERE,
    580       base::Bind(&SingleThreadProxy::BeginMainFrame,
    581                  weak_factory_.GetWeakPtr()));
    582 }
    583 
    584 void SingleThreadProxy::BeginMainFrame() {
    585   if (defer_commits_) {
    586     DCHECK(!commit_was_deferred_);
    587     commit_was_deferred_ = true;
    588     layer_tree_host_->DidDeferCommit();
    589     return;
    590   }
    591 
    592   // This checker assumes NotifyReadyToCommit below causes a synchronous commit.
    593   ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
    594 
    595   if (!layer_tree_host_->visible()) {
    596     TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
    597     BeginMainFrameAbortedOnImplThread();
    598     return;
    599   }
    600 
    601   if (layer_tree_host_->output_surface_lost()) {
    602     TRACE_EVENT_INSTANT0(
    603         "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
    604     BeginMainFrameAbortedOnImplThread();
    605     return;
    606   }
    607 
    608   timing_history_.DidBeginMainFrame();
    609 
    610   DCHECK(scheduler_on_impl_thread_);
    611   scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
    612   scheduler_on_impl_thread_->NotifyReadyToCommit();
    613 }
    614 
    615 void SingleThreadProxy::BeginMainFrameAbortedOnImplThread() {
    616   DebugScopedSetImplThread impl(this);
    617   DCHECK(scheduler_on_impl_thread_->CommitPending());
    618   DCHECK(!layer_tree_host_impl_->pending_tree());
    619 
    620   // TODO(enne): SingleThreadProxy does not support cancelling commits yet so
    621   // did_handle is always false.
    622   bool did_handle = false;
    623   layer_tree_host_impl_->BeginMainFrameAborted(did_handle);
    624   scheduler_on_impl_thread_->BeginMainFrameAborted(did_handle);
    625 }
    626 
    627 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
    628   DebugScopedSetImplThread impl(this);
    629   LayerTreeHostImpl::FrameData frame;
    630   return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time,
    631                      &frame);
    632 }
    633 
    634 DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
    635   NOTREACHED();
    636   return INVALID_RESULT;
    637 }
    638 
    639 void SingleThreadProxy::ScheduledActionCommit() {
    640   DebugScopedSetMainThread main(this);
    641   DoCommit(layer_tree_host_impl_->CurrentBeginFrameArgs());
    642 }
    643 
    644 void SingleThreadProxy::ScheduledActionAnimate() {
    645   TRACE_EVENT0("cc", "ScheduledActionAnimate");
    646   layer_tree_host_impl_->Animate(
    647       layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
    648 }
    649 
    650 void SingleThreadProxy::ScheduledActionUpdateVisibleTiles() {
    651   // Impl-side painting only.
    652   NOTREACHED();
    653 }
    654 
    655 void SingleThreadProxy::ScheduledActionActivateSyncTree() {
    656 }
    657 
    658 void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
    659   DebugScopedSetMainThread main(this);
    660   DCHECK(scheduler_on_impl_thread_);
    661   // If possible, create the output surface in a post task.  Synchronously
    662   // creating the output surface makes tests more awkward since this differs
    663   // from the ThreadProxy behavior.  However, sometimes there is no
    664   // task runner.
    665   if (Proxy::MainThreadTaskRunner()) {
    666     MainThreadTaskRunner()->PostTask(
    667         FROM_HERE,
    668         base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
    669                    weak_factory_.GetWeakPtr()));
    670   } else {
    671     RequestNewOutputSurface();
    672   }
    673 }
    674 
    675 void SingleThreadProxy::ScheduledActionManageTiles() {
    676   // Impl-side painting only.
    677   NOTREACHED();
    678 }
    679 
    680 void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
    681 }
    682 
    683 base::TimeDelta SingleThreadProxy::DrawDurationEstimate() {
    684   return timing_history_.DrawDurationEstimate();
    685 }
    686 
    687 base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
    688   return timing_history_.BeginMainFrameToCommitDurationEstimate();
    689 }
    690 
    691 base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() {
    692   return timing_history_.CommitToActivateDurationEstimate();
    693 }
    694 
    695 void SingleThreadProxy::DidBeginImplFrameDeadline() {
    696   layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
    697 }
    698 
    699 }  // namespace cc
    700