Fix build break
[chromium-blink-merge.git] / cc / trees / thread_proxy.cc
blob3cc54e64b5524c134e4f3232982201e5925e1b1b
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 renderer_initialized_(false),
50 started_(false),
51 textures_acquired_(true),
52 in_composite_and_readback_(false),
53 manage_tiles_pending_(false),
54 weak_factory_on_impl_thread_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
55 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
56 begin_frame_completion_event_on_impl_thread_(NULL),
57 readback_request_on_impl_thread_(NULL),
58 commit_completion_event_on_impl_thread_(NULL),
59 completion_event_for_commit_held_on_tree_activation_(NULL),
60 texture_acquisition_completion_event_on_impl_thread_(NULL),
61 next_frame_is_newly_committed_frame_on_impl_thread_(false),
62 render_vsync_enabled_(layer_tree_host->settings().render_vsync_enabled),
63 render_vsync_notification_enabled_(
64 layer_tree_host->settings().render_vsync_notification_enabled),
65 vsync_client_(NULL),
66 inside_draw_(false),
67 defer_commits_(false),
68 renew_tree_priority_on_impl_thread_pending_(false) {
69 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
70 DCHECK(IsMainThread());
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_->InitializeRendererIfNeeded()) {
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 bool ThreadProxy::InitializeOutputSurface() {
153 TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurface");
154 scoped_ptr<OutputSurface> context = layer_tree_host_->CreateOutputSurface();
155 if (!context)
156 return false;
158 Proxy::ImplThread()->PostTask(
159 base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
160 impl_thread_weak_ptr_,
161 base::Passed(&context)));
162 return true;
165 void ThreadProxy::SetSurfaceReady() {
166 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReady");
167 Proxy::ImplThread()->PostTask(base::Bind(
168 &ThreadProxy::SetSurfaceReadyOnImplThread, impl_thread_weak_ptr_));
171 void ThreadProxy::SetSurfaceReadyOnImplThread() {
172 TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReadyOnImplThread");
173 scheduler_on_impl_thread_->SetCanBeginFrame(true);
176 void ThreadProxy::SetVisible(bool visible) {
177 TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
178 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
179 CompletionEvent completion;
180 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::SetVisibleOnImplThread,
181 impl_thread_weak_ptr_,
182 &completion,
183 visible));
184 completion.Wait();
187 void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
188 bool visible) {
189 TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
190 layer_tree_host_impl_->SetVisible(visible);
191 scheduler_on_impl_thread_->SetVisible(visible);
192 completion->Signal();
195 bool ThreadProxy::InitializeRenderer() {
196 TRACE_EVENT0("cc", "ThreadProxy::InitializeRenderer");
197 // Make a blocking call to InitializeRendererOnImplThread. The results of that
198 // call are pushed into the initialize_succeeded and capabilities local
199 // variables.
200 CompletionEvent completion;
201 bool initialize_succeeded = false;
202 RendererCapabilities capabilities;
203 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
204 Proxy::ImplThread()->PostTask(
205 base::Bind(&ThreadProxy::InitializeRendererOnImplThread,
206 impl_thread_weak_ptr_,
207 &completion,
208 &initialize_succeeded,
209 &capabilities));
210 completion.Wait();
212 if (initialize_succeeded) {
213 renderer_initialized_ = true;
214 renderer_capabilities_main_thread_copy_ = capabilities;
216 return initialize_succeeded;
219 bool ThreadProxy::RecreateOutputSurface() {
220 TRACE_EVENT0("cc", "ThreadProxy::RecreateOutputSurface");
221 DCHECK(IsMainThread());
223 // Try to create the surface.
224 scoped_ptr<OutputSurface> output_surface =
225 layer_tree_host_->CreateOutputSurface();
226 if (!output_surface)
227 return false;
228 scoped_refptr<cc::ContextProvider> offscreen_context_provider;
229 if (created_offscreen_context_provider_) {
230 offscreen_context_provider = layer_tree_host_->client()->
231 OffscreenContextProviderForCompositorThread();
232 if (!offscreen_context_provider)
233 return false;
236 // Make a blocking call to RecreateOutputSurfaceOnImplThread. The results of
237 // that call are pushed into the recreate_succeeded and capabilities local
238 // variables.
239 CompletionEvent completion;
240 bool recreate_succeeded = false;
241 RendererCapabilities capabilities;
242 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
243 Proxy::ImplThread()->PostTask(
244 base::Bind(&ThreadProxy::RecreateOutputSurfaceOnImplThread,
245 impl_thread_weak_ptr_,
246 &completion,
247 base::Passed(&output_surface),
248 offscreen_context_provider,
249 &recreate_succeeded,
250 &capabilities));
251 completion.Wait();
253 if (recreate_succeeded)
254 renderer_capabilities_main_thread_copy_ = capabilities;
255 return recreate_succeeded;
258 const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
259 DCHECK(renderer_initialized_);
260 return renderer_capabilities_main_thread_copy_;
263 void ThreadProxy::SetNeedsAnimate() {
264 DCHECK(IsMainThread());
265 if (animate_requested_)
266 return;
268 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
269 animate_requested_ = true;
271 if (commit_request_sent_to_impl_thread_)
272 return;
273 commit_request_sent_to_impl_thread_ = true;
274 Proxy::ImplThread()->PostTask(base::Bind(
275 &ThreadProxy::SetNeedsCommitOnImplThread, impl_thread_weak_ptr_));
278 void ThreadProxy::SetNeedsCommit() {
279 DCHECK(IsMainThread());
280 if (commit_requested_)
281 return;
282 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
283 commit_requested_ = true;
285 if (commit_request_sent_to_impl_thread_)
286 return;
287 commit_request_sent_to_impl_thread_ = true;
288 Proxy::ImplThread()->PostTask(base::Bind(
289 &ThreadProxy::SetNeedsCommitOnImplThread, impl_thread_weak_ptr_));
292 void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
293 DCHECK(IsImplThread());
294 TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
295 Proxy::ImplThread()->PostTask(
296 base::Bind(&ThreadProxy::CheckOutputSurfaceStatusOnImplThread,
297 impl_thread_weak_ptr_));
300 void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
301 DCHECK(IsImplThread());
302 TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
303 if (!layer_tree_host_impl_->IsContextLost())
304 return;
305 if (cc::ContextProvider* offscreen_contexts = layer_tree_host_impl_->
306 resource_provider()->offscreen_context_provider())
307 offscreen_contexts->VerifyContexts();
308 scheduler_on_impl_thread_->DidLoseOutputSurface();
311 void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
312 DCHECK(IsImplThread());
313 TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
314 scheduler_on_impl_thread_->DidSwapBuffersComplete();
315 Proxy::MainThread()->PostTask(
316 base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
319 void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase,
320 base::TimeDelta interval) {
321 DCHECK(IsImplThread());
322 TRACE_EVENT2("cc",
323 "ThreadProxy::OnVSyncParametersChanged",
324 "timebase",
325 (timebase - base::TimeTicks()).InMilliseconds(),
326 "interval",
327 interval.InMilliseconds());
328 scheduler_on_impl_thread_->SetTimebaseAndInterval(timebase, interval);
331 void ThreadProxy::DidVSync(base::TimeTicks frame_time) {
332 DCHECK(IsImplThread());
333 TRACE_EVENT0("cc", "ThreadProxy::DidVSync");
334 if (vsync_client_)
335 vsync_client_->DidVSync(frame_time);
338 void ThreadProxy::RequestVSyncNotification(VSyncClient* client) {
339 DCHECK(IsImplThread());
340 TRACE_EVENT1(
341 "cc", "ThreadProxy::RequestVSyncNotification", "enable", !!client);
342 vsync_client_ = client;
343 layer_tree_host_impl_->EnableVSyncNotification(!!client);
346 void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
347 DCHECK(IsImplThread());
348 TRACE_EVENT1(
349 "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
350 scheduler_on_impl_thread_->SetCanDraw(can_draw);
351 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
352 !scheduler_on_impl_thread_->WillDrawIfNeeded());
355 void ThreadProxy::OnHasPendingTreeStateChanged(bool has_pending_tree) {
356 DCHECK(IsImplThread());
357 TRACE_EVENT1("cc",
358 "ThreadProxy::OnHasPendingTreeStateChanged",
359 "has_pending_tree",
360 has_pending_tree);
361 scheduler_on_impl_thread_->SetHasPendingTree(has_pending_tree);
364 void ThreadProxy::SetNeedsCommitOnImplThread() {
365 DCHECK(IsImplThread());
366 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
367 scheduler_on_impl_thread_->SetNeedsCommit();
370 void ThreadProxy::SetNeedsManageTilesOnImplThread() {
371 if (manage_tiles_pending_)
372 return;
373 Proxy::ImplThread()->PostTask(
374 base::Bind(&ThreadProxy::ManageTilesOnImplThread, impl_thread_weak_ptr_));
375 manage_tiles_pending_ = true;
378 void ThreadProxy::ManageTilesOnImplThread() {
379 // TODO(nduca): If needed, move this into CCSchedulerStateMachine.
380 manage_tiles_pending_ = false;
381 if (layer_tree_host_impl_)
382 layer_tree_host_impl_->ManageTiles();
385 void ThreadProxy::SetNeedsForcedCommitOnImplThread() {
386 DCHECK(IsImplThread());
387 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsForcedCommitOnImplThread");
388 scheduler_on_impl_thread_->SetNeedsForcedCommit();
391 void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
392 scoped_ptr<AnimationEventsVector> events,
393 base::Time wall_clock_time) {
394 DCHECK(IsImplThread());
395 TRACE_EVENT0("cc",
396 "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
397 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::SetAnimationEvents,
398 main_thread_weak_ptr_,
399 base::Passed(&events),
400 wall_clock_time));
403 bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
404 int priority_cutoff) {
405 DCHECK(IsImplThread());
407 if (!layer_tree_host_->contents_texture_manager())
408 return false;
410 bool reduce_result = layer_tree_host_->contents_texture_manager()->
411 ReduceMemoryOnImplThread(limit_bytes,
412 priority_cutoff,
413 layer_tree_host_impl_->resource_provider());
414 if (!reduce_result)
415 return false;
417 // The texture upload queue may reference textures that were just purged,
418 // clear them from the queue.
419 if (current_resource_update_controller_on_impl_thread_) {
420 current_resource_update_controller_on_impl_thread_->
421 DiscardUploadsToEvictedResources();
423 return true;
426 void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
427 DCHECK(IsImplThread());
429 if (!layer_tree_host_->contents_texture_manager())
430 return;
432 layer_tree_host_->contents_texture_manager()->ReduceWastedMemoryOnImplThread(
433 layer_tree_host_impl_->resource_provider());
436 void ThreadProxy::SendManagedMemoryStats() {
437 DCHECK(IsImplThread());
438 if (!layer_tree_host_impl_)
439 return;
440 if (!layer_tree_host_->contents_texture_manager())
441 return;
443 // If we are using impl-side painting, then SendManagedMemoryStats is called
444 // directly after the tile manager's manage function, and doesn't need to
445 // interact with main thread's layer tree.
446 if (layer_tree_host_->settings().impl_side_painting)
447 return;
449 layer_tree_host_impl_->SendManagedMemoryStats(
450 layer_tree_host_->contents_texture_manager()->MemoryVisibleBytes(),
451 layer_tree_host_->contents_texture_manager()->
452 MemoryVisibleAndNearbyBytes(),
453 layer_tree_host_->contents_texture_manager()->MemoryUseBytes());
456 bool ThreadProxy::IsInsideDraw() { return inside_draw_; }
458 void ThreadProxy::SetNeedsRedraw(const gfx::Rect& damage_rect) {
459 DCHECK(IsMainThread());
460 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
461 Proxy::ImplThread()->PostTask(base::Bind(
462 &ThreadProxy::SetViewportDamageOnImplThread,
463 impl_thread_weak_ptr_, damage_rect));
464 Proxy::ImplThread()->PostTask(base::Bind(
465 &ThreadProxy::SetNeedsRedrawOnImplThread, impl_thread_weak_ptr_));
468 void ThreadProxy::SetDeferCommits(bool defer_commits) {
469 DCHECK(IsMainThread());
470 DCHECK_NE(defer_commits_, defer_commits);
471 defer_commits_ = defer_commits;
473 if (defer_commits_)
474 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
475 else
476 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
478 if (!defer_commits_ && pending_deferred_commit_)
479 Proxy::MainThread()->PostTask(
480 base::Bind(&ThreadProxy::BeginFrame,
481 main_thread_weak_ptr_,
482 base::Passed(&pending_deferred_commit_)));
485 bool ThreadProxy::CommitRequested() const {
486 DCHECK(IsMainThread());
487 return commit_requested_;
490 void ThreadProxy::SetNeedsRedrawOnImplThread() {
491 DCHECK(IsImplThread());
492 TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
493 scheduler_on_impl_thread_->SetNeedsRedraw();
496 void ThreadProxy::DidSwapUseIncompleteTileOnImplThread() {
497 DCHECK(IsImplThread());
498 TRACE_EVENT0("cc", "ThreadProxy::DidSwapUseIncompleteTileOnImplThread");
499 scheduler_on_impl_thread_->DidSwapUseIncompleteTile();
502 void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
503 DCHECK(IsImplThread());
504 TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
505 scheduler_on_impl_thread_->SetNeedsRedraw();
508 void ThreadProxy::MainThreadHasStoppedFlinging() {
509 if (input_handler_on_impl_thread_)
510 input_handler_on_impl_thread_->MainThreadHasStoppedFlinging();
513 void ThreadProxy::Start() {
514 DCHECK(IsMainThread());
515 DCHECK(Proxy::ImplThread());
516 // Create LayerTreeHostImpl.
517 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
518 CompletionEvent completion;
519 scoped_ptr<InputHandler> handler = layer_tree_host_->CreateInputHandler();
520 Proxy::ImplThread()->PostTask(
521 base::Bind(&ThreadProxy::InitializeImplOnImplThread,
522 base::Unretained(this),
523 &completion,
524 handler.release()));
525 completion.Wait();
527 main_thread_weak_ptr_ = weak_factory_.GetWeakPtr();
529 started_ = true;
532 void ThreadProxy::Stop() {
533 TRACE_EVENT0("cc", "ThreadProxy::Stop");
534 DCHECK(IsMainThread());
535 DCHECK(started_);
537 // Synchronously deletes the impl.
539 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
541 CompletionEvent completion;
542 Proxy::ImplThread()->PostTask(
543 base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread,
544 impl_thread_weak_ptr_,
545 &completion));
546 completion.Wait();
549 weak_factory_.InvalidateWeakPtrs();
551 DCHECK(!layer_tree_host_impl_.get()); // verify that the impl deleted.
552 layer_tree_host_ = NULL;
553 started_ = false;
556 void ThreadProxy::ForceSerializeOnSwapBuffers() {
557 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
558 CompletionEvent completion;
559 Proxy::ImplThread()->PostTask(
560 base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
561 impl_thread_weak_ptr_,
562 &completion));
563 completion.Wait();
566 void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
567 CompletionEvent* completion) {
568 if (renderer_initialized_)
569 layer_tree_host_impl_->renderer()->DoNoOp();
570 completion->Signal();
573 void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
574 TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
575 DCHECK(IsImplThread());
576 layer_tree_host_impl_->FinishAllRendering();
577 completion->Signal();
580 void ThreadProxy::ForceBeginFrameOnImplThread(CompletionEvent* completion) {
581 TRACE_EVENT0("cc", "ThreadProxy::ForceBeginFrameOnImplThread");
582 DCHECK(!begin_frame_completion_event_on_impl_thread_);
584 SetNeedsForcedCommitOnImplThread();
585 if (scheduler_on_impl_thread_->CommitPending()) {
586 completion->Signal();
587 return;
590 begin_frame_completion_event_on_impl_thread_ = completion;
593 void ThreadProxy::ScheduledActionBeginFrame() {
594 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginFrame");
595 scoped_ptr<BeginFrameAndCommitState> begin_frame_state(
596 new BeginFrameAndCommitState);
597 begin_frame_state->monotonic_frame_begin_time = base::TimeTicks::Now();
598 begin_frame_state->scroll_info = layer_tree_host_impl_->ProcessScrollDeltas();
599 begin_frame_state->impl_transform =
600 layer_tree_host_impl_->active_tree()->ImplTransform();
601 DCHECK_GT(layer_tree_host_impl_->memory_allocation_limit_bytes(), 0u);
602 begin_frame_state->memory_allocation_limit_bytes =
603 layer_tree_host_impl_->memory_allocation_limit_bytes();
604 Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::BeginFrame,
605 main_thread_weak_ptr_,
606 base::Passed(&begin_frame_state)));
608 if (begin_frame_completion_event_on_impl_thread_) {
609 begin_frame_completion_event_on_impl_thread_->Signal();
610 begin_frame_completion_event_on_impl_thread_ = NULL;
614 void ThreadProxy::BeginFrame(
615 scoped_ptr<BeginFrameAndCommitState> begin_frame_state) {
616 TRACE_EVENT0("cc", "ThreadProxy::BeginFrame");
617 DCHECK(IsMainThread());
618 if (!layer_tree_host_)
619 return;
621 if (defer_commits_) {
622 pending_deferred_commit_ = begin_frame_state.Pass();
623 layer_tree_host_->DidDeferCommit();
624 TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
625 return;
628 // Do not notify the impl thread of commit requests that occur during
629 // the apply/animate/layout part of the BeginFrameAndCommit process since
630 // those commit requests will get painted immediately. Once we have done
631 // the paint, commit_requested_ will be set to false to allow new commit
632 // requests to be scheduled.
633 commit_requested_ = true;
634 commit_request_sent_to_impl_thread_ = true;
636 // On the other hand, the AnimationRequested flag needs to be cleared
637 // here so that any animation requests generated by the apply or animate
638 // callbacks will trigger another frame.
639 animate_requested_ = false;
641 if (begin_frame_state) {
642 layer_tree_host_->ApplyScrollAndScale(*begin_frame_state->scroll_info);
643 layer_tree_host_->SetImplTransform(begin_frame_state->impl_transform);
646 if (!in_composite_and_readback_ && !layer_tree_host_->visible()) {
647 commit_requested_ = false;
648 commit_request_sent_to_impl_thread_ = false;
650 TRACE_EVENT0("cc", "EarlyOut_NotVisible");
651 Proxy::ImplThread()->PostTask(base::Bind(
652 &ThreadProxy::BeginFrameAbortedOnImplThread, impl_thread_weak_ptr_));
653 return;
656 layer_tree_host_->WillBeginFrame();
658 if (begin_frame_state) {
659 layer_tree_host_->UpdateAnimations(
660 begin_frame_state->monotonic_frame_begin_time);
663 // Unlink any backings that the impl thread has evicted, so that we know to
664 // re-paint them in UpdateLayers.
665 if (layer_tree_host_->contents_texture_manager()) {
666 layer_tree_host_->contents_texture_manager()->
667 UnlinkAndClearEvictedBackings();
670 layer_tree_host_->Layout();
672 // Clear the commit flag after updating animations and layout here --- objects
673 // that only layout when painted will trigger another SetNeedsCommit inside
674 // UpdateLayers.
675 commit_requested_ = false;
676 commit_request_sent_to_impl_thread_ = false;
678 if (!layer_tree_host_->InitializeRendererIfNeeded()) {
679 TRACE_EVENT0("cc", "EarlyOut_InitializeFailed");
680 return;
683 scoped_ptr<ResourceUpdateQueue> queue =
684 make_scoped_ptr(new ResourceUpdateQueue);
685 layer_tree_host_->UpdateLayers(
686 queue.get(),
687 begin_frame_state ? begin_frame_state->memory_allocation_limit_bytes
688 : 0u);
690 // Once single buffered layers are committed, they cannot be modified until
691 // they are drawn by the impl thread.
692 textures_acquired_ = false;
694 layer_tree_host_->WillCommit();
695 // Before applying scrolls and calling animate, we set animate_requested_ to
696 // false. If it is true now, it means SetNeedAnimate was called again, but
697 // during a state when commit_request_sent_to_impl_thread_ = true. We need to
698 // force that call to happen again now so that the commit request is sent to
699 // the impl thread.
700 if (animate_requested_) {
701 // Forces SetNeedsAnimate to consider posting a commit task.
702 animate_requested_ = false;
703 SetNeedsAnimate();
706 scoped_refptr<cc::ContextProvider> offscreen_context_provider;
707 if (renderer_capabilities_main_thread_copy_.using_offscreen_context3d &&
708 layer_tree_host_->needs_offscreen_context()) {
709 offscreen_context_provider = layer_tree_host_->client()->
710 OffscreenContextProviderForCompositorThread();
711 if (offscreen_context_provider)
712 created_offscreen_context_provider_ = true;
715 // Notify the impl thread that the BeginFrame has completed. This will
716 // begin the commit process, which is blocking from the main thread's
717 // point of view, but asynchronously performed on the impl thread,
718 // coordinated by the Scheduler.
720 TRACE_EVENT0("cc", "commit");
722 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
724 RenderingStatsInstrumentation* stats_instrumentation =
725 layer_tree_host_->rendering_stats_instrumentation();
726 base::TimeTicks start_time = stats_instrumentation->StartRecording();
728 CompletionEvent completion;
729 Proxy::ImplThread()->PostTask(
730 base::Bind(&ThreadProxy::BeginFrameCompleteOnImplThread,
731 impl_thread_weak_ptr_,
732 &completion,
733 queue.release(),
734 offscreen_context_provider));
735 completion.Wait();
737 base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
738 stats_instrumentation->AddCommit(duration);
741 layer_tree_host_->CommitComplete();
742 layer_tree_host_->DidBeginFrame();
745 void ThreadProxy::BeginFrameCompleteOnImplThread(
746 CompletionEvent* completion,
747 ResourceUpdateQueue* raw_queue,
748 scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
749 scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
751 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameCompleteOnImplThread");
752 DCHECK(!commit_completion_event_on_impl_thread_);
753 DCHECK(IsImplThread() && IsMainThreadBlocked());
754 DCHECK(scheduler_on_impl_thread_);
755 DCHECK(scheduler_on_impl_thread_->CommitPending());
757 if (!layer_tree_host_impl_) {
758 TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
759 completion->Signal();
760 return;
763 if (offscreen_context_provider)
764 offscreen_context_provider->BindToCurrentThread();
765 layer_tree_host_impl_->resource_provider()->
766 set_offscreen_context_provider(offscreen_context_provider);
768 if (layer_tree_host_->contents_texture_manager()->
769 LinkedEvictedBackingsExist()) {
770 // Clear any uploads we were making to textures linked to evicted
771 // resources
772 queue->ClearUploadsToEvictedResources();
773 // Some textures in the layer tree are invalid. Kick off another commit
774 // to fill them again.
775 SetNeedsCommitOnImplThread();
778 layer_tree_host_->contents_texture_manager()->
779 PushTexturePrioritiesToBackings();
781 current_resource_update_controller_on_impl_thread_ =
782 ResourceUpdateController::Create(
783 this,
784 Proxy::ImplThread(),
785 queue.Pass(),
786 layer_tree_host_impl_->resource_provider());
787 current_resource_update_controller_on_impl_thread_->PerformMoreUpdates(
788 scheduler_on_impl_thread_->AnticipatedDrawTime());
790 commit_completion_event_on_impl_thread_ = completion;
793 void ThreadProxy::BeginFrameAbortedOnImplThread() {
794 TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedOnImplThread");
795 DCHECK(IsImplThread());
796 DCHECK(scheduler_on_impl_thread_);
797 DCHECK(scheduler_on_impl_thread_->CommitPending());
799 scheduler_on_impl_thread_->BeginFrameAborted();
802 void ThreadProxy::ScheduledActionCommit() {
803 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
804 DCHECK(IsImplThread());
805 DCHECK(commit_completion_event_on_impl_thread_);
806 DCHECK(current_resource_update_controller_on_impl_thread_);
808 // Complete all remaining texture updates.
809 current_resource_update_controller_on_impl_thread_->Finalize();
810 current_resource_update_controller_on_impl_thread_.reset();
812 layer_tree_host_impl_->BeginCommit();
813 layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
814 layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
815 layer_tree_host_impl_->CommitComplete();
817 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(
818 !scheduler_on_impl_thread_->WillDrawIfNeeded());
820 next_frame_is_newly_committed_frame_on_impl_thread_ = true;
822 if (layer_tree_host_->settings().impl_side_painting &&
823 layer_tree_host_->BlocksPendingCommit()) {
824 // For some layer types in impl-side painting, the commit is held until
825 // the pending tree is activated.
826 TRACE_EVENT_INSTANT0("cc", "HoldCommit", TRACE_EVENT_SCOPE_THREAD);
827 completion_event_for_commit_held_on_tree_activation_ =
828 commit_completion_event_on_impl_thread_;
829 commit_completion_event_on_impl_thread_ = NULL;
830 } else {
831 commit_completion_event_on_impl_thread_->Signal();
832 commit_completion_event_on_impl_thread_ = NULL;
835 // SetVisible kicks off the next scheduler action, so this must be last.
836 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
839 void ThreadProxy::ScheduledActionCheckForCompletedTileUploads() {
840 DCHECK(IsImplThread());
841 TRACE_EVENT0("cc",
842 "ThreadProxy::ScheduledActionCheckForCompletedTileUploads");
843 layer_tree_host_impl_->CheckForCompletedTileUploads();
846 void ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded() {
847 DCHECK(IsImplThread());
848 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded");
849 layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
852 void ThreadProxy::ScheduledActionBeginContextRecreation() {
853 DCHECK(IsImplThread());
854 Proxy::MainThread()->PostTask(
855 base::Bind(&ThreadProxy::BeginContextRecreation, main_thread_weak_ptr_));
858 ScheduledActionDrawAndSwapResult
859 ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) {
860 TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
862 base::AutoReset<bool> mark_inside(&inside_draw_, true);
864 ScheduledActionDrawAndSwapResult result;
865 result.did_draw = false;
866 result.did_swap = false;
867 DCHECK(IsImplThread());
868 DCHECK(layer_tree_host_impl_.get());
869 if (!layer_tree_host_impl_)
870 return result;
872 DCHECK(layer_tree_host_impl_->renderer());
873 if (!layer_tree_host_impl_->renderer())
874 return result;
876 // FIXME: compute the frame display time more intelligently
877 base::TimeTicks monotonic_time = base::TimeTicks::Now();
878 base::Time wall_clock_time = base::Time::Now();
880 if (input_handler_on_impl_thread_)
881 input_handler_on_impl_thread_->Animate(monotonic_time);
883 layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
884 layer_tree_host_impl_->Animate(monotonic_time, wall_clock_time);
885 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(false);
887 // This method is called on a forced draw, regardless of whether we are able
888 // to produce a frame, as the calling site on main thread is blocked until its
889 // request completes, and we signal completion here. If CanDraw() is false, we
890 // will indicate success=false to the caller, but we must still signal
891 // completion to avoid deadlock.
893 // We guard PrepareToDraw() with CanDraw() because it always returns a valid
894 // frame, so can only be used when such a frame is possible. Since
895 // DrawLayers() depends on the result of PrepareToDraw(), it is guarded on
896 // CanDraw() as well.
898 // If it is a forced draw, make sure we do a draw and swap.
899 gfx::Rect readback_rect;
900 if (readback_request_on_impl_thread_)
901 readback_rect = readback_request_on_impl_thread_->rect;
903 LayerTreeHostImpl::FrameData frame;
904 bool draw_frame = false;
905 bool start_ready_animations = true;
907 if (layer_tree_host_impl_->CanDraw()) {
908 // Do not start animations if we skip drawing the frame to avoid
909 // checkerboarding.
910 if (layer_tree_host_impl_->PrepareToDraw(&frame, readback_rect) ||
911 forced_draw)
912 draw_frame = true;
913 else
914 start_ready_animations = false;
917 if (draw_frame) {
918 layer_tree_host_impl_->DrawLayers(
919 &frame,
920 scheduler_on_impl_thread_->LastVSyncTime());
921 result.did_draw = true;
923 layer_tree_host_impl_->DidDrawAllLayers(frame);
925 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations);
927 // Check for tree activation.
928 if (completion_event_for_commit_held_on_tree_activation_ &&
929 !layer_tree_host_impl_->pending_tree()) {
930 TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation",
931 TRACE_EVENT_SCOPE_THREAD);
932 DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
933 completion_event_for_commit_held_on_tree_activation_->Signal();
934 completion_event_for_commit_held_on_tree_activation_ = NULL;
937 // Check for a pending CompositeAndReadback.
938 if (readback_request_on_impl_thread_) {
939 readback_request_on_impl_thread_->success = false;
940 if (draw_frame) {
941 layer_tree_host_impl_->Readback(readback_request_on_impl_thread_->pixels,
942 readback_request_on_impl_thread_->rect);
943 readback_request_on_impl_thread_->success =
944 !layer_tree_host_impl_->IsContextLost();
946 readback_request_on_impl_thread_->completion.Signal();
947 readback_request_on_impl_thread_ = NULL;
948 } else if (draw_frame) {
949 result.did_swap = layer_tree_host_impl_->SwapBuffers(frame);
951 if (frame.contains_incomplete_tile)
952 DidSwapUseIncompleteTileOnImplThread();
955 // Tell the main thread that the the newly-commited frame was drawn.
956 if (next_frame_is_newly_committed_frame_on_impl_thread_) {
957 next_frame_is_newly_committed_frame_on_impl_thread_ = false;
958 Proxy::MainThread()->PostTask(
959 base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_));
962 if (draw_frame)
963 CheckOutputSurfaceStatusOnImplThread();
965 layer_tree_host_impl_->BeginNextFrame();
967 return result;
970 void ThreadProxy::AcquireLayerTextures() {
971 // Called when the main thread needs to modify a layer texture that is used
972 // directly by the compositor.
973 // This method will block until the next compositor draw if there is a
974 // previously committed frame that is still undrawn. This is necessary to
975 // ensure that the main thread does not monopolize access to the textures.
976 DCHECK(IsMainThread());
978 if (textures_acquired_)
979 return;
981 TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures");
982 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
983 CompletionEvent completion;
984 Proxy::ImplThread()->PostTask(
985 base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread,
986 impl_thread_weak_ptr_,
987 &completion));
988 // Block until it is safe to write to layer textures from the main thread.
989 completion.Wait();
991 textures_acquired_ = true;
994 void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread(
995 CompletionEvent* completion) {
996 DCHECK(IsImplThread());
997 DCHECK(!texture_acquisition_completion_event_on_impl_thread_);
999 texture_acquisition_completion_event_on_impl_thread_ = completion;
1000 scheduler_on_impl_thread_->SetMainThreadNeedsLayerTextures();
1003 void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() {
1004 DCHECK(texture_acquisition_completion_event_on_impl_thread_);
1005 texture_acquisition_completion_event_on_impl_thread_->Signal();
1006 texture_acquisition_completion_event_on_impl_thread_ = NULL;
1009 ScheduledActionDrawAndSwapResult
1010 ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
1011 return ScheduledActionDrawAndSwapInternal(false);
1014 ScheduledActionDrawAndSwapResult
1015 ThreadProxy::ScheduledActionDrawAndSwapForced() {
1016 return ScheduledActionDrawAndSwapInternal(true);
1019 void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1020 if (layer_tree_host_impl_)
1021 layer_tree_host_impl_->SetAnticipatedDrawTime(time);
1023 if (current_resource_update_controller_on_impl_thread_)
1024 current_resource_update_controller_on_impl_thread_
1025 ->PerformMoreUpdates(time);
1028 void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1029 DCHECK(IsImplThread());
1030 scheduler_on_impl_thread_->BeginFrameComplete();
1033 void ThreadProxy::DidCommitAndDrawFrame() {
1034 DCHECK(IsMainThread());
1035 if (!layer_tree_host_)
1036 return;
1037 layer_tree_host_->DidCommitAndDrawFrame();
1040 void ThreadProxy::DidCompleteSwapBuffers() {
1041 DCHECK(IsMainThread());
1042 if (!layer_tree_host_)
1043 return;
1044 layer_tree_host_->DidCompleteSwapBuffers();
1047 void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
1048 base::Time wall_clock_time) {
1049 TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1050 DCHECK(IsMainThread());
1051 if (!layer_tree_host_)
1052 return;
1053 layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time);
1056 void ThreadProxy::BeginContextRecreation() {
1057 TRACE_EVENT0("cc", "ThreadProxy::BeginContextRecreation");
1058 DCHECK(IsMainThread());
1059 layer_tree_host_->DidLoseOutputSurface();
1060 output_surface_recreation_callback_.Reset(base::Bind(
1061 &ThreadProxy::TryToRecreateOutputSurface, base::Unretained(this)));
1062 Proxy::MainThread()->PostTask(output_surface_recreation_callback_.callback());
1065 void ThreadProxy::TryToRecreateOutputSurface() {
1066 DCHECK(IsMainThread());
1067 DCHECK(layer_tree_host_);
1068 LayerTreeHost::RecreateResult result =
1069 layer_tree_host_->RecreateOutputSurface();
1070 if (result == LayerTreeHost::RecreateFailedButTryAgain)
1071 Proxy::MainThread()->PostTask(
1072 output_surface_recreation_callback_.callback());
1073 else if (result == LayerTreeHost::RecreateSucceeded)
1074 output_surface_recreation_callback_.Cancel();
1077 void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion,
1078 InputHandler* handler) {
1079 TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1080 DCHECK(IsImplThread());
1081 layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
1082 const base::TimeDelta display_refresh_interval =
1083 base::TimeDelta::FromMicroseconds(
1084 base::Time::kMicrosecondsPerSecond /
1085 layer_tree_host_->settings().refresh_rate);
1086 scoped_ptr<FrameRateController> frame_rate_controller;
1087 if (render_vsync_enabled_) {
1088 if (render_vsync_notification_enabled_) {
1089 frame_rate_controller.reset(
1090 new FrameRateController(VSyncTimeSource::Create(this)));
1091 } else {
1092 frame_rate_controller.reset(
1093 new FrameRateController(DelayBasedTimeSource::Create(
1094 display_refresh_interval, Proxy::ImplThread())));
1096 } else {
1097 frame_rate_controller.reset(new FrameRateController(Proxy::ImplThread()));
1099 const LayerTreeSettings& settings = layer_tree_host_->settings();
1100 SchedulerSettings scheduler_settings;
1101 scheduler_settings.impl_side_painting = settings.impl_side_painting;
1102 scheduler_settings.timeout_and_draw_when_animation_checkerboards =
1103 settings.timeout_and_draw_when_animation_checkerboards;
1104 scheduler_on_impl_thread_ = Scheduler::Create(this,
1105 frame_rate_controller.Pass(),
1106 scheduler_settings);
1107 scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
1109 input_handler_on_impl_thread_ = scoped_ptr<InputHandler>(handler);
1110 if (input_handler_on_impl_thread_)
1111 input_handler_on_impl_thread_->BindToClient(layer_tree_host_impl_.get());
1113 impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr();
1114 completion->Signal();
1117 void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1118 scoped_ptr<OutputSurface> output_surface) {
1119 TRACE_EVENT0("cc", "ThreadProxy::InitializeContextOnImplThread");
1120 DCHECK(IsImplThread());
1121 output_surface_before_initialization_on_impl_thread_ = output_surface.Pass();
1124 void ThreadProxy::InitializeRendererOnImplThread(
1125 CompletionEvent* completion,
1126 bool* initialize_succeeded,
1127 RendererCapabilities* capabilities) {
1128 TRACE_EVENT0("cc", "ThreadProxy::InitializeRendererOnImplThread");
1129 DCHECK(IsImplThread());
1130 DCHECK(output_surface_before_initialization_on_impl_thread_.get());
1131 *initialize_succeeded = layer_tree_host_impl_->InitializeRenderer(
1132 output_surface_before_initialization_on_impl_thread_.Pass());
1133 if (*initialize_succeeded) {
1134 *capabilities = layer_tree_host_impl_->GetRendererCapabilities();
1135 scheduler_on_impl_thread_->SetSwapBuffersCompleteSupported(
1136 capabilities->using_swap_complete_callback);
1138 int max_frames_pending = layer_tree_host_impl_->output_surface()->
1139 capabilities().max_frames_pending;
1140 if (max_frames_pending <= 0)
1141 max_frames_pending = FrameRateController::DEFAULT_MAX_FRAMES_PENDING;
1142 if (layer_tree_host_impl_->output_surface()->capabilities().
1143 has_parent_compositor)
1144 max_frames_pending = 1;
1145 scheduler_on_impl_thread_->SetMaxFramesPending(max_frames_pending);
1148 completion->Signal();
1151 void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
1152 TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1153 DCHECK(IsImplThread());
1154 layer_tree_host_->DeleteContentsTexturesOnImplThread(
1155 layer_tree_host_impl_->resource_provider());
1156 layer_tree_host_impl_->EnableVSyncNotification(false);
1157 input_handler_on_impl_thread_.reset();
1158 layer_tree_host_impl_.reset();
1159 scheduler_on_impl_thread_.reset();
1160 weak_factory_on_impl_thread_.InvalidateWeakPtrs();
1161 vsync_client_ = NULL;
1162 completion->Signal();
1165 void ThreadProxy::SetViewportDamageOnImplThread(const gfx::Rect& damage_rect) {
1166 DCHECK(IsImplThread());
1167 layer_tree_host_impl_->SetViewportDamage(damage_rect);
1170 size_t ThreadProxy::MaxPartialTextureUpdates() const {
1171 return ResourceUpdateController::MaxPartialTextureUpdates();
1174 void ThreadProxy::RecreateOutputSurfaceOnImplThread(
1175 CompletionEvent* completion,
1176 scoped_ptr<OutputSurface> output_surface,
1177 scoped_refptr<cc::ContextProvider> offscreen_context_provider,
1178 bool* recreate_succeeded,
1179 RendererCapabilities* capabilities) {
1180 TRACE_EVENT0("cc", "ThreadProxy::RecreateOutputSurfaceOnImplThread");
1181 DCHECK(IsImplThread());
1183 layer_tree_host_->DeleteContentsTexturesOnImplThread(
1184 layer_tree_host_impl_->resource_provider());
1185 *recreate_succeeded =
1186 layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
1187 if (offscreen_context_provider)
1188 offscreen_context_provider->BindToCurrentThread();
1190 if (*recreate_succeeded) {
1191 *capabilities = layer_tree_host_impl_->GetRendererCapabilities();
1192 layer_tree_host_impl_->resource_provider()->
1193 set_offscreen_context_provider(offscreen_context_provider);
1194 scheduler_on_impl_thread_->DidRecreateOutputSurface();
1195 } else if (offscreen_context_provider) {
1196 offscreen_context_provider->VerifyContexts();
1198 completion->Signal();
1201 ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
1202 : memory_allocation_limit_bytes(0) {}
1204 ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {}
1206 scoped_ptr<base::Value> ThreadProxy::AsValue() const {
1207 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1209 CompletionEvent completion;
1211 DebugScopedSetMainThreadBlocked main_thread_blocked(
1212 const_cast<ThreadProxy*>(this));
1213 Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::AsValueOnImplThread,
1214 impl_thread_weak_ptr_,
1215 &completion,
1216 state.get()));
1217 completion.Wait();
1219 return state.PassAs<base::Value>();
1222 void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
1223 base::DictionaryValue* state) const {
1224 state->Set("layer_tree_host_impl",
1225 layer_tree_host_impl_->AsValue().release());
1226 completion->Signal();
1229 bool ThreadProxy::CommitPendingForTesting() {
1230 DCHECK(IsMainThread());
1231 CommitPendingRequest commit_pending_request;
1233 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1234 Proxy::ImplThread()->PostTask(
1235 base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting,
1236 impl_thread_weak_ptr_,
1237 &commit_pending_request));
1238 commit_pending_request.completion.Wait();
1240 return commit_pending_request.commit_pending;
1243 void ThreadProxy::CommitPendingOnImplThreadForTesting(
1244 CommitPendingRequest* request) {
1245 DCHECK(IsImplThread());
1246 if (layer_tree_host_impl_->output_surface())
1247 request->commit_pending = scheduler_on_impl_thread_->CommitPending();
1248 else
1249 request->commit_pending = false;
1250 request->completion.Signal();
1253 skia::RefPtr<SkPicture> ThreadProxy::CapturePicture() {
1254 DCHECK(IsMainThread());
1255 CompletionEvent completion;
1256 skia::RefPtr<SkPicture> picture;
1258 DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1259 Proxy::ImplThread()->PostTask(
1260 base::Bind(&ThreadProxy::CapturePictureOnImplThread,
1261 impl_thread_weak_ptr_,
1262 &completion,
1263 &picture));
1264 completion.Wait();
1266 return picture;
1269 void ThreadProxy::CapturePictureOnImplThread(CompletionEvent* completion,
1270 skia::RefPtr<SkPicture>* picture) {
1271 DCHECK(IsImplThread());
1272 *picture = layer_tree_host_impl_->CapturePicture();
1273 completion->Signal();
1276 void ThreadProxy::RenewTreePriority() {
1277 bool smoothness_takes_priority =
1278 layer_tree_host_impl_->pinch_gesture_active() ||
1279 layer_tree_host_impl_->CurrentlyScrollingLayer() ||
1280 layer_tree_host_impl_->page_scale_animation_active();
1282 // Update expiration time if smoothness currently takes priority.
1283 if (smoothness_takes_priority) {
1284 smoothness_takes_priority_expiration_time_ =
1285 base::TimeTicks::Now() +
1286 base::TimeDelta::FromMilliseconds(
1287 kSmoothnessTakesPriorityExpirationDelay * 1000);
1290 // We use the same priority for both trees by default.
1291 TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES;
1293 // Smoothness takes priority if expiration time is in the future.
1294 if (smoothness_takes_priority_expiration_time_ > base::TimeTicks::Now())
1295 priority = SMOOTHNESS_TAKES_PRIORITY;
1297 // New content always takes priority when the active tree has
1298 // evicted resources or there is an invalid viewport size.
1299 if (layer_tree_host_impl_->active_tree()->ContentsTexturesPurged() ||
1300 layer_tree_host_impl_->active_tree()->ViewportSizeInvalid())
1301 priority = NEW_CONTENT_TAKES_PRIORITY;
1303 layer_tree_host_impl_->SetTreePriority(priority);
1305 // Notify the the client of this compositor via the output surface.
1306 // TODO(epenner): Route this to compositor-thread instead of output-surface
1307 // after GTFO refactor of compositor-thread (http://crbug/170828).
1308 if (layer_tree_host_impl_->output_surface()) {
1309 layer_tree_host_impl_->output_surface()->
1310 UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY);
1313 base::TimeDelta delay =
1314 smoothness_takes_priority_expiration_time_ - base::TimeTicks::Now();
1316 // Need to make sure a delayed task is posted when we have smoothness
1317 // takes priority expiration time in the future.
1318 if (delay <= base::TimeDelta())
1319 return;
1320 if (renew_tree_priority_on_impl_thread_pending_)
1321 return;
1323 Proxy::ImplThread()->PostDelayedTask(
1324 base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread,
1325 weak_factory_on_impl_thread_.GetWeakPtr()),
1326 delay);
1328 renew_tree_priority_on_impl_thread_pending_ = true;
1331 void ThreadProxy::RenewTreePriorityOnImplThread() {
1332 DCHECK(renew_tree_priority_on_impl_thread_pending_);
1333 renew_tree_priority_on_impl_thread_pending_ = false;
1335 RenewTreePriority();
1338 void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay) {
1339 Proxy::ImplThread()->PostDelayedTask(
1340 base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread,
1341 impl_thread_weak_ptr_),
1342 delay);
1345 void ThreadProxy::StartScrollbarAnimationOnImplThread() {
1346 layer_tree_host_impl_->StartScrollbarAnimation(base::TimeTicks::Now());
1349 } // namespace cc