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_impl.h" 6 7 #include <algorithm> 8 #include <limits> 9 10 #include "base/basictypes.h" 11 #include "base/containers/hash_tables.h" 12 #include "base/json/json_writer.h" 13 #include "base/metrics/histogram.h" 14 #include "base/stl_util.h" 15 #include "base/strings/stringprintf.h" 16 #include "cc/animation/scrollbar_animation_controller.h" 17 #include "cc/animation/timing_function.h" 18 #include "cc/base/latency_info_swap_promise_monitor.h" 19 #include "cc/base/math_util.h" 20 #include "cc/base/util.h" 21 #include "cc/debug/benchmark_instrumentation.h" 22 #include "cc/debug/debug_rect_history.h" 23 #include "cc/debug/devtools_instrumentation.h" 24 #include "cc/debug/frame_rate_counter.h" 25 #include "cc/debug/overdraw_metrics.h" 26 #include "cc/debug/paint_time_counter.h" 27 #include "cc/debug/rendering_stats_instrumentation.h" 28 #include "cc/debug/traced_value.h" 29 #include "cc/input/page_scale_animation.h" 30 #include "cc/input/top_controls_manager.h" 31 #include "cc/layers/append_quads_data.h" 32 #include "cc/layers/heads_up_display_layer_impl.h" 33 #include "cc/layers/layer_impl.h" 34 #include "cc/layers/layer_iterator.h" 35 #include "cc/layers/painted_scrollbar_layer_impl.h" 36 #include "cc/layers/render_surface_impl.h" 37 #include "cc/layers/scrollbar_layer_impl_base.h" 38 #include "cc/output/compositor_frame_metadata.h" 39 #include "cc/output/copy_output_request.h" 40 #include "cc/output/delegating_renderer.h" 41 #include "cc/output/gl_renderer.h" 42 #include "cc/output/software_renderer.h" 43 #include "cc/quads/render_pass_draw_quad.h" 44 #include "cc/quads/shared_quad_state.h" 45 #include "cc/quads/solid_color_draw_quad.h" 46 #include "cc/quads/texture_draw_quad.h" 47 #include "cc/resources/memory_history.h" 48 #include "cc/resources/picture_layer_tiling.h" 49 #include "cc/resources/prioritized_resource_manager.h" 50 #include "cc/resources/texture_mailbox_deleter.h" 51 #include "cc/resources/ui_resource_bitmap.h" 52 #include "cc/scheduler/delay_based_time_source.h" 53 #include "cc/scheduler/texture_uploader.h" 54 #include "cc/trees/damage_tracker.h" 55 #include "cc/trees/layer_tree_host.h" 56 #include "cc/trees/layer_tree_host_common.h" 57 #include "cc/trees/layer_tree_impl.h" 58 #include "cc/trees/quad_culler.h" 59 #include "cc/trees/single_thread_proxy.h" 60 #include "cc/trees/tree_synchronizer.h" 61 #include "gpu/GLES2/gl2extchromium.h" 62 #include "ui/gfx/frame_time.h" 63 #include "ui/gfx/size_conversions.h" 64 #include "ui/gfx/vector2d_conversions.h" 65 66 namespace { 67 68 void DidVisibilityChange(cc::LayerTreeHostImpl* id, bool visible) { 69 if (visible) { 70 TRACE_EVENT_ASYNC_BEGIN1("webkit", 71 "LayerTreeHostImpl::SetVisible", 72 id, 73 "LayerTreeHostImpl", 74 id); 75 return; 76 } 77 78 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::SetVisible", id); 79 } 80 81 size_t GetMaxTransferBufferUsageBytes(cc::ContextProvider* context_provider) { 82 // Software compositing should not use this value in production. Just use a 83 // default value when testing uploads with the software compositor. 84 if (!context_provider) 85 return std::numeric_limits<size_t>::max(); 86 87 // We want to make sure the default transfer buffer size is equal to the 88 // amount of data that can be uploaded by the compositor to avoid stalling 89 // the pipeline. 90 // For reference Chromebook Pixel can upload 1MB in about 0.5ms. 91 const size_t kMaxBytesUploadedPerMs = 1024 * 1024 * 2; 92 // Assuming a two frame deep pipeline between CPU and GPU and we are 93 // drawing 60 frames per second which would require us to draw one 94 // frame in 16 milliseconds. 95 const size_t kMaxTransferBufferUsageBytes = 16 * 2 * kMaxBytesUploadedPerMs; 96 return std::min( 97 context_provider->ContextCapabilities().max_transfer_buffer_usage_bytes, 98 kMaxTransferBufferUsageBytes); 99 } 100 101 size_t GetMaxRasterTasksUsageBytes(cc::ContextProvider* context_provider) { 102 // Transfer-buffer/raster-tasks limits are different but related. We make 103 // equal here, as this is ideal when using transfer buffers. When not using 104 // transfer buffers we should still limit raster to something similar, to 105 // preserve caching behavior (and limit memory waste when priorities change). 106 return GetMaxTransferBufferUsageBytes(context_provider); 107 } 108 109 GLenum GetMapImageTextureTarget(cc::ContextProvider* context_provider) { 110 if (!context_provider) 111 return GL_TEXTURE_2D; 112 113 // TODO(reveman): Determine if GL_TEXTURE_EXTERNAL_OES works well on 114 // Android before we enable this. crbug.com/322780 115 #if !defined(OS_ANDROID) 116 if (context_provider->ContextCapabilities().egl_image_external) 117 return GL_TEXTURE_EXTERNAL_OES; 118 if (context_provider->ContextCapabilities().texture_rectangle) 119 return GL_TEXTURE_RECTANGLE_ARB; 120 #endif 121 122 return GL_TEXTURE_2D; 123 } 124 125 } // namespace 126 127 namespace cc { 128 129 class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient { 130 public: 131 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> Create( 132 LayerTreeHostImpl* layer_tree_host_impl, 133 scoped_refptr<DelayBasedTimeSource> time_source) { 134 return make_scoped_ptr( 135 new LayerTreeHostImplTimeSourceAdapter(layer_tree_host_impl, 136 time_source)); 137 } 138 virtual ~LayerTreeHostImplTimeSourceAdapter() { 139 time_source_->SetClient(NULL); 140 time_source_->SetActive(false); 141 } 142 143 virtual void OnTimerTick() OVERRIDE { 144 // In single threaded mode we attempt to simulate changing the current 145 // thread by maintaining a fake thread id. When we switch from one 146 // thread to another, we construct DebugScopedSetXXXThread objects that 147 // update the thread id. This lets DCHECKS that ensure we're on the 148 // right thread to work correctly in single threaded mode. The problem 149 // here is that the timer tasks are run via the message loop, and when 150 // they run, we've had no chance to construct a DebugScopedSetXXXThread 151 // object. The result is that we report that we're running on the main 152 // thread. In multi-threaded mode, this timer is run on the compositor 153 // thread, so to keep this consistent in single-threaded mode, we'll 154 // construct a DebugScopedSetImplThread object. There is no need to do 155 // this in multi-threaded mode since the real thread id's will be 156 // correct. In fact, setting fake thread id's interferes with the real 157 // thread id's and causes breakage. 158 scoped_ptr<DebugScopedSetImplThread> set_impl_thread; 159 if (!layer_tree_host_impl_->proxy()->HasImplThread()) { 160 set_impl_thread.reset( 161 new DebugScopedSetImplThread(layer_tree_host_impl_->proxy())); 162 } 163 164 // TODO(enne): This should probably happen post-animate. 165 if (layer_tree_host_impl_->pending_tree()) { 166 layer_tree_host_impl_->pending_tree()->UpdateDrawProperties(); 167 layer_tree_host_impl_->ManageTiles(); 168 } 169 170 layer_tree_host_impl_->Animate( 171 layer_tree_host_impl_->CurrentFrameTimeTicks(), 172 layer_tree_host_impl_->CurrentFrameTime()); 173 layer_tree_host_impl_->UpdateBackgroundAnimateTicking(true); 174 bool start_ready_animations = true; 175 layer_tree_host_impl_->UpdateAnimationState(start_ready_animations); 176 layer_tree_host_impl_->ResetCurrentFrameTimeForNextFrame(); 177 } 178 179 void SetActive(bool active) { 180 if (active != time_source_->Active()) 181 time_source_->SetActive(active); 182 } 183 184 bool Active() const { return time_source_->Active(); } 185 186 private: 187 LayerTreeHostImplTimeSourceAdapter( 188 LayerTreeHostImpl* layer_tree_host_impl, 189 scoped_refptr<DelayBasedTimeSource> time_source) 190 : layer_tree_host_impl_(layer_tree_host_impl), 191 time_source_(time_source) { 192 time_source_->SetClient(this); 193 } 194 195 LayerTreeHostImpl* layer_tree_host_impl_; 196 scoped_refptr<DelayBasedTimeSource> time_source_; 197 198 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter); 199 }; 200 201 LayerTreeHostImpl::FrameData::FrameData() 202 : contains_incomplete_tile(false), has_no_damage(false) {} 203 204 LayerTreeHostImpl::FrameData::~FrameData() {} 205 206 scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::Create( 207 const LayerTreeSettings& settings, 208 LayerTreeHostImplClient* client, 209 Proxy* proxy, 210 RenderingStatsInstrumentation* rendering_stats_instrumentation, 211 SharedBitmapManager* manager, 212 int id) { 213 return make_scoped_ptr(new LayerTreeHostImpl( 214 settings, client, proxy, rendering_stats_instrumentation, manager, id)); 215 } 216 217 LayerTreeHostImpl::LayerTreeHostImpl( 218 const LayerTreeSettings& settings, 219 LayerTreeHostImplClient* client, 220 Proxy* proxy, 221 RenderingStatsInstrumentation* rendering_stats_instrumentation, 222 SharedBitmapManager* manager, 223 int id) 224 : client_(client), 225 proxy_(proxy), 226 input_handler_client_(NULL), 227 did_lock_scrolling_layer_(false), 228 should_bubble_scrolls_(false), 229 last_scroll_did_bubble_(false), 230 wheel_scrolling_(false), 231 scroll_layer_id_when_mouse_over_scrollbar_(0), 232 tile_priorities_dirty_(false), 233 root_layer_scroll_offset_delegate_(NULL), 234 settings_(settings), 235 visible_(true), 236 cached_managed_memory_policy_( 237 PrioritizedResourceManager::DefaultMemoryAllocationLimit(), 238 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 239 ManagedMemoryPolicy::kDefaultNumResourcesLimit), 240 pinch_gesture_active_(false), 241 pinch_gesture_end_should_clear_scrolling_layer_(false), 242 fps_counter_(FrameRateCounter::Create(proxy_->HasImplThread())), 243 paint_time_counter_(PaintTimeCounter::Create()), 244 memory_history_(MemoryHistory::Create()), 245 debug_rect_history_(DebugRectHistory::Create()), 246 texture_mailbox_deleter_(new TextureMailboxDeleter), 247 max_memory_needed_bytes_(0), 248 last_sent_memory_visible_bytes_(0), 249 last_sent_memory_visible_and_nearby_bytes_(0), 250 last_sent_memory_use_bytes_(0), 251 zero_budget_(false), 252 device_scale_factor_(1.f), 253 overhang_ui_resource_id_(0), 254 overdraw_bottom_height_(0.f), 255 device_viewport_valid_for_tile_management_(true), 256 external_stencil_test_enabled_(false), 257 animation_registrar_(AnimationRegistrar::Create()), 258 rendering_stats_instrumentation_(rendering_stats_instrumentation), 259 micro_benchmark_controller_(this), 260 need_to_update_visible_tiles_before_draw_(false), 261 #ifndef NDEBUG 262 did_lose_called_(false), 263 #endif 264 shared_bitmap_manager_(manager), 265 id_(id) { 266 DCHECK(proxy_->IsImplThread()); 267 DidVisibilityChange(this, visible_); 268 269 SetDebugState(settings.initial_debug_state); 270 271 if (settings.calculate_top_controls_position) { 272 top_controls_manager_ = 273 TopControlsManager::Create(this, 274 settings.top_controls_height, 275 settings.top_controls_show_threshold, 276 settings.top_controls_hide_threshold); 277 } 278 279 SetDebugState(settings.initial_debug_state); 280 281 // LTHI always has an active tree. 282 active_tree_ = LayerTreeImpl::create(this); 283 TRACE_EVENT_OBJECT_CREATED_WITH_ID( 284 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", this); 285 } 286 287 LayerTreeHostImpl::~LayerTreeHostImpl() { 288 DCHECK(proxy_->IsImplThread()); 289 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()"); 290 TRACE_EVENT_OBJECT_DELETED_WITH_ID( 291 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::LayerTreeHostImpl", this); 292 293 if (input_handler_client_) { 294 input_handler_client_->WillShutdown(); 295 input_handler_client_ = NULL; 296 } 297 298 // The layer trees must be destroyed before the layer tree host. We've 299 // made a contract with our animation controllers that the registrar 300 // will outlive them, and we must make good. 301 recycle_tree_.reset(); 302 pending_tree_.reset(); 303 active_tree_.reset(); 304 } 305 306 void LayerTreeHostImpl::BeginMainFrameAborted(bool did_handle) { 307 // If the begin frame data was handled, then scroll and scale set was applied 308 // by the main thread, so the active tree needs to be updated as if these sent 309 // values were applied and committed. 310 if (did_handle) { 311 active_tree_->ApplySentScrollAndScaleDeltasFromAbortedCommit(); 312 active_tree_->ResetContentsTexturesPurged(); 313 } 314 } 315 316 void LayerTreeHostImpl::BeginCommit() {} 317 318 void LayerTreeHostImpl::CommitComplete() { 319 TRACE_EVENT0("cc", "LayerTreeHostImpl::CommitComplete"); 320 321 if (settings_.impl_side_painting) { 322 // Impl-side painting needs an update immediately post-commit to have the 323 // opportunity to create tilings. Other paths can call UpdateDrawProperties 324 // more lazily when needed prior to drawing. 325 pending_tree()->ApplyScrollDeltasSinceBeginMainFrame(); 326 pending_tree_->set_needs_update_draw_properties(); 327 pending_tree_->UpdateDrawProperties(); 328 // Start working on newly created tiles immediately if needed. 329 if (!tile_manager_ || !tile_priorities_dirty_) 330 NotifyReadyToActivate(); 331 else 332 ManageTiles(); 333 } else { 334 active_tree_->set_needs_update_draw_properties(); 335 if (time_source_client_adapter_ && time_source_client_adapter_->Active()) 336 DCHECK(active_tree_->root_layer()); 337 } 338 339 client_->SendManagedMemoryStats(); 340 341 micro_benchmark_controller_.DidCompleteCommit(); 342 } 343 344 bool LayerTreeHostImpl::CanDraw() const { 345 // Note: If you are changing this function or any other function that might 346 // affect the result of CanDraw, make sure to call 347 // client_->OnCanDrawStateChanged in the proper places and update the 348 // NotifyIfCanDrawChanged test. 349 350 if (!renderer_) { 351 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no renderer", 352 TRACE_EVENT_SCOPE_THREAD); 353 return false; 354 } 355 356 // Must have an OutputSurface if |renderer_| is not NULL. 357 DCHECK(output_surface_); 358 359 // TODO(boliu): Make draws without root_layer work and move this below 360 // draw_and_swap_full_viewport_every_frame check. Tracked in crbug.com/264967. 361 if (!active_tree_->root_layer()) { 362 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw no root layer", 363 TRACE_EVENT_SCOPE_THREAD); 364 return false; 365 } 366 367 if (output_surface_->capabilities().draw_and_swap_full_viewport_every_frame) 368 return true; 369 370 if (DrawViewportSize().IsEmpty()) { 371 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::CanDraw empty viewport", 372 TRACE_EVENT_SCOPE_THREAD); 373 return false; 374 } 375 if (active_tree_->ViewportSizeInvalid()) { 376 TRACE_EVENT_INSTANT0( 377 "cc", "LayerTreeHostImpl::CanDraw viewport size recently changed", 378 TRACE_EVENT_SCOPE_THREAD); 379 return false; 380 } 381 if (active_tree_->ContentsTexturesPurged()) { 382 TRACE_EVENT_INSTANT0( 383 "cc", "LayerTreeHostImpl::CanDraw contents textures purged", 384 TRACE_EVENT_SCOPE_THREAD); 385 return false; 386 } 387 if (EvictedUIResourcesExist()) { 388 TRACE_EVENT_INSTANT0( 389 "cc", "LayerTreeHostImpl::CanDraw UI resources evicted not recreated", 390 TRACE_EVENT_SCOPE_THREAD); 391 return false; 392 } 393 return true; 394 } 395 396 void LayerTreeHostImpl::Animate(base::TimeTicks monotonic_time, 397 base::Time wall_clock_time) { 398 if (input_handler_client_) 399 input_handler_client_->Animate(monotonic_time); 400 AnimatePageScale(monotonic_time); 401 AnimateLayers(monotonic_time, wall_clock_time); 402 AnimateScrollbars(monotonic_time); 403 AnimateTopControls(monotonic_time); 404 } 405 406 void LayerTreeHostImpl::ManageTiles() { 407 if (!tile_manager_) 408 return; 409 if (!tile_priorities_dirty_) 410 return; 411 412 tile_priorities_dirty_ = false; 413 tile_manager_->ManageTiles(global_tile_state_); 414 415 size_t memory_required_bytes; 416 size_t memory_nice_to_have_bytes; 417 size_t memory_allocated_bytes; 418 size_t memory_used_bytes; 419 tile_manager_->GetMemoryStats(&memory_required_bytes, 420 &memory_nice_to_have_bytes, 421 &memory_allocated_bytes, 422 &memory_used_bytes); 423 SendManagedMemoryStats(memory_required_bytes, 424 memory_nice_to_have_bytes, 425 memory_used_bytes); 426 } 427 428 void LayerTreeHostImpl::StartPageScaleAnimation(gfx::Vector2d target_offset, 429 bool anchor_point, 430 float page_scale, 431 base::TimeDelta duration) { 432 if (!RootScrollLayer()) 433 return; 434 435 gfx::Vector2dF scroll_total = 436 RootScrollLayer()->scroll_offset() + RootScrollLayer()->ScrollDelta(); 437 gfx::SizeF scaled_scrollable_size = active_tree_->ScrollableSize(); 438 gfx::SizeF viewport_size = UnscaledScrollableViewportSize(); 439 440 // Easing constants experimentally determined. 441 scoped_ptr<TimingFunction> timing_function = 442 CubicBezierTimingFunction::Create(.8, 0, .3, .9).PassAs<TimingFunction>(); 443 444 page_scale_animation_ = 445 PageScaleAnimation::Create(scroll_total, 446 active_tree_->total_page_scale_factor(), 447 viewport_size, 448 scaled_scrollable_size, 449 timing_function.Pass()); 450 451 if (anchor_point) { 452 gfx::Vector2dF anchor(target_offset); 453 page_scale_animation_->ZoomWithAnchor(anchor, 454 page_scale, 455 duration.InSecondsF()); 456 } else { 457 gfx::Vector2dF scaled_target_offset = target_offset; 458 page_scale_animation_->ZoomTo(scaled_target_offset, 459 page_scale, 460 duration.InSecondsF()); 461 } 462 463 SetNeedsRedraw(); 464 client_->SetNeedsCommitOnImplThread(); 465 client_->RenewTreePriority(); 466 } 467 468 void LayerTreeHostImpl::ScheduleAnimation() { 469 SetNeedsRedraw(); 470 } 471 472 bool LayerTreeHostImpl::HaveTouchEventHandlersAt(gfx::Point viewport_point) { 473 if (!settings_.touch_hit_testing) 474 return true; 475 if (!EnsureRenderSurfaceLayerList()) 476 return false; 477 478 gfx::PointF device_viewport_point = 479 gfx::ScalePoint(viewport_point, device_scale_factor_); 480 481 LayerImpl* layer_impl = 482 LayerTreeHostCommon::FindLayerThatIsHitByPointInTouchHandlerRegion( 483 device_viewport_point, 484 active_tree_->RenderSurfaceLayerList()); 485 return layer_impl != NULL; 486 } 487 488 scoped_ptr<SwapPromiseMonitor> 489 LayerTreeHostImpl::CreateLatencyInfoSwapPromiseMonitor( 490 ui::LatencyInfo* latency) { 491 return scoped_ptr<SwapPromiseMonitor>( 492 new LatencyInfoSwapPromiseMonitor(latency, NULL, this)); 493 } 494 495 void LayerTreeHostImpl::TrackDamageForAllSurfaces( 496 LayerImpl* root_draw_layer, 497 const LayerImplList& render_surface_layer_list) { 498 // For now, we use damage tracking to compute a global scissor. To do this, we 499 // must compute all damage tracking before drawing anything, so that we know 500 // the root damage rect. The root damage rect is then used to scissor each 501 // surface. 502 503 for (int surface_index = render_surface_layer_list.size() - 1; 504 surface_index >= 0; 505 --surface_index) { 506 LayerImpl* render_surface_layer = render_surface_layer_list[surface_index]; 507 RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); 508 DCHECK(render_surface); 509 render_surface->damage_tracker()->UpdateDamageTrackingState( 510 render_surface->layer_list(), 511 render_surface_layer->id(), 512 render_surface->SurfacePropertyChangedOnlyFromDescendant(), 513 render_surface->content_rect(), 514 render_surface_layer->mask_layer(), 515 render_surface_layer->filters()); 516 } 517 } 518 519 scoped_ptr<base::Value> LayerTreeHostImpl::FrameData::AsValue() const { 520 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); 521 value->SetBoolean("contains_incomplete_tile", contains_incomplete_tile); 522 value->SetBoolean("has_no_damage", has_no_damage); 523 524 // Quad data can be quite large, so only dump render passes if we select 525 // cc.debug.quads. 526 bool quads_enabled; 527 TRACE_EVENT_CATEGORY_GROUP_ENABLED( 528 TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"), &quads_enabled); 529 if (quads_enabled) { 530 scoped_ptr<base::ListValue> render_pass_list(new base::ListValue()); 531 for (size_t i = 0; i < render_passes.size(); ++i) 532 render_pass_list->Append(render_passes[i]->AsValue().release()); 533 value->Set("render_passes", render_pass_list.release()); 534 } 535 return value.PassAs<base::Value>(); 536 } 537 538 void LayerTreeHostImpl::FrameData::AppendRenderPass( 539 scoped_ptr<RenderPass> render_pass) { 540 render_passes_by_id[render_pass->id] = render_pass.get(); 541 render_passes.push_back(render_pass.Pass()); 542 } 543 544 static DrawMode GetDrawMode(OutputSurface* output_surface) { 545 if (output_surface->ForcedDrawToSoftwareDevice()) { 546 return DRAW_MODE_RESOURCELESS_SOFTWARE; 547 } else if (output_surface->context_provider()) { 548 return DRAW_MODE_HARDWARE; 549 } else { 550 DCHECK_EQ(!output_surface->software_device(), 551 output_surface->capabilities().delegated_rendering); 552 return DRAW_MODE_SOFTWARE; 553 } 554 } 555 556 static void AppendQuadsForLayer(RenderPass* target_render_pass, 557 LayerImpl* layer, 558 const OcclusionTrackerImpl& occlusion_tracker, 559 AppendQuadsData* append_quads_data) { 560 bool for_surface = false; 561 QuadCuller quad_culler(&target_render_pass->quad_list, 562 &target_render_pass->shared_quad_state_list, 563 layer, 564 occlusion_tracker, 565 layer->ShowDebugBorders(), 566 for_surface); 567 layer->AppendQuads(&quad_culler, append_quads_data); 568 } 569 570 static void AppendQuadsForRenderSurfaceLayer( 571 RenderPass* target_render_pass, 572 LayerImpl* layer, 573 const RenderPass* contributing_render_pass, 574 const OcclusionTrackerImpl& occlusion_tracker, 575 AppendQuadsData* append_quads_data) { 576 bool for_surface = true; 577 QuadCuller quad_culler(&target_render_pass->quad_list, 578 &target_render_pass->shared_quad_state_list, 579 layer, 580 occlusion_tracker, 581 layer->ShowDebugBorders(), 582 for_surface); 583 584 bool is_replica = false; 585 layer->render_surface()->AppendQuads(&quad_culler, 586 append_quads_data, 587 is_replica, 588 contributing_render_pass->id); 589 590 // Add replica after the surface so that it appears below the surface. 591 if (layer->has_replica()) { 592 is_replica = true; 593 layer->render_surface()->AppendQuads(&quad_culler, 594 append_quads_data, 595 is_replica, 596 contributing_render_pass->id); 597 } 598 } 599 600 static void AppendQuadsToFillScreen( 601 ResourceProvider::ResourceId overhang_resource_id, 602 gfx::SizeF overhang_resource_scaled_size, 603 gfx::Rect root_scroll_layer_rect, 604 RenderPass* target_render_pass, 605 LayerImpl* root_layer, 606 SkColor screen_background_color, 607 const OcclusionTrackerImpl& occlusion_tracker) { 608 if (!root_layer || !SkColorGetA(screen_background_color)) 609 return; 610 611 Region fill_region = occlusion_tracker.ComputeVisibleRegionInScreen(); 612 if (fill_region.IsEmpty()) 613 return; 614 615 // Divide the fill region into the part to be filled with the overhang 616 // resource and the part to be filled with the background color. 617 Region screen_background_color_region = fill_region; 618 Region overhang_region; 619 if (overhang_resource_id) { 620 overhang_region = fill_region; 621 overhang_region.Subtract(root_scroll_layer_rect); 622 screen_background_color_region.Intersect(root_scroll_layer_rect); 623 } 624 625 bool for_surface = false; 626 QuadCuller quad_culler(&target_render_pass->quad_list, 627 &target_render_pass->shared_quad_state_list, 628 root_layer, 629 occlusion_tracker, 630 root_layer->ShowDebugBorders(), 631 for_surface); 632 633 // Manually create the quad state for the gutter quads, as the root layer 634 // doesn't have any bounds and so can't generate this itself. 635 // TODO(danakj): Make the gutter quads generated by the solid color layer 636 // (make it smarter about generating quads to fill unoccluded areas). 637 638 gfx::Rect root_target_rect = root_layer->render_surface()->content_rect(); 639 float opacity = 1.f; 640 SharedQuadState* shared_quad_state = 641 quad_culler.UseSharedQuadState(SharedQuadState::Create()); 642 shared_quad_state->SetAll(root_layer->draw_transform(), 643 root_target_rect.size(), 644 root_target_rect, 645 root_target_rect, 646 false, 647 opacity, 648 SkXfermode::kSrcOver_Mode); 649 650 AppendQuadsData append_quads_data; 651 652 gfx::Transform transform_to_layer_space(gfx::Transform::kSkipInitialization); 653 bool did_invert = root_layer->screen_space_transform().GetInverse( 654 &transform_to_layer_space); 655 DCHECK(did_invert); 656 for (Region::Iterator fill_rects(screen_background_color_region); 657 fill_rects.has_rect(); 658 fill_rects.next()) { 659 // The root layer transform is composed of translations and scales only, 660 // no perspective, so mapping is sufficient (as opposed to projecting). 661 gfx::Rect layer_rect = 662 MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect()); 663 // Skip the quad culler and just append the quads directly to avoid 664 // occlusion checks. 665 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create(); 666 quad->SetNew( 667 shared_quad_state, layer_rect, screen_background_color, false); 668 quad_culler.Append(quad.PassAs<DrawQuad>(), &append_quads_data); 669 } 670 for (Region::Iterator fill_rects(overhang_region); 671 fill_rects.has_rect(); 672 fill_rects.next()) { 673 DCHECK(overhang_resource_id); 674 gfx::Rect layer_rect = 675 MathUtil::MapClippedRect(transform_to_layer_space, fill_rects.rect()); 676 scoped_ptr<TextureDrawQuad> tex_quad = TextureDrawQuad::Create(); 677 const float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f}; 678 tex_quad->SetNew( 679 shared_quad_state, 680 layer_rect, 681 layer_rect, 682 overhang_resource_id, 683 false, 684 gfx::PointF(layer_rect.x() / overhang_resource_scaled_size.width(), 685 layer_rect.y() / overhang_resource_scaled_size.height()), 686 gfx::PointF(layer_rect.right() / 687 overhang_resource_scaled_size.width(), 688 layer_rect.bottom() / 689 overhang_resource_scaled_size.height()), 690 screen_background_color, 691 vertex_opacity, 692 false); 693 quad_culler.Append(tex_quad.PassAs<DrawQuad>(), &append_quads_data); 694 } 695 } 696 697 bool LayerTreeHostImpl::CalculateRenderPasses(FrameData* frame) { 698 DCHECK(frame->render_passes.empty()); 699 700 if (!CanDraw() || !active_tree_->root_layer()) 701 return false; 702 703 TrackDamageForAllSurfaces(active_tree_->root_layer(), 704 *frame->render_surface_layer_list); 705 706 // If the root render surface has no visible damage, then don't generate a 707 // frame at all. 708 RenderSurfaceImpl* root_surface = 709 active_tree_->root_layer()->render_surface(); 710 bool root_surface_has_no_visible_damage = 711 !root_surface->damage_tracker()->current_damage_rect().Intersects( 712 root_surface->content_rect()); 713 bool root_surface_has_contributing_layers = 714 !root_surface->layer_list().empty(); 715 if (root_surface_has_contributing_layers && 716 root_surface_has_no_visible_damage) { 717 TRACE_EVENT0("cc", 718 "LayerTreeHostImpl::CalculateRenderPasses::EmptyDamageRect"); 719 frame->has_no_damage = true; 720 // A copy request should cause damage, so we should not have any copy 721 // requests in this case. 722 DCHECK_EQ(0u, active_tree_->LayersWithCopyOutputRequest().size()); 723 DCHECK(!output_surface_->capabilities() 724 .draw_and_swap_full_viewport_every_frame); 725 return true; 726 } 727 728 TRACE_EVENT1("cc", 729 "LayerTreeHostImpl::CalculateRenderPasses", 730 "render_surface_layer_list.size()", 731 static_cast<uint64>(frame->render_surface_layer_list->size())); 732 733 // Create the render passes in dependency order. 734 for (int surface_index = frame->render_surface_layer_list->size() - 1; 735 surface_index >= 0; 736 --surface_index) { 737 LayerImpl* render_surface_layer = 738 (*frame->render_surface_layer_list)[surface_index]; 739 RenderSurfaceImpl* render_surface = render_surface_layer->render_surface(); 740 741 bool should_draw_into_render_pass = 742 render_surface_layer->parent() == NULL || 743 render_surface->contributes_to_drawn_surface() || 744 render_surface_layer->HasCopyRequest(); 745 if (should_draw_into_render_pass) 746 render_surface_layer->render_surface()->AppendRenderPasses(frame); 747 } 748 749 bool record_metrics_for_frame = 750 settings_.show_overdraw_in_tracing && 751 base::debug::TraceLog::GetInstance() && 752 base::debug::TraceLog::GetInstance()->IsEnabled(); 753 OcclusionTrackerImpl occlusion_tracker( 754 active_tree_->root_layer()->render_surface()->content_rect(), 755 record_metrics_for_frame); 756 occlusion_tracker.set_minimum_tracking_size( 757 settings_.minimum_occlusion_tracking_size); 758 759 if (debug_state_.show_occluding_rects) { 760 occlusion_tracker.set_occluding_screen_space_rects_container( 761 &frame->occluding_screen_space_rects); 762 } 763 if (debug_state_.show_non_occluding_rects) { 764 occlusion_tracker.set_non_occluding_screen_space_rects_container( 765 &frame->non_occluding_screen_space_rects); 766 } 767 768 // Add quads to the Render passes in FrontToBack order to allow for testing 769 // occlusion and performing culling during the tree walk. 770 typedef LayerIterator<LayerImpl, 771 LayerImplList, 772 RenderSurfaceImpl, 773 LayerIteratorActions::FrontToBack> LayerIteratorType; 774 775 // Typically when we are missing a texture and use a checkerboard quad, we 776 // still draw the frame. However when the layer being checkerboarded is moving 777 // due to an impl-animation, we drop the frame to avoid flashing due to the 778 // texture suddenly appearing in the future. 779 bool draw_frame = true; 780 // When we have a copy request for a layer, we need to draw no matter 781 // what, as the layer may disappear after this frame. 782 bool have_copy_request = false; 783 784 int layers_drawn = 0; 785 786 const DrawMode draw_mode = GetDrawMode(output_surface_.get()); 787 788 LayerIteratorType end = 789 LayerIteratorType::End(frame->render_surface_layer_list); 790 for (LayerIteratorType it = 791 LayerIteratorType::Begin(frame->render_surface_layer_list); 792 it != end; 793 ++it) { 794 RenderPass::Id target_render_pass_id = 795 it.target_render_surface_layer()->render_surface()->RenderPassId(); 796 RenderPass* target_render_pass = 797 frame->render_passes_by_id[target_render_pass_id]; 798 799 occlusion_tracker.EnterLayer(it); 800 801 AppendQuadsData append_quads_data(target_render_pass_id); 802 803 if (it.represents_target_render_surface()) { 804 if (it->HasCopyRequest()) { 805 have_copy_request = true; 806 it->TakeCopyRequestsAndTransformToTarget( 807 &target_render_pass->copy_requests); 808 } 809 } else if (it.represents_contributing_render_surface() && 810 it->render_surface()->contributes_to_drawn_surface()) { 811 RenderPass::Id contributing_render_pass_id = 812 it->render_surface()->RenderPassId(); 813 RenderPass* contributing_render_pass = 814 frame->render_passes_by_id[contributing_render_pass_id]; 815 AppendQuadsForRenderSurfaceLayer(target_render_pass, 816 *it, 817 contributing_render_pass, 818 occlusion_tracker, 819 &append_quads_data); 820 } else if (it.represents_itself() && it->DrawsContent() && 821 !it->visible_content_rect().IsEmpty()) { 822 bool impl_draw_transform_is_unknown = false; 823 bool occluded = occlusion_tracker.Occluded( 824 it->render_target(), 825 it->visible_content_rect(), 826 it->draw_transform(), 827 impl_draw_transform_is_unknown); 828 if (!occluded && it->WillDraw(draw_mode, resource_provider_.get())) { 829 DCHECK_EQ(active_tree_, it->layer_tree_impl()); 830 831 frame->will_draw_layers.push_back(*it); 832 833 if (it->HasContributingDelegatedRenderPasses()) { 834 RenderPass::Id contributing_render_pass_id = 835 it->FirstContributingRenderPassId(); 836 while (frame->render_passes_by_id.find(contributing_render_pass_id) != 837 frame->render_passes_by_id.end()) { 838 RenderPass* render_pass = 839 frame->render_passes_by_id[contributing_render_pass_id]; 840 841 AppendQuadsData append_quads_data(render_pass->id); 842 AppendQuadsForLayer(render_pass, 843 *it, 844 occlusion_tracker, 845 &append_quads_data); 846 847 contributing_render_pass_id = 848 it->NextContributingRenderPassId(contributing_render_pass_id); 849 } 850 } 851 852 AppendQuadsForLayer(target_render_pass, 853 *it, 854 occlusion_tracker, 855 &append_quads_data); 856 } 857 858 ++layers_drawn; 859 } 860 861 if (append_quads_data.num_missing_tiles) { 862 bool layer_has_animating_transform = 863 it->screen_space_transform_is_animating() || 864 it->draw_transform_is_animating(); 865 if (layer_has_animating_transform) 866 draw_frame = false; 867 } 868 869 if (append_quads_data.had_incomplete_tile) 870 frame->contains_incomplete_tile = true; 871 872 occlusion_tracker.LeaveLayer(it); 873 } 874 875 if (have_copy_request || 876 output_surface_->capabilities().draw_and_swap_full_viewport_every_frame) 877 draw_frame = true; 878 879 #ifndef NDEBUG 880 for (size_t i = 0; i < frame->render_passes.size(); ++i) { 881 for (size_t j = 0; j < frame->render_passes[i]->quad_list.size(); ++j) 882 DCHECK(frame->render_passes[i]->quad_list[j]->shared_quad_state); 883 DCHECK(frame->render_passes_by_id.find(frame->render_passes[i]->id) 884 != frame->render_passes_by_id.end()); 885 } 886 #endif 887 DCHECK(frame->render_passes.back()->output_rect.origin().IsOrigin()); 888 889 if (!active_tree_->has_transparent_background()) { 890 frame->render_passes.back()->has_transparent_background = false; 891 AppendQuadsToFillScreen( 892 ResourceIdForUIResource(overhang_ui_resource_id_), 893 gfx::ScaleSize(overhang_ui_resource_size_, device_scale_factor_), 894 active_tree_->RootScrollLayerDeviceViewportBounds(), 895 frame->render_passes.back(), 896 active_tree_->root_layer(), 897 active_tree_->background_color(), 898 occlusion_tracker); 899 } 900 901 if (draw_frame) 902 occlusion_tracker.overdraw_metrics()->RecordMetrics(this); 903 else 904 DCHECK(!have_copy_request); 905 906 RemoveRenderPasses(CullRenderPassesWithNoQuads(), frame); 907 renderer_->DecideRenderPassAllocationsForFrame(frame->render_passes); 908 909 // Any copy requests left in the tree are not going to get serviced, and 910 // should be aborted. 911 ScopedPtrVector<CopyOutputRequest> requests_to_abort; 912 while (!active_tree_->LayersWithCopyOutputRequest().empty()) { 913 LayerImpl* layer = active_tree_->LayersWithCopyOutputRequest().back(); 914 layer->TakeCopyRequestsAndTransformToTarget(&requests_to_abort); 915 } 916 for (size_t i = 0; i < requests_to_abort.size(); ++i) 917 requests_to_abort[i]->SendEmptyResult(); 918 919 // If we're making a frame to draw, it better have at least one render pass. 920 DCHECK(!frame->render_passes.empty()); 921 922 // Should only have one render pass in resourceless software mode. 923 if (output_surface_->ForcedDrawToSoftwareDevice()) 924 DCHECK_EQ(1u, frame->render_passes.size()); 925 926 return draw_frame; 927 } 928 929 void LayerTreeHostImpl::MainThreadHasStoppedFlinging() { 930 if (input_handler_client_) 931 input_handler_client_->MainThreadHasStoppedFlinging(); 932 } 933 934 void LayerTreeHostImpl::UpdateBackgroundAnimateTicking( 935 bool should_background_tick) { 936 DCHECK(proxy_->IsImplThread()); 937 if (should_background_tick) 938 DCHECK(active_tree_->root_layer()); 939 940 bool enabled = should_background_tick && 941 !animation_registrar_->active_animation_controllers().empty(); 942 943 // Lazily create the time_source adapter so that we can vary the interval for 944 // testing. 945 if (!time_source_client_adapter_) { 946 time_source_client_adapter_ = LayerTreeHostImplTimeSourceAdapter::Create( 947 this, 948 DelayBasedTimeSource::Create( 949 LowFrequencyAnimationInterval(), 950 proxy_->HasImplThread() ? proxy_->ImplThreadTaskRunner() 951 : proxy_->MainThreadTaskRunner())); 952 } 953 954 time_source_client_adapter_->SetActive(enabled); 955 } 956 957 void LayerTreeHostImpl::DidAnimateScrollOffset() { 958 client_->SetNeedsCommitOnImplThread(); 959 client_->RenewTreePriority(); 960 } 961 962 void LayerTreeHostImpl::SetViewportDamage(gfx::Rect damage_rect) { 963 viewport_damage_rect_.Union(damage_rect); 964 } 965 966 static inline RenderPass* FindRenderPassById( 967 RenderPass::Id render_pass_id, 968 const LayerTreeHostImpl::FrameData& frame) { 969 RenderPassIdHashMap::const_iterator it = 970 frame.render_passes_by_id.find(render_pass_id); 971 return it != frame.render_passes_by_id.end() ? it->second : NULL; 972 } 973 974 static void RemoveRenderPassesRecursive(RenderPass::Id remove_render_pass_id, 975 LayerTreeHostImpl::FrameData* frame) { 976 RenderPass* remove_render_pass = 977 FindRenderPassById(remove_render_pass_id, *frame); 978 // The pass was already removed by another quad - probably the original, and 979 // we are the replica. 980 if (!remove_render_pass) 981 return; 982 RenderPassList& render_passes = frame->render_passes; 983 RenderPassList::iterator to_remove = std::find(render_passes.begin(), 984 render_passes.end(), 985 remove_render_pass); 986 987 DCHECK(to_remove != render_passes.end()); 988 989 scoped_ptr<RenderPass> removed_pass = render_passes.take(to_remove); 990 frame->render_passes.erase(to_remove); 991 frame->render_passes_by_id.erase(remove_render_pass_id); 992 993 // Now follow up for all RenderPass quads and remove their RenderPasses 994 // recursively. 995 const QuadList& quad_list = removed_pass->quad_list; 996 QuadList::ConstBackToFrontIterator quad_list_iterator = 997 quad_list.BackToFrontBegin(); 998 for (; quad_list_iterator != quad_list.BackToFrontEnd(); 999 ++quad_list_iterator) { 1000 DrawQuad* current_quad = (*quad_list_iterator); 1001 if (current_quad->material != DrawQuad::RENDER_PASS) 1002 continue; 1003 1004 RenderPass::Id next_remove_render_pass_id = 1005 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id; 1006 RemoveRenderPassesRecursive(next_remove_render_pass_id, frame); 1007 } 1008 } 1009 1010 bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::ShouldRemoveRenderPass( 1011 const RenderPassDrawQuad& quad, const FrameData& frame) const { 1012 const RenderPass* render_pass = 1013 FindRenderPassById(quad.render_pass_id, frame); 1014 if (!render_pass) 1015 return false; 1016 1017 // If any quad or RenderPass draws into this RenderPass, then keep it. 1018 const QuadList& quad_list = render_pass->quad_list; 1019 for (QuadList::ConstBackToFrontIterator quad_list_iterator = 1020 quad_list.BackToFrontBegin(); 1021 quad_list_iterator != quad_list.BackToFrontEnd(); 1022 ++quad_list_iterator) { 1023 DrawQuad* current_quad = *quad_list_iterator; 1024 1025 if (current_quad->material != DrawQuad::RENDER_PASS) 1026 return false; 1027 1028 const RenderPass* contributing_pass = FindRenderPassById( 1029 RenderPassDrawQuad::MaterialCast(current_quad)->render_pass_id, frame); 1030 if (contributing_pass) 1031 return false; 1032 } 1033 return true; 1034 } 1035 1036 // Defined for linking tests. 1037 template CC_EXPORT void LayerTreeHostImpl::RemoveRenderPasses< 1038 LayerTreeHostImpl::CullRenderPassesWithNoQuads>( 1039 CullRenderPassesWithNoQuads culler, FrameData*); 1040 1041 // static 1042 template <typename RenderPassCuller> 1043 void LayerTreeHostImpl::RemoveRenderPasses(RenderPassCuller culler, 1044 FrameData* frame) { 1045 for (size_t it = culler.RenderPassListBegin(frame->render_passes); 1046 it != culler.RenderPassListEnd(frame->render_passes); 1047 it = culler.RenderPassListNext(it)) { 1048 const RenderPass* current_pass = frame->render_passes[it]; 1049 const QuadList& quad_list = current_pass->quad_list; 1050 QuadList::ConstBackToFrontIterator quad_list_iterator = 1051 quad_list.BackToFrontBegin(); 1052 1053 for (; quad_list_iterator != quad_list.BackToFrontEnd(); 1054 ++quad_list_iterator) { 1055 DrawQuad* current_quad = *quad_list_iterator; 1056 1057 if (current_quad->material != DrawQuad::RENDER_PASS) 1058 continue; 1059 1060 const RenderPassDrawQuad* render_pass_quad = 1061 RenderPassDrawQuad::MaterialCast(current_quad); 1062 if (!culler.ShouldRemoveRenderPass(*render_pass_quad, *frame)) 1063 continue; 1064 1065 // We are changing the vector in the middle of iteration. Because we 1066 // delete render passes that draw into the current pass, we are 1067 // guaranteed that any data from the iterator to the end will not 1068 // change. So, capture the iterator position from the end of the 1069 // list, and restore it after the change. 1070 size_t position_from_end = frame->render_passes.size() - it; 1071 RemoveRenderPassesRecursive(render_pass_quad->render_pass_id, frame); 1072 it = frame->render_passes.size() - position_from_end; 1073 DCHECK_GE(frame->render_passes.size(), position_from_end); 1074 } 1075 } 1076 } 1077 1078 bool LayerTreeHostImpl::PrepareToDraw(FrameData* frame, 1079 gfx::Rect device_viewport_damage_rect) { 1080 TRACE_EVENT1("cc", 1081 "LayerTreeHostImpl::PrepareToDraw", 1082 "SourceFrameNumber", 1083 active_tree_->source_frame_number()); 1084 1085 if (need_to_update_visible_tiles_before_draw_ && 1086 tile_manager_ && tile_manager_->UpdateVisibleTiles()) { 1087 DidInitializeVisibleTile(); 1088 } 1089 need_to_update_visible_tiles_before_draw_ = true; 1090 1091 active_tree_->UpdateDrawProperties(); 1092 1093 frame->render_surface_layer_list = &active_tree_->RenderSurfaceLayerList(); 1094 frame->render_passes.clear(); 1095 frame->render_passes_by_id.clear(); 1096 frame->will_draw_layers.clear(); 1097 frame->contains_incomplete_tile = false; 1098 frame->has_no_damage = false; 1099 1100 if (active_tree_->root_layer()) { 1101 device_viewport_damage_rect.Union(viewport_damage_rect_); 1102 viewport_damage_rect_ = gfx::Rect(); 1103 1104 active_tree_->root_layer()->render_surface()->damage_tracker()-> 1105 AddDamageNextUpdate(device_viewport_damage_rect); 1106 } 1107 1108 if (!CalculateRenderPasses(frame)) { 1109 DCHECK(!output_surface_->capabilities() 1110 .draw_and_swap_full_viewport_every_frame); 1111 return false; 1112 } 1113 1114 // If we return true, then we expect DrawLayers() to be called before this 1115 // function is called again. 1116 return true; 1117 } 1118 1119 void LayerTreeHostImpl::EvictTexturesForTesting() { 1120 EnforceManagedMemoryPolicy(ManagedMemoryPolicy(0)); 1121 } 1122 1123 void LayerTreeHostImpl::BlockNotifyReadyToActivateForTesting(bool block) { 1124 NOTREACHED(); 1125 } 1126 1127 void LayerTreeHostImpl::DidInitializeVisibleTileForTesting() { 1128 DidInitializeVisibleTile(); 1129 } 1130 1131 void LayerTreeHostImpl::EnforceManagedMemoryPolicy( 1132 const ManagedMemoryPolicy& policy) { 1133 1134 bool evicted_resources = client_->ReduceContentsTextureMemoryOnImplThread( 1135 visible_ ? policy.bytes_limit_when_visible : 0, 1136 ManagedMemoryPolicy::PriorityCutoffToValue( 1137 visible_ ? policy.priority_cutoff_when_visible 1138 : gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING)); 1139 if (evicted_resources) { 1140 active_tree_->SetContentsTexturesPurged(); 1141 if (pending_tree_) 1142 pending_tree_->SetContentsTexturesPurged(); 1143 client_->SetNeedsCommitOnImplThread(); 1144 client_->OnCanDrawStateChanged(CanDraw()); 1145 client_->RenewTreePriority(); 1146 } 1147 client_->SendManagedMemoryStats(); 1148 1149 UpdateTileManagerMemoryPolicy(policy); 1150 } 1151 1152 void LayerTreeHostImpl::UpdateTileManagerMemoryPolicy( 1153 const ManagedMemoryPolicy& policy) { 1154 if (!tile_manager_) 1155 return; 1156 1157 // TODO(reveman): We should avoid keeping around unused resources if 1158 // possible. crbug.com/224475 1159 global_tile_state_.memory_limit_in_bytes = 1160 visible_ ? 1161 policy.bytes_limit_when_visible : 0; 1162 global_tile_state_.unused_memory_limit_in_bytes = static_cast<size_t>( 1163 (static_cast<int64>(global_tile_state_.memory_limit_in_bytes) * 1164 settings_.max_unused_resource_memory_percentage) / 100); 1165 global_tile_state_.memory_limit_policy = 1166 ManagedMemoryPolicy::PriorityCutoffToTileMemoryLimitPolicy( 1167 visible_ ? 1168 policy.priority_cutoff_when_visible : 1169 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING); 1170 global_tile_state_.num_resources_limit = policy.num_resources_limit; 1171 1172 DidModifyTilePriorities(); 1173 } 1174 1175 void LayerTreeHostImpl::DidModifyTilePriorities() { 1176 DCHECK(settings_.impl_side_painting); 1177 // Mark priorities as dirty and schedule a ManageTiles(). 1178 tile_priorities_dirty_ = true; 1179 client_->SetNeedsManageTilesOnImplThread(); 1180 } 1181 1182 void LayerTreeHostImpl::DidInitializeVisibleTile() { 1183 // TODO(reveman): Determine tiles that changed and only damage 1184 // what's necessary. 1185 SetFullRootLayerDamage(); 1186 if (client_ && !client_->IsInsideDraw()) 1187 client_->DidInitializeVisibleTileOnImplThread(); 1188 } 1189 1190 void LayerTreeHostImpl::NotifyReadyToActivate() { 1191 client_->NotifyReadyToActivate(); 1192 } 1193 1194 void LayerTreeHostImpl::SetMemoryPolicy(const ManagedMemoryPolicy& policy) { 1195 SetManagedMemoryPolicy(policy, zero_budget_); 1196 } 1197 1198 void LayerTreeHostImpl::SetTreeActivationCallback( 1199 const base::Closure& callback) { 1200 DCHECK(proxy_->IsImplThread()); 1201 DCHECK(settings_.impl_side_painting || callback.is_null()); 1202 tree_activation_callback_ = callback; 1203 } 1204 1205 void LayerTreeHostImpl::SetManagedMemoryPolicy( 1206 const ManagedMemoryPolicy& policy, bool zero_budget) { 1207 if (cached_managed_memory_policy_ == policy && zero_budget_ == zero_budget) 1208 return; 1209 1210 ManagedMemoryPolicy old_policy = ActualManagedMemoryPolicy(); 1211 1212 cached_managed_memory_policy_ = policy; 1213 zero_budget_ = zero_budget; 1214 ManagedMemoryPolicy actual_policy = ActualManagedMemoryPolicy(); 1215 1216 if (old_policy == actual_policy) 1217 return; 1218 1219 if (!proxy_->HasImplThread()) { 1220 // In single-thread mode, this can be called on the main thread by 1221 // GLRenderer::OnMemoryAllocationChanged. 1222 DebugScopedSetImplThread impl_thread(proxy_); 1223 EnforceManagedMemoryPolicy(actual_policy); 1224 } else { 1225 DCHECK(proxy_->IsImplThread()); 1226 EnforceManagedMemoryPolicy(actual_policy); 1227 } 1228 1229 // If there is already enough memory to draw everything imaginable and the 1230 // new memory limit does not change this, then do not re-commit. Don't bother 1231 // skipping commits if this is not visible (commits don't happen when not 1232 // visible, there will almost always be a commit when this becomes visible). 1233 bool needs_commit = true; 1234 if (visible() && 1235 actual_policy.bytes_limit_when_visible >= max_memory_needed_bytes_ && 1236 old_policy.bytes_limit_when_visible >= max_memory_needed_bytes_ && 1237 actual_policy.priority_cutoff_when_visible == 1238 old_policy.priority_cutoff_when_visible) { 1239 needs_commit = false; 1240 } 1241 1242 if (needs_commit) 1243 client_->SetNeedsCommitOnImplThread(); 1244 } 1245 1246 void LayerTreeHostImpl::SetExternalDrawConstraints( 1247 const gfx::Transform& transform, 1248 gfx::Rect viewport, 1249 gfx::Rect clip, 1250 bool valid_for_tile_management) { 1251 external_transform_ = transform; 1252 external_viewport_ = viewport; 1253 external_clip_ = clip; 1254 device_viewport_valid_for_tile_management_ = valid_for_tile_management; 1255 } 1256 1257 void LayerTreeHostImpl::SetNeedsRedrawRect(gfx::Rect damage_rect) { 1258 if (damage_rect.IsEmpty()) 1259 return; 1260 NotifySwapPromiseMonitorsOfSetNeedsRedraw(); 1261 client_->SetNeedsRedrawRectOnImplThread(damage_rect); 1262 } 1263 1264 void LayerTreeHostImpl::BeginImplFrame(const BeginFrameArgs& args) { 1265 client_->BeginImplFrame(args); 1266 } 1267 1268 void LayerTreeHostImpl::DidSwapBuffers() { 1269 client_->DidSwapBuffersOnImplThread(); 1270 } 1271 1272 void LayerTreeHostImpl::OnSwapBuffersComplete() { 1273 client_->OnSwapBuffersCompleteOnImplThread(); 1274 } 1275 1276 void LayerTreeHostImpl::ReclaimResources(const CompositorFrameAck* ack) { 1277 // TODO(piman): We may need to do some validation on this ack before 1278 // processing it. 1279 if (renderer_) 1280 renderer_->ReceiveSwapBuffersAck(*ack); 1281 } 1282 1283 void LayerTreeHostImpl::OnCanDrawStateChangedForTree() { 1284 client_->OnCanDrawStateChanged(CanDraw()); 1285 } 1286 1287 CompositorFrameMetadata LayerTreeHostImpl::MakeCompositorFrameMetadata() const { 1288 CompositorFrameMetadata metadata; 1289 metadata.device_scale_factor = device_scale_factor_; 1290 metadata.page_scale_factor = active_tree_->total_page_scale_factor(); 1291 metadata.viewport_size = active_tree_->ScrollableViewportSize(); 1292 metadata.root_layer_size = active_tree_->ScrollableSize(); 1293 metadata.min_page_scale_factor = active_tree_->min_page_scale_factor(); 1294 metadata.max_page_scale_factor = active_tree_->max_page_scale_factor(); 1295 if (top_controls_manager_) { 1296 metadata.location_bar_offset = 1297 gfx::Vector2dF(0.f, top_controls_manager_->controls_top_offset()); 1298 metadata.location_bar_content_translation = 1299 gfx::Vector2dF(0.f, top_controls_manager_->content_top_offset()); 1300 metadata.overdraw_bottom_height = overdraw_bottom_height_; 1301 } 1302 1303 if (!RootScrollLayer()) 1304 return metadata; 1305 1306 metadata.root_scroll_offset = RootScrollLayer()->TotalScrollOffset(); 1307 1308 return metadata; 1309 } 1310 1311 static void LayerTreeHostImplDidBeginTracingCallback(LayerImpl* layer) { 1312 layer->DidBeginTracing(); 1313 } 1314 1315 void LayerTreeHostImpl::DrawLayers(FrameData* frame, 1316 base::TimeTicks frame_begin_time) { 1317 TRACE_EVENT0("cc", "LayerTreeHostImpl::DrawLayers"); 1318 DCHECK(CanDraw()); 1319 1320 if (frame->has_no_damage) { 1321 TRACE_EVENT0("cc", "EarlyOut_NoDamage"); 1322 DCHECK(!output_surface_->capabilities() 1323 .draw_and_swap_full_viewport_every_frame); 1324 return; 1325 } 1326 1327 DCHECK(!frame->render_passes.empty()); 1328 1329 fps_counter_->SaveTimeStamp(frame_begin_time, 1330 !output_surface_->context_provider()); 1331 1332 bool on_main_thread = false; 1333 rendering_stats_instrumentation_->IncrementFrameCount( 1334 1, on_main_thread); 1335 1336 if (tile_manager_) { 1337 memory_history_->SaveEntry( 1338 tile_manager_->memory_stats_from_last_assign()); 1339 } 1340 1341 if (debug_state_.ShowHudRects()) { 1342 debug_rect_history_->SaveDebugRectsForCurrentFrame( 1343 active_tree_->root_layer(), 1344 *frame->render_surface_layer_list, 1345 frame->occluding_screen_space_rects, 1346 frame->non_occluding_screen_space_rects, 1347 debug_state_); 1348 } 1349 1350 if (!settings_.impl_side_painting && debug_state_.continuous_painting) { 1351 const RenderingStats& stats = 1352 rendering_stats_instrumentation_->GetRenderingStats(); 1353 paint_time_counter_->SavePaintTime(stats.main_stats.paint_time); 1354 } 1355 1356 bool is_new_trace; 1357 TRACE_EVENT_IS_NEW_TRACE(&is_new_trace); 1358 if (is_new_trace) { 1359 if (pending_tree_) { 1360 LayerTreeHostCommon::CallFunctionForSubtree( 1361 pending_tree_->root_layer(), 1362 base::Bind(&LayerTreeHostImplDidBeginTracingCallback)); 1363 } 1364 LayerTreeHostCommon::CallFunctionForSubtree( 1365 active_tree_->root_layer(), 1366 base::Bind(&LayerTreeHostImplDidBeginTracingCallback)); 1367 } 1368 1369 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( 1370 TRACE_DISABLED_BY_DEFAULT("cc.debug") "," 1371 TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"), "cc::LayerTreeHostImpl", 1372 this, TracedValue::FromValue(AsValueWithFrame(frame).release())); 1373 1374 // Because the contents of the HUD depend on everything else in the frame, the 1375 // contents of its texture are updated as the last thing before the frame is 1376 // drawn. 1377 if (active_tree_->hud_layer()) { 1378 TRACE_EVENT0("cc", "DrawLayers.UpdateHudTexture"); 1379 active_tree_->hud_layer()->UpdateHudTexture( 1380 GetDrawMode(output_surface_.get()), resource_provider_.get()); 1381 } 1382 1383 if (output_surface_->ForcedDrawToSoftwareDevice()) { 1384 bool allow_partial_swap = false; 1385 bool disable_picture_quad_image_filtering = 1386 IsCurrentlyScrolling() || needs_animate_layers(); 1387 1388 scoped_ptr<SoftwareRenderer> temp_software_renderer = 1389 SoftwareRenderer::Create(this, &settings_, output_surface_.get(), NULL); 1390 temp_software_renderer->DrawFrame(&frame->render_passes, 1391 NULL, 1392 device_scale_factor_, 1393 DeviceViewport(), 1394 DeviceClip(), 1395 allow_partial_swap, 1396 disable_picture_quad_image_filtering); 1397 } else { 1398 // We don't track damage on the HUD layer (it interacts with damage tracking 1399 // visualizations), so disable partial swaps to make the HUD layer display 1400 // properly. 1401 bool allow_partial_swap = !debug_state_.ShowHudRects(); 1402 1403 renderer_->DrawFrame(&frame->render_passes, 1404 offscreen_context_provider_.get(), 1405 device_scale_factor_, 1406 DeviceViewport(), 1407 DeviceClip(), 1408 allow_partial_swap, 1409 false); 1410 } 1411 // The render passes should be consumed by the renderer. 1412 DCHECK(frame->render_passes.empty()); 1413 frame->render_passes_by_id.clear(); 1414 1415 // The next frame should start by assuming nothing has changed, and changes 1416 // are noted as they occur. 1417 // TODO(boliu): If we did a temporary software renderer frame, propogate the 1418 // damage forward to the next frame. 1419 for (size_t i = 0; i < frame->render_surface_layer_list->size(); i++) { 1420 (*frame->render_surface_layer_list)[i]->render_surface()->damage_tracker()-> 1421 DidDrawDamagedArea(); 1422 } 1423 active_tree_->root_layer()->ResetAllChangeTrackingForSubtree(); 1424 1425 BenchmarkInstrumentation::IssueImplThreadRenderingStatsEvent( 1426 rendering_stats_instrumentation_->impl_thread_rendering_stats()); 1427 rendering_stats_instrumentation_->AccumulateAndClearImplThreadStats(); 1428 } 1429 1430 void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) { 1431 for (size_t i = 0; i < frame.will_draw_layers.size(); ++i) 1432 frame.will_draw_layers[i]->DidDraw(resource_provider_.get()); 1433 1434 // Once all layers have been drawn, pending texture uploads should no 1435 // longer block future uploads. 1436 resource_provider_->MarkPendingUploadsAsNonBlocking(); 1437 } 1438 1439 void LayerTreeHostImpl::FinishAllRendering() { 1440 if (renderer_) 1441 renderer_->Finish(); 1442 } 1443 1444 bool LayerTreeHostImpl::IsContextLost() { 1445 DCHECK(proxy_->IsImplThread()); 1446 return renderer_ && renderer_->IsContextLost(); 1447 } 1448 1449 const RendererCapabilitiesImpl& 1450 LayerTreeHostImpl::GetRendererCapabilities() const { 1451 return renderer_->Capabilities(); 1452 } 1453 1454 bool LayerTreeHostImpl::SwapBuffers(const LayerTreeHostImpl::FrameData& frame) { 1455 if (frame.has_no_damage) { 1456 active_tree()->BreakSwapPromises(SwapPromise::SWAP_FAILS); 1457 return false; 1458 } 1459 CompositorFrameMetadata metadata = MakeCompositorFrameMetadata(); 1460 active_tree()->FinishSwapPromises(&metadata); 1461 renderer_->SwapBuffers(metadata); 1462 return true; 1463 } 1464 1465 void LayerTreeHostImpl::SetNeedsBeginImplFrame(bool enable) { 1466 if (output_surface_) 1467 output_surface_->SetNeedsBeginImplFrame(enable); 1468 } 1469 1470 gfx::SizeF LayerTreeHostImpl::UnscaledScrollableViewportSize() const { 1471 // Use the root container layer bounds if it clips to them, otherwise, the 1472 // true viewport size should be used. 1473 LayerImpl* container_layer = active_tree_->RootContainerLayer(); 1474 if (container_layer && container_layer->masks_to_bounds()) { 1475 DCHECK(!top_controls_manager_); 1476 DCHECK_EQ(0, overdraw_bottom_height_); 1477 return container_layer->bounds(); 1478 } 1479 1480 gfx::SizeF dip_size = 1481 gfx::ScaleSize(device_viewport_size_, 1.f / device_scale_factor()); 1482 1483 float top_offset = 1484 top_controls_manager_ ? top_controls_manager_->content_top_offset() : 0.f; 1485 return gfx::SizeF(dip_size.width(), 1486 dip_size.height() - top_offset - overdraw_bottom_height_); 1487 } 1488 1489 void LayerTreeHostImpl::DidLoseOutputSurface() { 1490 if (resource_provider_) 1491 resource_provider_->DidLoseOutputSurface(); 1492 // TODO(jamesr): The renderer_ check is needed to make some of the 1493 // LayerTreeHostContextTest tests pass, but shouldn't be necessary (or 1494 // important) in production. We should adjust the test to not need this. 1495 if (renderer_) 1496 client_->DidLoseOutputSurfaceOnImplThread(); 1497 #ifndef NDEBUG 1498 did_lose_called_ = true; 1499 #endif 1500 } 1501 1502 void LayerTreeHostImpl::Readback(void* pixels, 1503 gfx::Rect rect_in_device_viewport) { 1504 DCHECK(renderer_); 1505 renderer_->GetFramebufferPixels(pixels, rect_in_device_viewport); 1506 } 1507 1508 bool LayerTreeHostImpl::HaveRootScrollLayer() const { 1509 return !!RootScrollLayer(); 1510 } 1511 1512 LayerImpl* LayerTreeHostImpl::RootLayer() const { 1513 return active_tree_->root_layer(); 1514 } 1515 1516 LayerImpl* LayerTreeHostImpl::RootScrollLayer() const { 1517 return active_tree_->RootScrollLayer(); 1518 } 1519 1520 LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const { 1521 return active_tree_->CurrentlyScrollingLayer(); 1522 } 1523 1524 bool LayerTreeHostImpl::IsCurrentlyScrolling() const { 1525 return CurrentlyScrollingLayer() || 1526 (RootScrollLayer() && RootScrollLayer()->IsExternalFlingActive()); 1527 } 1528 1529 // Content layers can be either directly scrollable or contained in an outer 1530 // scrolling layer which applies the scroll transform. Given a content layer, 1531 // this function returns the associated scroll layer if any. 1532 static LayerImpl* FindScrollLayerForContentLayer(LayerImpl* layer_impl) { 1533 if (!layer_impl) 1534 return NULL; 1535 1536 if (layer_impl->scrollable()) 1537 return layer_impl; 1538 1539 if (layer_impl->DrawsContent() && 1540 layer_impl->parent() && 1541 layer_impl->parent()->scrollable()) 1542 return layer_impl->parent(); 1543 1544 return NULL; 1545 } 1546 1547 void LayerTreeHostImpl::CreatePendingTree() { 1548 CHECK(!pending_tree_); 1549 if (recycle_tree_) 1550 recycle_tree_.swap(pending_tree_); 1551 else 1552 pending_tree_ = LayerTreeImpl::create(this); 1553 client_->OnCanDrawStateChanged(CanDraw()); 1554 TRACE_EVENT_ASYNC_BEGIN0("cc", "PendingTree:waiting", pending_tree_.get()); 1555 } 1556 1557 void LayerTreeHostImpl::UpdateVisibleTiles() { 1558 if (tile_manager_ && tile_manager_->UpdateVisibleTiles()) 1559 DidInitializeVisibleTile(); 1560 need_to_update_visible_tiles_before_draw_ = false; 1561 } 1562 1563 void LayerTreeHostImpl::ActivatePendingTree() { 1564 CHECK(pending_tree_); 1565 TRACE_EVENT_ASYNC_END0("cc", "PendingTree:waiting", pending_tree_.get()); 1566 1567 need_to_update_visible_tiles_before_draw_ = true; 1568 1569 active_tree_->SetRootLayerScrollOffsetDelegate(NULL); 1570 active_tree_->PushPersistedState(pending_tree_.get()); 1571 if (pending_tree_->needs_full_tree_sync()) { 1572 active_tree_->SetRootLayer( 1573 TreeSynchronizer::SynchronizeTrees(pending_tree_->root_layer(), 1574 active_tree_->DetachLayerTree(), 1575 active_tree_.get())); 1576 } 1577 TreeSynchronizer::PushProperties(pending_tree_->root_layer(), 1578 active_tree_->root_layer()); 1579 DCHECK(!recycle_tree_); 1580 1581 // Process any requests in the UI resource queue. The request queue is given 1582 // in LayerTreeHost::FinishCommitOnImplThread. This must take place before 1583 // the swap. 1584 pending_tree_->ProcessUIResourceRequestQueue(); 1585 1586 pending_tree_->PushPropertiesTo(active_tree_.get()); 1587 1588 // Now that we've synced everything from the pending tree to the active 1589 // tree, rename the pending tree the recycle tree so we can reuse it on the 1590 // next sync. 1591 pending_tree_.swap(recycle_tree_); 1592 1593 active_tree_->DidBecomeActive(); 1594 active_tree_->SetRootLayerScrollOffsetDelegate( 1595 root_layer_scroll_offset_delegate_); 1596 1597 client_->OnCanDrawStateChanged(CanDraw()); 1598 SetNeedsRedraw(); 1599 client_->RenewTreePriority(); 1600 1601 if (debug_state_.continuous_painting) { 1602 const RenderingStats& stats = 1603 rendering_stats_instrumentation_->GetRenderingStats(); 1604 paint_time_counter_->SavePaintTime(stats.main_stats.paint_time + 1605 stats.main_stats.record_time + 1606 stats.impl_stats.rasterize_time); 1607 } 1608 1609 client_->DidActivatePendingTree(); 1610 if (!tree_activation_callback_.is_null()) 1611 tree_activation_callback_.Run(); 1612 1613 if (time_source_client_adapter_ && time_source_client_adapter_->Active()) 1614 DCHECK(active_tree_->root_layer()); 1615 devtools_instrumentation::didActivateLayerTree(id_, 1616 active_tree_->source_frame_number()); 1617 } 1618 1619 void LayerTreeHostImpl::SetVisible(bool visible) { 1620 DCHECK(proxy_->IsImplThread()); 1621 1622 if (visible_ == visible) 1623 return; 1624 visible_ = visible; 1625 DidVisibilityChange(this, visible_); 1626 EnforceManagedMemoryPolicy(ActualManagedMemoryPolicy()); 1627 1628 if (!visible_) 1629 EvictAllUIResources(); 1630 1631 // Evict tiles immediately if invisible since this tab may never get another 1632 // draw or timer tick. 1633 if (!visible_) 1634 ManageTiles(); 1635 1636 if (!renderer_) 1637 return; 1638 1639 renderer_->SetVisible(visible); 1640 } 1641 1642 void LayerTreeHostImpl::SetNeedsRedraw() { 1643 NotifySwapPromiseMonitorsOfSetNeedsRedraw(); 1644 client_->SetNeedsRedrawOnImplThread(); 1645 } 1646 1647 ManagedMemoryPolicy LayerTreeHostImpl::ActualManagedMemoryPolicy() const { 1648 ManagedMemoryPolicy actual = cached_managed_memory_policy_; 1649 if (debug_state_.rasterize_only_visible_content) { 1650 actual.priority_cutoff_when_visible = 1651 gpu::MemoryAllocation::CUTOFF_ALLOW_REQUIRED_ONLY; 1652 } 1653 1654 if (zero_budget_) { 1655 actual.bytes_limit_when_visible = 0; 1656 } 1657 1658 return actual; 1659 } 1660 1661 size_t LayerTreeHostImpl::memory_allocation_limit_bytes() const { 1662 return ActualManagedMemoryPolicy().bytes_limit_when_visible; 1663 } 1664 1665 int LayerTreeHostImpl::memory_allocation_priority_cutoff() const { 1666 return ManagedMemoryPolicy::PriorityCutoffToValue( 1667 ActualManagedMemoryPolicy().priority_cutoff_when_visible); 1668 } 1669 1670 void LayerTreeHostImpl::ReleaseTreeResources() { 1671 if (active_tree_->root_layer()) 1672 SendReleaseResourcesRecursive(active_tree_->root_layer()); 1673 if (pending_tree_ && pending_tree_->root_layer()) 1674 SendReleaseResourcesRecursive(pending_tree_->root_layer()); 1675 if (recycle_tree_ && recycle_tree_->root_layer()) 1676 SendReleaseResourcesRecursive(recycle_tree_->root_layer()); 1677 1678 EvictAllUIResources(); 1679 } 1680 1681 void LayerTreeHostImpl::CreateAndSetRenderer( 1682 OutputSurface* output_surface, 1683 ResourceProvider* resource_provider, 1684 bool skip_gl_renderer) { 1685 DCHECK(!renderer_); 1686 if (output_surface->capabilities().delegated_rendering) { 1687 renderer_ = DelegatingRenderer::Create( 1688 this, &settings_, output_surface, resource_provider); 1689 } else if (output_surface->context_provider() && !skip_gl_renderer) { 1690 renderer_ = GLRenderer::Create(this, 1691 &settings_, 1692 output_surface, 1693 resource_provider, 1694 texture_mailbox_deleter_.get(), 1695 settings_.highp_threshold_min); 1696 } else if (output_surface->software_device()) { 1697 renderer_ = SoftwareRenderer::Create( 1698 this, &settings_, output_surface, resource_provider); 1699 } 1700 1701 if (renderer_) { 1702 renderer_->SetVisible(visible_); 1703 SetFullRootLayerDamage(); 1704 1705 // See note in LayerTreeImpl::UpdateDrawProperties. Renderer needs to be 1706 // initialized to get max texture size. Also, after releasing resources, 1707 // trees need another update to generate new ones. 1708 active_tree_->set_needs_update_draw_properties(); 1709 if (pending_tree_) 1710 pending_tree_->set_needs_update_draw_properties(); 1711 client_->UpdateRendererCapabilitiesOnImplThread(); 1712 } 1713 } 1714 1715 void LayerTreeHostImpl::CreateAndSetTileManager( 1716 ResourceProvider* resource_provider, 1717 ContextProvider* context_provider, 1718 bool using_map_image) { 1719 DCHECK(settings_.impl_side_painting); 1720 DCHECK(resource_provider); 1721 tile_manager_ = 1722 TileManager::Create(this, 1723 resource_provider, 1724 settings_.num_raster_threads, 1725 rendering_stats_instrumentation_, 1726 using_map_image, 1727 GetMaxTransferBufferUsageBytes(context_provider), 1728 GetMaxRasterTasksUsageBytes(context_provider), 1729 GetMapImageTextureTarget(context_provider)); 1730 1731 UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy()); 1732 need_to_update_visible_tiles_before_draw_ = false; 1733 } 1734 1735 void LayerTreeHostImpl::EnforceZeroBudget(bool zero_budget) { 1736 SetManagedMemoryPolicy(cached_managed_memory_policy_, zero_budget); 1737 } 1738 1739 bool LayerTreeHostImpl::InitializeRenderer( 1740 scoped_ptr<OutputSurface> output_surface) { 1741 #ifndef NDEBUG 1742 DCHECK(!renderer_ || did_lose_called_); 1743 #endif 1744 1745 // Since we will create a new resource provider, we cannot continue to use 1746 // the old resources (i.e. render_surfaces and texture IDs). Clear them 1747 // before we destroy the old resource provider. 1748 ReleaseTreeResources(); 1749 1750 // Note: order is important here. 1751 renderer_.reset(); 1752 tile_manager_.reset(); 1753 resource_provider_.reset(); 1754 output_surface_.reset(); 1755 1756 if (!output_surface->BindToClient(this)) 1757 return false; 1758 1759 scoped_ptr<ResourceProvider> resource_provider = 1760 ResourceProvider::Create(output_surface.get(), 1761 shared_bitmap_manager_, 1762 settings_.highp_threshold_min, 1763 settings_.use_rgba_4444_textures, 1764 settings_.texture_id_allocation_chunk_size); 1765 if (!resource_provider) 1766 return false; 1767 1768 if (output_surface->capabilities().deferred_gl_initialization) 1769 EnforceZeroBudget(true); 1770 1771 bool skip_gl_renderer = false; 1772 CreateAndSetRenderer( 1773 output_surface.get(), resource_provider.get(), skip_gl_renderer); 1774 1775 if (!renderer_) 1776 return false; 1777 1778 if (settings_.impl_side_painting) { 1779 CreateAndSetTileManager(resource_provider.get(), 1780 output_surface->context_provider().get(), 1781 GetRendererCapabilities().using_map_image); 1782 } 1783 1784 // Setup BeginImplFrameEmulation if it's not supported natively 1785 if (!settings_.begin_impl_frame_scheduling_enabled) { 1786 const base::TimeDelta display_refresh_interval = 1787 base::TimeDelta::FromMicroseconds( 1788 base::Time::kMicrosecondsPerSecond / 1789 settings_.refresh_rate); 1790 1791 output_surface->InitializeBeginImplFrameEmulation( 1792 proxy_->ImplThreadTaskRunner(), 1793 settings_.throttle_frame_production, 1794 display_refresh_interval); 1795 } 1796 1797 int max_frames_pending = 1798 output_surface->capabilities().max_frames_pending; 1799 if (max_frames_pending <= 0) 1800 max_frames_pending = OutputSurface::DEFAULT_MAX_FRAMES_PENDING; 1801 output_surface->SetMaxFramesPending(max_frames_pending); 1802 1803 resource_provider_ = resource_provider.Pass(); 1804 output_surface_ = output_surface.Pass(); 1805 1806 client_->OnCanDrawStateChanged(CanDraw()); 1807 1808 return true; 1809 } 1810 1811 bool LayerTreeHostImpl::DeferredInitialize( 1812 scoped_refptr<ContextProvider> offscreen_context_provider) { 1813 DCHECK(output_surface_->capabilities().deferred_gl_initialization); 1814 DCHECK(settings_.impl_side_painting); 1815 DCHECK(output_surface_->context_provider()); 1816 1817 ReleaseTreeResources(); 1818 renderer_.reset(); 1819 1820 bool resource_provider_success = resource_provider_->InitializeGL(); 1821 1822 bool success = resource_provider_success; 1823 if (success) { 1824 bool skip_gl_renderer = false; 1825 CreateAndSetRenderer( 1826 output_surface_.get(), resource_provider_.get(), skip_gl_renderer); 1827 if (!renderer_) 1828 success = false; 1829 } 1830 1831 if (success) { 1832 if (offscreen_context_provider.get() && 1833 !offscreen_context_provider->BindToCurrentThread()) 1834 success = false; 1835 } 1836 1837 if (success) { 1838 EnforceZeroBudget(false); 1839 client_->SetNeedsCommitOnImplThread(); 1840 } else { 1841 if (offscreen_context_provider.get()) { 1842 if (offscreen_context_provider->BindToCurrentThread()) 1843 offscreen_context_provider->VerifyContexts(); 1844 offscreen_context_provider = NULL; 1845 } 1846 1847 client_->DidLoseOutputSurfaceOnImplThread(); 1848 1849 if (resource_provider_success) { 1850 // If this fails the context provider will be dropped from the output 1851 // surface and destroyed. But the GLRenderer expects the output surface 1852 // to stick around - and hold onto the context3d - as long as it is alive. 1853 // TODO(danakj): Remove the need for this code path: crbug.com/276411 1854 renderer_.reset(); 1855 1856 // The resource provider can't stay in GL mode or it tries to clean up GL 1857 // stuff, but the context provider is going away on the output surface 1858 // which contradicts being in GL mode. 1859 // TODO(danakj): Remove the need for this code path: crbug.com/276411 1860 resource_provider_->InitializeSoftware(); 1861 } 1862 } 1863 1864 SetOffscreenContextProvider(offscreen_context_provider); 1865 return success; 1866 } 1867 1868 void LayerTreeHostImpl::ReleaseGL() { 1869 DCHECK(output_surface_->capabilities().deferred_gl_initialization); 1870 DCHECK(settings_.impl_side_painting); 1871 DCHECK(output_surface_->context_provider()); 1872 1873 ReleaseTreeResources(); 1874 renderer_.reset(); 1875 tile_manager_.reset(); 1876 resource_provider_->InitializeSoftware(); 1877 1878 bool skip_gl_renderer = true; 1879 CreateAndSetRenderer( 1880 output_surface_.get(), resource_provider_.get(), skip_gl_renderer); 1881 DCHECK(renderer_); 1882 1883 EnforceZeroBudget(true); 1884 CreateAndSetTileManager(resource_provider_.get(), 1885 NULL, 1886 GetRendererCapabilities().using_map_image); 1887 DCHECK(tile_manager_); 1888 1889 SetOffscreenContextProvider(NULL); 1890 1891 client_->SetNeedsCommitOnImplThread(); 1892 } 1893 1894 void LayerTreeHostImpl::SetViewportSize(gfx::Size device_viewport_size) { 1895 if (device_viewport_size == device_viewport_size_) 1896 return; 1897 1898 if (pending_tree_) 1899 active_tree_->SetViewportSizeInvalid(); 1900 1901 device_viewport_size_ = device_viewport_size; 1902 1903 UpdateMaxScrollOffset(); 1904 1905 client_->OnCanDrawStateChanged(CanDraw()); 1906 SetFullRootLayerDamage(); 1907 } 1908 1909 void LayerTreeHostImpl::SetOverdrawBottomHeight(float overdraw_bottom_height) { 1910 if (overdraw_bottom_height == overdraw_bottom_height_) 1911 return; 1912 overdraw_bottom_height_ = overdraw_bottom_height; 1913 1914 UpdateMaxScrollOffset(); 1915 SetFullRootLayerDamage(); 1916 } 1917 1918 void LayerTreeHostImpl::SetOverhangUIResource( 1919 UIResourceId overhang_ui_resource_id, 1920 gfx::Size overhang_ui_resource_size) { 1921 overhang_ui_resource_id_ = overhang_ui_resource_id; 1922 overhang_ui_resource_size_ = overhang_ui_resource_size; 1923 } 1924 1925 void LayerTreeHostImpl::SetDeviceScaleFactor(float device_scale_factor) { 1926 if (device_scale_factor == device_scale_factor_) 1927 return; 1928 device_scale_factor_ = device_scale_factor; 1929 1930 UpdateMaxScrollOffset(); 1931 SetFullRootLayerDamage(); 1932 } 1933 1934 gfx::Size LayerTreeHostImpl::DrawViewportSize() const { 1935 return DeviceViewport().size(); 1936 } 1937 1938 gfx::Rect LayerTreeHostImpl::DeviceViewport() const { 1939 if (external_viewport_.IsEmpty()) 1940 return gfx::Rect(device_viewport_size_); 1941 1942 return external_viewport_; 1943 } 1944 1945 gfx::Rect LayerTreeHostImpl::DeviceClip() const { 1946 if (external_clip_.IsEmpty()) 1947 return DeviceViewport(); 1948 1949 return external_clip_; 1950 } 1951 1952 const gfx::Transform& LayerTreeHostImpl::DrawTransform() const { 1953 return external_transform_; 1954 } 1955 1956 void LayerTreeHostImpl::UpdateMaxScrollOffset() { 1957 active_tree_->UpdateMaxScrollOffset(); 1958 } 1959 1960 void LayerTreeHostImpl::DidChangeTopControlsPosition() { 1961 SetNeedsRedraw(); 1962 active_tree_->set_needs_update_draw_properties(); 1963 SetFullRootLayerDamage(); 1964 } 1965 1966 bool LayerTreeHostImpl::EnsureRenderSurfaceLayerList() { 1967 active_tree_->UpdateDrawProperties(); 1968 return !active_tree_->RenderSurfaceLayerList().empty(); 1969 } 1970 1971 void LayerTreeHostImpl::BindToClient(InputHandlerClient* client) { 1972 DCHECK(input_handler_client_ == NULL); 1973 input_handler_client_ = client; 1974 } 1975 1976 static LayerImpl* NextScrollLayer(LayerImpl* layer) { 1977 if (LayerImpl* scroll_parent = layer->scroll_parent()) 1978 return scroll_parent; 1979 return layer->parent(); 1980 } 1981 1982 LayerImpl* LayerTreeHostImpl::FindScrollLayerForDeviceViewportPoint( 1983 gfx::PointF device_viewport_point, InputHandler::ScrollInputType type, 1984 LayerImpl* layer_impl, bool* scroll_on_main_thread) const { 1985 DCHECK(scroll_on_main_thread); 1986 1987 // Walk up the hierarchy and look for a scrollable layer. 1988 LayerImpl* potentially_scrolling_layer_impl = 0; 1989 for (; layer_impl; layer_impl = NextScrollLayer(layer_impl)) { 1990 // The content layer can also block attempts to scroll outside the main 1991 // thread. 1992 ScrollStatus status = layer_impl->TryScroll(device_viewport_point, type); 1993 if (status == ScrollOnMainThread) { 1994 *scroll_on_main_thread = true; 1995 return NULL; 1996 } 1997 1998 LayerImpl* scroll_layer_impl = FindScrollLayerForContentLayer(layer_impl); 1999 if (!scroll_layer_impl) 2000 continue; 2001 2002 status = scroll_layer_impl->TryScroll(device_viewport_point, type); 2003 // If any layer wants to divert the scroll event to the main thread, abort. 2004 if (status == ScrollOnMainThread) { 2005 *scroll_on_main_thread = true; 2006 return NULL; 2007 } 2008 2009 if (status == ScrollStarted && !potentially_scrolling_layer_impl) 2010 potentially_scrolling_layer_impl = scroll_layer_impl; 2011 } 2012 2013 // When hiding top controls is enabled and the controls are hidden or 2014 // overlaying the content, force scrolls to be enabled on the root layer to 2015 // allow bringing the top controls back into view. 2016 if (!potentially_scrolling_layer_impl && top_controls_manager_ && 2017 top_controls_manager_->content_top_offset() != 2018 settings_.top_controls_height) { 2019 potentially_scrolling_layer_impl = RootScrollLayer(); 2020 } 2021 2022 return potentially_scrolling_layer_impl; 2023 } 2024 2025 InputHandler::ScrollStatus LayerTreeHostImpl::ScrollBegin( 2026 gfx::Point viewport_point, InputHandler::ScrollInputType type) { 2027 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBegin"); 2028 2029 if (top_controls_manager_) 2030 top_controls_manager_->ScrollBegin(); 2031 2032 DCHECK(!CurrentlyScrollingLayer()); 2033 ClearCurrentlyScrollingLayer(); 2034 2035 if (!EnsureRenderSurfaceLayerList()) 2036 return ScrollIgnored; 2037 2038 gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point, 2039 device_scale_factor_); 2040 LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint( 2041 device_viewport_point, 2042 active_tree_->RenderSurfaceLayerList()); 2043 bool scroll_on_main_thread = false; 2044 LayerImpl* potentially_scrolling_layer_impl = 2045 FindScrollLayerForDeviceViewportPoint(device_viewport_point, type, 2046 layer_impl, &scroll_on_main_thread); 2047 2048 if (scroll_on_main_thread) { 2049 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", true); 2050 return ScrollOnMainThread; 2051 } 2052 2053 // If we want to send a DidOverscroll for this scroll it can't be ignored. 2054 if (!potentially_scrolling_layer_impl && settings_.always_overscroll) 2055 potentially_scrolling_layer_impl = RootScrollLayer(); 2056 2057 if (potentially_scrolling_layer_impl) { 2058 active_tree_->SetCurrentlyScrollingLayer( 2059 potentially_scrolling_layer_impl); 2060 should_bubble_scrolls_ = (type != NonBubblingGesture); 2061 last_scroll_did_bubble_ = false; 2062 wheel_scrolling_ = (type == Wheel); 2063 client_->RenewTreePriority(); 2064 UMA_HISTOGRAM_BOOLEAN("TryScroll.SlowScroll", false); 2065 return ScrollStarted; 2066 } 2067 return ScrollIgnored; 2068 } 2069 2070 gfx::Vector2dF LayerTreeHostImpl::ScrollLayerWithViewportSpaceDelta( 2071 LayerImpl* layer_impl, 2072 float scale_from_viewport_to_screen_space, 2073 gfx::PointF viewport_point, 2074 gfx::Vector2dF viewport_delta) { 2075 // Layers with non-invertible screen space transforms should not have passed 2076 // the scroll hit test in the first place. 2077 DCHECK(layer_impl->screen_space_transform().IsInvertible()); 2078 gfx::Transform inverse_screen_space_transform( 2079 gfx::Transform::kSkipInitialization); 2080 bool did_invert = layer_impl->screen_space_transform().GetInverse( 2081 &inverse_screen_space_transform); 2082 // TODO(shawnsingh): With the advent of impl-side crolling for non-root 2083 // layers, we may need to explicitly handle uninvertible transforms here. 2084 DCHECK(did_invert); 2085 2086 gfx::PointF screen_space_point = 2087 gfx::ScalePoint(viewport_point, scale_from_viewport_to_screen_space); 2088 2089 gfx::Vector2dF screen_space_delta = viewport_delta; 2090 screen_space_delta.Scale(scale_from_viewport_to_screen_space); 2091 2092 // First project the scroll start and end points to local layer space to find 2093 // the scroll delta in layer coordinates. 2094 bool start_clipped, end_clipped; 2095 gfx::PointF screen_space_end_point = screen_space_point + screen_space_delta; 2096 gfx::PointF local_start_point = 2097 MathUtil::ProjectPoint(inverse_screen_space_transform, 2098 screen_space_point, 2099 &start_clipped); 2100 gfx::PointF local_end_point = 2101 MathUtil::ProjectPoint(inverse_screen_space_transform, 2102 screen_space_end_point, 2103 &end_clipped); 2104 2105 // In general scroll point coordinates should not get clipped. 2106 DCHECK(!start_clipped); 2107 DCHECK(!end_clipped); 2108 if (start_clipped || end_clipped) 2109 return gfx::Vector2dF(); 2110 2111 // local_start_point and local_end_point are in content space but we want to 2112 // move them to layer space for scrolling. 2113 float width_scale = 1.f / layer_impl->contents_scale_x(); 2114 float height_scale = 1.f / layer_impl->contents_scale_y(); 2115 local_start_point.Scale(width_scale, height_scale); 2116 local_end_point.Scale(width_scale, height_scale); 2117 2118 // Apply the scroll delta. 2119 gfx::Vector2dF previous_delta = layer_impl->ScrollDelta(); 2120 layer_impl->ScrollBy(local_end_point - local_start_point); 2121 2122 // Get the end point in the layer's content space so we can apply its 2123 // ScreenSpaceTransform. 2124 gfx::PointF actual_local_end_point = local_start_point + 2125 layer_impl->ScrollDelta() - 2126 previous_delta; 2127 gfx::PointF actual_local_content_end_point = 2128 gfx::ScalePoint(actual_local_end_point, 2129 1.f / width_scale, 2130 1.f / height_scale); 2131 2132 // Calculate the applied scroll delta in viewport space coordinates. 2133 gfx::PointF actual_screen_space_end_point = 2134 MathUtil::MapPoint(layer_impl->screen_space_transform(), 2135 actual_local_content_end_point, 2136 &end_clipped); 2137 DCHECK(!end_clipped); 2138 if (end_clipped) 2139 return gfx::Vector2dF(); 2140 gfx::PointF actual_viewport_end_point = 2141 gfx::ScalePoint(actual_screen_space_end_point, 2142 1.f / scale_from_viewport_to_screen_space); 2143 return actual_viewport_end_point - viewport_point; 2144 } 2145 2146 static gfx::Vector2dF ScrollLayerWithLocalDelta(LayerImpl* layer_impl, 2147 gfx::Vector2dF local_delta) { 2148 gfx::Vector2dF previous_delta(layer_impl->ScrollDelta()); 2149 layer_impl->ScrollBy(local_delta); 2150 return layer_impl->ScrollDelta() - previous_delta; 2151 } 2152 2153 bool LayerTreeHostImpl::ScrollBy(gfx::Point viewport_point, 2154 gfx::Vector2dF scroll_delta) { 2155 TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); 2156 if (!CurrentlyScrollingLayer()) 2157 return false; 2158 2159 gfx::Vector2dF pending_delta = scroll_delta; 2160 gfx::Vector2dF unused_root_delta; 2161 bool did_scroll_x = false; 2162 bool did_scroll_y = false; 2163 bool consume_by_top_controls = top_controls_manager_ && 2164 (CurrentlyScrollingLayer() == RootScrollLayer() || scroll_delta.y() < 0); 2165 last_scroll_did_bubble_ = false; 2166 2167 for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); 2168 layer_impl; 2169 layer_impl = layer_impl->parent()) { 2170 if (!layer_impl->scrollable()) 2171 continue; 2172 2173 if (layer_impl == RootScrollLayer()) { 2174 // Only allow bubble scrolling when the scroll is in the direction to make 2175 // the top controls visible. 2176 if (consume_by_top_controls && layer_impl == RootScrollLayer()) { 2177 pending_delta = top_controls_manager_->ScrollBy(pending_delta); 2178 UpdateMaxScrollOffset(); 2179 } 2180 // Track root layer deltas for reporting overscroll. 2181 unused_root_delta = pending_delta; 2182 } 2183 2184 gfx::Vector2dF applied_delta; 2185 // Gesture events need to be transformed from viewport coordinates to local 2186 // layer coordinates so that the scrolling contents exactly follow the 2187 // user's finger. In contrast, wheel events represent a fixed amount of 2188 // scrolling so we can just apply them directly. 2189 if (!wheel_scrolling_) { 2190 float scale_from_viewport_to_screen_space = device_scale_factor_; 2191 applied_delta = 2192 ScrollLayerWithViewportSpaceDelta(layer_impl, 2193 scale_from_viewport_to_screen_space, 2194 viewport_point, pending_delta); 2195 } else { 2196 applied_delta = ScrollLayerWithLocalDelta(layer_impl, pending_delta); 2197 } 2198 2199 // If the layer wasn't able to move, try the next one in the hierarchy. 2200 float move_threshold = 0.1f; 2201 bool did_move_layer_x = std::abs(applied_delta.x()) > move_threshold; 2202 bool did_move_layer_y = std::abs(applied_delta.y()) > move_threshold; 2203 did_scroll_x |= did_move_layer_x; 2204 did_scroll_y |= did_move_layer_y; 2205 if (!did_move_layer_x && !did_move_layer_y) { 2206 if (!did_lock_scrolling_layer_) 2207 continue; 2208 2209 if (should_bubble_scrolls_) { 2210 last_scroll_did_bubble_ = true; 2211 continue; 2212 } 2213 2214 break; 2215 } 2216 2217 if (layer_impl == RootScrollLayer()) 2218 unused_root_delta.Subtract(applied_delta); 2219 2220 did_lock_scrolling_layer_ = true; 2221 if (!should_bubble_scrolls_) { 2222 active_tree_->SetCurrentlyScrollingLayer(layer_impl); 2223 break; 2224 } 2225 2226 // If the applied delta is within 45 degrees of the input delta, bail out to 2227 // make it easier to scroll just one layer in one direction without 2228 // affecting any of its parents. 2229 float angle_threshold = 45; 2230 if (MathUtil::SmallestAngleBetweenVectors( 2231 applied_delta, pending_delta) < angle_threshold) { 2232 pending_delta = gfx::Vector2d(); 2233 break; 2234 } 2235 2236 // Allow further movement only on an axis perpendicular to the direction in 2237 // which the layer moved. 2238 gfx::Vector2dF perpendicular_axis(-applied_delta.y(), applied_delta.x()); 2239 pending_delta = MathUtil::ProjectVector(pending_delta, perpendicular_axis); 2240 2241 if (gfx::ToRoundedVector2d(pending_delta).IsZero()) 2242 break; 2243 } 2244 2245 bool did_scroll = did_scroll_x || did_scroll_y; 2246 if (did_scroll) { 2247 client_->SetNeedsCommitOnImplThread(); 2248 SetNeedsRedraw(); 2249 client_->RenewTreePriority(); 2250 } 2251 2252 // Scrolling along an axis resets accumulated root overscroll for that axis. 2253 if (did_scroll_x) 2254 accumulated_root_overscroll_.set_x(0); 2255 if (did_scroll_y) 2256 accumulated_root_overscroll_.set_y(0); 2257 2258 accumulated_root_overscroll_ += unused_root_delta; 2259 bool did_overscroll = !gfx::ToRoundedVector2d(unused_root_delta).IsZero(); 2260 if (did_overscroll && input_handler_client_) { 2261 DidOverscrollParams params; 2262 params.accumulated_overscroll = accumulated_root_overscroll_; 2263 params.latest_overscroll_delta = unused_root_delta; 2264 params.current_fling_velocity = current_fling_velocity_; 2265 input_handler_client_->DidOverscroll(params); 2266 } 2267 2268 return did_scroll; 2269 } 2270 2271 // This implements scrolling by page as described here: 2272 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms645601(v=vs.85).aspx#_win32_The_Mouse_Wheel 2273 // for events with WHEEL_PAGESCROLL set. 2274 bool LayerTreeHostImpl::ScrollVerticallyByPage(gfx::Point viewport_point, 2275 ScrollDirection direction) { 2276 DCHECK(wheel_scrolling_); 2277 2278 for (LayerImpl* layer_impl = CurrentlyScrollingLayer(); 2279 layer_impl; 2280 layer_impl = layer_impl->parent()) { 2281 if (!layer_impl->scrollable()) 2282 continue; 2283 2284 if (!layer_impl->vertical_scrollbar_layer()) 2285 continue; 2286 2287 float height = layer_impl->vertical_scrollbar_layer()->bounds().height(); 2288 2289 // These magical values match WebKit and are designed to scroll nearly the 2290 // entire visible content height but leave a bit of overlap. 2291 float page = std::max(height * 0.875f, 1.f); 2292 if (direction == SCROLL_BACKWARD) 2293 page = -page; 2294 2295 gfx::Vector2dF delta = gfx::Vector2dF(0.f, page); 2296 2297 gfx::Vector2dF applied_delta = ScrollLayerWithLocalDelta(layer_impl, delta); 2298 2299 if (!applied_delta.IsZero()) { 2300 client_->SetNeedsCommitOnImplThread(); 2301 SetNeedsRedraw(); 2302 client_->RenewTreePriority(); 2303 return true; 2304 } 2305 2306 active_tree_->SetCurrentlyScrollingLayer(layer_impl); 2307 } 2308 2309 return false; 2310 } 2311 2312 void LayerTreeHostImpl::SetRootLayerScrollOffsetDelegate( 2313 LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) { 2314 root_layer_scroll_offset_delegate_ = root_layer_scroll_offset_delegate; 2315 active_tree_->SetRootLayerScrollOffsetDelegate( 2316 root_layer_scroll_offset_delegate_); 2317 } 2318 2319 void LayerTreeHostImpl::OnRootLayerDelegatedScrollOffsetChanged() { 2320 DCHECK(root_layer_scroll_offset_delegate_ != NULL); 2321 client_->SetNeedsCommitOnImplThread(); 2322 } 2323 2324 void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() { 2325 active_tree_->ClearCurrentlyScrollingLayer(); 2326 did_lock_scrolling_layer_ = false; 2327 accumulated_root_overscroll_ = gfx::Vector2dF(); 2328 current_fling_velocity_ = gfx::Vector2dF(); 2329 } 2330 2331 void LayerTreeHostImpl::ScrollEnd() { 2332 if (top_controls_manager_) 2333 top_controls_manager_->ScrollEnd(); 2334 ClearCurrentlyScrollingLayer(); 2335 StartScrollbarAnimation(); 2336 } 2337 2338 InputHandler::ScrollStatus LayerTreeHostImpl::FlingScrollBegin() { 2339 if (!active_tree_->CurrentlyScrollingLayer()) 2340 return ScrollIgnored; 2341 2342 if (settings_.ignore_root_layer_flings && 2343 active_tree_->CurrentlyScrollingLayer() == 2344 active_tree_->RootScrollLayer()) { 2345 ClearCurrentlyScrollingLayer(); 2346 return ScrollIgnored; 2347 } 2348 2349 if (!wheel_scrolling_) 2350 should_bubble_scrolls_ = last_scroll_did_bubble_; 2351 2352 return ScrollStarted; 2353 } 2354 2355 void LayerTreeHostImpl::NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) { 2356 current_fling_velocity_ = velocity; 2357 } 2358 2359 float LayerTreeHostImpl::DeviceSpaceDistanceToLayer( 2360 gfx::PointF device_viewport_point, 2361 LayerImpl* layer_impl) { 2362 if (!layer_impl) 2363 return std::numeric_limits<float>::max(); 2364 2365 gfx::Rect layer_impl_bounds( 2366 layer_impl->content_bounds()); 2367 2368 gfx::RectF device_viewport_layer_impl_bounds = MathUtil::MapClippedRect( 2369 layer_impl->screen_space_transform(), 2370 layer_impl_bounds); 2371 2372 return device_viewport_layer_impl_bounds.ManhattanDistanceToPoint( 2373 device_viewport_point); 2374 } 2375 2376 void LayerTreeHostImpl::MouseMoveAt(gfx::Point viewport_point) { 2377 if (!EnsureRenderSurfaceLayerList()) 2378 return; 2379 2380 gfx::PointF device_viewport_point = gfx::ScalePoint(viewport_point, 2381 device_scale_factor_); 2382 2383 LayerImpl* layer_impl = LayerTreeHostCommon::FindLayerThatIsHitByPoint( 2384 device_viewport_point, 2385 active_tree_->RenderSurfaceLayerList()); 2386 if (HandleMouseOverScrollbar(layer_impl, device_viewport_point)) 2387 return; 2388 2389 if (scroll_layer_id_when_mouse_over_scrollbar_) { 2390 LayerImpl* scroll_layer_impl = active_tree_->LayerById( 2391 scroll_layer_id_when_mouse_over_scrollbar_); 2392 2393 ScrollbarAnimationController* animation_controller = 2394 scroll_layer_impl->scrollbar_animation_controller(); 2395 if (animation_controller) { 2396 animation_controller->DidMouseMoveOffScrollbar( 2397 CurrentPhysicalTimeTicks()); 2398 StartScrollbarAnimation(); 2399 } 2400 scroll_layer_id_when_mouse_over_scrollbar_ = 0; 2401 } 2402 2403 bool scroll_on_main_thread = false; 2404 LayerImpl* scroll_layer_impl = FindScrollLayerForDeviceViewportPoint( 2405 device_viewport_point, InputHandler::Gesture, layer_impl, 2406 &scroll_on_main_thread); 2407 if (scroll_on_main_thread || !scroll_layer_impl) 2408 return; 2409 2410 ScrollbarAnimationController* animation_controller = 2411 scroll_layer_impl->scrollbar_animation_controller(); 2412 if (!animation_controller) 2413 return; 2414 2415 float distance_to_scrollbar = std::min( 2416 DeviceSpaceDistanceToLayer(device_viewport_point, 2417 scroll_layer_impl->horizontal_scrollbar_layer()), 2418 DeviceSpaceDistanceToLayer(device_viewport_point, 2419 scroll_layer_impl->vertical_scrollbar_layer())); 2420 2421 bool should_animate = animation_controller->DidMouseMoveNear( 2422 CurrentPhysicalTimeTicks(), distance_to_scrollbar / device_scale_factor_); 2423 if (should_animate) 2424 StartScrollbarAnimation(); 2425 } 2426 2427 bool LayerTreeHostImpl::HandleMouseOverScrollbar(LayerImpl* layer_impl, 2428 gfx::PointF device_viewport_point) { 2429 if (layer_impl && layer_impl->ToScrollbarLayer()) { 2430 int scroll_layer_id = layer_impl->ToScrollbarLayer()->ScrollLayerId(); 2431 layer_impl = active_tree_->LayerById(scroll_layer_id); 2432 if (layer_impl && layer_impl->scrollbar_animation_controller()) { 2433 scroll_layer_id_when_mouse_over_scrollbar_ = scroll_layer_id; 2434 bool should_animate = 2435 layer_impl->scrollbar_animation_controller()->DidMouseMoveNear( 2436 CurrentPhysicalTimeTicks(), 0); 2437 if (should_animate) 2438 StartScrollbarAnimation(); 2439 } else { 2440 scroll_layer_id_when_mouse_over_scrollbar_ = 0; 2441 } 2442 2443 return true; 2444 } 2445 2446 return false; 2447 } 2448 2449 void LayerTreeHostImpl::PinchGestureBegin() { 2450 pinch_gesture_active_ = true; 2451 previous_pinch_anchor_ = gfx::Point(); 2452 client_->RenewTreePriority(); 2453 pinch_gesture_end_should_clear_scrolling_layer_ = !CurrentlyScrollingLayer(); 2454 active_tree_->SetCurrentlyScrollingLayer(RootScrollLayer()); 2455 if (top_controls_manager_) 2456 top_controls_manager_->PinchBegin(); 2457 } 2458 2459 void LayerTreeHostImpl::PinchGestureUpdate(float magnify_delta, 2460 gfx::Point anchor) { 2461 TRACE_EVENT0("cc", "LayerTreeHostImpl::PinchGestureUpdate"); 2462 2463 if (!RootScrollLayer()) 2464 return; 2465 2466 // Keep the center-of-pinch anchor specified by (x, y) in a stable 2467 // position over the course of the magnify. 2468 float page_scale_delta = active_tree_->page_scale_delta(); 2469 gfx::PointF previous_scale_anchor = 2470 gfx::ScalePoint(anchor, 1.f / page_scale_delta); 2471 active_tree_->SetPageScaleDelta(page_scale_delta * magnify_delta); 2472 page_scale_delta = active_tree_->page_scale_delta(); 2473 gfx::PointF new_scale_anchor = 2474 gfx::ScalePoint(anchor, 1.f / page_scale_delta); 2475 gfx::Vector2dF move = previous_scale_anchor - new_scale_anchor; 2476 2477 previous_pinch_anchor_ = anchor; 2478 2479 move.Scale(1 / active_tree_->page_scale_factor()); 2480 2481 RootScrollLayer()->ScrollBy(move); 2482 2483 client_->SetNeedsCommitOnImplThread(); 2484 SetNeedsRedraw(); 2485 client_->RenewTreePriority(); 2486 } 2487 2488 void LayerTreeHostImpl::PinchGestureEnd() { 2489 pinch_gesture_active_ = false; 2490 if (pinch_gesture_end_should_clear_scrolling_layer_) { 2491 pinch_gesture_end_should_clear_scrolling_layer_ = false; 2492 ClearCurrentlyScrollingLayer(); 2493 } 2494 if (top_controls_manager_) 2495 top_controls_manager_->PinchEnd(); 2496 client_->SetNeedsCommitOnImplThread(); 2497 } 2498 2499 static void CollectScrollDeltas(ScrollAndScaleSet* scroll_info, 2500 LayerImpl* layer_impl) { 2501 if (!layer_impl) 2502 return; 2503 2504 gfx::Vector2d scroll_delta = 2505 gfx::ToFlooredVector2d(layer_impl->ScrollDelta()); 2506 if (!scroll_delta.IsZero()) { 2507 LayerTreeHostCommon::ScrollUpdateInfo scroll; 2508 scroll.layer_id = layer_impl->id(); 2509 scroll.scroll_delta = scroll_delta; 2510 scroll_info->scrolls.push_back(scroll); 2511 layer_impl->SetSentScrollDelta(scroll_delta); 2512 } 2513 2514 for (size_t i = 0; i < layer_impl->children().size(); ++i) 2515 CollectScrollDeltas(scroll_info, layer_impl->children()[i]); 2516 } 2517 2518 scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::ProcessScrollDeltas() { 2519 scoped_ptr<ScrollAndScaleSet> scroll_info(new ScrollAndScaleSet()); 2520 2521 CollectScrollDeltas(scroll_info.get(), active_tree_->root_layer()); 2522 scroll_info->page_scale_delta = active_tree_->page_scale_delta(); 2523 active_tree_->set_sent_page_scale_delta(scroll_info->page_scale_delta); 2524 2525 return scroll_info.Pass(); 2526 } 2527 2528 void LayerTreeHostImpl::SetFullRootLayerDamage() { 2529 SetViewportDamage(gfx::Rect(DrawViewportSize())); 2530 } 2531 2532 void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks time) { 2533 if (!page_scale_animation_ || !RootScrollLayer()) 2534 return; 2535 2536 double monotonic_time = (time - base::TimeTicks()).InSecondsF(); 2537 gfx::Vector2dF scroll_total = RootScrollLayer()->scroll_offset() + 2538 RootScrollLayer()->ScrollDelta(); 2539 2540 if (!page_scale_animation_->IsAnimationStarted()) 2541 page_scale_animation_->StartAnimation(monotonic_time); 2542 2543 active_tree_->SetPageScaleDelta( 2544 page_scale_animation_->PageScaleFactorAtTime(monotonic_time) / 2545 active_tree_->page_scale_factor()); 2546 gfx::Vector2dF next_scroll = 2547 page_scale_animation_->ScrollOffsetAtTime(monotonic_time); 2548 2549 RootScrollLayer()->ScrollBy(next_scroll - scroll_total); 2550 SetNeedsRedraw(); 2551 2552 if (page_scale_animation_->IsAnimationCompleteAtTime(monotonic_time)) { 2553 page_scale_animation_.reset(); 2554 client_->SetNeedsCommitOnImplThread(); 2555 client_->RenewTreePriority(); 2556 } 2557 } 2558 2559 void LayerTreeHostImpl::AnimateTopControls(base::TimeTicks time) { 2560 if (!top_controls_manager_ || !RootScrollLayer()) 2561 return; 2562 gfx::Vector2dF scroll = top_controls_manager_->Animate(time); 2563 UpdateMaxScrollOffset(); 2564 if (RootScrollLayer()->TotalScrollOffset().y() == 0.f) 2565 return; 2566 RootScrollLayer()->ScrollBy(gfx::ScaleVector2d( 2567 scroll, 1.f / active_tree_->total_page_scale_factor())); 2568 } 2569 2570 void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time, 2571 base::Time wall_clock_time) { 2572 if (!settings_.accelerated_animation_enabled || 2573 animation_registrar_->active_animation_controllers().empty() || 2574 !active_tree_->root_layer()) 2575 return; 2576 2577 TRACE_EVENT0("cc", "LayerTreeHostImpl::AnimateLayers"); 2578 2579 last_animation_time_ = wall_clock_time; 2580 double monotonic_seconds = (monotonic_time - base::TimeTicks()).InSecondsF(); 2581 2582 AnimationRegistrar::AnimationControllerMap copy = 2583 animation_registrar_->active_animation_controllers(); 2584 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); 2585 iter != copy.end(); 2586 ++iter) 2587 (*iter).second->Animate(monotonic_seconds); 2588 2589 SetNeedsRedraw(); 2590 } 2591 2592 void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) { 2593 if (!settings_.accelerated_animation_enabled || 2594 animation_registrar_->active_animation_controllers().empty() || 2595 !active_tree_->root_layer()) 2596 return; 2597 2598 TRACE_EVENT0("cc", "LayerTreeHostImpl::UpdateAnimationState"); 2599 scoped_ptr<AnimationEventsVector> events = 2600 make_scoped_ptr(new AnimationEventsVector); 2601 AnimationRegistrar::AnimationControllerMap copy = 2602 animation_registrar_->active_animation_controllers(); 2603 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); 2604 iter != copy.end(); 2605 ++iter) 2606 (*iter).second->UpdateState(start_ready_animations, events.get()); 2607 2608 if (!events->empty()) { 2609 client_->PostAnimationEventsToMainThreadOnImplThread(events.Pass(), 2610 last_animation_time_); 2611 } 2612 } 2613 2614 base::TimeDelta LayerTreeHostImpl::LowFrequencyAnimationInterval() const { 2615 return base::TimeDelta::FromSeconds(1); 2616 } 2617 2618 void LayerTreeHostImpl::SendReleaseResourcesRecursive(LayerImpl* current) { 2619 DCHECK(current); 2620 // TODO(boliu): Rename DidLoseOutputSurface to ReleaseResources. 2621 current->DidLoseOutputSurface(); 2622 if (current->mask_layer()) 2623 SendReleaseResourcesRecursive(current->mask_layer()); 2624 if (current->replica_layer()) 2625 SendReleaseResourcesRecursive(current->replica_layer()); 2626 for (size_t i = 0; i < current->children().size(); ++i) 2627 SendReleaseResourcesRecursive(current->children()[i]); 2628 } 2629 2630 void LayerTreeHostImpl::SetOffscreenContextProvider( 2631 const scoped_refptr<ContextProvider>& offscreen_context_provider) { 2632 if (!offscreen_context_provider.get()) { 2633 offscreen_context_provider_ = NULL; 2634 return; 2635 } 2636 2637 if (!offscreen_context_provider->BindToCurrentThread()) { 2638 offscreen_context_provider_ = NULL; 2639 return; 2640 } 2641 2642 offscreen_context_provider_ = offscreen_context_provider; 2643 } 2644 2645 std::string LayerTreeHostImpl::LayerTreeAsJson() const { 2646 std::string str; 2647 if (active_tree_->root_layer()) { 2648 scoped_ptr<base::Value> json(active_tree_->root_layer()->LayerTreeAsJson()); 2649 base::JSONWriter::WriteWithOptions( 2650 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str); 2651 } 2652 return str; 2653 } 2654 2655 int LayerTreeHostImpl::SourceAnimationFrameNumber() const { 2656 return fps_counter_->current_frame_number(); 2657 } 2658 2659 void LayerTreeHostImpl::SendManagedMemoryStats( 2660 size_t memory_visible_bytes, 2661 size_t memory_visible_and_nearby_bytes, 2662 size_t memory_use_bytes) { 2663 if (!renderer_) 2664 return; 2665 2666 // Round the numbers being sent up to the next 8MB, to throttle the rate 2667 // at which we spam the GPU process. 2668 static const size_t rounding_step = 8 * 1024 * 1024; 2669 memory_visible_bytes = RoundUp(memory_visible_bytes, rounding_step); 2670 memory_visible_and_nearby_bytes = RoundUp(memory_visible_and_nearby_bytes, 2671 rounding_step); 2672 memory_use_bytes = RoundUp(memory_use_bytes, rounding_step); 2673 if (last_sent_memory_visible_bytes_ == memory_visible_bytes && 2674 last_sent_memory_visible_and_nearby_bytes_ == 2675 memory_visible_and_nearby_bytes && 2676 last_sent_memory_use_bytes_ == memory_use_bytes) { 2677 return; 2678 } 2679 last_sent_memory_visible_bytes_ = memory_visible_bytes; 2680 last_sent_memory_visible_and_nearby_bytes_ = memory_visible_and_nearby_bytes; 2681 last_sent_memory_use_bytes_ = memory_use_bytes; 2682 2683 renderer_->SendManagedMemoryStats(last_sent_memory_visible_bytes_, 2684 last_sent_memory_visible_and_nearby_bytes_, 2685 last_sent_memory_use_bytes_); 2686 } 2687 2688 void LayerTreeHostImpl::AnimateScrollbars(base::TimeTicks time) { 2689 AnimateScrollbarsRecursive(active_tree_->root_layer(), time); 2690 } 2691 2692 void LayerTreeHostImpl::AnimateScrollbarsRecursive(LayerImpl* layer, 2693 base::TimeTicks time) { 2694 if (!layer) 2695 return; 2696 2697 ScrollbarAnimationController* scrollbar_controller = 2698 layer->scrollbar_animation_controller(); 2699 if (scrollbar_controller && scrollbar_controller->Animate(time)) { 2700 TRACE_EVENT_INSTANT0( 2701 "cc", "LayerTreeHostImpl::SetNeedsRedraw due to AnimateScrollbars", 2702 TRACE_EVENT_SCOPE_THREAD); 2703 SetNeedsRedraw(); 2704 } 2705 2706 for (size_t i = 0; i < layer->children().size(); ++i) 2707 AnimateScrollbarsRecursive(layer->children()[i], time); 2708 } 2709 2710 void LayerTreeHostImpl::StartScrollbarAnimation() { 2711 TRACE_EVENT0("cc", "LayerTreeHostImpl::StartScrollbarAnimation"); 2712 StartScrollbarAnimationRecursive(RootLayer(), CurrentPhysicalTimeTicks()); 2713 } 2714 2715 void LayerTreeHostImpl::StartScrollbarAnimationRecursive(LayerImpl* layer, 2716 base::TimeTicks time) { 2717 if (!layer) 2718 return; 2719 2720 ScrollbarAnimationController* scrollbar_controller = 2721 layer->scrollbar_animation_controller(); 2722 if (scrollbar_controller && scrollbar_controller->IsAnimating()) { 2723 base::TimeDelta delay = scrollbar_controller->DelayBeforeStart(time); 2724 if (delay > base::TimeDelta()) 2725 client_->RequestScrollbarAnimationOnImplThread(delay); 2726 else if (scrollbar_controller->Animate(time)) 2727 SetNeedsRedraw(); 2728 } 2729 2730 for (size_t i = 0; i < layer->children().size(); ++i) 2731 StartScrollbarAnimationRecursive(layer->children()[i], time); 2732 } 2733 2734 void LayerTreeHostImpl::SetTreePriority(TreePriority priority) { 2735 if (!tile_manager_) 2736 return; 2737 2738 if (global_tile_state_.tree_priority == priority) 2739 return; 2740 global_tile_state_.tree_priority = priority; 2741 DidModifyTilePriorities(); 2742 } 2743 2744 void LayerTreeHostImpl::ResetCurrentFrameTimeForNextFrame() { 2745 current_frame_timeticks_ = base::TimeTicks(); 2746 current_frame_time_ = base::Time(); 2747 } 2748 2749 void LayerTreeHostImpl::UpdateCurrentFrameTime(base::TimeTicks* ticks, 2750 base::Time* now) const { 2751 if (ticks->is_null()) { 2752 DCHECK(now->is_null()); 2753 *ticks = CurrentPhysicalTimeTicks(); 2754 *now = base::Time::Now(); 2755 } 2756 } 2757 2758 base::TimeTicks LayerTreeHostImpl::CurrentFrameTimeTicks() { 2759 UpdateCurrentFrameTime(¤t_frame_timeticks_, ¤t_frame_time_); 2760 return current_frame_timeticks_; 2761 } 2762 2763 base::Time LayerTreeHostImpl::CurrentFrameTime() { 2764 UpdateCurrentFrameTime(¤t_frame_timeticks_, ¤t_frame_time_); 2765 return current_frame_time_; 2766 } 2767 2768 base::TimeTicks LayerTreeHostImpl::CurrentPhysicalTimeTicks() const { 2769 return gfx::FrameTime::Now(); 2770 } 2771 2772 scoped_ptr<base::Value> LayerTreeHostImpl::AsValueWithFrame( 2773 FrameData* frame) const { 2774 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); 2775 if (this->pending_tree_) 2776 state->Set("activation_state", ActivationStateAsValue().release()); 2777 state->Set("device_viewport_size", 2778 MathUtil::AsValue(device_viewport_size_).release()); 2779 if (tile_manager_) 2780 state->Set("tiles", tile_manager_->AllTilesAsValue().release()); 2781 state->Set("active_tree", active_tree_->AsValue().release()); 2782 if (pending_tree_) 2783 state->Set("pending_tree", pending_tree_->AsValue().release()); 2784 if (frame) 2785 state->Set("frame", frame->AsValue().release()); 2786 return state.PassAs<base::Value>(); 2787 } 2788 2789 scoped_ptr<base::Value> LayerTreeHostImpl::ActivationStateAsValue() const { 2790 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue()); 2791 state->Set("lthi", TracedValue::CreateIDRef(this).release()); 2792 if (tile_manager_) 2793 state->Set("tile_manager", tile_manager_->BasicStateAsValue().release()); 2794 return state.PassAs<base::Value>(); 2795 } 2796 2797 void LayerTreeHostImpl::SetDebugState( 2798 const LayerTreeDebugState& new_debug_state) { 2799 if (LayerTreeDebugState::Equal(debug_state_, new_debug_state)) 2800 return; 2801 if (debug_state_.continuous_painting != new_debug_state.continuous_painting) 2802 paint_time_counter_->ClearHistory(); 2803 2804 debug_state_ = new_debug_state; 2805 UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy()); 2806 SetFullRootLayerDamage(); 2807 } 2808 2809 void LayerTreeHostImpl::CreateUIResource(UIResourceId uid, 2810 const UIResourceBitmap& bitmap) { 2811 DCHECK_GT(uid, 0); 2812 2813 GLint wrap_mode = 0; 2814 switch (bitmap.GetWrapMode()) { 2815 case UIResourceBitmap::CLAMP_TO_EDGE: 2816 wrap_mode = GL_CLAMP_TO_EDGE; 2817 break; 2818 case UIResourceBitmap::REPEAT: 2819 wrap_mode = GL_REPEAT; 2820 break; 2821 } 2822 2823 // Allow for multiple creation requests with the same UIResourceId. The 2824 // previous resource is simply deleted. 2825 ResourceProvider::ResourceId id = ResourceIdForUIResource(uid); 2826 if (id) 2827 DeleteUIResource(uid); 2828 2829 ResourceFormat format = resource_provider_->best_texture_format(); 2830 if (bitmap.GetFormat() == UIResourceBitmap::ETC1) 2831 format = ETC1; 2832 id = resource_provider_->CreateResource( 2833 bitmap.GetSize(), 2834 wrap_mode, 2835 ResourceProvider::TextureUsageAny, 2836 format); 2837 2838 UIResourceData data; 2839 data.resource_id = id; 2840 data.size = bitmap.GetSize(); 2841 data.opaque = bitmap.GetOpaque(); 2842 2843 ui_resource_map_[uid] = data; 2844 2845 AutoLockUIResourceBitmap bitmap_lock(bitmap); 2846 resource_provider_->SetPixels(id, 2847 bitmap_lock.GetPixels(), 2848 gfx::Rect(bitmap.GetSize()), 2849 gfx::Rect(bitmap.GetSize()), 2850 gfx::Vector2d(0, 0)); 2851 MarkUIResourceNotEvicted(uid); 2852 } 2853 2854 void LayerTreeHostImpl::DeleteUIResource(UIResourceId uid) { 2855 ResourceProvider::ResourceId id = ResourceIdForUIResource(uid); 2856 if (id) { 2857 resource_provider_->DeleteResource(id); 2858 ui_resource_map_.erase(uid); 2859 } 2860 MarkUIResourceNotEvicted(uid); 2861 } 2862 2863 void LayerTreeHostImpl::EvictAllUIResources() { 2864 if (ui_resource_map_.empty()) 2865 return; 2866 2867 for (UIResourceMap::const_iterator iter = ui_resource_map_.begin(); 2868 iter != ui_resource_map_.end(); 2869 ++iter) { 2870 evicted_ui_resources_.insert(iter->first); 2871 resource_provider_->DeleteResource(iter->second.resource_id); 2872 } 2873 ui_resource_map_.clear(); 2874 2875 client_->SetNeedsCommitOnImplThread(); 2876 client_->OnCanDrawStateChanged(CanDraw()); 2877 client_->RenewTreePriority(); 2878 } 2879 2880 ResourceProvider::ResourceId LayerTreeHostImpl::ResourceIdForUIResource( 2881 UIResourceId uid) const { 2882 UIResourceMap::const_iterator iter = ui_resource_map_.find(uid); 2883 if (iter != ui_resource_map_.end()) 2884 return iter->second.resource_id; 2885 return 0; 2886 } 2887 2888 bool LayerTreeHostImpl::IsUIResourceOpaque(UIResourceId uid) const { 2889 UIResourceMap::const_iterator iter = ui_resource_map_.find(uid); 2890 DCHECK(iter != ui_resource_map_.end()); 2891 return iter->second.opaque; 2892 } 2893 2894 bool LayerTreeHostImpl::EvictedUIResourcesExist() const { 2895 return !evicted_ui_resources_.empty(); 2896 } 2897 2898 void LayerTreeHostImpl::MarkUIResourceNotEvicted(UIResourceId uid) { 2899 std::set<UIResourceId>::iterator found_in_evicted = 2900 evicted_ui_resources_.find(uid); 2901 if (found_in_evicted == evicted_ui_resources_.end()) 2902 return; 2903 evicted_ui_resources_.erase(found_in_evicted); 2904 if (evicted_ui_resources_.empty()) 2905 client_->OnCanDrawStateChanged(CanDraw()); 2906 } 2907 2908 void LayerTreeHostImpl::ScheduleMicroBenchmark( 2909 scoped_ptr<MicroBenchmarkImpl> benchmark) { 2910 micro_benchmark_controller_.ScheduleRun(benchmark.Pass()); 2911 } 2912 2913 void LayerTreeHostImpl::InsertSwapPromiseMonitor(SwapPromiseMonitor* monitor) { 2914 swap_promise_monitor_.insert(monitor); 2915 } 2916 2917 void LayerTreeHostImpl::RemoveSwapPromiseMonitor(SwapPromiseMonitor* monitor) { 2918 swap_promise_monitor_.erase(monitor); 2919 } 2920 2921 void LayerTreeHostImpl::NotifySwapPromiseMonitorsOfSetNeedsRedraw() { 2922 std::set<SwapPromiseMonitor*>::iterator it = swap_promise_monitor_.begin(); 2923 for (; it != swap_promise_monitor_.end(); it++) 2924 (*it)->OnSetNeedsRedrawOnImpl(); 2925 } 2926 2927 } // namespace cc 2928