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