1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/debug/trace_event.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/metrics/histogram.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "cc/animation/animation_registrar.h"
19 #include "cc/animation/layer_animation_controller.h"
20 #include "cc/base/math_util.h"
21 #include "cc/debug/devtools_instrumentation.h"
22 #include "cc/debug/overdraw_metrics.h"
23 #include "cc/debug/rendering_stats_instrumentation.h"
24 #include "cc/input/top_controls_manager.h"
25 #include "cc/layers/heads_up_display_layer.h"
26 #include "cc/layers/heads_up_display_layer_impl.h"
27 #include "cc/layers/layer.h"
28 #include "cc/layers/layer_iterator.h"
29 #include "cc/layers/painted_scrollbar_layer.h"
30 #include "cc/layers/render_surface.h"
31 #include "cc/resources/prioritized_resource_manager.h"
32 #include "cc/resources/ui_resource_client.h"
33 #include "cc/trees/layer_tree_host_client.h"
34 #include "cc/trees/layer_tree_host_common.h"
35 #include "cc/trees/layer_tree_host_impl.h"
36 #include "cc/trees/layer_tree_impl.h"
37 #include "cc/trees/occlusion_tracker.h"
38 #include "cc/trees/single_thread_proxy.h"
39 #include "cc/trees/thread_proxy.h"
40 #include "cc/trees/tree_synchronizer.h"
41 #include "ui/gfx/size_conversions.h"
44 static int s_num_layer_tree_instances;
49 RendererCapabilities::RendererCapabilities()
50 : best_texture_format(RGBA_8888),
51 using_partial_swap(false),
52 using_set_visibility(false),
53 using_egl_image(false),
54 allow_partial_texture_updates(false),
55 using_offscreen_context3d(false),
57 avoid_pow2_textures(false),
58 using_map_image(false),
59 using_shared_memory_resources(false),
60 using_discard_framebuffer(false) {}
62 RendererCapabilities::~RendererCapabilities() {}
64 UIResourceRequest::UIResourceRequest(UIResourceRequestType type,
66 : type_(type), id_(id) {}
68 UIResourceRequest::UIResourceRequest(UIResourceRequestType type,
70 const UIResourceBitmap& bitmap)
71 : type_(type), id_(id), bitmap_(new UIResourceBitmap(bitmap)) {}
73 UIResourceRequest::UIResourceRequest(const UIResourceRequest& request) {
77 UIResourceRequest& UIResourceRequest::operator=(
78 const UIResourceRequest& request) {
79 type_ = request.type_;
81 if (request.bitmap_) {
82 bitmap_ = make_scoped_ptr(new UIResourceBitmap(*request.bitmap_.get()));
90 UIResourceRequest::~UIResourceRequest() {}
92 bool LayerTreeHost::AnyLayerTreeHostInstanceExists() {
93 return s_num_layer_tree_instances > 0;
96 scoped_ptr<LayerTreeHost> LayerTreeHost::Create(
97 LayerTreeHostClient* client,
98 SharedBitmapManager* manager,
99 const LayerTreeSettings& settings,
100 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
101 scoped_ptr<LayerTreeHost> layer_tree_host(
102 new LayerTreeHost(client, manager, settings));
103 if (!layer_tree_host->Initialize(impl_task_runner))
104 return scoped_ptr<LayerTreeHost>();
105 return layer_tree_host.Pass();
108 static int s_next_tree_id = 1;
110 LayerTreeHost::LayerTreeHost(LayerTreeHostClient* client,
111 SharedBitmapManager* manager,
112 const LayerTreeSettings& settings)
113 : next_ui_resource_id_(1),
115 needs_full_tree_sync_(true),
116 needs_filter_context_(false),
118 source_frame_number_(0),
119 rendering_stats_instrumentation_(RenderingStatsInstrumentation::Create()),
120 micro_benchmark_controller_(this),
121 output_surface_can_be_initialized_(true),
122 output_surface_lost_(true),
123 num_failed_recreate_attempts_(0),
125 debug_state_(settings.initial_debug_state),
126 overdraw_bottom_height_(0.f),
127 device_scale_factor_(1.f),
129 page_scale_factor_(1.f),
130 min_page_scale_factor_(1.f),
131 max_page_scale_factor_(1.f),
132 trigger_idle_updates_(true),
133 background_color_(SK_ColorWHITE),
134 has_transparent_background_(false),
135 partial_texture_update_requests_(0),
136 in_paint_layer_contents_(false),
137 total_frames_used_for_lcd_text_metrics_(0),
138 tree_id_(s_next_tree_id++),
139 next_commit_forces_redraw_(false),
140 shared_bitmap_manager_(manager) {
141 if (settings_.accelerated_animation_enabled)
142 animation_registrar_ = AnimationRegistrar::Create();
143 s_num_layer_tree_instances++;
144 rendering_stats_instrumentation_->set_record_rendering_stats(
145 debug_state_.RecordRenderingStats());
148 bool LayerTreeHost::Initialize(
149 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) {
150 if (impl_task_runner.get())
151 return InitializeProxy(ThreadProxy::Create(this, impl_task_runner));
153 return InitializeProxy(SingleThreadProxy::Create(this));
156 bool LayerTreeHost::InitializeForTesting(scoped_ptr<Proxy> proxy_for_testing) {
157 return InitializeProxy(proxy_for_testing.Pass());
160 bool LayerTreeHost::InitializeProxy(scoped_ptr<Proxy> proxy) {
161 TRACE_EVENT0("cc", "LayerTreeHost::InitializeForReal");
163 scoped_ptr<OutputSurface> output_surface(CreateOutputSurface());
167 proxy_ = proxy.Pass();
168 proxy_->Start(output_surface.Pass());
172 LayerTreeHost::~LayerTreeHost() {
173 TRACE_EVENT0("cc", "LayerTreeHost::~LayerTreeHost");
175 overhang_ui_resource_.reset();
177 if (root_layer_.get())
178 root_layer_->SetLayerTreeHost(NULL);
181 DCHECK(proxy_->IsMainThread());
185 s_num_layer_tree_instances--;
186 RateLimiterMap::iterator it = rate_limiters_.begin();
187 if (it != rate_limiters_.end())
190 if (root_layer_.get()) {
191 // The layer tree must be destroyed before the layer tree host. We've
192 // made a contract with our animation controllers that the registrar
193 // will outlive them, and we must make good.
198 void LayerTreeHost::SetLayerTreeHostClientReady() {
199 proxy_->SetLayerTreeHostClientReady();
202 static void LayerTreeHostOnOutputSurfaceCreatedCallback(Layer* layer) {
203 layer->OnOutputSurfaceCreated();
206 LayerTreeHost::CreateResult
207 LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(bool success) {
209 "LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted",
213 DCHECK(output_surface_lost_);
215 output_surface_lost_ = false;
217 if (!contents_texture_manager_ && !settings_.impl_side_painting) {
218 contents_texture_manager_ =
219 PrioritizedResourceManager::Create(proxy_.get());
220 surface_memory_placeholder_ =
221 contents_texture_manager_->CreateTexture(gfx::Size(), RGBA_8888);
225 LayerTreeHostCommon::CallFunctionForSubtree(
227 base::Bind(&LayerTreeHostOnOutputSurfaceCreatedCallback));
230 client_->DidInitializeOutputSurface(true);
231 return CreateSucceeded;
236 client_->DidFailToInitializeOutputSurface();
238 // Tolerate a certain number of recreation failures to work around races
239 // in the output-surface-lost machinery.
240 ++num_failed_recreate_attempts_;
241 if (num_failed_recreate_attempts_ >= 5) {
242 // We have tried too many times to recreate the output surface. Tell the
243 // host to fall back to software rendering.
244 output_surface_can_be_initialized_ = false;
245 client_->DidInitializeOutputSurface(false);
246 return CreateFailedAndGaveUp;
249 return CreateFailedButTryAgain;
252 void LayerTreeHost::DeleteContentsTexturesOnImplThread(
253 ResourceProvider* resource_provider) {
254 DCHECK(proxy_->IsImplThread());
255 if (contents_texture_manager_)
256 contents_texture_manager_->ClearAllMemory(resource_provider);
259 void LayerTreeHost::AcquireLayerTextures() {
260 DCHECK(proxy_->IsMainThread());
261 proxy_->AcquireLayerTextures();
264 void LayerTreeHost::DidBeginMainFrame() {
265 client_->DidBeginMainFrame();
268 void LayerTreeHost::UpdateClientAnimations(base::TimeTicks frame_begin_time) {
270 client_->Animate((frame_begin_time - base::TimeTicks()).InSecondsF());
274 void LayerTreeHost::DidStopFlinging() {
275 proxy_->MainThreadHasStoppedFlinging();
278 void LayerTreeHost::Layout() {
282 void LayerTreeHost::BeginCommitOnImplThread(LayerTreeHostImpl* host_impl) {
283 DCHECK(proxy_->IsImplThread());
284 TRACE_EVENT0("cc", "LayerTreeHost::CommitTo");
287 // This function commits the LayerTreeHost to an impl tree. When modifying
288 // this function, keep in mind that the function *runs* on the impl thread! Any
289 // code that is logically a main thread operation, e.g. deletion of a Layer,
290 // should be delayed until the LayerTreeHost::CommitComplete, which will run
291 // after the commit, but on the main thread.
292 void LayerTreeHost::FinishCommitOnImplThread(LayerTreeHostImpl* host_impl) {
293 DCHECK(proxy_->IsImplThread());
295 // If there are linked evicted backings, these backings' resources may be put
296 // into the impl tree, so we can't draw yet. Determine this before clearing
297 // all evicted backings.
298 bool new_impl_tree_has_no_evicted_resources = false;
299 if (contents_texture_manager_) {
300 new_impl_tree_has_no_evicted_resources =
301 !contents_texture_manager_->LinkedEvictedBackingsExist();
303 // If the memory limit has been increased since this now-finishing
304 // commit began, and the extra now-available memory would have been used,
305 // then request another commit.
306 if (contents_texture_manager_->MaxMemoryLimitBytes() <
307 host_impl->memory_allocation_limit_bytes() &&
308 contents_texture_manager_->MaxMemoryLimitBytes() <
309 contents_texture_manager_->MaxMemoryNeededBytes()) {
310 host_impl->SetNeedsCommit();
313 host_impl->set_max_memory_needed_bytes(
314 contents_texture_manager_->MaxMemoryNeededBytes());
316 contents_texture_manager_->UpdateBackingsState(
317 host_impl->resource_provider());
320 // In impl-side painting, synchronize to the pending tree so that it has
321 // time to raster before being displayed. If no pending tree is needed,
322 // synchronization can happen directly to the active tree and
323 // unlinked contents resources can be reclaimed immediately.
324 LayerTreeImpl* sync_tree;
325 if (settings_.impl_side_painting) {
326 // Commits should not occur while there is already a pending tree.
327 DCHECK(!host_impl->pending_tree());
328 host_impl->CreatePendingTree();
329 sync_tree = host_impl->pending_tree();
330 if (next_commit_forces_redraw_)
331 sync_tree->ForceRedrawNextActivation();
333 if (next_commit_forces_redraw_)
334 host_impl->SetFullRootLayerDamage();
335 contents_texture_manager_->ReduceMemory(host_impl->resource_provider());
336 sync_tree = host_impl->active_tree();
339 next_commit_forces_redraw_ = false;
341 sync_tree->set_source_frame_number(source_frame_number());
343 if (needs_full_tree_sync_)
344 sync_tree->SetRootLayer(TreeSynchronizer::SynchronizeTrees(
345 root_layer(), sync_tree->DetachLayerTree(), sync_tree));
347 TRACE_EVENT0("cc", "LayerTreeHost::PushProperties");
348 TreeSynchronizer::PushProperties(root_layer(), sync_tree->root_layer());
351 sync_tree->set_needs_full_tree_sync(needs_full_tree_sync_);
352 needs_full_tree_sync_ = false;
354 if (hud_layer_.get()) {
355 LayerImpl* hud_impl = LayerTreeHostCommon::FindLayerInSubtree(
356 sync_tree->root_layer(), hud_layer_->id());
357 sync_tree->set_hud_layer(static_cast<HeadsUpDisplayLayerImpl*>(hud_impl));
359 sync_tree->set_hud_layer(NULL);
362 sync_tree->set_background_color(background_color_);
363 sync_tree->set_has_transparent_background(has_transparent_background_);
365 sync_tree->FindRootScrollLayer();
367 // TODO(wjmaclean) For now, not all LTH clients will register viewports, so
368 // only set them when available..
369 if (page_scale_layer_) {
370 DCHECK(inner_viewport_scroll_layer_);
371 sync_tree->SetViewportLayersFromIds(
372 page_scale_layer_->id(),
373 inner_viewport_scroll_layer_->id(),
374 outer_viewport_scroll_layer_ ? outer_viewport_scroll_layer_->id()
375 : Layer::INVALID_ID);
377 sync_tree->ClearViewportLayers();
380 float page_scale_delta, sent_page_scale_delta;
381 if (settings_.impl_side_painting) {
382 // Update the delta from the active tree, which may have
383 // adjusted its delta prior to the pending tree being created.
384 // This code is equivalent to that in LayerTreeImpl::SetPageScaleDelta.
385 DCHECK_EQ(1.f, sync_tree->sent_page_scale_delta());
386 page_scale_delta = host_impl->active_tree()->page_scale_delta();
387 sent_page_scale_delta = host_impl->active_tree()->sent_page_scale_delta();
389 page_scale_delta = sync_tree->page_scale_delta();
390 sent_page_scale_delta = sync_tree->sent_page_scale_delta();
391 sync_tree->set_sent_page_scale_delta(1.f);
394 sync_tree->SetPageScaleFactorAndLimits(page_scale_factor_,
395 min_page_scale_factor_,
396 max_page_scale_factor_);
397 sync_tree->SetPageScaleDelta(page_scale_delta / sent_page_scale_delta);
398 sync_tree->SetLatencyInfo(latency_info_);
399 latency_info_.Clear();
401 host_impl->SetViewportSize(device_viewport_size_);
402 host_impl->SetOverdrawBottomHeight(overdraw_bottom_height_);
403 host_impl->SetDeviceScaleFactor(device_scale_factor_);
404 host_impl->SetDebugState(debug_state_);
405 if (pending_page_scale_animation_) {
406 host_impl->StartPageScaleAnimation(
407 pending_page_scale_animation_->target_offset,
408 pending_page_scale_animation_->use_anchor,
409 pending_page_scale_animation_->scale,
410 pending_page_scale_animation_->duration);
411 pending_page_scale_animation_.reset();
414 if (!ui_resource_request_queue_.empty()) {
415 sync_tree->set_ui_resource_request_queue(ui_resource_request_queue_);
416 ui_resource_request_queue_.clear();
417 // Process any ui resource requests in the queue. For impl-side-painting,
418 // the queue is processed in LayerTreeHostImpl::ActivatePendingTree.
419 if (!settings_.impl_side_painting)
420 sync_tree->ProcessUIResourceRequestQueue();
422 if (overhang_ui_resource_) {
423 host_impl->SetOverhangUIResource(
424 overhang_ui_resource_->id(),
425 GetUIResourceSize(overhang_ui_resource_->id()));
428 DCHECK(!sync_tree->ViewportSizeInvalid());
430 if (new_impl_tree_has_no_evicted_resources) {
431 if (sync_tree->ContentsTexturesPurged())
432 sync_tree->ResetContentsTexturesPurged();
435 if (!settings_.impl_side_painting) {
436 // If we're not in impl-side painting, the tree is immediately
437 // considered active.
438 sync_tree->DidBecomeActive();
441 source_frame_number_++;
444 void LayerTreeHost::WillCommit() {
445 client_->WillCommit();
448 void LayerTreeHost::UpdateHudLayer() {
449 if (debug_state_.ShowHudInfo()) {
450 if (!hud_layer_.get())
451 hud_layer_ = HeadsUpDisplayLayer::Create();
453 if (root_layer_.get() && !hud_layer_->parent())
454 root_layer_->AddChild(hud_layer_);
455 } else if (hud_layer_.get()) {
456 hud_layer_->RemoveFromParent();
461 void LayerTreeHost::CommitComplete() {
462 client_->DidCommit();
465 scoped_ptr<OutputSurface> LayerTreeHost::CreateOutputSurface() {
466 return client_->CreateOutputSurface(num_failed_recreate_attempts_ >= 4);
469 scoped_ptr<LayerTreeHostImpl> LayerTreeHost::CreateLayerTreeHostImpl(
470 LayerTreeHostImplClient* client) {
471 DCHECK(proxy_->IsImplThread());
472 scoped_ptr<LayerTreeHostImpl> host_impl =
473 LayerTreeHostImpl::Create(settings_,
476 rendering_stats_instrumentation_.get(),
477 shared_bitmap_manager_);
478 shared_bitmap_manager_ = NULL;
479 if (settings_.calculate_top_controls_position &&
480 host_impl->top_controls_manager()) {
481 top_controls_manager_weak_ptr_ =
482 host_impl->top_controls_manager()->AsWeakPtr();
484 input_handler_weak_ptr_ = host_impl->AsWeakPtr();
485 return host_impl.Pass();
488 void LayerTreeHost::DidLoseOutputSurface() {
489 TRACE_EVENT0("cc", "LayerTreeHost::DidLoseOutputSurface");
490 DCHECK(proxy_->IsMainThread());
492 if (output_surface_lost_)
495 num_failed_recreate_attempts_ = 0;
496 output_surface_lost_ = true;
500 bool LayerTreeHost::CompositeAndReadback(void* pixels,
501 gfx::Rect rect_in_device_viewport) {
502 trigger_idle_updates_ = false;
503 bool ret = proxy_->CompositeAndReadback(pixels, rect_in_device_viewport);
504 trigger_idle_updates_ = true;
508 void LayerTreeHost::FinishAllRendering() {
509 proxy_->FinishAllRendering();
512 void LayerTreeHost::SetDeferCommits(bool defer_commits) {
513 proxy_->SetDeferCommits(defer_commits);
516 void LayerTreeHost::DidDeferCommit() {}
518 void LayerTreeHost::SetNeedsDisplayOnAllLayers() {
519 std::stack<Layer*> layer_stack;
520 layer_stack.push(root_layer());
521 while (!layer_stack.empty()) {
522 Layer* current_layer = layer_stack.top();
524 current_layer->SetNeedsDisplay();
525 for (unsigned int i = 0; i < current_layer->children().size(); i++) {
526 layer_stack.push(current_layer->child_at(i));
531 void LayerTreeHost::CollectRenderingStats(RenderingStats* stats) const {
532 CHECK(debug_state_.RecordRenderingStats());
533 *stats = rendering_stats_instrumentation_->GetRenderingStats();
536 const RendererCapabilities& LayerTreeHost::GetRendererCapabilities() const {
537 return proxy_->GetRendererCapabilities();
540 void LayerTreeHost::SetNeedsAnimate() {
541 DCHECK(proxy_->HasImplThread());
542 proxy_->SetNeedsAnimate();
545 void LayerTreeHost::SetNeedsUpdateLayers() { proxy_->SetNeedsUpdateLayers(); }
547 void LayerTreeHost::SetNeedsCommit() {
548 if (!prepaint_callback_.IsCancelled()) {
549 TRACE_EVENT_INSTANT0("cc",
550 "LayerTreeHost::SetNeedsCommit::cancel prepaint",
551 TRACE_EVENT_SCOPE_THREAD);
552 prepaint_callback_.Cancel();
554 proxy_->SetNeedsCommit();
557 void LayerTreeHost::SetNeedsFullTreeSync() {
558 needs_full_tree_sync_ = true;
562 void LayerTreeHost::SetNeedsRedraw() {
563 SetNeedsRedrawRect(gfx::Rect(device_viewport_size_));
566 void LayerTreeHost::SetNeedsRedrawRect(gfx::Rect damage_rect) {
567 proxy_->SetNeedsRedraw(damage_rect);
568 if (!proxy_->HasImplThread())
569 client_->ScheduleComposite();
572 bool LayerTreeHost::CommitRequested() const {
573 return proxy_->CommitRequested();
576 bool LayerTreeHost::BeginMainFrameRequested() const {
577 return proxy_->BeginMainFrameRequested();
581 void LayerTreeHost::SetNextCommitWaitsForActivation() {
582 proxy_->SetNextCommitWaitsForActivation();
585 void LayerTreeHost::SetNextCommitForcesRedraw() {
586 next_commit_forces_redraw_ = true;
589 void LayerTreeHost::SetAnimationEvents(scoped_ptr<AnimationEventsVector> events,
590 base::Time wall_clock_time) {
591 DCHECK(proxy_->IsMainThread());
592 for (size_t event_index = 0; event_index < events->size(); ++event_index) {
593 int event_layer_id = (*events)[event_index].layer_id;
595 // Use the map of all controllers, not just active ones, since non-active
596 // controllers may still receive events for impl-only animations.
597 const AnimationRegistrar::AnimationControllerMap& animation_controllers =
598 animation_registrar_->all_animation_controllers();
599 AnimationRegistrar::AnimationControllerMap::const_iterator iter =
600 animation_controllers.find(event_layer_id);
601 if (iter != animation_controllers.end()) {
602 switch ((*events)[event_index].type) {
603 case AnimationEvent::Started:
604 (*iter).second->NotifyAnimationStarted((*events)[event_index],
605 wall_clock_time.ToDoubleT());
608 case AnimationEvent::Finished:
609 (*iter).second->NotifyAnimationFinished((*events)[event_index],
610 wall_clock_time.ToDoubleT());
613 case AnimationEvent::PropertyUpdate:
614 (*iter).second->NotifyAnimationPropertyUpdate((*events)[event_index]);
621 void LayerTreeHost::SetRootLayer(scoped_refptr<Layer> root_layer) {
622 if (root_layer_.get() == root_layer.get())
625 if (root_layer_.get())
626 root_layer_->SetLayerTreeHost(NULL);
627 root_layer_ = root_layer;
628 if (root_layer_.get()) {
629 DCHECK(!root_layer_->parent());
630 root_layer_->SetLayerTreeHost(this);
633 if (hud_layer_.get())
634 hud_layer_->RemoveFromParent();
636 SetNeedsFullTreeSync();
639 void LayerTreeHost::SetDebugState(const LayerTreeDebugState& debug_state) {
640 LayerTreeDebugState new_debug_state =
641 LayerTreeDebugState::Unite(settings_.initial_debug_state, debug_state);
643 if (LayerTreeDebugState::Equal(debug_state_, new_debug_state))
646 debug_state_ = new_debug_state;
648 rendering_stats_instrumentation_->set_record_rendering_stats(
649 debug_state_.RecordRenderingStats());
654 void LayerTreeHost::SetViewportSize(gfx::Size device_viewport_size) {
655 if (device_viewport_size == device_viewport_size_)
658 device_viewport_size_ = device_viewport_size;
663 void LayerTreeHost::SetOverdrawBottomHeight(float overdraw_bottom_height) {
664 if (overdraw_bottom_height_ == overdraw_bottom_height)
667 overdraw_bottom_height_ = overdraw_bottom_height;
671 void LayerTreeHost::ApplyPageScaleDeltaFromImplSide(float page_scale_delta) {
672 DCHECK(CommitRequested());
673 page_scale_factor_ *= page_scale_delta;
676 void LayerTreeHost::SetPageScaleFactorAndLimits(float page_scale_factor,
677 float min_page_scale_factor,
678 float max_page_scale_factor) {
679 if (page_scale_factor == page_scale_factor_ &&
680 min_page_scale_factor == min_page_scale_factor_ &&
681 max_page_scale_factor == max_page_scale_factor_)
684 page_scale_factor_ = page_scale_factor;
685 min_page_scale_factor_ = min_page_scale_factor;
686 max_page_scale_factor_ = max_page_scale_factor;
690 void LayerTreeHost::SetOverhangBitmap(const SkBitmap& bitmap) {
691 DCHECK(bitmap.width() && bitmap.height());
692 DCHECK_EQ(bitmap.bytesPerPixel(), 4);
694 SkBitmap bitmap_copy;
695 if (bitmap.isImmutable()) {
696 bitmap_copy = bitmap;
698 bitmap.copyTo(&bitmap_copy, bitmap.config());
699 bitmap_copy.setImmutable();
702 UIResourceBitmap overhang_bitmap(bitmap_copy);
703 overhang_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
704 overhang_ui_resource_ = ScopedUIResource::Create(this, overhang_bitmap);
707 void LayerTreeHost::SetVisible(bool visible) {
708 if (visible_ == visible)
713 proxy_->SetVisible(visible);
716 void LayerTreeHost::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
717 latency_info_.MergeWith(latency_info);
720 void LayerTreeHost::StartPageScaleAnimation(gfx::Vector2d target_offset,
723 base::TimeDelta duration) {
724 pending_page_scale_animation_.reset(new PendingPageScaleAnimation);
725 pending_page_scale_animation_->target_offset = target_offset;
726 pending_page_scale_animation_->use_anchor = use_anchor;
727 pending_page_scale_animation_->scale = scale;
728 pending_page_scale_animation_->duration = duration;
733 void LayerTreeHost::NotifyInputThrottledUntilCommit() {
734 proxy_->NotifyInputThrottledUntilCommit();
737 void LayerTreeHost::Composite(base::TimeTicks frame_begin_time) {
738 if (!proxy_->HasImplThread())
739 static_cast<SingleThreadProxy*>(proxy_.get())->CompositeImmediately(
745 void LayerTreeHost::ScheduleComposite() {
746 client_->ScheduleComposite();
749 bool LayerTreeHost::InitializeOutputSurfaceIfNeeded() {
750 if (!output_surface_can_be_initialized_)
753 if (output_surface_lost_)
754 proxy_->CreateAndInitializeOutputSurface();
755 return !output_surface_lost_;
758 bool LayerTreeHost::UpdateLayers(ResourceUpdateQueue* queue) {
759 DCHECK(!output_surface_lost_);
764 DCHECK(!root_layer()->parent());
766 bool result = UpdateLayers(root_layer(), queue);
768 micro_benchmark_controller_.DidUpdateLayers();
773 static Layer* FindFirstScrollableLayer(Layer* layer) {
777 if (layer->scrollable())
780 for (size_t i = 0; i < layer->children().size(); ++i) {
781 Layer* found = FindFirstScrollableLayer(layer->children()[i].get());
789 void LayerTreeHost::CalculateLCDTextMetricsCallback(Layer* layer) {
790 if (!layer->SupportsLCDText())
793 lcd_text_metrics_.total_num_cc_layers++;
794 if (layer->draw_properties().can_use_lcd_text) {
795 lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text++;
796 if (layer->contents_opaque())
797 lcd_text_metrics_.total_num_cc_layers_will_use_lcd_text++;
801 bool LayerTreeHost::UsingSharedMemoryResources() {
802 return GetRendererCapabilities().using_shared_memory_resources;
805 bool LayerTreeHost::UpdateLayers(Layer* root_layer,
806 ResourceUpdateQueue* queue) {
807 TRACE_EVENT1("cc", "LayerTreeHost::UpdateLayers",
808 "source_frame_number", source_frame_number());
810 RenderSurfaceLayerList update_list;
814 Layer* root_scroll = FindFirstScrollableLayer(root_layer);
815 Layer* page_scale_layer = page_scale_layer_;
816 if (!page_scale_layer && root_scroll)
817 page_scale_layer = root_scroll->parent();
820 hud_layer_->PrepareForCalculateDrawProperties(
821 device_viewport_size(), device_scale_factor_);
824 TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::CalcDrawProps");
825 bool can_render_to_separate_surface = true;
826 LayerTreeHostCommon::CalcDrawPropsMainInputs inputs(
828 device_viewport_size(),
830 device_scale_factor_,
833 GetRendererCapabilities().max_texture_size,
834 settings_.can_use_lcd_text,
835 can_render_to_separate_surface,
836 settings_.layer_transforms_should_scale_layer_contents,
838 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
840 if (total_frames_used_for_lcd_text_metrics_ <=
841 kTotalFramesToUseForLCDTextMetrics) {
842 LayerTreeHostCommon::CallFunctionForSubtree(
844 base::Bind(&LayerTreeHost::CalculateLCDTextMetricsCallback,
845 base::Unretained(this)));
846 total_frames_used_for_lcd_text_metrics_++;
849 if (total_frames_used_for_lcd_text_metrics_ ==
850 kTotalFramesToUseForLCDTextMetrics) {
851 total_frames_used_for_lcd_text_metrics_++;
853 UMA_HISTOGRAM_PERCENTAGE(
854 "Renderer4.LCDText.PercentageOfCandidateLayers",
855 lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text * 100.0 /
856 lcd_text_metrics_.total_num_cc_layers);
857 UMA_HISTOGRAM_PERCENTAGE(
858 "Renderer4.LCDText.PercentageOfAALayers",
859 lcd_text_metrics_.total_num_cc_layers_will_use_lcd_text * 100.0 /
860 lcd_text_metrics_.total_num_cc_layers_can_use_lcd_text);
864 // Reset partial texture update requests.
865 partial_texture_update_requests_ = 0;
867 bool did_paint_content = false;
868 bool need_more_updates = false;
870 update_list, queue, &did_paint_content, &need_more_updates);
871 if (trigger_idle_updates_ && need_more_updates) {
872 TRACE_EVENT0("cc", "LayerTreeHost::UpdateLayers::posting prepaint task");
873 prepaint_callback_.Reset(base::Bind(&LayerTreeHost::TriggerPrepaint,
874 base::Unretained(this)));
875 static base::TimeDelta prepaint_delay =
876 base::TimeDelta::FromMilliseconds(100);
877 base::MessageLoop::current()->PostDelayedTask(
878 FROM_HERE, prepaint_callback_.callback(), prepaint_delay);
881 return did_paint_content;
884 void LayerTreeHost::TriggerPrepaint() {
885 prepaint_callback_.Cancel();
886 TRACE_EVENT0("cc", "LayerTreeHost::TriggerPrepaint");
890 static void LayerTreeHostReduceMemoryCallback(Layer* layer) {
891 layer->ReduceMemoryUsage();
894 void LayerTreeHost::ReduceMemoryUsage() {
898 LayerTreeHostCommon::CallFunctionForSubtree(
900 base::Bind(&LayerTreeHostReduceMemoryCallback));
903 void LayerTreeHost::SetPrioritiesForSurfaces(size_t surface_memory_bytes) {
904 DCHECK(surface_memory_placeholder_);
906 // Surfaces have a place holder for their memory since they are managed
907 // independantly but should still be tracked and reduce other memory usage.
908 surface_memory_placeholder_->SetTextureManager(
909 contents_texture_manager_.get());
910 surface_memory_placeholder_->set_request_priority(
911 PriorityCalculator::RenderSurfacePriority());
912 surface_memory_placeholder_->SetToSelfManagedMemoryPlaceholder(
913 surface_memory_bytes);
916 void LayerTreeHost::SetPrioritiesForLayers(
917 const RenderSurfaceLayerList& update_list) {
918 typedef LayerIterator<Layer,
919 RenderSurfaceLayerList,
921 LayerIteratorActions::FrontToBack> LayerIteratorType;
923 PriorityCalculator calculator;
924 LayerIteratorType end = LayerIteratorType::End(&update_list);
925 for (LayerIteratorType it = LayerIteratorType::Begin(&update_list);
928 if (it.represents_itself()) {
929 it->SetTexturePriorities(calculator);
930 } else if (it.represents_target_render_surface()) {
931 if (it->mask_layer())
932 it->mask_layer()->SetTexturePriorities(calculator);
933 if (it->replica_layer() && it->replica_layer()->mask_layer())
934 it->replica_layer()->mask_layer()->SetTexturePriorities(calculator);
939 void LayerTreeHost::PrioritizeTextures(
940 const RenderSurfaceLayerList& render_surface_layer_list,
941 OverdrawMetrics* metrics) {
942 if (!contents_texture_manager_)
945 contents_texture_manager_->ClearPriorities();
947 size_t memory_for_render_surfaces_metric =
948 CalculateMemoryForRenderSurfaces(render_surface_layer_list);
950 SetPrioritiesForLayers(render_surface_layer_list);
951 SetPrioritiesForSurfaces(memory_for_render_surfaces_metric);
953 metrics->DidUseContentsTextureMemoryBytes(
954 contents_texture_manager_->MemoryAboveCutoffBytes());
955 metrics->DidUseRenderSurfaceTextureMemoryBytes(
956 memory_for_render_surfaces_metric);
958 contents_texture_manager_->PrioritizeTextures();
961 size_t LayerTreeHost::CalculateMemoryForRenderSurfaces(
962 const RenderSurfaceLayerList& update_list) {
963 size_t readback_bytes = 0;
964 size_t max_background_texture_bytes = 0;
965 size_t contents_texture_bytes = 0;
967 // Start iteration at 1 to skip the root surface as it does not have a texture
969 for (size_t i = 1; i < update_list.size(); ++i) {
970 Layer* render_surface_layer = update_list.at(i);
971 RenderSurface* render_surface = render_surface_layer->render_surface();
974 Resource::MemorySizeBytes(render_surface->content_rect().size(),
976 contents_texture_bytes += bytes;
978 if (render_surface_layer->background_filters().IsEmpty())
981 if (bytes > max_background_texture_bytes)
982 max_background_texture_bytes = bytes;
983 if (!readback_bytes) {
984 readback_bytes = Resource::MemorySizeBytes(device_viewport_size_,
988 return readback_bytes + max_background_texture_bytes + contents_texture_bytes;
991 void LayerTreeHost::PaintMasksForRenderSurface(Layer* render_surface_layer,
992 ResourceUpdateQueue* queue,
993 bool* did_paint_content,
994 bool* need_more_updates) {
995 // Note: Masks and replicas only exist for layers that own render surfaces. If
996 // we reach this point in code, we already know that at least something will
997 // be drawn into this render surface, so the mask and replica should be
1000 Layer* mask_layer = render_surface_layer->mask_layer();
1002 devtools_instrumentation::ScopedLayerTreeTask
1003 update_layer(devtools_instrumentation::kUpdateLayer,
1006 *did_paint_content |= mask_layer->Update(queue, NULL);
1007 *need_more_updates |= mask_layer->NeedMoreUpdates();
1010 Layer* replica_mask_layer =
1011 render_surface_layer->replica_layer() ?
1012 render_surface_layer->replica_layer()->mask_layer() : NULL;
1013 if (replica_mask_layer) {
1014 devtools_instrumentation::ScopedLayerTreeTask
1015 update_layer(devtools_instrumentation::kUpdateLayer,
1016 replica_mask_layer->id(),
1018 *did_paint_content |= replica_mask_layer->Update(queue, NULL);
1019 *need_more_updates |= replica_mask_layer->NeedMoreUpdates();
1023 void LayerTreeHost::PaintLayerContents(
1024 const RenderSurfaceLayerList& render_surface_layer_list,
1025 ResourceUpdateQueue* queue,
1026 bool* did_paint_content,
1027 bool* need_more_updates) {
1028 // Use FrontToBack to allow for testing occlusion and performing culling
1029 // during the tree walk.
1030 typedef LayerIterator<Layer,
1031 RenderSurfaceLayerList,
1033 LayerIteratorActions::FrontToBack> LayerIteratorType;
1035 bool record_metrics_for_frame =
1036 settings_.show_overdraw_in_tracing &&
1037 base::debug::TraceLog::GetInstance() &&
1038 base::debug::TraceLog::GetInstance()->IsEnabled();
1039 OcclusionTracker occlusion_tracker(
1040 root_layer_->render_surface()->content_rect(), record_metrics_for_frame);
1041 occlusion_tracker.set_minimum_tracking_size(
1042 settings_.minimum_occlusion_tracking_size);
1044 PrioritizeTextures(render_surface_layer_list,
1045 occlusion_tracker.overdraw_metrics());
1047 in_paint_layer_contents_ = true;
1049 LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list);
1050 for (LayerIteratorType it =
1051 LayerIteratorType::Begin(&render_surface_layer_list);
1054 bool prevent_occlusion = it.target_render_surface_layer()->HasCopyRequest();
1055 occlusion_tracker.EnterLayer(it, prevent_occlusion);
1057 if (it.represents_target_render_surface()) {
1058 PaintMasksForRenderSurface(
1059 *it, queue, did_paint_content, need_more_updates);
1060 } else if (it.represents_itself() && it->DrawsContent()) {
1061 devtools_instrumentation::ScopedLayerTreeTask
1062 update_layer(devtools_instrumentation::kUpdateLayer, it->id(), id());
1063 DCHECK(!it->paint_properties().bounds.IsEmpty());
1064 *did_paint_content |= it->Update(queue, &occlusion_tracker);
1065 *need_more_updates |= it->NeedMoreUpdates();
1068 occlusion_tracker.LeaveLayer(it);
1071 in_paint_layer_contents_ = false;
1073 occlusion_tracker.overdraw_metrics()->RecordMetrics(this);
1076 void LayerTreeHost::ApplyScrollAndScale(const ScrollAndScaleSet& info) {
1077 if (!root_layer_.get())
1080 gfx::Vector2d root_scroll_delta;
1081 Layer* root_scroll_layer = FindFirstScrollableLayer(root_layer_.get());
1083 for (size_t i = 0; i < info.scrolls.size(); ++i) {
1085 LayerTreeHostCommon::FindLayerInSubtree(root_layer_.get(),
1086 info.scrolls[i].layer_id);
1089 if (layer == root_scroll_layer) {
1090 root_scroll_delta += info.scrolls[i].scroll_delta;
1092 layer->SetScrollOffsetFromImplSide(layer->scroll_offset() +
1093 info.scrolls[i].scroll_delta);
1097 if (!root_scroll_delta.IsZero() || info.page_scale_delta != 1.f) {
1098 // SetScrollOffsetFromImplSide above could have destroyed the tree,
1099 // so re-get this layer before doing anything to it.
1100 root_scroll_layer = FindFirstScrollableLayer(root_layer_.get());
1102 // Preemptively apply the scroll offset and scale delta here before sending
1103 // it to the client. If the client comes back and sets it to the same
1104 // value, then the layer can early out without needing a full commit.
1105 if (root_scroll_layer) {
1106 root_scroll_layer->SetScrollOffsetFromImplSide(
1107 root_scroll_layer->scroll_offset() + root_scroll_delta);
1109 ApplyPageScaleDeltaFromImplSide(info.page_scale_delta);
1110 client_->ApplyScrollAndScale(root_scroll_delta, info.page_scale_delta);
1114 void LayerTreeHost::StartRateLimiter(WebKit::WebGraphicsContext3D* context3d) {
1119 RateLimiterMap::iterator it = rate_limiters_.find(context3d);
1120 if (it != rate_limiters_.end()) {
1121 it->second->Start();
1123 scoped_refptr<RateLimiter> rate_limiter =
1124 RateLimiter::Create(context3d, this, proxy_->MainThreadTaskRunner());
1125 rate_limiters_[context3d] = rate_limiter;
1126 rate_limiter->Start();
1130 void LayerTreeHost::StopRateLimiter(WebKit::WebGraphicsContext3D* context3d) {
1131 RateLimiterMap::iterator it = rate_limiters_.find(context3d);
1132 if (it != rate_limiters_.end()) {
1134 rate_limiters_.erase(it);
1138 void LayerTreeHost::RateLimit() {
1139 // Force a no-op command on the compositor context, so that any ratelimiting
1140 // commands will wait for the compositing context, and therefore for the
1142 proxy_->ForceSerializeOnSwapBuffers();
1145 bool LayerTreeHost::AlwaysUsePartialTextureUpdates() {
1146 if (!proxy_->GetRendererCapabilities().allow_partial_texture_updates)
1148 return !proxy_->HasImplThread();
1151 size_t LayerTreeHost::MaxPartialTextureUpdates() const {
1152 size_t max_partial_texture_updates = 0;
1153 if (proxy_->GetRendererCapabilities().allow_partial_texture_updates &&
1154 !settings_.impl_side_painting) {
1155 max_partial_texture_updates =
1156 std::min(settings_.max_partial_texture_updates,
1157 proxy_->MaxPartialTextureUpdates());
1159 return max_partial_texture_updates;
1162 bool LayerTreeHost::RequestPartialTextureUpdate() {
1163 if (partial_texture_update_requests_ >= MaxPartialTextureUpdates())
1166 partial_texture_update_requests_++;
1170 void LayerTreeHost::SetDeviceScaleFactor(float device_scale_factor) {
1171 if (device_scale_factor == device_scale_factor_)
1173 device_scale_factor_ = device_scale_factor;
1178 void LayerTreeHost::UpdateTopControlsState(TopControlsState constraints,
1179 TopControlsState current,
1181 if (!settings_.calculate_top_controls_position)
1184 // Top controls are only used in threaded mode.
1185 proxy_->ImplThreadTaskRunner()->PostTask(
1187 base::Bind(&TopControlsManager::UpdateTopControlsState,
1188 top_controls_manager_weak_ptr_,
1194 scoped_ptr<base::Value> LayerTreeHost::AsValue() const {
1195 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
1196 state->Set("proxy", proxy_->AsValue().release());
1197 return state.PassAs<base::Value>();
1200 void LayerTreeHost::AnimateLayers(base::TimeTicks time) {
1201 if (!settings_.accelerated_animation_enabled ||
1202 animation_registrar_->active_animation_controllers().empty())
1205 TRACE_EVENT0("cc", "LayerTreeHost::AnimateLayers");
1207 double monotonic_time = (time - base::TimeTicks()).InSecondsF();
1209 AnimationRegistrar::AnimationControllerMap copy =
1210 animation_registrar_->active_animation_controllers();
1211 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin();
1214 (*iter).second->Animate(monotonic_time);
1215 bool start_ready_animations = true;
1216 (*iter).second->UpdateState(start_ready_animations, NULL);
1220 UIResourceId LayerTreeHost::CreateUIResource(UIResourceClient* client) {
1223 UIResourceId next_id = next_ui_resource_id_++;
1224 DCHECK(ui_resource_client_map_.find(next_id) ==
1225 ui_resource_client_map_.end());
1227 bool resource_lost = false;
1228 UIResourceRequest request(UIResourceRequest::UIResourceCreate,
1230 client->GetBitmap(next_id, resource_lost));
1231 ui_resource_request_queue_.push_back(request);
1233 UIResourceClientData data;
1234 data.client = client;
1235 data.size = request.GetBitmap().GetSize();
1237 ui_resource_client_map_[request.GetId()] = data;
1238 return request.GetId();
1241 // Deletes a UI resource. May safely be called more than once.
1242 void LayerTreeHost::DeleteUIResource(UIResourceId uid) {
1243 UIResourceClientMap::iterator iter = ui_resource_client_map_.find(uid);
1244 if (iter == ui_resource_client_map_.end())
1247 UIResourceRequest request(UIResourceRequest::UIResourceDelete, uid);
1248 ui_resource_request_queue_.push_back(request);
1249 ui_resource_client_map_.erase(iter);
1252 void LayerTreeHost::RecreateUIResources() {
1253 for (UIResourceClientMap::iterator iter = ui_resource_client_map_.begin();
1254 iter != ui_resource_client_map_.end();
1256 UIResourceId uid = iter->first;
1257 const UIResourceClientData& data = iter->second;
1258 bool resource_lost = true;
1259 UIResourceRequest request(UIResourceRequest::UIResourceCreate,
1261 data.client->GetBitmap(uid, resource_lost));
1262 ui_resource_request_queue_.push_back(request);
1266 // Returns the size of a resource given its id.
1267 gfx::Size LayerTreeHost::GetUIResourceSize(UIResourceId uid) const {
1268 UIResourceClientMap::const_iterator iter = ui_resource_client_map_.find(uid);
1269 if (iter == ui_resource_client_map_.end())
1272 const UIResourceClientData& data = iter->second;
1276 void LayerTreeHost::RegisterViewportLayers(
1277 scoped_refptr<Layer> page_scale_layer,
1278 scoped_refptr<Layer> inner_viewport_scroll_layer,
1279 scoped_refptr<Layer> outer_viewport_scroll_layer) {
1280 page_scale_layer_ = page_scale_layer;
1281 inner_viewport_scroll_layer_ = inner_viewport_scroll_layer;
1282 outer_viewport_scroll_layer_ = outer_viewport_scroll_layer;
1285 bool LayerTreeHost::ScheduleMicroBenchmark(
1286 const std::string& benchmark_name,
1287 scoped_ptr<base::Value> value,
1288 const MicroBenchmark::DoneCallback& callback) {
1289 return micro_benchmark_controller_.ScheduleRun(
1290 benchmark_name, value.Pass(), callback);