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/layers/tiled_layer.h" 6 7 #include <limits> 8 #include <vector> 9 10 #include "base/run_loop.h" 11 #include "cc/resources/bitmap_content_layer_updater.h" 12 #include "cc/resources/layer_painter.h" 13 #include "cc/resources/prioritized_resource_manager.h" 14 #include "cc/resources/resource_update_controller.h" 15 #include "cc/test/animation_test_common.h" 16 #include "cc/test/fake_layer_tree_host_client.h" 17 #include "cc/test/fake_layer_tree_host_impl.h" 18 #include "cc/test/fake_output_surface.h" 19 #include "cc/test/fake_output_surface_client.h" 20 #include "cc/test/fake_proxy.h" 21 #include "cc/test/fake_rendering_stats_instrumentation.h" 22 #include "cc/test/geometry_test_utils.h" 23 #include "cc/test/test_shared_bitmap_manager.h" 24 #include "cc/test/tiled_layer_test_common.h" 25 #include "cc/trees/occlusion_tracker.h" 26 #include "cc/trees/single_thread_proxy.h" 27 #include "testing/gtest/include/gtest/gtest.h" 28 #include "ui/gfx/rect_conversions.h" 29 #include "ui/gfx/transform.h" 30 31 namespace cc { 32 namespace { 33 34 class TestOcclusionTracker : public OcclusionTracker<Layer> { 35 public: 36 TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) { 37 stack_.push_back(StackObject()); 38 } 39 40 void SetRenderTarget(Layer* render_target) { 41 stack_.back().target = render_target; 42 } 43 44 void SetOcclusion(const SimpleEnclosedRegion& occlusion) { 45 stack_.back().occlusion_from_inside_target = occlusion; 46 } 47 }; 48 49 class SynchronousOutputSurfaceLayerTreeHost : public LayerTreeHost { 50 public: 51 static scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> Create( 52 LayerTreeHostClient* client, 53 SharedBitmapManager* manager, 54 const LayerTreeSettings& settings, 55 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) { 56 return make_scoped_ptr(new SynchronousOutputSurfaceLayerTreeHost( 57 client, manager, settings, impl_task_runner)); 58 } 59 60 virtual ~SynchronousOutputSurfaceLayerTreeHost() {} 61 62 bool EnsureOutputSurfaceCreated() { 63 base::MessageLoop::current()->PostDelayedTask( 64 FROM_HERE, 65 run_loop_.QuitClosure(), 66 base::TimeDelta::FromSeconds(5)); 67 run_loop_.Run(); 68 return output_surface_created_; 69 } 70 71 virtual void OnCreateAndInitializeOutputSurfaceAttempted( 72 bool success) OVERRIDE { 73 LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success); 74 output_surface_created_ = success; 75 run_loop_.Quit(); 76 } 77 78 private: 79 SynchronousOutputSurfaceLayerTreeHost( 80 LayerTreeHostClient* client, 81 SharedBitmapManager* manager, 82 const LayerTreeSettings& settings, 83 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner) 84 : LayerTreeHost(client, manager, settings), 85 output_surface_created_(false) { 86 LayerTreeHost::InitializeThreaded(base::MessageLoopProxy::current(), 87 impl_task_runner); 88 } 89 90 bool output_surface_created_; 91 base::RunLoop run_loop_; 92 }; 93 94 class TiledLayerTest : public testing::Test { 95 public: 96 TiledLayerTest() 97 : proxy_(NULL), 98 output_surface_(FakeOutputSurface::Create3d()), 99 queue_(make_scoped_ptr(new ResourceUpdateQueue)), 100 impl_thread_("ImplThread"), 101 fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D), 102 occlusion_(NULL) { 103 settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max(); 104 settings_.layer_transforms_should_scale_layer_contents = true; 105 } 106 107 virtual void SetUp() { 108 impl_thread_.Start(); 109 shared_bitmap_manager_.reset(new TestSharedBitmapManager()); 110 layer_tree_host_ = SynchronousOutputSurfaceLayerTreeHost::Create( 111 &fake_layer_tree_host_client_, 112 shared_bitmap_manager_.get(), 113 settings_, 114 impl_thread_.message_loop_proxy()); 115 fake_layer_tree_host_client_.SetLayerTreeHost(layer_tree_host_.get()); 116 proxy_ = layer_tree_host_->proxy(); 117 resource_manager_ = PrioritizedResourceManager::Create(proxy_); 118 layer_tree_host_->SetLayerTreeHostClientReady(); 119 CHECK(layer_tree_host_->EnsureOutputSurfaceCreated()); 120 layer_tree_host_->SetRootLayer(Layer::Create()); 121 122 CHECK(output_surface_->BindToClient(&output_surface_client_)); 123 124 DebugScopedSetImplThreadAndMainThreadBlocked 125 impl_thread_and_main_thread_blocked(proxy_); 126 resource_provider_ = ResourceProvider::Create(output_surface_.get(), 127 shared_bitmap_manager_.get(), 128 NULL, 129 0, 130 false, 131 1, 132 false); 133 host_impl_ = make_scoped_ptr( 134 new FakeLayerTreeHostImpl(proxy_, shared_bitmap_manager_.get())); 135 } 136 137 virtual ~TiledLayerTest() { 138 ResourceManagerClearAllMemory(resource_manager_.get(), 139 resource_provider_.get()); 140 141 DebugScopedSetImplThreadAndMainThreadBlocked 142 impl_thread_and_main_thread_blocked(proxy_); 143 resource_provider_.reset(); 144 host_impl_.reset(); 145 } 146 147 void ResourceManagerClearAllMemory( 148 PrioritizedResourceManager* resource_manager, 149 ResourceProvider* resource_provider) { 150 { 151 DebugScopedSetImplThreadAndMainThreadBlocked 152 impl_thread_and_main_thread_blocked(proxy_); 153 resource_manager->ClearAllMemory(resource_provider); 154 resource_manager->ReduceMemory(resource_provider); 155 } 156 resource_manager->UnlinkAndClearEvictedBackings(); 157 } 158 159 void UpdateTextures() { 160 DebugScopedSetImplThreadAndMainThreadBlocked 161 impl_thread_and_main_thread_blocked(proxy_); 162 DCHECK(queue_); 163 scoped_ptr<ResourceUpdateController> update_controller = 164 ResourceUpdateController::Create(NULL, 165 proxy_->ImplThreadTaskRunner(), 166 queue_.Pass(), 167 resource_provider_.get()); 168 update_controller->Finalize(); 169 queue_ = make_scoped_ptr(new ResourceUpdateQueue); 170 } 171 172 void LayerPushPropertiesTo(FakeTiledLayer* layer, 173 FakeTiledLayerImpl* layer_impl) { 174 DebugScopedSetImplThreadAndMainThreadBlocked 175 impl_thread_and_main_thread_blocked(proxy_); 176 layer->PushPropertiesTo(layer_impl); 177 layer->ResetNumDependentsNeedPushProperties(); 178 } 179 180 void LayerUpdate(FakeTiledLayer* layer, TestOcclusionTracker* occluded) { 181 DebugScopedSetMainThread main_thread(proxy_); 182 layer->Update(queue_.get(), occluded); 183 } 184 185 void CalcDrawProps(RenderSurfaceLayerList* render_surface_layer_list) { 186 if (occlusion_) 187 occlusion_->SetRenderTarget(layer_tree_host_->root_layer()); 188 189 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs( 190 layer_tree_host_->root_layer(), 191 layer_tree_host_->device_viewport_size(), 192 render_surface_layer_list); 193 inputs.device_scale_factor = layer_tree_host_->device_scale_factor(); 194 inputs.max_texture_size = 195 layer_tree_host_->GetRendererCapabilities().max_texture_size; 196 inputs.can_adjust_raster_scales = true; 197 LayerTreeHostCommon::CalculateDrawProperties(&inputs); 198 } 199 200 bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1, 201 const scoped_ptr<FakeTiledLayerImpl>& layer_impl1) { 202 scoped_refptr<FakeTiledLayer> layer2; 203 scoped_ptr<FakeTiledLayerImpl> layer_impl2; 204 return UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); 205 } 206 207 bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1, 208 const scoped_ptr<FakeTiledLayerImpl>& layer_impl1, 209 const scoped_refptr<FakeTiledLayer>& layer2, 210 const scoped_ptr<FakeTiledLayerImpl>& layer_impl2) { 211 // Get textures 212 resource_manager_->ClearPriorities(); 213 if (layer1.get()) 214 layer1->SetTexturePriorities(priority_calculator_); 215 if (layer2.get()) 216 layer2->SetTexturePriorities(priority_calculator_); 217 resource_manager_->PrioritizeTextures(); 218 219 // Save paint properties 220 if (layer1.get()) 221 layer1->SavePaintProperties(); 222 if (layer2.get()) 223 layer2->SavePaintProperties(); 224 225 // Update content 226 if (layer1.get()) 227 layer1->Update(queue_.get(), occlusion_); 228 if (layer2.get()) 229 layer2->Update(queue_.get(), occlusion_); 230 231 bool needs_update = false; 232 if (layer1.get()) 233 needs_update |= layer1->NeedsIdlePaint(); 234 if (layer2.get()) 235 needs_update |= layer2->NeedsIdlePaint(); 236 237 // Update textures and push. 238 UpdateTextures(); 239 if (layer1.get()) 240 LayerPushPropertiesTo(layer1.get(), layer_impl1.get()); 241 if (layer2.get()) 242 LayerPushPropertiesTo(layer2.get(), layer_impl2.get()); 243 244 return needs_update; 245 } 246 247 public: 248 Proxy* proxy_; 249 LayerTreeSettings settings_; 250 FakeOutputSurfaceClient output_surface_client_; 251 scoped_ptr<OutputSurface> output_surface_; 252 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_; 253 scoped_ptr<ResourceProvider> resource_provider_; 254 scoped_ptr<ResourceUpdateQueue> queue_; 255 PriorityCalculator priority_calculator_; 256 base::Thread impl_thread_; 257 FakeLayerTreeHostClient fake_layer_tree_host_client_; 258 scoped_ptr<SynchronousOutputSurfaceLayerTreeHost> layer_tree_host_; 259 scoped_ptr<FakeLayerTreeHostImpl> host_impl_; 260 scoped_ptr<PrioritizedResourceManager> resource_manager_; 261 TestOcclusionTracker* occlusion_; 262 }; 263 264 TEST_F(TiledLayerTest, PushDirtyTiles) { 265 scoped_refptr<FakeTiledLayer> layer = 266 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 267 scoped_ptr<FakeTiledLayerImpl> layer_impl = 268 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 269 RenderSurfaceLayerList render_surface_layer_list; 270 271 layer_tree_host_->root_layer()->AddChild(layer); 272 273 // The tile size is 100x100, so this invalidates and then paints two tiles. 274 layer->SetBounds(gfx::Size(100, 200)); 275 CalcDrawProps(&render_surface_layer_list); 276 UpdateAndPush(layer, layer_impl); 277 278 // We should have both tiles on the impl side. 279 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 280 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); 281 282 // Invalidates both tiles, but then only update one of them. 283 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 200)); 284 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); 285 UpdateAndPush(layer, layer_impl); 286 287 // We should only have the first tile since the other tile was invalidated but 288 // not painted. 289 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 290 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); 291 } 292 293 TEST_F(TiledLayerTest, Scale) { 294 layer_tree_host_->SetDeviceScaleFactor(1.5); 295 296 scoped_refptr<FakeTiledLayer> layer = 297 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 298 scoped_ptr<FakeTiledLayerImpl> layer_impl = 299 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 300 RenderSurfaceLayerList render_surface_layer_list; 301 302 layer_tree_host_->root_layer()->AddChild(layer); 303 304 layer->SetBounds(gfx::Size(100, 200)); 305 CalcDrawProps(&render_surface_layer_list); 306 307 // Change the width so that it doesn't divide cleanly by the scale. 308 layer->SetBounds(gfx::Size(101, 200)); 309 UpdateAndPush(layer, layer_impl); 310 311 EXPECT_EQ(1.5, layer->fake_layer_updater()->last_contents_width_scale()); 312 } 313 314 TEST_F(TiledLayerTest, PushOccludedDirtyTiles) { 315 scoped_refptr<FakeTiledLayer> layer = 316 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 317 scoped_ptr<FakeTiledLayerImpl> layer_impl = 318 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 319 TestOcclusionTracker occluded; 320 occlusion_ = &occluded; 321 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000)); 322 323 layer_tree_host_->root_layer()->AddChild(layer); 324 325 { 326 RenderSurfaceLayerList render_surface_layer_list; 327 328 // The tile size is 100x100, so this invalidates and then paints two tiles. 329 layer->SetBounds(gfx::Size(100, 200)); 330 CalcDrawProps(&render_surface_layer_list); 331 UpdateAndPush(layer, layer_impl); 332 333 // We should have both tiles on the impl side. 334 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 335 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); 336 } 337 338 { 339 RenderSurfaceLayerList render_surface_layer_list; 340 341 // Invalidates part of the top tile... 342 layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50)); 343 // ....but the area is occluded. 344 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50))); 345 CalcDrawProps(&render_surface_layer_list); 346 UpdateAndPush(layer, layer_impl); 347 348 // We should still have both tiles, as part of the top tile is still 349 // unoccluded. 350 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 351 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); 352 } 353 } 354 355 TEST_F(TiledLayerTest, PushDeletedTiles) { 356 scoped_refptr<FakeTiledLayer> layer = 357 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 358 scoped_ptr<FakeTiledLayerImpl> layer_impl = 359 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 360 RenderSurfaceLayerList render_surface_layer_list; 361 362 layer_tree_host_->root_layer()->AddChild(layer); 363 364 // The tile size is 100x100, so this invalidates and then paints two tiles. 365 layer->SetBounds(gfx::Size(100, 200)); 366 CalcDrawProps(&render_surface_layer_list); 367 UpdateAndPush(layer, layer_impl); 368 369 // We should have both tiles on the impl side. 370 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 371 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); 372 373 resource_manager_->ClearPriorities(); 374 ResourceManagerClearAllMemory(resource_manager_.get(), 375 resource_provider_.get()); 376 resource_manager_->SetMaxMemoryLimitBytes(4 * 1024 * 1024); 377 378 // This should drop the tiles on the impl thread. 379 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 380 381 // We should now have no textures on the impl thread. 382 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); 383 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); 384 385 // This should recreate and update one of the deleted textures. 386 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); 387 UpdateAndPush(layer, layer_impl); 388 389 // We should have one tiles on the impl side. 390 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 391 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); 392 } 393 394 TEST_F(TiledLayerTest, PushIdlePaintTiles) { 395 scoped_refptr<FakeTiledLayer> layer = 396 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 397 scoped_ptr<FakeTiledLayerImpl> layer_impl = 398 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 399 RenderSurfaceLayerList render_surface_layer_list; 400 401 layer_tree_host_->root_layer()->AddChild(layer); 402 403 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the 404 // center. This paints 1 visible of the 25 invalid tiles. 405 layer->SetBounds(gfx::Size(500, 500)); 406 CalcDrawProps(&render_surface_layer_list); 407 layer->draw_properties().visible_content_rect = gfx::Rect(200, 200, 100, 100); 408 bool needs_update = UpdateAndPush(layer, layer_impl); 409 // We should need idle-painting for surrounding tiles. 410 EXPECT_TRUE(needs_update); 411 412 // We should have one tile on the impl side. 413 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(2, 2)); 414 415 // For the next four updates, we should detect we still need idle painting. 416 for (int i = 0; i < 4; i++) { 417 needs_update = UpdateAndPush(layer, layer_impl); 418 EXPECT_TRUE(needs_update); 419 } 420 421 // We should always finish painting eventually. 422 for (int i = 0; i < 20; i++) 423 needs_update = UpdateAndPush(layer, layer_impl); 424 425 // We should have pre-painted all of the surrounding tiles. 426 for (int i = 0; i < 5; i++) { 427 for (int j = 0; j < 5; j++) 428 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j)); 429 } 430 431 EXPECT_FALSE(needs_update); 432 } 433 434 TEST_F(TiledLayerTest, PredictivePainting) { 435 scoped_refptr<FakeTiledLayer> layer = 436 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 437 scoped_ptr<FakeTiledLayerImpl> layer_impl = 438 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 439 440 layer_tree_host_->root_layer()->AddChild(layer); 441 442 // Prepainting should occur in the scroll direction first, and the 443 // visible rect should be extruded only along the dominant axis. 444 gfx::Vector2d directions[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0), 445 gfx::Vector2d(0, -10), gfx::Vector2d(0, 10), 446 gfx::Vector2d(10, 20), 447 gfx::Vector2d(-20, 10) }; 448 // We should push all tiles that touch the extruded visible rect. 449 gfx::Rect pushed_visible_tiles[6] = { 450 gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2), 451 gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1) 452 }; 453 // The first pre-paint should also paint first in the scroll 454 // direction so we should find one additional tile in the scroll direction. 455 gfx::Rect pushed_prepaint_tiles[6] = { 456 gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3), 457 gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1) 458 }; 459 for (int k = 0; k < 6; k++) { 460 // The tile size is 100x100. Setup 5x5 tiles with one visible tile 461 // in the center. 462 gfx::Size bounds = gfx::Size(500, 500); 463 gfx::Rect visible_rect = gfx::Rect(200, 200, 100, 100); 464 gfx::Rect previous_visible_rect = 465 gfx::Rect(visible_rect.origin() + directions[k], visible_rect.size()); 466 gfx::Rect next_visible_rect = 467 gfx::Rect(visible_rect.origin() - directions[k], visible_rect.size()); 468 469 // Setup. Use the previous_visible_rect to setup the prediction for next 470 // frame. 471 layer->SetBounds(bounds); 472 473 RenderSurfaceLayerList render_surface_layer_list; 474 CalcDrawProps(&render_surface_layer_list); 475 layer->draw_properties().visible_content_rect = previous_visible_rect; 476 bool needs_update = UpdateAndPush(layer, layer_impl); 477 478 // Invalidate and move the visible_rect in the scroll direction. 479 // Check that the correct tiles have been painted in the visible pass. 480 layer->SetNeedsDisplay(); 481 layer->draw_properties().visible_content_rect = visible_rect; 482 needs_update = UpdateAndPush(layer, layer_impl); 483 for (int i = 0; i < 5; i++) { 484 for (int j = 0; j < 5; j++) 485 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), 486 pushed_visible_tiles[k].Contains(i, j)); 487 } 488 489 // Move the transform in the same direction without invalidating. 490 // Check that non-visible pre-painting occured in the correct direction. 491 // Ignore diagonal scrolls here (k > 3) as these have new visible content 492 // now. 493 if (k <= 3) { 494 layer->draw_properties().visible_content_rect = next_visible_rect; 495 needs_update = UpdateAndPush(layer, layer_impl); 496 for (int i = 0; i < 5; i++) { 497 for (int j = 0; j < 5; j++) 498 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), 499 pushed_prepaint_tiles[k].Contains(i, j)); 500 } 501 } 502 503 // We should always finish painting eventually. 504 for (int i = 0; i < 20; i++) 505 needs_update = UpdateAndPush(layer, layer_impl); 506 EXPECT_FALSE(needs_update); 507 } 508 } 509 510 TEST_F(TiledLayerTest, PushTilesAfterIdlePaintFailed) { 511 // Start with 2mb of memory, but the test is going to try to use just more 512 // than 1mb, so we reduce to 1mb later. 513 resource_manager_->SetMaxMemoryLimitBytes(2 * 1024 * 1024); 514 scoped_refptr<FakeTiledLayer> layer1 = 515 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 516 scoped_ptr<FakeTiledLayerImpl> layer_impl1 = 517 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 518 scoped_refptr<FakeTiledLayer> layer2 = 519 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 520 scoped_ptr<FakeTiledLayerImpl> layer_impl2 = 521 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); 522 RenderSurfaceLayerList render_surface_layer_list; 523 524 layer_tree_host_->root_layer()->AddChild(layer1); 525 layer_tree_host_->root_layer()->AddChild(layer2); 526 527 // For this test we have two layers. layer1 exhausts most texture memory, 528 // leaving room for 2 more tiles from layer2, but not all three tiles. First 529 // we paint layer1, and one tile from layer2. Then when we idle paint layer2, 530 // we will fail on the third tile of layer2, and this should not leave the 531 // second tile in a bad state. 532 533 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough 534 // for 2 tiles only in the other layer. 535 gfx::Rect layer1_rect(0, 0, 100, 2400); 536 537 // This requires 4*30000 bytes of memory. 538 gfx::Rect layer2_rect(0, 0, 100, 300); 539 540 // Paint a single tile in layer2 so that it will idle paint. 541 layer1->SetBounds(layer1_rect.size()); 542 layer2->SetBounds(layer2_rect.size()); 543 CalcDrawProps(&render_surface_layer_list); 544 layer1->draw_properties().visible_content_rect = layer1_rect; 545 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); 546 bool needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); 547 // We should need idle-painting for both remaining tiles in layer2. 548 EXPECT_TRUE(needs_update); 549 550 // Reduce our memory limits to 1mb. 551 resource_manager_->SetMaxMemoryLimitBytes(1024 * 1024); 552 553 // Now idle paint layer2. We are going to run out of memory though! 554 // Oh well, commit the frame and push. 555 for (int i = 0; i < 4; i++) { 556 needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2); 557 } 558 559 // Sanity check, we should have textures for the big layer. 560 EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 0)); 561 EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 23)); 562 563 // We should only have the first two tiles from layer2 since 564 // it failed to idle update the last tile. 565 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0)); 566 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0)); 567 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1)); 568 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1)); 569 570 EXPECT_FALSE(needs_update); 571 EXPECT_FALSE(layer_impl2->HasResourceIdForTileAt(0, 2)); 572 } 573 574 TEST_F(TiledLayerTest, PushIdlePaintedOccludedTiles) { 575 scoped_refptr<FakeTiledLayer> layer = 576 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 577 scoped_ptr<FakeTiledLayerImpl> layer_impl = 578 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 579 RenderSurfaceLayerList render_surface_layer_list; 580 TestOcclusionTracker occluded; 581 occlusion_ = &occluded; 582 583 layer_tree_host_->root_layer()->AddChild(layer); 584 585 // The tile size is 100x100, so this invalidates one occluded tile, culls it 586 // during paint, but prepaints it. 587 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100))); 588 589 layer->SetBounds(gfx::Size(100, 100)); 590 CalcDrawProps(&render_surface_layer_list); 591 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); 592 UpdateAndPush(layer, layer_impl); 593 594 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 595 } 596 597 TEST_F(TiledLayerTest, PushTilesMarkedDirtyDuringPaint) { 598 scoped_refptr<FakeTiledLayer> layer = 599 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 600 scoped_ptr<FakeTiledLayerImpl> layer_impl = 601 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 602 RenderSurfaceLayerList render_surface_layer_list; 603 604 layer_tree_host_->root_layer()->AddChild(layer); 605 606 // The tile size is 100x100, so this invalidates and then paints two tiles. 607 // However, during the paint, we invalidate one of the tiles. This should 608 // not prevent the tile from being pushed. 609 layer->fake_layer_updater()->SetRectToInvalidate( 610 gfx::Rect(0, 50, 100, 50), layer.get()); 611 layer->SetBounds(gfx::Size(100, 200)); 612 CalcDrawProps(&render_surface_layer_list); 613 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); 614 UpdateAndPush(layer, layer_impl); 615 616 // We should have both tiles on the impl side. 617 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 618 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); 619 } 620 621 TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer) { 622 scoped_refptr<FakeTiledLayer> layer1 = 623 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 624 scoped_refptr<FakeTiledLayer> layer2 = 625 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 626 scoped_ptr<FakeTiledLayerImpl> layer1_impl = 627 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 628 scoped_ptr<FakeTiledLayerImpl> layer2_impl = 629 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); 630 RenderSurfaceLayerList render_surface_layer_list; 631 632 layer_tree_host_->root_layer()->AddChild(layer1); 633 layer_tree_host_->root_layer()->AddChild(layer2); 634 635 // Invalidate a tile on layer1, during update of layer 2. 636 layer2->fake_layer_updater()->SetRectToInvalidate( 637 gfx::Rect(0, 50, 100, 50), layer1.get()); 638 layer1->SetBounds(gfx::Size(100, 200)); 639 layer2->SetBounds(gfx::Size(100, 200)); 640 CalcDrawProps(&render_surface_layer_list); 641 layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); 642 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); 643 UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl); 644 645 // We should have both tiles on the impl side for all layers. 646 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0)); 647 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1)); 648 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0)); 649 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1)); 650 } 651 652 TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer) { 653 scoped_refptr<FakeTiledLayer> layer1 = 654 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 655 scoped_refptr<FakeTiledLayer> layer2 = 656 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 657 scoped_ptr<FakeTiledLayerImpl> layer1_impl = 658 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 659 scoped_ptr<FakeTiledLayerImpl> layer2_impl = 660 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2)); 661 RenderSurfaceLayerList render_surface_layer_list; 662 663 layer_tree_host_->root_layer()->AddChild(layer1); 664 layer_tree_host_->root_layer()->AddChild(layer2); 665 666 layer1->fake_layer_updater()->SetRectToInvalidate( 667 gfx::Rect(0, 50, 100, 50), layer2.get()); 668 layer1->SetBounds(gfx::Size(100, 200)); 669 layer2->SetBounds(gfx::Size(100, 200)); 670 CalcDrawProps(&render_surface_layer_list); 671 layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); 672 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); 673 UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl); 674 675 // We should have both tiles on the impl side for all layers. 676 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0)); 677 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1)); 678 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0)); 679 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1)); 680 } 681 682 TEST_F(TiledLayerTest, PaintSmallAnimatedLayersImmediately) { 683 // Create a LayerTreeHost that has the right viewportsize, 684 // so the layer is considered small enough. 685 bool run_out_of_memory[2] = { false, true }; 686 for (int i = 0; i < 2; i++) { 687 // Create a layer with 5x5 tiles, with 4x4 size viewport. 688 int viewport_width = 4 * FakeTiledLayer::tile_size().width(); 689 int viewport_height = 4 * FakeTiledLayer::tile_size().width(); 690 int layer_width = 5 * FakeTiledLayer::tile_size().width(); 691 int layer_height = 5 * FakeTiledLayer::tile_size().height(); 692 int memory_for_layer = layer_width * layer_height * 4; 693 layer_tree_host_->SetViewportSize( 694 gfx::Size(viewport_width, viewport_height)); 695 696 // Use 10x5 tiles to run out of memory. 697 if (run_out_of_memory[i]) 698 layer_width *= 2; 699 700 resource_manager_->SetMaxMemoryLimitBytes(memory_for_layer); 701 702 scoped_refptr<FakeTiledLayer> layer = 703 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 704 scoped_ptr<FakeTiledLayerImpl> layer_impl = 705 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 706 RenderSurfaceLayerList render_surface_layer_list; 707 708 layer_tree_host_->root_layer()->AddChild(layer); 709 710 // Full size layer with half being visible. 711 layer->SetBounds(gfx::Size(layer_width, layer_height)); 712 gfx::Rect visible_rect(0, 0, layer_width / 2, layer_height); 713 CalcDrawProps(&render_surface_layer_list); 714 715 // Pretend the layer is animating. 716 layer->draw_properties().target_space_transform_is_animating = true; 717 layer->draw_properties().visible_content_rect = visible_rect; 718 layer->SetLayerTreeHost(layer_tree_host_.get()); 719 720 // The layer should paint its entire contents on the first paint 721 // if it is close to the viewport size and has the available memory. 722 layer->SetTexturePriorities(priority_calculator_); 723 resource_manager_->PrioritizeTextures(); 724 layer->SavePaintProperties(); 725 layer->Update(queue_.get(), NULL); 726 UpdateTextures(); 727 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 728 729 // We should have all the tiles for the small animated layer. 730 // We should still have the visible tiles when we didn't 731 // have enough memory for all the tiles. 732 if (!run_out_of_memory[i]) { 733 for (int i = 0; i < 5; ++i) { 734 for (int j = 0; j < 5; ++j) 735 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j)); 736 } 737 } else { 738 for (int i = 0; i < 10; ++i) { 739 for (int j = 0; j < 5; ++j) 740 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), i < 5); 741 } 742 } 743 744 layer->RemoveFromParent(); 745 } 746 } 747 748 TEST_F(TiledLayerTest, IdlePaintOutOfMemory) { 749 scoped_refptr<FakeTiledLayer> layer = 750 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 751 scoped_ptr<FakeTiledLayerImpl> layer_impl = 752 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 753 RenderSurfaceLayerList render_surface_layer_list; 754 755 layer_tree_host_->root_layer()->AddChild(layer); 756 757 // We have enough memory for only the visible rect, so we will run out of 758 // memory in first idle paint. 759 int memory_limit = 4 * 100 * 100; // 1 tiles, 4 bytes per pixel. 760 resource_manager_->SetMaxMemoryLimitBytes(memory_limit); 761 762 // The tile size is 100x100, so this invalidates and then paints two tiles. 763 bool needs_update = false; 764 layer->SetBounds(gfx::Size(300, 300)); 765 CalcDrawProps(&render_surface_layer_list); 766 layer->draw_properties().visible_content_rect = gfx::Rect(100, 100, 100, 100); 767 for (int i = 0; i < 2; i++) 768 needs_update = UpdateAndPush(layer, layer_impl); 769 770 // Idle-painting should see no more priority tiles for painting. 771 EXPECT_FALSE(needs_update); 772 773 // We should have one tile on the impl side. 774 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1)); 775 } 776 777 TEST_F(TiledLayerTest, IdlePaintZeroSizedLayer) { 778 scoped_refptr<FakeTiledLayer> layer = 779 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 780 scoped_ptr<FakeTiledLayerImpl> layer_impl = 781 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 782 783 layer_tree_host_->root_layer()->AddChild(layer); 784 785 bool animating[2] = { false, true }; 786 for (int i = 0; i < 2; i++) { 787 // Pretend the layer is animating. 788 layer->draw_properties().target_space_transform_is_animating = animating[i]; 789 790 // The layer's bounds are empty. 791 // Empty layers don't paint or idle-paint. 792 layer->SetBounds(gfx::Size()); 793 794 RenderSurfaceLayerList render_surface_layer_list; 795 CalcDrawProps(&render_surface_layer_list); 796 layer->draw_properties().visible_content_rect = gfx::Rect(); 797 bool needs_update = UpdateAndPush(layer, layer_impl); 798 799 // Empty layers don't have tiles. 800 EXPECT_EQ(0u, layer->NumPaintedTiles()); 801 802 // Empty layers don't need prepaint. 803 EXPECT_FALSE(needs_update); 804 805 // Empty layers don't have tiles. 806 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); 807 } 808 } 809 810 TEST_F(TiledLayerTest, IdlePaintNonVisibleLayers) { 811 scoped_refptr<FakeTiledLayer> layer = 812 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 813 scoped_ptr<FakeTiledLayerImpl> layer_impl = 814 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 815 816 // Alternate between not visible and visible. 817 gfx::Rect v(0, 0, 100, 100); 818 gfx::Rect nv(0, 0, 0, 0); 819 gfx::Rect visible_rect[10] = { nv, nv, v, v, nv, nv, v, v, nv, nv }; 820 bool invalidate[10] = { true, true, true, true, true, true, true, true, false, 821 false }; 822 823 // We should not have any tiles except for when the layer was visible 824 // or after the layer was visible and we didn't invalidate. 825 bool have_tile[10] = { false, false, true, true, false, false, true, true, 826 true, true }; 827 828 layer_tree_host_->root_layer()->AddChild(layer); 829 830 for (int i = 0; i < 10; i++) { 831 layer->SetBounds(gfx::Size(100, 100)); 832 833 RenderSurfaceLayerList render_surface_layer_list; 834 CalcDrawProps(&render_surface_layer_list); 835 layer->draw_properties().visible_content_rect = visible_rect[i]; 836 837 if (invalidate[i]) 838 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 100)); 839 bool needs_update = UpdateAndPush(layer, layer_impl); 840 841 // We should never signal idle paint, as we painted the entire layer 842 // or the layer was not visible. 843 EXPECT_FALSE(needs_update); 844 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(0, 0), have_tile[i]); 845 } 846 } 847 848 TEST_F(TiledLayerTest, InvalidateFromPrepare) { 849 scoped_refptr<FakeTiledLayer> layer = 850 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 851 scoped_ptr<FakeTiledLayerImpl> layer_impl = 852 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 853 RenderSurfaceLayerList render_surface_layer_list; 854 855 layer_tree_host_->root_layer()->AddChild(layer); 856 857 // The tile size is 100x100, so this invalidates and then paints two tiles. 858 layer->SetBounds(gfx::Size(100, 200)); 859 CalcDrawProps(&render_surface_layer_list); 860 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200); 861 UpdateAndPush(layer, layer_impl); 862 863 // We should have both tiles on the impl side. 864 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 865 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); 866 867 layer->fake_layer_updater()->ClearPrepareCount(); 868 // Invoke update again. As the layer is valid update shouldn't be invoked on 869 // the LayerUpdater. 870 UpdateAndPush(layer, layer_impl); 871 EXPECT_EQ(0, layer->fake_layer_updater()->prepare_count()); 872 873 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from 874 // update. 875 layer->fake_layer_updater()->SetRectToInvalidate( 876 gfx::Rect(25, 25, 50, 50), layer.get()); 877 layer->fake_layer_updater()->ClearPrepareCount(); 878 layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50)); 879 UpdateAndPush(layer, layer_impl); 880 EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count()); 881 layer->fake_layer_updater()->ClearPrepareCount(); 882 883 // The layer should still be invalid as update invoked invalidate. 884 UpdateAndPush(layer, layer_impl); // visible 885 EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count()); 886 } 887 888 TEST_F(TiledLayerTest, VerifyUpdateRectWhenContentBoundsAreScaled) { 889 // The update rect (that indicates what was actually painted) should be in 890 // layer space, not the content space. 891 scoped_refptr<FakeTiledLayerWithScaledBounds> layer = make_scoped_refptr( 892 new FakeTiledLayerWithScaledBounds(resource_manager_.get())); 893 894 layer_tree_host_->root_layer()->AddChild(layer); 895 896 gfx::Rect layer_bounds(0, 0, 300, 200); 897 gfx::Rect content_bounds(0, 0, 150, 250); 898 899 layer->SetBounds(layer_bounds.size()); 900 layer->SetContentBounds(content_bounds.size()); 901 layer->draw_properties().visible_content_rect = content_bounds; 902 layer->draw_properties().contents_scale_x = .5f; 903 layer->draw_properties().contents_scale_y = 1.25f; 904 905 // On first update, the update_rect includes all tiles, even beyond the 906 // boundaries of the layer. 907 // However, it should still be in layer space, not content space. 908 layer->InvalidateContentRect(content_bounds); 909 910 layer->SetTexturePriorities(priority_calculator_); 911 resource_manager_->PrioritizeTextures(); 912 layer->SavePaintProperties(); 913 layer->Update(queue_.get(), NULL); 914 915 // Update rect is 200x300 (tile size of 100x100). Scaled this gives 400x240. 916 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 400, 240), layer->update_rect()); 917 UpdateTextures(); 918 919 // After the tiles are updated once, another invalidate only needs to update 920 // the bounds of the layer. 921 layer->SetTexturePriorities(priority_calculator_); 922 resource_manager_->PrioritizeTextures(); 923 layer->InvalidateContentRect(content_bounds); 924 layer->SavePaintProperties(); 925 layer->Update(queue_.get(), NULL); 926 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds), layer->update_rect()); 927 UpdateTextures(); 928 929 // Partial re-paint should also be represented by the update rect in layer 930 // space, not content space. 931 gfx::Rect partial_damage(30, 100, 10, 10); 932 layer->InvalidateContentRect(partial_damage); 933 layer->SetTexturePriorities(priority_calculator_); 934 resource_manager_->PrioritizeTextures(); 935 layer->SavePaintProperties(); 936 layer->Update(queue_.get(), NULL); 937 EXPECT_FLOAT_RECT_EQ(gfx::RectF(60, 80, 20, 8), layer->update_rect()); 938 } 939 940 TEST_F(TiledLayerTest, VerifyInvalidationWhenContentsScaleChanges) { 941 scoped_refptr<FakeTiledLayer> layer = 942 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 943 scoped_ptr<FakeTiledLayerImpl> layer_impl = 944 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 945 RenderSurfaceLayerList render_surface_layer_list; 946 947 layer_tree_host_->root_layer()->AddChild(layer); 948 949 // Create a layer with one tile. 950 layer->SetBounds(gfx::Size(100, 100)); 951 CalcDrawProps(&render_surface_layer_list); 952 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100); 953 layer->Update(queue_.get(), NULL); 954 UpdateTextures(); 955 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), 956 layer->last_needs_display_rect()); 957 958 // Push the tiles to the impl side and check that there is exactly one. 959 layer->SetTexturePriorities(priority_calculator_); 960 resource_manager_->PrioritizeTextures(); 961 layer->SavePaintProperties(); 962 layer->Update(queue_.get(), NULL); 963 UpdateTextures(); 964 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 965 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 966 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); 967 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0)); 968 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1)); 969 970 layer->SetNeedsDisplayRect(gfx::Rect()); 971 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer->last_needs_display_rect()); 972 973 // Change the contents scale. 974 layer->UpdateContentsScale(2.f); 975 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 200, 200); 976 977 // The impl side should get 2x2 tiles now. 978 layer->SetTexturePriorities(priority_calculator_); 979 resource_manager_->PrioritizeTextures(); 980 layer->SavePaintProperties(); 981 layer->Update(queue_.get(), NULL); 982 UpdateTextures(); 983 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 984 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0)); 985 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1)); 986 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 0)); 987 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1)); 988 989 // Verify that changing the contents scale caused invalidation, and 990 // that the layer-space rectangle requiring painting is not scaled. 991 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), 992 layer->last_needs_display_rect()); 993 994 // Invalidate the entire layer again, but do not paint. All tiles should be 995 // gone now from the impl side. 996 layer->SetNeedsDisplay(); 997 layer->SetTexturePriorities(priority_calculator_); 998 resource_manager_->PrioritizeTextures(); 999 1000 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 1001 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0)); 1002 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1)); 1003 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0)); 1004 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1)); 1005 } 1006 1007 TEST_F(TiledLayerTest, SkipsDrawGetsReset) { 1008 // Create two 300 x 300 tiled layers. 1009 gfx::Size content_bounds(300, 300); 1010 gfx::Rect content_rect(content_bounds); 1011 1012 // We have enough memory for only one of the two layers. 1013 int memory_limit = 4 * 300 * 300; // 4 bytes per pixel. 1014 1015 scoped_refptr<FakeTiledLayer> root_layer = make_scoped_refptr( 1016 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); 1017 scoped_refptr<FakeTiledLayer> child_layer = make_scoped_refptr( 1018 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); 1019 root_layer->AddChild(child_layer); 1020 1021 root_layer->SetBounds(content_bounds); 1022 root_layer->draw_properties().visible_content_rect = content_rect; 1023 root_layer->SetPosition(gfx::PointF(0, 0)); 1024 child_layer->SetBounds(content_bounds); 1025 child_layer->draw_properties().visible_content_rect = content_rect; 1026 child_layer->SetPosition(gfx::PointF(0, 0)); 1027 root_layer->InvalidateContentRect(content_rect); 1028 child_layer->InvalidateContentRect(content_rect); 1029 1030 layer_tree_host_->SetRootLayer(root_layer); 1031 layer_tree_host_->SetViewportSize(gfx::Size(300, 300)); 1032 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( 1033 memory_limit); 1034 1035 layer_tree_host_->UpdateLayers(queue_.get()); 1036 1037 // We'll skip the root layer. 1038 EXPECT_TRUE(root_layer->SkipsDraw()); 1039 EXPECT_FALSE(child_layer->SkipsDraw()); 1040 1041 layer_tree_host_->CommitComplete(); 1042 1043 // Remove the child layer. 1044 root_layer->RemoveAllChildren(); 1045 1046 layer_tree_host_->UpdateLayers(queue_.get()); 1047 EXPECT_FALSE(root_layer->SkipsDraw()); 1048 1049 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), 1050 resource_provider_.get()); 1051 layer_tree_host_->SetRootLayer(NULL); 1052 } 1053 1054 TEST_F(TiledLayerTest, ResizeToSmaller) { 1055 scoped_refptr<FakeTiledLayer> layer = 1056 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 1057 1058 layer_tree_host_->root_layer()->AddChild(layer); 1059 1060 layer->SetBounds(gfx::Size(700, 700)); 1061 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700); 1062 layer->InvalidateContentRect(gfx::Rect(0, 0, 700, 700)); 1063 1064 layer->SetTexturePriorities(priority_calculator_); 1065 resource_manager_->PrioritizeTextures(); 1066 layer->SavePaintProperties(); 1067 layer->Update(queue_.get(), NULL); 1068 1069 layer->SetBounds(gfx::Size(200, 200)); 1070 layer->InvalidateContentRect(gfx::Rect(0, 0, 200, 200)); 1071 } 1072 1073 TEST_F(TiledLayerTest, HugeLayerUpdateCrash) { 1074 scoped_refptr<FakeTiledLayer> layer = 1075 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 1076 1077 layer_tree_host_->root_layer()->AddChild(layer); 1078 1079 int size = 1 << 30; 1080 layer->SetBounds(gfx::Size(size, size)); 1081 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700); 1082 layer->InvalidateContentRect(gfx::Rect(0, 0, size, size)); 1083 1084 // Ensure no crash for bounds where size * size would overflow an int. 1085 layer->SetTexturePriorities(priority_calculator_); 1086 resource_manager_->PrioritizeTextures(); 1087 layer->SavePaintProperties(); 1088 layer->Update(queue_.get(), NULL); 1089 } 1090 1091 class TiledLayerPartialUpdateTest : public TiledLayerTest { 1092 public: 1093 TiledLayerPartialUpdateTest() { settings_.max_partial_texture_updates = 4; } 1094 }; 1095 1096 TEST_F(TiledLayerPartialUpdateTest, PartialUpdates) { 1097 // Create one 300 x 200 tiled layer with 3 x 2 tiles. 1098 gfx::Size content_bounds(300, 200); 1099 gfx::Rect content_rect(content_bounds); 1100 1101 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr( 1102 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); 1103 layer->SetBounds(content_bounds); 1104 layer->SetPosition(gfx::PointF(0, 0)); 1105 layer->draw_properties().visible_content_rect = content_rect; 1106 layer->InvalidateContentRect(content_rect); 1107 1108 layer_tree_host_->SetRootLayer(layer); 1109 layer_tree_host_->SetViewportSize(gfx::Size(300, 200)); 1110 1111 // Full update of all 6 tiles. 1112 layer_tree_host_->UpdateLayers(queue_.get()); 1113 { 1114 scoped_ptr<FakeTiledLayerImpl> layer_impl = 1115 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 1116 EXPECT_EQ(6u, queue_->FullUploadSize()); 1117 EXPECT_EQ(0u, queue_->PartialUploadSize()); 1118 UpdateTextures(); 1119 EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); 1120 EXPECT_FALSE(queue_->HasMoreUpdates()); 1121 layer->fake_layer_updater()->ClearUpdateCount(); 1122 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 1123 } 1124 layer_tree_host_->CommitComplete(); 1125 1126 // Full update of 3 tiles and partial update of 3 tiles. 1127 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 150)); 1128 layer_tree_host_->UpdateLayers(queue_.get()); 1129 { 1130 scoped_ptr<FakeTiledLayerImpl> layer_impl = 1131 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 1132 EXPECT_EQ(3u, queue_->FullUploadSize()); 1133 EXPECT_EQ(3u, queue_->PartialUploadSize()); 1134 UpdateTextures(); 1135 EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); 1136 EXPECT_FALSE(queue_->HasMoreUpdates()); 1137 layer->fake_layer_updater()->ClearUpdateCount(); 1138 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 1139 } 1140 layer_tree_host_->CommitComplete(); 1141 1142 // Partial update of 6 tiles. 1143 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100)); 1144 { 1145 scoped_ptr<FakeTiledLayerImpl> layer_impl = 1146 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 1147 layer_tree_host_->UpdateLayers(queue_.get()); 1148 EXPECT_EQ(2u, queue_->FullUploadSize()); 1149 EXPECT_EQ(4u, queue_->PartialUploadSize()); 1150 UpdateTextures(); 1151 EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); 1152 EXPECT_FALSE(queue_->HasMoreUpdates()); 1153 layer->fake_layer_updater()->ClearUpdateCount(); 1154 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 1155 } 1156 layer_tree_host_->CommitComplete(); 1157 1158 // Checkerboard all tiles. 1159 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 200)); 1160 { 1161 scoped_ptr<FakeTiledLayerImpl> layer_impl = 1162 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 1163 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 1164 } 1165 layer_tree_host_->CommitComplete(); 1166 1167 // Partial update of 6 checkerboard tiles. 1168 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100)); 1169 { 1170 scoped_ptr<FakeTiledLayerImpl> layer_impl = 1171 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 1172 layer_tree_host_->UpdateLayers(queue_.get()); 1173 EXPECT_EQ(6u, queue_->FullUploadSize()); 1174 EXPECT_EQ(0u, queue_->PartialUploadSize()); 1175 UpdateTextures(); 1176 EXPECT_EQ(6, layer->fake_layer_updater()->update_count()); 1177 EXPECT_FALSE(queue_->HasMoreUpdates()); 1178 layer->fake_layer_updater()->ClearUpdateCount(); 1179 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 1180 } 1181 layer_tree_host_->CommitComplete(); 1182 1183 // Partial update of 4 tiles. 1184 layer->InvalidateContentRect(gfx::Rect(50, 50, 100, 100)); 1185 { 1186 scoped_ptr<FakeTiledLayerImpl> layer_impl = 1187 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1)); 1188 layer_tree_host_->UpdateLayers(queue_.get()); 1189 EXPECT_EQ(0u, queue_->FullUploadSize()); 1190 EXPECT_EQ(4u, queue_->PartialUploadSize()); 1191 UpdateTextures(); 1192 EXPECT_EQ(4, layer->fake_layer_updater()->update_count()); 1193 EXPECT_FALSE(queue_->HasMoreUpdates()); 1194 layer->fake_layer_updater()->ClearUpdateCount(); 1195 LayerPushPropertiesTo(layer.get(), layer_impl.get()); 1196 } 1197 layer_tree_host_->CommitComplete(); 1198 1199 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), 1200 resource_provider_.get()); 1201 layer_tree_host_->SetRootLayer(NULL); 1202 } 1203 1204 TEST_F(TiledLayerTest, TilesPaintedWithoutOcclusion) { 1205 scoped_refptr<FakeTiledLayer> layer = 1206 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 1207 RenderSurfaceLayerList render_surface_layer_list; 1208 1209 layer_tree_host_->root_layer()->AddChild(layer); 1210 1211 // The tile size is 100x100, so this invalidates and then paints two tiles. 1212 layer->SetBounds(gfx::Size(100, 200)); 1213 CalcDrawProps(&render_surface_layer_list); 1214 1215 layer->SetTexturePriorities(priority_calculator_); 1216 resource_manager_->PrioritizeTextures(); 1217 layer->SavePaintProperties(); 1218 layer->Update(queue_.get(), NULL); 1219 EXPECT_EQ(2, layer->fake_layer_updater()->update_count()); 1220 } 1221 1222 TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) { 1223 scoped_refptr<FakeTiledLayer> layer = 1224 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 1225 RenderSurfaceLayerList render_surface_layer_list; 1226 TestOcclusionTracker occluded; 1227 occlusion_ = &occluded; 1228 1229 layer_tree_host_->root_layer()->AddChild(layer); 1230 1231 // The tile size is 100x100. 1232 1233 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); 1234 layer->SetBounds(gfx::Size(600, 600)); 1235 CalcDrawProps(&render_surface_layer_list); 1236 1237 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); 1238 layer->draw_properties().drawable_content_rect = 1239 gfx::Rect(layer->content_bounds()); 1240 layer->draw_properties().visible_content_rect = 1241 gfx::Rect(layer->content_bounds()); 1242 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1243 1244 layer->SetTexturePriorities(priority_calculator_); 1245 resource_manager_->PrioritizeTextures(); 1246 layer->SavePaintProperties(); 1247 layer->Update(queue_.get(), &occluded); 1248 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); 1249 1250 layer->fake_layer_updater()->ClearUpdateCount(); 1251 layer->SetTexturePriorities(priority_calculator_); 1252 resource_manager_->PrioritizeTextures(); 1253 1254 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100))); 1255 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1256 layer->SavePaintProperties(); 1257 layer->Update(queue_.get(), &occluded); 1258 EXPECT_EQ(36 - 2, layer->fake_layer_updater()->update_count()); 1259 1260 layer->fake_layer_updater()->ClearUpdateCount(); 1261 layer->SetTexturePriorities(priority_calculator_); 1262 resource_manager_->PrioritizeTextures(); 1263 1264 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100))); 1265 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1266 layer->SavePaintProperties(); 1267 layer->Update(queue_.get(), &occluded); 1268 EXPECT_EQ(36, layer->fake_layer_updater()->update_count()); 1269 } 1270 1271 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) { 1272 scoped_refptr<FakeTiledLayer> layer = 1273 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 1274 RenderSurfaceLayerList render_surface_layer_list; 1275 TestOcclusionTracker occluded; 1276 occlusion_ = &occluded; 1277 1278 layer_tree_host_->root_layer()->AddChild(layer); 1279 1280 // The tile size is 100x100. 1281 1282 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); 1283 layer->SetBounds(gfx::Size(600, 600)); 1284 CalcDrawProps(&render_surface_layer_list); 1285 1286 // The partially occluded tiles (by the 150 occlusion height) are visible 1287 // beyond the occlusion, so not culled. 1288 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); 1289 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 360); 1290 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 360); 1291 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1292 1293 layer->SetTexturePriorities(priority_calculator_); 1294 resource_manager_->PrioritizeTextures(); 1295 layer->SavePaintProperties(); 1296 layer->Update(queue_.get(), &occluded); 1297 EXPECT_EQ(24 - 3, layer->fake_layer_updater()->update_count()); 1298 1299 layer->fake_layer_updater()->ClearUpdateCount(); 1300 1301 // Now the visible region stops at the edge of the occlusion so the partly 1302 // visible tiles become fully occluded. 1303 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); 1304 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 350); 1305 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 350); 1306 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1307 layer->SetTexturePriorities(priority_calculator_); 1308 resource_manager_->PrioritizeTextures(); 1309 layer->SavePaintProperties(); 1310 layer->Update(queue_.get(), &occluded); 1311 EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count()); 1312 1313 layer->fake_layer_updater()->ClearUpdateCount(); 1314 1315 // Now the visible region is even smaller than the occlusion, it should have 1316 // the same result. 1317 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150))); 1318 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 340); 1319 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 340); 1320 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1321 layer->SetTexturePriorities(priority_calculator_); 1322 resource_manager_->PrioritizeTextures(); 1323 layer->SavePaintProperties(); 1324 layer->Update(queue_.get(), &occluded); 1325 EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count()); 1326 } 1327 1328 TEST_F(TiledLayerTest, TilesNotPaintedWithoutInvalidation) { 1329 scoped_refptr<FakeTiledLayer> layer = 1330 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 1331 RenderSurfaceLayerList render_surface_layer_list; 1332 TestOcclusionTracker occluded; 1333 occlusion_ = &occluded; 1334 1335 layer_tree_host_->root_layer()->AddChild(layer); 1336 1337 // The tile size is 100x100. 1338 1339 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); 1340 layer->SetBounds(gfx::Size(600, 600)); 1341 CalcDrawProps(&render_surface_layer_list); 1342 1343 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); 1344 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 600); 1345 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 600); 1346 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1347 layer->SetTexturePriorities(priority_calculator_); 1348 resource_manager_->PrioritizeTextures(); 1349 layer->SavePaintProperties(); 1350 layer->Update(queue_.get(), &occluded); 1351 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); 1352 UpdateTextures(); 1353 1354 layer->fake_layer_updater()->ClearUpdateCount(); 1355 layer->SetTexturePriorities(priority_calculator_); 1356 resource_manager_->PrioritizeTextures(); 1357 layer->SavePaintProperties(); 1358 1359 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted 1360 // now. 1361 layer->Update(queue_.get(), &occluded); 1362 EXPECT_EQ(3, layer->fake_layer_updater()->update_count()); 1363 } 1364 1365 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndTransforms) { 1366 scoped_refptr<FakeTiledLayer> layer = 1367 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get())); 1368 RenderSurfaceLayerList render_surface_layer_list; 1369 TestOcclusionTracker occluded; 1370 occlusion_ = &occluded; 1371 1372 layer_tree_host_->root_layer()->AddChild(layer); 1373 1374 // The tile size is 100x100. 1375 1376 // This makes sure the painting works when the occluded region (in screen 1377 // space) is transformed differently than the layer. 1378 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); 1379 layer->SetBounds(gfx::Size(600, 600)); 1380 CalcDrawProps(&render_surface_layer_list); 1381 gfx::Transform screen_transform; 1382 screen_transform.Scale(0.5, 0.5); 1383 layer->draw_properties().screen_space_transform = screen_transform; 1384 layer->draw_properties().target_space_transform = screen_transform; 1385 1386 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50))); 1387 layer->draw_properties().drawable_content_rect = 1388 gfx::Rect(layer->content_bounds()); 1389 layer->draw_properties().visible_content_rect = 1390 gfx::Rect(layer->content_bounds()); 1391 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1392 layer->SetTexturePriorities(priority_calculator_); 1393 resource_manager_->PrioritizeTextures(); 1394 layer->SavePaintProperties(); 1395 layer->Update(queue_.get(), &occluded); 1396 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count()); 1397 } 1398 1399 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) { 1400 scoped_refptr<FakeTiledLayer> layer = 1401 new FakeTiledLayer(resource_manager_.get()); 1402 RenderSurfaceLayerList render_surface_layer_list; 1403 TestOcclusionTracker occluded; 1404 occlusion_ = &occluded; 1405 1406 scoped_refptr<FakeTiledLayer> scale_layer = 1407 new FakeTiledLayer(resource_manager_.get()); 1408 gfx::Transform scale_transform; 1409 scale_transform.Scale(2.0, 2.0); 1410 scale_layer->SetTransform(scale_transform); 1411 1412 layer_tree_host_->root_layer()->AddChild(scale_layer); 1413 1414 // The tile size is 100x100. 1415 1416 // This makes sure the painting works when the content space is scaled to 1417 // a different layer space. 1418 layer_tree_host_->SetViewportSize(gfx::Size(600, 600)); 1419 layer->SetBounds(gfx::Size(300, 300)); 1420 scale_layer->AddChild(layer); 1421 CalcDrawProps(&render_surface_layer_list); 1422 EXPECT_FLOAT_EQ(2.f, layer->contents_scale_x()); 1423 EXPECT_FLOAT_EQ(2.f, layer->contents_scale_y()); 1424 EXPECT_EQ(gfx::Size(600, 600).ToString(), 1425 layer->content_bounds().ToString()); 1426 1427 // No tiles are covered by the 300x50 occlusion. 1428 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50))); 1429 layer->draw_properties().drawable_content_rect = 1430 gfx::Rect(layer->bounds()); 1431 layer->draw_properties().visible_content_rect = 1432 gfx::Rect(layer->content_bounds()); 1433 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1434 layer->SetTexturePriorities(priority_calculator_); 1435 resource_manager_->PrioritizeTextures(); 1436 layer->SavePaintProperties(); 1437 layer->Update(queue_.get(), &occluded); 1438 int visible_tiles1 = 6 * 6; 1439 EXPECT_EQ(visible_tiles1, layer->fake_layer_updater()->update_count()); 1440 1441 layer->fake_layer_updater()->ClearUpdateCount(); 1442 1443 // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still. 1444 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100))); 1445 layer->draw_properties().drawable_content_rect = 1446 gfx::Rect(layer->bounds()); 1447 layer->draw_properties().visible_content_rect = 1448 gfx::Rect(layer->content_bounds()); 1449 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1450 layer->SetTexturePriorities(priority_calculator_); 1451 resource_manager_->PrioritizeTextures(); 1452 layer->SavePaintProperties(); 1453 layer->Update(queue_.get(), &occluded); 1454 int visible_tiles2 = 6 * 6 - 3; 1455 EXPECT_EQ(visible_tiles2, layer->fake_layer_updater()->update_count()); 1456 1457 layer->fake_layer_updater()->ClearUpdateCount(); 1458 1459 // This makes sure content scaling and transforms work together. 1460 // When the tiles are scaled down by half, they are 50x50 each in the 1461 // screen. 1462 gfx::Transform screen_transform; 1463 screen_transform.Scale(0.5, 0.5); 1464 layer->draw_properties().screen_space_transform = screen_transform; 1465 layer->draw_properties().target_space_transform = screen_transform; 1466 1467 // An occlusion of 150x100 will cover 3*2 = 6 tiles. 1468 occluded.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100))); 1469 1470 gfx::Rect layer_bounds_rect(layer->bounds()); 1471 layer->draw_properties().drawable_content_rect = 1472 gfx::ScaleToEnclosingRect(layer_bounds_rect, 0.5f); 1473 layer->draw_properties().visible_content_rect = 1474 gfx::Rect(layer->content_bounds()); 1475 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600)); 1476 layer->SetTexturePriorities(priority_calculator_); 1477 resource_manager_->PrioritizeTextures(); 1478 layer->SavePaintProperties(); 1479 layer->Update(queue_.get(), &occluded); 1480 int visible_tiles3 = 6 * 6 - 6; 1481 EXPECT_EQ(visible_tiles3, layer->fake_layer_updater()->update_count()); 1482 } 1483 1484 TEST_F(TiledLayerTest, DontAllocateContentsWhenTargetSurfaceCantBeAllocated) { 1485 // Tile size is 100x100. 1486 gfx::Rect root_rect(0, 0, 300, 200); 1487 gfx::Rect child_rect(0, 0, 300, 100); 1488 gfx::Rect child2_rect(0, 100, 300, 100); 1489 1490 scoped_refptr<FakeTiledLayer> root = make_scoped_refptr( 1491 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); 1492 scoped_refptr<Layer> surface = Layer::Create(); 1493 scoped_refptr<FakeTiledLayer> child = make_scoped_refptr( 1494 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); 1495 scoped_refptr<FakeTiledLayer> child2 = make_scoped_refptr( 1496 new FakeTiledLayer(layer_tree_host_->contents_texture_manager())); 1497 1498 root->SetBounds(root_rect.size()); 1499 root->draw_properties().drawable_content_rect = root_rect; 1500 root->draw_properties().visible_content_rect = root_rect; 1501 root->AddChild(surface); 1502 1503 surface->SetForceRenderSurface(true); 1504 surface->SetOpacity(0.5); 1505 surface->AddChild(child); 1506 surface->AddChild(child2); 1507 1508 child->SetBounds(child_rect.size()); 1509 child->SetPosition(child_rect.origin()); 1510 child->draw_properties().visible_content_rect = child_rect; 1511 child->draw_properties().drawable_content_rect = root_rect; 1512 1513 child2->SetBounds(child2_rect.size()); 1514 child2->SetPosition(child2_rect.origin()); 1515 child2->draw_properties().visible_content_rect = child2_rect; 1516 child2->draw_properties().drawable_content_rect = root_rect; 1517 1518 layer_tree_host_->SetRootLayer(root); 1519 layer_tree_host_->SetViewportSize(root_rect.size()); 1520 1521 // With a huge memory limit, all layers should update and push their textures. 1522 root->InvalidateContentRect(root_rect); 1523 child->InvalidateContentRect(child_rect); 1524 child2->InvalidateContentRect(child2_rect); 1525 layer_tree_host_->UpdateLayers(queue_.get()); 1526 { 1527 UpdateTextures(); 1528 EXPECT_EQ(6, root->fake_layer_updater()->update_count()); 1529 EXPECT_EQ(3, child->fake_layer_updater()->update_count()); 1530 EXPECT_EQ(3, child2->fake_layer_updater()->update_count()); 1531 EXPECT_FALSE(queue_->HasMoreUpdates()); 1532 1533 root->fake_layer_updater()->ClearUpdateCount(); 1534 child->fake_layer_updater()->ClearUpdateCount(); 1535 child2->fake_layer_updater()->ClearUpdateCount(); 1536 1537 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( 1538 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); 1539 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( 1540 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); 1541 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( 1542 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); 1543 LayerPushPropertiesTo(child2.get(), child2_impl.get()); 1544 LayerPushPropertiesTo(child.get(), child_impl.get()); 1545 LayerPushPropertiesTo(root.get(), root_impl.get()); 1546 1547 for (unsigned i = 0; i < 3; ++i) { 1548 for (unsigned j = 0; j < 2; ++j) 1549 EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j)); 1550 EXPECT_TRUE(child_impl->HasResourceIdForTileAt(i, 0)); 1551 EXPECT_TRUE(child2_impl->HasResourceIdForTileAt(i, 0)); 1552 } 1553 } 1554 layer_tree_host_->CommitComplete(); 1555 1556 // With a memory limit that includes only the root layer (3x2 tiles) and half 1557 // the surface that the child layers draw into, the child layers will not be 1558 // allocated. If the surface isn't accounted for, then one of the children 1559 // would fit within the memory limit. 1560 root->InvalidateContentRect(root_rect); 1561 child->InvalidateContentRect(child_rect); 1562 child2->InvalidateContentRect(child2_rect); 1563 1564 size_t memory_limit = (3 * 2 + 3 * 1) * (100 * 100) * 4; 1565 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( 1566 memory_limit); 1567 layer_tree_host_->UpdateLayers(queue_.get()); 1568 { 1569 UpdateTextures(); 1570 EXPECT_EQ(6, root->fake_layer_updater()->update_count()); 1571 EXPECT_EQ(0, child->fake_layer_updater()->update_count()); 1572 EXPECT_EQ(0, child2->fake_layer_updater()->update_count()); 1573 EXPECT_FALSE(queue_->HasMoreUpdates()); 1574 1575 root->fake_layer_updater()->ClearUpdateCount(); 1576 child->fake_layer_updater()->ClearUpdateCount(); 1577 child2->fake_layer_updater()->ClearUpdateCount(); 1578 1579 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( 1580 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); 1581 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( 1582 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); 1583 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( 1584 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); 1585 LayerPushPropertiesTo(child2.get(), child2_impl.get()); 1586 LayerPushPropertiesTo(child.get(), child_impl.get()); 1587 LayerPushPropertiesTo(root.get(), root_impl.get()); 1588 1589 for (unsigned i = 0; i < 3; ++i) { 1590 for (unsigned j = 0; j < 2; ++j) 1591 EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j)); 1592 EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0)); 1593 EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0)); 1594 } 1595 } 1596 layer_tree_host_->CommitComplete(); 1597 1598 // With a memory limit that includes only half the root layer, no contents 1599 // will be allocated. If render surface memory wasn't accounted for, there is 1600 // enough space for one of the children layers, but they draw into a surface 1601 // that can't be allocated. 1602 root->InvalidateContentRect(root_rect); 1603 child->InvalidateContentRect(child_rect); 1604 child2->InvalidateContentRect(child2_rect); 1605 1606 memory_limit = (3 * 1) * (100 * 100) * 4; 1607 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes( 1608 memory_limit); 1609 layer_tree_host_->UpdateLayers(queue_.get()); 1610 { 1611 UpdateTextures(); 1612 EXPECT_EQ(0, root->fake_layer_updater()->update_count()); 1613 EXPECT_EQ(0, child->fake_layer_updater()->update_count()); 1614 EXPECT_EQ(0, child2->fake_layer_updater()->update_count()); 1615 EXPECT_FALSE(queue_->HasMoreUpdates()); 1616 1617 root->fake_layer_updater()->ClearUpdateCount(); 1618 child->fake_layer_updater()->ClearUpdateCount(); 1619 child2->fake_layer_updater()->ClearUpdateCount(); 1620 1621 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr( 1622 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id())); 1623 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr( 1624 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id())); 1625 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr( 1626 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id())); 1627 LayerPushPropertiesTo(child2.get(), child2_impl.get()); 1628 LayerPushPropertiesTo(child.get(), child_impl.get()); 1629 LayerPushPropertiesTo(root.get(), root_impl.get()); 1630 1631 for (unsigned i = 0; i < 3; ++i) { 1632 for (unsigned j = 0; j < 2; ++j) 1633 EXPECT_FALSE(root_impl->HasResourceIdForTileAt(i, j)); 1634 EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0)); 1635 EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0)); 1636 } 1637 } 1638 layer_tree_host_->CommitComplete(); 1639 1640 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), 1641 resource_provider_.get()); 1642 layer_tree_host_->SetRootLayer(NULL); 1643 } 1644 1645 class TrackingLayerPainter : public LayerPainter { 1646 public: 1647 static scoped_ptr<TrackingLayerPainter> Create() { 1648 return make_scoped_ptr(new TrackingLayerPainter()); 1649 } 1650 1651 virtual void Paint(SkCanvas* canvas, const gfx::Rect& content_rect) OVERRIDE { 1652 painted_rect_ = content_rect; 1653 } 1654 1655 gfx::Rect PaintedRect() const { return painted_rect_; } 1656 void ResetPaintedRect() { painted_rect_ = gfx::Rect(); } 1657 1658 private: 1659 gfx::Rect painted_rect_; 1660 }; 1661 1662 class UpdateTrackingTiledLayer : public FakeTiledLayer { 1663 public: 1664 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager) 1665 : FakeTiledLayer(manager) { 1666 scoped_ptr<TrackingLayerPainter> painter(TrackingLayerPainter::Create()); 1667 tracking_layer_painter_ = painter.get(); 1668 layer_updater_ = 1669 BitmapContentLayerUpdater::Create(painter.PassAs<LayerPainter>(), 1670 &stats_instrumentation_, 1671 0); 1672 } 1673 1674 TrackingLayerPainter* tracking_layer_painter() const { 1675 return tracking_layer_painter_; 1676 } 1677 1678 private: 1679 virtual LayerUpdater* Updater() const OVERRIDE { 1680 return layer_updater_.get(); 1681 } 1682 virtual ~UpdateTrackingTiledLayer() {} 1683 1684 TrackingLayerPainter* tracking_layer_painter_; 1685 scoped_refptr<BitmapContentLayerUpdater> layer_updater_; 1686 FakeRenderingStatsInstrumentation stats_instrumentation_; 1687 }; 1688 1689 TEST_F(TiledLayerTest, NonIntegerContentsScaleIsNotDistortedDuringPaint) { 1690 scoped_refptr<UpdateTrackingTiledLayer> layer = 1691 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get())); 1692 1693 layer_tree_host_->root_layer()->AddChild(layer); 1694 1695 gfx::Rect layer_rect(0, 0, 30, 31); 1696 layer->SetPosition(layer_rect.origin()); 1697 layer->SetBounds(layer_rect.size()); 1698 layer->UpdateContentsScale(1.5f); 1699 1700 gfx::Rect content_rect(0, 0, 45, 47); 1701 EXPECT_EQ(content_rect.size(), layer->content_bounds()); 1702 layer->draw_properties().visible_content_rect = content_rect; 1703 layer->draw_properties().drawable_content_rect = content_rect; 1704 1705 layer->SetTexturePriorities(priority_calculator_); 1706 resource_manager_->PrioritizeTextures(); 1707 layer->SavePaintProperties(); 1708 1709 // Update the whole tile. 1710 layer->Update(queue_.get(), NULL); 1711 layer->tracking_layer_painter()->ResetPaintedRect(); 1712 1713 EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect()); 1714 UpdateTextures(); 1715 1716 // Invalidate the entire layer in content space. When painting, the rect given 1717 // to webkit should match the layer's bounds. 1718 layer->InvalidateContentRect(content_rect); 1719 layer->Update(queue_.get(), NULL); 1720 1721 // Rounding leads to an extra pixel. 1722 gfx::Rect expanded_layer_rect(layer_rect); 1723 expanded_layer_rect.set_height(32); 1724 EXPECT_RECT_EQ(expanded_layer_rect, 1725 layer->tracking_layer_painter()->PaintedRect()); 1726 } 1727 1728 TEST_F(TiledLayerTest, 1729 NonIntegerContentsScaleIsNotDistortedDuringInvalidation) { 1730 scoped_refptr<UpdateTrackingTiledLayer> layer = 1731 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get())); 1732 1733 layer_tree_host_->root_layer()->AddChild(layer); 1734 1735 gfx::Rect layer_rect(0, 0, 30, 31); 1736 layer->SetPosition(layer_rect.origin()); 1737 layer->SetBounds(layer_rect.size()); 1738 layer->UpdateContentsScale(1.3f); 1739 1740 gfx::Rect content_rect(layer->content_bounds()); 1741 layer->draw_properties().visible_content_rect = content_rect; 1742 layer->draw_properties().drawable_content_rect = content_rect; 1743 1744 layer->SetTexturePriorities(priority_calculator_); 1745 resource_manager_->PrioritizeTextures(); 1746 layer->SavePaintProperties(); 1747 1748 // Update the whole tile. 1749 layer->Update(queue_.get(), NULL); 1750 layer->tracking_layer_painter()->ResetPaintedRect(); 1751 1752 EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect()); 1753 UpdateTextures(); 1754 1755 // Invalidate the entire layer in layer space. When painting, the rect given 1756 // to webkit should match the layer's bounds. 1757 layer->SetNeedsDisplayRect(layer_rect); 1758 layer->Update(queue_.get(), NULL); 1759 1760 // Rounding leads to an extra pixel. 1761 gfx::Rect expanded_layer_rect(layer_rect); 1762 expanded_layer_rect.set_height(32); 1763 EXPECT_RECT_EQ(expanded_layer_rect, 1764 layer->tracking_layer_painter()->PaintedRect()); 1765 } 1766 1767 } // namespace 1768 } // namespace cc 1769