thread_proxy.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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.
4
5#include "cc/trees/thread_proxy.h"
6
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/trees/layer_tree_host.h"
20#include "cc/trees/layer_tree_impl.h"
21
22namespace {
23
24// Measured in seconds.
25const double kContextRecreationTickRate = 0.03;
26
27// Measured in seconds.
28const double kSmoothnessTakesPriorityExpirationDelay = 0.25;
29
30}  // namespace
31
32namespace cc {
33
34scoped_ptr<Proxy> ThreadProxy::Create(LayerTreeHost* layer_tree_host,
35                                      scoped_ptr<Thread> impl_thread) {
36  return make_scoped_ptr(
37      new ThreadProxy(layer_tree_host, impl_thread.Pass())).PassAs<Proxy>();
38}
39
40ThreadProxy::ThreadProxy(LayerTreeHost* layer_tree_host,
41                         scoped_ptr<Thread> impl_thread)
42    : Proxy(impl_thread.Pass()),
43      animate_requested_(false),
44      commit_requested_(false),
45      commit_request_sent_to_impl_thread_(false),
46      created_offscreen_context_provider_(false),
47      layer_tree_host_(layer_tree_host),
48      renderer_initialized_(false),
49      started_(false),
50      textures_acquired_(true),
51      in_composite_and_readback_(false),
52      manage_tiles_pending_(false),
53      weak_factory_on_impl_thread_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
54      weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(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      inside_draw_(false),
63      defer_commits_(false),
64      renew_tree_priority_on_impl_thread_pending_(false) {
65  TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
66  DCHECK(IsMainThread());
67}
68
69ThreadProxy::~ThreadProxy() {
70  TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
71  DCHECK(IsMainThread());
72  DCHECK(!started_);
73}
74
75bool ThreadProxy::CompositeAndReadback(void* pixels, gfx::Rect rect) {
76  TRACE_EVENT0("cc", "ThreadProxy::CompositeAndReadback");
77  DCHECK(IsMainThread());
78  DCHECK(layer_tree_host_);
79  DCHECK(!defer_commits_);
80
81  if (!layer_tree_host_->InitializeRendererIfNeeded()) {
82    TRACE_EVENT0("cc", "CompositeAndReadback_EarlyOut_LR_Uninitialized");
83    return false;
84  }
85
86  // Perform a synchronous commit.
87  {
88    DebugScopedSetMainThreadBlocked main_thread_blocked(this);
89    CompletionEvent begin_frame_completion;
90    Proxy::ImplThread()->PostTask(
91        base::Bind(&ThreadProxy::ForceBeginFrameOnImplThread,
92                   impl_thread_weak_ptr_,
93                   &begin_frame_completion));
94    begin_frame_completion.Wait();
95  }
96  in_composite_and_readback_ = true;
97  BeginFrame(scoped_ptr<BeginFrameAndCommitState>());
98  in_composite_and_readback_ = false;
99
100  // Perform a synchronous readback.
101  ReadbackRequest request;
102  request.rect = rect;
103  request.pixels = pixels;
104  {
105    DebugScopedSetMainThreadBlocked main_thread_blocked(this);
106    Proxy::ImplThread()->PostTask(
107        base::Bind(&ThreadProxy::RequestReadbackOnImplThread,
108                   impl_thread_weak_ptr_,
109                   &request));
110    request.completion.Wait();
111  }
112  return request.success;
113}
114
115void ThreadProxy::RequestReadbackOnImplThread(ReadbackRequest* request) {
116  DCHECK(Proxy::IsImplThread());
117  DCHECK(!readback_request_on_impl_thread_);
118  if (!layer_tree_host_impl_) {
119    request->success = false;
120    request->completion.Signal();
121    return;
122  }
123
124  readback_request_on_impl_thread_ = request;
125  scheduler_on_impl_thread_->SetNeedsRedraw();
126  scheduler_on_impl_thread_->SetNeedsForcedRedraw();
127}
128
129void ThreadProxy::StartPageScaleAnimation(gfx::Vector2d target_offset,
130                                          bool use_anchor,
131                                          float scale,
132                                          base::TimeDelta duration) {
133  DCHECK(Proxy::IsMainThread());
134  Proxy::ImplThread()->PostTask(
135      base::Bind(&ThreadProxy::RequestStartPageScaleAnimationOnImplThread,
136                 impl_thread_weak_ptr_,
137                 target_offset,
138                 use_anchor,
139                 scale,
140                 duration));
141}
142
143void ThreadProxy::RequestStartPageScaleAnimationOnImplThread(
144    gfx::Vector2d target_offset,
145    bool use_anchor,
146    float scale,
147    base::TimeDelta duration) {
148  DCHECK(Proxy::IsImplThread());
149  if (layer_tree_host_impl_) {
150    layer_tree_host_impl_->StartPageScaleAnimation(
151        target_offset, use_anchor, scale, base::TimeTicks::Now(), duration);
152  }
153}
154
155void ThreadProxy::FinishAllRendering() {
156  DCHECK(Proxy::IsMainThread());
157  DCHECK(!defer_commits_);
158
159  // Make sure all GL drawing is finished on the impl thread.
160  DebugScopedSetMainThreadBlocked main_thread_blocked(this);
161  CompletionEvent completion;
162  Proxy::ImplThread()->PostTask(
163      base::Bind(&ThreadProxy::FinishAllRenderingOnImplThread,
164                 impl_thread_weak_ptr_,
165                 &completion));
166  completion.Wait();
167}
168
169bool ThreadProxy::IsStarted() const {
170  DCHECK(Proxy::IsMainThread());
171  return started_;
172}
173
174bool ThreadProxy::InitializeOutputSurface() {
175  TRACE_EVENT0("cc", "ThreadProxy::InitializeOutputSurface");
176  scoped_ptr<OutputSurface> context = layer_tree_host_->CreateOutputSurface();
177  if (!context)
178    return false;
179
180  Proxy::ImplThread()->PostTask(
181      base::Bind(&ThreadProxy::InitializeOutputSurfaceOnImplThread,
182                 impl_thread_weak_ptr_,
183                 base::Passed(&context)));
184  return true;
185}
186
187void ThreadProxy::SetSurfaceReady() {
188  TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReady");
189  Proxy::ImplThread()->PostTask(base::Bind(
190      &ThreadProxy::SetSurfaceReadyOnImplThread, impl_thread_weak_ptr_));
191}
192
193void ThreadProxy::SetSurfaceReadyOnImplThread() {
194  TRACE_EVENT0("cc", "ThreadProxy::SetSurfaceReadyOnImplThread");
195  scheduler_on_impl_thread_->SetCanBeginFrame(true);
196}
197
198void ThreadProxy::SetVisible(bool visible) {
199  TRACE_EVENT0("cc", "ThreadProxy::SetVisible");
200  DebugScopedSetMainThreadBlocked main_thread_blocked(this);
201  CompletionEvent completion;
202  Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::SetVisibleOnImplThread,
203                                           impl_thread_weak_ptr_,
204                                           &completion,
205                                           visible));
206  completion.Wait();
207}
208
209void ThreadProxy::SetVisibleOnImplThread(CompletionEvent* completion,
210                                         bool visible) {
211  TRACE_EVENT0("cc", "ThreadProxy::SetVisibleOnImplThread");
212  layer_tree_host_impl_->SetVisible(visible);
213  scheduler_on_impl_thread_->SetVisible(visible);
214  completion->Signal();
215}
216
217bool ThreadProxy::InitializeRenderer() {
218  TRACE_EVENT0("cc", "ThreadProxy::InitializeRenderer");
219  // Make a blocking call to InitializeRendererOnImplThread. The results of that
220  // call are pushed into the initialize_succeeded and capabilities local
221  // variables.
222  CompletionEvent completion;
223  bool initialize_succeeded = false;
224  RendererCapabilities capabilities;
225  DebugScopedSetMainThreadBlocked main_thread_blocked(this);
226  Proxy::ImplThread()->PostTask(
227      base::Bind(&ThreadProxy::InitializeRendererOnImplThread,
228                 impl_thread_weak_ptr_,
229                 &completion,
230                 &initialize_succeeded,
231                 &capabilities));
232  completion.Wait();
233
234  if (initialize_succeeded) {
235    renderer_initialized_ = true;
236    renderer_capabilities_main_thread_copy_ = capabilities;
237  }
238  return initialize_succeeded;
239}
240
241bool ThreadProxy::RecreateOutputSurface() {
242  TRACE_EVENT0("cc", "ThreadProxy::RecreateOutputSurface");
243  DCHECK(IsMainThread());
244
245  // Try to create the surface.
246  scoped_ptr<OutputSurface> output_surface =
247      layer_tree_host_->CreateOutputSurface();
248  if (!output_surface)
249    return false;
250  scoped_refptr<cc::ContextProvider> offscreen_context_provider;
251  if (created_offscreen_context_provider_) {
252    offscreen_context_provider = layer_tree_host_->client()->
253        OffscreenContextProviderForCompositorThread();
254    if (!offscreen_context_provider)
255      return false;
256  }
257
258  // Make a blocking call to RecreateOutputSurfaceOnImplThread. The results of
259  // that call are pushed into the recreate_succeeded and capabilities local
260  // variables.
261  CompletionEvent completion;
262  bool recreate_succeeded = false;
263  RendererCapabilities capabilities;
264  DebugScopedSetMainThreadBlocked main_thread_blocked(this);
265  Proxy::ImplThread()->PostTask(
266      base::Bind(&ThreadProxy::RecreateOutputSurfaceOnImplThread,
267                 impl_thread_weak_ptr_,
268                 &completion,
269                 base::Passed(&output_surface),
270                 offscreen_context_provider,
271                 &recreate_succeeded,
272                 &capabilities));
273  completion.Wait();
274
275  if (recreate_succeeded)
276    renderer_capabilities_main_thread_copy_ = capabilities;
277  return recreate_succeeded;
278}
279
280const RendererCapabilities& ThreadProxy::GetRendererCapabilities() const {
281  DCHECK(renderer_initialized_);
282  return renderer_capabilities_main_thread_copy_;
283}
284
285void ThreadProxy::SetNeedsAnimate() {
286  DCHECK(IsMainThread());
287  if (animate_requested_)
288    return;
289
290  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsAnimate");
291  animate_requested_ = true;
292
293  if (commit_request_sent_to_impl_thread_)
294    return;
295  commit_request_sent_to_impl_thread_ = true;
296  Proxy::ImplThread()->PostTask(base::Bind(
297      &ThreadProxy::SetNeedsCommitOnImplThread, impl_thread_weak_ptr_));
298}
299
300void ThreadProxy::SetNeedsCommit() {
301  DCHECK(IsMainThread());
302  if (commit_requested_)
303    return;
304  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommit");
305  commit_requested_ = true;
306
307  if (commit_request_sent_to_impl_thread_)
308    return;
309  commit_request_sent_to_impl_thread_ = true;
310  Proxy::ImplThread()->PostTask(base::Bind(
311      &ThreadProxy::SetNeedsCommitOnImplThread, impl_thread_weak_ptr_));
312}
313
314void ThreadProxy::DidLoseOutputSurfaceOnImplThread() {
315  DCHECK(IsImplThread());
316  TRACE_EVENT0("cc", "ThreadProxy::DidLoseOutputSurfaceOnImplThread");
317  Proxy::ImplThread()->PostTask(
318      base::Bind(&ThreadProxy::CheckOutputSurfaceStatusOnImplThread,
319                 impl_thread_weak_ptr_));
320}
321
322void ThreadProxy::CheckOutputSurfaceStatusOnImplThread() {
323  DCHECK(IsImplThread());
324  TRACE_EVENT0("cc", "ThreadProxy::CheckOutputSurfaceStatusOnImplThread");
325  if (!layer_tree_host_impl_->IsContextLost())
326    return;
327  if (cc::ContextProvider* offscreen_contexts = layer_tree_host_impl_->
328          resource_provider()->offscreen_context_provider())
329    offscreen_contexts->VerifyContexts();
330  scheduler_on_impl_thread_->DidLoseOutputSurface();
331}
332
333void ThreadProxy::OnSwapBuffersCompleteOnImplThread() {
334  DCHECK(IsImplThread());
335  TRACE_EVENT0("cc", "ThreadProxy::OnSwapBuffersCompleteOnImplThread");
336  scheduler_on_impl_thread_->DidSwapBuffersComplete();
337  Proxy::MainThread()->PostTask(
338      base::Bind(&ThreadProxy::DidCompleteSwapBuffers, main_thread_weak_ptr_));
339}
340
341void ThreadProxy::OnVSyncParametersChanged(base::TimeTicks timebase,
342                                           base::TimeDelta interval) {
343  DCHECK(IsImplThread());
344  TRACE_EVENT2("cc",
345               "ThreadProxy::OnVSyncParametersChanged",
346               "timebase",
347               (timebase - base::TimeTicks()).InMilliseconds(),
348               "interval",
349               interval.InMilliseconds());
350  scheduler_on_impl_thread_->SetTimebaseAndInterval(timebase, interval);
351}
352
353void ThreadProxy::OnCanDrawStateChanged(bool can_draw) {
354  DCHECK(IsImplThread());
355  TRACE_EVENT1(
356      "cc", "ThreadProxy::OnCanDrawStateChanged", "can_draw", can_draw);
357  scheduler_on_impl_thread_->SetCanDraw(can_draw);
358}
359
360void ThreadProxy::OnHasPendingTreeStateChanged(bool has_pending_tree) {
361  DCHECK(IsImplThread());
362  TRACE_EVENT1("cc",
363               "ThreadProxy::OnHasPendingTreeStateChanged",
364               "has_pending_tree",
365               has_pending_tree);
366  scheduler_on_impl_thread_->SetHasPendingTree(has_pending_tree);
367}
368
369void ThreadProxy::SetNeedsCommitOnImplThread() {
370  DCHECK(IsImplThread());
371  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsCommitOnImplThread");
372  scheduler_on_impl_thread_->SetNeedsCommit();
373}
374
375void ThreadProxy::SetNeedsManageTilesOnImplThread() {
376  if (manage_tiles_pending_)
377    return;
378  Proxy::ImplThread()->PostTask(
379      base::Bind(&ThreadProxy::ManageTilesOnImplThread, impl_thread_weak_ptr_));
380  manage_tiles_pending_ = true;
381}
382
383void ThreadProxy::ManageTilesOnImplThread() {
384  // TODO(nduca): If needed, move this into CCSchedulerStateMachine.
385  manage_tiles_pending_ = false;
386  if (layer_tree_host_impl_)
387    layer_tree_host_impl_->ManageTiles();
388}
389
390void ThreadProxy::SetNeedsForcedCommitOnImplThread() {
391  DCHECK(IsImplThread());
392  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsForcedCommitOnImplThread");
393  scheduler_on_impl_thread_->SetNeedsForcedCommit();
394}
395
396void ThreadProxy::PostAnimationEventsToMainThreadOnImplThread(
397    scoped_ptr<AnimationEventsVector> events,
398    base::Time wall_clock_time) {
399  DCHECK(IsImplThread());
400  TRACE_EVENT0("cc",
401               "ThreadProxy::PostAnimationEventsToMainThreadOnImplThread");
402  Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::SetAnimationEvents,
403                                           main_thread_weak_ptr_,
404                                           base::Passed(&events),
405                                           wall_clock_time));
406}
407
408bool ThreadProxy::ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
409                                                          int priority_cutoff) {
410  DCHECK(IsImplThread());
411
412  if (!layer_tree_host_->contents_texture_manager())
413    return false;
414
415  bool reduce_result = layer_tree_host_->contents_texture_manager()->
416      ReduceMemoryOnImplThread(limit_bytes,
417                               priority_cutoff,
418                               layer_tree_host_impl_->resource_provider());
419  if (!reduce_result)
420    return false;
421
422  // The texture upload queue may reference textures that were just purged,
423  // clear them from the queue.
424  if (current_resource_update_controller_on_impl_thread_) {
425    current_resource_update_controller_on_impl_thread_->
426        DiscardUploadsToEvictedResources();
427  }
428  return true;
429}
430
431void ThreadProxy::ReduceWastedContentsTextureMemoryOnImplThread() {
432  DCHECK(IsImplThread());
433
434  if (!layer_tree_host_->contents_texture_manager())
435    return;
436
437  layer_tree_host_->contents_texture_manager()->ReduceWastedMemoryOnImplThread(
438      layer_tree_host_impl_->resource_provider());
439}
440
441void ThreadProxy::SendManagedMemoryStats() {
442  DCHECK(IsImplThread());
443  if (!layer_tree_host_impl_)
444    return;
445  if (!layer_tree_host_->contents_texture_manager())
446    return;
447
448  // If we are using impl-side painting, then SendManagedMemoryStats is called
449  // directly after the tile manager's manage function, and doesn't need to
450  // interact with main thread's layer tree.
451  if (layer_tree_host_->settings().impl_side_painting)
452    return;
453
454  layer_tree_host_impl_->SendManagedMemoryStats(
455      layer_tree_host_->contents_texture_manager()->MemoryVisibleBytes(),
456      layer_tree_host_->contents_texture_manager()->
457          MemoryVisibleAndNearbyBytes(),
458      layer_tree_host_->contents_texture_manager()->MemoryUseBytes());
459}
460
461bool ThreadProxy::IsInsideDraw() { return inside_draw_; }
462
463void ThreadProxy::SetNeedsRedraw() {
464  DCHECK(IsMainThread());
465  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedraw");
466  Proxy::ImplThread()->PostTask(base::Bind(
467      &ThreadProxy::SetFullRootLayerDamageOnImplThread, impl_thread_weak_ptr_));
468  Proxy::ImplThread()->PostTask(base::Bind(
469      &ThreadProxy::SetNeedsRedrawOnImplThread, impl_thread_weak_ptr_));
470}
471
472void ThreadProxy::SetDeferCommits(bool defer_commits) {
473  DCHECK(IsMainThread());
474  DCHECK_NE(defer_commits_, defer_commits);
475  defer_commits_ = defer_commits;
476
477  if (defer_commits_)
478    TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::SetDeferCommits", this);
479  else
480    TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::SetDeferCommits", this);
481
482  if (!defer_commits_ && pending_deferred_commit_)
483    Proxy::MainThread()->PostTask(
484        base::Bind(&ThreadProxy::BeginFrame,
485                   main_thread_weak_ptr_,
486                   base::Passed(&pending_deferred_commit_)));
487}
488
489bool ThreadProxy::CommitRequested() const {
490  DCHECK(IsMainThread());
491  return commit_requested_;
492}
493
494void ThreadProxy::SetNeedsRedrawOnImplThread() {
495  DCHECK(IsImplThread());
496  TRACE_EVENT0("cc", "ThreadProxy::SetNeedsRedrawOnImplThread");
497  scheduler_on_impl_thread_->SetNeedsRedraw();
498}
499
500void ThreadProxy::DidSwapUseIncompleteTileOnImplThread() {
501  DCHECK(IsImplThread());
502  TRACE_EVENT0("cc", "ThreadProxy::DidSwapUseIncompleteTileOnImplThread");
503  scheduler_on_impl_thread_->DidSwapUseIncompleteTile();
504}
505
506void ThreadProxy::DidInitializeVisibleTileOnImplThread() {
507  DCHECK(IsImplThread());
508  TRACE_EVENT0("cc", "ThreadProxy::DidInitializeVisibleTileOnImplThread");
509  scheduler_on_impl_thread_->SetNeedsRedraw();
510}
511
512void ThreadProxy::MainThreadHasStoppedFlinging() {
513  if (input_handler_on_impl_thread_)
514    input_handler_on_impl_thread_->MainThreadHasStoppedFlinging();
515}
516
517void ThreadProxy::Start() {
518  DCHECK(IsMainThread());
519  DCHECK(Proxy::ImplThread());
520  // Create LayerTreeHostImpl.
521  DebugScopedSetMainThreadBlocked main_thread_blocked(this);
522  CompletionEvent completion;
523  scoped_ptr<InputHandler> handler = layer_tree_host_->CreateInputHandler();
524  Proxy::ImplThread()->PostTask(
525      base::Bind(&ThreadProxy::InitializeImplOnImplThread,
526                 base::Unretained(this),
527                 &completion,
528                 handler.release()));
529  completion.Wait();
530
531  main_thread_weak_ptr_ = weak_factory_.GetWeakPtr();
532
533  started_ = true;
534}
535
536void ThreadProxy::Stop() {
537  TRACE_EVENT0("cc", "ThreadProxy::Stop");
538  DCHECK(IsMainThread());
539  DCHECK(started_);
540
541  // Synchronously deletes the impl.
542  {
543    DebugScopedSetMainThreadBlocked main_thread_blocked(this);
544
545    CompletionEvent completion;
546    Proxy::ImplThread()->PostTask(
547        base::Bind(&ThreadProxy::LayerTreeHostClosedOnImplThread,
548                   impl_thread_weak_ptr_,
549                   &completion));
550    completion.Wait();
551  }
552
553  weak_factory_.InvalidateWeakPtrs();
554
555  DCHECK(!layer_tree_host_impl_.get());  // verify that the impl deleted.
556  layer_tree_host_ = NULL;
557  started_ = false;
558}
559
560void ThreadProxy::ForceSerializeOnSwapBuffers() {
561  DebugScopedSetMainThreadBlocked main_thread_blocked(this);
562  CompletionEvent completion;
563  Proxy::ImplThread()->PostTask(
564      base::Bind(&ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread,
565                 impl_thread_weak_ptr_,
566                 &completion));
567  completion.Wait();
568}
569
570void ThreadProxy::ForceSerializeOnSwapBuffersOnImplThread(
571    CompletionEvent* completion) {
572  if (renderer_initialized_)
573    layer_tree_host_impl_->renderer()->DoNoOp();
574  completion->Signal();
575}
576
577void ThreadProxy::FinishAllRenderingOnImplThread(CompletionEvent* completion) {
578  TRACE_EVENT0("cc", "ThreadProxy::FinishAllRenderingOnImplThread");
579  DCHECK(IsImplThread());
580  layer_tree_host_impl_->FinishAllRendering();
581  completion->Signal();
582}
583
584void ThreadProxy::ForceBeginFrameOnImplThread(CompletionEvent* completion) {
585  TRACE_EVENT0("cc", "ThreadProxy::ForceBeginFrameOnImplThread");
586  DCHECK(!begin_frame_completion_event_on_impl_thread_);
587
588  SetNeedsForcedCommitOnImplThread();
589  if (scheduler_on_impl_thread_->CommitPending()) {
590    completion->Signal();
591    return;
592  }
593
594  begin_frame_completion_event_on_impl_thread_ = completion;
595}
596
597void ThreadProxy::ScheduledActionBeginFrame() {
598  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionBeginFrame");
599  scoped_ptr<BeginFrameAndCommitState> begin_frame_state(
600      new BeginFrameAndCommitState);
601  begin_frame_state->monotonic_frame_begin_time = base::TimeTicks::Now();
602  begin_frame_state->scroll_info = layer_tree_host_impl_->ProcessScrollDeltas();
603  begin_frame_state->impl_transform =
604      layer_tree_host_impl_->active_tree()->ImplTransform();
605  DCHECK_GT(layer_tree_host_impl_->memory_allocation_limit_bytes(), 0u);
606  begin_frame_state->memory_allocation_limit_bytes =
607      layer_tree_host_impl_->memory_allocation_limit_bytes();
608  Proxy::MainThread()->PostTask(base::Bind(&ThreadProxy::BeginFrame,
609                                           main_thread_weak_ptr_,
610                                           base::Passed(&begin_frame_state)));
611
612  if (begin_frame_completion_event_on_impl_thread_) {
613    begin_frame_completion_event_on_impl_thread_->Signal();
614    begin_frame_completion_event_on_impl_thread_ = NULL;
615  }
616}
617
618void ThreadProxy::BeginFrame(
619    scoped_ptr<BeginFrameAndCommitState> begin_frame_state) {
620  TRACE_EVENT0("cc", "ThreadProxy::BeginFrame");
621  DCHECK(IsMainThread());
622  if (!layer_tree_host_)
623    return;
624
625  if (defer_commits_) {
626    pending_deferred_commit_ = begin_frame_state.Pass();
627    layer_tree_host_->DidDeferCommit();
628    TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
629    return;
630  }
631
632  // Do not notify the impl thread of commit requests that occur during
633  // the apply/animate/layout part of the BeginFrameAndCommit process since
634  // those commit requests will get painted immediately. Once we have done
635  // the paint, commit_requested_ will be set to false to allow new commit
636  // requests to be scheduled.
637  commit_requested_ = true;
638  commit_request_sent_to_impl_thread_ = true;
639
640  // On the other hand, the AnimationRequested flag needs to be cleared
641  // here so that any animation requests generated by the apply or animate
642  // callbacks will trigger another frame.
643  animate_requested_ = false;
644
645  if (begin_frame_state) {
646    layer_tree_host_->ApplyScrollAndScale(*begin_frame_state->scroll_info);
647    layer_tree_host_->SetImplTransform(begin_frame_state->impl_transform);
648  }
649
650  if (!in_composite_and_readback_ && !layer_tree_host_->visible()) {
651    commit_requested_ = false;
652    commit_request_sent_to_impl_thread_ = false;
653
654    TRACE_EVENT0("cc", "EarlyOut_NotVisible");
655    Proxy::ImplThread()->PostTask(base::Bind(
656        &ThreadProxy::BeginFrameAbortedOnImplThread, impl_thread_weak_ptr_));
657    return;
658  }
659
660  layer_tree_host_->WillBeginFrame();
661
662  if (begin_frame_state) {
663    layer_tree_host_->UpdateAnimations(
664        begin_frame_state->monotonic_frame_begin_time);
665  }
666
667  // Unlink any backings that the impl thread has evicted, so that we know to
668  // re-paint them in UpdateLayers.
669  if (layer_tree_host_->contents_texture_manager()) {
670    layer_tree_host_->contents_texture_manager()->
671        UnlinkAndClearEvictedBackings();
672  }
673
674  layer_tree_host_->Layout();
675
676  // Clear the commit flag after updating animations and layout here --- objects
677  // that only layout when painted will trigger another SetNeedsCommit inside
678  // UpdateLayers.
679  commit_requested_ = false;
680  commit_request_sent_to_impl_thread_ = false;
681
682  if (!layer_tree_host_->InitializeRendererIfNeeded()) {
683    TRACE_EVENT0("cc", "EarlyOut_InitializeFailed");
684    return;
685  }
686
687  scoped_ptr<ResourceUpdateQueue> queue =
688      make_scoped_ptr(new ResourceUpdateQueue);
689  layer_tree_host_->UpdateLayers(
690      queue.get(),
691      begin_frame_state ? begin_frame_state->memory_allocation_limit_bytes
692                        : 0u);
693
694  // Once single buffered layers are committed, they cannot be modified until
695  // they are drawn by the impl thread.
696  textures_acquired_ = false;
697
698  layer_tree_host_->WillCommit();
699  // Before applying scrolls and calling animate, we set animate_requested_ to
700  // false. If it is true now, it means SetNeedAnimate was called again, but
701  // during a state when commit_request_sent_to_impl_thread_ = true. We need to
702  // force that call to happen again now so that the commit request is sent to
703  // the impl thread.
704  if (animate_requested_) {
705    // Forces SetNeedsAnimate to consider posting a commit task.
706    animate_requested_ = false;
707    SetNeedsAnimate();
708  }
709
710  scoped_refptr<cc::ContextProvider> offscreen_context_provider;
711  if (renderer_capabilities_main_thread_copy_.using_offscreen_context3d &&
712      layer_tree_host_->needs_offscreen_context()) {
713    offscreen_context_provider = layer_tree_host_->client()->
714        OffscreenContextProviderForCompositorThread();
715    if (offscreen_context_provider)
716      created_offscreen_context_provider_ = true;
717  }
718
719  // Notify the impl thread that the BeginFrame has completed. This will
720  // begin the commit process, which is blocking from the main thread's
721  // point of view, but asynchronously performed on the impl thread,
722  // coordinated by the Scheduler.
723  {
724    TRACE_EVENT0("cc", "commit");
725
726    DebugScopedSetMainThreadBlocked main_thread_blocked(this);
727
728    RenderingStatsInstrumentation* stats_instrumentation =
729        layer_tree_host_->rendering_stats_instrumentation();
730    base::TimeTicks start_time = stats_instrumentation->StartRecording();
731
732    CompletionEvent completion;
733    Proxy::ImplThread()->PostTask(
734        base::Bind(&ThreadProxy::BeginFrameCompleteOnImplThread,
735                   impl_thread_weak_ptr_,
736                   &completion,
737                   queue.release(),
738                   offscreen_context_provider));
739    completion.Wait();
740
741    base::TimeDelta duration = stats_instrumentation->EndRecording(start_time);
742    stats_instrumentation->AddCommit(duration);
743  }
744
745  layer_tree_host_->CommitComplete();
746  layer_tree_host_->DidBeginFrame();
747}
748
749void ThreadProxy::BeginFrameCompleteOnImplThread(
750    CompletionEvent* completion,
751    ResourceUpdateQueue* raw_queue,
752    scoped_refptr<cc::ContextProvider> offscreen_context_provider) {
753  scoped_ptr<ResourceUpdateQueue> queue(raw_queue);
754
755  TRACE_EVENT0("cc", "ThreadProxy::BeginFrameCompleteOnImplThread");
756  DCHECK(!commit_completion_event_on_impl_thread_);
757  DCHECK(IsImplThread() && IsMainThreadBlocked());
758  DCHECK(scheduler_on_impl_thread_);
759  DCHECK(scheduler_on_impl_thread_->CommitPending());
760
761  if (!layer_tree_host_impl_) {
762    TRACE_EVENT0("cc", "EarlyOut_NoLayerTree");
763    completion->Signal();
764    return;
765  }
766
767  if (offscreen_context_provider)
768    offscreen_context_provider->BindToCurrentThread();
769  layer_tree_host_impl_->resource_provider()->
770      set_offscreen_context_provider(offscreen_context_provider);
771
772  if (layer_tree_host_->contents_texture_manager()->
773          LinkedEvictedBackingsExist()) {
774    // Clear any uploads we were making to textures linked to evicted
775    // resources
776    queue->ClearUploadsToEvictedResources();
777    // Some textures in the layer tree are invalid. Kick off another commit
778    // to fill them again.
779    SetNeedsCommitOnImplThread();
780  }
781
782  layer_tree_host_->contents_texture_manager()->
783      PushTexturePrioritiesToBackings();
784
785  current_resource_update_controller_on_impl_thread_ =
786      ResourceUpdateController::Create(
787          this,
788          Proxy::ImplThread(),
789          queue.Pass(),
790          layer_tree_host_impl_->resource_provider());
791  current_resource_update_controller_on_impl_thread_->PerformMoreUpdates(
792      scheduler_on_impl_thread_->AnticipatedDrawTime());
793
794  commit_completion_event_on_impl_thread_ = completion;
795}
796
797void ThreadProxy::BeginFrameAbortedOnImplThread() {
798  TRACE_EVENT0("cc", "ThreadProxy::BeginFrameAbortedOnImplThread");
799  DCHECK(IsImplThread());
800  DCHECK(scheduler_on_impl_thread_);
801  DCHECK(scheduler_on_impl_thread_->CommitPending());
802
803  scheduler_on_impl_thread_->BeginFrameAborted();
804}
805
806void ThreadProxy::ScheduledActionCommit() {
807  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionCommit");
808  DCHECK(IsImplThread());
809  DCHECK(commit_completion_event_on_impl_thread_);
810  DCHECK(current_resource_update_controller_on_impl_thread_);
811
812  // Complete all remaining texture updates.
813  current_resource_update_controller_on_impl_thread_->Finalize();
814  current_resource_update_controller_on_impl_thread_.reset();
815
816  layer_tree_host_impl_->BeginCommit();
817  layer_tree_host_->BeginCommitOnImplThread(layer_tree_host_impl_.get());
818  layer_tree_host_->FinishCommitOnImplThread(layer_tree_host_impl_.get());
819  layer_tree_host_impl_->CommitComplete();
820
821  next_frame_is_newly_committed_frame_on_impl_thread_ = true;
822
823  if (layer_tree_host_->settings().impl_side_painting &&
824      layer_tree_host_->BlocksPendingCommit()) {
825    // For some layer types in impl-side painting, the commit is held until
826    // the pending tree is activated.
827    TRACE_EVENT_INSTANT0("cc", "HoldCommit");
828    completion_event_for_commit_held_on_tree_activation_ =
829        commit_completion_event_on_impl_thread_;
830    commit_completion_event_on_impl_thread_ = NULL;
831  } else {
832    commit_completion_event_on_impl_thread_->Signal();
833    commit_completion_event_on_impl_thread_ = NULL;
834  }
835
836  // SetVisible kicks off the next scheduler action, so this must be last.
837  scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
838}
839
840void ThreadProxy::ScheduledActionCheckForCompletedTileUploads() {
841  DCHECK(IsImplThread());
842  TRACE_EVENT0("cc",
843               "ThreadProxy::ScheduledActionCheckForCompletedTileUploads");
844  layer_tree_host_impl_->CheckForCompletedTileUploads();
845}
846
847void ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded() {
848  DCHECK(IsImplThread());
849  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionActivatePendingTreeIfNeeded");
850  layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
851}
852
853void ThreadProxy::ScheduledActionBeginContextRecreation() {
854  DCHECK(IsImplThread());
855  Proxy::MainThread()->PostTask(
856      base::Bind(&ThreadProxy::BeginContextRecreation, main_thread_weak_ptr_));
857}
858
859ScheduledActionDrawAndSwapResult
860ThreadProxy::ScheduledActionDrawAndSwapInternal(bool forced_draw) {
861  TRACE_EVENT0("cc", "ThreadProxy::ScheduledActionDrawAndSwap");
862
863  base::AutoReset<bool> mark_inside(&inside_draw_, true);
864
865  ScheduledActionDrawAndSwapResult result;
866  result.did_draw = false;
867  result.did_swap = false;
868  DCHECK(IsImplThread());
869  DCHECK(layer_tree_host_impl_.get());
870  if (!layer_tree_host_impl_)
871    return result;
872
873  DCHECK(layer_tree_host_impl_->renderer());
874  if (!layer_tree_host_impl_->renderer())
875    return result;
876
877  // FIXME: compute the frame display time more intelligently
878  base::TimeTicks monotonic_time = base::TimeTicks::Now();
879  base::Time wall_clock_time = base::Time::Now();
880
881  if (input_handler_on_impl_thread_)
882    input_handler_on_impl_thread_->Animate(monotonic_time);
883
884  layer_tree_host_impl_->ActivatePendingTreeIfNeeded();
885  layer_tree_host_impl_->Animate(monotonic_time, wall_clock_time);
886
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.
892
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.
897
898  LayerTreeHostImpl::FrameData frame;
899  bool draw_frame =
900      layer_tree_host_impl_->CanDraw() &&
901      (layer_tree_host_impl_->PrepareToDraw(&frame) || forced_draw);
902  if (draw_frame) {
903    layer_tree_host_impl_->DrawLayers(
904        &frame,
905        scheduler_on_impl_thread_->LastVSyncTime());
906    result.did_draw= true;
907  }
908  layer_tree_host_impl_->DidDrawAllLayers(frame);
909
910  // Check for tree activation.
911  if (completion_event_for_commit_held_on_tree_activation_ &&
912      !layer_tree_host_impl_->pending_tree()) {
913    TRACE_EVENT_INSTANT0("cc", "ReleaseCommitbyActivation");
914    DCHECK(layer_tree_host_impl_->settings().impl_side_painting);
915    completion_event_for_commit_held_on_tree_activation_->Signal();
916    completion_event_for_commit_held_on_tree_activation_ = NULL;
917  }
918
919  // Check for a pending CompositeAndReadback.
920  if (readback_request_on_impl_thread_) {
921    readback_request_on_impl_thread_->success = false;
922    if (draw_frame) {
923      layer_tree_host_impl_->Readback(readback_request_on_impl_thread_->pixels,
924                                      readback_request_on_impl_thread_->rect);
925      readback_request_on_impl_thread_->success =
926          !layer_tree_host_impl_->IsContextLost();
927    }
928    readback_request_on_impl_thread_->completion.Signal();
929    readback_request_on_impl_thread_ = NULL;
930  } else if (draw_frame) {
931    result.did_swap = layer_tree_host_impl_->SwapBuffers();
932
933    if (frame.contains_incomplete_tile)
934      DidSwapUseIncompleteTileOnImplThread();
935  }
936
937  // Tell the main thread that the the newly-commited frame was drawn.
938  if (next_frame_is_newly_committed_frame_on_impl_thread_) {
939    next_frame_is_newly_committed_frame_on_impl_thread_ = false;
940    Proxy::MainThread()->PostTask(
941        base::Bind(&ThreadProxy::DidCommitAndDrawFrame, main_thread_weak_ptr_));
942  }
943
944  if (draw_frame)
945    CheckOutputSurfaceStatusOnImplThread();
946
947  layer_tree_host_impl_->BeginNextFrame();
948
949  return result;
950}
951
952void ThreadProxy::AcquireLayerTextures() {
953  // Called when the main thread needs to modify a layer texture that is used
954  // directly by the compositor.
955  // This method will block until the next compositor draw if there is a
956  // previously committed frame that is still undrawn. This is necessary to
957  // ensure that the main thread does not monopolize access to the textures.
958  DCHECK(IsMainThread());
959
960  if (textures_acquired_)
961    return;
962
963  TRACE_EVENT0("cc", "ThreadProxy::AcquireLayerTextures");
964  DebugScopedSetMainThreadBlocked main_thread_blocked(this);
965  CompletionEvent completion;
966  Proxy::ImplThread()->PostTask(
967      base::Bind(&ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread,
968                 impl_thread_weak_ptr_,
969                 &completion));
970  // Block until it is safe to write to layer textures from the main thread.
971  completion.Wait();
972
973  textures_acquired_ = true;
974}
975
976void ThreadProxy::AcquireLayerTexturesForMainThreadOnImplThread(
977    CompletionEvent* completion) {
978  DCHECK(IsImplThread());
979  DCHECK(!texture_acquisition_completion_event_on_impl_thread_);
980
981  texture_acquisition_completion_event_on_impl_thread_ = completion;
982  scheduler_on_impl_thread_->SetMainThreadNeedsLayerTextures();
983}
984
985void ThreadProxy::ScheduledActionAcquireLayerTexturesForMainThread() {
986  DCHECK(texture_acquisition_completion_event_on_impl_thread_);
987  texture_acquisition_completion_event_on_impl_thread_->Signal();
988  texture_acquisition_completion_event_on_impl_thread_ = NULL;
989}
990
991ScheduledActionDrawAndSwapResult
992ThreadProxy::ScheduledActionDrawAndSwapIfPossible() {
993  return ScheduledActionDrawAndSwapInternal(false);
994}
995
996ScheduledActionDrawAndSwapResult
997ThreadProxy::ScheduledActionDrawAndSwapForced() {
998  return ScheduledActionDrawAndSwapInternal(true);
999}
1000
1001void ThreadProxy::DidAnticipatedDrawTimeChange(base::TimeTicks time) {
1002  if (layer_tree_host_impl_)
1003    layer_tree_host_impl_->SetAnticipatedDrawTime(time);
1004
1005  if (current_resource_update_controller_on_impl_thread_)
1006    current_resource_update_controller_on_impl_thread_->PerformMoreUpdates(time);
1007}
1008
1009void ThreadProxy::ReadyToFinalizeTextureUpdates() {
1010  DCHECK(IsImplThread());
1011  scheduler_on_impl_thread_->BeginFrameComplete();
1012}
1013
1014void ThreadProxy::DidCommitAndDrawFrame() {
1015  DCHECK(IsMainThread());
1016  if (!layer_tree_host_)
1017    return;
1018  layer_tree_host_->DidCommitAndDrawFrame();
1019}
1020
1021void ThreadProxy::DidCompleteSwapBuffers() {
1022  DCHECK(IsMainThread());
1023  if (!layer_tree_host_)
1024    return;
1025  layer_tree_host_->DidCompleteSwapBuffers();
1026}
1027
1028void ThreadProxy::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
1029                                     base::Time wall_clock_time) {
1030  TRACE_EVENT0("cc", "ThreadProxy::SetAnimationEvents");
1031  DCHECK(IsMainThread());
1032  if (!layer_tree_host_)
1033    return;
1034  layer_tree_host_->SetAnimationEvents(events.Pass(), wall_clock_time);
1035}
1036
1037void ThreadProxy::BeginContextRecreation() {
1038  TRACE_EVENT0("cc", "ThreadProxy::BeginContextRecreation");
1039  DCHECK(IsMainThread());
1040  layer_tree_host_->DidLoseOutputSurface();
1041  output_surface_recreation_callback_.Reset(base::Bind(
1042      &ThreadProxy::TryToRecreateOutputSurface, base::Unretained(this)));
1043  Proxy::MainThread()->PostTask(output_surface_recreation_callback_.callback());
1044}
1045
1046void ThreadProxy::TryToRecreateOutputSurface() {
1047  DCHECK(IsMainThread());
1048  DCHECK(layer_tree_host_);
1049  LayerTreeHost::RecreateResult result =
1050      layer_tree_host_->RecreateOutputSurface();
1051  if (result == LayerTreeHost::RecreateFailedButTryAgain)
1052    Proxy::MainThread()->PostTask(
1053        output_surface_recreation_callback_.callback());
1054  else if (result == LayerTreeHost::RecreateSucceeded)
1055    output_surface_recreation_callback_.Cancel();
1056}
1057
1058void ThreadProxy::InitializeImplOnImplThread(CompletionEvent* completion,
1059                                             InputHandler* handler) {
1060  TRACE_EVENT0("cc", "ThreadProxy::InitializeImplOnImplThread");
1061  DCHECK(IsImplThread());
1062  layer_tree_host_impl_ = layer_tree_host_->CreateLayerTreeHostImpl(this);
1063  const base::TimeDelta display_refresh_interval =
1064      base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond /
1065                                        60);
1066  scoped_ptr<FrameRateController> frame_rate_controller;
1067  if (render_vsync_enabled_) {
1068    frame_rate_controller.reset(
1069        new FrameRateController(DelayBasedTimeSource::Create(
1070            display_refresh_interval, Proxy::ImplThread())));
1071  } else {
1072    frame_rate_controller.reset(new FrameRateController(Proxy::ImplThread()));
1073  }
1074  SchedulerSettings scheduler_settings;
1075  scheduler_settings.impl_side_painting =
1076      layer_tree_host_->settings().impl_side_painting;
1077  scheduler_on_impl_thread_ = Scheduler::Create(this,
1078                                                frame_rate_controller.Pass(),
1079                                                scheduler_settings);
1080  scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible());
1081
1082  input_handler_on_impl_thread_ = scoped_ptr<InputHandler>(handler);
1083  if (input_handler_on_impl_thread_)
1084    input_handler_on_impl_thread_->BindToClient(layer_tree_host_impl_.get());
1085
1086  impl_thread_weak_ptr_ = weak_factory_on_impl_thread_.GetWeakPtr();
1087  completion->Signal();
1088}
1089
1090void ThreadProxy::InitializeOutputSurfaceOnImplThread(
1091    scoped_ptr<OutputSurface> output_surface) {
1092  TRACE_EVENT0("cc", "ThreadProxy::InitializeContextOnImplThread");
1093  DCHECK(IsImplThread());
1094  output_surface_before_initialization_on_impl_thread_ = output_surface.Pass();
1095}
1096
1097void ThreadProxy::InitializeRendererOnImplThread(
1098    CompletionEvent* completion,
1099    bool* initialize_succeeded,
1100    RendererCapabilities* capabilities) {
1101  TRACE_EVENT0("cc", "ThreadProxy::InitializeRendererOnImplThread");
1102  DCHECK(IsImplThread());
1103  DCHECK(output_surface_before_initialization_on_impl_thread_.get());
1104  *initialize_succeeded = layer_tree_host_impl_->InitializeRenderer(
1105      output_surface_before_initialization_on_impl_thread_.Pass());
1106  if (*initialize_succeeded) {
1107    *capabilities = layer_tree_host_impl_->GetRendererCapabilities();
1108    scheduler_on_impl_thread_->SetSwapBuffersCompleteSupported(
1109        capabilities->using_swap_complete_callback);
1110
1111    int max_frames_pending = layer_tree_host_impl_->output_surface()->
1112        capabilities().max_frames_pending;
1113    if (max_frames_pending <= 0)
1114      max_frames_pending = FrameRateController::DEFAULT_MAX_FRAMES_PENDING;
1115    if (layer_tree_host_impl_->output_surface()->capabilities().
1116            has_parent_compositor)
1117      max_frames_pending = 1;
1118    scheduler_on_impl_thread_->SetMaxFramesPending(max_frames_pending);
1119  }
1120
1121  completion->Signal();
1122}
1123
1124void ThreadProxy::LayerTreeHostClosedOnImplThread(CompletionEvent* completion) {
1125  TRACE_EVENT0("cc", "ThreadProxy::LayerTreeHostClosedOnImplThread");
1126  DCHECK(IsImplThread());
1127  layer_tree_host_->DeleteContentsTexturesOnImplThread(
1128      layer_tree_host_impl_->resource_provider());
1129  input_handler_on_impl_thread_.reset();
1130  layer_tree_host_impl_.reset();
1131  scheduler_on_impl_thread_.reset();
1132  weak_factory_on_impl_thread_.InvalidateWeakPtrs();
1133  completion->Signal();
1134}
1135
1136void ThreadProxy::SetFullRootLayerDamageOnImplThread() {
1137  DCHECK(IsImplThread());
1138  layer_tree_host_impl_->SetFullRootLayerDamage();
1139}
1140
1141size_t ThreadProxy::MaxPartialTextureUpdates() const {
1142  return ResourceUpdateController::MaxPartialTextureUpdates();
1143}
1144
1145void ThreadProxy::RecreateOutputSurfaceOnImplThread(
1146    CompletionEvent* completion,
1147    scoped_ptr<OutputSurface> output_surface,
1148    scoped_refptr<cc::ContextProvider> offscreen_context_provider,
1149    bool* recreate_succeeded,
1150    RendererCapabilities* capabilities) {
1151  TRACE_EVENT0("cc", "ThreadProxy::RecreateOutputSurfaceOnImplThread");
1152  DCHECK(IsImplThread());
1153
1154  layer_tree_host_->DeleteContentsTexturesOnImplThread(
1155      layer_tree_host_impl_->resource_provider());
1156  *recreate_succeeded =
1157      layer_tree_host_impl_->InitializeRenderer(output_surface.Pass());
1158  if (offscreen_context_provider)
1159      offscreen_context_provider->BindToCurrentThread();
1160
1161  if (*recreate_succeeded) {
1162    *capabilities = layer_tree_host_impl_->GetRendererCapabilities();
1163    layer_tree_host_impl_->resource_provider()->
1164        set_offscreen_context_provider(offscreen_context_provider);
1165    scheduler_on_impl_thread_->DidRecreateOutputSurface();
1166  } else if (offscreen_context_provider) {
1167    offscreen_context_provider->VerifyContexts();
1168  }
1169  completion->Signal();
1170}
1171
1172ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
1173    : memory_allocation_limit_bytes(0) {}
1174
1175ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() {}
1176
1177scoped_ptr<base::Value> ThreadProxy::AsValue() const {
1178  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1179
1180  CompletionEvent completion;
1181  {
1182    DebugScopedSetMainThreadBlocked main_thread_blocked(
1183        const_cast<ThreadProxy*>(this));
1184    Proxy::ImplThread()->PostTask(base::Bind(&ThreadProxy::AsValueOnImplThread,
1185                                             impl_thread_weak_ptr_,
1186                                             &completion,
1187                                             state.get()));
1188    completion.Wait();
1189  }
1190  return state.PassAs<base::Value>();
1191}
1192
1193void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
1194                                      base::DictionaryValue* state) const {
1195  state->Set("layer_tree_host_impl",
1196             layer_tree_host_impl_->AsValue().release());
1197  completion->Signal();
1198}
1199
1200bool ThreadProxy::CommitPendingForTesting() {
1201  DCHECK(IsMainThread());
1202  CommitPendingRequest commit_pending_request;
1203  {
1204    DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1205    Proxy::ImplThread()->PostTask(
1206        base::Bind(&ThreadProxy::CommitPendingOnImplThreadForTesting,
1207                   impl_thread_weak_ptr_,
1208                   &commit_pending_request));
1209    commit_pending_request.completion.Wait();
1210  }
1211  return commit_pending_request.commit_pending;
1212}
1213
1214void ThreadProxy::CommitPendingOnImplThreadForTesting(
1215    CommitPendingRequest* request) {
1216  DCHECK(IsImplThread());
1217  if (layer_tree_host_impl_->output_surface())
1218    request->commit_pending = scheduler_on_impl_thread_->CommitPending();
1219  else
1220    request->commit_pending = false;
1221  request->completion.Signal();
1222}
1223
1224skia::RefPtr<SkPicture> ThreadProxy::CapturePicture() {
1225  DCHECK(IsMainThread());
1226  CompletionEvent completion;
1227  skia::RefPtr<SkPicture> picture;
1228  {
1229    DebugScopedSetMainThreadBlocked main_thread_blocked(this);
1230    Proxy::ImplThread()->PostTask(
1231        base::Bind(&ThreadProxy::CapturePictureOnImplThread,
1232                   impl_thread_weak_ptr_,
1233                   &completion,
1234                   &picture));
1235    completion.Wait();
1236  }
1237  return picture;
1238}
1239
1240void ThreadProxy::CapturePictureOnImplThread(CompletionEvent* completion,
1241                                             skia::RefPtr<SkPicture>* picture) {
1242  DCHECK(IsImplThread());
1243  *picture = layer_tree_host_impl_->CapturePicture();
1244  completion->Signal();
1245}
1246
1247void ThreadProxy::RenewTreePriority() {
1248  bool smoothness_takes_priority =
1249      layer_tree_host_impl_->pinch_gesture_active() ||
1250      layer_tree_host_impl_->CurrentlyScrollingLayer() ||
1251      layer_tree_host_impl_->page_scale_animation_active();
1252
1253  // Update expiration time if smoothness currently takes priority.
1254  if (smoothness_takes_priority) {
1255    smoothness_takes_priority_expiration_time_ =
1256        base::TimeTicks::Now() +
1257        base::TimeDelta::FromMilliseconds(
1258            kSmoothnessTakesPriorityExpirationDelay * 1000);
1259  }
1260
1261  // We use the same priority for both trees by default.
1262  TreePriority priority = SAME_PRIORITY_FOR_BOTH_TREES;
1263
1264  // Smoothness takes priority if expiration time is in the future.
1265  if (smoothness_takes_priority_expiration_time_ > base::TimeTicks::Now())
1266    priority = SMOOTHNESS_TAKES_PRIORITY;
1267
1268  // New content always takes priority when the active tree has
1269  // evicted resources or there is an invalid viewport size.
1270  if (layer_tree_host_impl_->active_tree()->ContentsTexturesPurged() ||
1271      layer_tree_host_impl_->active_tree()->ViewportSizeInvalid())
1272    priority = NEW_CONTENT_TAKES_PRIORITY;
1273
1274  layer_tree_host_impl_->SetTreePriority(priority);
1275
1276  // Notify the the client of this compositor via the output surface.
1277  // TODO(epenner): Route this to compositor-thread instead of output-surface
1278  // after GTFO refactor of compositor-thread (http://crbug/170828).
1279  if (layer_tree_host_impl_->output_surface()) {
1280    layer_tree_host_impl_->output_surface()->
1281        UpdateSmoothnessTakesPriority(priority == SMOOTHNESS_TAKES_PRIORITY);
1282  }
1283
1284  base::TimeDelta delay =
1285      smoothness_takes_priority_expiration_time_ - base::TimeTicks::Now();
1286
1287  // Need to make sure a delayed task is posted when we have smoothness
1288  // takes priority expiration time in the future.
1289  if (delay <= base::TimeDelta())
1290    return;
1291  if (renew_tree_priority_on_impl_thread_pending_)
1292    return;
1293
1294  Proxy::ImplThread()->PostDelayedTask(
1295      base::Bind(&ThreadProxy::RenewTreePriorityOnImplThread,
1296                 weak_factory_on_impl_thread_.GetWeakPtr()),
1297      delay);
1298
1299  renew_tree_priority_on_impl_thread_pending_ = true;
1300}
1301
1302void ThreadProxy::RenewTreePriorityOnImplThread() {
1303  DCHECK(renew_tree_priority_on_impl_thread_pending_);
1304  renew_tree_priority_on_impl_thread_pending_ = false;
1305
1306  RenewTreePriority();
1307}
1308
1309void ThreadProxy::RequestScrollbarAnimationOnImplThread(base::TimeDelta delay) {
1310  Proxy::ImplThread()->PostDelayedTask(
1311      base::Bind(&ThreadProxy::StartScrollbarAnimationOnImplThread,
1312                 impl_thread_weak_ptr_),
1313      delay);
1314}
1315
1316void ThreadProxy::StartScrollbarAnimationOnImplThread() {
1317  layer_tree_host_impl_->StartScrollbarAnimation(base::TimeTicks::Now());
1318}
1319
1320}  // namespace cc
1321