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