Factor out a BluetoothChannelMac base class and a BluetoothRfcommChannelMac subclass.
[chromium-blink-merge.git] / cc / trees / thread_proxy.cc
blobf14e38b92f41602c0f22f46bf9991a29725ee8ac
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 <algorithm>
8 #include <string>
10 #include "base/auto_reset.h"
11 #include "base/bind.h"
12 #include "base/debug/trace_event.h"
13 #include "base/debug/trace_event_synthetic_delay.h"
14 #include "base/metrics/histogram.h"
15 #include "cc/base/swap_promise.h"
16 #include "cc/debug/benchmark_instrumentation.h"
17 #include "cc/debug/devtools_instrumentation.h"
18 #include "cc/input/input_handler.h"
19 #include "cc/output/context_provider.h"
20 #include "cc/output/output_surface.h"
21 #include "cc/quads/draw_quad.h"
22 #include "cc/resources/prioritized_resource_manager.h"
23 #include "cc/scheduler/delay_based_time_source.h"
24 #include "cc/scheduler/scheduler.h"
25 #include "cc/trees/blocking_task_runner.h"
26 #include "cc/trees/layer_tree_host.h"
27 #include "cc/trees/layer_tree_impl.h"
28 #include "ui/gfx/frame_time.h"
30 namespace {
32 // Measured in seconds.
33 const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
35 class SwapPromiseChecker {
36 public:
37 explicit SwapPromiseChecker(cc::LayerTreeHost* layer_tree_host)
38 : layer_tree_host_(layer_tree_host) {}
40 ~SwapPromiseChecker() {
41 layer_tree_host_->BreakSwapPromises(cc::SwapPromise::COMMIT_FAILS);
44 private:
45 cc::LayerTreeHost* layer_tree_host_;
48 } // namespace
50 namespace cc {
52 struct ThreadProxy::CommitPendingRequest {
53 CompletionEvent completion;
54 bool commit_pending;
57 struct ThreadProxy::SchedulerStateRequest {
58 CompletionEvent completion;
59 scoped_ptr<base::Value> state;
62 scoped_ptr<Proxy> ThreadProxy::Create(
63 LayerTreeHost* layer_tree_host,
64 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
65 return make_scoped_ptr(new ThreadProxy(layer_tree_host, impl_task_runner))
66 .PassAs<Proxy>();
69 ThreadProxy::ThreadProxy(
70 LayerTreeHost* layer_tree_host,
71 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
72 : Proxy(impl_task_runner),
73 main_thread_only_vars_unsafe_(this, layer_tree_host->id()),
74 main_thread_or_blocked_vars_unsafe_(layer_tree_host),
75 compositor_thread_vars_unsafe_(this, layer_tree_host->id()) {
76 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
77 DCHECK(IsMainThread());
78 DCHECK(this->layer_tree_host());
81 ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy,
82 int layer_tree_host_id)
83 : layer_tree_host_id(layer_tree_host_id),
84 animate_requested(false),
85 commit_requested(false),
86 commit_request_sent_to_impl_thread(false),
87 started(false),
88 manage_tiles_pending(false),
89 can_cancel_commit(true),
90 defer_commits(false),
91 weak_factory(proxy) {}
93 ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
95 ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread(
96 LayerTreeHost* host)
97 : layer_tree_host(host),
98 commit_waits_for_activation(false),
99 main_thread_inside_commit(false) {}
101 ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {}
103 PrioritizedResourceManager*
104 ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() {
105 return layer_tree_host->contents_texture_manager();
108 ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(ThreadProxy* proxy,
109 int layer_tree_host_id)
110 : layer_tree_host_id(layer_tree_host_id),
111 contents_texture_manager(NULL),
112 commit_completion_event(NULL),
113 completion_event_for_commit_held_on_tree_activation(NULL),
114 next_frame_is_newly_committed_frame(false),
115 inside_draw(false),
116 input_throttled_until_commit(false),
117 animations_frozen_until_next_draw(false),
118 did_commit_after_animating(false),
119 smoothness_priority_expiration_notifier(
120 proxy->ImplThreadTaskRunner(),
121 base::Bind(&ThreadProxy::RenewTreePriority, base::Unretained(proxy)),
122 base::TimeDelta::FromMilliseconds(
123 kSmoothnessTakesPriorityExpirationDelay * 1000)),
124 weak_factory(proxy) {
127 ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
129 ThreadProxy::~ThreadProxy() {
130 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
131 DCHECK(IsMainThread());
132 DCHECK(!main().started);
135 void ThreadProxy::FinishAllRendering() {
136 DCHECK(Proxy::IsMainThread());
137 DCHECK(!main().defer_commits);
139 // Make sure all GL drawing is finished on the impl thread.
140 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
141 CompletionEvent completion;
142 Proxy::ImplThreadTaskRunner()->PostTask(
143 FROM_HERE,
144 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread,
145 impl_thread_weak_ptr_,
146 &completion));
147 completion.Wait();
150 bool ThreadProxy::IsStarted() const {
151 DCHECK(Proxy::IsMainThread());
152 return main().started;
155 void ThreadProxy::SetLayerTreeHostClientReady() {
156 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
157 Proxy::ImplThreadTaskRunner()->PostTask(
158 FROM_HERE,
159 base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread,
160 impl_thread_weak_ptr_));
163 void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
164 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
165 impl().scheduler->SetCanStart();
168 void ThreadProxy::SetVisible(bool visible) {
169 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
170 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
172 CompletionEvent completion;
173 Proxy::ImplThreadTaskRunner()->PostTask(
174 FROM_HERE,
175 base::Bind(&ThreadProxy::SetVisibleOnImplThread,
176 impl_thread_weak_ptr_,
177 &completion,
178 visible));
179 completion.Wait();
182 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
183 bool visible) {
184 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
185 impl().layer_tree_host_impl->SetVisible(visible);
186 impl().scheduler->SetVisible(visible);
187 UpdateBackgroundAnimateTicking();
188 completion->Signal();
191 void ThreadProxy::UpdateBackgroundAnimateTicking() {
192 bool should_background_tick =
193 !impl().scheduler->WillDrawIfNeeded() &&
194 impl().layer_tree_host_impl->active_tree()->root_layer();
195 impl().layer_tree_host_impl->UpdateBackgroundAnimateTicking(
196 should_background_tick);
197 if (should_background_tick)
198 impl().animations_frozen_until_next_draw = false;
201 void ThreadProxy::DoCreateAndInitializeOutputSurface() {
202 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface");
203 DCHECK(IsMainThread());
205 scoped_ptr<OutputSurface> output_surface =
206 layer_tree_host()->CreateOutputSurface();
208 RendererCapabilities capabilities;
209 bool success = !!output_surface;
210 if (success) {
211 // Make a blocking call to InitializeOutputSurfaceOnImplThread. The results
212 // of that call are pushed into the success and capabilities local
213 // variables.
214 CompletionEvent completion;
215 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
217 Proxy::ImplThreadTaskRunner()->PostTask(
218 FROM_HERE,
219 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
220 impl_thread_weak_ptr_,
221 &completion,
222 base::Passed(&output_surface),
223 &success,
224 &capabilities));
225 completion.Wait();
227 main().renderer_capabilities_main_thread_copy = capabilities;
228 layer_tree_host()->OnCreateAndInitializeOutputSurfaceAttempted(success);
230 if (success) {
231 main().output_surface_creation_callback.Cancel();
232 } else if (!main().output_surface_creation_callback.IsCancelled()) {
233 Proxy::MainThreadTaskRunner()->PostTask(
234 FROM_HERE, main().output_surface_creation_callback.callback());
238 void ThreadProxy::SetRendererCapabilitiesMainThreadCopy(
239 const RendererCapabilities& capabilities) {
240 main().renderer_capabilities_main_thread_copy = capabilities;
243 void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
244 DCHECK(IsMainThread());
245 if (main().commit_request_sent_to_impl_thread)
246 return;
247 main().commit_request_sent_to_impl_thread = true;
248 Proxy::ImplThreadTaskRunner()->PostTask(
249 FROM_HERE,
250 base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread,
251 impl_thread_weak_ptr_));
254 const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
255 DCHECK(IsMainThread());
256 DCHECK(!layer_tree_host()->output_surface_lost());
257 return main().renderer_capabilities_main_thread_copy;
260 void ThreadProxy::SetNeedsAnimate() {
261 DCHECK(IsMainThread());
262 if (main().animate_requested)
263 return;
265 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
266 main().animate_requested = true;
267 SendCommitRequestToImplThreadIfNeeded();
270 void ThreadProxy::SetNeedsUpdateLayers() {
271 DCHECK(IsMainThread());
273 if (main().commit_request_sent_to_impl_thread)
274 return;
275 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers");
277 SendCommitRequestToImplThreadIfNeeded();
280 void ThreadProxy::SetNeedsCommit() {
281 DCHECK(IsMainThread());
282 // Unconditionally set here to handle SetNeedsCommit calls during a commit.
283 main().can_cancel_commit = false;
285 if (main().commit_requested)
286 return;
287 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
288 main().commit_requested = true;
290 SendCommitRequestToImplThreadIfNeeded();
293 void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
294 DCHECK(IsImplThread());
295 Proxy::MainThreadTaskRunner()->PostTask(
296 FROM_HERE,
297 base::Bind(&ThreadProxy::SetRendererCapabilitiesMainThreadCopy,
298 main_thread_weak_ptr_,
299 impl()
300 .layer_tree_host_impl->GetRendererCapabilities()
301 .MainThreadCapabilities()));
304 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
305 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
306 DCHECK(IsImplThread());
307 CheckOutputSurfaceStatusOnImplThread();
310 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
311 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
312 DCHECK(IsImplThread());
313 if (!impl().layer_tree_host_impl->IsContextLost())
314 return;
315 impl().scheduler->DidLoseOutputSurface();
318 void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
319 base::TimeDelta interval) {
320 impl().scheduler->CommitVSyncParameters(timebase, interval);
323 void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
324 impl().scheduler->SetEstimatedParentDrawTime(draw_time);
327 void ThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
328 impl().scheduler->SetMaxSwapsPending(max);
331 void ThreadProxy::DidSwapBuffersOnImplThread() {
332 impl().scheduler->DidSwapBuffers();
335 void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
336 TRACE_EVENT0("cc", "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
337 DCHECK(IsImplThread());
338 impl().scheduler->DidSwapBuffersComplete();
339 Proxy::MainThreadTaskRunner()->PostTask(
340 FROM_HERE,
341 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
344 void ThreadProxy::SetNeedsBeginFrame(bool enable) {
345 TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrame", "enable", enable);
346 impl().layer_tree_host_impl->SetNeedsBeginFrame(enable);
347 UpdateBackgroundAnimateTicking();
350 void ThreadProxy::BeginFrame(const BeginFrameArgs& args) {
351 impl().scheduler->BeginFrame(args);
354 void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
355 impl().layer_tree_host_impl->WillBeginImplFrame(args);
358 void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
359 TRACE_EVENT1(
360 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
361 DCHECK(IsImplThread());
362 impl().scheduler->SetCanDraw(can_draw);
363 UpdateBackgroundAnimateTicking();
366 void ThreadProxy::NotifyReadyToActivate() {
367 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
368 impl().scheduler->NotifyReadyToActivate();
371 void ThreadProxy::SetNeedsCommitOnImplThread() {
372 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
373 DCHECK(IsImplThread());
374 impl().scheduler->SetNeedsCommit();
377 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
378 scoped_ptr<AnimationEventsVector> events) {
379 TRACE_EVENT0("cc",
380 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
381 DCHECK(IsImplThread());
382 Proxy::MainThreadTaskRunner()->PostTask(
383 FROM_HERE,
384 base::Bind(&ThreadProxy::SetAnimationEvents,
385 main_thread_weak_ptr_,
386 base::Passed(&events)));
389 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
390 int priority_cutoff) {
391 DCHECK(IsImplThread());
393 if (!impl().contents_texture_manager)
394 return false;
395 if (!impl().layer_tree_host_impl->resource_provider())
396 return false;
398 bool reduce_result =
399 impl().contents_texture_manager->ReduceMemoryOnImplThread(
400 limit_bytes,
401 priority_cutoff,
402 impl().layer_tree_host_impl->resource_provider());
403 if (!reduce_result)
404 return false;
406 // The texture upload queue may reference textures that were just purged,
407 // clear them from the queue.
408 if (impl().current_resource_update_controller) {
409 impl()
410 .current_resource_update_controller->DiscardUploadsToEvictedResources();
412 return true;
415 void ThreadProxy::SendManagedMemoryStats() {
416 DCHECK(IsImplThread());
417 if (!impl().layer_tree_host_impl)
418 return;
419 if (!impl().contents_texture_manager)
420 return;
422 // If we are using impl-side painting, then SendManagedMemoryStats is called
423 // directly after the tile manager's manage function, and doesn't need to
424 // interact with main thread's layer tree.
425 if (impl().layer_tree_host_impl->settings().impl_side_painting)
426 return;
428 impl().layer_tree_host_impl->SendManagedMemoryStats(
429 impl().contents_texture_manager->MemoryVisibleBytes(),
430 impl().contents_texture_manager->MemoryVisibleAndNearbyBytes(),
431 impl().contents_texture_manager->MemoryUseBytes());
434 bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; }
436 void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
437 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
438 DCHECK(IsMainThread());
439 Proxy::ImplThreadTaskRunner()->PostTask(
440 FROM_HERE,
441 base::Bind(&ThreadProxy::SetNeedsRedrawRectOnImplThread,
442 impl_thread_weak_ptr_,
443 damage_rect));
446 void ThreadProxy::SetNextCommitWaitsForActivation() {
447 DCHECK(IsMainThread());
448 DCHECK(!blocked_main().main_thread_inside_commit);
449 blocked_main().commit_waits_for_activation = true;
452 void ThreadProxy::SetDeferCommits(bool defer_commits) {
453 DCHECK(IsMainThread());
454 DCHECK_NE(main().defer_commits, defer_commits);
455 main().defer_commits = defer_commits;
457 if (main().defer_commits)
458 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
459 else
460 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
462 if (!main().defer_commits && main().pending_deferred_commit)
463 Proxy::MainThreadTaskRunner()->PostTask(
464 FROM_HERE,
465 base::Bind(&ThreadProxy::BeginMainFrame,
466 main_thread_weak_ptr_,
467 base::Passed(&main().pending_deferred_commit)));
470 bool ThreadProxy::CommitRequested() const {
471 DCHECK(IsMainThread());
472 return main().commit_requested;
475 bool ThreadProxy::BeginMainFrameRequested() const {
476 DCHECK(IsMainThread());
477 return main().commit_request_sent_to_impl_thread;
480 void ThreadProxy::SetNeedsRedrawOnImplThread() {
481 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
482 DCHECK(IsImplThread());
483 impl().scheduler->SetNeedsRedraw();
486 void ThreadProxy::SetNeedsAnimateOnImplThread() {
487 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimateOnImplThread");
488 DCHECK(IsImplThread());
489 impl().scheduler->SetNeedsAnimate();
492 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
493 DCHECK(IsImplThread());
494 impl().scheduler->SetNeedsManageTiles();
497 void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
498 DCHECK(IsImplThread());
499 impl().layer_tree_host_impl->SetViewportDamage(damage_rect);
500 SetNeedsRedrawOnImplThread();
503 void ThreadProxy::SetSwapUsedIncompleteTileOnImplThread(
504 bool used_incomplete_tile) {
505 DCHECK(IsImplThread());
506 if (used_incomplete_tile) {
507 TRACE_EVENT_INSTANT0("cc",
508 "ThreadProxy::SetSwapUsedIncompleteTileOnImplThread",
509 TRACE_EVENT_SCOPE_THREAD);
511 impl().scheduler->SetSwapUsedIncompleteTile(used_incomplete_tile);
514 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
515 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
516 DCHECK(IsImplThread());
517 impl().scheduler->SetNeedsRedraw();
520 void ThreadProxy::MainThreadHasStoppedFlinging() {
521 DCHECK(IsMainThread());
522 Proxy::ImplThreadTaskRunner()->PostTask(
523 FROM_HERE,
524 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread,
525 impl_thread_weak_ptr_));
528 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
529 DCHECK(IsImplThread());
530 impl().layer_tree_host_impl->MainThreadHasStoppedFlinging();
533 void ThreadProxy::NotifyInputThrottledUntilCommit() {
534 DCHECK(IsMainThread());
535 Proxy::ImplThreadTaskRunner()->PostTask(
536 FROM_HERE,
537 base::Bind(&ThreadProxy::SetInputThrottledUntilCommitOnImplThread,
538 impl_thread_weak_ptr_,
539 true));
542 void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(bool is_throttled) {
543 DCHECK(IsImplThread());
544 if (is_throttled == impl().input_throttled_until_commit)
545 return;
546 impl().input_throttled_until_commit = is_throttled;
547 RenewTreePriority();
550 LayerTreeHost* ThreadProxy::layer_tree_host() {
551 return blocked_main().layer_tree_host;
554 const LayerTreeHost* ThreadProxy::layer_tree_host() const {
555 return blocked_main().layer_tree_host;
558 ThreadProxy::MainThreadOnly& ThreadProxy::main() {
559 DCHECK(IsMainThread());
560 return main_thread_only_vars_unsafe_;
562 const ThreadProxy::MainThreadOnly& ThreadProxy::main() const {
563 DCHECK(IsMainThread());
564 return main_thread_only_vars_unsafe_;
567 ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() {
568 DCHECK(IsMainThread() || IsMainThreadBlocked());
569 return main_thread_or_blocked_vars_unsafe_;
572 const ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main()
573 const {
574 DCHECK(IsMainThread() || IsMainThreadBlocked());
575 return main_thread_or_blocked_vars_unsafe_;
578 ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() {
579 DCHECK(IsImplThread());
580 return compositor_thread_vars_unsafe_;
583 const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const {
584 DCHECK(IsImplThread());
585 return compositor_thread_vars_unsafe_;
588 void ThreadProxy::Start() {
589 DCHECK(IsMainThread());
590 DCHECK(Proxy::HasImplThread());
592 // Create LayerTreeHostImpl.
593 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
594 CompletionEvent completion;
595 Proxy::ImplThreadTaskRunner()->PostTask(
596 FROM_HERE,
597 base::Bind(&ThreadProxy::InitializeImplOnImplThread,
598 base::Unretained(this),
599 &completion));
600 completion.Wait();
602 main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr();
604 main().started = true;
607 void ThreadProxy::Stop() {
608 TRACE_EVENT0("cc", "ThreadProxy::Stop");
609 DCHECK(IsMainThread());
610 DCHECK(main().started);
612 // Synchronously finishes pending GL operations and deletes the impl.
613 // The two steps are done as separate post tasks, so that tasks posted
614 // by the GL implementation due to the Finish can be executed by the
615 // renderer before shutting it down.
617 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
619 CompletionEvent completion;
620 Proxy::ImplThreadTaskRunner()->PostTask(
621 FROM_HERE,
622 base::Bind(&ThreadProxy::FinishGLOnImplThread,
623 impl_thread_weak_ptr_,
624 &completion));
625 completion.Wait();
628 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
630 CompletionEvent completion;
631 Proxy::ImplThreadTaskRunner()->PostTask(
632 FROM_HERE,
633 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread,
634 impl_thread_weak_ptr_,
635 &completion));
636 completion.Wait();
639 main().weak_factory.InvalidateWeakPtrs();
640 blocked_main().layer_tree_host = NULL;
641 main().started = false;
644 void ThreadProxy::ForceSerializeOnSwapBuffers() {
645 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
646 CompletionEvent completion;
647 Proxy::ImplThreadTaskRunner()->PostTask(
648 FROM_HERE,
649 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
650 impl_thread_weak_ptr_,
651 &completion));
652 completion.Wait();
655 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
656 CompletionEvent* completion) {
657 if (impl().layer_tree_host_impl->renderer())
658 impl().layer_tree_host_impl->renderer()->DoNoOp();
659 completion->Signal();
662 void ThreadProxy::SetDebugState(const LayerTreeDebugState& debug_state) {
663 Proxy::ImplThreadTaskRunner()->PostTask(
664 FROM_HERE,
665 base::Bind(&ThreadProxy::SetDebugStateOnImplThread,
666 impl_thread_weak_ptr_,
667 debug_state));
670 void ThreadProxy::SetDebugStateOnImplThread(
671 const LayerTreeDebugState& debug_state) {
672 DCHECK(IsImplThread());
673 impl().scheduler->SetContinuousPainting(debug_state.continuous_painting);
676 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
677 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
678 DCHECK(IsImplThread());
679 impl().layer_tree_host_impl->FinishAllRendering();
680 completion->Signal();
683 void ThreadProxy::ScheduledActionSendBeginMainFrame() {
684 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginMainFrame");
685 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
686 new BeginMainFrameAndCommitState);
687 begin_main_frame_state->monotonic_frame_begin_time =
688 impl().layer_tree_host_impl->CurrentFrameTimeTicks();
689 begin_main_frame_state->scroll_info =
690 impl().layer_tree_host_impl->ProcessScrollDeltas();
692 if (!impl().layer_tree_host_impl->settings().impl_side_painting) {
693 DCHECK_GT(impl().layer_tree_host_impl->memory_allocation_limit_bytes(), 0u);
695 begin_main_frame_state->memory_allocation_limit_bytes =
696 impl().layer_tree_host_impl->memory_allocation_limit_bytes();
697 begin_main_frame_state->memory_allocation_priority_cutoff =
698 impl().layer_tree_host_impl->memory_allocation_priority_cutoff();
699 begin_main_frame_state->evicted_ui_resources =
700 impl().layer_tree_host_impl->EvictedUIResourcesExist();
701 Proxy::MainThreadTaskRunner()->PostTask(
702 FROM_HERE,
703 base::Bind(&ThreadProxy::BeginMainFrame,
704 main_thread_weak_ptr_,
705 base::Passed(&begin_main_frame_state)));
706 devtools_instrumentation::DidRequestMainThreadFrame(
707 impl().layer_tree_host_id);
708 impl().timing_history.DidBeginMainFrame();
711 void ThreadProxy::BeginMainFrame(
712 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
713 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame");
714 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
715 DCHECK(IsMainThread());
717 if (main().defer_commits) {
718 main().pending_deferred_commit = begin_main_frame_state.Pass();
719 layer_tree_host()->DidDeferCommit();
720 TRACE_EVENT_INSTANT0(
721 "cc", "EarlyOut_DeferCommits", TRACE_EVENT_SCOPE_THREAD);
722 return;
725 // If the commit finishes, LayerTreeHost will transfer its swap promises to
726 // LayerTreeImpl. The destructor of SwapPromiseChecker checks LayerTressHost's
727 // swap promises.
728 SwapPromiseChecker swap_promise_checker(layer_tree_host());
730 // Do not notify the impl thread of commit requests that occur during
731 // the apply/animate/layout part of the BeginMainFrameAndCommit process since
732 // those commit requests will get painted immediately. Once we have done
733 // the paint, main().commit_requested will be set to false to allow new commit
734 // requests to be scheduled.
735 main().commit_requested = true;
736 main().commit_request_sent_to_impl_thread = true;
738 // On the other hand, the AnimationRequested flag needs to be cleared
739 // here so that any animation requests generated by the apply or animate
740 // callbacks will trigger another frame.
741 main().animate_requested = false;
743 if (!layer_tree_host()->visible()) {
744 main().commit_requested = false;
745 main().commit_request_sent_to_impl_thread = false;
747 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
748 bool did_handle = false;
749 Proxy::ImplThreadTaskRunner()->PostTask(
750 FROM_HERE,
751 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
752 impl_thread_weak_ptr_,
753 did_handle));
754 return;
757 layer_tree_host()->ApplyScrollAndScale(*begin_main_frame_state->scroll_info);
759 layer_tree_host()->WillBeginMainFrame();
761 layer_tree_host()->UpdateClientAnimations(
762 begin_main_frame_state->monotonic_frame_begin_time);
763 layer_tree_host()->AnimateLayers(
764 begin_main_frame_state->monotonic_frame_begin_time);
765 blocked_main().last_monotonic_frame_begin_time =
766 begin_main_frame_state->monotonic_frame_begin_time;
768 // Unlink any backings that the impl thread has evicted, so that we know to
769 // re-paint them in UpdateLayers.
770 if (blocked_main().contents_texture_manager()) {
771 blocked_main().contents_texture_manager()->UnlinkAndClearEvictedBackings();
773 blocked_main().contents_texture_manager()->SetMaxMemoryLimitBytes(
774 begin_main_frame_state->memory_allocation_limit_bytes);
775 blocked_main().contents_texture_manager()->SetExternalPriorityCutoff(
776 begin_main_frame_state->memory_allocation_priority_cutoff);
779 // Recreate all UI resources if there were evicted UI resources when the impl
780 // thread initiated the commit.
781 if (begin_main_frame_state->evicted_ui_resources)
782 layer_tree_host()->RecreateUIResources();
784 layer_tree_host()->Layout();
785 TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
787 // Clear the commit flag after updating animations and layout here --- objects
788 // that only layout when painted will trigger another SetNeedsCommit inside
789 // UpdateLayers.
790 main().commit_requested = false;
791 main().commit_request_sent_to_impl_thread = false;
792 bool can_cancel_this_commit =
793 main().can_cancel_commit && !begin_main_frame_state->evicted_ui_resources;
794 main().can_cancel_commit = true;
796 scoped_ptr<ResourceUpdateQueue> queue =
797 make_scoped_ptr(new ResourceUpdateQueue);
799 bool updated = layer_tree_host()->UpdateLayers(queue.get());
801 layer_tree_host()->WillCommit();
803 // Before calling animate, we set main().animate_requested to false. If it is
804 // true now, it means SetNeedAnimate was called again, but during a state when
805 // main().commit_request_sent_to_impl_thread = true. We need to force that
806 // call to happen again now so that the commit request is sent to the impl
807 // thread.
808 if (main().animate_requested) {
809 // Forces SetNeedsAnimate to consider posting a commit task.
810 main().animate_requested = false;
811 SetNeedsAnimate();
814 if (!updated && can_cancel_this_commit) {
815 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
816 bool did_handle = true;
817 Proxy::ImplThreadTaskRunner()->PostTask(
818 FROM_HERE,
819 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
820 impl_thread_weak_ptr_,
821 did_handle));
823 // Although the commit is internally aborted, this is because it has been
824 // detected to be a no-op. From the perspective of an embedder, this commit
825 // went through, and input should no longer be throttled, etc.
826 layer_tree_host()->CommitComplete();
827 layer_tree_host()->DidBeginMainFrame();
828 return;
831 // Notify the impl thread that the main thread is ready to commit. This will
832 // begin the commit process, which is blocking from the main thread's
833 // point of view, but asynchronously performed on the impl thread,
834 // coordinated by the Scheduler.
836 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
838 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
840 // This CapturePostTasks should be destroyed before CommitComplete() is
841 // called since that goes out to the embedder, and we want the embedder
842 // to receive its callbacks before that.
843 BlockingTaskRunner::CapturePostTasks blocked;
845 CompletionEvent completion;
846 Proxy::ImplThreadTaskRunner()->PostTask(
847 FROM_HERE,
848 base::Bind(&ThreadProxy::StartCommitOnImplThread,
849 impl_thread_weak_ptr_,
850 &completion,
851 queue.release()));
852 completion.Wait();
854 RenderingStatsInstrumentation* stats_instrumentation =
855 layer_tree_host()->rendering_stats_instrumentation();
856 BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
857 stats_instrumentation->main_thread_rendering_stats());
858 stats_instrumentation->AccumulateAndClearMainThreadStats();
861 layer_tree_host()->CommitComplete();
862 layer_tree_host()->DidBeginMainFrame();
865 void ThreadProxy::StartCommitOnImplThread(CompletionEvent* completion,
866 ResourceUpdateQueue* raw_queue) {
867 TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
868 DCHECK(!impl().commit_completion_event);
869 DCHECK(IsImplThread() && IsMainThreadBlocked());
870 DCHECK(impl().scheduler);
871 DCHECK(impl().scheduler->CommitPending());
873 if (!impl().layer_tree_host_impl) {
874 TRACE_EVENT_INSTANT0(
875 "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD);
876 completion->Signal();
877 return;
880 // Ideally, we should inform to impl thread when BeginMainFrame is started.
881 // But, we can avoid a PostTask in here.
882 impl().scheduler->NotifyBeginMainFrameStarted();
884 scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
886 if (impl().contents_texture_manager) {
887 DCHECK_EQ(impl().contents_texture_manager,
888 blocked_main().contents_texture_manager());
889 } else {
890 // Cache this pointer that was created on the main thread side to avoid a
891 // data race between creating it and using it on the compositor thread.
892 impl().contents_texture_manager = blocked_main().contents_texture_manager();
895 if (impl().contents_texture_manager) {
896 if (impl().contents_texture_manager->LinkedEvictedBackingsExist()) {
897 // Clear any uploads we were making to textures linked to evicted
898 // resources
899 queue->ClearUploadsToEvictedResources();
900 // Some textures in the layer tree are invalid. Kick off another commit
901 // to fill them again.
902 SetNeedsCommitOnImplThread();
905 impl().contents_texture_manager->PushTexturePrioritiesToBackings();
908 impl().commit_completion_event = completion;
909 impl().current_resource_update_controller = ResourceUpdateController::Create(
910 this,
911 Proxy::ImplThreadTaskRunner(),
912 queue.Pass(),
913 impl().layer_tree_host_impl->resource_provider());
914 impl().current_resource_update_controller->PerformMoreUpdates(
915 impl().scheduler->AnticipatedDrawTime());
918 void ThreadProxy::BeginMainFrameAbortedOnImplThread(bool did_handle) {
919 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread");
920 DCHECK(IsImplThread());
921 DCHECK(impl().scheduler);
922 DCHECK(impl().scheduler->CommitPending());
923 DCHECK(!impl().layer_tree_host_impl->pending_tree());
925 if (did_handle)
926 SetInputThrottledUntilCommitOnImplThread(false);
927 impl().layer_tree_host_impl->BeginMainFrameAborted(did_handle);
928 impl().scheduler->BeginMainFrameAborted(did_handle);
931 void ThreadProxy::ScheduledActionAnimate() {
932 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionAnimate");
933 DCHECK(IsImplThread());
935 if (!impl().animations_frozen_until_next_draw) {
936 impl().animation_time =
937 impl().layer_tree_host_impl->CurrentFrameTimeTicks();
939 impl().layer_tree_host_impl->Animate(impl().animation_time);
940 impl().did_commit_after_animating = false;
943 void ThreadProxy::ScheduledActionCommit() {
944 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
945 DCHECK(IsImplThread());
946 DCHECK(IsMainThreadBlocked());
947 DCHECK(impl().commit_completion_event);
948 DCHECK(impl().current_resource_update_controller);
950 // Complete all remaining texture updates.
951 impl().current_resource_update_controller->Finalize();
952 impl().current_resource_update_controller.reset();
954 if (impl().animations_frozen_until_next_draw) {
955 impl().animation_time = std::max(
956 impl().animation_time, blocked_main().last_monotonic_frame_begin_time);
958 impl().did_commit_after_animating = true;
960 blocked_main().main_thread_inside_commit = true;
961 impl().layer_tree_host_impl->BeginCommit();
962 layer_tree_host()->BeginCommitOnImplThread(impl().layer_tree_host_impl.get());
963 layer_tree_host()->FinishCommitOnImplThread(
964 impl().layer_tree_host_impl.get());
965 blocked_main().main_thread_inside_commit = false;
967 bool hold_commit = layer_tree_host()->settings().impl_side_painting &&
968 blocked_main().commit_waits_for_activation;
969 blocked_main().commit_waits_for_activation = false;
971 if (hold_commit) {
972 // For some layer types in impl-side painting, the commit is held until
973 // the pending tree is activated. It's also possible that the
974 // pending tree has already activated if there was no work to be done.
975 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
976 impl().completion_event_for_commit_held_on_tree_activation =
977 impl().commit_completion_event;
978 impl().commit_completion_event = NULL;
979 } else {
980 impl().commit_completion_event->Signal();
981 impl().commit_completion_event = NULL;
984 // Delay this step until afer the main thread has been released as it's
985 // often a good bit of work to update the tree and prepare the new frame.
986 impl().layer_tree_host_impl->CommitComplete();
988 SetInputThrottledUntilCommitOnImplThread(false);
990 UpdateBackgroundAnimateTicking();
992 impl().next_frame_is_newly_committed_frame = true;
994 impl().timing_history.DidCommit();
997 void ThreadProxy::ScheduledActionUpdateVisibleTiles() {
998 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles");
999 DCHECK(IsImplThread());
1000 impl().layer_tree_host_impl->UpdateVisibleTiles();
1003 void ThreadProxy::ScheduledActionActivatePendingTree() {
1004 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTree");
1005 DCHECK(IsImplThread());
1006 impl().layer_tree_host_impl->ActivatePendingTree();
1009 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
1010 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
1011 DCHECK(IsImplThread());
1012 Proxy::MainThreadTaskRunner()->PostTask(
1013 FROM_HERE,
1014 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface,
1015 main_thread_weak_ptr_));
1018 DrawResult ThreadProxy::DrawSwapInternal(bool forced_draw) {
1019 TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
1020 DrawResult result;
1022 DCHECK(IsImplThread());
1023 DCHECK(impl().layer_tree_host_impl.get());
1025 impl().timing_history.DidStartDrawing();
1026 base::TimeDelta draw_duration_estimate = DrawDurationEstimate();
1027 base::AutoReset<bool> mark_inside(&impl().inside_draw, true);
1029 if (impl().did_commit_after_animating) {
1030 impl().layer_tree_host_impl->Animate(impl().animation_time);
1031 impl().did_commit_after_animating = false;
1034 if (impl().layer_tree_host_impl->pending_tree())
1035 impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties();
1037 // This method is called on a forced draw, regardless of whether we are able
1038 // to produce a frame, as the calling site on main thread is blocked until its
1039 // request completes, and we signal completion here. If CanDraw() is false, we
1040 // will indicate success=false to the caller, but we must still signal
1041 // completion to avoid deadlock.
1043 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
1044 // frame, so can only be used when such a frame is possible. Since
1045 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
1046 // CanDraw() as well.
1048 LayerTreeHostImpl::FrameData frame;
1049 bool draw_frame = false;
1051 if (impl().layer_tree_host_impl->CanDraw()) {
1052 result = impl().layer_tree_host_impl->PrepareToDraw(&frame);
1053 draw_frame = forced_draw || result == DRAW_SUCCESS;
1054 } else {
1055 result = DRAW_ABORTED_CANT_DRAW;
1058 if (draw_frame) {
1059 impl().layer_tree_host_impl->DrawLayers(
1060 &frame, impl().scheduler->LastBeginImplFrameTime());
1061 result = DRAW_SUCCESS;
1062 impl().animations_frozen_until_next_draw = false;
1063 } else if (result == DRAW_ABORTED_CHECKERBOARD_ANIMATIONS &&
1064 !impl().layer_tree_host_impl->settings().impl_side_painting) {
1065 // Without impl-side painting, the animated layer that is checkerboarding
1066 // will continue to checkerboard until the next commit. If this layer
1067 // continues to move during the commit, it may continue to checkerboard
1068 // after the commit since the region rasterized during the commit will not
1069 // match the region that is currently visible; eventually this
1070 // checkerboarding will be displayed when we force a draw. To avoid this,
1071 // we freeze animations until we successfully draw.
1072 impl().animations_frozen_until_next_draw = true;
1073 } else {
1074 DCHECK_NE(DRAW_SUCCESS, result);
1076 impl().layer_tree_host_impl->DidDrawAllLayers(frame);
1078 bool start_ready_animations = draw_frame;
1079 impl().layer_tree_host_impl->UpdateAnimationState(start_ready_animations);
1081 if (draw_frame) {
1082 bool did_request_swap = impl().layer_tree_host_impl->SwapBuffers(frame);
1084 // We don't know if we have incomplete tiles if we didn't actually swap.
1085 if (did_request_swap) {
1086 DCHECK(!frame.has_no_damage);
1087 SetSwapUsedIncompleteTileOnImplThread(frame.contains_incomplete_tile);
1091 // Tell the main thread that the the newly-commited frame was drawn.
1092 if (impl().next_frame_is_newly_committed_frame) {
1093 impl().next_frame_is_newly_committed_frame = false;
1094 Proxy::MainThreadTaskRunner()->PostTask(
1095 FROM_HERE,
1096 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_));
1099 if (draw_frame)
1100 CheckOutputSurfaceStatusOnImplThread();
1102 if (result == DRAW_SUCCESS) {
1103 base::TimeDelta draw_duration = impl().timing_history.DidFinishDrawing();
1105 base::TimeDelta draw_duration_overestimate;
1106 base::TimeDelta draw_duration_underestimate;
1107 if (draw_duration > draw_duration_estimate)
1108 draw_duration_underestimate = draw_duration - draw_duration_estimate;
1109 else
1110 draw_duration_overestimate = draw_duration_estimate - draw_duration;
1111 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration",
1112 draw_duration,
1113 base::TimeDelta::FromMilliseconds(1),
1114 base::TimeDelta::FromMilliseconds(100),
1115 50);
1116 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate",
1117 draw_duration_underestimate,
1118 base::TimeDelta::FromMilliseconds(1),
1119 base::TimeDelta::FromMilliseconds(100),
1120 50);
1121 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate",
1122 draw_duration_overestimate,
1123 base::TimeDelta::FromMilliseconds(1),
1124 base::TimeDelta::FromMilliseconds(100),
1125 50);
1128 DCHECK_NE(INVALID_RESULT, result);
1129 return result;
1132 void ThreadProxy::ScheduledActionManageTiles() {
1133 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionManageTiles");
1134 DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting);
1135 impl().layer_tree_host_impl->ManageTiles();
1138 DrawResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1139 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
1141 // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
1142 // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should
1143 // never generate this call when it can't draw.
1144 DCHECK(impl().layer_tree_host_impl->CanDraw());
1146 bool forced_draw = false;
1147 return DrawSwapInternal(forced_draw);
1150 DrawResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
1151 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
1152 bool forced_draw = true;
1153 return DrawSwapInternal(forced_draw);
1156 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1157 if (impl().current_resource_update_controller)
1158 impl().current_resource_update_controller->PerformMoreUpdates(time);
1161 base::TimeDelta ThreadProxy::DrawDurationEstimate() {
1162 return impl().timing_history.DrawDurationEstimate();
1165 base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() {
1166 return impl().timing_history.BeginMainFrameToCommitDurationEstimate();
1169 base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() {
1170 return impl().timing_history.CommitToActivateDurationEstimate();
1173 void ThreadProxy::DidBeginImplFrameDeadline() {
1174 impl().layer_tree_host_impl->ResetCurrentFrameTimeForNextFrame();
1177 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1178 DCHECK(IsImplThread());
1179 impl().scheduler->NotifyReadyToCommit();
1182 void ThreadProxy::DidCommitAndDrawFrame() {
1183 DCHECK(IsMainThread());
1184 layer_tree_host()->DidCommitAndDrawFrame();
1187 void ThreadProxy::DidCompleteSwapBuffers() {
1188 DCHECK(IsMainThread());
1189 layer_tree_host()->DidCompleteSwapBuffers();
1192 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
1193 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1194 DCHECK(IsMainThread());
1195 layer_tree_host()->SetAnimationEvents(events.Pass());
1198 void ThreadProxy::CreateAndInitializeOutputSurface() {
1199 TRACE_EVENT0("cc", "ThreadProxy::CreateAndInitializeOutputSurface");
1200 DCHECK(IsMainThread());
1202 // Check that output surface has not been recreated by CompositeAndReadback
1203 // after this task is posted but before it is run.
1204 bool has_initialized_output_surface = true;
1206 CompletionEvent completion;
1207 Proxy::ImplThreadTaskRunner()->PostTask(
1208 FROM_HERE,
1209 base::Bind(&ThreadProxy::HasInitializedOutputSurfaceOnImplThread,
1210 impl_thread_weak_ptr_,
1211 &completion,
1212 &has_initialized_output_surface));
1213 completion.Wait();
1215 if (has_initialized_output_surface)
1216 return;
1218 layer_tree_host()->DidLoseOutputSurface();
1219 main().output_surface_creation_callback.Reset(
1220 base::Bind(&ThreadProxy::DoCreateAndInitializeOutputSurface,
1221 base::Unretained(this)));
1222 main().output_surface_creation_callback.callback().Run();
1225 void ThreadProxy::HasInitializedOutputSurfaceOnImplThread(
1226 CompletionEvent* completion,
1227 bool* has_initialized_output_surface) {
1228 DCHECK(IsImplThread());
1229 *has_initialized_output_surface =
1230 impl().scheduler->HasInitializedOutputSurface();
1231 completion->Signal();
1234 void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
1235 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1236 DCHECK(IsImplThread());
1237 impl().layer_tree_host_impl =
1238 layer_tree_host()->CreateLayerTreeHostImpl(this);
1239 const LayerTreeSettings& settings = layer_tree_host()->settings();
1240 SchedulerSettings scheduler_settings;
1241 scheduler_settings.begin_frame_scheduling_enabled =
1242 settings.begin_frame_scheduling_enabled;
1243 scheduler_settings.main_frame_before_draw_enabled =
1244 settings.main_frame_before_draw_enabled;
1245 scheduler_settings.main_frame_before_activation_enabled =
1246 settings.main_frame_before_activation_enabled;
1247 scheduler_settings.impl_side_painting = settings.impl_side_painting;
1248 scheduler_settings.timeout_and_draw_when_animation_checkerboards =
1249 settings.timeout_and_draw_when_animation_checkerboards;
1250 scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ =
1251 settings.maximum_number_of_failed_draws_before_draw_is_forced_;
1252 scheduler_settings.using_synchronous_renderer_compositor =
1253 settings.using_synchronous_renderer_compositor;
1254 scheduler_settings.throttle_frame_production =
1255 settings.throttle_frame_production;
1256 impl().scheduler = Scheduler::Create(this,
1257 scheduler_settings,
1258 impl().layer_tree_host_id,
1259 ImplThreadTaskRunner());
1260 impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible());
1262 impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr();
1263 completion->Signal();
1266 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1267 CompletionEvent* completion,
1268 scoped_ptr<OutputSurface> output_surface,
1269 bool* success,
1270 RendererCapabilities* capabilities) {
1271 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1272 DCHECK(IsImplThread());
1273 DCHECK(IsMainThreadBlocked());
1274 DCHECK(success);
1275 DCHECK(capabilities);
1277 layer_tree_host()->DeleteContentsTexturesOnImplThread(
1278 impl().layer_tree_host_impl->resource_provider());
1280 *success =
1281 impl().layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
1283 if (*success) {
1284 *capabilities = impl()
1285 .layer_tree_host_impl->GetRendererCapabilities()
1286 .MainThreadCapabilities();
1287 impl().scheduler->DidCreateAndInitializeOutputSurface();
1290 completion->Signal();
1293 void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) {
1294 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
1295 DCHECK(IsImplThread());
1296 if (impl().layer_tree_host_impl->resource_provider())
1297 impl().layer_tree_host_impl->resource_provider()->Finish();
1298 completion->Signal();
1301 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
1302 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1303 DCHECK(IsImplThread());
1304 layer_tree_host()->DeleteContentsTexturesOnImplThread(
1305 impl().layer_tree_host_impl->resource_provider());
1306 impl().current_resource_update_controller.reset();
1307 impl().layer_tree_host_impl->SetNeedsBeginFrame(false);
1308 impl().scheduler.reset();
1309 impl().layer_tree_host_impl.reset();
1310 impl().weak_factory.InvalidateWeakPtrs();
1311 impl().contents_texture_manager = NULL;
1312 completion->Signal();
1315 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1316 return ResourceUpdateController::MaxPartialTextureUpdates();
1319 ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState()
1320 : memory_allocation_limit_bytes(0),
1321 memory_allocation_priority_cutoff(0),
1322 evicted_ui_resources(false) {}
1324 ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
1326 scoped_ptr<base::Value> ThreadProxy::AsValue() const {
1327 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1329 CompletionEvent completion;
1331 DebugScopedSetMainThreadBlocked main_thread_blocked(
1332 const_cast<ThreadProxy*>(this));
1333 Proxy::ImplThreadTaskRunner()->PostTask(
1334 FROM_HERE,
1335 base::Bind(&ThreadProxy::AsValueOnImplThread,
1336 impl_thread_weak_ptr_,
1337 &completion,
1338 state.get()));
1339 completion.Wait();
1341 return state.PassAs<base::Value>();
1344 void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
1345 base::DictionaryValue* state) const {
1346 state->Set("layer_tree_host_impl",
1347 impl().layer_tree_host_impl->AsValue().release());
1348 completion->Signal();
1351 bool ThreadProxy::CommitPendingForTesting() {
1352 DCHECK(IsMainThread());
1353 CommitPendingRequest commit_pending_request;
1355 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1356 Proxy::ImplThreadTaskRunner()->PostTask(
1357 FROM_HERE,
1358 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting,
1359 impl_thread_weak_ptr_,
1360 &commit_pending_request));
1361 commit_pending_request.completion.Wait();
1363 return commit_pending_request.commit_pending;
1366 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1367 CommitPendingRequest* request) {
1368 DCHECK(IsImplThread());
1369 if (impl().layer_tree_host_impl->output_surface())
1370 request->commit_pending = impl().scheduler->CommitPending();
1371 else
1372 request->commit_pending = false;
1373 request->completion.Signal();
1376 scoped_ptr<base::Value> ThreadProxy::SchedulerAsValueForTesting() {
1377 if (IsImplThread())
1378 return impl().scheduler->AsValue().Pass();
1380 SchedulerStateRequest scheduler_state_request;
1382 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1383 Proxy::ImplThreadTaskRunner()->PostTask(
1384 FROM_HERE,
1385 base::Bind(&ThreadProxy::SchedulerAsValueOnImplThreadForTesting,
1386 impl_thread_weak_ptr_,
1387 &scheduler_state_request));
1388 scheduler_state_request.completion.Wait();
1390 return scheduler_state_request.state.Pass();
1393 void ThreadProxy::SchedulerAsValueOnImplThreadForTesting(
1394 SchedulerStateRequest* request) {
1395 DCHECK(IsImplThread());
1396 request->state = impl().scheduler->AsValue();
1397 request->completion.Signal();
1400 void ThreadProxy::RenewTreePriority() {
1401 DCHECK(IsImplThread());
1402 bool smoothness_takes_priority =
1403 impl().layer_tree_host_impl->pinch_gesture_active() ||
1404 impl().layer_tree_host_impl->page_scale_animation_active() ||
1405 (impl().layer_tree_host_impl->IsCurrentlyScrolling() &&
1406 !impl().layer_tree_host_impl->scroll_affects_scroll_handler());
1408 // Schedule expiration if smoothness currently takes priority.
1409 if (smoothness_takes_priority)
1410 impl().smoothness_priority_expiration_notifier.Schedule();
1412 // We use the same priority for both trees by default.
1413 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES;
1415 // Smoothness takes priority if we have an expiration for it scheduled.
1416 if (impl().smoothness_priority_expiration_notifier.HasPendingNotification())
1417 priority = SMOOTHNESS_TAKES_PRIORITY;
1419 // New content always takes priority when the active tree has
1420 // evicted resources or there is an invalid viewport size.
1421 if (impl().layer_tree_host_impl->active_tree()->ContentsTexturesPurged() ||
1422 impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() ||
1423 impl().layer_tree_host_impl->EvictedUIResourcesExist() ||
1424 impl().input_throttled_until_commit) {
1425 // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
1426 // tree might be freed. We need to set RequiresHighResToDraw to ensure that
1427 // high res tiles will be required to activate pending tree.
1428 impl().layer_tree_host_impl->active_tree()->SetRequiresHighResToDraw();
1429 priority = NEW_CONTENT_TAKES_PRIORITY;
1432 impl().layer_tree_host_impl->SetTreePriority(priority);
1433 impl().scheduler->SetSmoothnessTakesPriority(priority ==
1434 SMOOTHNESS_TAKES_PRIORITY);
1436 // Notify the the client of this compositor via the output surface.
1437 // TODO(epenner): Route this to compositor-thread instead of output-surface
1438 // after GTFO refactor of compositor-thread (http://crbug/170828).
1439 if (impl().layer_tree_host_impl->output_surface()) {
1440 impl()
1441 .layer_tree_host_impl->output_surface()
1442 ->UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY);
1446 void ThreadProxy::PostDelayedScrollbarFadeOnImplThread(
1447 const base::Closure& start_fade,
1448 base::TimeDelta delay) {
1449 Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, start_fade, delay);
1452 void ThreadProxy::DidActivatePendingTree() {
1453 TRACE_EVENT0("cc", "ThreadProxy::DidActivatePendingTreeOnImplThread");
1454 DCHECK(IsImplThread());
1455 DCHECK(!impl().layer_tree_host_impl->pending_tree());
1457 if (impl().completion_event_for_commit_held_on_tree_activation) {
1458 TRACE_EVENT_INSTANT0(
1459 "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD);
1460 DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting);
1461 impl().completion_event_for_commit_held_on_tree_activation->Signal();
1462 impl().completion_event_for_commit_held_on_tree_activation = NULL;
1465 UpdateBackgroundAnimateTicking();
1467 impl().timing_history.DidActivatePendingTree();
1470 void ThreadProxy::DidManageTiles() {
1471 DCHECK(IsImplThread());
1472 impl().scheduler->DidManageTiles();
1475 } // namespace cc