Move prefs::kLastPolicyStatisticsUpdate to the policy component.
[chromium-blink-merge.git] / cc / trees / thread_proxy.cc
blob7f590f06be330d2f445f013eafa1aac4364045b6
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 <string>
9 #include "base/auto_reset.h"
10 #include "base/bind.h"
11 #include "base/debug/trace_event.h"
12 #include "base/metrics/histogram.h"
13 #include "cc/input/input_handler.h"
14 #include "cc/output/context_provider.h"
15 #include "cc/output/output_surface.h"
16 #include "cc/quads/draw_quad.h"
17 #include "cc/resources/prioritized_resource_manager.h"
18 #include "cc/scheduler/delay_based_time_source.h"
19 #include "cc/scheduler/frame_rate_controller.h"
20 #include "cc/scheduler/scheduler.h"
21 #include "cc/trees/blocking_task_runner.h"
22 #include "cc/trees/layer_tree_host.h"
23 #include "cc/trees/layer_tree_impl.h"
25 namespace {
27 // Measured in seconds.
28 const double kContextRecreationTickRate = 0.03;
30 // Measured in seconds.
31 const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
33 const size_t kDurationHistorySize = 60;
34 const double kCommitAndActivationDurationEstimationPercentile = 50.0;
35 const double kDrawDurationEstimationPercentile = 100.0;
36 const int kDrawDurationEstimatePaddingInMicroseconds = 0;
38 } // namespace
40 namespace cc {
42 struct ThreadProxy::ReadbackRequest {
43 CompletionEvent completion;
44 bool success;
45 void* pixels;
46 gfx::Rect rect;
49 struct ThreadProxy::CommitPendingRequest {
50 CompletionEvent completion;
51 bool commit_pending;
54 struct ThreadProxy::SchedulerStateRequest {
55 CompletionEvent completion;
56 scoped_ptr<base::Value> state;
59 scoped_ptr<Proxy> ThreadProxy::Create(
60 LayerTreeHost* layer_tree_host,
61 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
62 return make_scoped_ptr(
63 new ThreadProxy(layer_tree_host, impl_task_runner)).PassAs<Proxy>();
66 ThreadProxy::ThreadProxy(
67 LayerTreeHost* layer_tree_host,
68 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner)
69 : Proxy(impl_task_runner),
70 animate_requested_(false),
71 commit_requested_(false),
72 commit_request_sent_to_impl_thread_(false),
73 created_offscreen_context_provider_(false),
74 layer_tree_host_(layer_tree_host),
75 started_(false),
76 textures_acquired_(true),
77 in_composite_and_readback_(false),
78 manage_tiles_pending_(false),
79 commit_waits_for_activation_(false),
80 inside_commit_(false),
81 weak_factory_on_impl_thread_(this),
82 weak_factory_(this),
83 begin_frame_sent_to_main_thread_completion_event_on_impl_thread_(NULL),
84 readback_request_on_impl_thread_(NULL),
85 commit_completion_event_on_impl_thread_(NULL),
86 completion_event_for_commit_held_on_tree_activation_(NULL),
87 texture_acquisition_completion_event_on_impl_thread_(NULL),
88 next_frame_is_newly_committed_frame_on_impl_thread_(false),
89 throttle_frame_production_(
90 layer_tree_host->settings().throttle_frame_production),
91 begin_frame_scheduling_enabled_(
92 layer_tree_host->settings().begin_frame_scheduling_enabled),
93 using_synchronous_renderer_compositor_(
94 layer_tree_host->settings().using_synchronous_renderer_compositor),
95 inside_draw_(false),
96 can_cancel_commit_(true),
97 defer_commits_(false),
98 input_throttled_until_commit_(false),
99 renew_tree_priority_on_impl_thread_pending_(false),
100 draw_duration_history_(kDurationHistorySize),
101 begin_frame_to_commit_duration_history_(kDurationHistorySize),
102 commit_to_activate_duration_history_(kDurationHistorySize) {
103 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
104 DCHECK(IsMainThread());
105 DCHECK(layer_tree_host_);
108 ThreadProxy::~ThreadProxy() {
109 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
110 DCHECK(IsMainThread());
111 DCHECK(!started_);
114 bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
115 TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
116 DCHECK(IsMainThread());
117 DCHECK(layer_tree_host_);
119 if (defer_commits_) {
120 TRACE_EVENT0("cc", "CompositeAndReadback_DeferCommit");
121 return false;
124 if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded()) {
125 TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized");
126 return false;
129 // Perform a synchronous commit with an associated readback.
130 ReadbackRequest request;
131 request.rect = rect;
132 request.pixels = pixels;
134 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
135 CompletionEvent begin_frame_sent_to_main_thread_completion;
136 Proxy::ImplThreadTaskRunner()
137 ->PostTask(FROM_HERE,
138 base::Bind(&ThreadProxy::ForceCommitForReadbackOnImplThread,
139 impl_thread_weak_ptr_,
140 &begin_frame_sent_to_main_thread_completion,
141 &request));
142 begin_frame_sent_to_main_thread_completion.Wait();
145 in_composite_and_readback_ = true;
146 // This is the forced commit.
147 // Note: The Impl thread also queues a separate BeginFrameOnMainThread on the
148 // main thread, which will be called after this CompositeAndReadback
149 // completes, to replace the forced commit.
150 BeginFrameOnMainThread(scoped_ptr<BeginFrameAndCommitState>());
151 in_composite_and_readback_ = false;
153 // Composite and readback requires a second commit to undo any changes
154 // that it made.
155 can_cancel_commit_ = false;
157 request.completion.Wait();
158 return request.success;
161 void ThreadProxy::ForceCommitForReadbackOnImplThread(
162 CompletionEvent* begin_frame_sent_completion,
163 ReadbackRequest* request) {
164 TRACE_EVENT0("cc", "ThreadProxy::ForceCommitForReadbackOnImplThread");
165 DCHECK(IsImplThread());
166 DCHECK(!begin_frame_sent_to_main_thread_completion_event_on_impl_thread_);
167 DCHECK(!readback_request_on_impl_thread_);
169 if (!layer_tree_host_impl_) {
170 begin_frame_sent_completion->Signal();
171 request->success = false;
172 request->completion.Signal();
173 return;
176 readback_request_on_impl_thread_ = request;
178 scheduler_on_impl_thread_->SetNeedsForcedCommitForReadback();
179 if (scheduler_on_impl_thread_->CommitPending()) {
180 begin_frame_sent_completion->Signal();
181 return;
184 begin_frame_sent_to_main_thread_completion_event_on_impl_thread_ =
185 begin_frame_sent_completion;
188 void ThreadProxy::FinishAllRendering() {
189 DCHECK(Proxy::IsMainThread());
190 DCHECK(!defer_commits_);
192 // Make sure all GL drawing is finished on the impl thread.
193 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
194 CompletionEvent completion;
195 Proxy::ImplThreadTaskRunner()->PostTask(
196 FROM_HERE,
197 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread,
198 impl_thread_weak_ptr_,
199 &completion));
200 completion.Wait();
203 bool ThreadProxy::IsStarted() const {
204 DCHECK(Proxy::IsMainThread());
205 return started_;
208 void ThreadProxy::SetLayerTreeHostClientReady() {
209 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReady");
210 Proxy::ImplThreadTaskRunner()->PostTask(
211 FROM_HERE,
212 base::Bind(&ThreadProxy::SetLayerTreeHostClientReadyOnImplThread,
213 impl_thread_weak_ptr_));
216 void ThreadProxy::SetLayerTreeHostClientReadyOnImplThread() {
217 TRACE_EVENT0("cc", "ThreadProxy::SetLayerTreeHostClientReadyOnImplThread");
218 scheduler_on_impl_thread_->SetCanStart();
221 void ThreadProxy::SetVisible(bool visible) {
222 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
223 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
225 CompletionEvent completion;
226 Proxy::ImplThreadTaskRunner()->PostTask(
227 FROM_HERE,
228 base::Bind(&ThreadProxy::SetVisibleOnImplThread,
229 impl_thread_weak_ptr_,
230 &completion,
231 visible));
232 completion.Wait();
235 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
236 bool visible) {
237 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
238 layer_tree_host_impl_->SetVisible(visible);
239 scheduler_on_impl_thread_->SetVisible(visible);
240 UpdateBackgroundAnimateTicking();
241 completion->Signal();
244 void ThreadProxy::UpdateBackgroundAnimateTicking() {
245 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
246 !scheduler_on_impl_thread_->WillDrawIfNeeded() &&
247 layer_tree_host_impl_->active_tree()->root_layer());
250 void ThreadProxy::DoCreateAndInitializeOutputSurface() {
251 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface");
252 DCHECK(IsMainThread());
254 scoped_ptr<OutputSurface> output_surface = first_output_surface_.Pass();
255 if (!output_surface)
256 output_surface = layer_tree_host_->CreateOutputSurface();
258 RendererCapabilities capabilities;
259 bool success = !!output_surface;
260 if (!success) {
261 OnOutputSurfaceInitializeAttempted(false, capabilities);
262 return;
265 scoped_refptr<ContextProvider> offscreen_context_provider;
266 if (created_offscreen_context_provider_) {
267 offscreen_context_provider = layer_tree_host_->client()->
268 OffscreenContextProviderForCompositorThread();
269 success = !!offscreen_context_provider.get();
270 if (!success) {
271 OnOutputSurfaceInitializeAttempted(false, capabilities);
272 return;
276 success = false;
278 // Make a blocking call to InitializeOutputSurfaceOnImplThread. The results
279 // of that call are pushed into the success and capabilities local
280 // variables.
281 CompletionEvent completion;
282 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
284 Proxy::ImplThreadTaskRunner()->PostTask(
285 FROM_HERE,
286 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
287 impl_thread_weak_ptr_,
288 &completion,
289 base::Passed(&output_surface),
290 offscreen_context_provider,
291 &success,
292 &capabilities));
293 completion.Wait();
296 OnOutputSurfaceInitializeAttempted(success, capabilities);
299 void ThreadProxy::OnOutputSurfaceInitializeAttempted(
300 bool success,
301 const RendererCapabilities& capabilities) {
302 DCHECK(IsMainThread());
303 DCHECK(layer_tree_host_);
305 if (success) {
306 renderer_capabilities_main_thread_copy_ = capabilities;
309 LayerTreeHost::CreateResult result =
310 layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
311 if (result == LayerTreeHost::CreateFailedButTryAgain) {
312 if (!output_surface_creation_callback_.callback().is_null()) {
313 Proxy::MainThreadTaskRunner()->PostTask(
314 FROM_HERE, output_surface_creation_callback_.callback());
316 } else {
317 output_surface_creation_callback_.Cancel();
321 void ThreadProxy::SendCommitRequestToImplThreadIfNeeded() {
322 DCHECK(IsMainThread());
323 if (commit_request_sent_to_impl_thread_)
324 return;
325 commit_request_sent_to_impl_thread_ = true;
326 Proxy::ImplThreadTaskRunner()->PostTask(
327 FROM_HERE,
328 base::Bind(&ThreadProxy::SetNeedsCommitOnImplThread,
329 impl_thread_weak_ptr_));
332 const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
333 DCHECK(IsMainThread());
334 DCHECK(!layer_tree_host_->output_surface_lost());
335 return renderer_capabilities_main_thread_copy_;
338 void ThreadProxy::SetNeedsAnimate() {
339 DCHECK(IsMainThread());
340 if (animate_requested_)
341 return;
343 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
344 animate_requested_ = true;
345 can_cancel_commit_ = false;
346 SendCommitRequestToImplThreadIfNeeded();
349 void ThreadProxy::SetNeedsUpdateLayers() {
350 DCHECK(IsMainThread());
351 SendCommitRequestToImplThreadIfNeeded();
354 void ThreadProxy::SetNeedsCommit() {
355 DCHECK(IsMainThread());
356 // Unconditionally set here to handle SetNeedsCommit calls during a commit.
357 can_cancel_commit_ = false;
359 if (commit_requested_)
360 return;
361 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
362 commit_requested_ = true;
364 SendCommitRequestToImplThreadIfNeeded();
367 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
368 DCHECK(IsImplThread());
369 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
370 Proxy::ImplThreadTaskRunner()->PostTask(
371 FROM_HERE,
372 base::Bind(&ThreadProxy::CheckOutputSurfaceStatusOnImplThread,
373 impl_thread_weak_ptr_));
376 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
377 DCHECK(IsImplThread());
378 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
379 if (!layer_tree_host_impl_->IsContextLost())
380 return;
381 if (cc::ContextProvider* offscreen_contexts =
382 layer_tree_host_impl_->offscreen_context_provider())
383 offscreen_contexts->VerifyContexts();
384 scheduler_on_impl_thread_->DidLoseOutputSurface();
387 void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
388 DCHECK(IsImplThread());
389 TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
390 Proxy::MainThreadTaskRunner()->PostTask(
391 FROM_HERE,
392 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
395 void ThreadProxy::SetNeedsBeginFrameOnImplThread(bool enable) {
396 DCHECK(IsImplThread());
397 TRACE_EVENT1("cc", "ThreadProxy::SetNeedsBeginFrameOnImplThread",
398 "enable", enable);
399 layer_tree_host_impl_->SetNeedsBeginFrame(enable);
402 void ThreadProxy::BeginFrameOnImplThread(const BeginFrameArgs& args) {
403 DCHECK(IsImplThread());
404 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnImplThread");
405 scheduler_on_impl_thread_->BeginFrame(args);
408 void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
409 DCHECK(IsImplThread());
410 TRACE_EVENT1(
411 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
412 scheduler_on_impl_thread_->SetCanDraw(can_draw);
413 UpdateBackgroundAnimateTicking();
416 void ThreadProxy::NotifyReadyToActivate() {
417 TRACE_EVENT0("cc", "ThreadProxy::NotifyReadyToActivate");
418 scheduler_on_impl_thread_->NotifyReadyToActivate();
421 void ThreadProxy::SetNeedsCommitOnImplThread() {
422 DCHECK(IsImplThread());
423 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
424 scheduler_on_impl_thread_->SetNeedsCommit();
427 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
428 scoped_ptr<AnimationEventsVector> events,
429 base::Time wall_clock_time) {
430 DCHECK(IsImplThread());
431 TRACE_EVENT0("cc",
432 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
433 Proxy::MainThreadTaskRunner()->PostTask(
434 FROM_HERE,
435 base::Bind(&ThreadProxy::SetAnimationEvents,
436 main_thread_weak_ptr_,
437 base::Passed(&events),
438 wall_clock_time));
441 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
442 int priority_cutoff) {
443 DCHECK(IsImplThread());
445 if (!layer_tree_host_->contents_texture_manager())
446 return false;
448 bool reduce_result = layer_tree_host_->contents_texture_manager()->
449 ReduceMemoryOnImplThread(limit_bytes,
450 priority_cutoff,
451 layer_tree_host_impl_->resource_provider());
452 if (!reduce_result)
453 return false;
455 // The texture upload queue may reference textures that were just purged,
456 // clear them from the queue.
457 if (current_resource_update_controller_on_impl_thread_) {
458 current_resource_update_controller_on_impl_thread_->
459 DiscardUploadsToEvictedResources();
461 return true;
464 void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
465 DCHECK(IsImplThread());
467 if (!layer_tree_host_->contents_texture_manager())
468 return;
470 layer_tree_host_->contents_texture_manager()->ReduceWastedMemoryOnImplThread(
471 layer_tree_host_impl_->resource_provider());
474 void ThreadProxy::SendManagedMemoryStats() {
475 DCHECK(IsImplThread());
476 if (!layer_tree_host_impl_)
477 return;
478 if (!layer_tree_host_->contents_texture_manager())
479 return;
481 // If we are using impl-side painting, then SendManagedMemoryStats is called
482 // directly after the tile manager's manage function, and doesn't need to
483 // interact with main thread's layer tree.
484 if (layer_tree_host_->settings().impl_side_painting)
485 return;
487 layer_tree_host_impl_->SendManagedMemoryStats(
488 layer_tree_host_->contents_texture_manager()->MemoryVisibleBytes(),
489 layer_tree_host_->contents_texture_manager()->
490 MemoryVisibleAndNearbyBytes(),
491 layer_tree_host_->contents_texture_manager()->MemoryUseBytes());
494 bool ThreadProxy::IsInsideDraw() { return inside_draw_; }
496 void ThreadProxy::SetNeedsRedraw(gfx::Rect damage_rect) {
497 DCHECK(IsMainThread());
498 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
499 Proxy::ImplThreadTaskRunner()->PostTask(
500 FROM_HERE,
501 base::Bind(&ThreadProxy::SetNeedsRedrawRectOnImplThread,
502 impl_thread_weak_ptr_,
503 damage_rect));
506 void ThreadProxy::SetNextCommitWaitsForActivation() {
507 DCHECK(IsMainThread());
508 DCHECK(!inside_commit_);
509 commit_waits_for_activation_ = true;
512 void ThreadProxy::SetDeferCommits(bool defer_commits) {
513 DCHECK(IsMainThread());
514 DCHECK_NE(defer_commits_, defer_commits);
515 defer_commits_ = defer_commits;
517 if (defer_commits_)
518 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
519 else
520 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
522 if (!defer_commits_ && pending_deferred_commit_)
523 Proxy::MainThreadTaskRunner()->PostTask(
524 FROM_HERE,
525 base::Bind(&ThreadProxy::BeginFrameOnMainThread,
526 main_thread_weak_ptr_,
527 base::Passed(&pending_deferred_commit_)));
530 bool ThreadProxy::CommitRequested() const {
531 DCHECK(IsMainThread());
532 return commit_requested_;
535 void ThreadProxy::SetNeedsRedrawOnImplThread() {
536 DCHECK(IsImplThread());
537 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
538 scheduler_on_impl_thread_->SetNeedsRedraw();
541 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
542 DCHECK(IsImplThread());
543 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsManageTilesOnImplThread");
544 scheduler_on_impl_thread_->SetNeedsManageTiles();
547 void ThreadProxy::SetNeedsRedrawRectOnImplThread(gfx::Rect damage_rect) {
548 DCHECK(IsImplThread());
549 layer_tree_host_impl_->SetViewportDamage(damage_rect);
550 SetNeedsRedrawOnImplThread();
553 void ThreadProxy::SetSwapUsedIncompleteTileOnImplThread(
554 bool used_incomplete_tile) {
555 DCHECK(IsImplThread());
556 if (used_incomplete_tile) {
557 TRACE_EVENT_INSTANT0(
558 "cc",
559 "ThreadProxy::SetSwapUsedIncompleteTileOnImplThread",
560 TRACE_EVENT_SCOPE_THREAD);
562 scheduler_on_impl_thread_->SetSwapUsedIncompleteTile(
563 used_incomplete_tile);
566 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
567 DCHECK(IsImplThread());
568 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
569 scheduler_on_impl_thread_->SetNeedsRedraw();
572 void ThreadProxy::MainThreadHasStoppedFlinging() {
573 DCHECK(IsMainThread());
574 Proxy::ImplThreadTaskRunner()->PostTask(
575 FROM_HERE,
576 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread,
577 impl_thread_weak_ptr_));
580 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
581 DCHECK(IsImplThread());
582 layer_tree_host_impl_->MainThreadHasStoppedFlinging();
585 void ThreadProxy::NotifyInputThrottledUntilCommit() {
586 DCHECK(IsMainThread());
587 Proxy::ImplThreadTaskRunner()->PostTask(
588 FROM_HERE,
589 base::Bind(&ThreadProxy::SetInputThrottledUntilCommitOnImplThread,
590 impl_thread_weak_ptr_,
591 true));
594 void ThreadProxy::SetInputThrottledUntilCommitOnImplThread(
595 bool is_throttled) {
596 DCHECK(IsImplThread());
597 if (is_throttled == input_throttled_until_commit_)
598 return;
599 input_throttled_until_commit_ = is_throttled;
600 RenewTreePriority();
603 void ThreadProxy::Start(scoped_ptr<OutputSurface> first_output_surface) {
604 DCHECK(IsMainThread());
605 DCHECK(Proxy::HasImplThread());
606 DCHECK(first_output_surface);
608 // Create LayerTreeHostImpl.
609 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
610 CompletionEvent completion;
611 Proxy::ImplThreadTaskRunner()->PostTask(
612 FROM_HERE,
613 base::Bind(&ThreadProxy::InitializeImplOnImplThread,
614 base::Unretained(this),
615 &completion));
616 completion.Wait();
618 main_thread_weak_ptr_ = weak_factory_.GetWeakPtr();
619 first_output_surface_ = first_output_surface.Pass();
621 started_ = true;
624 void ThreadProxy::Stop() {
625 TRACE_EVENT0("cc", "ThreadProxy::Stop");
626 DCHECK(IsMainThread());
627 DCHECK(started_);
629 // Synchronously finishes pending GL operations and deletes the impl.
630 // The two steps are done as separate post tasks, so that tasks posted
631 // by the GL implementation due to the Finish can be executed by the
632 // renderer before shutting it down.
634 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
636 CompletionEvent completion;
637 Proxy::ImplThreadTaskRunner()->PostTask(
638 FROM_HERE,
639 base::Bind(&ThreadProxy::FinishGLOnImplThread,
640 impl_thread_weak_ptr_,
641 &completion));
642 completion.Wait();
645 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
647 CompletionEvent completion;
648 Proxy::ImplThreadTaskRunner()->PostTask(
649 FROM_HERE,
650 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread,
651 impl_thread_weak_ptr_,
652 &completion));
653 completion.Wait();
656 weak_factory_.InvalidateWeakPtrs();
658 DCHECK(!layer_tree_host_impl_.get()); // verify that the impl deleted.
659 layer_tree_host_ = NULL;
660 started_ = false;
663 void ThreadProxy::ForceSerializeOnSwapBuffers() {
664 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
665 CompletionEvent completion;
666 Proxy::ImplThreadTaskRunner()->PostTask(
667 FROM_HERE,
668 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
669 impl_thread_weak_ptr_,
670 &completion));
671 completion.Wait();
674 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
675 CompletionEvent* completion) {
676 if (layer_tree_host_impl_->renderer())
677 layer_tree_host_impl_->renderer()->DoNoOp();
678 completion->Signal();
681 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
682 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
683 DCHECK(IsImplThread());
684 layer_tree_host_impl_->FinishAllRendering();
685 completion->Signal();
688 void ThreadProxy::ScheduledActionSendBeginFrameToMainThread() {
689 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionSendBeginFrameToMainThread");
690 scoped_ptr<BeginFrameAndCommitState> begin_frame_state(
691 new BeginFrameAndCommitState);
692 begin_frame_state->monotonic_frame_begin_time =
693 layer_tree_host_impl_->CurrentPhysicalTimeTicks();
694 begin_frame_state->scroll_info =
695 layer_tree_host_impl_->ProcessScrollDeltas();
697 if (!layer_tree_host_impl_->settings().impl_side_painting) {
698 DCHECK_GT(layer_tree_host_impl_->memory_allocation_limit_bytes(), 0u);
700 begin_frame_state->memory_allocation_limit_bytes =
701 layer_tree_host_impl_->memory_allocation_limit_bytes();
702 begin_frame_state->evicted_ui_resources =
703 layer_tree_host_impl_->EvictedUIResourcesExist();
704 Proxy::MainThreadTaskRunner()->PostTask(
705 FROM_HERE,
706 base::Bind(&ThreadProxy::BeginFrameOnMainThread,
707 main_thread_weak_ptr_,
708 base::Passed(&begin_frame_state)));
710 if (begin_frame_sent_to_main_thread_completion_event_on_impl_thread_) {
711 begin_frame_sent_to_main_thread_completion_event_on_impl_thread_->Signal();
712 begin_frame_sent_to_main_thread_completion_event_on_impl_thread_ = NULL;
714 begin_frame_sent_to_main_thread_time_ = base::TimeTicks::HighResNow();
717 void ThreadProxy::BeginFrameOnMainThread(
718 scoped_ptr<BeginFrameAndCommitState> begin_frame_state) {
719 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnMainThread");
720 DCHECK(IsMainThread());
722 if (!layer_tree_host_)
723 return;
725 if (defer_commits_) {
726 pending_deferred_commit_ = begin_frame_state.Pass();
727 layer_tree_host_->DidDeferCommit();
728 TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
729 return;
732 // Do not notify the impl thread of commit requests that occur during
733 // the apply/animate/layout part of the BeginFrameAndCommit process since
734 // those commit requests will get painted immediately. Once we have done
735 // the paint, commit_requested_ will be set to false to allow new commit
736 // requests to be scheduled.
737 commit_requested_ = true;
738 commit_request_sent_to_impl_thread_ = true;
740 // On the other hand, the AnimationRequested flag needs to be cleared
741 // here so that any animation requests generated by the apply or animate
742 // callbacks will trigger another frame.
743 animate_requested_ = false;
745 if (!in_composite_and_readback_ && !layer_tree_host_->visible()) {
746 commit_requested_ = false;
747 commit_request_sent_to_impl_thread_ = false;
749 TRACE_EVENT0("cc", "EarlyOut_NotVisible");
750 bool did_handle = false;
751 Proxy::ImplThreadTaskRunner()->PostTask(
752 FROM_HERE,
753 base::Bind(&ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread,
754 impl_thread_weak_ptr_,
755 did_handle));
756 return;
759 if (begin_frame_state)
760 layer_tree_host_->ApplyScrollAndScale(*begin_frame_state->scroll_info);
762 layer_tree_host_->WillBeginFrame();
764 if (begin_frame_state) {
765 layer_tree_host_->UpdateClientAnimations(
766 begin_frame_state->monotonic_frame_begin_time);
767 layer_tree_host_->AnimateLayers(
768 begin_frame_state->monotonic_frame_begin_time);
771 // Unlink any backings that the impl thread has evicted, so that we know to
772 // re-paint them in UpdateLayers.
773 if (layer_tree_host_->contents_texture_manager()) {
774 layer_tree_host_->contents_texture_manager()->
775 UnlinkAndClearEvictedBackings();
778 // Recreate all UI resources if there were evicted UI resources when the impl
779 // thread initiated the commit.
780 bool evicted_ui_resources =
781 begin_frame_state ? begin_frame_state->evicted_ui_resources : false;
782 if (evicted_ui_resources)
783 layer_tree_host_->RecreateUIResources();
785 layer_tree_host_->Layout();
787 // Clear the commit flag after updating animations and layout here --- objects
788 // that only layout when painted will trigger another SetNeedsCommit inside
789 // UpdateLayers.
790 commit_requested_ = false;
791 commit_request_sent_to_impl_thread_ = false;
792 bool can_cancel_this_commit =
793 can_cancel_commit_ &&
794 !in_composite_and_readback_ &&
795 !evicted_ui_resources;
796 can_cancel_commit_ = true;
798 scoped_ptr<ResourceUpdateQueue> queue =
799 make_scoped_ptr(new ResourceUpdateQueue);
800 bool updated = layer_tree_host_->UpdateLayers(
801 queue.get(),
802 begin_frame_state ? begin_frame_state->memory_allocation_limit_bytes
803 : 0u);
805 // Once single buffered layers are committed, they cannot be modified until
806 // they are drawn by the impl thread.
807 textures_acquired_ = false;
809 layer_tree_host_->WillCommit();
811 if (!updated && can_cancel_this_commit) {
812 TRACE_EVENT0("cc", "EarlyOut_NoUpdates");
813 bool did_handle = true;
814 Proxy::ImplThreadTaskRunner()->PostTask(
815 FROM_HERE,
816 base::Bind(&ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread,
817 impl_thread_weak_ptr_,
818 did_handle));
820 // Although the commit is internally aborted, this is because it has been
821 // detected to be a no-op. From the perspective of an embedder, this commit
822 // went through, and input should no longer be throttled, etc.
823 layer_tree_host_->CommitComplete();
824 layer_tree_host_->DidBeginFrame();
825 return;
828 // Before calling animate, we set animate_requested_ to false. If it is true
829 // now, it means SetNeedAnimate was called again, but during a state when
830 // commit_request_sent_to_impl_thread_ = true. We need to force that call to
831 // happen again now so that the commit request is sent to the impl thread.
832 if (animate_requested_) {
833 // Forces SetNeedsAnimate to consider posting a commit task.
834 animate_requested_ = false;
835 SetNeedsAnimate();
838 scoped_refptr<cc::ContextProvider> offscreen_context_provider;
839 if (renderer_capabilities_main_thread_copy_.using_offscreen_context3d &&
840 layer_tree_host_->needs_offscreen_context()) {
841 offscreen_context_provider = layer_tree_host_->client()->
842 OffscreenContextProviderForCompositorThread();
843 if (offscreen_context_provider.get())
844 created_offscreen_context_provider_ = true;
847 // Notify the impl thread that the main thread is ready to commit. This will
848 // begin the commit process, which is blocking from the main thread's
849 // point of view, but asynchronously performed on the impl thread,
850 // coordinated by the Scheduler.
852 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameOnMainThread::commit");
854 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
856 // This CapturePostTasks should be destroyed before CommitComplete() is
857 // called since that goes out to the embedder, and we want the embedder
858 // to receive its callbacks before that.
859 BlockingTaskRunner::CapturePostTasks blocked;
861 RenderingStatsInstrumentation* stats_instrumentation =
862 layer_tree_host_->rendering_stats_instrumentation();
863 base::TimeTicks start_time = stats_instrumentation->StartRecording();
865 CompletionEvent completion;
866 Proxy::ImplThreadTaskRunner()->PostTask(
867 FROM_HERE,
868 base::Bind(&ThreadProxy::StartCommitOnImplThread,
869 impl_thread_weak_ptr_,
870 &completion,
871 queue.release(),
872 offscreen_context_provider));
873 completion.Wait();
875 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
876 stats_instrumentation->AddCommit(duration);
877 stats_instrumentation->IssueTraceEventForMainThreadStats();
878 stats_instrumentation->AccumulateAndClearMainThreadStats();
881 layer_tree_host_->CommitComplete();
882 layer_tree_host_->DidBeginFrame();
885 void ThreadProxy::StartCommitOnImplThread(
886 CompletionEvent* completion,
887 ResourceUpdateQueue* raw_queue,
888 scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
889 scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
891 TRACE_EVENT0("cc", "ThreadProxy::StartCommitOnImplThread");
892 DCHECK(!commit_completion_event_on_impl_thread_);
893 DCHECK(IsImplThread() && IsMainThreadBlocked());
894 DCHECK(scheduler_on_impl_thread_);
895 DCHECK(scheduler_on_impl_thread_->CommitPending());
897 if (!layer_tree_host_impl_) {
898 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
899 completion->Signal();
900 return;
903 if (offscreen_context_provider.get())
904 offscreen_context_provider->BindToCurrentThread();
905 layer_tree_host_impl_->SetOffscreenContextProvider(
906 offscreen_context_provider);
908 if (layer_tree_host_->contents_texture_manager()) {
909 if (layer_tree_host_->contents_texture_manager()->
910 LinkedEvictedBackingsExist()) {
911 // Clear any uploads we were making to textures linked to evicted
912 // resources
913 queue->ClearUploadsToEvictedResources();
914 // Some textures in the layer tree are invalid. Kick off another commit
915 // to fill them again.
916 SetNeedsCommitOnImplThread();
919 layer_tree_host_->contents_texture_manager()->
920 PushTexturePrioritiesToBackings();
923 commit_completion_event_on_impl_thread_ = completion;
924 current_resource_update_controller_on_impl_thread_ =
925 ResourceUpdateController::Create(
926 this,
927 Proxy::ImplThreadTaskRunner(),
928 queue.Pass(),
929 layer_tree_host_impl_->resource_provider());
930 current_resource_update_controller_on_impl_thread_->PerformMoreUpdates(
931 scheduler_on_impl_thread_->AnticipatedDrawTime());
934 void ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread(bool did_handle) {
935 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedByMainThreadOnImplThread");
936 DCHECK(IsImplThread());
937 DCHECK(scheduler_on_impl_thread_);
938 DCHECK(scheduler_on_impl_thread_->CommitPending());
939 DCHECK(!layer_tree_host_impl_->pending_tree());
941 // If the begin frame data was handled, then scroll and scale set was applied
942 // by the main thread, so the active tree needs to be updated as if these sent
943 // values were applied and committed.
944 if (did_handle) {
945 layer_tree_host_impl_->active_tree()
946 ->ApplySentScrollAndScaleDeltasFromAbortedCommit();
947 layer_tree_host_impl_->active_tree()->ResetContentsTexturesPurged();
948 SetInputThrottledUntilCommitOnImplThread(false);
950 scheduler_on_impl_thread_->BeginFrameAbortedByMainThread(did_handle);
953 void ThreadProxy::ScheduledActionCommit() {
954 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
955 DCHECK(IsImplThread());
956 DCHECK(commit_completion_event_on_impl_thread_);
957 DCHECK(current_resource_update_controller_on_impl_thread_);
959 // Complete all remaining texture updates.
960 current_resource_update_controller_on_impl_thread_->Finalize();
961 current_resource_update_controller_on_impl_thread_.reset();
963 inside_commit_ = true;
964 layer_tree_host_impl_->BeginCommit();
965 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
966 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
967 layer_tree_host_impl_->CommitComplete();
968 inside_commit_ = false;
970 SetInputThrottledUntilCommitOnImplThread(false);
972 UpdateBackgroundAnimateTicking();
974 next_frame_is_newly_committed_frame_on_impl_thread_ = true;
976 if (layer_tree_host_->settings().impl_side_painting &&
977 commit_waits_for_activation_) {
978 // For some layer types in impl-side painting, the commit is held until
979 // the pending tree is activated. It's also possible that the
980 // pending tree has already activated if there was no work to be done.
981 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
982 completion_event_for_commit_held_on_tree_activation_ =
983 commit_completion_event_on_impl_thread_;
984 commit_completion_event_on_impl_thread_ = NULL;
985 } else {
986 commit_completion_event_on_impl_thread_->Signal();
987 commit_completion_event_on_impl_thread_ = NULL;
990 commit_waits_for_activation_ = false;
992 commit_complete_time_ = base::TimeTicks::HighResNow();
993 begin_frame_to_commit_duration_history_.InsertSample(
994 commit_complete_time_ - begin_frame_sent_to_main_thread_time_);
996 // SetVisible kicks off the next scheduler action, so this must be last.
997 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
1000 void ThreadProxy::ScheduledActionUpdateVisibleTiles() {
1001 DCHECK(IsImplThread());
1002 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionUpdateVisibleTiles");
1003 layer_tree_host_impl_->UpdateVisibleTiles();
1006 void ThreadProxy::ScheduledActionActivatePendingTree() {
1007 DCHECK(IsImplThread());
1008 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTree");
1009 layer_tree_host_impl_->ActivatePendingTree();
1012 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
1013 DCHECK(IsImplThread());
1014 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginOutputSurfaceCreation");
1015 Proxy::MainThreadTaskRunner()->PostTask(
1016 FROM_HERE,
1017 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface,
1018 main_thread_weak_ptr_));
1021 DrawSwapReadbackResult ThreadProxy::DrawSwapReadbackInternal(
1022 bool forced_draw,
1023 bool swap_requested,
1024 bool readback_requested) {
1025 DrawSwapReadbackResult result;
1026 result.did_draw = false;
1027 result.did_swap = false;
1028 result.did_readback = false;
1029 DCHECK(IsImplThread());
1030 DCHECK(layer_tree_host_impl_.get());
1031 if (!layer_tree_host_impl_)
1032 return result;
1034 DCHECK(layer_tree_host_impl_->renderer());
1035 if (!layer_tree_host_impl_->renderer())
1036 return result;
1038 base::TimeTicks monotonic_time =
1039 layer_tree_host_impl_->CurrentFrameTimeTicks();
1040 base::Time wall_clock_time = layer_tree_host_impl_->CurrentFrameTime();
1042 // TODO(enne): This should probably happen post-animate.
1043 if (layer_tree_host_impl_->pending_tree())
1044 layer_tree_host_impl_->pending_tree()->UpdateDrawProperties();
1045 layer_tree_host_impl_->Animate(monotonic_time, wall_clock_time);
1046 UpdateBackgroundAnimateTicking();
1048 base::TimeTicks start_time = base::TimeTicks::HighResNow();
1049 base::TimeDelta draw_duration_estimate = DrawDurationEstimate();
1050 base::AutoReset<bool> mark_inside(&inside_draw_, true);
1052 // This method is called on a forced draw, regardless of whether we are able
1053 // to produce a frame, as the calling site on main thread is blocked until its
1054 // request completes, and we signal completion here. If CanDraw() is false, we
1055 // will indicate success=false to the caller, but we must still signal
1056 // completion to avoid deadlock.
1058 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
1059 // frame, so can only be used when such a frame is possible. Since
1060 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
1061 // CanDraw() as well.
1063 // readback_request_on_impl_thread_ may be for the pending tree, do
1064 // not perform the readback unless explicitly requested.
1065 bool drawing_for_readback =
1066 readback_requested && !!readback_request_on_impl_thread_;
1067 bool can_do_readback = layer_tree_host_impl_->renderer()->CanReadPixels();
1069 LayerTreeHostImpl::FrameData frame;
1070 bool draw_frame = false;
1071 bool start_ready_animations = true;
1073 if (layer_tree_host_impl_->CanDraw() &&
1074 (!drawing_for_readback || can_do_readback)) {
1075 // If it is for a readback, make sure we draw the portion being read back.
1076 gfx::Rect readback_rect;
1077 if (drawing_for_readback)
1078 readback_rect = readback_request_on_impl_thread_->rect;
1080 // Do not start animations if we skip drawing the frame to avoid
1081 // checkerboarding.
1082 if (layer_tree_host_impl_->PrepareToDraw(&frame, readback_rect) ||
1083 forced_draw)
1084 draw_frame = true;
1085 else
1086 start_ready_animations = false;
1089 if (draw_frame) {
1090 layer_tree_host_impl_->DrawLayers(
1091 &frame,
1092 scheduler_on_impl_thread_->LastBeginFrameOnImplThreadTime());
1093 result.did_draw = true;
1095 layer_tree_host_impl_->DidDrawAllLayers(frame);
1096 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
1098 // Check for a pending CompositeAndReadback.
1099 if (drawing_for_readback) {
1100 DCHECK(!swap_requested);
1101 result.did_readback = false;
1102 if (draw_frame && !layer_tree_host_impl_->IsContextLost()) {
1103 layer_tree_host_impl_->Readback(readback_request_on_impl_thread_->pixels,
1104 readback_request_on_impl_thread_->rect);
1105 result.did_readback = true;
1107 readback_request_on_impl_thread_->success = result.did_readback;
1108 readback_request_on_impl_thread_->completion.Signal();
1109 readback_request_on_impl_thread_ = NULL;
1110 } else if (draw_frame) {
1111 DCHECK(swap_requested);
1112 result.did_swap = layer_tree_host_impl_->SwapBuffers(frame);
1114 // We don't know if we have incomplete tiles if we didn't actually swap.
1115 if (result.did_swap) {
1116 DCHECK(!frame.has_no_damage);
1117 SetSwapUsedIncompleteTileOnImplThread(frame.contains_incomplete_tile);
1121 // Tell the main thread that the the newly-commited frame was drawn.
1122 if (next_frame_is_newly_committed_frame_on_impl_thread_) {
1123 next_frame_is_newly_committed_frame_on_impl_thread_ = false;
1124 Proxy::MainThreadTaskRunner()->PostTask(
1125 FROM_HERE,
1126 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_));
1129 if (draw_frame) {
1130 CheckOutputSurfaceStatusOnImplThread();
1132 base::TimeDelta draw_duration = base::TimeTicks::HighResNow() - start_time;
1133 draw_duration_history_.InsertSample(draw_duration);
1134 base::TimeDelta draw_duration_overestimate;
1135 base::TimeDelta draw_duration_underestimate;
1136 if (draw_duration > draw_duration_estimate)
1137 draw_duration_underestimate = draw_duration - draw_duration_estimate;
1138 else
1139 draw_duration_overestimate = draw_duration_estimate - draw_duration;
1140 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDuration",
1141 draw_duration,
1142 base::TimeDelta::FromMilliseconds(1),
1143 base::TimeDelta::FromMilliseconds(100),
1144 50);
1145 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationUnderestimate",
1146 draw_duration_underestimate,
1147 base::TimeDelta::FromMilliseconds(1),
1148 base::TimeDelta::FromMilliseconds(100),
1149 50);
1150 UMA_HISTOGRAM_CUSTOM_TIMES("Renderer.DrawDurationOverestimate",
1151 draw_duration_overestimate,
1152 base::TimeDelta::FromMilliseconds(1),
1153 base::TimeDelta::FromMilliseconds(100),
1154 50);
1157 return result;
1160 void ThreadProxy::AcquireLayerTextures() {
1161 // Called when the main thread needs to modify a layer texture that is used
1162 // directly by the compositor.
1163 // This method will block until the next compositor draw if there is a
1164 // previously committed frame that is still undrawn. This is necessary to
1165 // ensure that the main thread does not monopolize access to the textures.
1166 DCHECK(IsMainThread());
1168 if (textures_acquired_)
1169 return;
1171 TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures");
1172 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1173 CompletionEvent completion;
1174 Proxy::ImplThreadTaskRunner()->PostTask(
1175 FROM_HERE,
1176 base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread,
1177 impl_thread_weak_ptr_,
1178 &completion));
1179 // Block until it is safe to write to layer textures from the main thread.
1180 completion.Wait();
1182 textures_acquired_ = true;
1183 can_cancel_commit_ = false;
1186 void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread(
1187 CompletionEvent* completion) {
1188 DCHECK(IsImplThread());
1189 DCHECK(!texture_acquisition_completion_event_on_impl_thread_);
1191 texture_acquisition_completion_event_on_impl_thread_ = completion;
1192 scheduler_on_impl_thread_->SetMainThreadNeedsLayerTextures();
1195 void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() {
1196 DCHECK(texture_acquisition_completion_event_on_impl_thread_);
1197 texture_acquisition_completion_event_on_impl_thread_->Signal();
1198 texture_acquisition_completion_event_on_impl_thread_ = NULL;
1201 void ThreadProxy::ScheduledActionManageTiles() {
1202 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionManageTiles");
1203 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
1204 layer_tree_host_impl_->ManageTiles();
1207 DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1208 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
1209 bool forced_draw = false;
1210 bool swap_requested = true;
1211 bool readback_requested = false;
1212 return DrawSwapReadbackInternal(
1213 forced_draw, swap_requested, readback_requested);
1216 DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndSwapForced() {
1217 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwapForced");
1218 bool forced_draw = true;
1219 bool swap_requested = true;
1220 bool readback_requested = false;
1221 return DrawSwapReadbackInternal(
1222 forced_draw, swap_requested, readback_requested);
1225 DrawSwapReadbackResult ThreadProxy::ScheduledActionDrawAndReadback() {
1226 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndReadback");
1227 bool forced_draw = true;
1228 bool swap_requested = false;
1229 bool readback_requested = true;
1230 return DrawSwapReadbackInternal(
1231 forced_draw, swap_requested, readback_requested);
1234 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1235 if (current_resource_update_controller_on_impl_thread_)
1236 current_resource_update_controller_on_impl_thread_
1237 ->PerformMoreUpdates(time);
1238 layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame();
1241 base::TimeDelta ThreadProxy::DrawDurationEstimate() {
1242 base::TimeDelta historical_estimate =
1243 draw_duration_history_.Percentile(kDrawDurationEstimationPercentile);
1244 base::TimeDelta padding = base::TimeDelta::FromMicroseconds(
1245 kDrawDurationEstimatePaddingInMicroseconds);
1246 return historical_estimate + padding;
1249 base::TimeDelta ThreadProxy::BeginFrameToCommitDurationEstimate() {
1250 return begin_frame_to_commit_duration_history_.Percentile(
1251 kCommitAndActivationDurationEstimationPercentile);
1254 base::TimeDelta ThreadProxy::CommitToActivateDurationEstimate() {
1255 return commit_to_activate_duration_history_.Percentile(
1256 kCommitAndActivationDurationEstimationPercentile);
1259 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1260 DCHECK(IsImplThread());
1261 scheduler_on_impl_thread_->FinishCommit();
1264 void ThreadProxy::DidCommitAndDrawFrame() {
1265 DCHECK(IsMainThread());
1266 if (!layer_tree_host_)
1267 return;
1268 layer_tree_host_->DidCommitAndDrawFrame();
1271 void ThreadProxy::DidCompleteSwapBuffers() {
1272 DCHECK(IsMainThread());
1273 if (!layer_tree_host_)
1274 return;
1275 layer_tree_host_->DidCompleteSwapBuffers();
1278 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
1279 base::Time wall_clock_time) {
1280 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1281 DCHECK(IsMainThread());
1282 if (!layer_tree_host_)
1283 return;
1284 layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time);
1287 void ThreadProxy::CreateAndInitializeOutputSurface() {
1288 TRACE_EVENT0("cc", "ThreadProxy::CreateAndInitializeOutputSurface");
1289 DCHECK(IsMainThread());
1291 // Check that output surface has not been recreated by CompositeAndReadback
1292 // after this task is posted but before it is run.
1293 bool has_initialized_output_surface_on_impl_thread = true;
1295 CompletionEvent completion;
1296 Proxy::ImplThreadTaskRunner()->PostTask(
1297 FROM_HERE,
1298 base::Bind(&ThreadProxy::HasInitializedOutputSurfaceOnImplThread,
1299 impl_thread_weak_ptr_,
1300 &completion,
1301 &has_initialized_output_surface_on_impl_thread));
1302 completion.Wait();
1304 if (has_initialized_output_surface_on_impl_thread)
1305 return;
1307 layer_tree_host_->DidLoseOutputSurface();
1308 output_surface_creation_callback_.Reset(base::Bind(
1309 &ThreadProxy::DoCreateAndInitializeOutputSurface,
1310 base::Unretained(this)));
1311 output_surface_creation_callback_.callback().Run();
1314 void ThreadProxy::HasInitializedOutputSurfaceOnImplThread(
1315 CompletionEvent* completion,
1316 bool* has_initialized_output_surface) {
1317 DCHECK(IsImplThread());
1318 *has_initialized_output_surface =
1319 scheduler_on_impl_thread_->HasInitializedOutputSurface();
1320 completion->Signal();
1323 void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion) {
1324 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1325 DCHECK(IsImplThread());
1326 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
1327 const LayerTreeSettings& settings = layer_tree_host_->settings();
1328 SchedulerSettings scheduler_settings;
1329 scheduler_settings.impl_side_painting = settings.impl_side_painting;
1330 scheduler_settings.timeout_and_draw_when_animation_checkerboards =
1331 settings.timeout_and_draw_when_animation_checkerboards;
1332 scheduler_settings.maximum_number_of_failed_draws_before_draw_is_forced_ =
1333 settings.maximum_number_of_failed_draws_before_draw_is_forced_;
1334 scheduler_settings.using_synchronous_renderer_compositor =
1335 settings.using_synchronous_renderer_compositor;
1336 scheduler_settings.throttle_frame_production =
1337 settings.throttle_frame_production;
1338 scheduler_on_impl_thread_ = Scheduler::Create(this, scheduler_settings);
1339 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
1341 impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr();
1342 completion->Signal();
1345 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1346 CompletionEvent* completion,
1347 scoped_ptr<OutputSurface> output_surface,
1348 scoped_refptr<ContextProvider> offscreen_context_provider,
1349 bool* success,
1350 RendererCapabilities* capabilities) {
1351 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1352 DCHECK(IsImplThread());
1353 DCHECK(IsMainThreadBlocked());
1354 DCHECK(success);
1355 DCHECK(capabilities);
1357 layer_tree_host_->DeleteContentsTexturesOnImplThread(
1358 layer_tree_host_impl_->resource_provider());
1360 *success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
1362 if (*success) {
1363 *capabilities = layer_tree_host_impl_->GetRendererCapabilities();
1364 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
1365 } else if (offscreen_context_provider.get()) {
1366 if (offscreen_context_provider->BindToCurrentThread())
1367 offscreen_context_provider->VerifyContexts();
1368 offscreen_context_provider = NULL;
1371 layer_tree_host_impl_->SetOffscreenContextProvider(
1372 offscreen_context_provider);
1374 completion->Signal();
1377 void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) {
1378 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
1379 DCHECK(IsImplThread());
1380 if (layer_tree_host_impl_->resource_provider())
1381 layer_tree_host_impl_->resource_provider()->Finish();
1382 completion->Signal();
1385 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
1386 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1387 DCHECK(IsImplThread());
1388 layer_tree_host_->DeleteContentsTexturesOnImplThread(
1389 layer_tree_host_impl_->resource_provider());
1390 layer_tree_host_impl_->SetNeedsBeginFrame(false);
1391 scheduler_on_impl_thread_.reset();
1392 layer_tree_host_impl_.reset();
1393 weak_factory_on_impl_thread_.InvalidateWeakPtrs();
1394 completion->Signal();
1397 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1398 return ResourceUpdateController::MaxPartialTextureUpdates();
1401 ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
1402 : memory_allocation_limit_bytes(0), evicted_ui_resources(false) {}
1404 ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {}
1406 scoped_ptr<base::Value> ThreadProxy::AsValue() const {
1407 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1409 CompletionEvent completion;
1411 DebugScopedSetMainThreadBlocked main_thread_blocked(
1412 const_cast<ThreadProxy*>(this));
1413 Proxy::ImplThreadTaskRunner()->PostTask(
1414 FROM_HERE,
1415 base::Bind(&ThreadProxy::AsValueOnImplThread,
1416 impl_thread_weak_ptr_,
1417 &completion,
1418 state.get()));
1419 completion.Wait();
1421 return state.PassAs<base::Value>();
1424 void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
1425 base::DictionaryValue* state) const {
1426 state->Set("layer_tree_host_impl",
1427 layer_tree_host_impl_->AsValue().release());
1428 completion->Signal();
1431 bool ThreadProxy::CommitPendingForTesting() {
1432 DCHECK(IsMainThread());
1433 CommitPendingRequest commit_pending_request;
1435 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1436 Proxy::ImplThreadTaskRunner()->PostTask(
1437 FROM_HERE,
1438 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting,
1439 impl_thread_weak_ptr_,
1440 &commit_pending_request));
1441 commit_pending_request.completion.Wait();
1443 return commit_pending_request.commit_pending;
1446 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1447 CommitPendingRequest* request) {
1448 DCHECK(IsImplThread());
1449 if (layer_tree_host_impl_->output_surface())
1450 request->commit_pending = scheduler_on_impl_thread_->CommitPending();
1451 else
1452 request->commit_pending = false;
1453 request->completion.Signal();
1456 scoped_ptr<base::Value> ThreadProxy::SchedulerStateAsValueForTesting() {
1457 if (IsImplThread())
1458 return scheduler_on_impl_thread_->StateAsValue().Pass();
1460 SchedulerStateRequest scheduler_state_request;
1462 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1463 Proxy::ImplThreadTaskRunner()->PostTask(
1464 FROM_HERE,
1465 base::Bind(&ThreadProxy::SchedulerStateAsValueOnImplThreadForTesting,
1466 impl_thread_weak_ptr_,
1467 &scheduler_state_request));
1468 scheduler_state_request.completion.Wait();
1470 return scheduler_state_request.state.Pass();
1473 void ThreadProxy::SchedulerStateAsValueOnImplThreadForTesting(
1474 SchedulerStateRequest* request) {
1475 DCHECK(IsImplThread());
1476 request->state = scheduler_on_impl_thread_->StateAsValue();
1477 request->completion.Signal();
1480 void ThreadProxy::RenewTreePriority() {
1481 DCHECK(IsImplThread());
1482 bool smoothness_takes_priority =
1483 layer_tree_host_impl_->pinch_gesture_active() ||
1484 layer_tree_host_impl_->CurrentlyScrollingLayer() ||
1485 layer_tree_host_impl_->page_scale_animation_active();
1487 base::TimeTicks now = layer_tree_host_impl_->CurrentPhysicalTimeTicks();
1489 // Update expiration time if smoothness currently takes priority.
1490 if (smoothness_takes_priority) {
1491 smoothness_takes_priority_expiration_time_ =
1492 now + base::TimeDelta::FromMilliseconds(
1493 kSmoothnessTakesPriorityExpirationDelay * 1000);
1496 // We use the same priority for both trees by default.
1497 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES;
1499 // Smoothness takes priority if expiration time is in the future.
1500 if (smoothness_takes_priority_expiration_time_ > now)
1501 priority = SMOOTHNESS_TAKES_PRIORITY;
1503 // New content always takes priority when the active tree has
1504 // evicted resources or there is an invalid viewport size.
1505 if (layer_tree_host_impl_->active_tree()->ContentsTexturesPurged() ||
1506 layer_tree_host_impl_->active_tree()->ViewportSizeInvalid() ||
1507 layer_tree_host_impl_->EvictedUIResourcesExist() ||
1508 input_throttled_until_commit_)
1509 priority = NEW_CONTENT_TAKES_PRIORITY;
1511 layer_tree_host_impl_->SetTreePriority(priority);
1513 // Notify the the client of this compositor via the output surface.
1514 // TODO(epenner): Route this to compositor-thread instead of output-surface
1515 // after GTFO refactor of compositor-thread (http://crbug/170828).
1516 if (layer_tree_host_impl_->output_surface()) {
1517 layer_tree_host_impl_->output_surface()->
1518 UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY);
1521 base::TimeDelta delay = smoothness_takes_priority_expiration_time_ - now;
1523 // Need to make sure a delayed task is posted when we have smoothness
1524 // takes priority expiration time in the future.
1525 if (delay <= base::TimeDelta())
1526 return;
1527 if (renew_tree_priority_on_impl_thread_pending_)
1528 return;
1530 Proxy::ImplThreadTaskRunner()->PostDelayedTask(
1531 FROM_HERE,
1532 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread,
1533 weak_factory_on_impl_thread_.GetWeakPtr()),
1534 delay);
1536 renew_tree_priority_on_impl_thread_pending_ = true;
1539 void ThreadProxy::RenewTreePriorityOnImplThread() {
1540 DCHECK(renew_tree_priority_on_impl_thread_pending_);
1541 renew_tree_priority_on_impl_thread_pending_ = false;
1543 RenewTreePriority();
1546 void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay) {
1547 Proxy::ImplThreadTaskRunner()->PostDelayedTask(
1548 FROM_HERE,
1549 base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread,
1550 impl_thread_weak_ptr_),
1551 delay);
1554 void ThreadProxy::StartScrollbarAnimationOnImplThread() {
1555 layer_tree_host_impl_->StartScrollbarAnimation();
1558 void ThreadProxy::DidActivatePendingTree() {
1559 DCHECK(IsImplThread());
1560 TRACE_EVENT0("cc", "ThreadProxy::DidActivatePendingTreeOnImplThread");
1562 if (completion_event_for_commit_held_on_tree_activation_ &&
1563 !layer_tree_host_impl_->pending_tree()) {
1564 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
1565 TRACE_EVENT_SCOPE_THREAD);
1566 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
1567 completion_event_for_commit_held_on_tree_activation_->Signal();
1568 completion_event_for_commit_held_on_tree_activation_ = NULL;
1571 UpdateBackgroundAnimateTicking();
1573 commit_to_activate_duration_history_.InsertSample(
1574 base::TimeTicks::HighResNow() - commit_complete_time_);
1577 } // namespace cc