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