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"
9 #include "base/auto_reset.h"
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/metrics/histogram.h"
13 #include "cc/input/input_handler.h"
14 #include "cc/output/context_provider.h"
15 #include "cc/output/output_surface.h"
16 #include "cc/quads/draw_quad.h"
17 #include "cc/resources/prioritized_resource_manager.h"
18 #include "cc/scheduler/delay_based_time_source.h"
19 #include "cc/scheduler/frame_rate_controller.h"
20 #include "cc/scheduler/scheduler.h"
21 #include "cc/trees/blocking_task_runner.h"
22 #include "cc/trees/layer_tree_host.h"
23 #include "cc/trees/layer_tree_impl.h"
27 // Measured in seconds.
28 const double kContextRecreationTickRate
= 0.03;
30 // Measured in seconds.
31 const double kSmoothnessTakesPriorityExpirationDelay
= 0.25;
33 const size_t kDurationHistorySize
= 60;
34 const double kCommitAndActivationDurationEstimationPercentile
= 50.0;
35 const double kDrawDurationEstimationPercentile
= 100.0;
36 const int kDrawDurationEstimatePaddingInMicroseconds
= 0;
42 struct ThreadProxy::ReadbackRequest
{
43 CompletionEvent completion
;
49 struct ThreadProxy::CommitPendingRequest
{
50 CompletionEvent completion
;
54 struct ThreadProxy::SchedulerStateRequest
{
55 CompletionEvent completion
;
56 scoped_ptr
<base::Value
> state
;
59 scoped_ptr
<Proxy
> ThreadProxy::Create(
60 LayerTreeHost
* layer_tree_host
,
61 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
) {
62 return make_scoped_ptr(
63 new ThreadProxy(layer_tree_host
, impl_task_runner
)).PassAs
<Proxy
>();
66 ThreadProxy::ThreadProxy(
67 LayerTreeHost
* layer_tree_host
,
68 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
)
69 : Proxy(impl_task_runner
),
70 animate_requested_(false),
71 commit_requested_(false),
72 commit_request_sent_to_impl_thread_(false),
73 created_offscreen_context_provider_(false),
74 layer_tree_host_(layer_tree_host
),
76 textures_acquired_(true),
77 in_composite_and_readback_(false),
78 manage_tiles_pending_(false),
79 commit_waits_for_activation_(false),
80 inside_commit_(false),
81 weak_factory_on_impl_thread_(this),
83 begin_frame_sent_to_main_thread_completion_event_on_impl_thread_(NULL
),
84 readback_request_on_impl_thread_(NULL
),
85 commit_completion_event_on_impl_thread_(NULL
),
86 completion_event_for_commit_held_on_tree_activation_(NULL
),
87 texture_acquisition_completion_event_on_impl_thread_(NULL
),
88 next_frame_is_newly_committed_frame_on_impl_thread_(false),
89 throttle_frame_production_(
90 layer_tree_host
->settings().throttle_frame_production
),
91 begin_frame_scheduling_enabled_(
92 layer_tree_host
->settings().begin_frame_scheduling_enabled
),
93 using_synchronous_renderer_compositor_(
94 layer_tree_host
->settings().using_synchronous_renderer_compositor
),
96 can_cancel_commit_(true),
97 defer_commits_(false),
98 input_throttled_until_commit_(false),
99 renew_tree_priority_on_impl_thread_pending_(false),
100 draw_duration_history_(kDurationHistorySize
),
101 begin_frame_to_commit_duration_history_(kDurationHistorySize
),
102 commit_to_activate_duration_history_(kDurationHistorySize
) {
103 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
104 DCHECK(IsMainThread());
105 DCHECK(layer_tree_host_
);
108 ThreadProxy::~ThreadProxy() {
109 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
110 DCHECK(IsMainThread());
114 bool ThreadProxy::CompositeAndReadback(void* pixels
, gfx::Rect rect
) {
115 TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
116 DCHECK(IsMainThread());
117 DCHECK(layer_tree_host_
);
119 if (defer_commits_
) {
120 TRACE_EVENT0("cc", "CompositeAndReadback_DeferCommit");
124 if (!layer_tree_host_
->InitializeOutputSurfaceIfNeeded()) {
125 TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized");
129 // Perform a synchronous commit with an associated readback.
130 ReadbackRequest request
;
132 request
.pixels
= pixels
;
134 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
135 CompletionEvent begin_frame_sent_to_main_thread_completion
;
136 Proxy::ImplThreadTaskRunner()
137 ->PostTask(FROM_HERE
,
138 base::Bind(&ThreadProxy::ForceCommitForReadbackOnImplThread
,
139 impl_thread_weak_ptr_
,
140 &begin_frame_sent_to_main_thread_completion
,
142 begin_frame_sent_to_main_thread_completion
.Wait();
145 in_composite_and_readback_
= true;
146 // This is the forced commit.
147 // Note: The Impl thread also queues a separate BeginFrameOnMainThread on the
148 // main thread, which will be called after this CompositeAndReadback
149 // completes, to replace the forced commit.
150 BeginFrameOnMainThread(scoped_ptr
<BeginFrameAndCommitState
>());
151 in_composite_and_readback_
= false;
153 // Composite and readback requires a second commit to undo any changes
155 can_cancel_commit_
= false;
157 request
.completion
.Wait();
158 return request
.success
;
161 void ThreadProxy::ForceCommitForReadbackOnImplThread(
162 CompletionEvent
* begin_frame_sent_completion
,
163 ReadbackRequest
* request
) {
164 TRACE_EVENT0("cc", "ThreadProxy::ForceCommitForReadbackOnImplThread");
165 DCHECK(IsImplThread());
166 DCHECK(!begin_frame_sent_to_main_thread_completion_event_on_impl_thread_
);
167 DCHECK(!readback_request_on_impl_thread_
);
169 if (!layer_tree_host_impl_
) {
170 begin_frame_sent_completion
->Signal();
171 request
->success
= false;
172 request
->completion
.Signal();
176 readback_request_on_impl_thread_
= request
;
178 scheduler_on_impl_thread_
->SetNeedsForcedCommitForReadback();
179 if (scheduler_on_impl_thread_
->CommitPending()) {
180 begin_frame_sent_completion
->Signal();
184 begin_frame_sent_to_main_thread_completion_event_on_impl_thread_
=
185 begin_frame_sent_completion
;
188 void ThreadProxy::FinishAllRendering() {
189 DCHECK(Proxy::IsMainThread());
190 DCHECK(!defer_commits_
);
192 // Make sure all GL drawing is finished on the impl thread.
193 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
194 CompletionEvent completion
;
195 Proxy::ImplThreadTaskRunner()->PostTask(
197 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread
,
198 impl_thread_weak_ptr_
,
203 bool ThreadProxy::IsStarted() const {
204 DCHECK(Proxy::IsMainThread());
208 void ThreadProxy::SetLayerTreeHostClientReady() {
209 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
210 Proxy::ImplThreadTaskRunner()->PostTask(
212 base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread
,
213 impl_thread_weak_ptr_
));
216 void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
217 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
218 scheduler_on_impl_thread_
->SetCanStart();
221 void ThreadProxy::SetVisible(bool visible
) {
222 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
223 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
225 CompletionEvent completion
;
226 Proxy::ImplThreadTaskRunner()->PostTask(
228 base::Bind(&ThreadProxy::SetVisibleOnImplThread
,
229 impl_thread_weak_ptr_
,
235 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent
* completion
,
237 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
238 layer_tree_host_impl_
->SetVisible(visible
);
239 scheduler_on_impl_thread_
->SetVisible(visible
);
240 UpdateBackgroundAnimateTicking();
241 completion
->Signal();
244 void ThreadProxy::UpdateBackgroundAnimateTicking() {
245 layer_tree_host_impl_
->UpdateBackgroundAnimateTicking(
246 !scheduler_on_impl_thread_
->WillDrawIfNeeded() &&
247 layer_tree_host_impl_
->active_tree()->root_layer());
250 void ThreadProxy::DoCreateAndInitializeOutputSurface() {
251 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface");
252 DCHECK(IsMainThread());
254 scoped_ptr
<OutputSurface
> output_surface
= first_output_surface_
.Pass();
256 output_surface
= layer_tree_host_
->CreateOutputSurface();
258 RendererCapabilities capabilities
;
259 bool success
= !!output_surface
;
261 OnOutputSurfaceInitializeAttempted(false, capabilities
);
265 scoped_refptr
<ContextProvider
> offscreen_context_provider
;
266 if (created_offscreen_context_provider_
) {
267 offscreen_context_provider
= layer_tree_host_
->client()->
268 OffscreenContextProviderForCompositorThread();
269 success
= !!offscreen_context_provider
.get();
271 OnOutputSurfaceInitializeAttempted(false, capabilities
);
278 // Make a blocking call to InitializeOutputSurfaceOnImplThread. The results
279 // of that call are pushed into the success and capabilities local
281 CompletionEvent completion
;
282 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
284 Proxy::ImplThreadTaskRunner()->PostTask(
286 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread
,
287 impl_thread_weak_ptr_
,
289 base::Passed(&output_surface
),
290 offscreen_context_provider
,
296 OnOutputSurfaceInitializeAttempted(success
, capabilities
);
299 void ThreadProxy::OnOutputSurfaceInitializeAttempted(
301 const RendererCapabilities
& capabilities
) {
302 DCHECK(IsMainThread());
303 DCHECK(layer_tree_host_
);
306 renderer_capabilities_main_thread_copy_
= capabilities
;
309 LayerTreeHost::CreateResult result
=
310 layer_tree_host_
->OnCreateAndInitializeOutputSurfaceAttempted(success
);
311 if (result
== LayerTreeHost::CreateFailedButTryAgain
) {
312 if (!output_surface_creation_callback_
.callback().is_null()) {
313 Proxy::MainThreadTaskRunner()->PostTask(
314 FROM_HERE
, output_surface_creation_callback_
.callback());
317 output_surface_creation_callback_
.Cancel();
321 void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
322 DCHECK(IsMainThread());
323 if (commit_request_sent_to_impl_thread_
)
325 commit_request_sent_to_impl_thread_
= true;
326 Proxy::ImplThreadTaskRunner()->PostTask(
328 base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread
,
329 impl_thread_weak_ptr_
));
332 const RendererCapabilities
& ThreadProxy::GetRendererCapabilities() const {
333 DCHECK(IsMainThread());
334 DCHECK(!layer_tree_host_
->output_surface_lost());
335 return renderer_capabilities_main_thread_copy_
;
338 void ThreadProxy::SetNeedsAnimate() {
339 DCHECK(IsMainThread());
340 if (animate_requested_
)
343 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
344 animate_requested_
= true;
345 can_cancel_commit_
= false;
346 SendCommitRequestToImplThreadIfNeeded();
349 void ThreadProxy::SetNeedsUpdateLayers() {
350 DCHECK(IsMainThread());
351 SendCommitRequestToImplThreadIfNeeded();
354 void ThreadProxy::SetNeedsCommit() {
355 DCHECK(IsMainThread());
356 // Unconditionally set here to handle SetNeedsCommit calls during a commit.
357 can_cancel_commit_
= false;
359 if (commit_requested_
)
361 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
362 commit_requested_
= true;
364 SendCommitRequestToImplThreadIfNeeded();
367 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
368 DCHECK(IsImplThread());
369 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
370 Proxy::ImplThreadTaskRunner()->PostTask(
372 base::Bind(&ThreadProxy::CheckOutputSurfaceStatusOnImplThread
,
373 impl_thread_weak_ptr_
));
376 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
377 DCHECK(IsImplThread());
378 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
379 if (!layer_tree_host_impl_
->IsContextLost())
381 if (cc::ContextProvider
* offscreen_contexts
=
382 layer_tree_host_impl_
->offscreen_context_provider())
383 offscreen_contexts
->VerifyContexts();
384 scheduler_on_impl_thread_
->DidLoseOutputSurface();
387 void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
388 DCHECK(IsImplThread());
389 TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
390 Proxy::MainThreadTaskRunner()->PostTask(
392 base::Bind(&ThreadProxy::DidCompleteSwapBuffers
, main_thread_weak_ptr_
));
395 void ThreadProxy::SetNeedsBeginFrameOnImplThread(bool enable
) {
396 DCHECK(IsImplThread());
397 TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrameOnImplThread",
399 layer_tree_host_impl_
->SetNeedsBeginFrame(enable
);
402 void ThreadProxy::BeginFrameOnImplThread(const BeginFrameArgs
& args
) {
403 DCHECK(IsImplThread());
404 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnImplThread");
405 scheduler_on_impl_thread_
->BeginFrame(args
);
408 void ThreadProxy::OnCanDrawStateChanged(bool can_draw
) {
409 DCHECK(IsImplThread());
411 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw
);
412 scheduler_on_impl_thread_
->SetCanDraw(can_draw
);
413 UpdateBackgroundAnimateTicking();
416 void ThreadProxy::NotifyReadyToActivate() {
417 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
418 scheduler_on_impl_thread_
->NotifyReadyToActivate();
421 void ThreadProxy::SetNeedsCommitOnImplThread() {
422 DCHECK(IsImplThread());
423 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
424 scheduler_on_impl_thread_
->SetNeedsCommit();
427 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
428 scoped_ptr
<AnimationEventsVector
> events
,
429 base::Time wall_clock_time
) {
430 DCHECK(IsImplThread());
432 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
433 Proxy::MainThreadTaskRunner()->PostTask(
435 base::Bind(&ThreadProxy::SetAnimationEvents
,
436 main_thread_weak_ptr_
,
437 base::Passed(&events
),
441 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes
,
442 int priority_cutoff
) {
443 DCHECK(IsImplThread());
445 if (!layer_tree_host_
->contents_texture_manager())
448 bool reduce_result
= layer_tree_host_
->contents_texture_manager()->
449 ReduceMemoryOnImplThread(limit_bytes
,
451 layer_tree_host_impl_
->resource_provider());
455 // The texture upload queue may reference textures that were just purged,
456 // clear them from the queue.
457 if (current_resource_update_controller_on_impl_thread_
) {
458 current_resource_update_controller_on_impl_thread_
->
459 DiscardUploadsToEvictedResources();
464 void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
465 DCHECK(IsImplThread());
467 if (!layer_tree_host_
->contents_texture_manager())
470 layer_tree_host_
->contents_texture_manager()->ReduceWastedMemoryOnImplThread(
471 layer_tree_host_impl_
->resource_provider());
474 void ThreadProxy::SendManagedMemoryStats() {
475 DCHECK(IsImplThread());
476 if (!layer_tree_host_impl_
)
478 if (!layer_tree_host_
->contents_texture_manager())
481 // If we are using impl-side painting, then SendManagedMemoryStats is called
482 // directly after the tile manager's manage function, and doesn't need to
483 // interact with main thread's layer tree.
484 if (layer_tree_host_
->settings().impl_side_painting
)
487 layer_tree_host_impl_
->SendManagedMemoryStats(
488 layer_tree_host_
->contents_texture_manager()->MemoryVisibleBytes(),
489 layer_tree_host_
->contents_texture_manager()->
490 MemoryVisibleAndNearbyBytes(),
491 layer_tree_host_
->contents_texture_manager()->MemoryUseBytes());
494 bool ThreadProxy::IsInsideDraw() { return inside_draw_
; }
496 void ThreadProxy::SetNeedsRedraw(gfx::Rect damage_rect
) {
497 DCHECK(IsMainThread());
498 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
499 Proxy::ImplThreadTaskRunner()->PostTask(
501 base::Bind(&ThreadProxy::SetNeedsRedrawRectOnImplThread
,
502 impl_thread_weak_ptr_
,
506 void ThreadProxy::SetNextCommitWaitsForActivation() {
507 DCHECK(IsMainThread());
508 DCHECK(!inside_commit_
);
509 commit_waits_for_activation_
= true;
512 void ThreadProxy::SetDeferCommits(bool defer_commits
) {
513 DCHECK(IsMainThread());
514 DCHECK_NE(defer_commits_
, defer_commits
);
515 defer_commits_
= defer_commits
;
518 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
520 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
522 if (!defer_commits_
&& pending_deferred_commit_
)
523 Proxy::MainThreadTaskRunner()->PostTask(
525 base::Bind(&ThreadProxy::BeginFrameOnMainThread
,
526 main_thread_weak_ptr_
,
527 base::Passed(&pending_deferred_commit_
)));
530 bool ThreadProxy::CommitRequested() const {
531 DCHECK(IsMainThread());
532 return commit_requested_
;
535 void ThreadProxy::SetNeedsRedrawOnImplThread() {
536 DCHECK(IsImplThread());
537 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
538 scheduler_on_impl_thread_
->SetNeedsRedraw();
541 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
542 DCHECK(IsImplThread());
543 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsManageTilesOnImplThread");
544 scheduler_on_impl_thread_
->SetNeedsManageTiles();
547 void ThreadProxy::SetNeedsRedrawRectOnImplThread(gfx::Rect damage_rect
) {
548 DCHECK(IsImplThread());
549 layer_tree_host_impl_
->SetViewportDamage(damage_rect
);
550 SetNeedsRedrawOnImplThread();
553 void ThreadProxy::SetSwapUsedIncompleteTileOnImplThread(
554 bool used_incomplete_tile
) {
555 DCHECK(IsImplThread());
556 if (used_incomplete_tile
) {
557 TRACE_EVENT_INSTANT0(
559 "ThreadProxy::SetSwapUsedIncompleteTileOnImplThread",
560 TRACE_EVENT_SCOPE_THREAD
);
562 scheduler_on_impl_thread_
->SetSwapUsedIncompleteTile(
563 used_incomplete_tile
);
566 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
567 DCHECK(IsImplThread());
568 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
569 scheduler_on_impl_thread_
->SetNeedsRedraw();
572 void ThreadProxy::MainThreadHasStoppedFlinging() {
573 DCHECK(IsMainThread());
574 Proxy::ImplThreadTaskRunner()->PostTask(
576 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread
,
577 impl_thread_weak_ptr_
));
580 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
581 DCHECK(IsImplThread());
582 layer_tree_host_impl_
->MainThreadHasStoppedFlinging();
585 void ThreadProxy::NotifyInputThrottledUntilCommit() {
586 DCHECK(IsMainThread());
587 Proxy::ImplThreadTaskRunner()->PostTask(
589 base::Bind(&ThreadProxy::SetInputThrottledUntilCommitOnImplThread
,
590 impl_thread_weak_ptr_
,
594 void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(
596 DCHECK(IsImplThread());
597 if (is_throttled
== input_throttled_until_commit_
)
599 input_throttled_until_commit_
= is_throttled
;
603 void ThreadProxy::Start(scoped_ptr
<OutputSurface
> first_output_surface
) {
604 DCHECK(IsMainThread());
605 DCHECK(Proxy::HasImplThread());
606 DCHECK(first_output_surface
);
608 // Create LayerTreeHostImpl.
609 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
610 CompletionEvent completion
;
611 Proxy::ImplThreadTaskRunner()->PostTask(
613 base::Bind(&ThreadProxy::InitializeImplOnImplThread
,
614 base::Unretained(this),
618 main_thread_weak_ptr_
= weak_factory_
.GetWeakPtr();
619 first_output_surface_
= first_output_surface
.Pass();
624 void ThreadProxy::Stop() {
625 TRACE_EVENT0("cc", "ThreadProxy::Stop");
626 DCHECK(IsMainThread());
629 // Synchronously finishes pending GL operations and deletes the impl.
630 // The two steps are done as separate post tasks, so that tasks posted
631 // by the GL implementation due to the Finish can be executed by the
632 // renderer before shutting it down.
634 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
636 CompletionEvent completion
;
637 Proxy::ImplThreadTaskRunner()->PostTask(
639 base::Bind(&ThreadProxy::FinishGLOnImplThread
,
640 impl_thread_weak_ptr_
,
645 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
647 CompletionEvent completion
;
648 Proxy::ImplThreadTaskRunner()->PostTask(
650 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread
,
651 impl_thread_weak_ptr_
,
656 weak_factory_
.InvalidateWeakPtrs();
658 DCHECK(!layer_tree_host_impl_
.get()); // verify that the impl deleted.
659 layer_tree_host_
= NULL
;
663 void ThreadProxy::ForceSerializeOnSwapBuffers() {
664 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
665 CompletionEvent completion
;
666 Proxy::ImplThreadTaskRunner()->PostTask(
668 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread
,
669 impl_thread_weak_ptr_
,
674 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
675 CompletionEvent
* completion
) {
676 if (layer_tree_host_impl_
->renderer())
677 layer_tree_host_impl_
->renderer()->DoNoOp();
678 completion
->Signal();
681 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent
* completion
) {
682 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
683 DCHECK(IsImplThread());
684 layer_tree_host_impl_
->FinishAllRendering();
685 completion
->Signal();
688 void ThreadProxy::ScheduledActionSendBeginFrameToMainThread() {
689 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginFrameToMainThread");
690 scoped_ptr
<BeginFrameAndCommitState
> begin_frame_state(
691 new BeginFrameAndCommitState
);
692 begin_frame_state
->monotonic_frame_begin_time
=
693 layer_tree_host_impl_
->CurrentPhysicalTimeTicks();
694 begin_frame_state
->scroll_info
=
695 layer_tree_host_impl_
->ProcessScrollDeltas();
697 if (!layer_tree_host_impl_
->settings().impl_side_painting
) {
698 DCHECK_GT(layer_tree_host_impl_
->memory_allocation_limit_bytes(), 0u);
700 begin_frame_state
->memory_allocation_limit_bytes
=
701 layer_tree_host_impl_
->memory_allocation_limit_bytes();
702 begin_frame_state
->evicted_ui_resources
=
703 layer_tree_host_impl_
->EvictedUIResourcesExist();
704 Proxy::MainThreadTaskRunner()->PostTask(
706 base::Bind(&ThreadProxy::BeginFrameOnMainThread
,
707 main_thread_weak_ptr_
,
708 base::Passed(&begin_frame_state
)));
710 if (begin_frame_sent_to_main_thread_completion_event_on_impl_thread_
) {
711 begin_frame_sent_to_main_thread_completion_event_on_impl_thread_
->Signal();
712 begin_frame_sent_to_main_thread_completion_event_on_impl_thread_
= NULL
;
714 begin_frame_sent_to_main_thread_time_
= base::TimeTicks::HighResNow();
717 void ThreadProxy::BeginFrameOnMainThread(
718 scoped_ptr
<BeginFrameAndCommitState
> begin_frame_state
) {
719 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnMainThread");
720 DCHECK(IsMainThread());
722 if (!layer_tree_host_
)
725 if (defer_commits_
) {
726 pending_deferred_commit_
= begin_frame_state
.Pass();
727 layer_tree_host_
->DidDeferCommit();
728 TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
732 // Do not notify the impl thread of commit requests that occur during
733 // the apply/animate/layout part of the BeginFrameAndCommit process since
734 // those commit requests will get painted immediately. Once we have done
735 // the paint, commit_requested_ will be set to false to allow new commit
736 // requests to be scheduled.
737 commit_requested_
= true;
738 commit_request_sent_to_impl_thread_
= true;
740 // On the other hand, the AnimationRequested flag needs to be cleared
741 // here so that any animation requests generated by the apply or animate
742 // callbacks will trigger another frame.
743 animate_requested_
= false;
745 if (!in_composite_and_readback_
&& !layer_tree_host_
->visible()) {
746 commit_requested_
= false;
747 commit_request_sent_to_impl_thread_
= false;
749 TRACE_EVENT0("cc", "EarlyOut_NotVisible");
750 bool did_handle
= false;
751 Proxy::ImplThreadTaskRunner()->PostTask(
753 base::Bind(&ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread
,
754 impl_thread_weak_ptr_
,
759 if (begin_frame_state
)
760 layer_tree_host_
->ApplyScrollAndScale(*begin_frame_state
->scroll_info
);
762 layer_tree_host_
->WillBeginFrame();
764 if (begin_frame_state
) {
765 layer_tree_host_
->UpdateClientAnimations(
766 begin_frame_state
->monotonic_frame_begin_time
);
767 layer_tree_host_
->AnimateLayers(
768 begin_frame_state
->monotonic_frame_begin_time
);
771 // Unlink any backings that the impl thread has evicted, so that we know to
772 // re-paint them in UpdateLayers.
773 if (layer_tree_host_
->contents_texture_manager()) {
774 layer_tree_host_
->contents_texture_manager()->
775 UnlinkAndClearEvictedBackings();
778 // Recreate all UI resources if there were evicted UI resources when the impl
779 // thread initiated the commit.
780 bool evicted_ui_resources
=
781 begin_frame_state
? begin_frame_state
->evicted_ui_resources
: false;
782 if (evicted_ui_resources
)
783 layer_tree_host_
->RecreateUIResources();
785 layer_tree_host_
->Layout();
787 // Clear the commit flag after updating animations and layout here --- objects
788 // that only layout when painted will trigger another SetNeedsCommit inside
790 commit_requested_
= false;
791 commit_request_sent_to_impl_thread_
= false;
792 bool can_cancel_this_commit
=
793 can_cancel_commit_
&&
794 !in_composite_and_readback_
&&
795 !evicted_ui_resources
;
796 can_cancel_commit_
= true;
798 scoped_ptr
<ResourceUpdateQueue
> queue
=
799 make_scoped_ptr(new ResourceUpdateQueue
);
800 bool updated
= layer_tree_host_
->UpdateLayers(
802 begin_frame_state
? begin_frame_state
->memory_allocation_limit_bytes
805 // Once single buffered layers are committed, they cannot be modified until
806 // they are drawn by the impl thread.
807 textures_acquired_
= false;
809 layer_tree_host_
->WillCommit();
811 if (!updated
&& can_cancel_this_commit
) {
812 TRACE_EVENT0("cc", "EarlyOut_NoUpdates");
813 bool did_handle
= true;
814 Proxy::ImplThreadTaskRunner()->PostTask(
816 base::Bind(&ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread
,
817 impl_thread_weak_ptr_
,
820 // Although the commit is internally aborted, this is because it has been
821 // detected to be a no-op. From the perspective of an embedder, this commit
822 // went through, and input should no longer be throttled, etc.
823 layer_tree_host_
->CommitComplete();
824 layer_tree_host_
->DidBeginFrame();
828 // Before calling animate, we set animate_requested_ to false. If it is true
829 // now, it means SetNeedAnimate was called again, but during a state when
830 // commit_request_sent_to_impl_thread_ = true. We need to force that call to
831 // happen again now so that the commit request is sent to the impl thread.
832 if (animate_requested_
) {
833 // Forces SetNeedsAnimate to consider posting a commit task.
834 animate_requested_
= false;
838 scoped_refptr
<cc::ContextProvider
> offscreen_context_provider
;
839 if (renderer_capabilities_main_thread_copy_
.using_offscreen_context3d
&&
840 layer_tree_host_
->needs_offscreen_context()) {
841 offscreen_context_provider
= layer_tree_host_
->client()->
842 OffscreenContextProviderForCompositorThread();
843 if (offscreen_context_provider
.get())
844 created_offscreen_context_provider_
= true;
847 // Notify the impl thread that the main thread is ready to commit. This will
848 // begin the commit process, which is blocking from the main thread's
849 // point of view, but asynchronously performed on the impl thread,
850 // coordinated by the Scheduler.
852 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnMainThread::commit");
854 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
856 // This CapturePostTasks should be destroyed before CommitComplete() is
857 // called since that goes out to the embedder, and we want the embedder
858 // to receive its callbacks before that.
859 BlockingTaskRunner::CapturePostTasks blocked
;
861 RenderingStatsInstrumentation
* stats_instrumentation
=
862 layer_tree_host_
->rendering_stats_instrumentation();
863 base::TimeTicks start_time
= stats_instrumentation
->StartRecording();
865 CompletionEvent completion
;
866 Proxy::ImplThreadTaskRunner()->PostTask(
868 base::Bind(&ThreadProxy::StartCommitOnImplThread
,
869 impl_thread_weak_ptr_
,
872 offscreen_context_provider
));
875 base::TimeDelta duration
= stats_instrumentation
->EndRecording(start_time
);
876 stats_instrumentation
->AddCommit(duration
);
877 stats_instrumentation
->IssueTraceEventForMainThreadStats();
878 stats_instrumentation
->AccumulateAndClearMainThreadStats();
881 layer_tree_host_
->CommitComplete();
882 layer_tree_host_
->DidBeginFrame();
885 void ThreadProxy::StartCommitOnImplThread(
886 CompletionEvent
* completion
,
887 ResourceUpdateQueue
* raw_queue
,
888 scoped_refptr
<cc::ContextProvider
> offscreen_context_provider
) {
889 scoped_ptr
<ResourceUpdateQueue
> queue(raw_queue
);
891 TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
892 DCHECK(!commit_completion_event_on_impl_thread_
);
893 DCHECK(IsImplThread() && IsMainThreadBlocked());
894 DCHECK(scheduler_on_impl_thread_
);
895 DCHECK(scheduler_on_impl_thread_
->CommitPending());
897 if (!layer_tree_host_impl_
) {
898 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
899 completion
->Signal();
903 if (offscreen_context_provider
.get())
904 offscreen_context_provider
->BindToCurrentThread();
905 layer_tree_host_impl_
->SetOffscreenContextProvider(
906 offscreen_context_provider
);
908 if (layer_tree_host_
->contents_texture_manager()) {
909 if (layer_tree_host_
->contents_texture_manager()->
910 LinkedEvictedBackingsExist()) {
911 // Clear any uploads we were making to textures linked to evicted
913 queue
->ClearUploadsToEvictedResources();
914 // Some textures in the layer tree are invalid. Kick off another commit
915 // to fill them again.
916 SetNeedsCommitOnImplThread();
919 layer_tree_host_
->contents_texture_manager()->
920 PushTexturePrioritiesToBackings();
923 commit_completion_event_on_impl_thread_
= completion
;
924 current_resource_update_controller_on_impl_thread_
=
925 ResourceUpdateController::Create(
927 Proxy::ImplThreadTaskRunner(),
929 layer_tree_host_impl_
->resource_provider());
930 current_resource_update_controller_on_impl_thread_
->PerformMoreUpdates(
931 scheduler_on_impl_thread_
->AnticipatedDrawTime());
934 void ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread(bool did_handle
) {
935 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread");
936 DCHECK(IsImplThread());
937 DCHECK(scheduler_on_impl_thread_
);
938 DCHECK(scheduler_on_impl_thread_
->CommitPending());
939 DCHECK(!layer_tree_host_impl_
->pending_tree());
941 // If the begin frame data was handled, then scroll and scale set was applied
942 // by the main thread, so the active tree needs to be updated as if these sent
943 // values were applied and committed.
945 layer_tree_host_impl_
->active_tree()
946 ->ApplySentScrollAndScaleDeltasFromAbortedCommit();
947 layer_tree_host_impl_
->active_tree()->ResetContentsTexturesPurged();
948 SetInputThrottledUntilCommitOnImplThread(false);
950 scheduler_on_impl_thread_
->BeginFrameAbortedByMainThread(did_handle
);
953 void ThreadProxy::ScheduledActionCommit() {
954 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
955 DCHECK(IsImplThread());
956 DCHECK(commit_completion_event_on_impl_thread_
);
957 DCHECK(current_resource_update_controller_on_impl_thread_
);
959 // Complete all remaining texture updates.
960 current_resource_update_controller_on_impl_thread_
->Finalize();
961 current_resource_update_controller_on_impl_thread_
.reset();
963 inside_commit_
= true;
964 layer_tree_host_impl_
->BeginCommit();
965 layer_tree_host_
->BeginCommitOnImplThread(layer_tree_host_impl_
.get());
966 layer_tree_host_
->FinishCommitOnImplThread(layer_tree_host_impl_
.get());
967 layer_tree_host_impl_
->CommitComplete();
968 inside_commit_
= false;
970 SetInputThrottledUntilCommitOnImplThread(false);
972 UpdateBackgroundAnimateTicking();
974 next_frame_is_newly_committed_frame_on_impl_thread_
= true;
976 if (layer_tree_host_
->settings().impl_side_painting
&&
977 commit_waits_for_activation_
) {
978 // For some layer types in impl-side painting, the commit is held until
979 // the pending tree is activated. It's also possible that the
980 // pending tree has already activated if there was no work to be done.
981 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD
);
982 completion_event_for_commit_held_on_tree_activation_
=
983 commit_completion_event_on_impl_thread_
;
984 commit_completion_event_on_impl_thread_
= NULL
;
986 commit_completion_event_on_impl_thread_
->Signal();
987 commit_completion_event_on_impl_thread_
= NULL
;
990 commit_waits_for_activation_
= false;
992 commit_complete_time_
= base::TimeTicks::HighResNow();
993 begin_frame_to_commit_duration_history_
.InsertSample(
994 commit_complete_time_
- begin_frame_sent_to_main_thread_time_
);
996 // SetVisible kicks off the next scheduler action, so this must be last.
997 scheduler_on_impl_thread_
->SetVisible(layer_tree_host_impl_
->visible());
1000 void ThreadProxy::ScheduledActionUpdateVisibleTiles() {
1001 DCHECK(IsImplThread());
1002 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles");
1003 layer_tree_host_impl_
->UpdateVisibleTiles();
1006 void ThreadProxy::ScheduledActionActivatePendingTree() {
1007 DCHECK(IsImplThread());
1008 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTree");
1009 layer_tree_host_impl_
->ActivatePendingTree();
1012 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
1013 DCHECK(IsImplThread());
1014 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
1015 Proxy::MainThreadTaskRunner()->PostTask(
1017 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface
,
1018 main_thread_weak_ptr_
));
1021 DrawSwapReadbackResult
ThreadProxy::DrawSwapReadbackInternal(
1023 bool swap_requested
,
1024 bool readback_requested
) {
1025 DrawSwapReadbackResult result
;
1026 result
.did_draw
= false;
1027 result
.did_swap
= false;
1028 result
.did_readback
= false;
1029 DCHECK(IsImplThread());
1030 DCHECK(layer_tree_host_impl_
.get());
1031 if (!layer_tree_host_impl_
)
1034 DCHECK(layer_tree_host_impl_
->renderer());
1035 if (!layer_tree_host_impl_
->renderer())
1038 base::TimeTicks monotonic_time
=
1039 layer_tree_host_impl_
->CurrentFrameTimeTicks();
1040 base::Time wall_clock_time
= layer_tree_host_impl_
->CurrentFrameTime();
1042 // TODO(enne): This should probably happen post-animate.
1043 if (layer_tree_host_impl_
->pending_tree())
1044 layer_tree_host_impl_
->pending_tree()->UpdateDrawProperties();
1045 layer_tree_host_impl_
->Animate(monotonic_time
, wall_clock_time
);
1046 UpdateBackgroundAnimateTicking();
1048 base::TimeTicks start_time
= base::TimeTicks::HighResNow();
1049 base::TimeDelta draw_duration_estimate
= DrawDurationEstimate();
1050 base::AutoReset
<bool> mark_inside(&inside_draw_
, true);
1052 // This method is called on a forced draw, regardless of whether we are able
1053 // to produce a frame, as the calling site on main thread is blocked until its
1054 // request completes, and we signal completion here. If CanDraw() is false, we
1055 // will indicate success=false to the caller, but we must still signal
1056 // completion to avoid deadlock.
1058 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
1059 // frame, so can only be used when such a frame is possible. Since
1060 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
1061 // CanDraw() as well.
1063 // readback_request_on_impl_thread_ may be for the pending tree, do
1064 // not perform the readback unless explicitly requested.
1065 bool drawing_for_readback
=
1066 readback_requested
&& !!readback_request_on_impl_thread_
;
1067 bool can_do_readback
= layer_tree_host_impl_
->renderer()->CanReadPixels();
1069 LayerTreeHostImpl::FrameData frame
;
1070 bool draw_frame
= false;
1071 bool start_ready_animations
= true;
1073 if (layer_tree_host_impl_
->CanDraw() &&
1074 (!drawing_for_readback
|| can_do_readback
)) {
1075 // If it is for a readback, make sure we draw the portion being read back.
1076 gfx::Rect readback_rect
;
1077 if (drawing_for_readback
)
1078 readback_rect
= readback_request_on_impl_thread_
->rect
;
1080 // Do not start animations if we skip drawing the frame to avoid
1082 if (layer_tree_host_impl_
->PrepareToDraw(&frame
, readback_rect
) ||
1086 start_ready_animations
= false;
1090 layer_tree_host_impl_
->DrawLayers(
1092 scheduler_on_impl_thread_
->LastBeginFrameOnImplThreadTime());
1093 result
.did_draw
= true;
1095 layer_tree_host_impl_
->DidDrawAllLayers(frame
);
1096 layer_tree_host_impl_
->UpdateAnimationState(start_ready_animations
);
1098 // Check for a pending CompositeAndReadback.
1099 if (drawing_for_readback
) {
1100 DCHECK(!swap_requested
);
1101 result
.did_readback
= false;
1102 if (draw_frame
&& !layer_tree_host_impl_
->IsContextLost()) {
1103 layer_tree_host_impl_
->Readback(readback_request_on_impl_thread_
->pixels
,
1104 readback_request_on_impl_thread_
->rect
);
1105 result
.did_readback
= true;
1107 readback_request_on_impl_thread_
->success
= result
.did_readback
;
1108 readback_request_on_impl_thread_
->completion
.Signal();
1109 readback_request_on_impl_thread_
= NULL
;
1110 } else if (draw_frame
) {
1111 DCHECK(swap_requested
);
1112 result
.did_swap
= layer_tree_host_impl_
->SwapBuffers(frame
);
1114 // We don't know if we have incomplete tiles if we didn't actually swap.
1115 if (result
.did_swap
) {
1116 DCHECK(!frame
.has_no_damage
);
1117 SetSwapUsedIncompleteTileOnImplThread(frame
.contains_incomplete_tile
);
1121 // Tell the main thread that the the newly-commited frame was drawn.
1122 if (next_frame_is_newly_committed_frame_on_impl_thread_
) {
1123 next_frame_is_newly_committed_frame_on_impl_thread_
= false;
1124 Proxy::MainThreadTaskRunner()->PostTask(
1126 base::Bind(&ThreadProxy::DidCommitAndDrawFrame
, main_thread_weak_ptr_
));
1130 CheckOutputSurfaceStatusOnImplThread();
1132 base::TimeDelta draw_duration
= base::TimeTicks::HighResNow() - start_time
;
1133 draw_duration_history_
.InsertSample(draw_duration
);
1134 base::TimeDelta draw_duration_overestimate
;
1135 base::TimeDelta draw_duration_underestimate
;
1136 if (draw_duration
> draw_duration_estimate
)
1137 draw_duration_underestimate
= draw_duration
- draw_duration_estimate
;
1139 draw_duration_overestimate
= draw_duration_estimate
- draw_duration
;
1140 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration",
1142 base::TimeDelta::FromMilliseconds(1),
1143 base::TimeDelta::FromMilliseconds(100),
1145 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate",
1146 draw_duration_underestimate
,
1147 base::TimeDelta::FromMilliseconds(1),
1148 base::TimeDelta::FromMilliseconds(100),
1150 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate",
1151 draw_duration_overestimate
,
1152 base::TimeDelta::FromMilliseconds(1),
1153 base::TimeDelta::FromMilliseconds(100),
1160 void ThreadProxy::AcquireLayerTextures() {
1161 // Called when the main thread needs to modify a layer texture that is used
1162 // directly by the compositor.
1163 // This method will block until the next compositor draw if there is a
1164 // previously committed frame that is still undrawn. This is necessary to
1165 // ensure that the main thread does not monopolize access to the textures.
1166 DCHECK(IsMainThread());
1168 if (textures_acquired_
)
1171 TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures");
1172 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1173 CompletionEvent completion
;
1174 Proxy::ImplThreadTaskRunner()->PostTask(
1176 base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread
,
1177 impl_thread_weak_ptr_
,
1179 // Block until it is safe to write to layer textures from the main thread.
1182 textures_acquired_
= true;
1183 can_cancel_commit_
= false;
1186 void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread(
1187 CompletionEvent
* completion
) {
1188 DCHECK(IsImplThread());
1189 DCHECK(!texture_acquisition_completion_event_on_impl_thread_
);
1191 texture_acquisition_completion_event_on_impl_thread_
= completion
;
1192 scheduler_on_impl_thread_
->SetMainThreadNeedsLayerTextures();
1195 void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() {
1196 DCHECK(texture_acquisition_completion_event_on_impl_thread_
);
1197 texture_acquisition_completion_event_on_impl_thread_
->Signal();
1198 texture_acquisition_completion_event_on_impl_thread_
= NULL
;
1201 void ThreadProxy::ScheduledActionManageTiles() {
1202 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionManageTiles");
1203 DCHECK(layer_tree_host_impl_
->settings().impl_side_painting
);
1204 layer_tree_host_impl_
->ManageTiles();
1207 DrawSwapReadbackResult
ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1208 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
1209 bool forced_draw
= false;
1210 bool swap_requested
= true;
1211 bool readback_requested
= false;
1212 return DrawSwapReadbackInternal(
1213 forced_draw
, swap_requested
, readback_requested
);
1216 DrawSwapReadbackResult
ThreadProxy::ScheduledActionDrawAndSwapForced() {
1217 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
1218 bool forced_draw
= true;
1219 bool swap_requested
= true;
1220 bool readback_requested
= false;
1221 return DrawSwapReadbackInternal(
1222 forced_draw
, swap_requested
, readback_requested
);
1225 DrawSwapReadbackResult
ThreadProxy::ScheduledActionDrawAndReadback() {
1226 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndReadback");
1227 bool forced_draw
= true;
1228 bool swap_requested
= false;
1229 bool readback_requested
= true;
1230 return DrawSwapReadbackInternal(
1231 forced_draw
, swap_requested
, readback_requested
);
1234 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time
) {
1235 if (current_resource_update_controller_on_impl_thread_
)
1236 current_resource_update_controller_on_impl_thread_
1237 ->PerformMoreUpdates(time
);
1238 layer_tree_host_impl_
->ResetCurrentFrameTimeForNextFrame();
1241 base::TimeDelta
ThreadProxy::DrawDurationEstimate() {
1242 base::TimeDelta historical_estimate
=
1243 draw_duration_history_
.Percentile(kDrawDurationEstimationPercentile
);
1244 base::TimeDelta padding
= base::TimeDelta::FromMicroseconds(
1245 kDrawDurationEstimatePaddingInMicroseconds
);
1246 return historical_estimate
+ padding
;
1249 base::TimeDelta
ThreadProxy::BeginFrameToCommitDurationEstimate() {
1250 return begin_frame_to_commit_duration_history_
.Percentile(
1251 kCommitAndActivationDurationEstimationPercentile
);
1254 base::TimeDelta
ThreadProxy::CommitToActivateDurationEstimate() {
1255 return commit_to_activate_duration_history_
.Percentile(
1256 kCommitAndActivationDurationEstimationPercentile
);
1259 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1260 DCHECK(IsImplThread());
1261 scheduler_on_impl_thread_
->FinishCommit();
1264 void ThreadProxy::DidCommitAndDrawFrame() {
1265 DCHECK(IsMainThread());
1266 if (!layer_tree_host_
)
1268 layer_tree_host_
->DidCommitAndDrawFrame();
1271 void ThreadProxy::DidCompleteSwapBuffers() {
1272 DCHECK(IsMainThread());
1273 if (!layer_tree_host_
)
1275 layer_tree_host_
->DidCompleteSwapBuffers();
1278 void ThreadProxy::SetAnimationEvents(scoped_ptr
<AnimationEventsVector
> events
,
1279 base::Time wall_clock_time
) {
1280 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1281 DCHECK(IsMainThread());
1282 if (!layer_tree_host_
)
1284 layer_tree_host_
->SetAnimationEvents(events
.Pass(), wall_clock_time
);
1287 void ThreadProxy::CreateAndInitializeOutputSurface() {
1288 TRACE_EVENT0("cc", "ThreadProxy::CreateAndInitializeOutputSurface");
1289 DCHECK(IsMainThread());
1291 // Check that output surface has not been recreated by CompositeAndReadback
1292 // after this task is posted but before it is run.
1293 bool has_initialized_output_surface_on_impl_thread
= true;
1295 CompletionEvent completion
;
1296 Proxy::ImplThreadTaskRunner()->PostTask(
1298 base::Bind(&ThreadProxy::HasInitializedOutputSurfaceOnImplThread
,
1299 impl_thread_weak_ptr_
,
1301 &has_initialized_output_surface_on_impl_thread
));
1304 if (has_initialized_output_surface_on_impl_thread
)
1307 layer_tree_host_
->DidLoseOutputSurface();
1308 output_surface_creation_callback_
.Reset(base::Bind(
1309 &ThreadProxy::DoCreateAndInitializeOutputSurface
,
1310 base::Unretained(this)));
1311 output_surface_creation_callback_
.callback().Run();
1314 void ThreadProxy::HasInitializedOutputSurfaceOnImplThread(
1315 CompletionEvent
* completion
,
1316 bool* has_initialized_output_surface
) {
1317 DCHECK(IsImplThread());
1318 *has_initialized_output_surface
=
1319 scheduler_on_impl_thread_
->HasInitializedOutputSurface();
1320 completion
->Signal();
1323 void ThreadProxy::InitializeImplOnImplThread(CompletionEvent
* completion
) {
1324 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1325 DCHECK(IsImplThread());
1326 layer_tree_host_impl_
= layer_tree_host_
->CreateLayerTreeHostImpl(this);
1327 const LayerTreeSettings
& settings
= layer_tree_host_
->settings();
1328 SchedulerSettings scheduler_settings
;
1329 scheduler_settings
.impl_side_painting
= settings
.impl_side_painting
;
1330 scheduler_settings
.timeout_and_draw_when_animation_checkerboards
=
1331 settings
.timeout_and_draw_when_animation_checkerboards
;
1332 scheduler_settings
.maximum_number_of_failed_draws_before_draw_is_forced_
=
1333 settings
.maximum_number_of_failed_draws_before_draw_is_forced_
;
1334 scheduler_settings
.using_synchronous_renderer_compositor
=
1335 settings
.using_synchronous_renderer_compositor
;
1336 scheduler_settings
.throttle_frame_production
=
1337 settings
.throttle_frame_production
;
1338 scheduler_on_impl_thread_
= Scheduler::Create(this, scheduler_settings
);
1339 scheduler_on_impl_thread_
->SetVisible(layer_tree_host_impl_
->visible());
1341 impl_thread_weak_ptr_
= weak_factory_on_impl_thread_
.GetWeakPtr();
1342 completion
->Signal();
1345 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1346 CompletionEvent
* completion
,
1347 scoped_ptr
<OutputSurface
> output_surface
,
1348 scoped_refptr
<ContextProvider
> offscreen_context_provider
,
1350 RendererCapabilities
* capabilities
) {
1351 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1352 DCHECK(IsImplThread());
1353 DCHECK(IsMainThreadBlocked());
1355 DCHECK(capabilities
);
1357 layer_tree_host_
->DeleteContentsTexturesOnImplThread(
1358 layer_tree_host_impl_
->resource_provider());
1360 *success
= layer_tree_host_impl_
->InitializeRenderer(output_surface
.Pass());
1363 *capabilities
= layer_tree_host_impl_
->GetRendererCapabilities();
1364 scheduler_on_impl_thread_
->DidCreateAndInitializeOutputSurface();
1365 } else if (offscreen_context_provider
.get()) {
1366 if (offscreen_context_provider
->BindToCurrentThread())
1367 offscreen_context_provider
->VerifyContexts();
1368 offscreen_context_provider
= NULL
;
1371 layer_tree_host_impl_
->SetOffscreenContextProvider(
1372 offscreen_context_provider
);
1374 completion
->Signal();
1377 void ThreadProxy::FinishGLOnImplThread(CompletionEvent
* completion
) {
1378 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
1379 DCHECK(IsImplThread());
1380 if (layer_tree_host_impl_
->resource_provider())
1381 layer_tree_host_impl_
->resource_provider()->Finish();
1382 completion
->Signal();
1385 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent
* completion
) {
1386 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1387 DCHECK(IsImplThread());
1388 layer_tree_host_
->DeleteContentsTexturesOnImplThread(
1389 layer_tree_host_impl_
->resource_provider());
1390 layer_tree_host_impl_
->SetNeedsBeginFrame(false);
1391 scheduler_on_impl_thread_
.reset();
1392 layer_tree_host_impl_
.reset();
1393 weak_factory_on_impl_thread_
.InvalidateWeakPtrs();
1394 completion
->Signal();
1397 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1398 return ResourceUpdateController::MaxPartialTextureUpdates();
1401 ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
1402 : memory_allocation_limit_bytes(0), evicted_ui_resources(false) {}
1404 ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {}
1406 scoped_ptr
<base::Value
> ThreadProxy::AsValue() const {
1407 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1409 CompletionEvent completion
;
1411 DebugScopedSetMainThreadBlocked
main_thread_blocked(
1412 const_cast<ThreadProxy
*>(this));
1413 Proxy::ImplThreadTaskRunner()->PostTask(
1415 base::Bind(&ThreadProxy::AsValueOnImplThread
,
1416 impl_thread_weak_ptr_
,
1421 return state
.PassAs
<base::Value
>();
1424 void ThreadProxy::AsValueOnImplThread(CompletionEvent
* completion
,
1425 base::DictionaryValue
* state
) const {
1426 state
->Set("layer_tree_host_impl",
1427 layer_tree_host_impl_
->AsValue().release());
1428 completion
->Signal();
1431 bool ThreadProxy::CommitPendingForTesting() {
1432 DCHECK(IsMainThread());
1433 CommitPendingRequest commit_pending_request
;
1435 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1436 Proxy::ImplThreadTaskRunner()->PostTask(
1438 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting
,
1439 impl_thread_weak_ptr_
,
1440 &commit_pending_request
));
1441 commit_pending_request
.completion
.Wait();
1443 return commit_pending_request
.commit_pending
;
1446 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1447 CommitPendingRequest
* request
) {
1448 DCHECK(IsImplThread());
1449 if (layer_tree_host_impl_
->output_surface())
1450 request
->commit_pending
= scheduler_on_impl_thread_
->CommitPending();
1452 request
->commit_pending
= false;
1453 request
->completion
.Signal();
1456 scoped_ptr
<base::Value
> ThreadProxy::SchedulerStateAsValueForTesting() {
1458 return scheduler_on_impl_thread_
->StateAsValue().Pass();
1460 SchedulerStateRequest scheduler_state_request
;
1462 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1463 Proxy::ImplThreadTaskRunner()->PostTask(
1465 base::Bind(&ThreadProxy::SchedulerStateAsValueOnImplThreadForTesting
,
1466 impl_thread_weak_ptr_
,
1467 &scheduler_state_request
));
1468 scheduler_state_request
.completion
.Wait();
1470 return scheduler_state_request
.state
.Pass();
1473 void ThreadProxy::SchedulerStateAsValueOnImplThreadForTesting(
1474 SchedulerStateRequest
* request
) {
1475 DCHECK(IsImplThread());
1476 request
->state
= scheduler_on_impl_thread_
->StateAsValue();
1477 request
->completion
.Signal();
1480 void ThreadProxy::RenewTreePriority() {
1481 DCHECK(IsImplThread());
1482 bool smoothness_takes_priority
=
1483 layer_tree_host_impl_
->pinch_gesture_active() ||
1484 layer_tree_host_impl_
->CurrentlyScrollingLayer() ||
1485 layer_tree_host_impl_
->page_scale_animation_active();
1487 base::TimeTicks now
= layer_tree_host_impl_
->CurrentPhysicalTimeTicks();
1489 // Update expiration time if smoothness currently takes priority.
1490 if (smoothness_takes_priority
) {
1491 smoothness_takes_priority_expiration_time_
=
1492 now
+ base::TimeDelta::FromMilliseconds(
1493 kSmoothnessTakesPriorityExpirationDelay
* 1000);
1496 // We use the same priority for both trees by default.
1497 TreePriority priority
= SAME_PRIORITY_FOR_BOTH_TREES
;
1499 // Smoothness takes priority if expiration time is in the future.
1500 if (smoothness_takes_priority_expiration_time_
> now
)
1501 priority
= SMOOTHNESS_TAKES_PRIORITY
;
1503 // New content always takes priority when the active tree has
1504 // evicted resources or there is an invalid viewport size.
1505 if (layer_tree_host_impl_
->active_tree()->ContentsTexturesPurged() ||
1506 layer_tree_host_impl_
->active_tree()->ViewportSizeInvalid() ||
1507 layer_tree_host_impl_
->EvictedUIResourcesExist() ||
1508 input_throttled_until_commit_
)
1509 priority
= NEW_CONTENT_TAKES_PRIORITY
;
1511 layer_tree_host_impl_
->SetTreePriority(priority
);
1513 // Notify the the client of this compositor via the output surface.
1514 // TODO(epenner): Route this to compositor-thread instead of output-surface
1515 // after GTFO refactor of compositor-thread (http://crbug/170828).
1516 if (layer_tree_host_impl_
->output_surface()) {
1517 layer_tree_host_impl_
->output_surface()->
1518 UpdateSmoothnessTakesPriority(priority
== SMOOTHNESS_TAKES_PRIORITY
);
1521 base::TimeDelta delay
= smoothness_takes_priority_expiration_time_
- now
;
1523 // Need to make sure a delayed task is posted when we have smoothness
1524 // takes priority expiration time in the future.
1525 if (delay
<= base::TimeDelta())
1527 if (renew_tree_priority_on_impl_thread_pending_
)
1530 Proxy::ImplThreadTaskRunner()->PostDelayedTask(
1532 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread
,
1533 weak_factory_on_impl_thread_
.GetWeakPtr()),
1536 renew_tree_priority_on_impl_thread_pending_
= true;
1539 void ThreadProxy::RenewTreePriorityOnImplThread() {
1540 DCHECK(renew_tree_priority_on_impl_thread_pending_
);
1541 renew_tree_priority_on_impl_thread_pending_
= false;
1543 RenewTreePriority();
1546 void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay
) {
1547 Proxy::ImplThreadTaskRunner()->PostDelayedTask(
1549 base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread
,
1550 impl_thread_weak_ptr_
),
1554 void ThreadProxy::StartScrollbarAnimationOnImplThread() {
1555 layer_tree_host_impl_
->StartScrollbarAnimation();
1558 void ThreadProxy::DidActivatePendingTree() {
1559 DCHECK(IsImplThread());
1560 TRACE_EVENT0("cc", "ThreadProxy::DidActivatePendingTreeOnImplThread");
1562 if (completion_event_for_commit_held_on_tree_activation_
&&
1563 !layer_tree_host_impl_
->pending_tree()) {
1564 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
1565 TRACE_EVENT_SCOPE_THREAD
);
1566 DCHECK(layer_tree_host_impl_
->settings().impl_side_painting
);
1567 completion_event_for_commit_held_on_tree_activation_
->Signal();
1568 completion_event_for_commit_held_on_tree_activation_
= NULL
;
1571 UpdateBackgroundAnimateTicking();
1573 commit_to_activate_duration_history_
.InsertSample(
1574 base::TimeTicks::HighResNow() - commit_complete_time_
);