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_synthetic_delay.h"
14 #include "base/metrics/histogram.h"
15 #include "cc/base/swap_promise.h"
16 #include "cc/debug/benchmark_instrumentation.h"
17 #include "cc/debug/devtools_instrumentation.h"
18 #include "cc/input/input_handler.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/output/output_surface.h"
21 #include "cc/quads/draw_quad.h"
22 #include "cc/resources/prioritized_resource_manager.h"
23 #include "cc/scheduler/delay_based_time_source.h"
24 #include "cc/scheduler/scheduler.h"
25 #include "cc/trees/blocking_task_runner.h"
26 #include "cc/trees/layer_tree_host.h"
27 #include "cc/trees/layer_tree_impl.h"
28 #include "ui/gfx/frame_time.h"
32 // Measured in seconds.
33 const double kSmoothnessTakesPriorityExpirationDelay
= 0.25;
35 unsigned int nextBeginFrameId
= 0;
37 class SwapPromiseChecker
{
39 explicit SwapPromiseChecker(cc::LayerTreeHost
* layer_tree_host
)
40 : layer_tree_host_(layer_tree_host
) {}
42 ~SwapPromiseChecker() {
43 layer_tree_host_
->BreakSwapPromises(cc::SwapPromise::COMMIT_FAILS
);
47 cc::LayerTreeHost
* layer_tree_host_
;
54 struct ThreadProxy::CommitPendingRequest
{
55 CompletionEvent completion
;
59 struct ThreadProxy::SchedulerStateRequest
{
60 CompletionEvent completion
;
61 scoped_ptr
<base::Value
> state
;
64 scoped_ptr
<Proxy
> ThreadProxy::Create(
65 LayerTreeHost
* layer_tree_host
,
66 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
) {
67 return make_scoped_ptr(new ThreadProxy(layer_tree_host
, impl_task_runner
))
71 ThreadProxy::ThreadProxy(
72 LayerTreeHost
* layer_tree_host
,
73 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
)
74 : Proxy(impl_task_runner
),
75 main_thread_only_vars_unsafe_(this, layer_tree_host
->id()),
76 main_thread_or_blocked_vars_unsafe_(layer_tree_host
),
77 compositor_thread_vars_unsafe_(this, layer_tree_host
->id()) {
78 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
79 DCHECK(IsMainThread());
80 DCHECK(this->layer_tree_host());
83 ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy
* proxy
,
84 int layer_tree_host_id
)
85 : layer_tree_host_id(layer_tree_host_id
),
86 animate_requested(false),
87 commit_requested(false),
88 commit_request_sent_to_impl_thread(false),
90 manage_tiles_pending(false),
91 can_cancel_commit(true),
93 weak_factory(proxy
) {}
95 ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
97 ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread(
99 : layer_tree_host(host
),
100 commit_waits_for_activation(false),
101 main_thread_inside_commit(false) {}
103 ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {}
105 PrioritizedResourceManager
*
106 ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() {
107 return layer_tree_host
->contents_texture_manager();
110 ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(ThreadProxy
* proxy
,
111 int layer_tree_host_id
)
112 : layer_tree_host_id(layer_tree_host_id
),
113 contents_texture_manager(NULL
),
114 commit_completion_event(NULL
),
115 completion_event_for_commit_held_on_tree_activation(NULL
),
116 next_frame_is_newly_committed_frame(false),
118 input_throttled_until_commit(false),
119 animations_frozen_until_next_draw(false),
120 did_commit_after_animating(false),
121 smoothness_priority_expiration_notifier(
122 proxy
->ImplThreadTaskRunner(),
123 base::Bind(&ThreadProxy::RenewTreePriority
, base::Unretained(proxy
)),
124 base::TimeDelta::FromMilliseconds(
125 kSmoothnessTakesPriorityExpirationDelay
* 1000)),
126 weak_factory(proxy
) {
129 ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
131 ThreadProxy::~ThreadProxy() {
132 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
133 DCHECK(IsMainThread());
134 DCHECK(!main().started
);
137 void ThreadProxy::FinishAllRendering() {
138 DCHECK(Proxy::IsMainThread());
139 DCHECK(!main().defer_commits
);
141 // Make sure all GL drawing is finished on the impl thread.
142 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
143 CompletionEvent completion
;
144 Proxy::ImplThreadTaskRunner()->PostTask(
146 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread
,
147 impl_thread_weak_ptr_
,
152 bool ThreadProxy::IsStarted() const {
153 DCHECK(Proxy::IsMainThread());
154 return main().started
;
157 void ThreadProxy::SetLayerTreeHostClientReady() {
158 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
159 Proxy::ImplThreadTaskRunner()->PostTask(
161 base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread
,
162 impl_thread_weak_ptr_
));
165 void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
166 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
167 impl().scheduler
->SetCanStart();
170 void ThreadProxy::SetVisible(bool visible
) {
171 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
172 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
174 CompletionEvent completion
;
175 Proxy::ImplThreadTaskRunner()->PostTask(
177 base::Bind(&ThreadProxy::SetVisibleOnImplThread
,
178 impl_thread_weak_ptr_
,
184 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent
* completion
,
186 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
187 impl().layer_tree_host_impl
->SetVisible(visible
);
188 impl().scheduler
->SetVisible(visible
);
189 UpdateBackgroundAnimateTicking();
190 completion
->Signal();
193 void ThreadProxy::UpdateBackgroundAnimateTicking() {
194 bool should_background_tick
=
195 !impl().scheduler
->WillDrawIfNeeded() &&
196 impl().layer_tree_host_impl
->active_tree()->root_layer();
197 impl().layer_tree_host_impl
->UpdateBackgroundAnimateTicking(
198 should_background_tick
);
199 if (should_background_tick
)
200 impl().animations_frozen_until_next_draw
= false;
203 void ThreadProxy::DidLoseOutputSurface() {
204 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurface");
205 DCHECK(IsMainThread());
206 layer_tree_host()->DidLoseOutputSurface();
209 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
211 // Return lost resources to their owners immediately.
212 BlockingTaskRunner::CapturePostTasks blocked
;
214 CompletionEvent completion
;
215 Proxy::ImplThreadTaskRunner()->PostTask(
217 base::Bind(&ThreadProxy::DeleteContentsTexturesOnImplThread
,
218 impl_thread_weak_ptr_
,
224 void ThreadProxy::CreateAndInitializeOutputSurface() {
225 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface");
226 DCHECK(IsMainThread());
228 scoped_ptr
<OutputSurface
> output_surface
=
229 layer_tree_host()->CreateOutputSurface();
231 if (output_surface
) {
232 Proxy::ImplThreadTaskRunner()->PostTask(
234 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread
,
235 impl_thread_weak_ptr_
,
236 base::Passed(&output_surface
)));
240 DidInitializeOutputSurface(false, RendererCapabilities());
243 void ThreadProxy::DidInitializeOutputSurface(
245 const RendererCapabilities
& capabilities
) {
246 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeOutputSurface");
247 DCHECK(IsMainThread());
248 main().renderer_capabilities_main_thread_copy
= capabilities
;
249 layer_tree_host()->OnCreateAndInitializeOutputSurfaceAttempted(success
);
252 Proxy::MainThreadTaskRunner()->PostTask(
254 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface
,
255 main_thread_weak_ptr_
));
259 void ThreadProxy::SetRendererCapabilitiesMainThreadCopy(
260 const RendererCapabilities
& capabilities
) {
261 main().renderer_capabilities_main_thread_copy
= capabilities
;
264 void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
265 DCHECK(IsMainThread());
266 if (main().commit_request_sent_to_impl_thread
)
268 main().commit_request_sent_to_impl_thread
= true;
269 Proxy::ImplThreadTaskRunner()->PostTask(
271 base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread
,
272 impl_thread_weak_ptr_
));
275 const RendererCapabilities
& ThreadProxy::GetRendererCapabilities() const {
276 DCHECK(IsMainThread());
277 DCHECK(!layer_tree_host()->output_surface_lost());
278 return main().renderer_capabilities_main_thread_copy
;
281 void ThreadProxy::SetNeedsAnimate() {
282 DCHECK(IsMainThread());
283 if (main().animate_requested
)
286 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
287 main().animate_requested
= true;
288 SendCommitRequestToImplThreadIfNeeded();
291 void ThreadProxy::SetNeedsUpdateLayers() {
292 DCHECK(IsMainThread());
294 if (main().commit_request_sent_to_impl_thread
)
296 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers");
298 SendCommitRequestToImplThreadIfNeeded();
301 void ThreadProxy::SetNeedsCommit() {
302 DCHECK(IsMainThread());
303 // Unconditionally set here to handle SetNeedsCommit calls during a commit.
304 main().can_cancel_commit
= false;
306 if (main().commit_requested
)
308 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
309 main().commit_requested
= true;
311 SendCommitRequestToImplThreadIfNeeded();
314 void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
315 DCHECK(IsImplThread());
316 Proxy::MainThreadTaskRunner()->PostTask(
318 base::Bind(&ThreadProxy::SetRendererCapabilitiesMainThreadCopy
,
319 main_thread_weak_ptr_
,
321 .layer_tree_host_impl
->GetRendererCapabilities()
322 .MainThreadCapabilities()));
325 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
326 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
327 DCHECK(IsImplThread());
328 CheckOutputSurfaceStatusOnImplThread();
331 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
332 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
333 DCHECK(IsImplThread());
334 if (!impl().layer_tree_host_impl
->IsContextLost())
336 Proxy::MainThreadTaskRunner()->PostTask(
338 base::Bind(&ThreadProxy::DidLoseOutputSurface
, main_thread_weak_ptr_
));
339 impl().scheduler
->DidLoseOutputSurface();
342 void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase
,
343 base::TimeDelta interval
) {
344 impl().scheduler
->CommitVSyncParameters(timebase
, interval
);
347 void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time
) {
348 impl().scheduler
->SetEstimatedParentDrawTime(draw_time
);
351 void ThreadProxy::SetMaxSwapsPendingOnImplThread(int max
) {
352 impl().scheduler
->SetMaxSwapsPending(max
);
355 void ThreadProxy::DidSwapBuffersOnImplThread() {
356 impl().scheduler
->DidSwapBuffers();
359 void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
360 TRACE_EVENT0("cc", "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
361 DCHECK(IsImplThread());
362 impl().scheduler
->DidSwapBuffersComplete();
363 Proxy::MainThreadTaskRunner()->PostTask(
365 base::Bind(&ThreadProxy::DidCompleteSwapBuffers
, main_thread_weak_ptr_
));
368 void ThreadProxy::SetNeedsBeginFrame(bool enable
) {
369 TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrame", "enable", enable
);
370 impl().layer_tree_host_impl
->SetNeedsBeginFrame(enable
);
371 UpdateBackgroundAnimateTicking();
374 void ThreadProxy::BeginFrame(const BeginFrameArgs
& args
) {
375 impl().scheduler
->BeginFrame(args
);
378 void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs
& args
) {
379 impl().layer_tree_host_impl
->WillBeginImplFrame(args
);
382 void ThreadProxy::OnCanDrawStateChanged(bool can_draw
) {
384 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw
);
385 DCHECK(IsImplThread());
386 impl().scheduler
->SetCanDraw(can_draw
);
387 UpdateBackgroundAnimateTicking();
390 void ThreadProxy::NotifyReadyToActivate() {
391 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
392 impl().scheduler
->NotifyReadyToActivate();
395 void ThreadProxy::SetNeedsCommitOnImplThread() {
396 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
397 DCHECK(IsImplThread());
398 impl().scheduler
->SetNeedsCommit();
401 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
402 scoped_ptr
<AnimationEventsVector
> events
) {
404 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
405 DCHECK(IsImplThread());
406 Proxy::MainThreadTaskRunner()->PostTask(
408 base::Bind(&ThreadProxy::SetAnimationEvents
,
409 main_thread_weak_ptr_
,
410 base::Passed(&events
)));
413 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes
,
414 int priority_cutoff
) {
415 DCHECK(IsImplThread());
417 if (!impl().contents_texture_manager
)
419 if (!impl().layer_tree_host_impl
->resource_provider())
423 impl().contents_texture_manager
->ReduceMemoryOnImplThread(
426 impl().layer_tree_host_impl
->resource_provider());
430 // The texture upload queue may reference textures that were just purged,
431 // clear them from the queue.
432 if (impl().current_resource_update_controller
) {
434 .current_resource_update_controller
->DiscardUploadsToEvictedResources();
439 bool ThreadProxy::IsInsideDraw() { return impl().inside_draw
; }
441 void ThreadProxy::SetNeedsRedraw(const gfx::Rect
& damage_rect
) {
442 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
443 DCHECK(IsMainThread());
444 Proxy::ImplThreadTaskRunner()->PostTask(
446 base::Bind(&ThreadProxy::SetNeedsRedrawRectOnImplThread
,
447 impl_thread_weak_ptr_
,
451 void ThreadProxy::SetNextCommitWaitsForActivation() {
452 DCHECK(IsMainThread());
453 DCHECK(!blocked_main().main_thread_inside_commit
);
454 blocked_main().commit_waits_for_activation
= true;
457 void ThreadProxy::SetDeferCommits(bool defer_commits
) {
458 DCHECK(IsMainThread());
459 DCHECK_NE(main().defer_commits
, defer_commits
);
460 main().defer_commits
= defer_commits
;
462 if (main().defer_commits
)
463 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
465 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
467 if (!main().defer_commits
&& main().pending_deferred_commit
)
468 Proxy::MainThreadTaskRunner()->PostTask(
470 base::Bind(&ThreadProxy::BeginMainFrame
,
471 main_thread_weak_ptr_
,
472 base::Passed(&main().pending_deferred_commit
)));
475 bool ThreadProxy::CommitRequested() const {
476 DCHECK(IsMainThread());
477 return main().commit_requested
;
480 bool ThreadProxy::BeginMainFrameRequested() const {
481 DCHECK(IsMainThread());
482 return main().commit_request_sent_to_impl_thread
;
485 void ThreadProxy::SetNeedsRedrawOnImplThread() {
486 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
487 DCHECK(IsImplThread());
488 impl().scheduler
->SetNeedsRedraw();
491 void ThreadProxy::SetNeedsAnimateOnImplThread() {
492 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimateOnImplThread");
493 DCHECK(IsImplThread());
494 impl().scheduler
->SetNeedsAnimate();
497 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
498 DCHECK(IsImplThread());
499 impl().scheduler
->SetNeedsManageTiles();
502 void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect
& damage_rect
) {
503 DCHECK(IsImplThread());
504 impl().layer_tree_host_impl
->SetViewportDamage(damage_rect
);
505 SetNeedsRedrawOnImplThread();
508 void ThreadProxy::SetSwapUsedIncompleteTileOnImplThread(
509 bool used_incomplete_tile
) {
510 DCHECK(IsImplThread());
511 if (used_incomplete_tile
) {
512 TRACE_EVENT_INSTANT0("cc",
513 "ThreadProxy::SetSwapUsedIncompleteTileOnImplThread",
514 TRACE_EVENT_SCOPE_THREAD
);
516 impl().scheduler
->SetSwapUsedIncompleteTile(used_incomplete_tile
);
519 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
520 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
521 DCHECK(IsImplThread());
522 impl().scheduler
->SetNeedsRedraw();
525 void ThreadProxy::MainThreadHasStoppedFlinging() {
526 DCHECK(IsMainThread());
527 Proxy::ImplThreadTaskRunner()->PostTask(
529 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread
,
530 impl_thread_weak_ptr_
));
533 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
534 DCHECK(IsImplThread());
535 impl().layer_tree_host_impl
->MainThreadHasStoppedFlinging();
538 void ThreadProxy::NotifyInputThrottledUntilCommit() {
539 DCHECK(IsMainThread());
540 Proxy::ImplThreadTaskRunner()->PostTask(
542 base::Bind(&ThreadProxy::SetInputThrottledUntilCommitOnImplThread
,
543 impl_thread_weak_ptr_
,
547 void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(bool is_throttled
) {
548 DCHECK(IsImplThread());
549 if (is_throttled
== impl().input_throttled_until_commit
)
551 impl().input_throttled_until_commit
= is_throttled
;
555 LayerTreeHost
* ThreadProxy::layer_tree_host() {
556 return blocked_main().layer_tree_host
;
559 const LayerTreeHost
* ThreadProxy::layer_tree_host() const {
560 return blocked_main().layer_tree_host
;
563 ThreadProxy::MainThreadOnly
& ThreadProxy::main() {
564 DCHECK(IsMainThread());
565 return main_thread_only_vars_unsafe_
;
567 const ThreadProxy::MainThreadOnly
& ThreadProxy::main() const {
568 DCHECK(IsMainThread());
569 return main_thread_only_vars_unsafe_
;
572 ThreadProxy::MainThreadOrBlockedMainThread
& ThreadProxy::blocked_main() {
573 DCHECK(IsMainThread() || IsMainThreadBlocked());
574 return main_thread_or_blocked_vars_unsafe_
;
577 const ThreadProxy::MainThreadOrBlockedMainThread
& ThreadProxy::blocked_main()
579 DCHECK(IsMainThread() || IsMainThreadBlocked());
580 return main_thread_or_blocked_vars_unsafe_
;
583 ThreadProxy::CompositorThreadOnly
& ThreadProxy::impl() {
584 DCHECK(IsImplThread());
585 return compositor_thread_vars_unsafe_
;
588 const ThreadProxy::CompositorThreadOnly
& ThreadProxy::impl() const {
589 DCHECK(IsImplThread());
590 return compositor_thread_vars_unsafe_
;
593 void ThreadProxy::Start() {
594 DCHECK(IsMainThread());
595 DCHECK(Proxy::HasImplThread());
597 // Create LayerTreeHostImpl.
598 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
599 CompletionEvent completion
;
600 Proxy::ImplThreadTaskRunner()->PostTask(
602 base::Bind(&ThreadProxy::InitializeImplOnImplThread
,
603 base::Unretained(this),
607 main_thread_weak_ptr_
= main().weak_factory
.GetWeakPtr();
609 main().started
= true;
612 void ThreadProxy::Stop() {
613 TRACE_EVENT0("cc", "ThreadProxy::Stop");
614 DCHECK(IsMainThread());
615 DCHECK(main().started
);
617 // Synchronously finishes pending GL operations and deletes the impl.
618 // The two steps are done as separate post tasks, so that tasks posted
619 // by the GL implementation due to the Finish can be executed by the
620 // renderer before shutting it down.
622 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
624 CompletionEvent completion
;
625 Proxy::ImplThreadTaskRunner()->PostTask(
627 base::Bind(&ThreadProxy::FinishGLOnImplThread
,
628 impl_thread_weak_ptr_
,
633 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
635 CompletionEvent completion
;
636 Proxy::ImplThreadTaskRunner()->PostTask(
638 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread
,
639 impl_thread_weak_ptr_
,
644 main().weak_factory
.InvalidateWeakPtrs();
645 blocked_main().layer_tree_host
= NULL
;
646 main().started
= false;
649 void ThreadProxy::ForceSerializeOnSwapBuffers() {
650 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
651 CompletionEvent completion
;
652 Proxy::ImplThreadTaskRunner()->PostTask(
654 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread
,
655 impl_thread_weak_ptr_
,
660 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
661 CompletionEvent
* completion
) {
662 if (impl().layer_tree_host_impl
->renderer())
663 impl().layer_tree_host_impl
->renderer()->DoNoOp();
664 completion
->Signal();
667 bool ThreadProxy::SupportsImplScrolling() const {
671 void ThreadProxy::SetDebugState(const LayerTreeDebugState
& debug_state
) {
672 Proxy::ImplThreadTaskRunner()->PostTask(
674 base::Bind(&ThreadProxy::SetDebugStateOnImplThread
,
675 impl_thread_weak_ptr_
,
679 void ThreadProxy::SetDebugStateOnImplThread(
680 const LayerTreeDebugState
& debug_state
) {
681 DCHECK(IsImplThread());
682 impl().scheduler
->SetContinuousPainting(debug_state
.continuous_painting
);
685 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent
* completion
) {
686 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
687 DCHECK(IsImplThread());
688 impl().layer_tree_host_impl
->FinishAllRendering();
689 completion
->Signal();
692 void ThreadProxy::ScheduledActionSendBeginMainFrame() {
693 unsigned int begin_frame_id
= nextBeginFrameId
++;
694 benchmark_instrumentation::ScopedBeginFrameTask
begin_frame_task(
695 benchmark_instrumentation::kSendBeginFrame
, begin_frame_id
);
696 scoped_ptr
<BeginMainFrameAndCommitState
> begin_main_frame_state(
697 new BeginMainFrameAndCommitState
);
698 begin_main_frame_state
->begin_frame_id
= begin_frame_id
;
699 begin_main_frame_state
->monotonic_frame_begin_time
=
700 impl().layer_tree_host_impl
->CurrentFrameTimeTicks();
701 begin_main_frame_state
->scroll_info
=
702 impl().layer_tree_host_impl
->ProcessScrollDeltas();
704 if (!impl().layer_tree_host_impl
->settings().impl_side_painting
) {
705 DCHECK_GT(impl().layer_tree_host_impl
->memory_allocation_limit_bytes(), 0u);
707 begin_main_frame_state
->memory_allocation_limit_bytes
=
708 impl().layer_tree_host_impl
->memory_allocation_limit_bytes();
709 begin_main_frame_state
->memory_allocation_priority_cutoff
=
710 impl().layer_tree_host_impl
->memory_allocation_priority_cutoff();
711 begin_main_frame_state
->evicted_ui_resources
=
712 impl().layer_tree_host_impl
->EvictedUIResourcesExist();
713 Proxy::MainThreadTaskRunner()->PostTask(
715 base::Bind(&ThreadProxy::BeginMainFrame
,
716 main_thread_weak_ptr_
,
717 base::Passed(&begin_main_frame_state
)));
718 devtools_instrumentation::DidRequestMainThreadFrame(
719 impl().layer_tree_host_id
);
720 impl().timing_history
.DidBeginMainFrame();
723 void ThreadProxy::BeginMainFrame(
724 scoped_ptr
<BeginMainFrameAndCommitState
> begin_main_frame_state
) {
725 benchmark_instrumentation::ScopedBeginFrameTask
begin_frame_task(
726 benchmark_instrumentation::kDoBeginFrame
,
727 begin_main_frame_state
->begin_frame_id
);
728 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
729 DCHECK(IsMainThread());
731 if (main().defer_commits
) {
732 main().pending_deferred_commit
= begin_main_frame_state
.Pass();
733 layer_tree_host()->DidDeferCommit();
734 TRACE_EVENT_INSTANT0(
735 "cc", "EarlyOut_DeferCommits", TRACE_EVENT_SCOPE_THREAD
);
739 // If the commit finishes, LayerTreeHost will transfer its swap promises to
740 // LayerTreeImpl. The destructor of SwapPromiseChecker checks LayerTressHost's
742 SwapPromiseChecker
swap_promise_checker(layer_tree_host());
744 main().commit_requested
= false;
745 main().commit_request_sent_to_impl_thread
= false;
746 main().animate_requested
= false;
748 if (!layer_tree_host()->visible()) {
749 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD
);
750 bool did_handle
= false;
751 Proxy::ImplThreadTaskRunner()->PostTask(
753 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread
,
754 impl_thread_weak_ptr_
,
759 if (layer_tree_host()->output_surface_lost()) {
760 TRACE_EVENT_INSTANT0(
761 "cc", "EarlyOut_OutputSurfaceLost", TRACE_EVENT_SCOPE_THREAD
);
762 bool did_handle
= false;
763 Proxy::ImplThreadTaskRunner()->PostTask(
765 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread
,
766 impl_thread_weak_ptr_
,
771 // Do not notify the impl thread of commit requests that occur during
772 // the apply/animate/layout part of the BeginMainFrameAndCommit process since
773 // those commit requests will get painted immediately. Once we have done
774 // the paint, main().commit_requested will be set to false to allow new commit
775 // requests to be scheduled.
776 // On the other hand, the animate_requested flag should remain cleared
777 // here so that any animation requests generated by the apply or animate
778 // callbacks will trigger another frame.
779 main().commit_requested
= true;
780 main().commit_request_sent_to_impl_thread
= true;
782 layer_tree_host()->ApplyScrollAndScale(
783 begin_main_frame_state
->scroll_info
.get());
785 layer_tree_host()->WillBeginMainFrame();
787 layer_tree_host()->UpdateClientAnimations(
788 begin_main_frame_state
->monotonic_frame_begin_time
);
789 layer_tree_host()->AnimateLayers(
790 begin_main_frame_state
->monotonic_frame_begin_time
);
791 blocked_main().last_monotonic_frame_begin_time
=
792 begin_main_frame_state
->monotonic_frame_begin_time
;
794 // Unlink any backings that the impl thread has evicted, so that we know to
795 // re-paint them in UpdateLayers.
796 if (blocked_main().contents_texture_manager()) {
797 blocked_main().contents_texture_manager()->UnlinkAndClearEvictedBackings();
799 blocked_main().contents_texture_manager()->SetMaxMemoryLimitBytes(
800 begin_main_frame_state
->memory_allocation_limit_bytes
);
801 blocked_main().contents_texture_manager()->SetExternalPriorityCutoff(
802 begin_main_frame_state
->memory_allocation_priority_cutoff
);
805 // Recreate all UI resources if there were evicted UI resources when the impl
806 // thread initiated the commit.
807 if (begin_main_frame_state
->evicted_ui_resources
)
808 layer_tree_host()->RecreateUIResources();
810 layer_tree_host()->Layout();
811 TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
813 // Clear the commit flag after updating animations and layout here --- objects
814 // that only layout when painted will trigger another SetNeedsCommit inside
816 main().commit_requested
= false;
817 main().commit_request_sent_to_impl_thread
= false;
818 bool can_cancel_this_commit
=
819 main().can_cancel_commit
&& !begin_main_frame_state
->evicted_ui_resources
;
820 main().can_cancel_commit
= true;
822 scoped_ptr
<ResourceUpdateQueue
> queue
=
823 make_scoped_ptr(new ResourceUpdateQueue
);
825 bool updated
= layer_tree_host()->UpdateLayers(queue
.get());
827 layer_tree_host()->WillCommit();
829 // Before calling animate, we set main().animate_requested to false. If it is
830 // true now, it means SetNeedAnimate was called again, but during a state when
831 // main().commit_request_sent_to_impl_thread = true. We need to force that
832 // call to happen again now so that the commit request is sent to the impl
834 if (main().animate_requested
) {
835 // Forces SetNeedsAnimate to consider posting a commit task.
836 main().animate_requested
= false;
840 if (!updated
&& can_cancel_this_commit
) {
841 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD
);
842 bool did_handle
= true;
843 Proxy::ImplThreadTaskRunner()->PostTask(
845 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread
,
846 impl_thread_weak_ptr_
,
849 // Although the commit is internally aborted, this is because it has been
850 // detected to be a no-op. From the perspective of an embedder, this commit
851 // went through, and input should no longer be throttled, etc.
852 layer_tree_host()->CommitComplete();
853 layer_tree_host()->DidBeginMainFrame();
857 // Notify the impl thread that the main thread is ready to commit. This will
858 // begin the commit process, which is blocking from the main thread's
859 // point of view, but asynchronously performed on the impl thread,
860 // coordinated by the Scheduler.
862 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
864 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
866 // This CapturePostTasks should be destroyed before CommitComplete() is
867 // called since that goes out to the embedder, and we want the embedder
868 // to receive its callbacks before that.
869 BlockingTaskRunner::CapturePostTasks blocked
;
871 CompletionEvent completion
;
872 Proxy::ImplThreadTaskRunner()->PostTask(
874 base::Bind(&ThreadProxy::StartCommitOnImplThread
,
875 impl_thread_weak_ptr_
,
880 RenderingStatsInstrumentation
* stats_instrumentation
=
881 layer_tree_host()->rendering_stats_instrumentation();
882 benchmark_instrumentation::IssueMainThreadRenderingStatsEvent(
883 stats_instrumentation
->main_thread_rendering_stats());
884 stats_instrumentation
->AccumulateAndClearMainThreadStats();
887 layer_tree_host()->CommitComplete();
888 layer_tree_host()->DidBeginMainFrame();
891 void ThreadProxy::StartCommitOnImplThread(CompletionEvent
* completion
,
892 ResourceUpdateQueue
* raw_queue
) {
893 TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
894 DCHECK(!impl().commit_completion_event
);
895 DCHECK(IsImplThread() && IsMainThreadBlocked());
896 DCHECK(impl().scheduler
);
897 DCHECK(impl().scheduler
->CommitPending());
899 if (!impl().layer_tree_host_impl
) {
900 TRACE_EVENT_INSTANT0(
901 "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD
);
902 completion
->Signal();
906 // Ideally, we should inform to impl thread when BeginMainFrame is started.
907 // But, we can avoid a PostTask in here.
908 impl().scheduler
->NotifyBeginMainFrameStarted();
910 scoped_ptr
<ResourceUpdateQueue
> queue(raw_queue
);
912 if (impl().contents_texture_manager
) {
913 DCHECK_EQ(impl().contents_texture_manager
,
914 blocked_main().contents_texture_manager());
916 // Cache this pointer that was created on the main thread side to avoid a
917 // data race between creating it and using it on the compositor thread.
918 impl().contents_texture_manager
= blocked_main().contents_texture_manager();
921 if (impl().contents_texture_manager
) {
922 if (impl().contents_texture_manager
->LinkedEvictedBackingsExist()) {
923 // Clear any uploads we were making to textures linked to evicted
925 queue
->ClearUploadsToEvictedResources();
926 // Some textures in the layer tree are invalid. Kick off another commit
927 // to fill them again.
928 SetNeedsCommitOnImplThread();
931 impl().contents_texture_manager
->PushTexturePrioritiesToBackings();
934 impl().commit_completion_event
= completion
;
935 impl().current_resource_update_controller
= ResourceUpdateController::Create(
937 Proxy::ImplThreadTaskRunner(),
939 impl().layer_tree_host_impl
->resource_provider());
940 impl().current_resource_update_controller
->PerformMoreUpdates(
941 impl().scheduler
->AnticipatedDrawTime());
944 void ThreadProxy::BeginMainFrameAbortedOnImplThread(bool did_handle
) {
945 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread");
946 DCHECK(IsImplThread());
947 DCHECK(impl().scheduler
);
948 DCHECK(impl().scheduler
->CommitPending());
949 DCHECK(!impl().layer_tree_host_impl
->pending_tree());
952 SetInputThrottledUntilCommitOnImplThread(false);
953 impl().layer_tree_host_impl
->BeginMainFrameAborted(did_handle
);
954 impl().scheduler
->BeginMainFrameAborted(did_handle
);
957 void ThreadProxy::ScheduledActionAnimate() {
958 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionAnimate");
959 DCHECK(IsImplThread());
961 if (!impl().animations_frozen_until_next_draw
) {
962 impl().animation_time
=
963 impl().layer_tree_host_impl
->CurrentFrameTimeTicks();
965 impl().layer_tree_host_impl
->Animate(impl().animation_time
);
966 impl().did_commit_after_animating
= false;
969 void ThreadProxy::ScheduledActionCommit() {
970 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
971 DCHECK(IsImplThread());
972 DCHECK(IsMainThreadBlocked());
973 DCHECK(impl().commit_completion_event
);
974 DCHECK(impl().current_resource_update_controller
);
976 // Complete all remaining texture updates.
977 impl().current_resource_update_controller
->Finalize();
978 impl().current_resource_update_controller
.reset();
980 if (impl().animations_frozen_until_next_draw
) {
981 impl().animation_time
= std::max(
982 impl().animation_time
, blocked_main().last_monotonic_frame_begin_time
);
984 impl().did_commit_after_animating
= true;
986 blocked_main().main_thread_inside_commit
= true;
987 impl().layer_tree_host_impl
->BeginCommit();
988 layer_tree_host()->BeginCommitOnImplThread(impl().layer_tree_host_impl
.get());
989 layer_tree_host()->FinishCommitOnImplThread(
990 impl().layer_tree_host_impl
.get());
991 blocked_main().main_thread_inside_commit
= false;
993 bool hold_commit
= layer_tree_host()->settings().impl_side_painting
&&
994 blocked_main().commit_waits_for_activation
;
995 blocked_main().commit_waits_for_activation
= false;
998 // For some layer types in impl-side painting, the commit is held until
999 // the sync tree is activated. It's also possible that the
1000 // sync tree has already activated if there was no work to be done.
1001 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD
);
1002 impl().completion_event_for_commit_held_on_tree_activation
=
1003 impl().commit_completion_event
;
1004 impl().commit_completion_event
= NULL
;
1006 impl().commit_completion_event
->Signal();
1007 impl().commit_completion_event
= NULL
;
1010 // Delay this step until afer the main thread has been released as it's
1011 // often a good bit of work to update the tree and prepare the new frame.
1012 impl().layer_tree_host_impl
->CommitComplete();
1014 SetInputThrottledUntilCommitOnImplThread(false);
1016 UpdateBackgroundAnimateTicking();
1018 impl().next_frame_is_newly_committed_frame
= true;
1020 impl().timing_history
.DidCommit();
1023 void ThreadProxy::ScheduledActionUpdateVisibleTiles() {
1024 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles");
1025 DCHECK(IsImplThread());
1026 impl().layer_tree_host_impl
->UpdateVisibleTiles();
1029 void ThreadProxy::ScheduledActionActivateSyncTree() {
1030 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivateSyncTree");
1031 DCHECK(IsImplThread());
1032 impl().layer_tree_host_impl
->ActivateSyncTree();
1035 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
1036 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
1037 DCHECK(IsImplThread());
1038 Proxy::MainThreadTaskRunner()->PostTask(
1040 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface
,
1041 main_thread_weak_ptr_
));
1044 DrawResult
ThreadProxy::DrawSwapInternal(bool forced_draw
) {
1045 TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
1048 DCHECK(IsImplThread());
1049 DCHECK(impl().layer_tree_host_impl
.get());
1051 impl().timing_history
.DidStartDrawing();
1052 base::TimeDelta draw_duration_estimate
= DrawDurationEstimate();
1053 base::AutoReset
<bool> mark_inside(&impl().inside_draw
, true);
1055 if (impl().did_commit_after_animating
) {
1056 impl().layer_tree_host_impl
->Animate(impl().animation_time
);
1057 impl().did_commit_after_animating
= false;
1060 if (impl().layer_tree_host_impl
->pending_tree())
1061 impl().layer_tree_host_impl
->pending_tree()->UpdateDrawProperties();
1063 // This method is called on a forced draw, regardless of whether we are able
1064 // to produce a frame, as the calling site on main thread is blocked until its
1065 // request completes, and we signal completion here. If CanDraw() is false, we
1066 // will indicate success=false to the caller, but we must still signal
1067 // completion to avoid deadlock.
1069 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
1070 // frame, so can only be used when such a frame is possible. Since
1071 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
1072 // CanDraw() as well.
1074 LayerTreeHostImpl::FrameData frame
;
1075 bool draw_frame
= false;
1077 if (impl().layer_tree_host_impl
->CanDraw()) {
1078 result
= impl().layer_tree_host_impl
->PrepareToDraw(&frame
);
1079 draw_frame
= forced_draw
|| result
== DRAW_SUCCESS
;
1081 result
= DRAW_ABORTED_CANT_DRAW
;
1085 impl().layer_tree_host_impl
->DrawLayers(&frame
);
1086 result
= DRAW_SUCCESS
;
1087 impl().animations_frozen_until_next_draw
= false;
1088 } else if (result
== DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
&&
1089 !impl().layer_tree_host_impl
->settings().impl_side_painting
) {
1090 // Without impl-side painting, the animated layer that is checkerboarding
1091 // will continue to checkerboard until the next commit. If this layer
1092 // continues to move during the commit, it may continue to checkerboard
1093 // after the commit since the region rasterized during the commit will not
1094 // match the region that is currently visible; eventually this
1095 // checkerboarding will be displayed when we force a draw. To avoid this,
1096 // we freeze animations until we successfully draw.
1097 impl().animations_frozen_until_next_draw
= true;
1099 DCHECK_NE(DRAW_SUCCESS
, result
);
1101 impl().layer_tree_host_impl
->DidDrawAllLayers(frame
);
1103 bool start_ready_animations
= draw_frame
;
1104 impl().layer_tree_host_impl
->UpdateAnimationState(start_ready_animations
);
1107 bool did_request_swap
= impl().layer_tree_host_impl
->SwapBuffers(frame
);
1109 // We don't know if we have incomplete tiles if we didn't actually swap.
1110 if (did_request_swap
) {
1111 DCHECK(!frame
.has_no_damage
);
1112 SetSwapUsedIncompleteTileOnImplThread(frame
.contains_incomplete_tile
);
1116 // Tell the main thread that the the newly-commited frame was drawn.
1117 if (impl().next_frame_is_newly_committed_frame
) {
1118 impl().next_frame_is_newly_committed_frame
= false;
1119 Proxy::MainThreadTaskRunner()->PostTask(
1121 base::Bind(&ThreadProxy::DidCommitAndDrawFrame
, main_thread_weak_ptr_
));
1125 CheckOutputSurfaceStatusOnImplThread();
1127 if (result
== DRAW_SUCCESS
) {
1128 base::TimeDelta draw_duration
= impl().timing_history
.DidFinishDrawing();
1130 base::TimeDelta draw_duration_overestimate
;
1131 base::TimeDelta draw_duration_underestimate
;
1132 if (draw_duration
> draw_duration_estimate
)
1133 draw_duration_underestimate
= draw_duration
- draw_duration_estimate
;
1135 draw_duration_overestimate
= draw_duration_estimate
- draw_duration
;
1136 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration",
1138 base::TimeDelta::FromMilliseconds(1),
1139 base::TimeDelta::FromMilliseconds(100),
1141 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate",
1142 draw_duration_underestimate
,
1143 base::TimeDelta::FromMilliseconds(1),
1144 base::TimeDelta::FromMilliseconds(100),
1146 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate",
1147 draw_duration_overestimate
,
1148 base::TimeDelta::FromMilliseconds(1),
1149 base::TimeDelta::FromMilliseconds(100),
1153 DCHECK_NE(INVALID_RESULT
, result
);
1157 void ThreadProxy::ScheduledActionManageTiles() {
1158 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionManageTiles");
1159 DCHECK(impl().layer_tree_host_impl
->settings().impl_side_painting
);
1160 impl().layer_tree_host_impl
->ManageTiles();
1163 DrawResult
ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1164 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
1166 // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
1167 // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should
1168 // never generate this call when it can't draw.
1169 DCHECK(impl().layer_tree_host_impl
->CanDraw());
1171 bool forced_draw
= false;
1172 return DrawSwapInternal(forced_draw
);
1175 DrawResult
ThreadProxy::ScheduledActionDrawAndSwapForced() {
1176 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
1177 bool forced_draw
= true;
1178 return DrawSwapInternal(forced_draw
);
1181 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time
) {
1182 if (impl().current_resource_update_controller
)
1183 impl().current_resource_update_controller
->PerformMoreUpdates(time
);
1186 base::TimeDelta
ThreadProxy::DrawDurationEstimate() {
1187 return impl().timing_history
.DrawDurationEstimate();
1190 base::TimeDelta
ThreadProxy::BeginMainFrameToCommitDurationEstimate() {
1191 return impl().timing_history
.BeginMainFrameToCommitDurationEstimate();
1194 base::TimeDelta
ThreadProxy::CommitToActivateDurationEstimate() {
1195 return impl().timing_history
.CommitToActivateDurationEstimate();
1198 void ThreadProxy::DidBeginImplFrameDeadline() {
1199 impl().layer_tree_host_impl
->ResetCurrentFrameTimeForNextFrame();
1202 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1203 DCHECK(IsImplThread());
1204 impl().scheduler
->NotifyReadyToCommit();
1207 void ThreadProxy::DidCommitAndDrawFrame() {
1208 DCHECK(IsMainThread());
1209 layer_tree_host()->DidCommitAndDrawFrame();
1212 void ThreadProxy::DidCompleteSwapBuffers() {
1213 DCHECK(IsMainThread());
1214 layer_tree_host()->DidCompleteSwapBuffers();
1217 void ThreadProxy::SetAnimationEvents(scoped_ptr
<AnimationEventsVector
> events
) {
1218 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1219 DCHECK(IsMainThread());
1220 layer_tree_host()->SetAnimationEvents(events
.Pass());
1223 void ThreadProxy::InitializeImplOnImplThread(CompletionEvent
* completion
) {
1224 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1225 DCHECK(IsImplThread());
1226 impl().layer_tree_host_impl
=
1227 layer_tree_host()->CreateLayerTreeHostImpl(this);
1228 SchedulerSettings
scheduler_settings(layer_tree_host()->settings());
1229 impl().scheduler
= Scheduler::Create(this,
1231 impl().layer_tree_host_id
,
1232 ImplThreadTaskRunner());
1233 impl().scheduler
->SetVisible(impl().layer_tree_host_impl
->visible());
1235 impl_thread_weak_ptr_
= impl().weak_factory
.GetWeakPtr();
1236 completion
->Signal();
1239 void ThreadProxy::DeleteContentsTexturesOnImplThread(
1240 CompletionEvent
* completion
) {
1241 TRACE_EVENT0("cc", "ThreadProxy::DeleteContentsTexturesOnImplThread");
1242 DCHECK(IsImplThread());
1243 DCHECK(IsMainThreadBlocked());
1244 layer_tree_host()->DeleteContentsTexturesOnImplThread(
1245 impl().layer_tree_host_impl
->resource_provider());
1246 completion
->Signal();
1249 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1250 scoped_ptr
<OutputSurface
> output_surface
) {
1251 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1252 DCHECK(IsImplThread());
1254 LayerTreeHostImpl
* host_impl
= impl().layer_tree_host_impl
.get();
1255 bool success
= host_impl
->InitializeRenderer(output_surface
.Pass());
1256 RendererCapabilities capabilities
;
1259 host_impl
->GetRendererCapabilities().MainThreadCapabilities();
1262 Proxy::MainThreadTaskRunner()->PostTask(
1264 base::Bind(&ThreadProxy::DidInitializeOutputSurface
,
1265 main_thread_weak_ptr_
,
1270 impl().scheduler
->DidCreateAndInitializeOutputSurface();
1273 void ThreadProxy::FinishGLOnImplThread(CompletionEvent
* completion
) {
1274 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
1275 DCHECK(IsImplThread());
1276 if (impl().layer_tree_host_impl
->resource_provider())
1277 impl().layer_tree_host_impl
->resource_provider()->Finish();
1278 completion
->Signal();
1281 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent
* completion
) {
1282 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1283 DCHECK(IsImplThread());
1284 DCHECK(IsMainThreadBlocked());
1285 layer_tree_host()->DeleteContentsTexturesOnImplThread(
1286 impl().layer_tree_host_impl
->resource_provider());
1287 impl().current_resource_update_controller
.reset();
1288 impl().layer_tree_host_impl
->SetNeedsBeginFrame(false);
1289 impl().scheduler
.reset();
1290 impl().layer_tree_host_impl
.reset();
1291 impl().weak_factory
.InvalidateWeakPtrs();
1292 impl().contents_texture_manager
= NULL
;
1293 completion
->Signal();
1296 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1297 return ResourceUpdateController::MaxPartialTextureUpdates();
1300 ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState()
1301 : memory_allocation_limit_bytes(0),
1302 memory_allocation_priority_cutoff(0),
1303 evicted_ui_resources(false) {}
1305 ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
1307 scoped_ptr
<base::Value
> ThreadProxy::AsValue() const {
1308 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1310 CompletionEvent completion
;
1312 DebugScopedSetMainThreadBlocked
main_thread_blocked(
1313 const_cast<ThreadProxy
*>(this));
1314 Proxy::ImplThreadTaskRunner()->PostTask(
1316 base::Bind(&ThreadProxy::AsValueOnImplThread
,
1317 impl_thread_weak_ptr_
,
1322 return state
.PassAs
<base::Value
>();
1325 void ThreadProxy::AsValueOnImplThread(CompletionEvent
* completion
,
1326 base::DictionaryValue
* state
) const {
1327 state
->Set("layer_tree_host_impl",
1328 impl().layer_tree_host_impl
->AsValue().release());
1329 completion
->Signal();
1332 bool ThreadProxy::CommitPendingForTesting() {
1333 DCHECK(IsMainThread());
1334 CommitPendingRequest commit_pending_request
;
1336 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1337 Proxy::ImplThreadTaskRunner()->PostTask(
1339 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting
,
1340 impl_thread_weak_ptr_
,
1341 &commit_pending_request
));
1342 commit_pending_request
.completion
.Wait();
1344 return commit_pending_request
.commit_pending
;
1347 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1348 CommitPendingRequest
* request
) {
1349 DCHECK(IsImplThread());
1350 if (impl().layer_tree_host_impl
->output_surface())
1351 request
->commit_pending
= impl().scheduler
->CommitPending();
1353 request
->commit_pending
= false;
1354 request
->completion
.Signal();
1357 scoped_ptr
<base::Value
> ThreadProxy::SchedulerAsValueForTesting() {
1359 return impl().scheduler
->AsValue().Pass();
1361 SchedulerStateRequest scheduler_state_request
;
1363 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1364 Proxy::ImplThreadTaskRunner()->PostTask(
1366 base::Bind(&ThreadProxy::SchedulerAsValueOnImplThreadForTesting
,
1367 impl_thread_weak_ptr_
,
1368 &scheduler_state_request
));
1369 scheduler_state_request
.completion
.Wait();
1371 return scheduler_state_request
.state
.Pass();
1374 void ThreadProxy::SchedulerAsValueOnImplThreadForTesting(
1375 SchedulerStateRequest
* request
) {
1376 DCHECK(IsImplThread());
1377 request
->state
= impl().scheduler
->AsValue();
1378 request
->completion
.Signal();
1381 void ThreadProxy::RenewTreePriority() {
1382 DCHECK(IsImplThread());
1383 bool smoothness_takes_priority
=
1384 impl().layer_tree_host_impl
->pinch_gesture_active() ||
1385 impl().layer_tree_host_impl
->page_scale_animation_active() ||
1386 (impl().layer_tree_host_impl
->IsCurrentlyScrolling() &&
1387 !impl().layer_tree_host_impl
->scroll_affects_scroll_handler());
1389 // Schedule expiration if smoothness currently takes priority.
1390 if (smoothness_takes_priority
)
1391 impl().smoothness_priority_expiration_notifier
.Schedule();
1393 // We use the same priority for both trees by default.
1394 TreePriority priority
= SAME_PRIORITY_FOR_BOTH_TREES
;
1396 // Smoothness takes priority if we have an expiration for it scheduled.
1397 if (impl().smoothness_priority_expiration_notifier
.HasPendingNotification())
1398 priority
= SMOOTHNESS_TAKES_PRIORITY
;
1400 // New content always takes priority when the active tree has
1401 // evicted resources or there is an invalid viewport size.
1402 if (impl().layer_tree_host_impl
->active_tree()->ContentsTexturesPurged() ||
1403 impl().layer_tree_host_impl
->active_tree()->ViewportSizeInvalid() ||
1404 impl().layer_tree_host_impl
->EvictedUIResourcesExist() ||
1405 impl().input_throttled_until_commit
) {
1406 // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
1407 // tree might be freed. We need to set RequiresHighResToDraw to ensure that
1408 // high res tiles will be required to activate pending tree.
1409 impl().layer_tree_host_impl
->active_tree()->SetRequiresHighResToDraw();
1410 priority
= NEW_CONTENT_TAKES_PRIORITY
;
1413 impl().layer_tree_host_impl
->SetTreePriority(priority
);
1414 impl().scheduler
->SetSmoothnessTakesPriority(priority
==
1415 SMOOTHNESS_TAKES_PRIORITY
);
1417 // Notify the the client of this compositor via the output surface.
1418 // TODO(epenner): Route this to compositor-thread instead of output-surface
1419 // after GTFO refactor of compositor-thread (http://crbug/170828).
1420 if (impl().layer_tree_host_impl
->output_surface()) {
1422 .layer_tree_host_impl
->output_surface()
1423 ->UpdateSmoothnessTakesPriority(priority
== SMOOTHNESS_TAKES_PRIORITY
);
1427 void ThreadProxy::PostDelayedScrollbarFadeOnImplThread(
1428 const base::Closure
& start_fade
,
1429 base::TimeDelta delay
) {
1430 Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE
, start_fade
, delay
);
1433 void ThreadProxy::DidActivateSyncTree() {
1434 TRACE_EVENT0("cc", "ThreadProxy::DidActivateSyncTreeOnImplThread");
1435 DCHECK(IsImplThread());
1437 if (impl().completion_event_for_commit_held_on_tree_activation
) {
1438 TRACE_EVENT_INSTANT0(
1439 "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD
);
1440 DCHECK(impl().layer_tree_host_impl
->settings().impl_side_painting
);
1441 impl().completion_event_for_commit_held_on_tree_activation
->Signal();
1442 impl().completion_event_for_commit_held_on_tree_activation
= NULL
;
1445 UpdateBackgroundAnimateTicking();
1447 impl().timing_history
.DidActivateSyncTree();
1450 void ThreadProxy::DidManageTiles() {
1451 DCHECK(IsImplThread());
1452 impl().scheduler
->DidManageTiles();