Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / cc / trees / thread_proxy.cc
blob19cf3ba62b9cc004bd77ca81aa4afb110b54bdf0
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::ReadbackRequest {
53 CompletionEvent completion;
54 bool success;
55 void* pixels;
56 gfx::Rect rect;
59 struct ThreadProxy::CommitPendingRequest {
60 CompletionEvent completion;
61 bool commit_pending;
64 struct ThreadProxy::SchedulerStateRequest {
65 CompletionEvent completion;
66 scoped_ptr<base::Value> state;
69 scoped_ptr<Proxy> ThreadProxy::Create(
70 LayerTreeHost* layer_tree_host,
71 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
72 return make_scoped_ptr(new ThreadProxy(layer_tree_host, impl_task_runner))
73 .PassAs<Proxy>();
76 ThreadProxy::ThreadProxy(
77 LayerTreeHost* layer_tree_host,
78 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
79 : Proxy(impl_task_runner),
80 main_thread_only_vars_unsafe_(this, layer_tree_host->id()),
81 main_thread_or_blocked_vars_unsafe_(layer_tree_host),
82 compositor_thread_vars_unsafe_(this, layer_tree_host->id()) {
83 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
84 DCHECK(IsMainThread());
85 DCHECK(this->layer_tree_host());
88 ThreadProxy::MainThreadOnly::MainThreadOnly(ThreadProxy* proxy,
89 int layer_tree_host_id)
90 : layer_tree_host_id(layer_tree_host_id),
91 animate_requested(false),
92 commit_requested(false),
93 commit_request_sent_to_impl_thread(false),
94 started(false),
95 in_composite_and_readback(false),
96 manage_tiles_pending(false),
97 can_cancel_commit(true),
98 defer_commits(false),
99 weak_factory(proxy) {}
101 ThreadProxy::MainThreadOnly::~MainThreadOnly() {}
103 ThreadProxy::MainThreadOrBlockedMainThread::MainThreadOrBlockedMainThread(
104 LayerTreeHost* host)
105 : layer_tree_host(host),
106 commit_waits_for_activation(false),
107 main_thread_inside_commit(false) {}
109 ThreadProxy::MainThreadOrBlockedMainThread::~MainThreadOrBlockedMainThread() {}
111 PrioritizedResourceManager*
112 ThreadProxy::MainThreadOrBlockedMainThread::contents_texture_manager() {
113 return layer_tree_host->contents_texture_manager();
116 ThreadProxy::CompositorThreadOnly::CompositorThreadOnly(ThreadProxy* proxy,
117 int layer_tree_host_id)
118 : layer_tree_host_id(layer_tree_host_id),
119 contents_texture_manager(NULL),
120 begin_main_frame_sent_completion_event(NULL),
121 readback_request(NULL),
122 commit_completion_event(NULL),
123 completion_event_for_commit_held_on_tree_activation(NULL),
124 next_frame_is_newly_committed_frame(false),
125 inside_draw(false),
126 input_throttled_until_commit(false),
127 animations_frozen_until_next_draw(false),
128 did_commit_after_animating(false),
129 renew_tree_priority_pending(false),
130 weak_factory(proxy) {
133 ThreadProxy::CompositorThreadOnly::~CompositorThreadOnly() {}
135 ThreadProxy::~ThreadProxy() {
136 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
137 DCHECK(IsMainThread());
138 DCHECK(!main().started);
141 bool ThreadProxy::CompositeAndReadback(void* pixels, const gfx::Rect& rect) {
142 TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
143 DCHECK(IsMainThread());
144 DCHECK(layer_tree_host());
146 if (main().defer_commits) {
147 TRACE_EVENT0("cc", "CompositeAndReadback_DeferCommit");
148 return false;
151 if (!layer_tree_host()->InitializeOutputSurfaceIfNeeded()) {
152 TRACE_EVENT_INSTANT0("cc",
153 "CompositeAndReadback_EarlyOut_LR_Uninitialized",
154 TRACE_EVENT_SCOPE_THREAD);
155 return false;
158 // Perform a synchronous commit with an associated readback.
159 ReadbackRequest request;
160 request.rect = rect;
161 request.pixels = pixels;
163 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
164 CompletionEvent begin_main_frame_sent_completion;
165 Proxy::ImplThreadTaskRunner()->PostTask(
166 FROM_HERE,
167 base::Bind(&ThreadProxy::ForceCommitForReadbackOnImplThread,
168 impl_thread_weak_ptr_,
169 &begin_main_frame_sent_completion,
170 &request));
171 begin_main_frame_sent_completion.Wait();
174 main().in_composite_and_readback = true;
175 // This is the forced commit.
176 // Note: The Impl thread also queues a separate BeginMainFrame on the
177 // main thread, which will be called after this CompositeAndReadback
178 // completes, to replace the forced commit.
179 BeginMainFrame(scoped_ptr<BeginMainFrameAndCommitState>());
180 main().in_composite_and_readback = false;
182 // Composite and readback requires a second commit to undo any changes
183 // that it made.
184 main().can_cancel_commit = false;
186 request.completion.Wait();
187 return request.success;
190 void ThreadProxy::ForceCommitForReadbackOnImplThread(
191 CompletionEvent* begin_main_frame_sent_completion,
192 ReadbackRequest* request) {
193 TRACE_EVENT0("cc", "ThreadProxy::ForceCommitForReadbackOnImplThread");
194 DCHECK(IsImplThread());
195 DCHECK(!impl().begin_main_frame_sent_completion_event);
196 DCHECK(!impl().readback_request);
198 if (!impl().layer_tree_host_impl) {
199 begin_main_frame_sent_completion->Signal();
200 request->success = false;
201 request->completion.Signal();
202 return;
205 impl().readback_request = request;
207 impl().scheduler->SetNeedsForcedCommitForReadback();
208 if (impl().scheduler->IsBeginMainFrameSent()) {
209 begin_main_frame_sent_completion->Signal();
210 return;
213 impl().begin_main_frame_sent_completion_event =
214 begin_main_frame_sent_completion;
217 void ThreadProxy::FinishAllRendering() {
218 DCHECK(Proxy::IsMainThread());
219 DCHECK(!main().defer_commits);
221 // Make sure all GL drawing is finished on the impl thread.
222 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
223 CompletionEvent completion;
224 Proxy::ImplThreadTaskRunner()->PostTask(
225 FROM_HERE,
226 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread,
227 impl_thread_weak_ptr_,
228 &completion));
229 completion.Wait();
232 bool ThreadProxy::IsStarted() const {
233 DCHECK(Proxy::IsMainThread());
234 return main().started;
237 void ThreadProxy::SetLayerTreeHostClientReady() {
238 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
239 Proxy::ImplThreadTaskRunner()->PostTask(
240 FROM_HERE,
241 base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread,
242 impl_thread_weak_ptr_));
245 void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
246 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
247 impl().scheduler->SetCanStart();
250 void ThreadProxy::SetVisible(bool visible) {
251 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
252 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
254 CompletionEvent completion;
255 Proxy::ImplThreadTaskRunner()->PostTask(
256 FROM_HERE,
257 base::Bind(&ThreadProxy::SetVisibleOnImplThread,
258 impl_thread_weak_ptr_,
259 &completion,
260 visible));
261 completion.Wait();
264 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
265 bool visible) {
266 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
267 impl().layer_tree_host_impl->SetVisible(visible);
268 impl().scheduler->SetVisible(visible);
269 UpdateBackgroundAnimateTicking();
270 completion->Signal();
273 void ThreadProxy::UpdateBackgroundAnimateTicking() {
274 bool should_background_tick =
275 !impl().scheduler->WillDrawIfNeeded() &&
276 impl().layer_tree_host_impl->active_tree()->root_layer();
277 impl().layer_tree_host_impl->UpdateBackgroundAnimateTicking(
278 should_background_tick);
279 if (should_background_tick)
280 impl().animations_frozen_until_next_draw = false;
283 void ThreadProxy::DoCreateAndInitializeOutputSurface() {
284 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface");
285 DCHECK(IsMainThread());
287 scoped_ptr<OutputSurface> output_surface =
288 layer_tree_host()->CreateOutputSurface();
290 RendererCapabilities capabilities;
291 bool success = !!output_surface;
292 if (success) {
293 // Make a blocking call to InitializeOutputSurfaceOnImplThread. The results
294 // of that call are pushed into the success and capabilities local
295 // variables.
296 CompletionEvent completion;
297 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
299 Proxy::ImplThreadTaskRunner()->PostTask(
300 FROM_HERE,
301 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
302 impl_thread_weak_ptr_,
303 &completion,
304 base::Passed(&output_surface),
305 &success,
306 &capabilities));
307 completion.Wait();
309 main().renderer_capabilities_main_thread_copy = capabilities;
310 layer_tree_host()->OnCreateAndInitializeOutputSurfaceAttempted(success);
312 if (success) {
313 main().output_surface_creation_callback.Cancel();
314 } else if (!main().output_surface_creation_callback.IsCancelled()) {
315 Proxy::MainThreadTaskRunner()->PostTask(
316 FROM_HERE, main().output_surface_creation_callback.callback());
320 void ThreadProxy::SetRendererCapabilitiesMainThreadCopy(
321 const RendererCapabilities& capabilities) {
322 main().renderer_capabilities_main_thread_copy = capabilities;
325 void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
326 DCHECK(IsMainThread());
327 if (main().commit_request_sent_to_impl_thread)
328 return;
329 main().commit_request_sent_to_impl_thread = true;
330 Proxy::ImplThreadTaskRunner()->PostTask(
331 FROM_HERE,
332 base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread,
333 impl_thread_weak_ptr_));
336 const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
337 DCHECK(IsMainThread());
338 DCHECK(!layer_tree_host()->output_surface_lost());
339 return main().renderer_capabilities_main_thread_copy;
342 void ThreadProxy::SetNeedsAnimate() {
343 DCHECK(IsMainThread());
344 if (main().animate_requested)
345 return;
347 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
348 main().animate_requested = true;
349 SendCommitRequestToImplThreadIfNeeded();
352 void ThreadProxy::SetNeedsUpdateLayers() {
353 DCHECK(IsMainThread());
355 if (main().commit_request_sent_to_impl_thread)
356 return;
357 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsUpdateLayers");
359 SendCommitRequestToImplThreadIfNeeded();
362 void ThreadProxy::SetNeedsCommit() {
363 DCHECK(IsMainThread());
364 // Unconditionally set here to handle SetNeedsCommit calls during a commit.
365 main().can_cancel_commit = false;
367 if (main().commit_requested)
368 return;
369 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
370 main().commit_requested = true;
372 SendCommitRequestToImplThreadIfNeeded();
375 void ThreadProxy::UpdateRendererCapabilitiesOnImplThread() {
376 DCHECK(IsImplThread());
377 Proxy::MainThreadTaskRunner()->PostTask(
378 FROM_HERE,
379 base::Bind(&ThreadProxy::SetRendererCapabilitiesMainThreadCopy,
380 main_thread_weak_ptr_,
381 impl()
382 .layer_tree_host_impl->GetRendererCapabilities()
383 .MainThreadCapabilities()));
386 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
387 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
388 DCHECK(IsImplThread());
389 CheckOutputSurfaceStatusOnImplThread();
392 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
393 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
394 DCHECK(IsImplThread());
395 if (!impl().layer_tree_host_impl->IsContextLost())
396 return;
397 impl().scheduler->DidLoseOutputSurface();
400 void ThreadProxy::CommitVSyncParameters(base::TimeTicks timebase,
401 base::TimeDelta interval) {
402 impl().scheduler->CommitVSyncParameters(timebase, interval);
405 void ThreadProxy::SetEstimatedParentDrawTime(base::TimeDelta draw_time) {
406 impl().scheduler->SetEstimatedParentDrawTime(draw_time);
409 void ThreadProxy::SetMaxSwapsPendingOnImplThread(int max) {
410 impl().scheduler->SetMaxSwapsPending(max);
413 void ThreadProxy::DidSwapBuffersOnImplThread() {
414 impl().scheduler->DidSwapBuffers();
417 void ThreadProxy::DidSwapBuffersCompleteOnImplThread() {
418 TRACE_EVENT0("cc", "ThreadProxy::DidSwapBuffersCompleteOnImplThread");
419 DCHECK(IsImplThread());
420 impl().scheduler->DidSwapBuffersComplete();
421 Proxy::MainThreadTaskRunner()->PostTask(
422 FROM_HERE,
423 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
426 void ThreadProxy::SetNeedsBeginFrame(bool enable) {
427 TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrame", "enable", enable);
428 impl().layer_tree_host_impl->SetNeedsBeginFrame(enable);
429 UpdateBackgroundAnimateTicking();
432 void ThreadProxy::BeginFrame(const BeginFrameArgs& args) {
433 impl().scheduler->BeginFrame(args);
436 void ThreadProxy::WillBeginImplFrame(const BeginFrameArgs& args) {
437 impl().layer_tree_host_impl->WillBeginImplFrame(args);
440 void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
441 TRACE_EVENT1(
442 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
443 DCHECK(IsImplThread());
444 impl().scheduler->SetCanDraw(can_draw);
445 UpdateBackgroundAnimateTicking();
448 void ThreadProxy::NotifyReadyToActivate() {
449 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
450 impl().scheduler->NotifyReadyToActivate();
453 void ThreadProxy::SetNeedsCommitOnImplThread() {
454 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
455 DCHECK(IsImplThread());
456 impl().scheduler->SetNeedsCommit();
459 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
460 scoped_ptr<AnimationEventsVector> events) {
461 TRACE_EVENT0("cc",
462 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
463 DCHECK(IsImplThread());
464 Proxy::MainThreadTaskRunner()->PostTask(
465 FROM_HERE,
466 base::Bind(&ThreadProxy::SetAnimationEvents,
467 main_thread_weak_ptr_,
468 base::Passed(&events)));
471 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
472 int priority_cutoff) {
473 DCHECK(IsImplThread());
475 if (!impl().contents_texture_manager)
476 return false;
477 if (!impl().layer_tree_host_impl->resource_provider())
478 return false;
480 bool reduce_result =
481 impl().contents_texture_manager->ReduceMemoryOnImplThread(
482 limit_bytes,
483 priority_cutoff,
484 impl().layer_tree_host_impl->resource_provider());
485 if (!reduce_result)
486 return false;
488 // The texture upload queue may reference textures that were just purged,
489 // clear them from the queue.
490 if (impl().current_resource_update_controller) {
491 impl()
492 .current_resource_update_controller->DiscardUploadsToEvictedResources();
494 return true;
497 void ThreadProxy::SendManagedMemoryStats() {
498 DCHECK(IsImplThread());
499 if (!impl().layer_tree_host_impl)
500 return;
501 if (!impl().contents_texture_manager)
502 return;
504 // If we are using impl-side painting, then SendManagedMemoryStats is called
505 // directly after the tile manager's manage function, and doesn't need to
506 // interact with main thread's layer tree.
507 if (impl().layer_tree_host_impl->settings().impl_side_painting)
508 return;
510 impl().layer_tree_host_impl->SendManagedMemoryStats(
511 impl().contents_texture_manager->MemoryVisibleBytes(),
512 impl().contents_texture_manager->MemoryVisibleAndNearbyBytes(),
513 impl().contents_texture_manager->MemoryUseBytes());
516 bool ThreadProxy::IsInsideDraw() { return impl().inside_draw; }
518 void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
519 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
520 DCHECK(IsMainThread());
521 Proxy::ImplThreadTaskRunner()->PostTask(
522 FROM_HERE,
523 base::Bind(&ThreadProxy::SetNeedsRedrawRectOnImplThread,
524 impl_thread_weak_ptr_,
525 damage_rect));
528 void ThreadProxy::SetNextCommitWaitsForActivation() {
529 DCHECK(IsMainThread());
530 DCHECK(!blocked_main().main_thread_inside_commit);
531 blocked_main().commit_waits_for_activation = true;
534 void ThreadProxy::SetDeferCommits(bool defer_commits) {
535 DCHECK(IsMainThread());
536 DCHECK_NE(main().defer_commits, defer_commits);
537 main().defer_commits = defer_commits;
539 if (main().defer_commits)
540 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
541 else
542 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
544 if (!main().defer_commits && main().pending_deferred_commit)
545 Proxy::MainThreadTaskRunner()->PostTask(
546 FROM_HERE,
547 base::Bind(&ThreadProxy::BeginMainFrame,
548 main_thread_weak_ptr_,
549 base::Passed(&main().pending_deferred_commit)));
552 bool ThreadProxy::CommitRequested() const {
553 DCHECK(IsMainThread());
554 return main().commit_requested;
557 bool ThreadProxy::BeginMainFrameRequested() const {
558 DCHECK(IsMainThread());
559 return main().commit_request_sent_to_impl_thread;
562 void ThreadProxy::SetNeedsRedrawOnImplThread() {
563 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
564 DCHECK(IsImplThread());
565 impl().scheduler->SetNeedsRedraw();
568 void ThreadProxy::SetNeedsAnimateOnImplThread() {
569 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimateOnImplThread");
570 DCHECK(IsImplThread());
571 impl().scheduler->SetNeedsAnimate();
574 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
575 DCHECK(IsImplThread());
576 impl().scheduler->SetNeedsManageTiles();
579 void ThreadProxy::SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) {
580 DCHECK(IsImplThread());
581 impl().layer_tree_host_impl->SetViewportDamage(damage_rect);
582 SetNeedsRedrawOnImplThread();
585 void ThreadProxy::SetSwapUsedIncompleteTileOnImplThread(
586 bool used_incomplete_tile) {
587 DCHECK(IsImplThread());
588 if (used_incomplete_tile) {
589 TRACE_EVENT_INSTANT0("cc",
590 "ThreadProxy::SetSwapUsedIncompleteTileOnImplThread",
591 TRACE_EVENT_SCOPE_THREAD);
593 impl().scheduler->SetSwapUsedIncompleteTile(used_incomplete_tile);
596 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
597 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
598 DCHECK(IsImplThread());
599 impl().scheduler->SetNeedsRedraw();
602 void ThreadProxy::MainThreadHasStoppedFlinging() {
603 DCHECK(IsMainThread());
604 Proxy::ImplThreadTaskRunner()->PostTask(
605 FROM_HERE,
606 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread,
607 impl_thread_weak_ptr_));
610 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
611 DCHECK(IsImplThread());
612 impl().layer_tree_host_impl->MainThreadHasStoppedFlinging();
615 void ThreadProxy::NotifyInputThrottledUntilCommit() {
616 DCHECK(IsMainThread());
617 Proxy::ImplThreadTaskRunner()->PostTask(
618 FROM_HERE,
619 base::Bind(&ThreadProxy::SetInputThrottledUntilCommitOnImplThread,
620 impl_thread_weak_ptr_,
621 true));
624 void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(bool is_throttled) {
625 DCHECK(IsImplThread());
626 if (is_throttled == impl().input_throttled_until_commit)
627 return;
628 impl().input_throttled_until_commit = is_throttled;
629 RenewTreePriority();
632 LayerTreeHost* ThreadProxy::layer_tree_host() {
633 return blocked_main().layer_tree_host;
636 const LayerTreeHost* ThreadProxy::layer_tree_host() const {
637 return blocked_main().layer_tree_host;
640 ThreadProxy::MainThreadOnly& ThreadProxy::main() {
641 DCHECK(IsMainThread());
642 return main_thread_only_vars_unsafe_;
644 const ThreadProxy::MainThreadOnly& ThreadProxy::main() const {
645 DCHECK(IsMainThread());
646 return main_thread_only_vars_unsafe_;
649 ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main() {
650 DCHECK(IsMainThread() || IsMainThreadBlocked());
651 return main_thread_or_blocked_vars_unsafe_;
654 const ThreadProxy::MainThreadOrBlockedMainThread& ThreadProxy::blocked_main()
655 const {
656 DCHECK(IsMainThread() || IsMainThreadBlocked());
657 return main_thread_or_blocked_vars_unsafe_;
660 ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() {
661 DCHECK(IsImplThread());
662 return compositor_thread_vars_unsafe_;
665 const ThreadProxy::CompositorThreadOnly& ThreadProxy::impl() const {
666 DCHECK(IsImplThread());
667 return compositor_thread_vars_unsafe_;
670 void ThreadProxy::Start() {
671 DCHECK(IsMainThread());
672 DCHECK(Proxy::HasImplThread());
674 // Create LayerTreeHostImpl.
675 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
676 CompletionEvent completion;
677 Proxy::ImplThreadTaskRunner()->PostTask(
678 FROM_HERE,
679 base::Bind(&ThreadProxy::InitializeImplOnImplThread,
680 base::Unretained(this),
681 &completion));
682 completion.Wait();
684 main_thread_weak_ptr_ = main().weak_factory.GetWeakPtr();
686 main().started = true;
689 void ThreadProxy::Stop() {
690 TRACE_EVENT0("cc", "ThreadProxy::Stop");
691 DCHECK(IsMainThread());
692 DCHECK(main().started);
694 // Synchronously finishes pending GL operations and deletes the impl.
695 // The two steps are done as separate post tasks, so that tasks posted
696 // by the GL implementation due to the Finish can be executed by the
697 // renderer before shutting it down.
699 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
701 CompletionEvent completion;
702 Proxy::ImplThreadTaskRunner()->PostTask(
703 FROM_HERE,
704 base::Bind(&ThreadProxy::FinishGLOnImplThread,
705 impl_thread_weak_ptr_,
706 &completion));
707 completion.Wait();
710 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
712 CompletionEvent completion;
713 Proxy::ImplThreadTaskRunner()->PostTask(
714 FROM_HERE,
715 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread,
716 impl_thread_weak_ptr_,
717 &completion));
718 completion.Wait();
721 main().weak_factory.InvalidateWeakPtrs();
722 blocked_main().layer_tree_host = NULL;
723 main().started = false;
726 void ThreadProxy::ForceSerializeOnSwapBuffers() {
727 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
728 CompletionEvent completion;
729 Proxy::ImplThreadTaskRunner()->PostTask(
730 FROM_HERE,
731 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
732 impl_thread_weak_ptr_,
733 &completion));
734 completion.Wait();
737 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
738 CompletionEvent* completion) {
739 if (impl().layer_tree_host_impl->renderer())
740 impl().layer_tree_host_impl->renderer()->DoNoOp();
741 completion->Signal();
744 void ThreadProxy::SetDebugState(const LayerTreeDebugState& debug_state) {
745 Proxy::ImplThreadTaskRunner()->PostTask(
746 FROM_HERE,
747 base::Bind(&ThreadProxy::SetDebugStateOnImplThread,
748 impl_thread_weak_ptr_,
749 debug_state));
752 void ThreadProxy::SetDebugStateOnImplThread(
753 const LayerTreeDebugState& debug_state) {
754 DCHECK(IsImplThread());
755 impl().scheduler->SetContinuousPainting(debug_state.continuous_painting);
758 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
759 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
760 DCHECK(IsImplThread());
761 impl().layer_tree_host_impl->FinishAllRendering();
762 completion->Signal();
765 void ThreadProxy::ScheduledActionSendBeginMainFrame() {
766 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginMainFrame");
767 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
768 new BeginMainFrameAndCommitState);
769 begin_main_frame_state->monotonic_frame_begin_time =
770 impl().layer_tree_host_impl->CurrentFrameTimeTicks();
771 begin_main_frame_state->scroll_info =
772 impl().layer_tree_host_impl->ProcessScrollDeltas();
774 if (!impl().layer_tree_host_impl->settings().impl_side_painting) {
775 DCHECK_GT(impl().layer_tree_host_impl->memory_allocation_limit_bytes(), 0u);
777 begin_main_frame_state->memory_allocation_limit_bytes =
778 impl().layer_tree_host_impl->memory_allocation_limit_bytes();
779 begin_main_frame_state->memory_allocation_priority_cutoff =
780 impl().layer_tree_host_impl->memory_allocation_priority_cutoff();
781 begin_main_frame_state->evicted_ui_resources =
782 impl().layer_tree_host_impl->EvictedUIResourcesExist();
783 Proxy::MainThreadTaskRunner()->PostTask(
784 FROM_HERE,
785 base::Bind(&ThreadProxy::BeginMainFrame,
786 main_thread_weak_ptr_,
787 base::Passed(&begin_main_frame_state)));
788 devtools_instrumentation::DidRequestMainThreadFrame(
789 impl().layer_tree_host_id);
790 if (impl().begin_main_frame_sent_completion_event) {
791 impl().begin_main_frame_sent_completion_event->Signal();
792 impl().begin_main_frame_sent_completion_event = NULL;
794 impl().timing_history.DidBeginMainFrame();
797 void ThreadProxy::BeginMainFrame(
798 scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state) {
799 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame");
800 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("cc.BeginMainFrame");
801 DCHECK(IsMainThread());
803 if (!layer_tree_host())
804 return;
806 if (main().defer_commits) {
807 main().pending_deferred_commit = begin_main_frame_state.Pass();
808 layer_tree_host()->DidDeferCommit();
809 TRACE_EVENT_INSTANT0(
810 "cc", "EarlyOut_DeferCommits", TRACE_EVENT_SCOPE_THREAD);
811 return;
814 // If the commit finishes, LayerTreeHost will transfer its swap promises to
815 // LayerTreeImpl. The destructor of SwapPromiseChecker checks LayerTressHost's
816 // swap promises.
817 SwapPromiseChecker swap_promise_checker(layer_tree_host());
819 // Do not notify the impl thread of commit requests that occur during
820 // the apply/animate/layout part of the BeginMainFrameAndCommit process since
821 // those commit requests will get painted immediately. Once we have done
822 // the paint, main().commit_requested will be set to false to allow new commit
823 // requests to be scheduled.
824 main().commit_requested = true;
825 main().commit_request_sent_to_impl_thread = true;
827 // On the other hand, the AnimationRequested flag needs to be cleared
828 // here so that any animation requests generated by the apply or animate
829 // callbacks will trigger another frame.
830 main().animate_requested = false;
832 if (!main().in_composite_and_readback && !layer_tree_host()->visible()) {
833 main().commit_requested = false;
834 main().commit_request_sent_to_impl_thread = false;
836 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
837 bool did_handle = false;
838 Proxy::ImplThreadTaskRunner()->PostTask(
839 FROM_HERE,
840 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
841 impl_thread_weak_ptr_,
842 did_handle));
843 return;
846 if (begin_main_frame_state) {
847 layer_tree_host()->ApplyScrollAndScale(
848 *begin_main_frame_state->scroll_info);
851 layer_tree_host()->WillBeginMainFrame();
853 if (begin_main_frame_state) {
854 layer_tree_host()->UpdateClientAnimations(
855 begin_main_frame_state->monotonic_frame_begin_time);
856 layer_tree_host()->AnimateLayers(
857 begin_main_frame_state->monotonic_frame_begin_time);
858 blocked_main().last_monotonic_frame_begin_time =
859 begin_main_frame_state->monotonic_frame_begin_time;
862 // Unlink any backings that the impl thread has evicted, so that we know to
863 // re-paint them in UpdateLayers.
864 if (blocked_main().contents_texture_manager()) {
865 blocked_main().contents_texture_manager()->UnlinkAndClearEvictedBackings();
867 if (begin_main_frame_state) {
868 blocked_main().contents_texture_manager()->SetMaxMemoryLimitBytes(
869 begin_main_frame_state->memory_allocation_limit_bytes);
870 blocked_main().contents_texture_manager()->SetExternalPriorityCutoff(
871 begin_main_frame_state->memory_allocation_priority_cutoff);
875 // Recreate all UI resources if there were evicted UI resources when the impl
876 // thread initiated the commit.
877 bool evicted_ui_resources = begin_main_frame_state
878 ? begin_main_frame_state->evicted_ui_resources
879 : false;
880 if (evicted_ui_resources)
881 layer_tree_host()->RecreateUIResources();
883 layer_tree_host()->Layout();
884 TRACE_EVENT_SYNTHETIC_DELAY_END("cc.BeginMainFrame");
886 // Clear the commit flag after updating animations and layout here --- objects
887 // that only layout when painted will trigger another SetNeedsCommit inside
888 // UpdateLayers.
889 main().commit_requested = false;
890 main().commit_request_sent_to_impl_thread = false;
891 bool can_cancel_this_commit = main().can_cancel_commit &&
892 !main().in_composite_and_readback &&
893 !evicted_ui_resources;
894 main().can_cancel_commit = true;
896 scoped_ptr<ResourceUpdateQueue> queue =
897 make_scoped_ptr(new ResourceUpdateQueue);
899 bool updated = layer_tree_host()->UpdateLayers(queue.get());
901 layer_tree_host()->WillCommit();
903 // Before calling animate, we set main().animate_requested to false. If it is
904 // true now, it means SetNeedAnimate was called again, but during a state when
905 // main().commit_request_sent_to_impl_thread = true. We need to force that
906 // call to happen again now so that the commit request is sent to the impl
907 // thread.
908 if (main().animate_requested) {
909 // Forces SetNeedsAnimate to consider posting a commit task.
910 main().animate_requested = false;
911 SetNeedsAnimate();
914 if (!updated && can_cancel_this_commit) {
915 TRACE_EVENT_INSTANT0("cc", "EarlyOut_NoUpdates", TRACE_EVENT_SCOPE_THREAD);
916 bool did_handle = true;
917 Proxy::ImplThreadTaskRunner()->PostTask(
918 FROM_HERE,
919 base::Bind(&ThreadProxy::BeginMainFrameAbortedOnImplThread,
920 impl_thread_weak_ptr_,
921 did_handle));
923 // Although the commit is internally aborted, this is because it has been
924 // detected to be a no-op. From the perspective of an embedder, this commit
925 // went through, and input should no longer be throttled, etc.
926 layer_tree_host()->CommitComplete();
927 layer_tree_host()->DidBeginMainFrame();
928 return;
931 // Notify the impl thread that the main thread is ready to commit. This will
932 // begin the commit process, which is blocking from the main thread's
933 // point of view, but asynchronously performed on the impl thread,
934 // coordinated by the Scheduler.
936 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrame::commit");
938 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
940 // This CapturePostTasks should be destroyed before CommitComplete() is
941 // called since that goes out to the embedder, and we want the embedder
942 // to receive its callbacks before that.
943 BlockingTaskRunner::CapturePostTasks blocked;
945 CompletionEvent completion;
946 Proxy::ImplThreadTaskRunner()->PostTask(
947 FROM_HERE,
948 base::Bind(&ThreadProxy::StartCommitOnImplThread,
949 impl_thread_weak_ptr_,
950 &completion,
951 queue.release()));
952 completion.Wait();
954 RenderingStatsInstrumentation* stats_instrumentation =
955 layer_tree_host()->rendering_stats_instrumentation();
956 BenchmarkInstrumentation::IssueMainThreadRenderingStatsEvent(
957 stats_instrumentation->main_thread_rendering_stats());
958 stats_instrumentation->AccumulateAndClearMainThreadStats();
961 layer_tree_host()->CommitComplete();
962 layer_tree_host()->DidBeginMainFrame();
965 void ThreadProxy::StartCommitOnImplThread(CompletionEvent* completion,
966 ResourceUpdateQueue* raw_queue) {
967 TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
968 DCHECK(!impl().commit_completion_event);
969 DCHECK(IsImplThread() && IsMainThreadBlocked());
970 DCHECK(impl().scheduler);
971 DCHECK(impl().scheduler->CommitPending());
973 if (!impl().layer_tree_host_impl) {
974 TRACE_EVENT_INSTANT0(
975 "cc", "EarlyOut_NoLayerTree", TRACE_EVENT_SCOPE_THREAD);
976 completion->Signal();
977 return;
980 // Ideally, we should inform to impl thread when BeginMainFrame is started.
981 // But, we can avoid a PostTask in here.
982 impl().scheduler->NotifyBeginMainFrameStarted();
984 scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
986 if (impl().contents_texture_manager) {
987 DCHECK_EQ(impl().contents_texture_manager,
988 blocked_main().contents_texture_manager());
989 } else {
990 // Cache this pointer that was created on the main thread side to avoid a
991 // data race between creating it and using it on the compositor thread.
992 impl().contents_texture_manager = blocked_main().contents_texture_manager();
995 if (impl().contents_texture_manager) {
996 if (impl().contents_texture_manager->LinkedEvictedBackingsExist()) {
997 // Clear any uploads we were making to textures linked to evicted
998 // resources
999 queue->ClearUploadsToEvictedResources();
1000 // Some textures in the layer tree are invalid. Kick off another commit
1001 // to fill them again.
1002 SetNeedsCommitOnImplThread();
1005 impl().contents_texture_manager->PushTexturePrioritiesToBackings();
1008 impl().commit_completion_event = completion;
1009 impl().current_resource_update_controller = ResourceUpdateController::Create(
1010 this,
1011 Proxy::ImplThreadTaskRunner(),
1012 queue.Pass(),
1013 impl().layer_tree_host_impl->resource_provider());
1014 impl().current_resource_update_controller->PerformMoreUpdates(
1015 impl().scheduler->AnticipatedDrawTime());
1018 void ThreadProxy::BeginMainFrameAbortedOnImplThread(bool did_handle) {
1019 TRACE_EVENT0("cc", "ThreadProxy::BeginMainFrameAbortedOnImplThread");
1020 DCHECK(IsImplThread());
1021 DCHECK(impl().scheduler);
1022 DCHECK(impl().scheduler->CommitPending());
1023 DCHECK(!impl().layer_tree_host_impl->pending_tree());
1025 if (did_handle)
1026 SetInputThrottledUntilCommitOnImplThread(false);
1027 impl().layer_tree_host_impl->BeginMainFrameAborted(did_handle);
1028 impl().scheduler->BeginMainFrameAborted(did_handle);
1031 void ThreadProxy::ScheduledActionAnimate() {
1032 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionAnimate");
1033 DCHECK(IsImplThread());
1035 if (!impl().animations_frozen_until_next_draw) {
1036 impl().animation_time =
1037 impl().layer_tree_host_impl->CurrentFrameTimeTicks();
1039 impl().layer_tree_host_impl->Animate(impl().animation_time);
1040 impl().did_commit_after_animating = false;
1043 void ThreadProxy::ScheduledActionCommit() {
1044 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
1045 DCHECK(IsImplThread());
1046 DCHECK(IsMainThreadBlocked());
1047 DCHECK(impl().commit_completion_event);
1048 DCHECK(impl().current_resource_update_controller);
1050 // Complete all remaining texture updates.
1051 impl().current_resource_update_controller->Finalize();
1052 impl().current_resource_update_controller.reset();
1054 if (impl().animations_frozen_until_next_draw) {
1055 impl().animation_time = std::max(
1056 impl().animation_time, blocked_main().last_monotonic_frame_begin_time);
1058 impl().did_commit_after_animating = true;
1060 blocked_main().main_thread_inside_commit = true;
1061 impl().layer_tree_host_impl->BeginCommit();
1062 layer_tree_host()->BeginCommitOnImplThread(impl().layer_tree_host_impl.get());
1063 layer_tree_host()->FinishCommitOnImplThread(
1064 impl().layer_tree_host_impl.get());
1065 blocked_main().main_thread_inside_commit = false;
1067 bool hold_commit = layer_tree_host()->settings().impl_side_painting &&
1068 blocked_main().commit_waits_for_activation;
1069 blocked_main().commit_waits_for_activation = false;
1071 if (hold_commit) {
1072 // For some layer types in impl-side painting, the commit is held until
1073 // the pending tree is activated. It's also possible that the
1074 // pending tree has already activated if there was no work to be done.
1075 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
1076 impl().completion_event_for_commit_held_on_tree_activation =
1077 impl().commit_completion_event;
1078 impl().commit_completion_event = NULL;
1079 } else {
1080 impl().commit_completion_event->Signal();
1081 impl().commit_completion_event = NULL;
1084 // Delay this step until afer the main thread has been released as it's
1085 // often a good bit of work to update the tree and prepare the new frame.
1086 impl().layer_tree_host_impl->CommitComplete();
1088 SetInputThrottledUntilCommitOnImplThread(false);
1090 UpdateBackgroundAnimateTicking();
1092 impl().next_frame_is_newly_committed_frame = true;
1094 impl().timing_history.DidCommit();
1097 void ThreadProxy::ScheduledActionUpdateVisibleTiles() {
1098 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles");
1099 DCHECK(IsImplThread());
1100 impl().layer_tree_host_impl->UpdateVisibleTiles();
1103 void ThreadProxy::ScheduledActionActivatePendingTree() {
1104 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTree");
1105 DCHECK(IsImplThread());
1106 impl().layer_tree_host_impl->ActivatePendingTree();
1109 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
1110 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
1111 DCHECK(IsImplThread());
1112 Proxy::MainThreadTaskRunner()->PostTask(
1113 FROM_HERE,
1114 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface,
1115 main_thread_weak_ptr_));
1118 DrawSwapReadbackResult ThreadProxy::DrawSwapReadbackInternal(
1119 bool forced_draw,
1120 bool swap_requested,
1121 bool readback_requested) {
1122 TRACE_EVENT_SYNTHETIC_DELAY("cc.DrawAndSwap");
1123 DrawSwapReadbackResult result;
1125 DCHECK(IsImplThread());
1126 DCHECK(impl().layer_tree_host_impl.get());
1128 impl().timing_history.DidStartDrawing();
1129 base::TimeDelta draw_duration_estimate = DrawDurationEstimate();
1130 base::AutoReset<bool> mark_inside(&impl().inside_draw, true);
1132 if (impl().did_commit_after_animating) {
1133 impl().layer_tree_host_impl->Animate(impl().animation_time);
1134 impl().did_commit_after_animating = false;
1137 if (impl().layer_tree_host_impl->pending_tree())
1138 impl().layer_tree_host_impl->pending_tree()->UpdateDrawProperties();
1140 // This method is called on a forced draw, regardless of whether we are able
1141 // to produce a frame, as the calling site on main thread is blocked until its
1142 // request completes, and we signal completion here. If CanDraw() is false, we
1143 // will indicate success=false to the caller, but we must still signal
1144 // completion to avoid deadlock.
1146 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
1147 // frame, so can only be used when such a frame is possible. Since
1148 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
1149 // CanDraw() as well.
1151 bool drawing_for_readback = readback_requested && !!impl().readback_request;
1152 bool can_do_readback =
1153 impl().layer_tree_host_impl->renderer()->CanReadPixels();
1155 LayerTreeHostImpl::FrameData frame;
1156 bool draw_frame = false;
1158 if (impl().layer_tree_host_impl->CanDraw()) {
1159 if (!drawing_for_readback || can_do_readback) {
1160 // If it is for a readback, make sure we draw the portion being read back.
1161 gfx::Rect readback_rect;
1162 if (drawing_for_readback)
1163 readback_rect = impl().readback_request->rect;
1165 result.draw_result =
1166 impl().layer_tree_host_impl->PrepareToDraw(&frame, readback_rect);
1167 draw_frame = forced_draw ||
1168 result.draw_result == DrawSwapReadbackResult::DRAW_SUCCESS;
1169 } else {
1170 result.draw_result = DrawSwapReadbackResult::DRAW_ABORTED_CANT_READBACK;
1172 } else {
1173 result.draw_result = DrawSwapReadbackResult::DRAW_ABORTED_CANT_DRAW;
1176 if (draw_frame) {
1177 impl().layer_tree_host_impl->DrawLayers(
1178 &frame, impl().scheduler->LastBeginImplFrameTime());
1179 result.draw_result = DrawSwapReadbackResult::DRAW_SUCCESS;
1180 impl().animations_frozen_until_next_draw = false;
1181 } else if (result.draw_result ==
1182 DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS &&
1183 !impl().layer_tree_host_impl->settings().impl_side_painting) {
1184 // Without impl-side painting, the animated layer that is checkerboarding
1185 // will continue to checkerboard until the next commit. If this layer
1186 // continues to move during the commit, it may continue to checkerboard
1187 // after the commit since the region rasterized during the commit will not
1188 // match the region that is currently visible; eventually this
1189 // checkerboarding will be displayed when we force a draw. To avoid this,
1190 // we freeze animations until we successfully draw.
1191 impl().animations_frozen_until_next_draw = true;
1192 } else {
1193 DCHECK_NE(DrawSwapReadbackResult::DRAW_SUCCESS, result.draw_result);
1195 impl().layer_tree_host_impl->DidDrawAllLayers(frame);
1197 bool start_ready_animations = draw_frame;
1198 impl().layer_tree_host_impl->UpdateAnimationState(start_ready_animations);
1200 // Check for a pending CompositeAndReadback.
1201 if (drawing_for_readback) {
1202 DCHECK(!swap_requested);
1203 result.did_readback = false;
1204 if (draw_frame) {
1205 if (!impl().layer_tree_host_impl->IsContextLost()) {
1206 impl().layer_tree_host_impl->Readback(impl().readback_request->pixels,
1207 impl().readback_request->rect);
1208 result.did_readback = true;
1209 } else {
1210 result.draw_result = DrawSwapReadbackResult::DRAW_ABORTED_CONTEXT_LOST;
1213 impl().readback_request->success = result.did_readback;
1214 impl().readback_request->completion.Signal();
1215 impl().readback_request = NULL;
1216 } else if (draw_frame) {
1217 DCHECK(swap_requested);
1218 result.did_request_swap = impl().layer_tree_host_impl->SwapBuffers(frame);
1220 // We don't know if we have incomplete tiles if we didn't actually swap.
1221 if (result.did_request_swap) {
1222 DCHECK(!frame.has_no_damage);
1223 SetSwapUsedIncompleteTileOnImplThread(frame.contains_incomplete_tile);
1227 // Tell the main thread that the the newly-commited frame was drawn.
1228 if (impl().next_frame_is_newly_committed_frame) {
1229 impl().next_frame_is_newly_committed_frame = false;
1230 Proxy::MainThreadTaskRunner()->PostTask(
1231 FROM_HERE,
1232 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_));
1235 if (draw_frame)
1236 CheckOutputSurfaceStatusOnImplThread();
1238 if (result.draw_result == DrawSwapReadbackResult::DRAW_SUCCESS) {
1239 base::TimeDelta draw_duration = impl().timing_history.DidFinishDrawing();
1241 base::TimeDelta draw_duration_overestimate;
1242 base::TimeDelta draw_duration_underestimate;
1243 if (draw_duration > draw_duration_estimate)
1244 draw_duration_underestimate = draw_duration - draw_duration_estimate;
1245 else
1246 draw_duration_overestimate = draw_duration_estimate - draw_duration;
1247 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration",
1248 draw_duration,
1249 base::TimeDelta::FromMilliseconds(1),
1250 base::TimeDelta::FromMilliseconds(100),
1251 50);
1252 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate",
1253 draw_duration_underestimate,
1254 base::TimeDelta::FromMilliseconds(1),
1255 base::TimeDelta::FromMilliseconds(100),
1256 50);
1257 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate",
1258 draw_duration_overestimate,
1259 base::TimeDelta::FromMilliseconds(1),
1260 base::TimeDelta::FromMilliseconds(100),
1261 50);
1264 DCHECK_NE(DrawSwapReadbackResult::INVALID_RESULT, result.draw_result);
1265 return result;
1268 void ThreadProxy::ScheduledActionManageTiles() {
1269 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionManageTiles");
1270 DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting);
1271 impl().layer_tree_host_impl->ManageTiles();
1274 DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1275 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
1277 // SchedulerStateMachine::DidDrawIfPossibleCompleted isn't set up to
1278 // handle DRAW_ABORTED_CANT_DRAW. Moreover, the scheduler should
1279 // never generate this call when it can't draw.
1280 DCHECK(impl().layer_tree_host_impl->CanDraw());
1282 bool forced_draw = false;
1283 bool swap_requested = true;
1284 bool readback_requested = false;
1285 return DrawSwapReadbackInternal(
1286 forced_draw, swap_requested, readback_requested);
1289 DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
1290 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
1291 bool forced_draw = true;
1292 bool swap_requested = true;
1293 bool readback_requested = false;
1294 return DrawSwapReadbackInternal(
1295 forced_draw, swap_requested, readback_requested);
1298 DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndReadback() {
1299 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndReadback");
1300 bool forced_draw = true;
1301 bool swap_requested = false;
1302 bool readback_requested = true;
1303 return DrawSwapReadbackInternal(
1304 forced_draw, swap_requested, readback_requested);
1307 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1308 if (impl().current_resource_update_controller)
1309 impl().current_resource_update_controller->PerformMoreUpdates(time);
1312 base::TimeDelta ThreadProxy::DrawDurationEstimate() {
1313 return impl().timing_history.DrawDurationEstimate();
1316 base::TimeDelta ThreadProxy::BeginMainFrameToCommitDurationEstimate() {
1317 return impl().timing_history.BeginMainFrameToCommitDurationEstimate();
1320 base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() {
1321 return impl().timing_history.CommitToActivateDurationEstimate();
1324 void ThreadProxy::DidBeginImplFrameDeadline() {
1325 impl().layer_tree_host_impl->ResetCurrentFrameTimeForNextFrame();
1328 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1329 DCHECK(IsImplThread());
1330 impl().scheduler->NotifyReadyToCommit();
1333 void ThreadProxy::DidCommitAndDrawFrame() {
1334 DCHECK(IsMainThread());
1335 if (!layer_tree_host())
1336 return;
1337 layer_tree_host()->DidCommitAndDrawFrame();
1340 void ThreadProxy::DidCompleteSwapBuffers() {
1341 DCHECK(IsMainThread());
1342 if (!layer_tree_host())
1343 return;
1344 layer_tree_host()->DidCompleteSwapBuffers();
1347 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events) {
1348 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1349 DCHECK(IsMainThread());
1350 if (!layer_tree_host())
1351 return;
1352 layer_tree_host()->SetAnimationEvents(events.Pass());
1355 void ThreadProxy::CreateAndInitializeOutputSurface() {
1356 TRACE_EVENT0("cc", "ThreadProxy::CreateAndInitializeOutputSurface");
1357 DCHECK(IsMainThread());
1359 // Check that output surface has not been recreated by CompositeAndReadback
1360 // after this task is posted but before it is run.
1361 bool has_initialized_output_surface = true;
1363 CompletionEvent completion;
1364 Proxy::ImplThreadTaskRunner()->PostTask(
1365 FROM_HERE,
1366 base::Bind(&ThreadProxy::HasInitializedOutputSurfaceOnImplThread,
1367 impl_thread_weak_ptr_,
1368 &completion,
1369 &has_initialized_output_surface));
1370 completion.Wait();
1372 if (has_initialized_output_surface)
1373 return;
1375 layer_tree_host()->DidLoseOutputSurface();
1376 main().output_surface_creation_callback.Reset(
1377 base::Bind(&ThreadProxy::DoCreateAndInitializeOutputSurface,
1378 base::Unretained(this)));
1379 main().output_surface_creation_callback.callback().Run();
1382 void ThreadProxy::HasInitializedOutputSurfaceOnImplThread(
1383 CompletionEvent* completion,
1384 bool* has_initialized_output_surface) {
1385 DCHECK(IsImplThread());
1386 *has_initialized_output_surface =
1387 impl().scheduler->HasInitializedOutputSurface();
1388 completion->Signal();
1391 void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
1392 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1393 DCHECK(IsImplThread());
1394 impl().layer_tree_host_impl =
1395 layer_tree_host()->CreateLayerTreeHostImpl(this);
1396 const LayerTreeSettings& settings = layer_tree_host()->settings();
1397 SchedulerSettings scheduler_settings;
1398 scheduler_settings.begin_frame_scheduling_enabled =
1399 settings.begin_frame_scheduling_enabled;
1400 scheduler_settings.main_frame_before_draw_enabled =
1401 settings.main_frame_before_draw_enabled;
1402 scheduler_settings.main_frame_before_activation_enabled =
1403 settings.main_frame_before_activation_enabled;
1404 scheduler_settings.impl_side_painting = settings.impl_side_painting;
1405 scheduler_settings.timeout_and_draw_when_animation_checkerboards =
1406 settings.timeout_and_draw_when_animation_checkerboards;
1407 scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ =
1408 settings.maximum_number_of_failed_draws_before_draw_is_forced_;
1409 scheduler_settings.using_synchronous_renderer_compositor =
1410 settings.using_synchronous_renderer_compositor;
1411 scheduler_settings.throttle_frame_production =
1412 settings.throttle_frame_production;
1413 impl().scheduler = Scheduler::Create(this,
1414 scheduler_settings,
1415 impl().layer_tree_host_id,
1416 ImplThreadTaskRunner());
1417 impl().scheduler->SetVisible(impl().layer_tree_host_impl->visible());
1419 impl_thread_weak_ptr_ = impl().weak_factory.GetWeakPtr();
1420 completion->Signal();
1423 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1424 CompletionEvent* completion,
1425 scoped_ptr<OutputSurface> output_surface,
1426 bool* success,
1427 RendererCapabilities* capabilities) {
1428 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1429 DCHECK(IsImplThread());
1430 DCHECK(IsMainThreadBlocked());
1431 DCHECK(success);
1432 DCHECK(capabilities);
1434 layer_tree_host()->DeleteContentsTexturesOnImplThread(
1435 impl().layer_tree_host_impl->resource_provider());
1437 *success =
1438 impl().layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
1440 if (*success) {
1441 *capabilities = impl()
1442 .layer_tree_host_impl->GetRendererCapabilities()
1443 .MainThreadCapabilities();
1444 impl().scheduler->DidCreateAndInitializeOutputSurface();
1447 completion->Signal();
1450 void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) {
1451 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
1452 DCHECK(IsImplThread());
1453 if (impl().layer_tree_host_impl->resource_provider())
1454 impl().layer_tree_host_impl->resource_provider()->Finish();
1455 completion->Signal();
1458 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
1459 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1460 DCHECK(IsImplThread());
1461 layer_tree_host()->DeleteContentsTexturesOnImplThread(
1462 impl().layer_tree_host_impl->resource_provider());
1463 impl().current_resource_update_controller.reset();
1464 impl().layer_tree_host_impl->SetNeedsBeginFrame(false);
1465 impl().scheduler.reset();
1466 impl().layer_tree_host_impl.reset();
1467 impl().weak_factory.InvalidateWeakPtrs();
1468 impl().contents_texture_manager = NULL;
1469 completion->Signal();
1472 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1473 return ResourceUpdateController::MaxPartialTextureUpdates();
1476 ThreadProxy::BeginMainFrameAndCommitState::BeginMainFrameAndCommitState()
1477 : memory_allocation_limit_bytes(0),
1478 memory_allocation_priority_cutoff(0),
1479 evicted_ui_resources(false) {}
1481 ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
1483 scoped_ptr<base::Value> ThreadProxy::AsValue() const {
1484 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1486 CompletionEvent completion;
1488 DebugScopedSetMainThreadBlocked main_thread_blocked(
1489 const_cast<ThreadProxy*>(this));
1490 Proxy::ImplThreadTaskRunner()->PostTask(
1491 FROM_HERE,
1492 base::Bind(&ThreadProxy::AsValueOnImplThread,
1493 impl_thread_weak_ptr_,
1494 &completion,
1495 state.get()));
1496 completion.Wait();
1498 return state.PassAs<base::Value>();
1501 void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
1502 base::DictionaryValue* state) const {
1503 state->Set("layer_tree_host_impl",
1504 impl().layer_tree_host_impl->AsValue().release());
1505 completion->Signal();
1508 bool ThreadProxy::CommitPendingForTesting() {
1509 DCHECK(IsMainThread());
1510 CommitPendingRequest commit_pending_request;
1512 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1513 Proxy::ImplThreadTaskRunner()->PostTask(
1514 FROM_HERE,
1515 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting,
1516 impl_thread_weak_ptr_,
1517 &commit_pending_request));
1518 commit_pending_request.completion.Wait();
1520 return commit_pending_request.commit_pending;
1523 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1524 CommitPendingRequest* request) {
1525 DCHECK(IsImplThread());
1526 if (impl().layer_tree_host_impl->output_surface())
1527 request->commit_pending = impl().scheduler->CommitPending();
1528 else
1529 request->commit_pending = false;
1530 request->completion.Signal();
1533 scoped_ptr<base::Value> ThreadProxy::SchedulerStateAsValueForTesting() {
1534 if (IsImplThread())
1535 return impl().scheduler->StateAsValue().Pass();
1537 SchedulerStateRequest scheduler_state_request;
1539 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1540 Proxy::ImplThreadTaskRunner()->PostTask(
1541 FROM_HERE,
1542 base::Bind(&ThreadProxy::SchedulerStateAsValueOnImplThreadForTesting,
1543 impl_thread_weak_ptr_,
1544 &scheduler_state_request));
1545 scheduler_state_request.completion.Wait();
1547 return scheduler_state_request.state.Pass();
1550 void ThreadProxy::SchedulerStateAsValueOnImplThreadForTesting(
1551 SchedulerStateRequest* request) {
1552 DCHECK(IsImplThread());
1553 request->state = impl().scheduler->StateAsValue();
1554 request->completion.Signal();
1557 void ThreadProxy::RenewTreePriority() {
1558 DCHECK(IsImplThread());
1559 bool smoothness_takes_priority =
1560 impl().layer_tree_host_impl->pinch_gesture_active() ||
1561 impl().layer_tree_host_impl->page_scale_animation_active() ||
1562 (impl().layer_tree_host_impl->IsCurrentlyScrolling() &&
1563 !impl().layer_tree_host_impl->scroll_affects_scroll_handler());
1565 base::TimeTicks now = impl().layer_tree_host_impl->CurrentFrameTimeTicks();
1567 // Update expiration time if smoothness currently takes priority.
1568 if (smoothness_takes_priority) {
1569 impl().smoothness_takes_priority_expiration_time =
1570 now + base::TimeDelta::FromMilliseconds(
1571 kSmoothnessTakesPriorityExpirationDelay * 1000);
1574 // We use the same priority for both trees by default.
1575 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES;
1577 // Smoothness takes priority if expiration time is in the future.
1578 if (impl().smoothness_takes_priority_expiration_time > now)
1579 priority = SMOOTHNESS_TAKES_PRIORITY;
1581 // New content always takes priority when the active tree has
1582 // evicted resources or there is an invalid viewport size.
1583 if (impl().layer_tree_host_impl->active_tree()->ContentsTexturesPurged() ||
1584 impl().layer_tree_host_impl->active_tree()->ViewportSizeInvalid() ||
1585 impl().layer_tree_host_impl->EvictedUIResourcesExist() ||
1586 impl().input_throttled_until_commit) {
1587 // Once we enter NEW_CONTENTS_TAKES_PRIORITY mode, visible tiles on active
1588 // tree might be freed. We need to set RequiresHighResToDraw to ensure that
1589 // high res tiles will be required to activate pending tree.
1590 impl().layer_tree_host_impl->active_tree()->SetRequiresHighResToDraw();
1591 priority = NEW_CONTENT_TAKES_PRIORITY;
1594 impl().layer_tree_host_impl->SetTreePriority(priority);
1595 impl().scheduler->SetSmoothnessTakesPriority(priority ==
1596 SMOOTHNESS_TAKES_PRIORITY);
1598 // Notify the the client of this compositor via the output surface.
1599 // TODO(epenner): Route this to compositor-thread instead of output-surface
1600 // after GTFO refactor of compositor-thread (http://crbug/170828).
1601 if (impl().layer_tree_host_impl->output_surface()) {
1602 impl()
1603 .layer_tree_host_impl->output_surface()
1604 ->UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY);
1607 base::TimeDelta delay =
1608 impl().smoothness_takes_priority_expiration_time - now;
1610 // Need to make sure a delayed task is posted when we have smoothness
1611 // takes priority expiration time in the future.
1612 if (delay <= base::TimeDelta())
1613 return;
1614 if (impl().renew_tree_priority_pending)
1615 return;
1617 Proxy::ImplThreadTaskRunner()->PostDelayedTask(
1618 FROM_HERE,
1619 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread,
1620 impl_thread_weak_ptr_),
1621 delay);
1623 impl().renew_tree_priority_pending = true;
1626 void ThreadProxy::RenewTreePriorityOnImplThread() {
1627 DCHECK(impl().renew_tree_priority_pending);
1628 impl().renew_tree_priority_pending = false;
1630 RenewTreePriority();
1633 void ThreadProxy::PostDelayedScrollbarFadeOnImplThread(
1634 const base::Closure& start_fade,
1635 base::TimeDelta delay) {
1636 Proxy::ImplThreadTaskRunner()->PostDelayedTask(FROM_HERE, start_fade, delay);
1639 void ThreadProxy::DidActivatePendingTree() {
1640 TRACE_EVENT0("cc", "ThreadProxy::DidActivatePendingTreeOnImplThread");
1641 DCHECK(IsImplThread());
1642 DCHECK(!impl().layer_tree_host_impl->pending_tree());
1644 if (impl().completion_event_for_commit_held_on_tree_activation) {
1645 TRACE_EVENT_INSTANT0(
1646 "cc", "ReleaseCommitbyActivation", TRACE_EVENT_SCOPE_THREAD);
1647 DCHECK(impl().layer_tree_host_impl->settings().impl_side_painting);
1648 impl().completion_event_for_commit_held_on_tree_activation->Signal();
1649 impl().completion_event_for_commit_held_on_tree_activation = NULL;
1652 UpdateBackgroundAnimateTicking();
1654 impl().timing_history.DidActivatePendingTree();
1657 void ThreadProxy::DidManageTiles() {
1658 DCHECK(IsImplThread());
1659 impl().scheduler->DidManageTiles();
1662 } // namespace cc