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.
5 #include "cc/trees/thread_proxy.h"
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"
36 // Measured in seconds.
37 const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
39 unsigned int nextBeginFrameId = 0;
43 struct ThreadProxy::SchedulerStateRequest {
44 CompletionEvent completion;
45 scoped_ptr<base::Value> state;
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));
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_(
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());
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),
79 manage_tiles_pending(false),
80 can_cancel_commit(true),
82 weak_factory(proxy) {}
84 ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
86 ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread(
88 : layer_tree_host(host),
89 commit_waits_for_activation(false),
90 main_thread_inside_commit(false) {}
92 ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {}
94 PrioritizedResourceManager*
95 ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() {
96 return layer_tree_host->contents_texture_manager();
99 ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(
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),
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) {
119 ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
121 ThreadProxy::~ThreadProxy() {
122 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
123 DCHECK(IsMainThread());
124 DCHECK(!main().started);
127 void ThreadProxy::FinishAllRendering() {
128 DCHECK(Proxy::IsMainThread());
129 DCHECK(!main().defer_commits);
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(
136 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread,
137 impl_thread_weak_ptr_,
142 bool ThreadProxy::IsStarted() const {
143 DCHECK(Proxy::IsMainThread());
144 return main().started;
147 void ThreadProxy::SetLayerTreeHostClientReady() {
148 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
149 Proxy::ImplThreadTaskRunner()->PostTask(
151 base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread,
152 impl_thread_weak_ptr_));
155 void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
156 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
157 impl().scheduler->SetCanStart();
160 void ThreadProxy::SetVisible(bool visible) {
161 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
162 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
164 CompletionEvent completion;
165 Proxy::ImplThreadTaskRunner()->PostTask(
167 base::Bind(&ThreadProxy::SetVisibleOnImplThread,
168 impl_thread_weak_ptr_,
174 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
176 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
177 impl().layer_tree_host_impl->SetVisible(visible);
178 impl().scheduler->SetVisible(visible);
179 UpdateBackgroundAnimateTicking();
180 completion->Signal();
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);
191 void ThreadProxy::DidLoseOutputSurface() {
192 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurface");
193 DCHECK(IsMainThread());
194 layer_tree_host()->DidLoseOutputSurface();
197 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
199 // Return lost resources to their owners immediately.
200 BlockingTaskRunner::CapturePostTasks blocked(
201 blocking_main_thread_task_runner());
203 CompletionEvent completion;
204 Proxy::ImplThreadTaskRunner()->PostTask(
206 base::Bind(&ThreadProxy::DeleteContentsTexturesOnImplThread,
207 impl_thread_weak_ptr_,
213 void ThreadProxy::RequestNewOutputSurface() {
214 DCHECK(IsMainThread());
215 layer_tree_host()->RequestNewOutputSurface();
218 void ThreadProxy::SetOutputSurface(scoped_ptr<OutputSurface> output_surface) {
219 if (output_surface) {
220 Proxy::ImplThreadTaskRunner()->PostTask(
222 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
223 impl_thread_weak_ptr_,
224 base::Passed(&output_surface)));
228 DidInitializeOutputSurface(false, RendererCapabilities());
231 void ThreadProxy::DidInitializeOutputSurface(
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);
240 Proxy::MainThreadTaskRunner()->PostTask(
242 base::Bind(&ThreadProxy::RequestNewOutputSurface,
243 main_thread_weak_ptr_));
247 void ThreadProxy::SetRendererCapabilitiesMainThreadCopy(
248 const RendererCapabilities& capabilities) {
249 main().renderer_capabilities_main_thread_copy = capabilities;
252 void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
253 DCHECK(IsMainThread());
254 if (main().commit_request_sent_to_impl_thread)
256 main().commit_request_sent_to_impl_thread = true;
257 Proxy::ImplThreadTaskRunner()->PostTask(
259 base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread,
260 impl_thread_weak_ptr_));
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;
269 void ThreadProxy::SetNeedsAnimate() {
270 DCHECK(IsMainThread());
271 if (main().animate_requested)
274 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
275 main().animate_requested = true;
276 SendCommitRequestToImplThreadIfNeeded();
279 void ThreadProxy::SetNeedsUpdateLayers() {
280 DCHECK(IsMainThread());
282 if (main().commit_request_sent_to_impl_thread)
284 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers");
286 SendCommitRequestToImplThreadIfNeeded();
289 void ThreadProxy::SetNeedsCommit() {
290 DCHECK(IsMainThread());
291 // Unconditionally set here to handle SetNeedsCommit calls during a commit.
292 main().can_cancel_commit = false;
294 if (main().commit_requested)
296 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
297 main().commit_requested = true;
299 SendCommitRequestToImplThreadIfNeeded();
302 void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
303 DCHECK(IsImplThread());
304 Proxy::MainThreadTaskRunner()->PostTask(
306 base::Bind(&ThreadProxy::SetRendererCapabilitiesMainThreadCopy,
307 main_thread_weak_ptr_,
309 .layer_tree_host_impl->GetRendererCapabilities()
310 .MainThreadCapabilities()));
313 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
314 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
315 DCHECK(IsImplThread());
316 Proxy::MainThreadTaskRunner()->PostTask(
318 base::Bind(&ThreadProxy::DidLoseOutputSurface, main_thread_weak_ptr_));
319 impl().scheduler->DidLoseOutputSurface();
322 void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
323 base::TimeDelta interval) {
324 impl().scheduler->CommitVSyncParameters(timebase, interval);
327 void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
328 impl().scheduler->SetEstimatedParentDrawTime(draw_time);
331 void ThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
332 impl().scheduler->SetMaxSwapsPending(max);
335 void ThreadProxy::DidSwapBuffersOnImplThread() {
336 impl().scheduler->DidSwapBuffers();
339 void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
340 TRACE_EVENT0("cc", "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
341 DCHECK(IsImplThread());
342 impl().scheduler->DidSwapBuffersComplete();
343 Proxy::MainThreadTaskRunner()->PostTask(
345 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
348 BeginFrameSource* ThreadProxy::ExternalBeginFrameSource() {
349 return impl().layer_tree_host_impl.get();
352 void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
353 impl().layer_tree_host_impl->WillBeginImplFrame(args);
356 void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
358 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
359 DCHECK(IsImplThread());
360 impl().scheduler->SetCanDraw(can_draw);
361 UpdateBackgroundAnimateTicking();
364 void ThreadProxy::NotifyReadyToActivate() {
365 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
366 impl().scheduler->NotifyReadyToActivate();
369 void ThreadProxy::SetNeedsCommitOnImplThread() {
370 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
371 DCHECK(IsImplThread());
372 impl().scheduler->SetNeedsCommit();
375 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
376 scoped_ptr<AnimationEventsVector> events) {
378 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
379 DCHECK(IsImplThread());
380 Proxy::MainThreadTaskRunner()->PostTask(
382 base::Bind(&ThreadProxy::SetAnimationEvents,
383 main_thread_weak_ptr_,
384 base::Passed(&events)));
387 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
388 int priority_cutoff) {
389 DCHECK(IsImplThread());
391 if (!impl().contents_texture_manager)
393 if (!impl().layer_tree_host_impl->resource_provider())
397 impl().contents_texture_manager->ReduceMemoryOnImplThread(
400 impl().layer_tree_host_impl->resource_provider());
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) {
408 .current_resource_update_controller->DiscardUploadsToEvictedResources();
413 bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; }
415 void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
416 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
417 DCHECK(IsMainThread());
418 Proxy::ImplThreadTaskRunner()->PostTask(
420 base::Bind(&ThreadProxy::SetNeedsRedrawRectOnImplThread,
421 impl_thread_weak_ptr_,
425 void ThreadProxy::SetNextCommitWaitsForActivation() {
426 DCHECK(IsMainThread());
427 DCHECK(!blocked_main().main_thread_inside_commit);
428 blocked_main().commit_waits_for_activation = true;
431 void ThreadProxy::SetDeferCommits(bool defer_commits) {
432 DCHECK(IsMainThread());
433 if (main().defer_commits == defer_commits)
436 main().defer_commits = defer_commits;
437 if (main().defer_commits)
438 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
440 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
442 if (!main().defer_commits && main().pending_deferred_commit) {
443 Proxy::MainThreadTaskRunner()->PostTask(
445 base::Bind(&ThreadProxy::BeginMainFrame,
446 main_thread_weak_ptr_,
447 base::Passed(&main().pending_deferred_commit)));
451 bool ThreadProxy::CommitRequested() const {
452 DCHECK(IsMainThread());
453 return main().commit_requested;
456 bool ThreadProxy::BeginMainFrameRequested() const {
457 DCHECK(IsMainThread());
458 return main().commit_request_sent_to_impl_thread;
461 void ThreadProxy::SetNeedsRedrawOnImplThread() {
462 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
463 DCHECK(IsImplThread());
464 impl().scheduler->SetNeedsRedraw();
467 void ThreadProxy::SetNeedsAnimateOnImplThread() {
468 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimateOnImplThread");
469 DCHECK(IsImplThread());
470 impl().scheduler->SetNeedsAnimate();
473 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
474 DCHECK(IsImplThread());
475 impl().scheduler->SetNeedsManageTiles();
478 void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
479 DCHECK(IsImplThread());
480 impl().layer_tree_host_impl->SetViewportDamage(damage_rect);
481 SetNeedsRedrawOnImplThread();
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);
492 impl().scheduler->SetSwapUsedIncompleteTile(used_incomplete_tile);
495 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
496 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
497 DCHECK(IsImplThread());
498 impl().scheduler->SetNeedsRedraw();
501 void ThreadProxy::MainThreadHasStoppedFlinging() {
502 DCHECK(IsMainThread());
503 Proxy::ImplThreadTaskRunner()->PostTask(
505 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread,
506 impl_thread_weak_ptr_));
509 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
510 DCHECK(IsImplThread());
511 impl().layer_tree_host_impl->MainThreadHasStoppedFlinging();
514 void ThreadProxy::NotifyInputThrottledUntilCommit() {
515 DCHECK(IsMainThread());
516 Proxy::ImplThreadTaskRunner()->PostTask(
518 base::Bind(&ThreadProxy::SetInputThrottledUntilCommitOnImplThread,
519 impl_thread_weak_ptr_,
523 void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(bool is_throttled) {
524 DCHECK(IsImplThread());
525 if (is_throttled == impl().input_throttled_until_commit)
527 impl().input_throttled_until_commit = is_throttled;
531 LayerTreeHost* ThreadProxy::layer_tree_host() {
532 return blocked_main().layer_tree_host;
535 const LayerTreeHost* ThreadProxy::layer_tree_host() const {
536 return blocked_main().layer_tree_host;
539 ThreadProxy::MainThreadOnly& ThreadProxy::main() {
540 DCHECK(IsMainThread());
541 return main_thread_only_vars_unsafe_;
543 const ThreadProxy::MainThreadOnly& ThreadProxy::main() const {
544 DCHECK(IsMainThread());
545 return main_thread_only_vars_unsafe_;
548 ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() {
549 DCHECK(IsMainThread() || IsMainThreadBlocked());
550 return main_thread_or_blocked_vars_unsafe_;
553 const ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main()
555 DCHECK(IsMainThread() || IsMainThreadBlocked());
556 return main_thread_or_blocked_vars_unsafe_;
559 ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() {
560 DCHECK(IsImplThread());
561 return compositor_thread_vars_unsafe_;
564 const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const {
565 DCHECK(IsImplThread());
566 return compositor_thread_vars_unsafe_;
569 void ThreadProxy::Start() {
570 DCHECK(IsMainThread());
571 DCHECK(Proxy::HasImplThread());
573 // Create LayerTreeHostImpl.
574 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
575 CompletionEvent completion;
576 Proxy::ImplThreadTaskRunner()->PostTask(
578 base::Bind(&ThreadProxy::InitializeImplOnImplThread,
579 base::Unretained(this),
583 main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr();
585 main().started = true;
588 void ThreadProxy::Stop() {
589 TRACE_EVENT0("cc", "ThreadProxy::Stop");
590 DCHECK(IsMainThread());
591 DCHECK(main().started);
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.
598 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
600 CompletionEvent completion;
601 Proxy::ImplThreadTaskRunner()->PostTask(
603 base::Bind(&ThreadProxy::FinishGLOnImplThread,
604 impl_thread_weak_ptr_,
609 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
611 CompletionEvent completion;
612 Proxy::ImplThreadTaskRunner()->PostTask(
614 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread,
615 impl_thread_weak_ptr_,
620 main().weak_factory.InvalidateWeakPtrs();
621 blocked_main().layer_tree_host = NULL;
622 main().started = false;
625 void ThreadProxy::ForceSerializeOnSwapBuffers() {
626 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
627 CompletionEvent completion;
628 Proxy::ImplThreadTaskRunner()->PostTask(
630 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
631 impl_thread_weak_ptr_,
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();
643 bool ThreadProxy::SupportsImplScrolling() const {
647 void ThreadProxy::SetDebugState(const LayerTreeDebugState& debug_state) {
648 Proxy::ImplThreadTaskRunner()->PostTask(
650 base::Bind(&ThreadProxy::SetDebugStateOnImplThread,
651 impl_thread_weak_ptr_,
655 void ThreadProxy::SetDebugStateOnImplThread(
656 const LayerTreeDebugState& debug_state) {
657 DCHECK(IsImplThread());
658 impl().scheduler->SetContinuousPainting(debug_state.continuous_painting);
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();
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();
680 if (!impl().layer_tree_host_impl->settings().impl_side_painting) {
681 DCHECK_GT(impl().layer_tree_host_impl->memory_allocation_limit_bytes(), 0u);
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(
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();
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());
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);
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());
720 main().commit_requested = false;
721 main().commit_request_sent_to_impl_thread = false;
722 main().animate_requested = false;
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(
729 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
730 impl_thread_weak_ptr_,
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(
741 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
742 impl_thread_weak_ptr_,
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;
758 layer_tree_host()->ApplyScrollAndScale(
759 begin_main_frame_state->scroll_info.get());
761 layer_tree_host()->WillBeginMainFrame();
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);
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();
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);
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();
783 layer_tree_host()->Layout();
784 TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
786 // Clear the commit flag after updating animations and layout here --- objects
787 // that only layout when painted will trigger another SetNeedsCommit inside
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;
795 scoped_ptr<ResourceUpdateQueue> queue =
796 make_scoped_ptr(new ResourceUpdateQueue);
798 bool updated = layer_tree_host()->UpdateLayers(queue.get());
800 layer_tree_host()->WillCommit();
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
807 if (main().animate_requested) {
808 // Forces SetNeedsAnimate to consider posting a commit task.
809 main().animate_requested = false;
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(
818 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
819 impl_thread_weak_ptr_,
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);
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.
836 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
838 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
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());
846 CompletionEvent completion;
847 Proxy::ImplThreadTaskRunner()->PostTask(
849 base::Bind(&ThreadProxy::StartCommitOnImplThread,
850 impl_thread_weak_ptr_,
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();
862 layer_tree_host()->CommitComplete();
863 layer_tree_host()->DidBeginMainFrame();
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());
874 if (!impl().layer_tree_host_impl) {
875 TRACE_EVENT_INSTANT0(
876 "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD);
877 completion->Signal();
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();
885 scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
887 if (impl().contents_texture_manager) {
888 DCHECK_EQ(impl().contents_texture_manager,
889 blocked_main().contents_texture_manager());
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();
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
900 queue->ClearUploadsToEvictedResources();
901 // Some textures in the layer tree are invalid. Kick off another commit
902 // to fill them again.
903 SetNeedsCommitOnImplThread();
906 impl().contents_texture_manager->PushTexturePrioritiesToBackings();
909 impl().commit_completion_event = completion;
910 impl().current_resource_update_controller = ResourceUpdateController::Create(
912 Proxy::ImplThreadTaskRunner(),
914 impl().layer_tree_host_impl->resource_provider());
915 impl().current_resource_update_controller->PerformMoreUpdates(
916 impl().scheduler->AnticipatedDrawTime());
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());
927 SetInputThrottledUntilCommitOnImplThread(false);
928 impl().layer_tree_host_impl->BeginMainFrameAborted(did_handle);
929 impl().scheduler->BeginMainFrameAborted(did_handle);
932 void ThreadProxy::ScheduledActionAnimate() {
933 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionAnimate");
934 DCHECK(IsImplThread());
936 impl().animation_time =
937 impl().layer_tree_host_impl->CurrentBeginFrameArgs().frame_time;
938 impl().layer_tree_host_impl->Animate(impl().animation_time);
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);
948 // Complete all remaining texture updates.
949 impl().current_resource_update_controller->Finalize();
950 impl().current_resource_update_controller = nullptr;
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;
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;
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;
972 impl().commit_completion_event->Signal();
973 impl().commit_completion_event = NULL;
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();
980 SetInputThrottledUntilCommitOnImplThread(false);
982 UpdateBackgroundAnimateTicking();
984 impl().next_frame_is_newly_committed_frame = true;
986 impl().timing_history.DidCommit();
989 void ThreadProxy::ScheduledActionUpdateVisibleTiles() {
990 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles");
991 DCHECK(IsImplThread());
992 impl().layer_tree_host_impl->UpdateVisibleTiles();
995 void ThreadProxy::ScheduledActionActivateSyncTree() {
996 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivateSyncTree");
997 DCHECK(IsImplThread());
998 impl().layer_tree_host_impl->ActivateSyncTree();
1001 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
1002 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
1003 DCHECK(IsImplThread());
1004 Proxy::MainThreadTaskRunner()->PostTask(
1006 base::Bind(&ThreadProxy::RequestNewOutputSurface, main_thread_weak_ptr_));
1009 DrawResult ThreadProxy::DrawSwapInternal(bool forced_draw) {
1010 TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
1013 DCHECK(IsImplThread());
1014 DCHECK(impl().layer_tree_host_impl.get());
1016 impl().timing_history.DidStartDrawing();
1017 base::AutoReset<bool> mark_inside(&impl().inside_draw, true);
1019 if (impl().layer_tree_host_impl->pending_tree())
1020 impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties();
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.
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.
1033 LayerTreeHostImpl::FrameData frame;
1034 bool draw_frame = false;
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;
1040 result = DRAW_ABORTED_CANT_DRAW;
1044 impl().layer_tree_host_impl->DrawLayers(
1045 &frame, impl().scheduler->LastBeginImplFrameTime());
1046 result = DRAW_SUCCESS;
1048 DCHECK_NE(DRAW_SUCCESS, result);
1050 impl().layer_tree_host_impl->DidDrawAllLayers(frame);
1052 bool start_ready_animations = draw_frame;
1053 impl().layer_tree_host_impl->UpdateAnimationState(start_ready_animations);
1056 bool did_request_swap = impl().layer_tree_host_impl->SwapBuffers(frame);
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);
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(
1070 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_));
1073 if (result == DRAW_SUCCESS)
1074 impl().timing_history.DidFinishDrawing();
1076 DCHECK_NE(INVALID_RESULT, result);
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();
1086 DrawResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1087 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
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());
1094 bool forced_draw = false;
1095 return DrawSwapInternal(forced_draw);
1098 DrawResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
1099 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
1100 bool forced_draw = true;
1101 return DrawSwapInternal(forced_draw);
1104 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1105 if (impl().current_resource_update_controller)
1106 impl().current_resource_update_controller->PerformMoreUpdates(time);
1109 base::TimeDelta ThreadProxy::DrawDurationEstimate() {
1110 return impl().timing_history.DrawDurationEstimate();
1113 base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() {
1114 return impl().timing_history.BeginMainFrameToCommitDurationEstimate();
1117 base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() {
1118 return impl().timing_history.CommitToActivateDurationEstimate();
1121 void ThreadProxy::DidBeginImplFrameDeadline() {
1122 impl().layer_tree_host_impl->ResetCurrentBeginFrameArgsForNextFrame();
1125 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1126 DCHECK(IsImplThread());
1127 impl().scheduler->NotifyReadyToCommit();
1130 void ThreadProxy::DidCommitAndDrawFrame() {
1131 DCHECK(IsMainThread());
1132 layer_tree_host()->DidCommitAndDrawFrame();
1135 void ThreadProxy::DidCompleteSwapBuffers() {
1136 DCHECK(IsMainThread());
1137 layer_tree_host()->DidCompleteSwapBuffers();
1140 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
1141 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1142 DCHECK(IsMainThread());
1143 layer_tree_host()->SetAnimationEvents(events.Pass());
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,
1154 impl().layer_tree_host_id,
1155 ImplThreadTaskRunner(),
1156 base::PowerMonitor::Get());
1157 impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible());
1159 impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr();
1160 completion->Signal();
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();
1173 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1174 scoped_ptr<OutputSurface> output_surface) {
1175 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1176 DCHECK(IsImplThread());
1178 LayerTreeHostImpl* host_impl = impl().layer_tree_host_impl.get();
1179 bool success = host_impl->InitializeRenderer(output_surface.Pass());
1180 RendererCapabilities capabilities;
1183 host_impl->GetRendererCapabilities().MainThreadCapabilities();
1186 Proxy::MainThreadTaskRunner()->PostTask(
1188 base::Bind(&ThreadProxy::DidInitializeOutputSurface,
1189 main_thread_weak_ptr_,
1194 impl().scheduler->DidCreateAndInitializeOutputSurface();
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();
1206 completion->Signal();
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();
1228 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1229 return ResourceUpdateController::MaxPartialTextureUpdates();
1232 ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState()
1233 : memory_allocation_limit_bytes(0),
1234 memory_allocation_priority_cutoff(0),
1235 evicted_ui_resources(false) {}
1237 ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
1239 void ThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
1240 CompletionEvent completion;
1242 DebugScopedSetMainThreadBlocked main_thread_blocked(
1243 const_cast<ThreadProxy*>(this));
1244 scoped_refptr<base::debug::TracedValue> state_refptr(state);
1245 Proxy::ImplThreadTaskRunner()->PostTask(
1247 base::Bind(&ThreadProxy::AsValueOnImplThread,
1248 impl_thread_weak_ptr_,
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();
1263 bool ThreadProxy::MainFrameWillHappenForTesting() {
1264 DCHECK(IsMainThread());
1265 CompletionEvent completion;
1266 bool main_frame_will_happen = false;
1268 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1269 Proxy::ImplThreadTaskRunner()->PostTask(
1271 base::Bind(&ThreadProxy::MainFrameWillHappenOnImplThreadForTesting,
1272 impl_thread_weak_ptr_,
1274 &main_frame_will_happen));
1277 return main_frame_will_happen;
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();
1287 *main_frame_will_happen = false;
1289 completion->Signal();
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();
1299 // Schedule expiration if smoothness currently takes priority.
1300 if (smoothness_takes_priority)
1301 impl().smoothness_priority_expiration_notifier.Schedule();
1303 // We use the same priority for both trees by default.
1304 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES;
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;
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;
1323 impl().layer_tree_host_impl->SetTreePriority(priority);
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());
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()) {
1338 .layer_tree_host_impl->output_surface()
1339 ->UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY);
1343 void ThreadProxy::PostDelayedScrollbarFadeOnImplThread(
1344 const base::Closure& start_fade,
1345 base::TimeDelta delay) {
1346 Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, start_fade, delay);
1349 void ThreadProxy::DidActivateSyncTree() {
1350 TRACE_EVENT0("cc", "ThreadProxy::DidActivateSyncTreeOnImplThread");
1351 DCHECK(IsImplThread());
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;
1361 UpdateBackgroundAnimateTicking();
1363 impl().timing_history.DidActivateSyncTree();
1366 void ThreadProxy::DidManageTiles() {
1367 DCHECK(IsImplThread());
1368 impl().scheduler->DidManageTiles();