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