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"
7 #include "base/auto_reset.h"
9 #include "base/debug/trace_event.h"
10 #include "cc/base/thread.h"
11 #include "cc/input/input_handler.h"
12 #include "cc/output/context_provider.h"
13 #include "cc/output/output_surface.h"
14 #include "cc/quads/draw_quad.h"
15 #include "cc/resources/prioritized_resource_manager.h"
16 #include "cc/scheduler/delay_based_time_source.h"
17 #include "cc/scheduler/frame_rate_controller.h"
18 #include "cc/scheduler/scheduler.h"
19 #include "cc/scheduler/vsync_time_source.h"
20 #include "cc/trees/layer_tree_host.h"
21 #include "cc/trees/layer_tree_impl.h"
25 // Measured in seconds.
26 const double kContextRecreationTickRate
= 0.03;
28 // Measured in seconds.
29 const double kSmoothnessTakesPriorityExpirationDelay
= 0.25;
35 scoped_ptr
<Proxy
> ThreadProxy::Create(LayerTreeHost
* layer_tree_host
,
36 scoped_ptr
<Thread
> impl_thread
) {
37 return make_scoped_ptr(
38 new ThreadProxy(layer_tree_host
, impl_thread
.Pass())).PassAs
<Proxy
>();
41 ThreadProxy::ThreadProxy(LayerTreeHost
* layer_tree_host
,
42 scoped_ptr
<Thread
> impl_thread
)
43 : Proxy(impl_thread
.Pass()),
44 animate_requested_(false),
45 commit_requested_(false),
46 commit_request_sent_to_impl_thread_(false),
47 created_offscreen_context_provider_(false),
48 layer_tree_host_(layer_tree_host
),
50 textures_acquired_(true),
51 in_composite_and_readback_(false),
52 manage_tiles_pending_(false),
53 weak_factory_on_impl_thread_(this),
55 begin_frame_completion_event_on_impl_thread_(NULL
),
56 readback_request_on_impl_thread_(NULL
),
57 commit_completion_event_on_impl_thread_(NULL
),
58 completion_event_for_commit_held_on_tree_activation_(NULL
),
59 texture_acquisition_completion_event_on_impl_thread_(NULL
),
60 next_frame_is_newly_committed_frame_on_impl_thread_(false),
61 render_vsync_enabled_(layer_tree_host
->settings().render_vsync_enabled
),
62 render_vsync_notification_enabled_(
63 layer_tree_host
->settings().render_vsync_notification_enabled
),
66 defer_commits_(false),
67 renew_tree_priority_on_impl_thread_pending_(false) {
68 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
69 DCHECK(IsMainThread());
70 DCHECK(layer_tree_host_
);
73 ThreadProxy::~ThreadProxy() {
74 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
75 DCHECK(IsMainThread());
79 bool ThreadProxy::CompositeAndReadback(void* pixels
, gfx::Rect rect
) {
80 TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
81 DCHECK(IsMainThread());
82 DCHECK(layer_tree_host_
);
83 DCHECK(!defer_commits_
);
85 if (!layer_tree_host_
->InitializeOutputSurfaceIfNeeded()) {
86 TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized");
90 // Perform a synchronous commit.
92 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
93 CompletionEvent begin_frame_completion
;
94 Proxy::ImplThread()->PostTask(
95 base::Bind(&ThreadProxy::ForceBeginFrameOnImplThread
,
96 impl_thread_weak_ptr_
,
97 &begin_frame_completion
));
98 begin_frame_completion
.Wait();
100 in_composite_and_readback_
= true;
101 BeginFrame(scoped_ptr
<BeginFrameAndCommitState
>());
102 in_composite_and_readback_
= false;
104 // Perform a synchronous readback.
105 ReadbackRequest request
;
107 request
.pixels
= pixels
;
109 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
110 Proxy::ImplThread()->PostTask(
111 base::Bind(&ThreadProxy::RequestReadbackOnImplThread
,
112 impl_thread_weak_ptr_
,
114 request
.completion
.Wait();
116 return request
.success
;
119 void ThreadProxy::RequestReadbackOnImplThread(ReadbackRequest
* request
) {
120 DCHECK(Proxy::IsImplThread());
121 DCHECK(!readback_request_on_impl_thread_
);
122 if (!layer_tree_host_impl_
) {
123 request
->success
= false;
124 request
->completion
.Signal();
128 readback_request_on_impl_thread_
= request
;
129 scheduler_on_impl_thread_
->SetNeedsRedraw();
130 scheduler_on_impl_thread_
->SetNeedsForcedRedraw();
133 void ThreadProxy::FinishAllRendering() {
134 DCHECK(Proxy::IsMainThread());
135 DCHECK(!defer_commits_
);
137 // Make sure all GL drawing is finished on the impl thread.
138 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
139 CompletionEvent completion
;
140 Proxy::ImplThread()->PostTask(
141 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread
,
142 impl_thread_weak_ptr_
,
147 bool ThreadProxy::IsStarted() const {
148 DCHECK(Proxy::IsMainThread());
152 void ThreadProxy::SetSurfaceReady() {
153 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReady");
154 Proxy::ImplThread()->PostTask(base::Bind(
155 &ThreadProxy::SetSurfaceReadyOnImplThread
, impl_thread_weak_ptr_
));
158 void ThreadProxy::SetSurfaceReadyOnImplThread() {
159 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReadyOnImplThread");
160 scheduler_on_impl_thread_
->SetCanStart();
163 void ThreadProxy::SetVisible(bool visible
) {
164 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
165 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
166 CompletionEvent completion
;
167 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::SetVisibleOnImplThread
,
168 impl_thread_weak_ptr_
,
174 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent
* completion
,
176 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
177 layer_tree_host_impl_
->SetVisible(visible
);
178 scheduler_on_impl_thread_
->SetVisible(visible
);
179 completion
->Signal();
182 void ThreadProxy::DoCreateAndInitializeOutputSurface() {
183 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface");
184 DCHECK(IsMainThread());
186 scoped_ptr
<OutputSurface
> output_surface
= first_output_surface_
.Pass();
188 output_surface
= layer_tree_host_
->CreateOutputSurface();
190 RendererCapabilities capabilities
;
191 bool success
= !!output_surface
;
193 OnOutputSurfaceInitializeAttempted(false, capabilities
);
197 scoped_refptr
<ContextProvider
> offscreen_context_provider
;
198 if (created_offscreen_context_provider_
) {
199 offscreen_context_provider
= layer_tree_host_
->client()->
200 OffscreenContextProviderForCompositorThread();
201 success
= !!offscreen_context_provider
;
203 OnOutputSurfaceInitializeAttempted(false, capabilities
);
210 // Make a blocking call to InitializeOutputSurfaceOnImplThread. The results
211 // of that call are pushed into the success and capabilities local
213 CompletionEvent completion
;
214 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
216 Proxy::ImplThread()->PostTask(
217 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread
,
218 impl_thread_weak_ptr_
,
220 base::Passed(&output_surface
),
221 offscreen_context_provider
,
227 OnOutputSurfaceInitializeAttempted(success
, capabilities
);
230 void ThreadProxy::OnOutputSurfaceInitializeAttempted(
232 const RendererCapabilities
& capabilities
) {
233 DCHECK(IsMainThread());
234 DCHECK(layer_tree_host_
);
237 renderer_capabilities_main_thread_copy_
= capabilities
;
240 LayerTreeHost::CreateResult result
=
241 layer_tree_host_
->OnCreateAndInitializeOutputSurfaceAttempted(success
);
242 if (result
== LayerTreeHost::CreateFailedButTryAgain
) {
243 if (!output_surface_creation_callback_
.callback().is_null()) {
244 Proxy::MainThread()->PostTask(
245 output_surface_creation_callback_
.callback());
248 output_surface_creation_callback_
.Cancel();
252 const RendererCapabilities
& ThreadProxy::GetRendererCapabilities() const {
253 DCHECK(IsMainThread());
254 DCHECK(!layer_tree_host_
->output_surface_lost());
255 return renderer_capabilities_main_thread_copy_
;
258 void ThreadProxy::SetNeedsAnimate() {
259 DCHECK(IsMainThread());
260 if (animate_requested_
)
263 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
264 animate_requested_
= true;
266 if (commit_request_sent_to_impl_thread_
)
268 commit_request_sent_to_impl_thread_
= true;
269 Proxy::ImplThread()->PostTask(base::Bind(
270 &ThreadProxy::SetNeedsCommitOnImplThread
, impl_thread_weak_ptr_
));
273 void ThreadProxy::SetNeedsCommit() {
274 DCHECK(IsMainThread());
275 if (commit_requested_
)
277 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
278 commit_requested_
= true;
280 if (commit_request_sent_to_impl_thread_
)
282 commit_request_sent_to_impl_thread_
= true;
283 Proxy::ImplThread()->PostTask(base::Bind(
284 &ThreadProxy::SetNeedsCommitOnImplThread
, impl_thread_weak_ptr_
));
287 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
288 DCHECK(IsImplThread());
289 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
290 Proxy::ImplThread()->PostTask(
291 base::Bind(&ThreadProxy::CheckOutputSurfaceStatusOnImplThread
,
292 impl_thread_weak_ptr_
));
295 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
296 DCHECK(IsImplThread());
297 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
298 if (!layer_tree_host_impl_
->IsContextLost())
300 if (cc::ContextProvider
* offscreen_contexts
= layer_tree_host_impl_
->
301 resource_provider()->offscreen_context_provider())
302 offscreen_contexts
->VerifyContexts();
303 scheduler_on_impl_thread_
->DidLoseOutputSurface();
306 void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
307 DCHECK(IsImplThread());
308 TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
309 scheduler_on_impl_thread_
->DidSwapBuffersComplete();
310 Proxy::MainThread()->PostTask(
311 base::Bind(&ThreadProxy::DidCompleteSwapBuffers
, main_thread_weak_ptr_
));
314 void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase
,
315 base::TimeDelta interval
) {
316 DCHECK(IsImplThread());
318 "ThreadProxy::OnVSyncParametersChanged",
320 (timebase
- base::TimeTicks()).InMilliseconds(),
322 interval
.InMilliseconds());
323 scheduler_on_impl_thread_
->SetTimebaseAndInterval(timebase
, interval
);
326 void ThreadProxy::DidVSync(base::TimeTicks frame_time
) {
327 DCHECK(IsImplThread());
328 TRACE_EVENT0("cc", "ThreadProxy::DidVSync");
330 vsync_client_
->DidVSync(frame_time
);
333 void ThreadProxy::RequestVSyncNotification(VSyncClient
* client
) {
334 DCHECK(IsImplThread());
336 "cc", "ThreadProxy::RequestVSyncNotification", "enable", !!client
);
337 vsync_client_
= client
;
338 layer_tree_host_impl_
->EnableVSyncNotification(!!client
);
341 void ThreadProxy::OnCanDrawStateChanged(bool can_draw
) {
342 DCHECK(IsImplThread());
344 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw
);
345 scheduler_on_impl_thread_
->SetCanDraw(can_draw
);
346 layer_tree_host_impl_
->UpdateBackgroundAnimateTicking(
347 !scheduler_on_impl_thread_
->WillDrawIfNeeded());
350 void ThreadProxy::OnHasPendingTreeStateChanged(bool has_pending_tree
) {
351 DCHECK(IsImplThread());
353 "ThreadProxy::OnHasPendingTreeStateChanged",
356 scheduler_on_impl_thread_
->SetHasPendingTree(has_pending_tree
);
359 void ThreadProxy::SetNeedsCommitOnImplThread() {
360 DCHECK(IsImplThread());
361 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
362 scheduler_on_impl_thread_
->SetNeedsCommit();
365 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
366 if (manage_tiles_pending_
)
368 Proxy::ImplThread()->PostTask(
369 base::Bind(&ThreadProxy::ManageTilesOnImplThread
, impl_thread_weak_ptr_
));
370 manage_tiles_pending_
= true;
373 void ThreadProxy::ManageTilesOnImplThread() {
374 // TODO(nduca): If needed, move this into CCSchedulerStateMachine.
375 manage_tiles_pending_
= false;
376 if (layer_tree_host_impl_
)
377 layer_tree_host_impl_
->ManageTiles();
380 void ThreadProxy::SetNeedsForcedCommitOnImplThread() {
381 DCHECK(IsImplThread());
382 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsForcedCommitOnImplThread");
383 scheduler_on_impl_thread_
->SetNeedsForcedCommit();
386 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
387 scoped_ptr
<AnimationEventsVector
> events
,
388 base::Time wall_clock_time
) {
389 DCHECK(IsImplThread());
391 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
392 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::SetAnimationEvents
,
393 main_thread_weak_ptr_
,
394 base::Passed(&events
),
398 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes
,
399 int priority_cutoff
) {
400 DCHECK(IsImplThread());
402 if (!layer_tree_host_
->contents_texture_manager())
405 bool reduce_result
= layer_tree_host_
->contents_texture_manager()->
406 ReduceMemoryOnImplThread(limit_bytes
,
408 layer_tree_host_impl_
->resource_provider());
412 // The texture upload queue may reference textures that were just purged,
413 // clear them from the queue.
414 if (current_resource_update_controller_on_impl_thread_
) {
415 current_resource_update_controller_on_impl_thread_
->
416 DiscardUploadsToEvictedResources();
421 void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
422 DCHECK(IsImplThread());
424 if (!layer_tree_host_
->contents_texture_manager())
427 layer_tree_host_
->contents_texture_manager()->ReduceWastedMemoryOnImplThread(
428 layer_tree_host_impl_
->resource_provider());
431 void ThreadProxy::SendManagedMemoryStats() {
432 DCHECK(IsImplThread());
433 if (!layer_tree_host_impl_
)
435 if (!layer_tree_host_
->contents_texture_manager())
438 // If we are using impl-side painting, then SendManagedMemoryStats is called
439 // directly after the tile manager's manage function, and doesn't need to
440 // interact with main thread's layer tree.
441 if (layer_tree_host_
->settings().impl_side_painting
)
444 layer_tree_host_impl_
->SendManagedMemoryStats(
445 layer_tree_host_
->contents_texture_manager()->MemoryVisibleBytes(),
446 layer_tree_host_
->contents_texture_manager()->
447 MemoryVisibleAndNearbyBytes(),
448 layer_tree_host_
->contents_texture_manager()->MemoryUseBytes());
451 bool ThreadProxy::IsInsideDraw() { return inside_draw_
; }
453 void ThreadProxy::SetNeedsRedraw(gfx::Rect damage_rect
) {
454 DCHECK(IsMainThread());
455 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
456 Proxy::ImplThread()->PostTask(base::Bind(
457 &ThreadProxy::SetNeedsRedrawRectOnImplThread
,
458 impl_thread_weak_ptr_
, damage_rect
));
461 void ThreadProxy::SetDeferCommits(bool defer_commits
) {
462 DCHECK(IsMainThread());
463 DCHECK_NE(defer_commits_
, defer_commits
);
464 defer_commits_
= defer_commits
;
467 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
469 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
471 if (!defer_commits_
&& pending_deferred_commit_
)
472 Proxy::MainThread()->PostTask(
473 base::Bind(&ThreadProxy::BeginFrame
,
474 main_thread_weak_ptr_
,
475 base::Passed(&pending_deferred_commit_
)));
478 bool ThreadProxy::CommitRequested() const {
479 DCHECK(IsMainThread());
480 return commit_requested_
;
483 void ThreadProxy::SetNeedsRedrawOnImplThread() {
484 DCHECK(IsImplThread());
485 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
486 scheduler_on_impl_thread_
->SetNeedsRedraw();
489 void ThreadProxy::SetNeedsRedrawRectOnImplThread(gfx::Rect damage_rect
) {
490 DCHECK(IsImplThread());
491 layer_tree_host_impl_
->SetViewportDamage(damage_rect
);
492 SetNeedsRedrawOnImplThread();
495 void ThreadProxy::DidSwapUseIncompleteTileOnImplThread() {
496 DCHECK(IsImplThread());
497 TRACE_EVENT0("cc", "ThreadProxy::DidSwapUseIncompleteTileOnImplThread");
498 scheduler_on_impl_thread_
->DidSwapUseIncompleteTile();
501 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
502 DCHECK(IsImplThread());
503 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
504 scheduler_on_impl_thread_
->SetNeedsRedraw();
507 void ThreadProxy::MainThreadHasStoppedFlinging() {
508 DCHECK(IsMainThread());
509 Proxy::ImplThread()->PostTask(
510 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread
,
511 impl_thread_weak_ptr_
));
514 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
515 DCHECK(IsImplThread());
516 if (input_handler_client_on_impl_thread_
)
517 input_handler_client_on_impl_thread_
->MainThreadHasStoppedFlinging();
520 void ThreadProxy::Start(scoped_ptr
<OutputSurface
> first_output_surface
) {
521 DCHECK(IsMainThread());
522 DCHECK(Proxy::ImplThread());
523 DCHECK(first_output_surface
);
524 // Create LayerTreeHostImpl.
525 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
526 CompletionEvent completion
;
527 scoped_ptr
<InputHandlerClient
> input_handler_client
=
528 layer_tree_host_
->CreateInputHandlerClient();
529 Proxy::ImplThread()->PostTask(
530 base::Bind(&ThreadProxy::InitializeImplOnImplThread
,
531 base::Unretained(this),
533 input_handler_client
.release()));
536 main_thread_weak_ptr_
= weak_factory_
.GetWeakPtr();
537 first_output_surface_
= first_output_surface
.Pass();
542 void ThreadProxy::Stop() {
543 TRACE_EVENT0("cc", "ThreadProxy::Stop");
544 DCHECK(IsMainThread());
547 // Synchronously finishes pending GL operations and deletes the impl.
548 // The two steps are done as separate post tasks, so that tasks posted
549 // by the GL implementation due to the Finish can be executed by the
550 // renderer before shutting it down.
552 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
554 CompletionEvent completion
;
555 Proxy::ImplThread()->PostTask(
556 base::Bind(&ThreadProxy::FinishGLOnImplThread
,
557 impl_thread_weak_ptr_
,
562 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
564 CompletionEvent completion
;
565 Proxy::ImplThread()->PostTask(
566 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread
,
567 impl_thread_weak_ptr_
,
572 weak_factory_
.InvalidateWeakPtrs();
574 DCHECK(!layer_tree_host_impl_
.get()); // verify that the impl deleted.
575 layer_tree_host_
= NULL
;
579 void ThreadProxy::ForceSerializeOnSwapBuffers() {
580 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
581 CompletionEvent completion
;
582 Proxy::ImplThread()->PostTask(
583 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread
,
584 impl_thread_weak_ptr_
,
589 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
590 CompletionEvent
* completion
) {
591 if (layer_tree_host_impl_
->renderer())
592 layer_tree_host_impl_
->renderer()->DoNoOp();
593 completion
->Signal();
596 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent
* completion
) {
597 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
598 DCHECK(IsImplThread());
599 layer_tree_host_impl_
->FinishAllRendering();
600 completion
->Signal();
603 void ThreadProxy::ForceBeginFrameOnImplThread(CompletionEvent
* completion
) {
604 TRACE_EVENT0("cc", "ThreadProxy::ForceBeginFrameOnImplThread");
605 DCHECK(!begin_frame_completion_event_on_impl_thread_
);
607 SetNeedsForcedCommitOnImplThread();
608 if (scheduler_on_impl_thread_
->CommitPending()) {
609 completion
->Signal();
613 begin_frame_completion_event_on_impl_thread_
= completion
;
616 void ThreadProxy::ScheduledActionBeginFrame() {
617 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginFrame");
618 scoped_ptr
<BeginFrameAndCommitState
> begin_frame_state(
619 new BeginFrameAndCommitState
);
620 begin_frame_state
->monotonic_frame_begin_time
= base::TimeTicks::Now();
621 begin_frame_state
->scroll_info
= layer_tree_host_impl_
->ProcessScrollDeltas();
622 DCHECK_GT(layer_tree_host_impl_
->memory_allocation_limit_bytes(), 0u);
623 begin_frame_state
->memory_allocation_limit_bytes
=
624 layer_tree_host_impl_
->memory_allocation_limit_bytes();
625 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::BeginFrame
,
626 main_thread_weak_ptr_
,
627 base::Passed(&begin_frame_state
)));
629 if (begin_frame_completion_event_on_impl_thread_
) {
630 begin_frame_completion_event_on_impl_thread_
->Signal();
631 begin_frame_completion_event_on_impl_thread_
= NULL
;
635 void ThreadProxy::BeginFrame(
636 scoped_ptr
<BeginFrameAndCommitState
> begin_frame_state
) {
637 TRACE_EVENT0("cc", "ThreadProxy::BeginFrame");
638 DCHECK(IsMainThread());
639 if (!layer_tree_host_
)
642 if (defer_commits_
) {
643 pending_deferred_commit_
= begin_frame_state
.Pass();
644 layer_tree_host_
->DidDeferCommit();
645 TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
649 // Do not notify the impl thread of commit requests that occur during
650 // the apply/animate/layout part of the BeginFrameAndCommit process since
651 // those commit requests will get painted immediately. Once we have done
652 // the paint, commit_requested_ will be set to false to allow new commit
653 // requests to be scheduled.
654 commit_requested_
= true;
655 commit_request_sent_to_impl_thread_
= true;
657 // On the other hand, the AnimationRequested flag needs to be cleared
658 // here so that any animation requests generated by the apply or animate
659 // callbacks will trigger another frame.
660 animate_requested_
= false;
662 if (begin_frame_state
)
663 layer_tree_host_
->ApplyScrollAndScale(*begin_frame_state
->scroll_info
);
665 if (!in_composite_and_readback_
&& !layer_tree_host_
->visible()) {
666 commit_requested_
= false;
667 commit_request_sent_to_impl_thread_
= false;
669 TRACE_EVENT0("cc", "EarlyOut_NotVisible");
670 Proxy::ImplThread()->PostTask(base::Bind(
671 &ThreadProxy::BeginFrameAbortedOnImplThread
, impl_thread_weak_ptr_
));
675 layer_tree_host_
->WillBeginFrame();
677 if (begin_frame_state
) {
678 layer_tree_host_
->UpdateAnimations(
679 begin_frame_state
->monotonic_frame_begin_time
);
682 // Unlink any backings that the impl thread has evicted, so that we know to
683 // re-paint them in UpdateLayers.
684 if (layer_tree_host_
->contents_texture_manager()) {
685 layer_tree_host_
->contents_texture_manager()->
686 UnlinkAndClearEvictedBackings();
689 layer_tree_host_
->Layout();
691 // Clear the commit flag after updating animations and layout here --- objects
692 // that only layout when painted will trigger another SetNeedsCommit inside
694 commit_requested_
= false;
695 commit_request_sent_to_impl_thread_
= false;
697 scoped_ptr
<ResourceUpdateQueue
> queue
=
698 make_scoped_ptr(new ResourceUpdateQueue
);
699 layer_tree_host_
->UpdateLayers(
701 begin_frame_state
? begin_frame_state
->memory_allocation_limit_bytes
704 // Once single buffered layers are committed, they cannot be modified until
705 // they are drawn by the impl thread.
706 textures_acquired_
= false;
708 layer_tree_host_
->WillCommit();
709 // Before applying scrolls and calling animate, we set animate_requested_ to
710 // false. If it is true now, it means SetNeedAnimate was called again, but
711 // during a state when commit_request_sent_to_impl_thread_ = true. We need to
712 // force that call to happen again now so that the commit request is sent to
714 if (animate_requested_
) {
715 // Forces SetNeedsAnimate to consider posting a commit task.
716 animate_requested_
= false;
720 scoped_refptr
<cc::ContextProvider
> offscreen_context_provider
;
721 if (renderer_capabilities_main_thread_copy_
.using_offscreen_context3d
&&
722 layer_tree_host_
->needs_offscreen_context()) {
723 offscreen_context_provider
= layer_tree_host_
->client()->
724 OffscreenContextProviderForCompositorThread();
725 if (offscreen_context_provider
)
726 created_offscreen_context_provider_
= true;
729 // Notify the impl thread that the BeginFrame has completed. This will
730 // begin the commit process, which is blocking from the main thread's
731 // point of view, but asynchronously performed on the impl thread,
732 // coordinated by the Scheduler.
734 TRACE_EVENT0("cc", "commit");
736 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
738 RenderingStatsInstrumentation
* stats_instrumentation
=
739 layer_tree_host_
->rendering_stats_instrumentation();
740 base::TimeTicks start_time
= stats_instrumentation
->StartRecording();
742 CompletionEvent completion
;
743 Proxy::ImplThread()->PostTask(
744 base::Bind(&ThreadProxy::BeginFrameCompleteOnImplThread
,
745 impl_thread_weak_ptr_
,
748 offscreen_context_provider
));
751 base::TimeDelta duration
= stats_instrumentation
->EndRecording(start_time
);
752 stats_instrumentation
->AddCommit(duration
);
755 layer_tree_host_
->CommitComplete();
756 layer_tree_host_
->DidBeginFrame();
759 void ThreadProxy::BeginFrameCompleteOnImplThread(
760 CompletionEvent
* completion
,
761 ResourceUpdateQueue
* raw_queue
,
762 scoped_refptr
<cc::ContextProvider
> offscreen_context_provider
) {
763 scoped_ptr
<ResourceUpdateQueue
> queue(raw_queue
);
765 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameCompleteOnImplThread");
766 DCHECK(!commit_completion_event_on_impl_thread_
);
767 DCHECK(IsImplThread() && IsMainThreadBlocked());
768 DCHECK(scheduler_on_impl_thread_
);
769 DCHECK(scheduler_on_impl_thread_
->CommitPending());
771 if (!layer_tree_host_impl_
) {
772 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
773 completion
->Signal();
777 if (offscreen_context_provider
)
778 offscreen_context_provider
->BindToCurrentThread();
779 layer_tree_host_impl_
->resource_provider()->
780 set_offscreen_context_provider(offscreen_context_provider
);
782 if (layer_tree_host_
->contents_texture_manager()->
783 LinkedEvictedBackingsExist()) {
784 // Clear any uploads we were making to textures linked to evicted
786 queue
->ClearUploadsToEvictedResources();
787 // Some textures in the layer tree are invalid. Kick off another commit
788 // to fill them again.
789 SetNeedsCommitOnImplThread();
792 layer_tree_host_
->contents_texture_manager()->
793 PushTexturePrioritiesToBackings();
795 current_resource_update_controller_on_impl_thread_
=
796 ResourceUpdateController::Create(
800 layer_tree_host_impl_
->resource_provider());
801 current_resource_update_controller_on_impl_thread_
->PerformMoreUpdates(
802 scheduler_on_impl_thread_
->AnticipatedDrawTime());
804 commit_completion_event_on_impl_thread_
= completion
;
807 void ThreadProxy::BeginFrameAbortedOnImplThread() {
808 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedOnImplThread");
809 DCHECK(IsImplThread());
810 DCHECK(scheduler_on_impl_thread_
);
811 DCHECK(scheduler_on_impl_thread_
->CommitPending());
813 scheduler_on_impl_thread_
->BeginFrameAborted();
816 void ThreadProxy::ScheduledActionCommit() {
817 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
818 DCHECK(IsImplThread());
819 DCHECK(commit_completion_event_on_impl_thread_
);
820 DCHECK(current_resource_update_controller_on_impl_thread_
);
822 // Complete all remaining texture updates.
823 current_resource_update_controller_on_impl_thread_
->Finalize();
824 current_resource_update_controller_on_impl_thread_
.reset();
826 layer_tree_host_impl_
->BeginCommit();
827 layer_tree_host_
->BeginCommitOnImplThread(layer_tree_host_impl_
.get());
828 layer_tree_host_
->FinishCommitOnImplThread(layer_tree_host_impl_
.get());
829 layer_tree_host_impl_
->CommitComplete();
831 layer_tree_host_impl_
->UpdateBackgroundAnimateTicking(
832 !scheduler_on_impl_thread_
->WillDrawIfNeeded());
834 next_frame_is_newly_committed_frame_on_impl_thread_
= true;
836 if (layer_tree_host_
->settings().impl_side_painting
&&
837 layer_tree_host_
->BlocksPendingCommit()) {
838 // For some layer types in impl-side painting, the commit is held until
839 // the pending tree is activated.
840 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD
);
841 completion_event_for_commit_held_on_tree_activation_
=
842 commit_completion_event_on_impl_thread_
;
843 commit_completion_event_on_impl_thread_
= NULL
;
845 commit_completion_event_on_impl_thread_
->Signal();
846 commit_completion_event_on_impl_thread_
= NULL
;
849 // SetVisible kicks off the next scheduler action, so this must be last.
850 scheduler_on_impl_thread_
->SetVisible(layer_tree_host_impl_
->visible());
853 void ThreadProxy::ScheduledActionCheckForCompletedTileUploads() {
854 DCHECK(IsImplThread());
856 "ThreadProxy::ScheduledActionCheckForCompletedTileUploads");
857 layer_tree_host_impl_
->CheckForCompletedTileUploads();
860 void ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded() {
861 DCHECK(IsImplThread());
862 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded");
863 layer_tree_host_impl_
->ActivatePendingTreeIfNeeded();
866 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
867 DCHECK(IsImplThread());
868 Proxy::MainThread()->PostTask(
869 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface
,
870 main_thread_weak_ptr_
));
873 ScheduledActionDrawAndSwapResult
874 ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw
) {
875 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
877 base::AutoReset
<bool> mark_inside(&inside_draw_
, true);
879 ScheduledActionDrawAndSwapResult result
;
880 result
.did_draw
= false;
881 result
.did_swap
= false;
882 DCHECK(IsImplThread());
883 DCHECK(layer_tree_host_impl_
.get());
884 if (!layer_tree_host_impl_
)
887 DCHECK(layer_tree_host_impl_
->renderer());
888 if (!layer_tree_host_impl_
->renderer())
891 base::TimeTicks monotonic_time
=
892 layer_tree_host_impl_
->CurrentFrameTimeTicks();
893 base::Time wall_clock_time
= layer_tree_host_impl_
->CurrentFrameTime();
895 if (input_handler_client_on_impl_thread_
)
896 input_handler_client_on_impl_thread_
->Animate(monotonic_time
);
898 layer_tree_host_impl_
->ActivatePendingTreeIfNeeded();
899 layer_tree_host_impl_
->Animate(monotonic_time
, wall_clock_time
);
900 layer_tree_host_impl_
->UpdateBackgroundAnimateTicking(false);
902 // This method is called on a forced draw, regardless of whether we are able
903 // to produce a frame, as the calling site on main thread is blocked until its
904 // request completes, and we signal completion here. If CanDraw() is false, we
905 // will indicate success=false to the caller, but we must still signal
906 // completion to avoid deadlock.
908 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
909 // frame, so can only be used when such a frame is possible. Since
910 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
911 // CanDraw() as well.
913 // If it is a forced draw, make sure we do a draw and swap.
914 gfx::Rect readback_rect
;
915 if (readback_request_on_impl_thread_
)
916 readback_rect
= readback_request_on_impl_thread_
->rect
;
918 LayerTreeHostImpl::FrameData frame
;
919 bool draw_frame
= false;
920 bool start_ready_animations
= true;
922 if (layer_tree_host_impl_
->CanDraw()) {
923 // Do not start animations if we skip drawing the frame to avoid
925 if (layer_tree_host_impl_
->PrepareToDraw(&frame
, readback_rect
) ||
929 start_ready_animations
= false;
933 layer_tree_host_impl_
->DrawLayers(
935 scheduler_on_impl_thread_
->LastVSyncTime());
936 result
.did_draw
= true;
938 layer_tree_host_impl_
->DidDrawAllLayers(frame
);
940 layer_tree_host_impl_
->UpdateAnimationState(start_ready_animations
);
942 // Check for tree activation.
943 if (completion_event_for_commit_held_on_tree_activation_
&&
944 !layer_tree_host_impl_
->pending_tree()) {
945 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
946 TRACE_EVENT_SCOPE_THREAD
);
947 DCHECK(layer_tree_host_impl_
->settings().impl_side_painting
);
948 completion_event_for_commit_held_on_tree_activation_
->Signal();
949 completion_event_for_commit_held_on_tree_activation_
= NULL
;
952 // Check for a pending CompositeAndReadback.
953 if (readback_request_on_impl_thread_
) {
954 readback_request_on_impl_thread_
->success
= false;
956 layer_tree_host_impl_
->Readback(readback_request_on_impl_thread_
->pixels
,
957 readback_request_on_impl_thread_
->rect
);
958 readback_request_on_impl_thread_
->success
=
959 !layer_tree_host_impl_
->IsContextLost();
961 readback_request_on_impl_thread_
->completion
.Signal();
962 readback_request_on_impl_thread_
= NULL
;
963 } else if (draw_frame
) {
964 result
.did_swap
= layer_tree_host_impl_
->SwapBuffers(frame
);
966 if (frame
.contains_incomplete_tile
)
967 DidSwapUseIncompleteTileOnImplThread();
970 // Tell the main thread that the the newly-commited frame was drawn.
971 if (next_frame_is_newly_committed_frame_on_impl_thread_
) {
972 next_frame_is_newly_committed_frame_on_impl_thread_
= false;
973 Proxy::MainThread()->PostTask(
974 base::Bind(&ThreadProxy::DidCommitAndDrawFrame
, main_thread_weak_ptr_
));
978 CheckOutputSurfaceStatusOnImplThread();
980 layer_tree_host_impl_
->BeginNextFrame();
985 void ThreadProxy::AcquireLayerTextures() {
986 // Called when the main thread needs to modify a layer texture that is used
987 // directly by the compositor.
988 // This method will block until the next compositor draw if there is a
989 // previously committed frame that is still undrawn. This is necessary to
990 // ensure that the main thread does not monopolize access to the textures.
991 DCHECK(IsMainThread());
993 if (textures_acquired_
)
996 TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures");
997 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
998 CompletionEvent completion
;
999 Proxy::ImplThread()->PostTask(
1000 base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread
,
1001 impl_thread_weak_ptr_
,
1003 // Block until it is safe to write to layer textures from the main thread.
1006 textures_acquired_
= true;
1009 void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread(
1010 CompletionEvent
* completion
) {
1011 DCHECK(IsImplThread());
1012 DCHECK(!texture_acquisition_completion_event_on_impl_thread_
);
1014 texture_acquisition_completion_event_on_impl_thread_
= completion
;
1015 scheduler_on_impl_thread_
->SetMainThreadNeedsLayerTextures();
1018 void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() {
1019 DCHECK(texture_acquisition_completion_event_on_impl_thread_
);
1020 texture_acquisition_completion_event_on_impl_thread_
->Signal();
1021 texture_acquisition_completion_event_on_impl_thread_
= NULL
;
1024 ScheduledActionDrawAndSwapResult
1025 ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1026 return ScheduledActionDrawAndSwapInternal(false);
1029 ScheduledActionDrawAndSwapResult
1030 ThreadProxy::ScheduledActionDrawAndSwapForced() {
1031 return ScheduledActionDrawAndSwapInternal(true);
1034 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time
) {
1035 if (current_resource_update_controller_on_impl_thread_
)
1036 current_resource_update_controller_on_impl_thread_
1037 ->PerformMoreUpdates(time
);
1040 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1041 DCHECK(IsImplThread());
1042 scheduler_on_impl_thread_
->BeginFrameComplete();
1045 void ThreadProxy::DidCommitAndDrawFrame() {
1046 DCHECK(IsMainThread());
1047 if (!layer_tree_host_
)
1049 layer_tree_host_
->DidCommitAndDrawFrame();
1052 void ThreadProxy::DidCompleteSwapBuffers() {
1053 DCHECK(IsMainThread());
1054 if (!layer_tree_host_
)
1056 layer_tree_host_
->DidCompleteSwapBuffers();
1059 void ThreadProxy::SetAnimationEvents(scoped_ptr
<AnimationEventsVector
> events
,
1060 base::Time wall_clock_time
) {
1061 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1062 DCHECK(IsMainThread());
1063 if (!layer_tree_host_
)
1065 layer_tree_host_
->SetAnimationEvents(events
.Pass(), wall_clock_time
);
1068 void ThreadProxy::CreateAndInitializeOutputSurface() {
1069 TRACE_EVENT0("cc", "ThreadProxy::CreateAndInitializeOutputSurface");
1070 DCHECK(IsMainThread());
1072 // Check that output surface has not been recreated by CompositeAndReadback
1073 // after this task is posted but before it is run.
1074 bool has_initialized_output_surface_on_impl_thread
= true;
1076 CompletionEvent completion
;
1077 Proxy::ImplThread()->PostTask(
1078 base::Bind(&ThreadProxy::HasInitializedOutputSurfaceOnImplThread
,
1079 impl_thread_weak_ptr_
,
1081 &has_initialized_output_surface_on_impl_thread
));
1084 if (has_initialized_output_surface_on_impl_thread
)
1087 layer_tree_host_
->DidLoseOutputSurface();
1088 output_surface_creation_callback_
.Reset(base::Bind(
1089 &ThreadProxy::DoCreateAndInitializeOutputSurface
,
1090 base::Unretained(this)));
1091 output_surface_creation_callback_
.callback().Run();
1094 void ThreadProxy::HasInitializedOutputSurfaceOnImplThread(
1095 CompletionEvent
* completion
,
1096 bool* has_initialized_output_surface
) {
1097 DCHECK(IsImplThread());
1098 *has_initialized_output_surface
=
1099 scheduler_on_impl_thread_
->HasInitializedOutputSurface();
1100 completion
->Signal();
1103 void ThreadProxy::InitializeImplOnImplThread(
1104 CompletionEvent
* completion
,
1105 InputHandlerClient
* input_handler_client
) {
1106 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1107 DCHECK(IsImplThread());
1108 layer_tree_host_impl_
= layer_tree_host_
->CreateLayerTreeHostImpl(this);
1109 const base::TimeDelta display_refresh_interval
=
1110 base::TimeDelta::FromMicroseconds(
1111 base::Time::kMicrosecondsPerSecond
/
1112 layer_tree_host_
->settings().refresh_rate
);
1113 scoped_ptr
<FrameRateController
> frame_rate_controller
;
1114 if (render_vsync_enabled_
) {
1115 if (render_vsync_notification_enabled_
) {
1116 frame_rate_controller
.reset(
1117 new FrameRateController(VSyncTimeSource::Create(this)));
1119 frame_rate_controller
.reset(
1120 new FrameRateController(DelayBasedTimeSource::Create(
1121 display_refresh_interval
, Proxy::ImplThread())));
1124 frame_rate_controller
.reset(new FrameRateController(Proxy::ImplThread()));
1126 const LayerTreeSettings
& settings
= layer_tree_host_
->settings();
1127 SchedulerSettings scheduler_settings
;
1128 scheduler_settings
.impl_side_painting
= settings
.impl_side_painting
;
1129 scheduler_settings
.timeout_and_draw_when_animation_checkerboards
=
1130 settings
.timeout_and_draw_when_animation_checkerboards
;
1131 scheduler_on_impl_thread_
= Scheduler::Create(this,
1132 frame_rate_controller
.Pass(),
1133 scheduler_settings
);
1134 scheduler_on_impl_thread_
->SetVisible(layer_tree_host_impl_
->visible());
1136 input_handler_client_on_impl_thread_
.reset(input_handler_client
);
1137 if (input_handler_client_on_impl_thread_
) {
1138 input_handler_client_on_impl_thread_
->BindToHandler(
1139 layer_tree_host_impl_
.get());
1142 impl_thread_weak_ptr_
= weak_factory_on_impl_thread_
.GetWeakPtr();
1143 completion
->Signal();
1146 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1147 CompletionEvent
* completion
,
1148 scoped_ptr
<OutputSurface
> output_surface
,
1149 scoped_refptr
<ContextProvider
> offscreen_context_provider
,
1151 RendererCapabilities
* capabilities
) {
1152 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1153 DCHECK(IsImplThread());
1154 DCHECK(IsMainThreadBlocked());
1156 DCHECK(capabilities
);
1158 layer_tree_host_
->DeleteContentsTexturesOnImplThread(
1159 layer_tree_host_impl_
->resource_provider());
1161 *success
= layer_tree_host_impl_
->InitializeRenderer(output_surface
.Pass());
1163 if (offscreen_context_provider
)
1164 offscreen_context_provider
->BindToCurrentThread();
1167 *capabilities
= layer_tree_host_impl_
->GetRendererCapabilities();
1168 scheduler_on_impl_thread_
->SetSwapBuffersCompleteSupported(
1169 capabilities
->using_swap_complete_callback
);
1171 OutputSurface
* output_surface_ptr
= layer_tree_host_impl_
->output_surface();
1172 DCHECK(output_surface_ptr
);
1173 int max_frames_pending
=
1174 output_surface_ptr
->capabilities().max_frames_pending
;
1175 if (max_frames_pending
<= 0)
1176 max_frames_pending
= FrameRateController::DEFAULT_MAX_FRAMES_PENDING
;
1177 if (output_surface_ptr
->capabilities().has_parent_compositor
)
1178 max_frames_pending
= 1;
1180 scheduler_on_impl_thread_
->SetMaxFramesPending(max_frames_pending
);
1182 layer_tree_host_impl_
->resource_provider()->
1183 set_offscreen_context_provider(offscreen_context_provider
);
1185 scheduler_on_impl_thread_
->DidCreateAndInitializeOutputSurface();
1186 } else if (offscreen_context_provider
) {
1187 offscreen_context_provider
->VerifyContexts();
1190 completion
->Signal();
1193 void ThreadProxy::FinishGLOnImplThread(CompletionEvent
* completion
) {
1194 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
1195 DCHECK(IsImplThread());
1196 if (layer_tree_host_impl_
->resource_provider())
1197 layer_tree_host_impl_
->resource_provider()->Finish();
1198 completion
->Signal();
1201 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent
* completion
) {
1202 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1203 DCHECK(IsImplThread());
1204 layer_tree_host_
->DeleteContentsTexturesOnImplThread(
1205 layer_tree_host_impl_
->resource_provider());
1206 layer_tree_host_impl_
->EnableVSyncNotification(false);
1207 input_handler_client_on_impl_thread_
.reset();
1208 layer_tree_host_impl_
.reset();
1209 scheduler_on_impl_thread_
.reset();
1210 weak_factory_on_impl_thread_
.InvalidateWeakPtrs();
1211 vsync_client_
= NULL
;
1212 completion
->Signal();
1215 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1216 return ResourceUpdateController::MaxPartialTextureUpdates();
1219 ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
1220 : memory_allocation_limit_bytes(0) {}
1222 ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {}
1224 scoped_ptr
<base::Value
> ThreadProxy::AsValue() const {
1225 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1227 CompletionEvent completion
;
1229 DebugScopedSetMainThreadBlocked
main_thread_blocked(
1230 const_cast<ThreadProxy
*>(this));
1231 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::AsValueOnImplThread
,
1232 impl_thread_weak_ptr_
,
1237 return state
.PassAs
<base::Value
>();
1240 void ThreadProxy::AsValueOnImplThread(CompletionEvent
* completion
,
1241 base::DictionaryValue
* state
) const {
1242 state
->Set("layer_tree_host_impl",
1243 layer_tree_host_impl_
->AsValue().release());
1244 completion
->Signal();
1247 bool ThreadProxy::CommitPendingForTesting() {
1248 DCHECK(IsMainThread());
1249 CommitPendingRequest commit_pending_request
;
1251 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1252 Proxy::ImplThread()->PostTask(
1253 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting
,
1254 impl_thread_weak_ptr_
,
1255 &commit_pending_request
));
1256 commit_pending_request
.completion
.Wait();
1258 return commit_pending_request
.commit_pending
;
1261 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1262 CommitPendingRequest
* request
) {
1263 DCHECK(IsImplThread());
1264 if (layer_tree_host_impl_
->output_surface())
1265 request
->commit_pending
= scheduler_on_impl_thread_
->CommitPending();
1267 request
->commit_pending
= false;
1268 request
->completion
.Signal();
1271 skia::RefPtr
<SkPicture
> ThreadProxy::CapturePicture() {
1272 DCHECK(IsMainThread());
1273 CompletionEvent completion
;
1274 skia::RefPtr
<SkPicture
> picture
;
1276 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1277 Proxy::ImplThread()->PostTask(
1278 base::Bind(&ThreadProxy::CapturePictureOnImplThread
,
1279 impl_thread_weak_ptr_
,
1287 void ThreadProxy::CapturePictureOnImplThread(CompletionEvent
* completion
,
1288 skia::RefPtr
<SkPicture
>* picture
) {
1289 DCHECK(IsImplThread());
1290 *picture
= layer_tree_host_impl_
->CapturePicture();
1291 completion
->Signal();
1294 void ThreadProxy::RenewTreePriority() {
1295 bool smoothness_takes_priority
=
1296 layer_tree_host_impl_
->pinch_gesture_active() ||
1297 layer_tree_host_impl_
->CurrentlyScrollingLayer() ||
1298 layer_tree_host_impl_
->page_scale_animation_active();
1300 // Update expiration time if smoothness currently takes priority.
1301 if (smoothness_takes_priority
) {
1302 smoothness_takes_priority_expiration_time_
=
1303 base::TimeTicks::Now() +
1304 base::TimeDelta::FromMilliseconds(
1305 kSmoothnessTakesPriorityExpirationDelay
* 1000);
1308 // We use the same priority for both trees by default.
1309 TreePriority priority
= SAME_PRIORITY_FOR_BOTH_TREES
;
1311 // Smoothness takes priority if expiration time is in the future.
1312 if (smoothness_takes_priority_expiration_time_
> base::TimeTicks::Now())
1313 priority
= SMOOTHNESS_TAKES_PRIORITY
;
1315 // New content always takes priority when the active tree has
1316 // evicted resources or there is an invalid viewport size.
1317 if (layer_tree_host_impl_
->active_tree()->ContentsTexturesPurged() ||
1318 layer_tree_host_impl_
->active_tree()->ViewportSizeInvalid())
1319 priority
= NEW_CONTENT_TAKES_PRIORITY
;
1321 layer_tree_host_impl_
->SetTreePriority(priority
);
1323 // Notify the the client of this compositor via the output surface.
1324 // TODO(epenner): Route this to compositor-thread instead of output-surface
1325 // after GTFO refactor of compositor-thread (http://crbug/170828).
1326 if (layer_tree_host_impl_
->output_surface()) {
1327 layer_tree_host_impl_
->output_surface()->
1328 UpdateSmoothnessTakesPriority(priority
== SMOOTHNESS_TAKES_PRIORITY
);
1331 base::TimeDelta delay
=
1332 smoothness_takes_priority_expiration_time_
- base::TimeTicks::Now();
1334 // Need to make sure a delayed task is posted when we have smoothness
1335 // takes priority expiration time in the future.
1336 if (delay
<= base::TimeDelta())
1338 if (renew_tree_priority_on_impl_thread_pending_
)
1341 Proxy::ImplThread()->PostDelayedTask(
1342 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread
,
1343 weak_factory_on_impl_thread_
.GetWeakPtr()),
1346 renew_tree_priority_on_impl_thread_pending_
= true;
1349 void ThreadProxy::RenewTreePriorityOnImplThread() {
1350 DCHECK(renew_tree_priority_on_impl_thread_pending_
);
1351 renew_tree_priority_on_impl_thread_pending_
= false;
1353 RenewTreePriority();
1356 void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay
) {
1357 Proxy::ImplThread()->PostDelayedTask(
1358 base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread
,
1359 impl_thread_weak_ptr_
),
1363 void ThreadProxy::StartScrollbarAnimationOnImplThread() {
1364 layer_tree_host_impl_
->StartScrollbarAnimation(
1365 layer_tree_host_impl_
->CurrentFrameTimeTicks());
1368 void ThreadProxy::DidReceiveLastInputEventForVSync(
1369 base::TimeTicks frame_time
) {
1370 if (render_vsync_notification_enabled_
) {
1371 TRACE_EVENT0("cc", "ThreadProxy::DidReceiveLastInputEventForVSync");
1372 DidVSync(frame_time
);