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