Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / cc / trees / single_thread_proxy.cc
index f400733..97b06bc 100644 (file)
@@ -16,6 +16,7 @@
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_host_single_thread_client.h"
 #include "cc/trees/layer_tree_impl.h"
+#include "cc/trees/scoped_abort_remaining_swap_promises.h"
 #include "ui/gfx/frame_time.h"
 
 namespace cc {
@@ -36,8 +37,13 @@ SingleThreadProxy::SingleThreadProxy(
     : Proxy(main_task_runner, NULL),
       layer_tree_host_(layer_tree_host),
       client_(client),
+      timing_history_(layer_tree_host->rendering_stats_instrumentation()),
       next_frame_is_newly_committed_frame_(false),
-      inside_draw_(false) {
+      inside_draw_(false),
+      defer_commits_(false),
+      commit_was_deferred_(false),
+      commit_requested_(false),
+      weak_factory_(this) {
   TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy");
   DCHECK(Proxy::IsMainThread());
   DCHECK(layer_tree_host);
@@ -77,26 +83,40 @@ void SingleThreadProxy::SetLayerTreeHostClientReady() {
   TRACE_EVENT0("cc", "SingleThreadProxy::SetLayerTreeHostClientReady");
   // Scheduling is controlled by the embedder in the single thread case, so
   // nothing to do.
+  DCHECK(Proxy::IsMainThread());
+  DebugScopedSetImplThread impl(this);
+  if (layer_tree_host_->settings().single_thread_proxy_scheduler &&
+      !scheduler_on_impl_thread_) {
+    SchedulerSettings scheduler_settings(layer_tree_host_->settings());
+    scheduler_on_impl_thread_ = Scheduler::Create(this,
+                                                  scheduler_settings,
+                                                  layer_tree_host_->id(),
+                                                  MainThreadTaskRunner());
+    scheduler_on_impl_thread_->SetCanStart();
+    scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
+  }
 }
 
 void SingleThreadProxy::SetVisible(bool visible) {
   TRACE_EVENT0("cc", "SingleThreadProxy::SetVisible");
   DebugScopedSetImplThread impl(this);
   layer_tree_host_impl_->SetVisible(visible);
-
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
   // Changing visibility could change ShouldComposite().
   UpdateBackgroundAnimateTicking();
 }
 
-void SingleThreadProxy::CreateAndInitializeOutputSurface() {
-  TRACE_EVENT0(
-      "cc", "SingleThreadProxy::CreateAndInitializeOutputSurface");
+void SingleThreadProxy::RequestNewOutputSurface() {
   DCHECK(Proxy::IsMainThread());
   DCHECK(layer_tree_host_->output_surface_lost());
+  layer_tree_host_->RequestNewOutputSurface();
+}
 
-  scoped_ptr<OutputSurface> output_surface =
-      layer_tree_host_->CreateOutputSurface();
-
+void SingleThreadProxy::SetOutputSurface(
+    scoped_ptr<OutputSurface> output_surface) {
+  DCHECK(Proxy::IsMainThread());
+  DCHECK(layer_tree_host_->output_surface_lost());
   renderer_capabilities_for_main_thread_ = RendererCapabilities();
 
   bool success = !!output_surface;
@@ -110,9 +130,14 @@ void SingleThreadProxy::CreateAndInitializeOutputSurface() {
 
   layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
 
-  if (!success) {
-    // Force another recreation attempt to happen by requesting another commit.
-    SetNeedsCommit();
+  if (success) {
+    if (scheduler_on_impl_thread_)
+      scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
+  } else if (Proxy::MainThreadTaskRunner()) {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
+                   weak_factory_.GetWeakPtr()));
   }
 }
 
@@ -126,17 +151,40 @@ void SingleThreadProxy::SetNeedsAnimate() {
   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsAnimate");
   DCHECK(Proxy::IsMainThread());
   client_->ScheduleAnimation();
+  SetNeedsCommit();
 }
 
 void SingleThreadProxy::SetNeedsUpdateLayers() {
   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsUpdateLayers");
   DCHECK(Proxy::IsMainThread());
-  client_->ScheduleComposite();
+  SetNeedsCommit();
 }
 
-void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
+void SingleThreadProxy::DoCommit(const BeginFrameArgs& begin_frame_args) {
   TRACE_EVENT0("cc", "SingleThreadProxy::DoCommit");
   DCHECK(Proxy::IsMainThread());
+  layer_tree_host_->WillBeginMainFrame();
+  layer_tree_host_->BeginMainFrame(begin_frame_args);
+  layer_tree_host_->AnimateLayers(begin_frame_args.frame_time);
+  layer_tree_host_->Layout();
+  commit_requested_ = false;
+
+  if (PrioritizedResourceManager* contents_texture_manager =
+          layer_tree_host_->contents_texture_manager()) {
+    contents_texture_manager->UnlinkAndClearEvictedBackings();
+    contents_texture_manager->SetMaxMemoryLimitBytes(
+        layer_tree_host_impl_->memory_allocation_limit_bytes());
+    contents_texture_manager->SetExternalPriorityCutoff(
+        layer_tree_host_impl_->memory_allocation_priority_cutoff());
+  }
+
+  scoped_ptr<ResourceUpdateQueue> queue =
+      make_scoped_ptr(new ResourceUpdateQueue);
+
+  layer_tree_host_->UpdateLayers(queue.get());
+
+  layer_tree_host_->WillCommit();
+
   // Commit immediately.
   {
     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
@@ -145,7 +193,8 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
     // This CapturePostTasks should be destroyed before CommitComplete() is
     // called since that goes out to the embedder, and we want the embedder
     // to receive its callbacks before that.
-    BlockingTaskRunner::CapturePostTasks blocked;
+    BlockingTaskRunner::CapturePostTasks blocked(
+        blocking_main_thread_task_runner());
 
     layer_tree_host_impl_->BeginCommit();
 
@@ -158,7 +207,7 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
     scoped_ptr<ResourceUpdateController> update_controller =
         ResourceUpdateController::Create(
             NULL,
-            Proxy::MainThreadTaskRunner(),
+            MainThreadTaskRunner(),
             queue.Pass(),
             layer_tree_host_impl_->resource_provider());
     update_controller->Finalize();
@@ -170,6 +219,8 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
 
     layer_tree_host_impl_->CommitComplete();
 
+    UpdateBackgroundAnimateTicking();
+
 #if DCHECK_IS_ON
     // In the single-threaded case, the scale and scroll deltas should never be
     // touched on the impl layer tree.
@@ -186,33 +237,66 @@ void SingleThreadProxy::DoCommit(scoped_ptr<ResourceUpdateQueue> queue) {
     stats_instrumentation->AccumulateAndClearMainThreadStats();
   }
   layer_tree_host_->CommitComplete();
+  layer_tree_host_->DidBeginMainFrame();
+  timing_history_.DidCommit();
+
   next_frame_is_newly_committed_frame_ = true;
 }
 
 void SingleThreadProxy::SetNeedsCommit() {
   DCHECK(Proxy::IsMainThread());
+  DebugScopedSetImplThread impl(this);
   client_->ScheduleComposite();
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->SetNeedsCommit();
+  commit_requested_ = true;
 }
 
 void SingleThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
   TRACE_EVENT0("cc", "SingleThreadProxy::SetNeedsRedraw");
-  SetNeedsRedrawRectOnImplThread(damage_rect);
+  DCHECK(Proxy::IsMainThread());
+  DebugScopedSetImplThread impl(this);
   client_->ScheduleComposite();
+  SetNeedsRedrawRectOnImplThread(damage_rect);
 }
 
 void SingleThreadProxy::SetNextCommitWaitsForActivation() {
   // There is no activation here other than commit. So do nothing.
+  DCHECK(Proxy::IsMainThread());
 }
 
 void SingleThreadProxy::SetDeferCommits(bool defer_commits) {
+  DCHECK(Proxy::IsMainThread());
+  // Deferring commits only makes sense if there's a scheduler.
+  if (!scheduler_on_impl_thread_)
+    return;
+  if (defer_commits_ == defer_commits)
+    return;
+
+  if (defer_commits)
+    TRACE_EVENT_ASYNC_BEGIN0("cc", "SingleThreadProxy::SetDeferCommits", this);
+  else
+    TRACE_EVENT_ASYNC_END0("cc", "SingleThreadProxy::SetDeferCommits", this);
+
+  defer_commits_ = defer_commits;
+  if (!defer_commits_ && commit_was_deferred_) {
+    commit_was_deferred_ = false;
+    BeginMainFrame();
+  }
 }
 
 bool SingleThreadProxy::CommitRequested() const {
-  return false;
+  DCHECK(Proxy::IsMainThread());
+  return commit_requested_;
 }
 
 bool SingleThreadProxy::BeginMainFrameRequested() const {
-  return false;
+  DCHECK(Proxy::IsMainThread());
+  // If there is no scheduler, then there can be no pending begin frame,
+  // as all frames are all manually initiated by the embedder of cc.
+  if (!scheduler_on_impl_thread_)
+    return false;
+  return commit_requested_;
 }
 
 size_t SingleThreadProxy::MaxPartialTextureUpdates() const {
@@ -226,9 +310,11 @@ void SingleThreadProxy::Stop() {
     DebugScopedSetMainThreadBlocked main_thread_blocked(this);
     DebugScopedSetImplThread impl(this);
 
-    BlockingTaskRunner::CapturePostTasks blocked;
+    BlockingTaskRunner::CapturePostTasks blocked(
+        blocking_main_thread_task_runner());
     layer_tree_host_->DeleteContentsTexturesOnImplThread(
         layer_tree_host_impl_->resource_provider());
+    scheduler_on_impl_thread_.reset();
     layer_tree_host_impl_.reset();
   }
   layer_tree_host_ = NULL;
@@ -239,15 +325,19 @@ void SingleThreadProxy::OnCanDrawStateChanged(bool can_draw) {
       "cc", "SingleThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
   DCHECK(Proxy::IsImplThread());
   UpdateBackgroundAnimateTicking();
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->SetCanDraw(can_draw);
 }
 
 void SingleThreadProxy::NotifyReadyToActivate() {
-  // Thread-only feature.
+  // Impl-side painting only.
   NOTREACHED();
 }
 
 void SingleThreadProxy::SetNeedsRedrawOnImplThread() {
   client_->ScheduleComposite();
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->SetNeedsRedraw();
 }
 
 void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
@@ -255,17 +345,14 @@ void SingleThreadProxy::SetNeedsAnimateOnImplThread() {
 }
 
 void SingleThreadProxy::SetNeedsManageTilesOnImplThread() {
-  // Thread-only/Impl-side-painting-only feature.
+  // Impl-side painting only.
   NOTREACHED();
 }
 
 void SingleThreadProxy::SetNeedsRedrawRectOnImplThread(
     const gfx::Rect& damage_rect) {
-  // TODO(brianderson): Once we move render_widget scheduling into this class,
-  // we can treat redraw requests more efficiently than CommitAndRedraw
-  // requests.
   layer_tree_host_impl_->SetViewportDamage(damage_rect);
-  SetNeedsCommit();
+  SetNeedsRedrawOnImplThread();
 }
 
 void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
@@ -275,6 +362,8 @@ void SingleThreadProxy::DidInitializeVisibleTileOnImplThread() {
 
 void SingleThreadProxy::SetNeedsCommitOnImplThread() {
   client_->ScheduleComposite();
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->SetNeedsCommit();
 }
 
 void SingleThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
@@ -311,66 +400,55 @@ void SingleThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
       layer_tree_host_impl_->GetRendererCapabilities().MainThreadCapabilities();
 }
 
+void SingleThreadProxy::DidManageTiles() {
+  // Impl-side painting only.
+  NOTREACHED();
+}
+
 void SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() {
   TRACE_EVENT0("cc", "SingleThreadProxy::DidLoseOutputSurfaceOnImplThread");
-  // Cause a commit so we can notice the lost context.
-  SetNeedsCommitOnImplThread();
+  {
+    DebugScopedSetMainThread main(this);
+    // This must happen before we notify the scheduler as it may try to recreate
+    // the output surface if already in BEGIN_IMPL_FRAME_STATE_IDLE.
+    layer_tree_host_->DidLoseOutputSurface();
+  }
   client_->DidAbortSwapBuffers();
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->DidLoseOutputSurface();
 }
 
 void SingleThreadProxy::DidSwapBuffersOnImplThread() {
+  TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersOnImplThread");
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->DidSwapBuffers();
   client_->DidPostSwapBuffers();
 }
 
 void SingleThreadProxy::DidSwapBuffersCompleteOnImplThread() {
   TRACE_EVENT0("cc", "SingleThreadProxy::DidSwapBuffersCompleteOnImplThread");
-  client_->DidCompleteSwapBuffers();
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->DidSwapBuffersComplete();
+  layer_tree_host_->DidCompleteSwapBuffers();
+}
+
+void SingleThreadProxy::BeginFrame(const BeginFrameArgs& args) {
+  TRACE_EVENT0("cc", "SingleThreadProxy::BeginFrame");
+  if (scheduler_on_impl_thread_)
+    scheduler_on_impl_thread_->BeginFrame(args);
 }
 
-// Called by the legacy scheduling path (e.g. where render_widget does the
-// scheduling)
 void SingleThreadProxy::CompositeImmediately(base::TimeTicks frame_begin_time) {
   TRACE_EVENT0("cc", "SingleThreadProxy::CompositeImmediately");
   DCHECK(Proxy::IsMainThread());
   DCHECK(!layer_tree_host_->output_surface_lost());
 
-  layer_tree_host_->AnimateLayers(frame_begin_time);
-
-  if (PrioritizedResourceManager* contents_texture_manager =
-          layer_tree_host_->contents_texture_manager()) {
-    contents_texture_manager->UnlinkAndClearEvictedBackings();
-    contents_texture_manager->SetMaxMemoryLimitBytes(
-        layer_tree_host_impl_->memory_allocation_limit_bytes());
-    contents_texture_manager->SetExternalPriorityCutoff(
-        layer_tree_host_impl_->memory_allocation_priority_cutoff());
-  }
-
-  scoped_ptr<ResourceUpdateQueue> queue =
-      make_scoped_ptr(new ResourceUpdateQueue);
-  layer_tree_host_->UpdateLayers(queue.get());
-  layer_tree_host_->WillCommit();
-  DoCommit(queue.Pass());
-  layer_tree_host_->DidBeginMainFrame();
+  BeginFrameArgs begin_frame_args = BeginFrameArgs::Create(
+      frame_begin_time, base::TimeTicks(), BeginFrameArgs::DefaultInterval());
+  DoCommit(begin_frame_args);
 
   LayerTreeHostImpl::FrameData frame;
-  if (DoComposite(frame_begin_time, &frame)) {
-    {
-      DebugScopedSetMainThreadBlocked main_thread_blocked(this);
-      DebugScopedSetImplThread impl(this);
-
-      // This CapturePostTasks should be destroyed before
-      // DidCommitAndDrawFrame() is called since that goes out to the embedder,
-      // and we want the embedder to receive its callbacks before that.
-      // NOTE: This maintains consistent ordering with the ThreadProxy since
-      // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
-      // there as the main thread is not blocked, so any posted tasks inside
-      // the swap buffers will execute first.
-      BlockingTaskRunner::CapturePostTasks blocked;
-
-      layer_tree_host_impl_->SwapBuffers(frame);
-    }
-    DidSwapFrame();
-  }
+  DoComposite(frame_begin_time, &frame);
 }
 
 void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
@@ -410,12 +488,11 @@ void SingleThreadProxy::UpdateBackgroundAnimateTicking() {
       !ShouldComposite() && layer_tree_host_impl_->active_tree()->root_layer());
 }
 
-bool SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
-                                    LayerTreeHostImpl::FrameData* frame) {
+DrawResult SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
+                                          LayerTreeHostImpl::FrameData* frame) {
   TRACE_EVENT0("cc", "SingleThreadProxy::DoComposite");
   DCHECK(!layer_tree_host_->output_surface_lost());
 
-  bool lost_output_surface = false;
   {
     DebugScopedSetImplThread impl(this);
     base::AutoReset<bool> mark_inside(&inside_draw_, true);
@@ -426,36 +503,52 @@ bool SingleThreadProxy::DoComposite(base::TimeTicks frame_begin_time,
     // CanDraw() as well.
     if (!ShouldComposite()) {
       UpdateBackgroundAnimateTicking();
-      return false;
+      return DRAW_ABORTED_CANT_DRAW;
     }
 
+    timing_history_.DidStartDrawing();
+
     layer_tree_host_impl_->Animate(
-        layer_tree_host_impl_->CurrentFrameTimeTicks());
+        layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
     UpdateBackgroundAnimateTicking();
 
-    if (!layer_tree_host_impl_->IsContextLost()) {
-      layer_tree_host_impl_->PrepareToDraw(frame);
-      layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
-      layer_tree_host_impl_->DidDrawAllLayers(*frame);
-    }
-    lost_output_surface = layer_tree_host_impl_->IsContextLost();
+    layer_tree_host_impl_->PrepareToDraw(frame);
+    layer_tree_host_impl_->DrawLayers(frame, frame_begin_time);
+    layer_tree_host_impl_->DidDrawAllLayers(*frame);
 
     bool start_ready_animations = true;
     layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
 
-    layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
+    layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
+
+    timing_history_.DidFinishDrawing();
   }
 
-  if (lost_output_surface) {
-    layer_tree_host_->DidLoseOutputSurface();
-    return false;
+  {
+    DebugScopedSetImplThread impl(this);
+
+    // This CapturePostTasks should be destroyed before
+    // DidCommitAndDrawFrame() is called since that goes out to the
+    // embedder,
+    // and we want the embedder to receive its callbacks before that.
+    // NOTE: This maintains consistent ordering with the ThreadProxy since
+    // the DidCommitAndDrawFrame() must be post-tasked from the impl thread
+    // there as the main thread is not blocked, so any posted tasks inside
+    // the swap buffers will execute first.
+    DebugScopedSetMainThreadBlocked main_thread_blocked(this);
+
+    BlockingTaskRunner::CapturePostTasks blocked(
+        blocking_main_thread_task_runner());
+    layer_tree_host_impl_->SwapBuffers(*frame);
   }
+  DidCommitAndDrawFrame();
 
-  return true;
+  return DRAW_SUCCESS;
 }
 
-void SingleThreadProxy::DidSwapFrame() {
+void SingleThreadProxy::DidCommitAndDrawFrame() {
   if (next_frame_is_newly_committed_frame_) {
+    DebugScopedSetMainThread main(this);
     next_frame_is_newly_committed_frame_ = false;
     layer_tree_host_->DidCommitAndDrawFrame();
   }
@@ -465,4 +558,142 @@ bool SingleThreadProxy::MainFrameWillHappenForTesting() {
   return false;
 }
 
+void SingleThreadProxy::SetNeedsBeginFrame(bool enable) {
+  layer_tree_host_impl_->SetNeedsBeginFrame(enable);
+}
+
+void SingleThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
+  layer_tree_host_impl_->WillBeginImplFrame(args);
+}
+
+void SingleThreadProxy::ScheduledActionSendBeginMainFrame() {
+  TRACE_EVENT0("cc", "SingleThreadProxy::ScheduledActionSendBeginMainFrame");
+  // Although this proxy is single-threaded, it's problematic to synchronously
+  // have BeginMainFrame happen after ScheduledActionSendBeginMainFrame.  This
+  // could cause a commit to occur in between a series of SetNeedsCommit calls
+  // (i.e. property modifications) causing some to fall on one frame and some to
+  // fall on the next.  Doing it asynchronously instead matches the semantics of
+  // ThreadProxy::SetNeedsCommit where SetNeedsCommit will not cause a
+  // synchronous commit.
+  MainThreadTaskRunner()->PostTask(
+      FROM_HERE,
+      base::Bind(&SingleThreadProxy::BeginMainFrame,
+                 weak_factory_.GetWeakPtr()));
+}
+
+void SingleThreadProxy::BeginMainFrame() {
+  if (defer_commits_) {
+    DCHECK(!commit_was_deferred_);
+    commit_was_deferred_ = true;
+    layer_tree_host_->DidDeferCommit();
+    return;
+  }
+
+  // This checker assumes NotifyReadyToCommit below causes a synchronous commit.
+  ScopedAbortRemainingSwapPromises swap_promise_checker(layer_tree_host_);
+
+  if (!layer_tree_host_->visible()) {
+    TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
+    BeginMainFrameAbortedOnImplThread();
+    return;
+  }
+
+  if (layer_tree_host_->output_surface_lost()) {
+    TRACE_EVENT_INSTANT0(
+        "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD);
+    BeginMainFrameAbortedOnImplThread();
+    return;
+  }
+
+  timing_history_.DidBeginMainFrame();
+
+  DCHECK(scheduler_on_impl_thread_);
+  scheduler_on_impl_thread_->NotifyBeginMainFrameStarted();
+  scheduler_on_impl_thread_->NotifyReadyToCommit();
+}
+
+void SingleThreadProxy::BeginMainFrameAbortedOnImplThread() {
+  DebugScopedSetImplThread impl(this);
+  DCHECK(scheduler_on_impl_thread_->CommitPending());
+  DCHECK(!layer_tree_host_impl_->pending_tree());
+
+  // TODO(enne): SingleThreadProxy does not support cancelling commits yet so
+  // did_handle is always false.
+  bool did_handle = false;
+  layer_tree_host_impl_->BeginMainFrameAborted(did_handle);
+  scheduler_on_impl_thread_->BeginMainFrameAborted(did_handle);
+}
+
+DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
+  DebugScopedSetImplThread impl(this);
+  LayerTreeHostImpl::FrameData frame;
+  return DoComposite(layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time,
+                     &frame);
+}
+
+DrawResult SingleThreadProxy::ScheduledActionDrawAndSwapForced() {
+  NOTREACHED();
+  return INVALID_RESULT;
+}
+
+void SingleThreadProxy::ScheduledActionCommit() {
+  DebugScopedSetMainThread main(this);
+  DoCommit(layer_tree_host_impl_->CurrentBeginFrameArgs());
+}
+
+void SingleThreadProxy::ScheduledActionAnimate() {
+  TRACE_EVENT0("cc", "ScheduledActionAnimate");
+  layer_tree_host_impl_->Animate(
+      layer_tree_host_impl_->CurrentBeginFrameArgs().frame_time);
+}
+
+void SingleThreadProxy::ScheduledActionUpdateVisibleTiles() {
+  // Impl-side painting only.
+  NOTREACHED();
+}
+
+void SingleThreadProxy::ScheduledActionActivateSyncTree() {
+}
+
+void SingleThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
+  DebugScopedSetMainThread main(this);
+  DCHECK(scheduler_on_impl_thread_);
+  // If possible, create the output surface in a post task.  Synchronously
+  // creating the output surface makes tests more awkward since this differs
+  // from the ThreadProxy behavior.  However, sometimes there is no
+  // task runner.
+  if (Proxy::MainThreadTaskRunner()) {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::Bind(&SingleThreadProxy::RequestNewOutputSurface,
+                   weak_factory_.GetWeakPtr()));
+  } else {
+    RequestNewOutputSurface();
+  }
+}
+
+void SingleThreadProxy::ScheduledActionManageTiles() {
+  // Impl-side painting only.
+  NOTREACHED();
+}
+
+void SingleThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
+}
+
+base::TimeDelta SingleThreadProxy::DrawDurationEstimate() {
+  return timing_history_.DrawDurationEstimate();
+}
+
+base::TimeDelta SingleThreadProxy::BeginMainFrameToCommitDurationEstimate() {
+  return timing_history_.BeginMainFrameToCommitDurationEstimate();
+}
+
+base::TimeDelta SingleThreadProxy::CommitToActivateDurationEstimate() {
+  return timing_history_.CommitToActivateDurationEstimate();
+}
+
+void SingleThreadProxy::DidBeginImplFrameDeadline() {
+  layer_tree_host_impl_->ResetCurrentBeginFrameArgsForNextFrame();
+}
+
 }  // namespace cc