• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
30 namespace {
31 
32 // Measured in seconds.
33 const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
34 
35 class SwapPromiseChecker {
36  public:
SwapPromiseChecker(cc::LayerTreeHost * layer_tree_host)37   explicit SwapPromiseChecker(cc::LayerTreeHost* layer_tree_host)
38       : layer_tree_host_(layer_tree_host) {}
39 
~SwapPromiseChecker()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 
50 namespace cc {
51 
52 struct ThreadProxy::CommitPendingRequest {
53   CompletionEvent completion;
54   bool commit_pending;
55 };
56 
57 struct ThreadProxy::SchedulerStateRequest {
58   CompletionEvent completion;
59   scoped_ptr<base::Value> state;
60 };
61 
Create(LayerTreeHost * layer_tree_host,scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)62 scoped_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 
ThreadProxy(LayerTreeHost * layer_tree_host,scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)69 ThreadProxy::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 
MainThreadOnly(ThreadProxy * proxy,int layer_tree_host_id)81 ThreadProxy::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 
~MainThreadOnly()93 ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
94 
MainThreadOrBlockedMainThread(LayerTreeHost * host)95 ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread(
96     LayerTreeHost* host)
97     : layer_tree_host(host),
98       commit_waits_for_activation(false),
99       main_thread_inside_commit(false) {}
100 
~MainThreadOrBlockedMainThread()101 ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {}
102 
103 PrioritizedResourceManager*
contents_texture_manager()104 ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() {
105   return layer_tree_host->contents_texture_manager();
106 }
107 
CompositorThreadOnly(ThreadProxy * proxy,int layer_tree_host_id)108 ThreadProxy::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 
~CompositorThreadOnly()127 ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
128 
~ThreadProxy()129 ThreadProxy::~ThreadProxy() {
130   TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
131   DCHECK(IsMainThread());
132   DCHECK(!main().started);
133 }
134 
FinishAllRendering()135 void 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 
IsStarted() const150 bool ThreadProxy::IsStarted() const {
151   DCHECK(Proxy::IsMainThread());
152   return main().started;
153 }
154 
SetLayerTreeHostClientReady()155 void 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 
SetLayerTreeHostClientReadyOnImplThread()163 void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
164   TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
165   impl().scheduler->SetCanStart();
166 }
167 
SetVisible(bool visible)168 void 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 
SetVisibleOnImplThread(CompletionEvent * completion,bool visible)182 void 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 
UpdateBackgroundAnimateTicking()191 void 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 
DidLoseOutputSurface()201 void 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 
CreateAndInitializeOutputSurface()222 void 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 
DidInitializeOutputSurface(bool success,const RendererCapabilities & capabilities)241 void 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 
SetRendererCapabilitiesMainThreadCopy(const RendererCapabilities & capabilities)257 void ThreadProxy::SetRendererCapabilitiesMainThreadCopy(
258     const RendererCapabilities& capabilities) {
259   main().renderer_capabilities_main_thread_copy = capabilities;
260 }
261 
SendCommitRequestToImplThreadIfNeeded()262 void 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 
GetRendererCapabilities() const273 const 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 
SetNeedsAnimate()279 void 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 
SetNeedsUpdateLayers()289 void 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 
SetNeedsCommit()299 void 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 
UpdateRendererCapabilitiesOnImplThread()312 void 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 
DidLoseOutputSurfaceOnImplThread()323 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
324   TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
325   DCHECK(IsImplThread());
326   CheckOutputSurfaceStatusOnImplThread();
327 }
328 
CheckOutputSurfaceStatusOnImplThread()329 void 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 
CommitVSyncParameters(base::TimeTicks timebase,base::TimeDelta interval)340 void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
341                                         base::TimeDelta interval) {
342   impl().scheduler->CommitVSyncParameters(timebase, interval);
343 }
344 
SetEstimatedParentDrawTime(base::TimeDelta draw_time)345 void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
346   impl().scheduler->SetEstimatedParentDrawTime(draw_time);
347 }
348 
SetMaxSwapsPendingOnImplThread(int max)349 void ThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
350   impl().scheduler->SetMaxSwapsPending(max);
351 }
352 
DidSwapBuffersOnImplThread()353 void ThreadProxy::DidSwapBuffersOnImplThread() {
354   impl().scheduler->DidSwapBuffers();
355 }
356 
DidSwapBuffersCompleteOnImplThread()357 void 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 
SetNeedsBeginFrame(bool enable)366 void ThreadProxy::SetNeedsBeginFrame(bool enable) {
367   TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrame", "enable", enable);
368   impl().layer_tree_host_impl->SetNeedsBeginFrame(enable);
369   UpdateBackgroundAnimateTicking();
370 }
371 
BeginFrame(const BeginFrameArgs & args)372 void ThreadProxy::BeginFrame(const BeginFrameArgs& args) {
373   impl().scheduler->BeginFrame(args);
374 }
375 
WillBeginImplFrame(const BeginFrameArgs & args)376 void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
377   impl().layer_tree_host_impl->WillBeginImplFrame(args);
378 }
379 
OnCanDrawStateChanged(bool can_draw)380 void 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 
NotifyReadyToActivate()388 void ThreadProxy::NotifyReadyToActivate() {
389   TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
390   impl().scheduler->NotifyReadyToActivate();
391 }
392 
SetNeedsCommitOnImplThread()393 void ThreadProxy::SetNeedsCommitOnImplThread() {
394   TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
395   DCHECK(IsImplThread());
396   impl().scheduler->SetNeedsCommit();
397 }
398 
PostAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector> events)399 void 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 
ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,int priority_cutoff)411 bool 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 
IsInsideDraw()437 bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; }
438 
SetNeedsRedraw(const gfx::Rect & damage_rect)439 void 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 
SetNextCommitWaitsForActivation()449 void ThreadProxy::SetNextCommitWaitsForActivation() {
450   DCHECK(IsMainThread());
451   DCHECK(!blocked_main().main_thread_inside_commit);
452   blocked_main().commit_waits_for_activation = true;
453 }
454 
SetDeferCommits(bool defer_commits)455 void 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 
CommitRequested() const473 bool ThreadProxy::CommitRequested() const {
474   DCHECK(IsMainThread());
475   return main().commit_requested;
476 }
477 
BeginMainFrameRequested() const478 bool ThreadProxy::BeginMainFrameRequested() const {
479   DCHECK(IsMainThread());
480   return main().commit_request_sent_to_impl_thread;
481 }
482 
SetNeedsRedrawOnImplThread()483 void ThreadProxy::SetNeedsRedrawOnImplThread() {
484   TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
485   DCHECK(IsImplThread());
486   impl().scheduler->SetNeedsRedraw();
487 }
488 
SetNeedsAnimateOnImplThread()489 void ThreadProxy::SetNeedsAnimateOnImplThread() {
490   TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimateOnImplThread");
491   DCHECK(IsImplThread());
492   impl().scheduler->SetNeedsAnimate();
493 }
494 
SetNeedsManageTilesOnImplThread()495 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
496   DCHECK(IsImplThread());
497   impl().scheduler->SetNeedsManageTiles();
498 }
499 
SetNeedsRedrawRectOnImplThread(const gfx::Rect & damage_rect)500 void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
501   DCHECK(IsImplThread());
502   impl().layer_tree_host_impl->SetViewportDamage(damage_rect);
503   SetNeedsRedrawOnImplThread();
504 }
505 
SetSwapUsedIncompleteTileOnImplThread(bool used_incomplete_tile)506 void 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 
DidInitializeVisibleTileOnImplThread()517 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
518   TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
519   DCHECK(IsImplThread());
520   impl().scheduler->SetNeedsRedraw();
521 }
522 
MainThreadHasStoppedFlinging()523 void ThreadProxy::MainThreadHasStoppedFlinging() {
524   DCHECK(IsMainThread());
525   Proxy::ImplThreadTaskRunner()->PostTask(
526       FROM_HERE,
527       base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread,
528                  impl_thread_weak_ptr_));
529 }
530 
MainThreadHasStoppedFlingingOnImplThread()531 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
532   DCHECK(IsImplThread());
533   impl().layer_tree_host_impl->MainThreadHasStoppedFlinging();
534 }
535 
NotifyInputThrottledUntilCommit()536 void 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 
SetInputThrottledUntilCommitOnImplThread(bool is_throttled)545 void 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 
layer_tree_host()553 LayerTreeHost* ThreadProxy::layer_tree_host() {
554   return blocked_main().layer_tree_host;
555 }
556 
layer_tree_host() const557 const LayerTreeHost* ThreadProxy::layer_tree_host() const {
558   return blocked_main().layer_tree_host;
559 }
560 
main()561 ThreadProxy::MainThreadOnly& ThreadProxy::main() {
562   DCHECK(IsMainThread());
563   return main_thread_only_vars_unsafe_;
564 }
main() const565 const ThreadProxy::MainThreadOnly& ThreadProxy::main() const {
566   DCHECK(IsMainThread());
567   return main_thread_only_vars_unsafe_;
568 }
569 
blocked_main()570 ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() {
571   DCHECK(IsMainThread() || IsMainThreadBlocked());
572   return main_thread_or_blocked_vars_unsafe_;
573 }
574 
blocked_main() const575 const ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main()
576     const {
577   DCHECK(IsMainThread() || IsMainThreadBlocked());
578   return main_thread_or_blocked_vars_unsafe_;
579 }
580 
impl()581 ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() {
582   DCHECK(IsImplThread());
583   return compositor_thread_vars_unsafe_;
584 }
585 
impl() const586 const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const {
587   DCHECK(IsImplThread());
588   return compositor_thread_vars_unsafe_;
589 }
590 
Start()591 void 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 
Stop()610 void 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 
ForceSerializeOnSwapBuffers()647 void 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 
ForceSerializeOnSwapBuffersOnImplThread(CompletionEvent * completion)658 void 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 
SetDebugState(const LayerTreeDebugState & debug_state)665 void 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 
SetDebugStateOnImplThread(const LayerTreeDebugState & debug_state)673 void ThreadProxy::SetDebugStateOnImplThread(
674     const LayerTreeDebugState& debug_state) {
675   DCHECK(IsImplThread());
676   impl().scheduler->SetContinuousPainting(debug_state.continuous_painting);
677 }
678 
FinishAllRenderingOnImplThread(CompletionEvent * completion)679 void 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 
ScheduledActionSendBeginMainFrame()686 void 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 
BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state)714 void 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 
StartCommitOnImplThread(CompletionEvent * completion,ResourceUpdateQueue * raw_queue)879 void 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 
BeginMainFrameAbortedOnImplThread(bool did_handle)932 void 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 
ScheduledActionAnimate()945 void 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 
ScheduledActionCommit()957 void 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 
ScheduledActionUpdateVisibleTiles()1011 void ThreadProxy::ScheduledActionUpdateVisibleTiles() {
1012   TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles");
1013   DCHECK(IsImplThread());
1014   impl().layer_tree_host_impl->UpdateVisibleTiles();
1015 }
1016 
ScheduledActionActivatePendingTree()1017 void ThreadProxy::ScheduledActionActivatePendingTree() {
1018   TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTree");
1019   DCHECK(IsImplThread());
1020   impl().layer_tree_host_impl->ActivatePendingTree();
1021 }
1022 
ScheduledActionBeginOutputSurfaceCreation()1023 void 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 
DrawSwapInternal(bool forced_draw)1032 DrawResult 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 
ScheduledActionManageTiles()1146 void 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 
ScheduledActionDrawAndSwapIfPossible()1152 DrawResult 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 
ScheduledActionDrawAndSwapForced()1164 DrawResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
1165   TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
1166   bool forced_draw = true;
1167   return DrawSwapInternal(forced_draw);
1168 }
1169 
DidAnticipatedDrawTimeChange(base::TimeTicks time)1170 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1171   if (impl().current_resource_update_controller)
1172     impl().current_resource_update_controller->PerformMoreUpdates(time);
1173 }
1174 
DrawDurationEstimate()1175 base::TimeDelta ThreadProxy::DrawDurationEstimate() {
1176   return impl().timing_history.DrawDurationEstimate();
1177 }
1178 
BeginMainFrameToCommitDurationEstimate()1179 base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() {
1180   return impl().timing_history.BeginMainFrameToCommitDurationEstimate();
1181 }
1182 
CommitToActivateDurationEstimate()1183 base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() {
1184   return impl().timing_history.CommitToActivateDurationEstimate();
1185 }
1186 
DidBeginImplFrameDeadline()1187 void ThreadProxy::DidBeginImplFrameDeadline() {
1188   impl().layer_tree_host_impl->ResetCurrentFrameTimeForNextFrame();
1189 }
1190 
ReadyToFinalizeTextureUpdates()1191 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1192   DCHECK(IsImplThread());
1193   impl().scheduler->NotifyReadyToCommit();
1194 }
1195 
DidCommitAndDrawFrame()1196 void ThreadProxy::DidCommitAndDrawFrame() {
1197   DCHECK(IsMainThread());
1198   layer_tree_host()->DidCommitAndDrawFrame();
1199 }
1200 
DidCompleteSwapBuffers()1201 void ThreadProxy::DidCompleteSwapBuffers() {
1202   DCHECK(IsMainThread());
1203   layer_tree_host()->DidCompleteSwapBuffers();
1204 }
1205 
SetAnimationEvents(scoped_ptr<AnimationEventsVector> events)1206 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
1207   TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1208   DCHECK(IsMainThread());
1209   layer_tree_host()->SetAnimationEvents(events.Pass());
1210 }
1211 
InitializeImplOnImplThread(CompletionEvent * completion)1212 void 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 
DeleteContentsTexturesOnImplThread(CompletionEvent * completion)1228 void 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 
InitializeOutputSurfaceOnImplThread(scoped_ptr<OutputSurface> output_surface)1238 void 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 
FinishGLOnImplThread(CompletionEvent * completion)1262 void 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 
LayerTreeHostClosedOnImplThread(CompletionEvent * completion)1270 void 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 
MaxPartialTextureUpdates() const1285 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1286   return ResourceUpdateController::MaxPartialTextureUpdates();
1287 }
1288 
BeginMainFrameAndCommitState()1289 ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState()
1290     : memory_allocation_limit_bytes(0),
1291       memory_allocation_priority_cutoff(0),
1292       evicted_ui_resources(false) {}
1293 
~BeginMainFrameAndCommitState()1294 ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
1295 
AsValue() const1296 scoped_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 
AsValueOnImplThread(CompletionEvent * completion,base::DictionaryValue * state) const1314 void 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 
CommitPendingForTesting()1321 bool 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 
CommitPendingOnImplThreadForTesting(CommitPendingRequest * request)1336 void 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 
SchedulerAsValueForTesting()1346 scoped_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 
SchedulerAsValueOnImplThreadForTesting(SchedulerStateRequest * request)1363 void ThreadProxy::SchedulerAsValueOnImplThreadForTesting(
1364     SchedulerStateRequest* request) {
1365   DCHECK(IsImplThread());
1366   request->state = impl().scheduler->AsValue();
1367   request->completion.Signal();
1368 }
1369 
RenewTreePriority()1370 void 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 
PostDelayedScrollbarFadeOnImplThread(const base::Closure & start_fade,base::TimeDelta delay)1416 void ThreadProxy::PostDelayedScrollbarFadeOnImplThread(
1417     const base::Closure& start_fade,
1418     base::TimeDelta delay) {
1419   Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, start_fade, delay);
1420 }
1421 
DidActivatePendingTree()1422 void 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 
DidManageTiles()1440 void ThreadProxy::DidManageTiles() {
1441   DCHECK(IsImplThread());
1442   impl().scheduler->DidManageTiles();
1443 }
1444 
1445 }  // namespace cc
1446