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
),
49 renderer_initialized_(false),
51 textures_acquired_(true),
52 in_composite_and_readback_(false),
53 manage_tiles_pending_(false),
54 weak_factory_on_impl_thread_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
55 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
56 begin_frame_completion_event_on_impl_thread_(NULL
),
57 readback_request_on_impl_thread_(NULL
),
58 commit_completion_event_on_impl_thread_(NULL
),
59 completion_event_for_commit_held_on_tree_activation_(NULL
),
60 texture_acquisition_completion_event_on_impl_thread_(NULL
),
61 next_frame_is_newly_committed_frame_on_impl_thread_(false),
62 render_vsync_enabled_(layer_tree_host
->settings().render_vsync_enabled
),
63 render_vsync_notification_enabled_(
64 layer_tree_host
->settings().render_vsync_notification_enabled
),
67 defer_commits_(false),
68 renew_tree_priority_on_impl_thread_pending_(false) {
69 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
70 DCHECK(IsMainThread());
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_
->InitializeRendererIfNeeded()) {
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 bool ThreadProxy::InitializeOutputSurface() {
153 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurface");
154 scoped_ptr
<OutputSurface
> context
= layer_tree_host_
->CreateOutputSurface();
158 Proxy::ImplThread()->PostTask(
159 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread
,
160 impl_thread_weak_ptr_
,
161 base::Passed(&context
)));
165 void ThreadProxy::SetSurfaceReady() {
166 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReady");
167 Proxy::ImplThread()->PostTask(base::Bind(
168 &ThreadProxy::SetSurfaceReadyOnImplThread
, impl_thread_weak_ptr_
));
171 void ThreadProxy::SetSurfaceReadyOnImplThread() {
172 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReadyOnImplThread");
173 scheduler_on_impl_thread_
->SetCanBeginFrame(true);
176 void ThreadProxy::SetVisible(bool visible
) {
177 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
178 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
179 CompletionEvent completion
;
180 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::SetVisibleOnImplThread
,
181 impl_thread_weak_ptr_
,
187 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent
* completion
,
189 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
190 layer_tree_host_impl_
->SetVisible(visible
);
191 scheduler_on_impl_thread_
->SetVisible(visible
);
192 completion
->Signal();
195 bool ThreadProxy::InitializeRenderer() {
196 TRACE_EVENT0("cc", "ThreadProxy::InitializeRenderer");
197 // Make a blocking call to InitializeRendererOnImplThread. The results of that
198 // call are pushed into the initialize_succeeded and capabilities local
200 CompletionEvent completion
;
201 bool initialize_succeeded
= false;
202 RendererCapabilities capabilities
;
203 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
204 Proxy::ImplThread()->PostTask(
205 base::Bind(&ThreadProxy::InitializeRendererOnImplThread
,
206 impl_thread_weak_ptr_
,
208 &initialize_succeeded
,
212 if (initialize_succeeded
) {
213 renderer_initialized_
= true;
214 renderer_capabilities_main_thread_copy_
= capabilities
;
216 return initialize_succeeded
;
219 bool ThreadProxy::RecreateOutputSurface() {
220 TRACE_EVENT0("cc", "ThreadProxy::RecreateOutputSurface");
221 DCHECK(IsMainThread());
223 // Try to create the surface.
224 scoped_ptr
<OutputSurface
> output_surface
=
225 layer_tree_host_
->CreateOutputSurface();
228 scoped_refptr
<cc::ContextProvider
> offscreen_context_provider
;
229 if (created_offscreen_context_provider_
) {
230 offscreen_context_provider
= layer_tree_host_
->client()->
231 OffscreenContextProviderForCompositorThread();
232 if (!offscreen_context_provider
)
236 // Make a blocking call to RecreateOutputSurfaceOnImplThread. The results of
237 // that call are pushed into the recreate_succeeded and capabilities local
239 CompletionEvent completion
;
240 bool recreate_succeeded
= false;
241 RendererCapabilities capabilities
;
242 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
243 Proxy::ImplThread()->PostTask(
244 base::Bind(&ThreadProxy::RecreateOutputSurfaceOnImplThread
,
245 impl_thread_weak_ptr_
,
247 base::Passed(&output_surface
),
248 offscreen_context_provider
,
253 if (recreate_succeeded
)
254 renderer_capabilities_main_thread_copy_
= capabilities
;
255 return recreate_succeeded
;
258 const RendererCapabilities
& ThreadProxy::GetRendererCapabilities() const {
259 DCHECK(renderer_initialized_
);
260 return renderer_capabilities_main_thread_copy_
;
263 void ThreadProxy::SetNeedsAnimate() {
264 DCHECK(IsMainThread());
265 if (animate_requested_
)
268 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
269 animate_requested_
= true;
271 if (commit_request_sent_to_impl_thread_
)
273 commit_request_sent_to_impl_thread_
= true;
274 Proxy::ImplThread()->PostTask(base::Bind(
275 &ThreadProxy::SetNeedsCommitOnImplThread
, impl_thread_weak_ptr_
));
278 void ThreadProxy::SetNeedsCommit() {
279 DCHECK(IsMainThread());
280 if (commit_requested_
)
282 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
283 commit_requested_
= true;
285 if (commit_request_sent_to_impl_thread_
)
287 commit_request_sent_to_impl_thread_
= true;
288 Proxy::ImplThread()->PostTask(base::Bind(
289 &ThreadProxy::SetNeedsCommitOnImplThread
, impl_thread_weak_ptr_
));
292 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
293 DCHECK(IsImplThread());
294 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
295 Proxy::ImplThread()->PostTask(
296 base::Bind(&ThreadProxy::CheckOutputSurfaceStatusOnImplThread
,
297 impl_thread_weak_ptr_
));
300 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
301 DCHECK(IsImplThread());
302 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
303 if (!layer_tree_host_impl_
->IsContextLost())
305 if (cc::ContextProvider
* offscreen_contexts
= layer_tree_host_impl_
->
306 resource_provider()->offscreen_context_provider())
307 offscreen_contexts
->VerifyContexts();
308 scheduler_on_impl_thread_
->DidLoseOutputSurface();
311 void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
312 DCHECK(IsImplThread());
313 TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
314 scheduler_on_impl_thread_
->DidSwapBuffersComplete();
315 Proxy::MainThread()->PostTask(
316 base::Bind(&ThreadProxy::DidCompleteSwapBuffers
, main_thread_weak_ptr_
));
319 void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase
,
320 base::TimeDelta interval
) {
321 DCHECK(IsImplThread());
323 "ThreadProxy::OnVSyncParametersChanged",
325 (timebase
- base::TimeTicks()).InMilliseconds(),
327 interval
.InMilliseconds());
328 scheduler_on_impl_thread_
->SetTimebaseAndInterval(timebase
, interval
);
331 void ThreadProxy::DidVSync(base::TimeTicks frame_time
) {
332 DCHECK(IsImplThread());
333 TRACE_EVENT0("cc", "ThreadProxy::DidVSync");
335 vsync_client_
->DidVSync(frame_time
);
338 void ThreadProxy::RequestVSyncNotification(VSyncClient
* client
) {
339 DCHECK(IsImplThread());
341 "cc", "ThreadProxy::RequestVSyncNotification", "enable", !!client
);
342 vsync_client_
= client
;
343 layer_tree_host_impl_
->EnableVSyncNotification(!!client
);
346 void ThreadProxy::OnCanDrawStateChanged(bool can_draw
) {
347 DCHECK(IsImplThread());
349 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw
);
350 scheduler_on_impl_thread_
->SetCanDraw(can_draw
);
351 layer_tree_host_impl_
->UpdateBackgroundAnimateTicking(
352 !scheduler_on_impl_thread_
->WillDrawIfNeeded());
355 void ThreadProxy::OnHasPendingTreeStateChanged(bool has_pending_tree
) {
356 DCHECK(IsImplThread());
358 "ThreadProxy::OnHasPendingTreeStateChanged",
361 scheduler_on_impl_thread_
->SetHasPendingTree(has_pending_tree
);
364 void ThreadProxy::SetNeedsCommitOnImplThread() {
365 DCHECK(IsImplThread());
366 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
367 scheduler_on_impl_thread_
->SetNeedsCommit();
370 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
371 if (manage_tiles_pending_
)
373 Proxy::ImplThread()->PostTask(
374 base::Bind(&ThreadProxy::ManageTilesOnImplThread
, impl_thread_weak_ptr_
));
375 manage_tiles_pending_
= true;
378 void ThreadProxy::ManageTilesOnImplThread() {
379 // TODO(nduca): If needed, move this into CCSchedulerStateMachine.
380 manage_tiles_pending_
= false;
381 if (layer_tree_host_impl_
)
382 layer_tree_host_impl_
->ManageTiles();
385 void ThreadProxy::SetNeedsForcedCommitOnImplThread() {
386 DCHECK(IsImplThread());
387 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsForcedCommitOnImplThread");
388 scheduler_on_impl_thread_
->SetNeedsForcedCommit();
391 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
392 scoped_ptr
<AnimationEventsVector
> events
,
393 base::Time wall_clock_time
) {
394 DCHECK(IsImplThread());
396 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
397 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::SetAnimationEvents
,
398 main_thread_weak_ptr_
,
399 base::Passed(&events
),
403 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes
,
404 int priority_cutoff
) {
405 DCHECK(IsImplThread());
407 if (!layer_tree_host_
->contents_texture_manager())
410 bool reduce_result
= layer_tree_host_
->contents_texture_manager()->
411 ReduceMemoryOnImplThread(limit_bytes
,
413 layer_tree_host_impl_
->resource_provider());
417 // The texture upload queue may reference textures that were just purged,
418 // clear them from the queue.
419 if (current_resource_update_controller_on_impl_thread_
) {
420 current_resource_update_controller_on_impl_thread_
->
421 DiscardUploadsToEvictedResources();
426 void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
427 DCHECK(IsImplThread());
429 if (!layer_tree_host_
->contents_texture_manager())
432 layer_tree_host_
->contents_texture_manager()->ReduceWastedMemoryOnImplThread(
433 layer_tree_host_impl_
->resource_provider());
436 void ThreadProxy::SendManagedMemoryStats() {
437 DCHECK(IsImplThread());
438 if (!layer_tree_host_impl_
)
440 if (!layer_tree_host_
->contents_texture_manager())
443 // If we are using impl-side painting, then SendManagedMemoryStats is called
444 // directly after the tile manager's manage function, and doesn't need to
445 // interact with main thread's layer tree.
446 if (layer_tree_host_
->settings().impl_side_painting
)
449 layer_tree_host_impl_
->SendManagedMemoryStats(
450 layer_tree_host_
->contents_texture_manager()->MemoryVisibleBytes(),
451 layer_tree_host_
->contents_texture_manager()->
452 MemoryVisibleAndNearbyBytes(),
453 layer_tree_host_
->contents_texture_manager()->MemoryUseBytes());
456 bool ThreadProxy::IsInsideDraw() { return inside_draw_
; }
458 void ThreadProxy::SetNeedsRedraw(const gfx::Rect
& damage_rect
) {
459 DCHECK(IsMainThread());
460 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
461 Proxy::ImplThread()->PostTask(base::Bind(
462 &ThreadProxy::SetViewportDamageOnImplThread
,
463 impl_thread_weak_ptr_
, damage_rect
));
464 Proxy::ImplThread()->PostTask(base::Bind(
465 &ThreadProxy::SetNeedsRedrawOnImplThread
, impl_thread_weak_ptr_
));
468 void ThreadProxy::SetDeferCommits(bool defer_commits
) {
469 DCHECK(IsMainThread());
470 DCHECK_NE(defer_commits_
, defer_commits
);
471 defer_commits_
= defer_commits
;
474 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
476 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
478 if (!defer_commits_
&& pending_deferred_commit_
)
479 Proxy::MainThread()->PostTask(
480 base::Bind(&ThreadProxy::BeginFrame
,
481 main_thread_weak_ptr_
,
482 base::Passed(&pending_deferred_commit_
)));
485 bool ThreadProxy::CommitRequested() const {
486 DCHECK(IsMainThread());
487 return commit_requested_
;
490 void ThreadProxy::SetNeedsRedrawOnImplThread() {
491 DCHECK(IsImplThread());
492 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
493 scheduler_on_impl_thread_
->SetNeedsRedraw();
496 void ThreadProxy::DidSwapUseIncompleteTileOnImplThread() {
497 DCHECK(IsImplThread());
498 TRACE_EVENT0("cc", "ThreadProxy::DidSwapUseIncompleteTileOnImplThread");
499 scheduler_on_impl_thread_
->DidSwapUseIncompleteTile();
502 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
503 DCHECK(IsImplThread());
504 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
505 scheduler_on_impl_thread_
->SetNeedsRedraw();
508 void ThreadProxy::MainThreadHasStoppedFlinging() {
509 if (input_handler_on_impl_thread_
)
510 input_handler_on_impl_thread_
->MainThreadHasStoppedFlinging();
513 void ThreadProxy::Start() {
514 DCHECK(IsMainThread());
515 DCHECK(Proxy::ImplThread());
516 // Create LayerTreeHostImpl.
517 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
518 CompletionEvent completion
;
519 scoped_ptr
<InputHandler
> handler
= layer_tree_host_
->CreateInputHandler();
520 Proxy::ImplThread()->PostTask(
521 base::Bind(&ThreadProxy::InitializeImplOnImplThread
,
522 base::Unretained(this),
527 main_thread_weak_ptr_
= weak_factory_
.GetWeakPtr();
532 void ThreadProxy::Stop() {
533 TRACE_EVENT0("cc", "ThreadProxy::Stop");
534 DCHECK(IsMainThread());
537 // Synchronously deletes the impl.
539 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
541 CompletionEvent completion
;
542 Proxy::ImplThread()->PostTask(
543 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread
,
544 impl_thread_weak_ptr_
,
549 weak_factory_
.InvalidateWeakPtrs();
551 DCHECK(!layer_tree_host_impl_
.get()); // verify that the impl deleted.
552 layer_tree_host_
= NULL
;
556 void ThreadProxy::ForceSerializeOnSwapBuffers() {
557 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
558 CompletionEvent completion
;
559 Proxy::ImplThread()->PostTask(
560 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread
,
561 impl_thread_weak_ptr_
,
566 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
567 CompletionEvent
* completion
) {
568 if (renderer_initialized_
)
569 layer_tree_host_impl_
->renderer()->DoNoOp();
570 completion
->Signal();
573 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent
* completion
) {
574 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
575 DCHECK(IsImplThread());
576 layer_tree_host_impl_
->FinishAllRendering();
577 completion
->Signal();
580 void ThreadProxy::ForceBeginFrameOnImplThread(CompletionEvent
* completion
) {
581 TRACE_EVENT0("cc", "ThreadProxy::ForceBeginFrameOnImplThread");
582 DCHECK(!begin_frame_completion_event_on_impl_thread_
);
584 SetNeedsForcedCommitOnImplThread();
585 if (scheduler_on_impl_thread_
->CommitPending()) {
586 completion
->Signal();
590 begin_frame_completion_event_on_impl_thread_
= completion
;
593 void ThreadProxy::ScheduledActionBeginFrame() {
594 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginFrame");
595 scoped_ptr
<BeginFrameAndCommitState
> begin_frame_state(
596 new BeginFrameAndCommitState
);
597 begin_frame_state
->monotonic_frame_begin_time
= base::TimeTicks::Now();
598 begin_frame_state
->scroll_info
= layer_tree_host_impl_
->ProcessScrollDeltas();
599 begin_frame_state
->impl_transform
=
600 layer_tree_host_impl_
->active_tree()->ImplTransform();
601 DCHECK_GT(layer_tree_host_impl_
->memory_allocation_limit_bytes(), 0u);
602 begin_frame_state
->memory_allocation_limit_bytes
=
603 layer_tree_host_impl_
->memory_allocation_limit_bytes();
604 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::BeginFrame
,
605 main_thread_weak_ptr_
,
606 base::Passed(&begin_frame_state
)));
608 if (begin_frame_completion_event_on_impl_thread_
) {
609 begin_frame_completion_event_on_impl_thread_
->Signal();
610 begin_frame_completion_event_on_impl_thread_
= NULL
;
614 void ThreadProxy::BeginFrame(
615 scoped_ptr
<BeginFrameAndCommitState
> begin_frame_state
) {
616 TRACE_EVENT0("cc", "ThreadProxy::BeginFrame");
617 DCHECK(IsMainThread());
618 if (!layer_tree_host_
)
621 if (defer_commits_
) {
622 pending_deferred_commit_
= begin_frame_state
.Pass();
623 layer_tree_host_
->DidDeferCommit();
624 TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
628 // Do not notify the impl thread of commit requests that occur during
629 // the apply/animate/layout part of the BeginFrameAndCommit process since
630 // those commit requests will get painted immediately. Once we have done
631 // the paint, commit_requested_ will be set to false to allow new commit
632 // requests to be scheduled.
633 commit_requested_
= true;
634 commit_request_sent_to_impl_thread_
= true;
636 // On the other hand, the AnimationRequested flag needs to be cleared
637 // here so that any animation requests generated by the apply or animate
638 // callbacks will trigger another frame.
639 animate_requested_
= false;
641 if (begin_frame_state
) {
642 layer_tree_host_
->ApplyScrollAndScale(*begin_frame_state
->scroll_info
);
643 layer_tree_host_
->SetImplTransform(begin_frame_state
->impl_transform
);
646 if (!in_composite_and_readback_
&& !layer_tree_host_
->visible()) {
647 commit_requested_
= false;
648 commit_request_sent_to_impl_thread_
= false;
650 TRACE_EVENT0("cc", "EarlyOut_NotVisible");
651 Proxy::ImplThread()->PostTask(base::Bind(
652 &ThreadProxy::BeginFrameAbortedOnImplThread
, impl_thread_weak_ptr_
));
656 layer_tree_host_
->WillBeginFrame();
658 if (begin_frame_state
) {
659 layer_tree_host_
->UpdateAnimations(
660 begin_frame_state
->monotonic_frame_begin_time
);
663 // Unlink any backings that the impl thread has evicted, so that we know to
664 // re-paint them in UpdateLayers.
665 if (layer_tree_host_
->contents_texture_manager()) {
666 layer_tree_host_
->contents_texture_manager()->
667 UnlinkAndClearEvictedBackings();
670 layer_tree_host_
->Layout();
672 // Clear the commit flag after updating animations and layout here --- objects
673 // that only layout when painted will trigger another SetNeedsCommit inside
675 commit_requested_
= false;
676 commit_request_sent_to_impl_thread_
= false;
678 if (!layer_tree_host_
->InitializeRendererIfNeeded()) {
679 TRACE_EVENT0("cc", "EarlyOut_InitializeFailed");
683 scoped_ptr
<ResourceUpdateQueue
> queue
=
684 make_scoped_ptr(new ResourceUpdateQueue
);
685 layer_tree_host_
->UpdateLayers(
687 begin_frame_state
? begin_frame_state
->memory_allocation_limit_bytes
690 // Once single buffered layers are committed, they cannot be modified until
691 // they are drawn by the impl thread.
692 textures_acquired_
= false;
694 layer_tree_host_
->WillCommit();
695 // Before applying scrolls and calling animate, we set animate_requested_ to
696 // false. If it is true now, it means SetNeedAnimate was called again, but
697 // during a state when commit_request_sent_to_impl_thread_ = true. We need to
698 // force that call to happen again now so that the commit request is sent to
700 if (animate_requested_
) {
701 // Forces SetNeedsAnimate to consider posting a commit task.
702 animate_requested_
= false;
706 scoped_refptr
<cc::ContextProvider
> offscreen_context_provider
;
707 if (renderer_capabilities_main_thread_copy_
.using_offscreen_context3d
&&
708 layer_tree_host_
->needs_offscreen_context()) {
709 offscreen_context_provider
= layer_tree_host_
->client()->
710 OffscreenContextProviderForCompositorThread();
711 if (offscreen_context_provider
)
712 created_offscreen_context_provider_
= true;
715 // Notify the impl thread that the BeginFrame has completed. This will
716 // begin the commit process, which is blocking from the main thread's
717 // point of view, but asynchronously performed on the impl thread,
718 // coordinated by the Scheduler.
720 TRACE_EVENT0("cc", "commit");
722 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
724 RenderingStatsInstrumentation
* stats_instrumentation
=
725 layer_tree_host_
->rendering_stats_instrumentation();
726 base::TimeTicks start_time
= stats_instrumentation
->StartRecording();
728 CompletionEvent completion
;
729 Proxy::ImplThread()->PostTask(
730 base::Bind(&ThreadProxy::BeginFrameCompleteOnImplThread
,
731 impl_thread_weak_ptr_
,
734 offscreen_context_provider
));
737 base::TimeDelta duration
= stats_instrumentation
->EndRecording(start_time
);
738 stats_instrumentation
->AddCommit(duration
);
741 layer_tree_host_
->CommitComplete();
742 layer_tree_host_
->DidBeginFrame();
745 void ThreadProxy::BeginFrameCompleteOnImplThread(
746 CompletionEvent
* completion
,
747 ResourceUpdateQueue
* raw_queue
,
748 scoped_refptr
<cc::ContextProvider
> offscreen_context_provider
) {
749 scoped_ptr
<ResourceUpdateQueue
> queue(raw_queue
);
751 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameCompleteOnImplThread");
752 DCHECK(!commit_completion_event_on_impl_thread_
);
753 DCHECK(IsImplThread() && IsMainThreadBlocked());
754 DCHECK(scheduler_on_impl_thread_
);
755 DCHECK(scheduler_on_impl_thread_
->CommitPending());
757 if (!layer_tree_host_impl_
) {
758 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
759 completion
->Signal();
763 if (offscreen_context_provider
)
764 offscreen_context_provider
->BindToCurrentThread();
765 layer_tree_host_impl_
->resource_provider()->
766 set_offscreen_context_provider(offscreen_context_provider
);
768 if (layer_tree_host_
->contents_texture_manager()->
769 LinkedEvictedBackingsExist()) {
770 // Clear any uploads we were making to textures linked to evicted
772 queue
->ClearUploadsToEvictedResources();
773 // Some textures in the layer tree are invalid. Kick off another commit
774 // to fill them again.
775 SetNeedsCommitOnImplThread();
778 layer_tree_host_
->contents_texture_manager()->
779 PushTexturePrioritiesToBackings();
781 current_resource_update_controller_on_impl_thread_
=
782 ResourceUpdateController::Create(
786 layer_tree_host_impl_
->resource_provider());
787 current_resource_update_controller_on_impl_thread_
->PerformMoreUpdates(
788 scheduler_on_impl_thread_
->AnticipatedDrawTime());
790 commit_completion_event_on_impl_thread_
= completion
;
793 void ThreadProxy::BeginFrameAbortedOnImplThread() {
794 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedOnImplThread");
795 DCHECK(IsImplThread());
796 DCHECK(scheduler_on_impl_thread_
);
797 DCHECK(scheduler_on_impl_thread_
->CommitPending());
799 scheduler_on_impl_thread_
->BeginFrameAborted();
802 void ThreadProxy::ScheduledActionCommit() {
803 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
804 DCHECK(IsImplThread());
805 DCHECK(commit_completion_event_on_impl_thread_
);
806 DCHECK(current_resource_update_controller_on_impl_thread_
);
808 // Complete all remaining texture updates.
809 current_resource_update_controller_on_impl_thread_
->Finalize();
810 current_resource_update_controller_on_impl_thread_
.reset();
812 layer_tree_host_impl_
->BeginCommit();
813 layer_tree_host_
->BeginCommitOnImplThread(layer_tree_host_impl_
.get());
814 layer_tree_host_
->FinishCommitOnImplThread(layer_tree_host_impl_
.get());
815 layer_tree_host_impl_
->CommitComplete();
817 layer_tree_host_impl_
->UpdateBackgroundAnimateTicking(
818 !scheduler_on_impl_thread_
->WillDrawIfNeeded());
820 next_frame_is_newly_committed_frame_on_impl_thread_
= true;
822 if (layer_tree_host_
->settings().impl_side_painting
&&
823 layer_tree_host_
->BlocksPendingCommit()) {
824 // For some layer types in impl-side painting, the commit is held until
825 // the pending tree is activated.
826 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD
);
827 completion_event_for_commit_held_on_tree_activation_
=
828 commit_completion_event_on_impl_thread_
;
829 commit_completion_event_on_impl_thread_
= NULL
;
831 commit_completion_event_on_impl_thread_
->Signal();
832 commit_completion_event_on_impl_thread_
= NULL
;
835 // SetVisible kicks off the next scheduler action, so this must be last.
836 scheduler_on_impl_thread_
->SetVisible(layer_tree_host_impl_
->visible());
839 void ThreadProxy::ScheduledActionCheckForCompletedTileUploads() {
840 DCHECK(IsImplThread());
842 "ThreadProxy::ScheduledActionCheckForCompletedTileUploads");
843 layer_tree_host_impl_
->CheckForCompletedTileUploads();
846 void ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded() {
847 DCHECK(IsImplThread());
848 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded");
849 layer_tree_host_impl_
->ActivatePendingTreeIfNeeded();
852 void ThreadProxy::ScheduledActionBeginContextRecreation() {
853 DCHECK(IsImplThread());
854 Proxy::MainThread()->PostTask(
855 base::Bind(&ThreadProxy::BeginContextRecreation
, main_thread_weak_ptr_
));
858 ScheduledActionDrawAndSwapResult
859 ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw
) {
860 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
862 base::AutoReset
<bool> mark_inside(&inside_draw_
, true);
864 ScheduledActionDrawAndSwapResult result
;
865 result
.did_draw
= false;
866 result
.did_swap
= false;
867 DCHECK(IsImplThread());
868 DCHECK(layer_tree_host_impl_
.get());
869 if (!layer_tree_host_impl_
)
872 DCHECK(layer_tree_host_impl_
->renderer());
873 if (!layer_tree_host_impl_
->renderer())
876 // FIXME: compute the frame display time more intelligently
877 base::TimeTicks monotonic_time
= base::TimeTicks::Now();
878 base::Time wall_clock_time
= base::Time::Now();
880 if (input_handler_on_impl_thread_
)
881 input_handler_on_impl_thread_
->Animate(monotonic_time
);
883 layer_tree_host_impl_
->ActivatePendingTreeIfNeeded();
884 layer_tree_host_impl_
->Animate(monotonic_time
, wall_clock_time
);
885 layer_tree_host_impl_
->UpdateBackgroundAnimateTicking(false);
887 // This method is called on a forced draw, regardless of whether we are able
888 // to produce a frame, as the calling site on main thread is blocked until its
889 // request completes, and we signal completion here. If CanDraw() is false, we
890 // will indicate success=false to the caller, but we must still signal
891 // completion to avoid deadlock.
893 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
894 // frame, so can only be used when such a frame is possible. Since
895 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
896 // CanDraw() as well.
898 // If it is a forced draw, make sure we do a draw and swap.
899 gfx::Rect readback_rect
;
900 if (readback_request_on_impl_thread_
)
901 readback_rect
= readback_request_on_impl_thread_
->rect
;
903 LayerTreeHostImpl::FrameData frame
;
904 bool draw_frame
= false;
905 bool start_ready_animations
= true;
907 if (layer_tree_host_impl_
->CanDraw()) {
908 // Do not start animations if we skip drawing the frame to avoid
910 if (layer_tree_host_impl_
->PrepareToDraw(&frame
, readback_rect
) ||
914 start_ready_animations
= false;
918 layer_tree_host_impl_
->DrawLayers(
920 scheduler_on_impl_thread_
->LastVSyncTime());
921 result
.did_draw
= true;
923 layer_tree_host_impl_
->DidDrawAllLayers(frame
);
925 layer_tree_host_impl_
->UpdateAnimationState(start_ready_animations
);
927 // Check for tree activation.
928 if (completion_event_for_commit_held_on_tree_activation_
&&
929 !layer_tree_host_impl_
->pending_tree()) {
930 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
931 TRACE_EVENT_SCOPE_THREAD
);
932 DCHECK(layer_tree_host_impl_
->settings().impl_side_painting
);
933 completion_event_for_commit_held_on_tree_activation_
->Signal();
934 completion_event_for_commit_held_on_tree_activation_
= NULL
;
937 // Check for a pending CompositeAndReadback.
938 if (readback_request_on_impl_thread_
) {
939 readback_request_on_impl_thread_
->success
= false;
941 layer_tree_host_impl_
->Readback(readback_request_on_impl_thread_
->pixels
,
942 readback_request_on_impl_thread_
->rect
);
943 readback_request_on_impl_thread_
->success
=
944 !layer_tree_host_impl_
->IsContextLost();
946 readback_request_on_impl_thread_
->completion
.Signal();
947 readback_request_on_impl_thread_
= NULL
;
948 } else if (draw_frame
) {
949 result
.did_swap
= layer_tree_host_impl_
->SwapBuffers(frame
);
951 if (frame
.contains_incomplete_tile
)
952 DidSwapUseIncompleteTileOnImplThread();
955 // Tell the main thread that the the newly-commited frame was drawn.
956 if (next_frame_is_newly_committed_frame_on_impl_thread_
) {
957 next_frame_is_newly_committed_frame_on_impl_thread_
= false;
958 Proxy::MainThread()->PostTask(
959 base::Bind(&ThreadProxy::DidCommitAndDrawFrame
, main_thread_weak_ptr_
));
963 CheckOutputSurfaceStatusOnImplThread();
965 layer_tree_host_impl_
->BeginNextFrame();
970 void ThreadProxy::AcquireLayerTextures() {
971 // Called when the main thread needs to modify a layer texture that is used
972 // directly by the compositor.
973 // This method will block until the next compositor draw if there is a
974 // previously committed frame that is still undrawn. This is necessary to
975 // ensure that the main thread does not monopolize access to the textures.
976 DCHECK(IsMainThread());
978 if (textures_acquired_
)
981 TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures");
982 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
983 CompletionEvent completion
;
984 Proxy::ImplThread()->PostTask(
985 base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread
,
986 impl_thread_weak_ptr_
,
988 // Block until it is safe to write to layer textures from the main thread.
991 textures_acquired_
= true;
994 void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread(
995 CompletionEvent
* completion
) {
996 DCHECK(IsImplThread());
997 DCHECK(!texture_acquisition_completion_event_on_impl_thread_
);
999 texture_acquisition_completion_event_on_impl_thread_
= completion
;
1000 scheduler_on_impl_thread_
->SetMainThreadNeedsLayerTextures();
1003 void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() {
1004 DCHECK(texture_acquisition_completion_event_on_impl_thread_
);
1005 texture_acquisition_completion_event_on_impl_thread_
->Signal();
1006 texture_acquisition_completion_event_on_impl_thread_
= NULL
;
1009 ScheduledActionDrawAndSwapResult
1010 ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1011 return ScheduledActionDrawAndSwapInternal(false);
1014 ScheduledActionDrawAndSwapResult
1015 ThreadProxy::ScheduledActionDrawAndSwapForced() {
1016 return ScheduledActionDrawAndSwapInternal(true);
1019 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time
) {
1020 if (layer_tree_host_impl_
)
1021 layer_tree_host_impl_
->SetAnticipatedDrawTime(time
);
1023 if (current_resource_update_controller_on_impl_thread_
)
1024 current_resource_update_controller_on_impl_thread_
1025 ->PerformMoreUpdates(time
);
1028 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1029 DCHECK(IsImplThread());
1030 scheduler_on_impl_thread_
->BeginFrameComplete();
1033 void ThreadProxy::DidCommitAndDrawFrame() {
1034 DCHECK(IsMainThread());
1035 if (!layer_tree_host_
)
1037 layer_tree_host_
->DidCommitAndDrawFrame();
1040 void ThreadProxy::DidCompleteSwapBuffers() {
1041 DCHECK(IsMainThread());
1042 if (!layer_tree_host_
)
1044 layer_tree_host_
->DidCompleteSwapBuffers();
1047 void ThreadProxy::SetAnimationEvents(scoped_ptr
<AnimationEventsVector
> events
,
1048 base::Time wall_clock_time
) {
1049 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1050 DCHECK(IsMainThread());
1051 if (!layer_tree_host_
)
1053 layer_tree_host_
->SetAnimationEvents(events
.Pass(), wall_clock_time
);
1056 void ThreadProxy::BeginContextRecreation() {
1057 TRACE_EVENT0("cc", "ThreadProxy::BeginContextRecreation");
1058 DCHECK(IsMainThread());
1059 layer_tree_host_
->DidLoseOutputSurface();
1060 output_surface_recreation_callback_
.Reset(base::Bind(
1061 &ThreadProxy::TryToRecreateOutputSurface
, base::Unretained(this)));
1062 Proxy::MainThread()->PostTask(output_surface_recreation_callback_
.callback());
1065 void ThreadProxy::TryToRecreateOutputSurface() {
1066 DCHECK(IsMainThread());
1067 DCHECK(layer_tree_host_
);
1068 LayerTreeHost::RecreateResult result
=
1069 layer_tree_host_
->RecreateOutputSurface();
1070 if (result
== LayerTreeHost::RecreateFailedButTryAgain
)
1071 Proxy::MainThread()->PostTask(
1072 output_surface_recreation_callback_
.callback());
1073 else if (result
== LayerTreeHost::RecreateSucceeded
)
1074 output_surface_recreation_callback_
.Cancel();
1077 void ThreadProxy::InitializeImplOnImplThread(CompletionEvent
* completion
,
1078 InputHandler
* handler
) {
1079 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1080 DCHECK(IsImplThread());
1081 layer_tree_host_impl_
= layer_tree_host_
->CreateLayerTreeHostImpl(this);
1082 const base::TimeDelta display_refresh_interval
=
1083 base::TimeDelta::FromMicroseconds(
1084 base::Time::kMicrosecondsPerSecond
/
1085 layer_tree_host_
->settings().refresh_rate
);
1086 scoped_ptr
<FrameRateController
> frame_rate_controller
;
1087 if (render_vsync_enabled_
) {
1088 if (render_vsync_notification_enabled_
) {
1089 frame_rate_controller
.reset(
1090 new FrameRateController(VSyncTimeSource::Create(this)));
1092 frame_rate_controller
.reset(
1093 new FrameRateController(DelayBasedTimeSource::Create(
1094 display_refresh_interval
, Proxy::ImplThread())));
1097 frame_rate_controller
.reset(new FrameRateController(Proxy::ImplThread()));
1099 const LayerTreeSettings
& settings
= layer_tree_host_
->settings();
1100 SchedulerSettings scheduler_settings
;
1101 scheduler_settings
.impl_side_painting
= settings
.impl_side_painting
;
1102 scheduler_settings
.timeout_and_draw_when_animation_checkerboards
=
1103 settings
.timeout_and_draw_when_animation_checkerboards
;
1104 scheduler_on_impl_thread_
= Scheduler::Create(this,
1105 frame_rate_controller
.Pass(),
1106 scheduler_settings
);
1107 scheduler_on_impl_thread_
->SetVisible(layer_tree_host_impl_
->visible());
1109 input_handler_on_impl_thread_
= scoped_ptr
<InputHandler
>(handler
);
1110 if (input_handler_on_impl_thread_
)
1111 input_handler_on_impl_thread_
->BindToClient(layer_tree_host_impl_
.get());
1113 impl_thread_weak_ptr_
= weak_factory_on_impl_thread_
.GetWeakPtr();
1114 completion
->Signal();
1117 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1118 scoped_ptr
<OutputSurface
> output_surface
) {
1119 TRACE_EVENT0("cc", "ThreadProxy::InitializeContextOnImplThread");
1120 DCHECK(IsImplThread());
1121 output_surface_before_initialization_on_impl_thread_
= output_surface
.Pass();
1124 void ThreadProxy::InitializeRendererOnImplThread(
1125 CompletionEvent
* completion
,
1126 bool* initialize_succeeded
,
1127 RendererCapabilities
* capabilities
) {
1128 TRACE_EVENT0("cc", "ThreadProxy::InitializeRendererOnImplThread");
1129 DCHECK(IsImplThread());
1130 DCHECK(output_surface_before_initialization_on_impl_thread_
.get());
1131 *initialize_succeeded
= layer_tree_host_impl_
->InitializeRenderer(
1132 output_surface_before_initialization_on_impl_thread_
.Pass());
1133 if (*initialize_succeeded
) {
1134 *capabilities
= layer_tree_host_impl_
->GetRendererCapabilities();
1135 scheduler_on_impl_thread_
->SetSwapBuffersCompleteSupported(
1136 capabilities
->using_swap_complete_callback
);
1138 int max_frames_pending
= layer_tree_host_impl_
->output_surface()->
1139 capabilities().max_frames_pending
;
1140 if (max_frames_pending
<= 0)
1141 max_frames_pending
= FrameRateController::DEFAULT_MAX_FRAMES_PENDING
;
1142 if (layer_tree_host_impl_
->output_surface()->capabilities().
1143 has_parent_compositor
)
1144 max_frames_pending
= 1;
1145 scheduler_on_impl_thread_
->SetMaxFramesPending(max_frames_pending
);
1148 completion
->Signal();
1151 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent
* completion
) {
1152 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1153 DCHECK(IsImplThread());
1154 layer_tree_host_
->DeleteContentsTexturesOnImplThread(
1155 layer_tree_host_impl_
->resource_provider());
1156 layer_tree_host_impl_
->EnableVSyncNotification(false);
1157 input_handler_on_impl_thread_
.reset();
1158 layer_tree_host_impl_
.reset();
1159 scheduler_on_impl_thread_
.reset();
1160 weak_factory_on_impl_thread_
.InvalidateWeakPtrs();
1161 vsync_client_
= NULL
;
1162 completion
->Signal();
1165 void ThreadProxy::SetViewportDamageOnImplThread(const gfx::Rect
& damage_rect
) {
1166 DCHECK(IsImplThread());
1167 layer_tree_host_impl_
->SetViewportDamage(damage_rect
);
1170 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1171 return ResourceUpdateController::MaxPartialTextureUpdates();
1174 void ThreadProxy::RecreateOutputSurfaceOnImplThread(
1175 CompletionEvent
* completion
,
1176 scoped_ptr
<OutputSurface
> output_surface
,
1177 scoped_refptr
<cc::ContextProvider
> offscreen_context_provider
,
1178 bool* recreate_succeeded
,
1179 RendererCapabilities
* capabilities
) {
1180 TRACE_EVENT0("cc", "ThreadProxy::RecreateOutputSurfaceOnImplThread");
1181 DCHECK(IsImplThread());
1183 layer_tree_host_
->DeleteContentsTexturesOnImplThread(
1184 layer_tree_host_impl_
->resource_provider());
1185 *recreate_succeeded
=
1186 layer_tree_host_impl_
->InitializeRenderer(output_surface
.Pass());
1187 if (offscreen_context_provider
)
1188 offscreen_context_provider
->BindToCurrentThread();
1190 if (*recreate_succeeded
) {
1191 *capabilities
= layer_tree_host_impl_
->GetRendererCapabilities();
1192 layer_tree_host_impl_
->resource_provider()->
1193 set_offscreen_context_provider(offscreen_context_provider
);
1194 scheduler_on_impl_thread_
->DidRecreateOutputSurface();
1195 } else if (offscreen_context_provider
) {
1196 offscreen_context_provider
->VerifyContexts();
1198 completion
->Signal();
1201 ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
1202 : memory_allocation_limit_bytes(0) {}
1204 ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {}
1206 scoped_ptr
<base::Value
> ThreadProxy::AsValue() const {
1207 scoped_ptr
<base::DictionaryValue
> state(new base::DictionaryValue());
1209 CompletionEvent completion
;
1211 DebugScopedSetMainThreadBlocked
main_thread_blocked(
1212 const_cast<ThreadProxy
*>(this));
1213 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::AsValueOnImplThread
,
1214 impl_thread_weak_ptr_
,
1219 return state
.PassAs
<base::Value
>();
1222 void ThreadProxy::AsValueOnImplThread(CompletionEvent
* completion
,
1223 base::DictionaryValue
* state
) const {
1224 state
->Set("layer_tree_host_impl",
1225 layer_tree_host_impl_
->AsValue().release());
1226 completion
->Signal();
1229 bool ThreadProxy::CommitPendingForTesting() {
1230 DCHECK(IsMainThread());
1231 CommitPendingRequest commit_pending_request
;
1233 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1234 Proxy::ImplThread()->PostTask(
1235 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting
,
1236 impl_thread_weak_ptr_
,
1237 &commit_pending_request
));
1238 commit_pending_request
.completion
.Wait();
1240 return commit_pending_request
.commit_pending
;
1243 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1244 CommitPendingRequest
* request
) {
1245 DCHECK(IsImplThread());
1246 if (layer_tree_host_impl_
->output_surface())
1247 request
->commit_pending
= scheduler_on_impl_thread_
->CommitPending();
1249 request
->commit_pending
= false;
1250 request
->completion
.Signal();
1253 skia::RefPtr
<SkPicture
> ThreadProxy::CapturePicture() {
1254 DCHECK(IsMainThread());
1255 CompletionEvent completion
;
1256 skia::RefPtr
<SkPicture
> picture
;
1258 DebugScopedSetMainThreadBlocked
main_thread_blocked(this);
1259 Proxy::ImplThread()->PostTask(
1260 base::Bind(&ThreadProxy::CapturePictureOnImplThread
,
1261 impl_thread_weak_ptr_
,
1269 void ThreadProxy::CapturePictureOnImplThread(CompletionEvent
* completion
,
1270 skia::RefPtr
<SkPicture
>* picture
) {
1271 DCHECK(IsImplThread());
1272 *picture
= layer_tree_host_impl_
->CapturePicture();
1273 completion
->Signal();
1276 void ThreadProxy::RenewTreePriority() {
1277 bool smoothness_takes_priority
=
1278 layer_tree_host_impl_
->pinch_gesture_active() ||
1279 layer_tree_host_impl_
->CurrentlyScrollingLayer() ||
1280 layer_tree_host_impl_
->page_scale_animation_active();
1282 // Update expiration time if smoothness currently takes priority.
1283 if (smoothness_takes_priority
) {
1284 smoothness_takes_priority_expiration_time_
=
1285 base::TimeTicks::Now() +
1286 base::TimeDelta::FromMilliseconds(
1287 kSmoothnessTakesPriorityExpirationDelay
* 1000);
1290 // We use the same priority for both trees by default.
1291 TreePriority priority
= SAME_PRIORITY_FOR_BOTH_TREES
;
1293 // Smoothness takes priority if expiration time is in the future.
1294 if (smoothness_takes_priority_expiration_time_
> base::TimeTicks::Now())
1295 priority
= SMOOTHNESS_TAKES_PRIORITY
;
1297 // New content always takes priority when the active tree has
1298 // evicted resources or there is an invalid viewport size.
1299 if (layer_tree_host_impl_
->active_tree()->ContentsTexturesPurged() ||
1300 layer_tree_host_impl_
->active_tree()->ViewportSizeInvalid())
1301 priority
= NEW_CONTENT_TAKES_PRIORITY
;
1303 layer_tree_host_impl_
->SetTreePriority(priority
);
1305 // Notify the the client of this compositor via the output surface.
1306 // TODO(epenner): Route this to compositor-thread instead of output-surface
1307 // after GTFO refactor of compositor-thread (http://crbug/170828).
1308 if (layer_tree_host_impl_
->output_surface()) {
1309 layer_tree_host_impl_
->output_surface()->
1310 UpdateSmoothnessTakesPriority(priority
== SMOOTHNESS_TAKES_PRIORITY
);
1313 base::TimeDelta delay
=
1314 smoothness_takes_priority_expiration_time_
- base::TimeTicks::Now();
1316 // Need to make sure a delayed task is posted when we have smoothness
1317 // takes priority expiration time in the future.
1318 if (delay
<= base::TimeDelta())
1320 if (renew_tree_priority_on_impl_thread_pending_
)
1323 Proxy::ImplThread()->PostDelayedTask(
1324 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread
,
1325 weak_factory_on_impl_thread_
.GetWeakPtr()),
1328 renew_tree_priority_on_impl_thread_pending_
= true;
1331 void ThreadProxy::RenewTreePriorityOnImplThread() {
1332 DCHECK(renew_tree_priority_on_impl_thread_pending_
);
1333 renew_tree_priority_on_impl_thread_pending_
= false;
1335 RenewTreePriority();
1338 void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay
) {
1339 Proxy::ImplThread()->PostDelayedTask(
1340 base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread
,
1341 impl_thread_weak_ptr_
),
1345 void ThreadProxy::StartScrollbarAnimationOnImplThread() {
1346 layer_tree_host_impl_
->StartScrollbarAnimation(base::TimeTicks::Now());