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