Fix revert "[chromeos] Remove dependencies of StatisticsProvider on chrome."
[chromium-blink-merge.git] / cc / trees / thread_proxy.cc
blob166e6e2f971b2856e1f443ef8094b785c053e60f
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/thread_proxy.h"
7 #include "base/auto_reset.h"
8 #include "base/bind.h"
9 #include "base/debug/trace_event.h"
10 #include "cc/base/thread.h"
11 #include "cc/input/input_handler.h"
12 #include "cc/output/context_provider.h"
13 #include "cc/output/output_surface.h"
14 #include "cc/quads/draw_quad.h"
15 #include "cc/resources/prioritized_resource_manager.h"
16 #include "cc/scheduler/delay_based_time_source.h"
17 #include "cc/scheduler/frame_rate_controller.h"
18 #include "cc/scheduler/scheduler.h"
19 #include "cc/scheduler/vsync_time_source.h"
20 #include "cc/trees/layer_tree_host.h"
21 #include "cc/trees/layer_tree_impl.h"
23 namespace {
25 // Measured in seconds.
26 const double kContextRecreationTickRate = 0.03;
28 // Measured in seconds.
29 const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
31 } // namespace
33 namespace cc {
35 scoped_ptr<Proxy> ThreadProxy::Create(LayerTreeHost* layer_tree_host,
36 scoped_ptr<Thread> impl_thread) {
37 return make_scoped_ptr(
38 new ThreadProxy(layer_tree_host, impl_thread.Pass())).PassAs<Proxy>();
41 ThreadProxy::ThreadProxy(LayerTreeHost* layer_tree_host,
42 scoped_ptr<Thread> impl_thread)
43 : Proxy(impl_thread.Pass()),
44 animate_requested_(false),
45 commit_requested_(false),
46 commit_request_sent_to_impl_thread_(false),
47 created_offscreen_context_provider_(false),
48 layer_tree_host_(layer_tree_host),
49 started_(false),
50 textures_acquired_(true),
51 in_composite_and_readback_(false),
52 manage_tiles_pending_(false),
53 weak_factory_on_impl_thread_(this),
54 weak_factory_(this),
55 begin_frame_completion_event_on_impl_thread_(NULL),
56 readback_request_on_impl_thread_(NULL),
57 commit_completion_event_on_impl_thread_(NULL),
58 completion_event_for_commit_held_on_tree_activation_(NULL),
59 texture_acquisition_completion_event_on_impl_thread_(NULL),
60 next_frame_is_newly_committed_frame_on_impl_thread_(false),
61 render_vsync_enabled_(layer_tree_host->settings().render_vsync_enabled),
62 render_vsync_notification_enabled_(
63 layer_tree_host->settings().render_vsync_notification_enabled),
64 vsync_client_(NULL),
65 inside_draw_(false),
66 defer_commits_(false),
67 renew_tree_priority_on_impl_thread_pending_(false) {
68 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
69 DCHECK(IsMainThread());
70 DCHECK(layer_tree_host_);
73 ThreadProxy::~ThreadProxy() {
74 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
75 DCHECK(IsMainThread());
76 DCHECK(!started_);
79 bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
80 TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
81 DCHECK(IsMainThread());
82 DCHECK(layer_tree_host_);
83 DCHECK(!defer_commits_);
85 if (!layer_tree_host_->InitializeOutputSurfaceIfNeeded()) {
86 TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized");
87 return false;
90 // Perform a synchronous commit.
92 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
93 CompletionEvent begin_frame_completion;
94 Proxy::ImplThread()->PostTask(
95 base::Bind(&ThreadProxy::ForceBeginFrameOnImplThread,
96 impl_thread_weak_ptr_,
97 &begin_frame_completion));
98 begin_frame_completion.Wait();
100 in_composite_and_readback_ = true;
101 BeginFrame(scoped_ptr<BeginFrameAndCommitState>());
102 in_composite_and_readback_ = false;
104 // Perform a synchronous readback.
105 ReadbackRequest request;
106 request.rect = rect;
107 request.pixels = pixels;
109 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
110 Proxy::ImplThread()->PostTask(
111 base::Bind(&ThreadProxy::RequestReadbackOnImplThread,
112 impl_thread_weak_ptr_,
113 &request));
114 request.completion.Wait();
116 return request.success;
119 void ThreadProxy::RequestReadbackOnImplThread(ReadbackRequest* request) {
120 DCHECK(Proxy::IsImplThread());
121 DCHECK(!readback_request_on_impl_thread_);
122 if (!layer_tree_host_impl_) {
123 request->success = false;
124 request->completion.Signal();
125 return;
128 readback_request_on_impl_thread_ = request;
129 scheduler_on_impl_thread_->SetNeedsRedraw();
130 scheduler_on_impl_thread_->SetNeedsForcedRedraw();
133 void ThreadProxy::FinishAllRendering() {
134 DCHECK(Proxy::IsMainThread());
135 DCHECK(!defer_commits_);
137 // Make sure all GL drawing is finished on the impl thread.
138 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
139 CompletionEvent completion;
140 Proxy::ImplThread()->PostTask(
141 base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread,
142 impl_thread_weak_ptr_,
143 &completion));
144 completion.Wait();
147 bool ThreadProxy::IsStarted() const {
148 DCHECK(Proxy::IsMainThread());
149 return started_;
152 void ThreadProxy::SetSurfaceReady() {
153 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReady");
154 Proxy::ImplThread()->PostTask(base::Bind(
155 &ThreadProxy::SetSurfaceReadyOnImplThread, impl_thread_weak_ptr_));
158 void ThreadProxy::SetSurfaceReadyOnImplThread() {
159 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReadyOnImplThread");
160 scheduler_on_impl_thread_->SetCanStart();
163 void ThreadProxy::SetVisible(bool visible) {
164 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
165 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
166 CompletionEvent completion;
167 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::SetVisibleOnImplThread,
168 impl_thread_weak_ptr_,
169 &completion,
170 visible));
171 completion.Wait();
174 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
175 bool visible) {
176 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
177 layer_tree_host_impl_->SetVisible(visible);
178 scheduler_on_impl_thread_->SetVisible(visible);
179 completion->Signal();
182 void ThreadProxy::DoCreateAndInitializeOutputSurface() {
183 TRACE_EVENT0("cc", "ThreadProxy::DoCreateAndInitializeOutputSurface");
184 DCHECK(IsMainThread());
186 scoped_ptr<OutputSurface> output_surface = first_output_surface_.Pass();
187 if (!output_surface)
188 output_surface = layer_tree_host_->CreateOutputSurface();
190 RendererCapabilities capabilities;
191 bool success = !!output_surface;
192 if (!success) {
193 OnOutputSurfaceInitializeAttempted(false, capabilities);
194 return;
197 scoped_refptr<ContextProvider> offscreen_context_provider;
198 if (created_offscreen_context_provider_) {
199 offscreen_context_provider = layer_tree_host_->client()->
200 OffscreenContextProviderForCompositorThread();
201 success = !!offscreen_context_provider;
202 if (!success) {
203 OnOutputSurfaceInitializeAttempted(false, capabilities);
204 return;
208 success = false;
210 // Make a blocking call to InitializeOutputSurfaceOnImplThread. The results
211 // of that call are pushed into the success and capabilities local
212 // variables.
213 CompletionEvent completion;
214 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
216 Proxy::ImplThread()->PostTask(
217 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
218 impl_thread_weak_ptr_,
219 &completion,
220 base::Passed(&output_surface),
221 offscreen_context_provider,
222 &success,
223 &capabilities));
224 completion.Wait();
227 OnOutputSurfaceInitializeAttempted(success, capabilities);
230 void ThreadProxy::OnOutputSurfaceInitializeAttempted(
231 bool success,
232 const RendererCapabilities& capabilities) {
233 DCHECK(IsMainThread());
234 DCHECK(layer_tree_host_);
236 if (success) {
237 renderer_capabilities_main_thread_copy_ = capabilities;
240 LayerTreeHost::CreateResult result =
241 layer_tree_host_->OnCreateAndInitializeOutputSurfaceAttempted(success);
242 if (result == LayerTreeHost::CreateFailedButTryAgain) {
243 if (!output_surface_creation_callback_.callback().is_null()) {
244 Proxy::MainThread()->PostTask(
245 output_surface_creation_callback_.callback());
247 } else {
248 output_surface_creation_callback_.Cancel();
252 const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
253 DCHECK(IsMainThread());
254 DCHECK(!layer_tree_host_->output_surface_lost());
255 return renderer_capabilities_main_thread_copy_;
258 void ThreadProxy::SetNeedsAnimate() {
259 DCHECK(IsMainThread());
260 if (animate_requested_)
261 return;
263 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
264 animate_requested_ = true;
266 if (commit_request_sent_to_impl_thread_)
267 return;
268 commit_request_sent_to_impl_thread_ = true;
269 Proxy::ImplThread()->PostTask(base::Bind(
270 &ThreadProxy::SetNeedsCommitOnImplThread, impl_thread_weak_ptr_));
273 void ThreadProxy::SetNeedsCommit() {
274 DCHECK(IsMainThread());
275 if (commit_requested_)
276 return;
277 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
278 commit_requested_ = true;
280 if (commit_request_sent_to_impl_thread_)
281 return;
282 commit_request_sent_to_impl_thread_ = true;
283 Proxy::ImplThread()->PostTask(base::Bind(
284 &ThreadProxy::SetNeedsCommitOnImplThread, impl_thread_weak_ptr_));
287 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
288 DCHECK(IsImplThread());
289 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
290 Proxy::ImplThread()->PostTask(
291 base::Bind(&ThreadProxy::CheckOutputSurfaceStatusOnImplThread,
292 impl_thread_weak_ptr_));
295 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
296 DCHECK(IsImplThread());
297 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
298 if (!layer_tree_host_impl_->IsContextLost())
299 return;
300 if (cc::ContextProvider* offscreen_contexts = layer_tree_host_impl_->
301 resource_provider()->offscreen_context_provider())
302 offscreen_contexts->VerifyContexts();
303 scheduler_on_impl_thread_->DidLoseOutputSurface();
306 void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
307 DCHECK(IsImplThread());
308 TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
309 scheduler_on_impl_thread_->DidSwapBuffersComplete();
310 Proxy::MainThread()->PostTask(
311 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
314 void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase,
315 base::TimeDelta interval) {
316 DCHECK(IsImplThread());
317 TRACE_EVENT2("cc",
318 "ThreadProxy::OnVSyncParametersChanged",
319 "timebase",
320 (timebase - base::TimeTicks()).InMilliseconds(),
321 "interval",
322 interval.InMilliseconds());
323 scheduler_on_impl_thread_->SetTimebaseAndInterval(timebase, interval);
326 void ThreadProxy::DidVSync(base::TimeTicks frame_time) {
327 DCHECK(IsImplThread());
328 TRACE_EVENT0("cc", "ThreadProxy::DidVSync");
329 if (vsync_client_)
330 vsync_client_->DidVSync(frame_time);
333 void ThreadProxy::RequestVSyncNotification(VSyncClient* client) {
334 DCHECK(IsImplThread());
335 TRACE_EVENT1(
336 "cc", "ThreadProxy::RequestVSyncNotification", "enable", !!client);
337 vsync_client_ = client;
338 layer_tree_host_impl_->EnableVSyncNotification(!!client);
341 void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
342 DCHECK(IsImplThread());
343 TRACE_EVENT1(
344 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
345 scheduler_on_impl_thread_->SetCanDraw(can_draw);
346 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
347 !scheduler_on_impl_thread_->WillDrawIfNeeded());
350 void ThreadProxy::OnHasPendingTreeStateChanged(bool has_pending_tree) {
351 DCHECK(IsImplThread());
352 TRACE_EVENT1("cc",
353 "ThreadProxy::OnHasPendingTreeStateChanged",
354 "has_pending_tree",
355 has_pending_tree);
356 scheduler_on_impl_thread_->SetHasPendingTree(has_pending_tree);
359 void ThreadProxy::SetNeedsCommitOnImplThread() {
360 DCHECK(IsImplThread());
361 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
362 scheduler_on_impl_thread_->SetNeedsCommit();
365 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
366 if (manage_tiles_pending_)
367 return;
368 Proxy::ImplThread()->PostTask(
369 base::Bind(&ThreadProxy::ManageTilesOnImplThread, impl_thread_weak_ptr_));
370 manage_tiles_pending_ = true;
373 void ThreadProxy::ManageTilesOnImplThread() {
374 // TODO(nduca): If needed, move this into CCSchedulerStateMachine.
375 manage_tiles_pending_ = false;
376 if (layer_tree_host_impl_)
377 layer_tree_host_impl_->ManageTiles();
380 void ThreadProxy::SetNeedsForcedCommitOnImplThread() {
381 DCHECK(IsImplThread());
382 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsForcedCommitOnImplThread");
383 scheduler_on_impl_thread_->SetNeedsForcedCommit();
386 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
387 scoped_ptr<AnimationEventsVector> events,
388 base::Time wall_clock_time) {
389 DCHECK(IsImplThread());
390 TRACE_EVENT0("cc",
391 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
392 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::SetAnimationEvents,
393 main_thread_weak_ptr_,
394 base::Passed(&events),
395 wall_clock_time));
398 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
399 int priority_cutoff) {
400 DCHECK(IsImplThread());
402 if (!layer_tree_host_->contents_texture_manager())
403 return false;
405 bool reduce_result = layer_tree_host_->contents_texture_manager()->
406 ReduceMemoryOnImplThread(limit_bytes,
407 priority_cutoff,
408 layer_tree_host_impl_->resource_provider());
409 if (!reduce_result)
410 return false;
412 // The texture upload queue may reference textures that were just purged,
413 // clear them from the queue.
414 if (current_resource_update_controller_on_impl_thread_) {
415 current_resource_update_controller_on_impl_thread_->
416 DiscardUploadsToEvictedResources();
418 return true;
421 void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
422 DCHECK(IsImplThread());
424 if (!layer_tree_host_->contents_texture_manager())
425 return;
427 layer_tree_host_->contents_texture_manager()->ReduceWastedMemoryOnImplThread(
428 layer_tree_host_impl_->resource_provider());
431 void ThreadProxy::SendManagedMemoryStats() {
432 DCHECK(IsImplThread());
433 if (!layer_tree_host_impl_)
434 return;
435 if (!layer_tree_host_->contents_texture_manager())
436 return;
438 // If we are using impl-side painting, then SendManagedMemoryStats is called
439 // directly after the tile manager's manage function, and doesn't need to
440 // interact with main thread's layer tree.
441 if (layer_tree_host_->settings().impl_side_painting)
442 return;
444 layer_tree_host_impl_->SendManagedMemoryStats(
445 layer_tree_host_->contents_texture_manager()->MemoryVisibleBytes(),
446 layer_tree_host_->contents_texture_manager()->
447 MemoryVisibleAndNearbyBytes(),
448 layer_tree_host_->contents_texture_manager()->MemoryUseBytes());
451 bool ThreadProxy::IsInsideDraw() { return inside_draw_; }
453 void ThreadProxy::SetNeedsRedraw(gfx::Rect damage_rect) {
454 DCHECK(IsMainThread());
455 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
456 Proxy::ImplThread()->PostTask(base::Bind(
457 &ThreadProxy::SetNeedsRedrawRectOnImplThread,
458 impl_thread_weak_ptr_, damage_rect));
461 void ThreadProxy::SetDeferCommits(bool defer_commits) {
462 DCHECK(IsMainThread());
463 DCHECK_NE(defer_commits_, defer_commits);
464 defer_commits_ = defer_commits;
466 if (defer_commits_)
467 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
468 else
469 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
471 if (!defer_commits_ && pending_deferred_commit_)
472 Proxy::MainThread()->PostTask(
473 base::Bind(&ThreadProxy::BeginFrame,
474 main_thread_weak_ptr_,
475 base::Passed(&pending_deferred_commit_)));
478 bool ThreadProxy::CommitRequested() const {
479 DCHECK(IsMainThread());
480 return commit_requested_;
483 void ThreadProxy::SetNeedsRedrawOnImplThread() {
484 DCHECK(IsImplThread());
485 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
486 scheduler_on_impl_thread_->SetNeedsRedraw();
489 void ThreadProxy::SetNeedsRedrawRectOnImplThread(gfx::Rect damage_rect) {
490 DCHECK(IsImplThread());
491 layer_tree_host_impl_->SetViewportDamage(damage_rect);
492 SetNeedsRedrawOnImplThread();
495 void ThreadProxy::DidSwapUseIncompleteTileOnImplThread() {
496 DCHECK(IsImplThread());
497 TRACE_EVENT0("cc", "ThreadProxy::DidSwapUseIncompleteTileOnImplThread");
498 scheduler_on_impl_thread_->DidSwapUseIncompleteTile();
501 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
502 DCHECK(IsImplThread());
503 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
504 scheduler_on_impl_thread_->SetNeedsRedraw();
507 void ThreadProxy::MainThreadHasStoppedFlinging() {
508 DCHECK(IsMainThread());
509 Proxy::ImplThread()->PostTask(
510 base::Bind(&ThreadProxy::MainThreadHasStoppedFlingingOnImplThread,
511 impl_thread_weak_ptr_));
514 void ThreadProxy::MainThreadHasStoppedFlingingOnImplThread() {
515 DCHECK(IsImplThread());
516 if (input_handler_client_on_impl_thread_)
517 input_handler_client_on_impl_thread_->MainThreadHasStoppedFlinging();
520 void ThreadProxy::Start(scoped_ptr<OutputSurface> first_output_surface) {
521 DCHECK(IsMainThread());
522 DCHECK(Proxy::ImplThread());
523 DCHECK(first_output_surface);
524 // Create LayerTreeHostImpl.
525 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
526 CompletionEvent completion;
527 scoped_ptr<InputHandlerClient> input_handler_client =
528 layer_tree_host_->CreateInputHandlerClient();
529 Proxy::ImplThread()->PostTask(
530 base::Bind(&ThreadProxy::InitializeImplOnImplThread,
531 base::Unretained(this),
532 &completion,
533 input_handler_client.release()));
534 completion.Wait();
536 main_thread_weak_ptr_ = weak_factory_.GetWeakPtr();
537 first_output_surface_ = first_output_surface.Pass();
539 started_ = true;
542 void ThreadProxy::Stop() {
543 TRACE_EVENT0("cc", "ThreadProxy::Stop");
544 DCHECK(IsMainThread());
545 DCHECK(started_);
547 // Synchronously finishes pending GL operations and deletes the impl.
548 // The two steps are done as separate post tasks, so that tasks posted
549 // by the GL implementation due to the Finish can be executed by the
550 // renderer before shutting it down.
552 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
554 CompletionEvent completion;
555 Proxy::ImplThread()->PostTask(
556 base::Bind(&ThreadProxy::FinishGLOnImplThread,
557 impl_thread_weak_ptr_,
558 &completion));
559 completion.Wait();
562 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
564 CompletionEvent completion;
565 Proxy::ImplThread()->PostTask(
566 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread,
567 impl_thread_weak_ptr_,
568 &completion));
569 completion.Wait();
572 weak_factory_.InvalidateWeakPtrs();
574 DCHECK(!layer_tree_host_impl_.get()); // verify that the impl deleted.
575 layer_tree_host_ = NULL;
576 started_ = false;
579 void ThreadProxy::ForceSerializeOnSwapBuffers() {
580 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
581 CompletionEvent completion;
582 Proxy::ImplThread()->PostTask(
583 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
584 impl_thread_weak_ptr_,
585 &completion));
586 completion.Wait();
589 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
590 CompletionEvent* completion) {
591 if (layer_tree_host_impl_->renderer())
592 layer_tree_host_impl_->renderer()->DoNoOp();
593 completion->Signal();
596 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
597 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
598 DCHECK(IsImplThread());
599 layer_tree_host_impl_->FinishAllRendering();
600 completion->Signal();
603 void ThreadProxy::ForceBeginFrameOnImplThread(CompletionEvent* completion) {
604 TRACE_EVENT0("cc", "ThreadProxy::ForceBeginFrameOnImplThread");
605 DCHECK(!begin_frame_completion_event_on_impl_thread_);
607 SetNeedsForcedCommitOnImplThread();
608 if (scheduler_on_impl_thread_->CommitPending()) {
609 completion->Signal();
610 return;
613 begin_frame_completion_event_on_impl_thread_ = completion;
616 void ThreadProxy::ScheduledActionBeginFrame() {
617 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginFrame");
618 scoped_ptr<BeginFrameAndCommitState> begin_frame_state(
619 new BeginFrameAndCommitState);
620 begin_frame_state->monotonic_frame_begin_time = base::TimeTicks::Now();
621 begin_frame_state->scroll_info = layer_tree_host_impl_->ProcessScrollDeltas();
622 DCHECK_GT(layer_tree_host_impl_->memory_allocation_limit_bytes(), 0u);
623 begin_frame_state->memory_allocation_limit_bytes =
624 layer_tree_host_impl_->memory_allocation_limit_bytes();
625 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::BeginFrame,
626 main_thread_weak_ptr_,
627 base::Passed(&begin_frame_state)));
629 if (begin_frame_completion_event_on_impl_thread_) {
630 begin_frame_completion_event_on_impl_thread_->Signal();
631 begin_frame_completion_event_on_impl_thread_ = NULL;
635 void ThreadProxy::BeginFrame(
636 scoped_ptr<BeginFrameAndCommitState> begin_frame_state) {
637 TRACE_EVENT0("cc", "ThreadProxy::BeginFrame");
638 DCHECK(IsMainThread());
639 if (!layer_tree_host_)
640 return;
642 if (defer_commits_) {
643 pending_deferred_commit_ = begin_frame_state.Pass();
644 layer_tree_host_->DidDeferCommit();
645 TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
646 return;
649 // Do not notify the impl thread of commit requests that occur during
650 // the apply/animate/layout part of the BeginFrameAndCommit process since
651 // those commit requests will get painted immediately. Once we have done
652 // the paint, commit_requested_ will be set to false to allow new commit
653 // requests to be scheduled.
654 commit_requested_ = true;
655 commit_request_sent_to_impl_thread_ = true;
657 // On the other hand, the AnimationRequested flag needs to be cleared
658 // here so that any animation requests generated by the apply or animate
659 // callbacks will trigger another frame.
660 animate_requested_ = false;
662 if (begin_frame_state)
663 layer_tree_host_->ApplyScrollAndScale(*begin_frame_state->scroll_info);
665 if (!in_composite_and_readback_ && !layer_tree_host_->visible()) {
666 commit_requested_ = false;
667 commit_request_sent_to_impl_thread_ = false;
669 TRACE_EVENT0("cc", "EarlyOut_NotVisible");
670 Proxy::ImplThread()->PostTask(base::Bind(
671 &ThreadProxy::BeginFrameAbortedOnImplThread, impl_thread_weak_ptr_));
672 return;
675 layer_tree_host_->WillBeginFrame();
677 if (begin_frame_state) {
678 layer_tree_host_->UpdateAnimations(
679 begin_frame_state->monotonic_frame_begin_time);
682 // Unlink any backings that the impl thread has evicted, so that we know to
683 // re-paint them in UpdateLayers.
684 if (layer_tree_host_->contents_texture_manager()) {
685 layer_tree_host_->contents_texture_manager()->
686 UnlinkAndClearEvictedBackings();
689 layer_tree_host_->Layout();
691 // Clear the commit flag after updating animations and layout here --- objects
692 // that only layout when painted will trigger another SetNeedsCommit inside
693 // UpdateLayers.
694 commit_requested_ = false;
695 commit_request_sent_to_impl_thread_ = false;
697 scoped_ptr<ResourceUpdateQueue> queue =
698 make_scoped_ptr(new ResourceUpdateQueue);
699 layer_tree_host_->UpdateLayers(
700 queue.get(),
701 begin_frame_state ? begin_frame_state->memory_allocation_limit_bytes
702 : 0u);
704 // Once single buffered layers are committed, they cannot be modified until
705 // they are drawn by the impl thread.
706 textures_acquired_ = false;
708 layer_tree_host_->WillCommit();
709 // Before applying scrolls and calling animate, we set animate_requested_ to
710 // false. If it is true now, it means SetNeedAnimate was called again, but
711 // during a state when commit_request_sent_to_impl_thread_ = true. We need to
712 // force that call to happen again now so that the commit request is sent to
713 // the impl thread.
714 if (animate_requested_) {
715 // Forces SetNeedsAnimate to consider posting a commit task.
716 animate_requested_ = false;
717 SetNeedsAnimate();
720 scoped_refptr<cc::ContextProvider> offscreen_context_provider;
721 if (renderer_capabilities_main_thread_copy_.using_offscreen_context3d &&
722 layer_tree_host_->needs_offscreen_context()) {
723 offscreen_context_provider = layer_tree_host_->client()->
724 OffscreenContextProviderForCompositorThread();
725 if (offscreen_context_provider)
726 created_offscreen_context_provider_ = true;
729 // Notify the impl thread that the BeginFrame has completed. This will
730 // begin the commit process, which is blocking from the main thread's
731 // point of view, but asynchronously performed on the impl thread,
732 // coordinated by the Scheduler.
734 TRACE_EVENT0("cc", "commit");
736 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
738 RenderingStatsInstrumentation* stats_instrumentation =
739 layer_tree_host_->rendering_stats_instrumentation();
740 base::TimeTicks start_time = stats_instrumentation->StartRecording();
742 CompletionEvent completion;
743 Proxy::ImplThread()->PostTask(
744 base::Bind(&ThreadProxy::BeginFrameCompleteOnImplThread,
745 impl_thread_weak_ptr_,
746 &completion,
747 queue.release(),
748 offscreen_context_provider));
749 completion.Wait();
751 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
752 stats_instrumentation->AddCommit(duration);
755 layer_tree_host_->CommitComplete();
756 layer_tree_host_->DidBeginFrame();
759 void ThreadProxy::BeginFrameCompleteOnImplThread(
760 CompletionEvent* completion,
761 ResourceUpdateQueue* raw_queue,
762 scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
763 scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
765 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameCompleteOnImplThread");
766 DCHECK(!commit_completion_event_on_impl_thread_);
767 DCHECK(IsImplThread() && IsMainThreadBlocked());
768 DCHECK(scheduler_on_impl_thread_);
769 DCHECK(scheduler_on_impl_thread_->CommitPending());
771 if (!layer_tree_host_impl_) {
772 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
773 completion->Signal();
774 return;
777 if (offscreen_context_provider)
778 offscreen_context_provider->BindToCurrentThread();
779 layer_tree_host_impl_->resource_provider()->
780 set_offscreen_context_provider(offscreen_context_provider);
782 if (layer_tree_host_->contents_texture_manager()->
783 LinkedEvictedBackingsExist()) {
784 // Clear any uploads we were making to textures linked to evicted
785 // resources
786 queue->ClearUploadsToEvictedResources();
787 // Some textures in the layer tree are invalid. Kick off another commit
788 // to fill them again.
789 SetNeedsCommitOnImplThread();
792 layer_tree_host_->contents_texture_manager()->
793 PushTexturePrioritiesToBackings();
795 current_resource_update_controller_on_impl_thread_ =
796 ResourceUpdateController::Create(
797 this,
798 Proxy::ImplThread(),
799 queue.Pass(),
800 layer_tree_host_impl_->resource_provider());
801 current_resource_update_controller_on_impl_thread_->PerformMoreUpdates(
802 scheduler_on_impl_thread_->AnticipatedDrawTime());
804 commit_completion_event_on_impl_thread_ = completion;
807 void ThreadProxy::BeginFrameAbortedOnImplThread() {
808 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedOnImplThread");
809 DCHECK(IsImplThread());
810 DCHECK(scheduler_on_impl_thread_);
811 DCHECK(scheduler_on_impl_thread_->CommitPending());
813 scheduler_on_impl_thread_->BeginFrameAborted();
816 void ThreadProxy::ScheduledActionCommit() {
817 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
818 DCHECK(IsImplThread());
819 DCHECK(commit_completion_event_on_impl_thread_);
820 DCHECK(current_resource_update_controller_on_impl_thread_);
822 // Complete all remaining texture updates.
823 current_resource_update_controller_on_impl_thread_->Finalize();
824 current_resource_update_controller_on_impl_thread_.reset();
826 layer_tree_host_impl_->BeginCommit();
827 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
828 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
829 layer_tree_host_impl_->CommitComplete();
831 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
832 !scheduler_on_impl_thread_->WillDrawIfNeeded());
834 next_frame_is_newly_committed_frame_on_impl_thread_ = true;
836 if (layer_tree_host_->settings().impl_side_painting &&
837 layer_tree_host_->BlocksPendingCommit()) {
838 // For some layer types in impl-side painting, the commit is held until
839 // the pending tree is activated.
840 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
841 completion_event_for_commit_held_on_tree_activation_ =
842 commit_completion_event_on_impl_thread_;
843 commit_completion_event_on_impl_thread_ = NULL;
844 } else {
845 commit_completion_event_on_impl_thread_->Signal();
846 commit_completion_event_on_impl_thread_ = NULL;
849 // SetVisible kicks off the next scheduler action, so this must be last.
850 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
853 void ThreadProxy::ScheduledActionCheckForCompletedTileUploads() {
854 DCHECK(IsImplThread());
855 TRACE_EVENT0("cc",
856 "ThreadProxy::ScheduledActionCheckForCompletedTileUploads");
857 layer_tree_host_impl_->CheckForCompletedTileUploads();
860 void ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded() {
861 DCHECK(IsImplThread());
862 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded");
863 layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
866 void ThreadProxy::ScheduledActionBeginOutputSurfaceCreation() {
867 DCHECK(IsImplThread());
868 Proxy::MainThread()->PostTask(
869 base::Bind(&ThreadProxy::CreateAndInitializeOutputSurface,
870 main_thread_weak_ptr_));
873 ScheduledActionDrawAndSwapResult
874 ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) {
875 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
877 base::AutoReset<bool> mark_inside(&inside_draw_, true);
879 ScheduledActionDrawAndSwapResult result;
880 result.did_draw = false;
881 result.did_swap = false;
882 DCHECK(IsImplThread());
883 DCHECK(layer_tree_host_impl_.get());
884 if (!layer_tree_host_impl_)
885 return result;
887 DCHECK(layer_tree_host_impl_->renderer());
888 if (!layer_tree_host_impl_->renderer())
889 return result;
891 base::TimeTicks monotonic_time =
892 layer_tree_host_impl_->CurrentFrameTimeTicks();
893 base::Time wall_clock_time = layer_tree_host_impl_->CurrentFrameTime();
895 if (input_handler_client_on_impl_thread_)
896 input_handler_client_on_impl_thread_->Animate(monotonic_time);
898 layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
899 layer_tree_host_impl_->Animate(monotonic_time, wall_clock_time);
900 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(false);
902 // This method is called on a forced draw, regardless of whether we are able
903 // to produce a frame, as the calling site on main thread is blocked until its
904 // request completes, and we signal completion here. If CanDraw() is false, we
905 // will indicate success=false to the caller, but we must still signal
906 // completion to avoid deadlock.
908 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
909 // frame, so can only be used when such a frame is possible. Since
910 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
911 // CanDraw() as well.
913 // If it is a forced draw, make sure we do a draw and swap.
914 gfx::Rect readback_rect;
915 if (readback_request_on_impl_thread_)
916 readback_rect = readback_request_on_impl_thread_->rect;
918 LayerTreeHostImpl::FrameData frame;
919 bool draw_frame = false;
920 bool start_ready_animations = true;
922 if (layer_tree_host_impl_->CanDraw()) {
923 // Do not start animations if we skip drawing the frame to avoid
924 // checkerboarding.
925 if (layer_tree_host_impl_->PrepareToDraw(&frame, readback_rect) ||
926 forced_draw)
927 draw_frame = true;
928 else
929 start_ready_animations = false;
932 if (draw_frame) {
933 layer_tree_host_impl_->DrawLayers(
934 &frame,
935 scheduler_on_impl_thread_->LastVSyncTime());
936 result.did_draw = true;
938 layer_tree_host_impl_->DidDrawAllLayers(frame);
940 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
942 // Check for tree activation.
943 if (completion_event_for_commit_held_on_tree_activation_ &&
944 !layer_tree_host_impl_->pending_tree()) {
945 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
946 TRACE_EVENT_SCOPE_THREAD);
947 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
948 completion_event_for_commit_held_on_tree_activation_->Signal();
949 completion_event_for_commit_held_on_tree_activation_ = NULL;
952 // Check for a pending CompositeAndReadback.
953 if (readback_request_on_impl_thread_) {
954 readback_request_on_impl_thread_->success = false;
955 if (draw_frame) {
956 layer_tree_host_impl_->Readback(readback_request_on_impl_thread_->pixels,
957 readback_request_on_impl_thread_->rect);
958 readback_request_on_impl_thread_->success =
959 !layer_tree_host_impl_->IsContextLost();
961 readback_request_on_impl_thread_->completion.Signal();
962 readback_request_on_impl_thread_ = NULL;
963 } else if (draw_frame) {
964 result.did_swap = layer_tree_host_impl_->SwapBuffers(frame);
966 if (frame.contains_incomplete_tile)
967 DidSwapUseIncompleteTileOnImplThread();
970 // Tell the main thread that the the newly-commited frame was drawn.
971 if (next_frame_is_newly_committed_frame_on_impl_thread_) {
972 next_frame_is_newly_committed_frame_on_impl_thread_ = false;
973 Proxy::MainThread()->PostTask(
974 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_));
977 if (draw_frame)
978 CheckOutputSurfaceStatusOnImplThread();
980 layer_tree_host_impl_->BeginNextFrame();
982 return result;
985 void ThreadProxy::AcquireLayerTextures() {
986 // Called when the main thread needs to modify a layer texture that is used
987 // directly by the compositor.
988 // This method will block until the next compositor draw if there is a
989 // previously committed frame that is still undrawn. This is necessary to
990 // ensure that the main thread does not monopolize access to the textures.
991 DCHECK(IsMainThread());
993 if (textures_acquired_)
994 return;
996 TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures");
997 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
998 CompletionEvent completion;
999 Proxy::ImplThread()->PostTask(
1000 base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread,
1001 impl_thread_weak_ptr_,
1002 &completion));
1003 // Block until it is safe to write to layer textures from the main thread.
1004 completion.Wait();
1006 textures_acquired_ = true;
1009 void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread(
1010 CompletionEvent* completion) {
1011 DCHECK(IsImplThread());
1012 DCHECK(!texture_acquisition_completion_event_on_impl_thread_);
1014 texture_acquisition_completion_event_on_impl_thread_ = completion;
1015 scheduler_on_impl_thread_->SetMainThreadNeedsLayerTextures();
1018 void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() {
1019 DCHECK(texture_acquisition_completion_event_on_impl_thread_);
1020 texture_acquisition_completion_event_on_impl_thread_->Signal();
1021 texture_acquisition_completion_event_on_impl_thread_ = NULL;
1024 ScheduledActionDrawAndSwapResult
1025 ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1026 return ScheduledActionDrawAndSwapInternal(false);
1029 ScheduledActionDrawAndSwapResult
1030 ThreadProxy::ScheduledActionDrawAndSwapForced() {
1031 return ScheduledActionDrawAndSwapInternal(true);
1034 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1035 if (current_resource_update_controller_on_impl_thread_)
1036 current_resource_update_controller_on_impl_thread_
1037 ->PerformMoreUpdates(time);
1040 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1041 DCHECK(IsImplThread());
1042 scheduler_on_impl_thread_->BeginFrameComplete();
1045 void ThreadProxy::DidCommitAndDrawFrame() {
1046 DCHECK(IsMainThread());
1047 if (!layer_tree_host_)
1048 return;
1049 layer_tree_host_->DidCommitAndDrawFrame();
1052 void ThreadProxy::DidCompleteSwapBuffers() {
1053 DCHECK(IsMainThread());
1054 if (!layer_tree_host_)
1055 return;
1056 layer_tree_host_->DidCompleteSwapBuffers();
1059 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
1060 base::Time wall_clock_time) {
1061 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1062 DCHECK(IsMainThread());
1063 if (!layer_tree_host_)
1064 return;
1065 layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time);
1068 void ThreadProxy::CreateAndInitializeOutputSurface() {
1069 TRACE_EVENT0("cc", "ThreadProxy::CreateAndInitializeOutputSurface");
1070 DCHECK(IsMainThread());
1072 // Check that output surface has not been recreated by CompositeAndReadback
1073 // after this task is posted but before it is run.
1074 bool has_initialized_output_surface_on_impl_thread = true;
1076 CompletionEvent completion;
1077 Proxy::ImplThread()->PostTask(
1078 base::Bind(&ThreadProxy::HasInitializedOutputSurfaceOnImplThread,
1079 impl_thread_weak_ptr_,
1080 &completion,
1081 &has_initialized_output_surface_on_impl_thread));
1082 completion.Wait();
1084 if (has_initialized_output_surface_on_impl_thread)
1085 return;
1087 layer_tree_host_->DidLoseOutputSurface();
1088 output_surface_creation_callback_.Reset(base::Bind(
1089 &ThreadProxy::DoCreateAndInitializeOutputSurface,
1090 base::Unretained(this)));
1091 output_surface_creation_callback_.callback().Run();
1094 void ThreadProxy::HasInitializedOutputSurfaceOnImplThread(
1095 CompletionEvent* completion,
1096 bool* has_initialized_output_surface) {
1097 DCHECK(IsImplThread());
1098 *has_initialized_output_surface =
1099 scheduler_on_impl_thread_->HasInitializedOutputSurface();
1100 completion->Signal();
1103 void ThreadProxy::InitializeImplOnImplThread(
1104 CompletionEvent* completion,
1105 InputHandlerClient* input_handler_client) {
1106 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1107 DCHECK(IsImplThread());
1108 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
1109 const base::TimeDelta display_refresh_interval =
1110 base::TimeDelta::FromMicroseconds(
1111 base::Time::kMicrosecondsPerSecond /
1112 layer_tree_host_->settings().refresh_rate);
1113 scoped_ptr<FrameRateController> frame_rate_controller;
1114 if (render_vsync_enabled_) {
1115 if (render_vsync_notification_enabled_) {
1116 frame_rate_controller.reset(
1117 new FrameRateController(VSyncTimeSource::Create(this)));
1118 } else {
1119 frame_rate_controller.reset(
1120 new FrameRateController(DelayBasedTimeSource::Create(
1121 display_refresh_interval, Proxy::ImplThread())));
1123 } else {
1124 frame_rate_controller.reset(new FrameRateController(Proxy::ImplThread()));
1126 const LayerTreeSettings& settings = layer_tree_host_->settings();
1127 SchedulerSettings scheduler_settings;
1128 scheduler_settings.impl_side_painting = settings.impl_side_painting;
1129 scheduler_settings.timeout_and_draw_when_animation_checkerboards =
1130 settings.timeout_and_draw_when_animation_checkerboards;
1131 scheduler_on_impl_thread_ = Scheduler::Create(this,
1132 frame_rate_controller.Pass(),
1133 scheduler_settings);
1134 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
1136 input_handler_client_on_impl_thread_.reset(input_handler_client);
1137 if (input_handler_client_on_impl_thread_) {
1138 input_handler_client_on_impl_thread_->BindToHandler(
1139 layer_tree_host_impl_.get());
1142 impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr();
1143 completion->Signal();
1146 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1147 CompletionEvent* completion,
1148 scoped_ptr<OutputSurface> output_surface,
1149 scoped_refptr<ContextProvider> offscreen_context_provider,
1150 bool* success,
1151 RendererCapabilities* capabilities) {
1152 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurfaceOnImplThread");
1153 DCHECK(IsImplThread());
1154 DCHECK(IsMainThreadBlocked());
1155 DCHECK(success);
1156 DCHECK(capabilities);
1158 layer_tree_host_->DeleteContentsTexturesOnImplThread(
1159 layer_tree_host_impl_->resource_provider());
1161 *success = layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
1163 if (offscreen_context_provider)
1164 offscreen_context_provider->BindToCurrentThread();
1166 if (*success) {
1167 *capabilities = layer_tree_host_impl_->GetRendererCapabilities();
1168 scheduler_on_impl_thread_->SetSwapBuffersCompleteSupported(
1169 capabilities->using_swap_complete_callback);
1171 OutputSurface* output_surface_ptr = layer_tree_host_impl_->output_surface();
1172 DCHECK(output_surface_ptr);
1173 int max_frames_pending =
1174 output_surface_ptr->capabilities().max_frames_pending;
1175 if (max_frames_pending <= 0)
1176 max_frames_pending = FrameRateController::DEFAULT_MAX_FRAMES_PENDING;
1177 if (output_surface_ptr->capabilities().has_parent_compositor)
1178 max_frames_pending = 1;
1180 scheduler_on_impl_thread_->SetMaxFramesPending(max_frames_pending);
1182 layer_tree_host_impl_->resource_provider()->
1183 set_offscreen_context_provider(offscreen_context_provider);
1185 scheduler_on_impl_thread_->DidCreateAndInitializeOutputSurface();
1186 } else if (offscreen_context_provider) {
1187 offscreen_context_provider->VerifyContexts();
1190 completion->Signal();
1193 void ThreadProxy::FinishGLOnImplThread(CompletionEvent* completion) {
1194 TRACE_EVENT0("cc", "ThreadProxy::FinishGLOnImplThread");
1195 DCHECK(IsImplThread());
1196 if (layer_tree_host_impl_->resource_provider())
1197 layer_tree_host_impl_->resource_provider()->Finish();
1198 completion->Signal();
1201 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
1202 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1203 DCHECK(IsImplThread());
1204 layer_tree_host_->DeleteContentsTexturesOnImplThread(
1205 layer_tree_host_impl_->resource_provider());
1206 layer_tree_host_impl_->EnableVSyncNotification(false);
1207 input_handler_client_on_impl_thread_.reset();
1208 layer_tree_host_impl_.reset();
1209 scheduler_on_impl_thread_.reset();
1210 weak_factory_on_impl_thread_.InvalidateWeakPtrs();
1211 vsync_client_ = NULL;
1212 completion->Signal();
1215 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1216 return ResourceUpdateController::MaxPartialTextureUpdates();
1219 ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
1220 : memory_allocation_limit_bytes(0) {}
1222 ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {}
1224 scoped_ptr<base::Value> ThreadProxy::AsValue() const {
1225 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1227 CompletionEvent completion;
1229 DebugScopedSetMainThreadBlocked main_thread_blocked(
1230 const_cast<ThreadProxy*>(this));
1231 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::AsValueOnImplThread,
1232 impl_thread_weak_ptr_,
1233 &completion,
1234 state.get()));
1235 completion.Wait();
1237 return state.PassAs<base::Value>();
1240 void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
1241 base::DictionaryValue* state) const {
1242 state->Set("layer_tree_host_impl",
1243 layer_tree_host_impl_->AsValue().release());
1244 completion->Signal();
1247 bool ThreadProxy::CommitPendingForTesting() {
1248 DCHECK(IsMainThread());
1249 CommitPendingRequest commit_pending_request;
1251 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1252 Proxy::ImplThread()->PostTask(
1253 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting,
1254 impl_thread_weak_ptr_,
1255 &commit_pending_request));
1256 commit_pending_request.completion.Wait();
1258 return commit_pending_request.commit_pending;
1261 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1262 CommitPendingRequest* request) {
1263 DCHECK(IsImplThread());
1264 if (layer_tree_host_impl_->output_surface())
1265 request->commit_pending = scheduler_on_impl_thread_->CommitPending();
1266 else
1267 request->commit_pending = false;
1268 request->completion.Signal();
1271 skia::RefPtr<SkPicture> ThreadProxy::CapturePicture() {
1272 DCHECK(IsMainThread());
1273 CompletionEvent completion;
1274 skia::RefPtr<SkPicture> picture;
1276 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1277 Proxy::ImplThread()->PostTask(
1278 base::Bind(&ThreadProxy::CapturePictureOnImplThread,
1279 impl_thread_weak_ptr_,
1280 &completion,
1281 &picture));
1282 completion.Wait();
1284 return picture;
1287 void ThreadProxy::CapturePictureOnImplThread(CompletionEvent* completion,
1288 skia::RefPtr<SkPicture>* picture) {
1289 DCHECK(IsImplThread());
1290 *picture = layer_tree_host_impl_->CapturePicture();
1291 completion->Signal();
1294 void ThreadProxy::RenewTreePriority() {
1295 bool smoothness_takes_priority =
1296 layer_tree_host_impl_->pinch_gesture_active() ||
1297 layer_tree_host_impl_->CurrentlyScrollingLayer() ||
1298 layer_tree_host_impl_->page_scale_animation_active();
1300 // Update expiration time if smoothness currently takes priority.
1301 if (smoothness_takes_priority) {
1302 smoothness_takes_priority_expiration_time_ =
1303 base::TimeTicks::Now() +
1304 base::TimeDelta::FromMilliseconds(
1305 kSmoothnessTakesPriorityExpirationDelay * 1000);
1308 // We use the same priority for both trees by default.
1309 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES;
1311 // Smoothness takes priority if expiration time is in the future.
1312 if (smoothness_takes_priority_expiration_time_ > base::TimeTicks::Now())
1313 priority = SMOOTHNESS_TAKES_PRIORITY;
1315 // New content always takes priority when the active tree has
1316 // evicted resources or there is an invalid viewport size.
1317 if (layer_tree_host_impl_->active_tree()->ContentsTexturesPurged() ||
1318 layer_tree_host_impl_->active_tree()->ViewportSizeInvalid())
1319 priority = NEW_CONTENT_TAKES_PRIORITY;
1321 layer_tree_host_impl_->SetTreePriority(priority);
1323 // Notify the the client of this compositor via the output surface.
1324 // TODO(epenner): Route this to compositor-thread instead of output-surface
1325 // after GTFO refactor of compositor-thread (http://crbug/170828).
1326 if (layer_tree_host_impl_->output_surface()) {
1327 layer_tree_host_impl_->output_surface()->
1328 UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY);
1331 base::TimeDelta delay =
1332 smoothness_takes_priority_expiration_time_ - base::TimeTicks::Now();
1334 // Need to make sure a delayed task is posted when we have smoothness
1335 // takes priority expiration time in the future.
1336 if (delay <= base::TimeDelta())
1337 return;
1338 if (renew_tree_priority_on_impl_thread_pending_)
1339 return;
1341 Proxy::ImplThread()->PostDelayedTask(
1342 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread,
1343 weak_factory_on_impl_thread_.GetWeakPtr()),
1344 delay);
1346 renew_tree_priority_on_impl_thread_pending_ = true;
1349 void ThreadProxy::RenewTreePriorityOnImplThread() {
1350 DCHECK(renew_tree_priority_on_impl_thread_pending_);
1351 renew_tree_priority_on_impl_thread_pending_ = false;
1353 RenewTreePriority();
1356 void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay) {
1357 Proxy::ImplThread()->PostDelayedTask(
1358 base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread,
1359 impl_thread_weak_ptr_),
1360 delay);
1363 void ThreadProxy::StartScrollbarAnimationOnImplThread() {
1364 layer_tree_host_impl_->StartScrollbarAnimation(
1365 layer_tree_host_impl_->CurrentFrameTimeTicks());
1368 void ThreadProxy::DidReceiveLastInputEventForVSync(
1369 base::TimeTicks frame_time) {
1370 if (render_vsync_notification_enabled_) {
1371 TRACE_EVENT0("cc", "ThreadProxy::DidReceiveLastInputEventForVSync");
1372 DidVSync(frame_time);
1376 } // namespace cc