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