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