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