layer_tree_host.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/layer_tree_host.h"
6
7#include <algorithm>
8#include <stack>
9#include <string>
10
11#include "base/bind.h"
12#include "base/command_line.h"
13#include "base/debug/trace_event.h"
14#include "base/lazy_instance.h"
15#include "base/message_loop/message_loop.h"
16#include "base/metrics/histogram.h"
17#include "base/stl_util.h"
18#include "base/strings/string_number_conversions.h"
19#include "base/synchronization/lock.h"
20#include "cc/animation/animation_registrar.h"
21#include "cc/animation/layer_animation_controller.h"
22#include "cc/base/math_util.h"
23#include "cc/debug/devtools_instrumentation.h"
24#include "cc/debug/overdraw_metrics.h"
25#include "cc/debug/rendering_stats_instrumentation.h"
26#include "cc/input/top_controls_manager.h"
27#include "cc/layers/heads_up_display_layer.h"
28#include "cc/layers/heads_up_display_layer_impl.h"
29#include "cc/layers/layer.h"
30#include "cc/layers/layer_iterator.h"
31#include "cc/layers/painted_scrollbar_layer.h"
32#include "cc/layers/render_surface.h"
33#include "cc/resources/prioritized_resource_manager.h"
34#include "cc/resources/ui_resource_request.h"
35#include "cc/trees/layer_tree_host_client.h"
36#include "cc/trees/layer_tree_host_common.h"
37#include "cc/trees/layer_tree_host_impl.h"
38#include "cc/trees/layer_tree_impl.h"
39#include "cc/trees/occlusion_tracker.h"
40#include "cc/trees/single_thread_proxy.h"
41#include "cc/trees/thread_proxy.h"
42#include "cc/trees/tree_synchronizer.h"
43#include "ui/gfx/size_conversions.h"
44
45namespace {
46static base::LazyInstance<base::Lock>::Leaky
47    s_next_tree_id_lock = LAZY_INSTANCE_INITIALIZER;
48
49inline int GetNextTreeId() {
50  static int s_next_tree_id = 1;
51  base::AutoLock lock(s_next_tree_id_lock.Get());
52  return s_next_tree_id++;
53}
54}
55
56namespace cc {
57
58RendererCapabilities::RendererCapabilities()
59    : best_texture_format(RGBA_8888),
60      using_partial_swap(false),
61      using_set_visibility(false),
62      using_egl_image(false),
63      allow_partial_texture_updates(false),
64      using_offscreen_context3d(false),
65      max_texture_size(0),
66      avoid_pow2_textures(false),
67      using_map_image(false),
68      using_shared_memory_resources(false),
69      using_discard_framebuffer(false) {}
70
71RendererCapabilities::~RendererCapabilities() {}
72
73scoped_ptr<LayerTreeHost> LayerTreeHost::CreateThreaded(
74    LayerTreeHostClient* client,
75    SharedBitmapManager* manager,
76    const LayerTreeSettings& settings,
77    scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
78  DCHECK(impl_task_runner);
79  scoped_ptr<LayerTreeHost> layer_tree_host(
80      new LayerTreeHost(client, manager, settings));
81  if (!layer_tree_host->InitializeThreaded(impl_task_runner))
82    return scoped_ptr<LayerTreeHost>();
83  return layer_tree_host.Pass();
84}
85
86scoped_ptr<LayerTreeHost> LayerTreeHost::CreateSingleThreaded(
87    LayerTreeHostClient* client,
88    LayerTreeHostSingleThreadClient* single_thread_client,
89    SharedBitmapManager* manager,
90    const LayerTreeSettings& settings) {
91  scoped_ptr<LayerTreeHost> layer_tree_host(
92      new LayerTreeHost(client, manager, settings));
93  if (!layer_tree_host->InitializeSingleThreaded(single_thread_client))
94    return scoped_ptr<LayerTreeHost>();
95  return layer_tree_host.Pass();
96}
97
98
99LayerTreeHost::LayerTreeHost(
100    LayerTreeHostClient* client,
101    SharedBitmapManager* manager,
102    const LayerTreeSettings& settings)
103    : micro_benchmark_controller_(this),
104      next_ui_resource_id_(1),
105      animating_(false),
106      needs_full_tree_sync_(true),
107      needs_filter_context_(false),
108      client_(client),
109      source_frame_number_(0),
110      rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()),
111      output_surface_can_be_initialized_(true),
112      output_surface_lost_(true),
113      num_failed_recreate_attempts_(0),
114      settings_(settings),
115      debug_state_(settings.initial_debug_state),
116      overdraw_bottom_height_(0.f),
117      device_scale_factor_(1.f),
118      visible_(true),
119      page_scale_factor_(1.f),
120      min_page_scale_factor_(1.f),
121      max_page_scale_factor_(1.f),
122      trigger_idle_updates_(true),
123      background_color_(SK_ColorWHITE),
124      has_transparent_background_(false),
125      partial_texture_update_requests_(0),
126      in_paint_layer_contents_(false),
127      total_frames_used_for_lcd_text_metrics_(0),
128      tree_id_(GetNextTreeId()),
129      next_commit_forces_redraw_(false),
130      shared_bitmap_manager_(manager) {
131  if (settings_.accelerated_animation_enabled)
132    animation_registrar_ = AnimationRegistrar::Create();
133  rendering_stats_instrumentation_->set_record_rendering_stats(
134      debug_state_.RecordRenderingStats());
135}
136
137bool LayerTreeHost::InitializeThreaded(
138    scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
139  return InitializeProxy(ThreadProxy::Create(this, impl_task_runner));
140}
141
142bool LayerTreeHost::InitializeSingleThreaded(
143    LayerTreeHostSingleThreadClient* single_thread_client) {
144    return InitializeProxy(
145        SingleThreadProxy::Create(this, single_thread_client));
146}
147
148bool LayerTreeHost::InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing) {
149  return InitializeProxy(proxy_for_testing.Pass());
150}
151
152bool LayerTreeHost::InitializeProxy(scoped_ptr<Proxy> proxy) {
153  TRACE_EVENT0("cc", "LayerTreeHost::InitializeForReal");
154
155  scoped_ptr<OutputSurface> output_surface(CreateOutputSurface());
156  if (!output_surface)
157    return false;
158
159  proxy_ = proxy.Pass();
160  proxy_->Start(output_surface.Pass());
161  return true;
162}
163
164LayerTreeHost::~LayerTreeHost() {
165  TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost");
166
167  overhang_ui_resource_.reset();
168
169  if (root_layer_.get())
170    root_layer_->SetLayerTreeHost(NULL);
171
172  if (proxy_) {
173    DCHECK(proxy_->IsMainThread());
174    proxy_->Stop();
175  }
176
177  if (root_layer_.get()) {
178    // The layer tree must be destroyed before the layer tree host. We've
179    // made a contract with our animation controllers that the registrar
180    // will outlive them, and we must make good.
181    root_layer_ = NULL;
182  }
183}
184
185void LayerTreeHost::SetLayerTreeHostClientReady() {
186  proxy_->SetLayerTreeHostClientReady();
187}
188
189static void LayerTreeHostOnOutputSurfaceCreatedCallback(Layer* layer) {
190  layer->OnOutputSurfaceCreated();
191}
192
193LayerTreeHost::CreateResult
194LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(bool success) {
195  TRACE_EVENT1("cc",
196               "LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted",
197               "success",
198               success);
199
200  DCHECK(output_surface_lost_);
201  if (success) {
202    output_surface_lost_ = false;
203
204    if (!contents_texture_manager_ && !settings_.impl_side_painting) {
205      contents_texture_manager_ =
206          PrioritizedResourceManager::Create(proxy_.get());
207      surface_memory_placeholder_ =
208          contents_texture_manager_->CreateTexture(gfx::Size(), RGBA_8888);
209    }
210
211    if (root_layer()) {
212      LayerTreeHostCommon::CallFunctionForSubtree(
213          root_layer(),
214          base::Bind(&LayerTreeHostOnOutputSurfaceCreatedCallback));
215    }
216
217    client_->DidInitializeOutputSurface(true);
218    return CreateSucceeded;
219  }
220
221  // Failure path.
222
223  client_->DidFailToInitializeOutputSurface();
224
225  // Tolerate a certain number of recreation failures to work around races
226  // in the output-surface-lost machinery.
227  ++num_failed_recreate_attempts_;
228  if (num_failed_recreate_attempts_ >= 5) {
229    // We have tried too many times to recreate the output surface. Tell the
230    // host to fall back to software rendering.
231    output_surface_can_be_initialized_ = false;
232    client_->DidInitializeOutputSurface(false);
233    return CreateFailedAndGaveUp;
234  }
235
236  return CreateFailedButTryAgain;
237}
238
239void LayerTreeHost::DeleteContentsTexturesOnImplThread(
240    ResourceProvider* resource_provider) {
241  DCHECK(proxy_->IsImplThread());
242  if (contents_texture_manager_)
243    contents_texture_manager_->ClearAllMemory(resource_provider);
244}
245
246void LayerTreeHost::AcquireLayerTextures() {
247  DCHECK(proxy_->IsMainThread());
248  proxy_->AcquireLayerTextures();
249}
250
251void LayerTreeHost::DidBeginMainFrame() {
252  client_->DidBeginMainFrame();
253}
254
255void LayerTreeHost::UpdateClientAnimations(base::TimeTicks frame_begin_time) {
256  animating_ = true;
257  client_->Animate((frame_begin_time - base::TimeTicks()).InSecondsF());
258  animating_ = false;
259}
260
261void LayerTreeHost::DidStopFlinging() {
262  proxy_->MainThreadHasStoppedFlinging();
263}
264
265void LayerTreeHost::Layout() {
266  client_->Layout();
267}
268
269void LayerTreeHost::BeginCommitOnImplThread(LayerTreeHostImpl* host_impl) {
270  DCHECK(proxy_->IsImplThread());
271  TRACE_EVENT0("cc", "LayerTreeHost::CommitTo");
272}
273
274// This function commits the LayerTreeHost to an impl tree. When modifying
275// this function, keep in mind that the function *runs* on the impl thread! Any
276// code that is logically a main thread operation, e.g. deletion of a Layer,
277// should be delayed until the LayerTreeHost::CommitComplete, which will run
278// after the commit, but on the main thread.
279void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
280  DCHECK(proxy_->IsImplThread());
281
282  // If there are linked evicted backings, these backings' resources may be put
283  // into the impl tree, so we can't draw yet. Determine this before clearing
284  // all evicted backings.
285  bool new_impl_tree_has_no_evicted_resources = false;
286  if (contents_texture_manager_) {
287    new_impl_tree_has_no_evicted_resources =
288        !contents_texture_manager_->LinkedEvictedBackingsExist();
289
290    // If the memory limit has been increased since this now-finishing
291    // commit began, and the extra now-available memory would have been used,
292    // then request another commit.
293    if (contents_texture_manager_->MaxMemoryLimitBytes() <
294            host_impl->memory_allocation_limit_bytes() &&
295        contents_texture_manager_->MaxMemoryLimitBytes() <
296            contents_texture_manager_->MaxMemoryNeededBytes()) {
297      host_impl->SetNeedsCommit();
298    }
299
300    host_impl->set_max_memory_needed_bytes(
301        contents_texture_manager_->MaxMemoryNeededBytes());
302
303    contents_texture_manager_->UpdateBackingsState(
304        host_impl->resource_provider());
305  }
306
307  // In impl-side painting, synchronize to the pending tree so that it has
308  // time to raster before being displayed.  If no pending tree is needed,
309  // synchronization can happen directly to the active tree and
310  // unlinked contents resources can be reclaimed immediately.
311  LayerTreeImpl* sync_tree;
312  if (settings_.impl_side_painting) {
313    // Commits should not occur while there is already a pending tree.
314    DCHECK(!host_impl->pending_tree());
315    host_impl->CreatePendingTree();
316    sync_tree = host_impl->pending_tree();
317    if (next_commit_forces_redraw_)
318      sync_tree->ForceRedrawNextActivation();
319  } else {
320    if (next_commit_forces_redraw_)
321      host_impl->SetFullRootLayerDamage();
322    contents_texture_manager_->ReduceMemory(host_impl->resource_provider());
323    sync_tree = host_impl->active_tree();
324  }
325
326  next_commit_forces_redraw_ = false;
327
328  sync_tree->set_source_frame_number(source_frame_number());
329
330  if (needs_full_tree_sync_)
331    sync_tree->SetRootLayer(TreeSynchronizer::SynchronizeTrees(
332        root_layer(), sync_tree->DetachLayerTree(), sync_tree));
333  {
334    TRACE_EVENT0("cc", "LayerTreeHost::PushProperties");
335    TreeSynchronizer::PushProperties(root_layer(), sync_tree->root_layer());
336  }
337
338  sync_tree->set_needs_full_tree_sync(needs_full_tree_sync_);
339  needs_full_tree_sync_ = false;
340
341  if (hud_layer_.get()) {
342    LayerImpl* hud_impl = LayerTreeHostCommon::FindLayerInSubtree(
343        sync_tree->root_layer(), hud_layer_->id());
344    sync_tree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(hud_impl));
345  } else {
346    sync_tree->set_hud_layer(NULL);
347  }
348
349  sync_tree->set_background_color(background_color_);
350  sync_tree->set_has_transparent_background(has_transparent_background_);
351
352  sync_tree->FindRootScrollLayer();
353
354  // TODO(wjmaclean) For now, not all LTH clients will register viewports, so
355  // only set them when available..
356  if (page_scale_layer_) {
357    DCHECK(inner_viewport_scroll_layer_);
358    sync_tree->SetViewportLayersFromIds(
359        page_scale_layer_->id(),
360        inner_viewport_scroll_layer_->id(),
361        outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id()
362                                     : Layer::INVALID_ID);
363  } else {
364    sync_tree->ClearViewportLayers();
365  }
366
367  float page_scale_delta, sent_page_scale_delta;
368  if (settings_.impl_side_painting) {
369    // Update the delta from the active tree, which may have
370    // adjusted its delta prior to the pending tree being created.
371    // This code is equivalent to that in LayerTreeImpl::SetPageScaleDelta.
372    DCHECK_EQ(1.f, sync_tree->sent_page_scale_delta());
373    page_scale_delta = host_impl->active_tree()->page_scale_delta();
374    sent_page_scale_delta = host_impl->active_tree()->sent_page_scale_delta();
375  } else {
376    page_scale_delta = sync_tree->page_scale_delta();
377    sent_page_scale_delta = sync_tree->sent_page_scale_delta();
378    sync_tree->set_sent_page_scale_delta(1.f);
379  }
380
381  sync_tree->SetPageScaleFactorAndLimits(page_scale_factor_,
382                                         min_page_scale_factor_,
383                                         max_page_scale_factor_);
384  sync_tree->SetPageScaleDelta(page_scale_delta / sent_page_scale_delta);
385  sync_tree->SetLatencyInfo(latency_info_);
386  latency_info_.Clear();
387
388  sync_tree->PassSwapPromises(&swap_promise_list_);
389
390  host_impl->SetViewportSize(device_viewport_size_);
391  host_impl->SetOverdrawBottomHeight(overdraw_bottom_height_);
392  host_impl->SetDeviceScaleFactor(device_scale_factor_);
393  host_impl->SetDebugState(debug_state_);
394  if (pending_page_scale_animation_) {
395    host_impl->StartPageScaleAnimation(
396        pending_page_scale_animation_->target_offset,
397        pending_page_scale_animation_->use_anchor,
398        pending_page_scale_animation_->scale,
399        pending_page_scale_animation_->duration);
400    pending_page_scale_animation_.reset();
401  }
402
403  if (!ui_resource_request_queue_.empty()) {
404    sync_tree->set_ui_resource_request_queue(ui_resource_request_queue_);
405    ui_resource_request_queue_.clear();
406    // Process any ui resource requests in the queue.  For impl-side-painting,
407    // the queue is processed in LayerTreeHostImpl::ActivatePendingTree.
408    if (!settings_.impl_side_painting)
409      sync_tree->ProcessUIResourceRequestQueue();
410  }
411  if (overhang_ui_resource_) {
412    host_impl->SetOverhangUIResource(
413        overhang_ui_resource_->id(),
414        GetUIResourceSize(overhang_ui_resource_->id()));
415  }
416
417  DCHECK(!sync_tree->ViewportSizeInvalid());
418
419  if (new_impl_tree_has_no_evicted_resources) {
420    if (sync_tree->ContentsTexturesPurged())
421      sync_tree->ResetContentsTexturesPurged();
422  }
423
424  if (!settings_.impl_side_painting) {
425    // If we're not in impl-side painting, the tree is immediately
426    // considered active.
427    sync_tree->DidBecomeActive();
428  }
429
430  micro_benchmark_controller_.ScheduleImplBenchmarks(host_impl);
431
432  source_frame_number_++;
433}
434
435void LayerTreeHost::WillCommit() {
436  client_->WillCommit();
437}
438
439void LayerTreeHost::UpdateHudLayer() {
440  if (debug_state_.ShowHudInfo()) {
441    if (!hud_layer_.get())
442      hud_layer_ = HeadsUpDisplayLayer::Create();
443
444    if (root_layer_.get() && !hud_layer_->parent())
445      root_layer_->AddChild(hud_layer_);
446  } else if (hud_layer_.get()) {
447    hud_layer_->RemoveFromParent();
448    hud_layer_ = NULL;
449  }
450}
451
452void LayerTreeHost::CommitComplete() {
453  client_->DidCommit();
454}
455
456scoped_ptr<OutputSurface> LayerTreeHost::CreateOutputSurface() {
457  return client_->CreateOutputSurface(num_failed_recreate_attempts_ >= 4);
458}
459
460scoped_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl(
461    LayerTreeHostImplClient* client) {
462  DCHECK(proxy_->IsImplThread());
463  scoped_ptr<LayerTreeHostImpl> host_impl =
464      LayerTreeHostImpl::Create(settings_,
465                                client,
466                                proxy_.get(),
467                                rendering_stats_instrumentation_.get(),
468                                shared_bitmap_manager_);
469  shared_bitmap_manager_ = NULL;
470  if (settings_.calculate_top_controls_position &&
471      host_impl->top_controls_manager()) {
472    top_controls_manager_weak_ptr_ =
473        host_impl->top_controls_manager()->AsWeakPtr();
474  }
475  input_handler_weak_ptr_ = host_impl->AsWeakPtr();
476  return host_impl.Pass();
477}
478
479void LayerTreeHost::DidLoseOutputSurface() {
480  TRACE_EVENT0("cc", "LayerTreeHost::DidLoseOutputSurface");
481  DCHECK(proxy_->IsMainThread());
482
483  if (output_surface_lost_)
484    return;
485
486  num_failed_recreate_attempts_ = 0;
487  output_surface_lost_ = true;
488  SetNeedsCommit();
489}
490
491bool LayerTreeHost::CompositeAndReadback(void* pixels,
492                                         gfx::Rect rect_in_device_viewport) {
493  trigger_idle_updates_ = false;
494  bool ret = proxy_->CompositeAndReadback(pixels, rect_in_device_viewport);
495  trigger_idle_updates_ = true;
496  return ret;
497}
498
499void LayerTreeHost::FinishAllRendering() {
500  proxy_->FinishAllRendering();
501}
502
503void LayerTreeHost::SetDeferCommits(bool defer_commits) {
504  proxy_->SetDeferCommits(defer_commits);
505}
506
507void LayerTreeHost::DidDeferCommit() {}
508
509void LayerTreeHost::SetNeedsDisplayOnAllLayers() {
510  std::stack<Layer*> layer_stack;
511  layer_stack.push(root_layer());
512  while (!layer_stack.empty()) {
513    Layer* current_layer = layer_stack.top();
514    layer_stack.pop();
515    current_layer->SetNeedsDisplay();
516    for (unsigned int i = 0; i < current_layer->children().size(); i++) {
517      layer_stack.push(current_layer->child_at(i));
518    }
519  }
520}
521
522void LayerTreeHost::CollectRenderingStats(RenderingStats* stats) const {
523  CHECK(debug_state_.RecordRenderingStats());
524  *stats = rendering_stats_instrumentation_->GetRenderingStats();
525}
526
527const RendererCapabilities& LayerTreeHost::GetRendererCapabilities() const {
528  return proxy_->GetRendererCapabilities();
529}
530
531void LayerTreeHost::SetNeedsAnimate() {
532  proxy_->SetNeedsAnimate();
533}
534
535void LayerTreeHost::SetNeedsUpdateLayers() { proxy_->SetNeedsUpdateLayers(); }
536
537void LayerTreeHost::SetNeedsCommit() {
538  if (!prepaint_callback_.IsCancelled()) {
539    TRACE_EVENT_INSTANT0("cc",
540                         "LayerTreeHost::SetNeedsCommit::cancel prepaint",
541                         TRACE_EVENT_SCOPE_THREAD);
542    prepaint_callback_.Cancel();
543  }
544  proxy_->SetNeedsCommit();
545}
546
547void LayerTreeHost::SetNeedsFullTreeSync() {
548  needs_full_tree_sync_ = true;
549  SetNeedsCommit();
550}
551
552void LayerTreeHost::SetNeedsRedraw() {
553  SetNeedsRedrawRect(gfx::Rect(device_viewport_size_));
554}
555
556void LayerTreeHost::SetNeedsRedrawRect(gfx::Rect damage_rect) {
557  proxy_->SetNeedsRedraw(damage_rect);
558}
559
560bool LayerTreeHost::CommitRequested() const {
561  return proxy_->CommitRequested();
562}
563
564bool LayerTreeHost::BeginMainFrameRequested() const {
565  return proxy_->BeginMainFrameRequested();
566}
567
568
569void LayerTreeHost::SetNextCommitWaitsForActivation() {
570  proxy_->SetNextCommitWaitsForActivation();
571}
572
573void LayerTreeHost::SetNextCommitForcesRedraw() {
574  next_commit_forces_redraw_ = true;
575}
576
577void LayerTreeHost::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
578                                       base::Time wall_clock_time) {
579  DCHECK(proxy_->IsMainThread());
580  for (size_t event_index = 0; event_index < events->size(); ++event_index) {
581    int event_layer_id = (*events)[event_index].layer_id;
582
583    // Use the map of all controllers, not just active ones, since non-active
584    // controllers may still receive events for impl-only animations.
585    const AnimationRegistrar::AnimationControllerMap& animation_controllers =
586        animation_registrar_->all_animation_controllers();
587    AnimationRegistrar::AnimationControllerMap::const_iterator iter =
588        animation_controllers.find(event_layer_id);
589    if (iter != animation_controllers.end()) {
590      switch ((*events)[event_index].type) {
591        case AnimationEvent::Started:
592          (*iter).second->NotifyAnimationStarted((*events)[event_index],
593                                                 wall_clock_time.ToDoubleT());
594          break;
595
596        case AnimationEvent::Finished:
597          (*iter).second->NotifyAnimationFinished((*events)[event_index],
598                                                  wall_clock_time.ToDoubleT());
599          break;
600
601        case AnimationEvent::Aborted:
602          (*iter).second->NotifyAnimationAborted((*events)[event_index]);
603          break;
604
605        case AnimationEvent::PropertyUpdate:
606          (*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]);
607          break;
608      }
609    }
610  }
611}
612
613void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) {
614  if (root_layer_.get() == root_layer.get())
615    return;
616
617  if (root_layer_.get())
618    root_layer_->SetLayerTreeHost(NULL);
619  root_layer_ = root_layer;
620  if (root_layer_.get()) {
621    DCHECK(!root_layer_->parent());
622    root_layer_->SetLayerTreeHost(this);
623  }
624
625  if (hud_layer_.get())
626    hud_layer_->RemoveFromParent();
627
628  SetNeedsFullTreeSync();
629}
630
631void LayerTreeHost::SetDebugState(const LayerTreeDebugState& debug_state) {
632  LayerTreeDebugState new_debug_state =
633      LayerTreeDebugState::Unite(settings_.initial_debug_state, debug_state);
634
635  if (LayerTreeDebugState::Equal(debug_state_, new_debug_state))
636    return;
637
638  debug_state_ = new_debug_state;
639
640  rendering_stats_instrumentation_->set_record_rendering_stats(
641      debug_state_.RecordRenderingStats());
642
643  SetNeedsCommit();
644}
645
646void LayerTreeHost::SetViewportSize(gfx::Size device_viewport_size) {
647  if (device_viewport_size == device_viewport_size_)
648    return;
649
650  device_viewport_size_ = device_viewport_size;
651
652  SetNeedsCommit();
653}
654
655void LayerTreeHost::SetOverdrawBottomHeight(float overdraw_bottom_height) {
656  if (overdraw_bottom_height_ == overdraw_bottom_height)
657    return;
658
659  overdraw_bottom_height_ = overdraw_bottom_height;
660  SetNeedsCommit();
661}
662
663void LayerTreeHost::ApplyPageScaleDeltaFromImplSide(float page_scale_delta) {
664  DCHECK(CommitRequested());
665  page_scale_factor_ *= page_scale_delta;
666}
667
668void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor,
669                                                float min_page_scale_factor,
670                                                float max_page_scale_factor) {
671  if (page_scale_factor == page_scale_factor_ &&
672      min_page_scale_factor == min_page_scale_factor_ &&
673      max_page_scale_factor == max_page_scale_factor_)
674    return;
675
676  page_scale_factor_ = page_scale_factor;
677  min_page_scale_factor_ = min_page_scale_factor;
678  max_page_scale_factor_ = max_page_scale_factor;
679  SetNeedsCommit();
680}
681
682void LayerTreeHost::SetOverhangBitmap(const SkBitmap& bitmap) {
683  DCHECK(bitmap.width() && bitmap.height());
684  DCHECK_EQ(bitmap.bytesPerPixel(), 4);
685
686  SkBitmap bitmap_copy;
687  if (bitmap.isImmutable()) {
688    bitmap_copy = bitmap;
689  } else {
690    bitmap.copyTo(&bitmap_copy, bitmap.config());
691    bitmap_copy.setImmutable();
692  }
693
694  UIResourceBitmap overhang_bitmap(bitmap_copy);
695  overhang_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
696  overhang_ui_resource_ = ScopedUIResource::Create(this, overhang_bitmap);
697}
698
699void LayerTreeHost::SetVisible(bool visible) {
700  if (visible_ == visible)
701    return;
702  visible_ = visible;
703  if (!visible)
704    ReduceMemoryUsage();
705  proxy_->SetVisible(visible);
706}
707
708void LayerTreeHost::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
709  latency_info_.MergeWith(latency_info);
710}
711
712void LayerTreeHost::StartPageScaleAnimation(gfx::Vector2d target_offset,
713                                            bool use_anchor,
714                                            float scale,
715                                            base::TimeDelta duration) {
716  pending_page_scale_animation_.reset(new PendingPageScaleAnimation);
717  pending_page_scale_animation_->target_offset = target_offset;
718  pending_page_scale_animation_->use_anchor = use_anchor;
719  pending_page_scale_animation_->scale = scale;
720  pending_page_scale_animation_->duration = duration;
721
722  SetNeedsCommit();
723}
724
725void LayerTreeHost::NotifyInputThrottledUntilCommit() {
726  proxy_->NotifyInputThrottledUntilCommit();
727}
728
729void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) {
730  if (!proxy_->HasImplThread())
731    static_cast<SingleThreadProxy*>(proxy_.get())->CompositeImmediately(
732        frame_begin_time);
733  else
734    SetNeedsCommit();
735}
736
737bool LayerTreeHost::InitializeOutputSurfaceIfNeeded() {
738  if (!output_surface_can_be_initialized_)
739    return false;
740
741  if (output_surface_lost_)
742    proxy_->CreateAndInitializeOutputSurface();
743  return !output_surface_lost_;
744}
745
746bool LayerTreeHost::UpdateLayers(ResourceUpdateQueue* queue) {
747  DCHECK(!output_surface_lost_);
748
749  if (!root_layer())
750    return false;
751
752  DCHECK(!root_layer()->parent());
753
754  bool result = UpdateLayers(root_layer(), queue);
755
756  micro_benchmark_controller_.DidUpdateLayers();
757
758  return result;
759}
760
761static Layer* FindFirstScrollableLayer(Layer* layer) {
762  if (!layer)
763    return NULL;
764
765  if (layer->scrollable())
766    return layer;
767
768  for (size_t i = 0; i < layer->children().size(); ++i) {
769    Layer* found = FindFirstScrollableLayer(layer->children()[i].get());
770    if (found)
771      return found;
772  }
773
774  return NULL;
775}
776
777void LayerTreeHost::CalculateLCDTextMetricsCallback(Layer* layer) {
778  if (!layer->SupportsLCDText())
779    return;
780
781  lcd_text_metrics_.total_num_cc_layers++;
782  if (layer->draw_properties().can_use_lcd_text) {
783    lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text++;
784    if (layer->contents_opaque())
785      lcd_text_metrics_.total_num_cc_layers_will_use_lcd_text++;
786  }
787}
788
789bool LayerTreeHost::UsingSharedMemoryResources() {
790  return GetRendererCapabilities().using_shared_memory_resources;
791}
792
793bool LayerTreeHost::UpdateLayers(Layer* root_layer,
794                                 ResourceUpdateQueue* queue) {
795  TRACE_EVENT1("cc", "LayerTreeHost::UpdateLayers",
796               "source_frame_number", source_frame_number());
797
798  RenderSurfaceLayerList update_list;
799  {
800    UpdateHudLayer();
801
802    Layer* root_scroll = FindFirstScrollableLayer(root_layer);
803    Layer* page_scale_layer = page_scale_layer_;
804    if (!page_scale_layer && root_scroll)
805      page_scale_layer = root_scroll->parent();
806
807    if (hud_layer_) {
808      hud_layer_->PrepareForCalculateDrawProperties(
809          device_viewport_size(), device_scale_factor_);
810    }
811
812    TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps");
813    bool can_render_to_separate_surface = true;
814    LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(
815        root_layer,
816        device_viewport_size(),
817        gfx::Transform(),
818        device_scale_factor_,
819        page_scale_factor_,
820        page_scale_layer,
821        GetRendererCapabilities().max_texture_size,
822        settings_.can_use_lcd_text,
823        can_render_to_separate_surface,
824        settings_.layer_transforms_should_scale_layer_contents,
825        &update_list);
826    LayerTreeHostCommon::CalculateDrawProperties(&inputs);
827
828    if (total_frames_used_for_lcd_text_metrics_ <=
829        kTotalFramesToUseForLCDTextMetrics) {
830      LayerTreeHostCommon::CallFunctionForSubtree(
831          root_layer,
832          base::Bind(&LayerTreeHost::CalculateLCDTextMetricsCallback,
833                     base::Unretained(this)));
834      total_frames_used_for_lcd_text_metrics_++;
835    }
836
837    if (total_frames_used_for_lcd_text_metrics_ ==
838        kTotalFramesToUseForLCDTextMetrics) {
839      total_frames_used_for_lcd_text_metrics_++;
840
841      UMA_HISTOGRAM_PERCENTAGE(
842          "Renderer4.LCDText.PercentageOfCandidateLayers",
843          lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text * 100.0 /
844          lcd_text_metrics_.total_num_cc_layers);
845      UMA_HISTOGRAM_PERCENTAGE(
846          "Renderer4.LCDText.PercentageOfAALayers",
847          lcd_text_metrics_.total_num_cc_layers_will_use_lcd_text * 100.0 /
848          lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text);
849    }
850  }
851
852  // Reset partial texture update requests.
853  partial_texture_update_requests_ = 0;
854
855  bool did_paint_content = false;
856  bool need_more_updates = false;
857  PaintLayerContents(
858      update_list, queue, &did_paint_content, &need_more_updates);
859  if (trigger_idle_updates_ && need_more_updates) {
860    TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::posting prepaint task");
861    prepaint_callback_.Reset(base::Bind(&LayerTreeHost::TriggerPrepaint,
862                                        base::Unretained(this)));
863    static base::TimeDelta prepaint_delay =
864        base::TimeDelta::FromMilliseconds(100);
865    base::MessageLoop::current()->PostDelayedTask(
866        FROM_HERE, prepaint_callback_.callback(), prepaint_delay);
867  }
868
869  return did_paint_content;
870}
871
872void LayerTreeHost::TriggerPrepaint() {
873  prepaint_callback_.Cancel();
874  TRACE_EVENT0("cc", "LayerTreeHost::TriggerPrepaint");
875  SetNeedsCommit();
876}
877
878static void LayerTreeHostReduceMemoryCallback(Layer* layer) {
879  layer->ReduceMemoryUsage();
880}
881
882void LayerTreeHost::ReduceMemoryUsage() {
883  if (!root_layer())
884    return;
885
886  LayerTreeHostCommon::CallFunctionForSubtree(
887      root_layer(),
888      base::Bind(&LayerTreeHostReduceMemoryCallback));
889}
890
891void LayerTreeHost::SetPrioritiesForSurfaces(size_t surface_memory_bytes) {
892  DCHECK(surface_memory_placeholder_);
893
894  // Surfaces have a place holder for their memory since they are managed
895  // independantly but should still be tracked and reduce other memory usage.
896  surface_memory_placeholder_->SetTextureManager(
897      contents_texture_manager_.get());
898  surface_memory_placeholder_->set_request_priority(
899      PriorityCalculator::RenderSurfacePriority());
900  surface_memory_placeholder_->SetToSelfManagedMemoryPlaceholder(
901      surface_memory_bytes);
902}
903
904void LayerTreeHost::SetPrioritiesForLayers(
905    const RenderSurfaceLayerList& update_list) {
906  typedef LayerIterator<Layer,
907                        RenderSurfaceLayerList,
908                        RenderSurface,
909                        LayerIteratorActions::FrontToBack> LayerIteratorType;
910
911  PriorityCalculator calculator;
912  LayerIteratorType end = LayerIteratorType::End(&update_list);
913  for (LayerIteratorType it = LayerIteratorType::Begin(&update_list);
914       it != end;
915       ++it) {
916    if (it.represents_itself()) {
917      it->SetTexturePriorities(calculator);
918    } else if (it.represents_target_render_surface()) {
919      if (it->mask_layer())
920        it->mask_layer()->SetTexturePriorities(calculator);
921      if (it->replica_layer() && it->replica_layer()->mask_layer())
922        it->replica_layer()->mask_layer()->SetTexturePriorities(calculator);
923    }
924  }
925}
926
927void LayerTreeHost::PrioritizeTextures(
928    const RenderSurfaceLayerList& render_surface_layer_list,
929    OverdrawMetrics* metrics) {
930  if (!contents_texture_manager_)
931    return;
932
933  contents_texture_manager_->ClearPriorities();
934
935  size_t memory_for_render_surfaces_metric =
936      CalculateMemoryForRenderSurfaces(render_surface_layer_list);
937
938  SetPrioritiesForLayers(render_surface_layer_list);
939  SetPrioritiesForSurfaces(memory_for_render_surfaces_metric);
940
941  metrics->DidUseContentsTextureMemoryBytes(
942      contents_texture_manager_->MemoryAboveCutoffBytes());
943  metrics->DidUseRenderSurfaceTextureMemoryBytes(
944      memory_for_render_surfaces_metric);
945
946  contents_texture_manager_->PrioritizeTextures();
947}
948
949size_t LayerTreeHost::CalculateMemoryForRenderSurfaces(
950    const RenderSurfaceLayerList& update_list) {
951  size_t readback_bytes = 0;
952  size_t max_background_texture_bytes = 0;
953  size_t contents_texture_bytes = 0;
954
955  // Start iteration at 1 to skip the root surface as it does not have a texture
956  // cost.
957  for (size_t i = 1; i < update_list.size(); ++i) {
958    Layer* render_surface_layer = update_list.at(i);
959    RenderSurface* render_surface = render_surface_layer->render_surface();
960
961    size_t bytes =
962        Resource::MemorySizeBytes(render_surface->content_rect().size(),
963                                  RGBA_8888);
964    contents_texture_bytes += bytes;
965
966    if (render_surface_layer->background_filters().IsEmpty())
967      continue;
968
969    if (bytes > max_background_texture_bytes)
970      max_background_texture_bytes = bytes;
971    if (!readback_bytes) {
972      readback_bytes = Resource::MemorySizeBytes(device_viewport_size_,
973                                                 RGBA_8888);
974    }
975  }
976  return readback_bytes + max_background_texture_bytes + contents_texture_bytes;
977}
978
979void LayerTreeHost::PaintMasksForRenderSurface(Layer* render_surface_layer,
980                                               ResourceUpdateQueue* queue,
981                                               bool* did_paint_content,
982                                               bool* need_more_updates) {
983  // Note: Masks and replicas only exist for layers that own render surfaces. If
984  // we reach this point in code, we already know that at least something will
985  // be drawn into this render surface, so the mask and replica should be
986  // painted.
987
988  Layer* mask_layer = render_surface_layer->mask_layer();
989  if (mask_layer) {
990    devtools_instrumentation::ScopedLayerTreeTask
991        update_layer(devtools_instrumentation::kUpdateLayer,
992                     mask_layer->id(),
993                     id());
994    *did_paint_content |= mask_layer->Update(queue, NULL);
995    *need_more_updates |= mask_layer->NeedMoreUpdates();
996  }
997
998  Layer* replica_mask_layer =
999      render_surface_layer->replica_layer() ?
1000      render_surface_layer->replica_layer()->mask_layer() : NULL;
1001  if (replica_mask_layer) {
1002    devtools_instrumentation::ScopedLayerTreeTask
1003        update_layer(devtools_instrumentation::kUpdateLayer,
1004                     replica_mask_layer->id(),
1005                     id());
1006    *did_paint_content |= replica_mask_layer->Update(queue, NULL);
1007    *need_more_updates |= replica_mask_layer->NeedMoreUpdates();
1008  }
1009}
1010
1011void LayerTreeHost::PaintLayerContents(
1012    const RenderSurfaceLayerList& render_surface_layer_list,
1013    ResourceUpdateQueue* queue,
1014    bool* did_paint_content,
1015    bool* need_more_updates) {
1016  // Use FrontToBack to allow for testing occlusion and performing culling
1017  // during the tree walk.
1018  typedef LayerIterator<Layer,
1019                        RenderSurfaceLayerList,
1020                        RenderSurface,
1021                        LayerIteratorActions::FrontToBack> LayerIteratorType;
1022
1023  bool record_metrics_for_frame =
1024      settings_.show_overdraw_in_tracing &&
1025      base::debug::TraceLog::GetInstance() &&
1026      base::debug::TraceLog::GetInstance()->IsEnabled();
1027  OcclusionTracker occlusion_tracker(
1028      root_layer_->render_surface()->content_rect(), record_metrics_for_frame);
1029  occlusion_tracker.set_minimum_tracking_size(
1030      settings_.minimum_occlusion_tracking_size);
1031
1032  PrioritizeTextures(render_surface_layer_list,
1033                     occlusion_tracker.overdraw_metrics());
1034
1035  in_paint_layer_contents_ = true;
1036
1037  LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
1038  for (LayerIteratorType it =
1039           LayerIteratorType::Begin(&render_surface_layer_list);
1040       it != end;
1041       ++it) {
1042    occlusion_tracker.EnterLayer(it);
1043
1044    if (it.represents_target_render_surface()) {
1045      PaintMasksForRenderSurface(
1046          *it, queue, did_paint_content, need_more_updates);
1047    } else if (it.represents_itself() && it->DrawsContent()) {
1048      devtools_instrumentation::ScopedLayerTreeTask
1049          update_layer(devtools_instrumentation::kUpdateLayer, it->id(), id());
1050      DCHECK(!it->paint_properties().bounds.IsEmpty());
1051      *did_paint_content |= it->Update(queue, &occlusion_tracker);
1052      *need_more_updates |= it->NeedMoreUpdates();
1053    }
1054
1055    occlusion_tracker.LeaveLayer(it);
1056  }
1057
1058  in_paint_layer_contents_ = false;
1059
1060  occlusion_tracker.overdraw_metrics()->RecordMetrics(this);
1061}
1062
1063void LayerTreeHost::ApplyScrollAndScale(const ScrollAndScaleSet& info) {
1064  if (!root_layer_.get())
1065    return;
1066
1067  gfx::Vector2d root_scroll_delta;
1068  Layer* root_scroll_layer = FindFirstScrollableLayer(root_layer_.get());
1069
1070  for (size_t i = 0; i < info.scrolls.size(); ++i) {
1071    Layer* layer =
1072        LayerTreeHostCommon::FindLayerInSubtree(root_layer_.get(),
1073                                                info.scrolls[i].layer_id);
1074    if (!layer)
1075      continue;
1076    if (layer == root_scroll_layer) {
1077      root_scroll_delta += info.scrolls[i].scroll_delta;
1078    } else {
1079      layer->SetScrollOffsetFromImplSide(layer->scroll_offset() +
1080                                         info.scrolls[i].scroll_delta);
1081    }
1082  }
1083
1084  if (!root_scroll_delta.IsZero() || info.page_scale_delta != 1.f) {
1085    // SetScrollOffsetFromImplSide above could have destroyed the tree,
1086    // so re-get this layer before doing anything to it.
1087    root_scroll_layer = FindFirstScrollableLayer(root_layer_.get());
1088
1089    // Preemptively apply the scroll offset and scale delta here before sending
1090    // it to the client.  If the client comes back and sets it to the same
1091    // value, then the layer can early out without needing a full commit.
1092    if (root_scroll_layer) {
1093      root_scroll_layer->SetScrollOffsetFromImplSide(
1094          root_scroll_layer->scroll_offset() + root_scroll_delta);
1095    }
1096    ApplyPageScaleDeltaFromImplSide(info.page_scale_delta);
1097    client_->ApplyScrollAndScale(root_scroll_delta, info.page_scale_delta);
1098  }
1099}
1100
1101void LayerTreeHost::StartRateLimiter() {
1102  if (animating_)
1103    return;
1104
1105  if (!rate_limit_timer_.IsRunning()) {
1106    rate_limit_timer_.Start(FROM_HERE,
1107                            base::TimeDelta(),
1108                            this,
1109                            &LayerTreeHost::RateLimit);
1110  }
1111}
1112
1113void LayerTreeHost::StopRateLimiter() {
1114  rate_limit_timer_.Stop();
1115}
1116
1117void LayerTreeHost::RateLimit() {
1118  // Force a no-op command on the compositor context, so that any ratelimiting
1119  // commands will wait for the compositing context, and therefore for the
1120  // SwapBuffers.
1121  proxy_->ForceSerializeOnSwapBuffers();
1122  client_->RateLimitSharedMainThreadContext();
1123}
1124
1125bool LayerTreeHost::AlwaysUsePartialTextureUpdates() {
1126  if (!proxy_->GetRendererCapabilities().allow_partial_texture_updates)
1127    return false;
1128  return !proxy_->HasImplThread();
1129}
1130
1131size_t LayerTreeHost::MaxPartialTextureUpdates() const {
1132  size_t max_partial_texture_updates = 0;
1133  if (proxy_->GetRendererCapabilities().allow_partial_texture_updates &&
1134      !settings_.impl_side_painting) {
1135    max_partial_texture_updates =
1136        std::min(settings_.max_partial_texture_updates,
1137                 proxy_->MaxPartialTextureUpdates());
1138  }
1139  return max_partial_texture_updates;
1140}
1141
1142bool LayerTreeHost::RequestPartialTextureUpdate() {
1143  if (partial_texture_update_requests_ >= MaxPartialTextureUpdates())
1144    return false;
1145
1146  partial_texture_update_requests_++;
1147  return true;
1148}
1149
1150void LayerTreeHost::SetDeviceScaleFactor(float device_scale_factor) {
1151  if (device_scale_factor == device_scale_factor_)
1152    return;
1153  device_scale_factor_ = device_scale_factor;
1154
1155  SetNeedsCommit();
1156}
1157
1158void LayerTreeHost::UpdateTopControlsState(TopControlsState constraints,
1159                                           TopControlsState current,
1160                                           bool animate) {
1161  if (!settings_.calculate_top_controls_position)
1162    return;
1163
1164  // Top controls are only used in threaded mode.
1165  proxy_->ImplThreadTaskRunner()->PostTask(
1166      FROM_HERE,
1167      base::Bind(&TopControlsManager::UpdateTopControlsState,
1168                 top_controls_manager_weak_ptr_,
1169                 constraints,
1170                 current,
1171                 animate));
1172}
1173
1174scoped_ptr<base::Value> LayerTreeHost::AsValue() const {
1175  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1176  state->Set("proxy", proxy_->AsValue().release());
1177  return state.PassAs<base::Value>();
1178}
1179
1180void LayerTreeHost::AnimateLayers(base::TimeTicks time) {
1181  if (!settings_.accelerated_animation_enabled ||
1182      animation_registrar_->active_animation_controllers().empty())
1183    return;
1184
1185  TRACE_EVENT0("cc", "LayerTreeHost::AnimateLayers");
1186
1187  double monotonic_time = (time - base::TimeTicks()).InSecondsF();
1188
1189  AnimationRegistrar::AnimationControllerMap copy =
1190      animation_registrar_->active_animation_controllers();
1191  for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
1192       iter != copy.end();
1193       ++iter) {
1194    (*iter).second->Animate(monotonic_time);
1195    bool start_ready_animations = true;
1196    (*iter).second->UpdateState(start_ready_animations, NULL);
1197  }
1198}
1199
1200UIResourceId LayerTreeHost::CreateUIResource(UIResourceClient* client) {
1201  DCHECK(client);
1202
1203  UIResourceId next_id = next_ui_resource_id_++;
1204  DCHECK(ui_resource_client_map_.find(next_id) ==
1205         ui_resource_client_map_.end());
1206
1207  bool resource_lost = false;
1208  UIResourceRequest request(UIResourceRequest::UIResourceCreate,
1209                            next_id,
1210                            client->GetBitmap(next_id, resource_lost));
1211  ui_resource_request_queue_.push_back(request);
1212
1213  UIResourceClientData data;
1214  data.client = client;
1215  data.size = request.GetBitmap().GetSize();
1216
1217  ui_resource_client_map_[request.GetId()] = data;
1218  return request.GetId();
1219}
1220
1221// Deletes a UI resource.  May safely be called more than once.
1222void LayerTreeHost::DeleteUIResource(UIResourceId uid) {
1223  UIResourceClientMap::iterator iter = ui_resource_client_map_.find(uid);
1224  if (iter == ui_resource_client_map_.end())
1225    return;
1226
1227  UIResourceRequest request(UIResourceRequest::UIResourceDelete, uid);
1228  ui_resource_request_queue_.push_back(request);
1229  ui_resource_client_map_.erase(iter);
1230}
1231
1232void LayerTreeHost::RecreateUIResources() {
1233  for (UIResourceClientMap::iterator iter = ui_resource_client_map_.begin();
1234       iter != ui_resource_client_map_.end();
1235       ++iter) {
1236    UIResourceId uid = iter->first;
1237    const UIResourceClientData& data = iter->second;
1238    bool resource_lost = true;
1239    UIResourceRequest request(UIResourceRequest::UIResourceCreate,
1240                              uid,
1241                              data.client->GetBitmap(uid, resource_lost));
1242    ui_resource_request_queue_.push_back(request);
1243  }
1244}
1245
1246// Returns the size of a resource given its id.
1247gfx::Size LayerTreeHost::GetUIResourceSize(UIResourceId uid) const {
1248  UIResourceClientMap::const_iterator iter = ui_resource_client_map_.find(uid);
1249  if (iter == ui_resource_client_map_.end())
1250    return gfx::Size();
1251
1252  const UIResourceClientData& data = iter->second;
1253  return data.size;
1254}
1255
1256void LayerTreeHost::RegisterViewportLayers(
1257    scoped_refptr<Layer> page_scale_layer,
1258    scoped_refptr<Layer> inner_viewport_scroll_layer,
1259    scoped_refptr<Layer> outer_viewport_scroll_layer) {
1260  page_scale_layer_ = page_scale_layer;
1261  inner_viewport_scroll_layer_ = inner_viewport_scroll_layer;
1262  outer_viewport_scroll_layer_ = outer_viewport_scroll_layer;
1263}
1264
1265bool LayerTreeHost::ScheduleMicroBenchmark(
1266    const std::string& benchmark_name,
1267    scoped_ptr<base::Value> value,
1268    const MicroBenchmark::DoneCallback& callback) {
1269  return micro_benchmark_controller_.ScheduleRun(
1270      benchmark_name, value.Pass(), callback);
1271}
1272
1273void LayerTreeHost::QueueSwapPromise(scoped_ptr<SwapPromise> swap_promise) {
1274  if (proxy_->HasImplThread()) {
1275    DCHECK(proxy_->CommitRequested() || proxy_->BeginMainFrameRequested());
1276  }
1277  DCHECK(swap_promise);
1278  if (swap_promise_list_.size() > kMaxQueuedSwapPromiseNumber)
1279    BreakSwapPromises(SwapPromise::SWAP_PROMISE_LIST_OVERFLOW);
1280  swap_promise_list_.push_back(swap_promise.Pass());
1281}
1282
1283void LayerTreeHost::BreakSwapPromises(SwapPromise::DidNotSwapReason reason) {
1284  for (size_t i = 0; i < swap_promise_list_.size(); i++)
1285    swap_promise_list_[i]->DidNotSwap(reason);
1286  swap_promise_list_.clear();
1287}
1288
1289}  // namespace cc
1290