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