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"
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"
33 class TestOcclusionTracker
: public OcclusionTracker
<Layer
> {
35 TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) {
36 stack_
.push_back(StackObject());
39 void SetRenderTarget(Layer
* render_target
) {
40 stack_
.back().target
= render_target
;
43 void SetOcclusion(const SimpleEnclosedRegion
& occlusion
) {
44 stack_
.back().occlusion_from_inside_target
= occlusion
;
48 class SynchronousOutputSurfaceLayerTreeHost
: public LayerTreeHost
{
50 static scoped_ptr
<SynchronousOutputSurfaceLayerTreeHost
> Create(
51 LayerTreeHostClient
* client
,
52 SharedBitmapManager
* manager
,
53 const LayerTreeSettings
& settings
,
54 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
) {
55 return make_scoped_ptr(new SynchronousOutputSurfaceLayerTreeHost(
56 client
, manager
, settings
, impl_task_runner
));
59 ~SynchronousOutputSurfaceLayerTreeHost() override
{}
61 bool EnsureOutputSurfaceCreated() {
62 base::MessageLoop::current()->PostDelayedTask(
64 run_loop_
.QuitClosure(),
65 base::TimeDelta::FromSeconds(5));
67 return output_surface_created_
;
70 void OnCreateAndInitializeOutputSurfaceAttempted(bool success
) override
{
71 LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success
);
72 output_surface_created_
= success
;
77 SynchronousOutputSurfaceLayerTreeHost(
78 LayerTreeHostClient
* client
,
79 SharedBitmapManager
* manager
,
80 const LayerTreeSettings
& settings
,
81 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
)
82 : LayerTreeHost(client
, manager
, NULL
, settings
),
83 output_surface_created_(false) {
84 LayerTreeHost::InitializeThreaded(base::MessageLoopProxy::current(),
89 bool output_surface_created_
;
90 base::RunLoop run_loop_
;
93 class TiledLayerTest
: public testing::Test
{
97 output_surface_(FakeOutputSurface::Create3d()),
98 queue_(make_scoped_ptr(new ResourceUpdateQueue
)),
99 impl_thread_("ImplThread"),
100 fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D
),
101 occlusion_(nullptr) {
102 settings_
.max_partial_texture_updates
= std::numeric_limits
<size_t>::max();
103 settings_
.layer_transforms_should_scale_layer_contents
= true;
106 void SetUp() override
{
107 impl_thread_
.Start();
108 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
109 layer_tree_host_
= SynchronousOutputSurfaceLayerTreeHost::Create(
110 &fake_layer_tree_host_client_
,
111 shared_bitmap_manager_
.get(),
113 impl_thread_
.message_loop_proxy());
114 fake_layer_tree_host_client_
.SetLayerTreeHost(layer_tree_host_
.get());
115 proxy_
= layer_tree_host_
->proxy();
116 resource_manager_
= PrioritizedResourceManager::Create(proxy_
);
117 layer_tree_host_
->SetLayerTreeHostClientReady();
118 CHECK(layer_tree_host_
->EnsureOutputSurfaceCreated());
119 layer_tree_host_
->SetRootLayer(Layer::Create());
121 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
123 DebugScopedSetImplThreadAndMainThreadBlocked
124 impl_thread_and_main_thread_blocked(proxy_
);
125 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
126 shared_bitmap_manager_
.get(),
132 host_impl_
= make_scoped_ptr(
133 new FakeLayerTreeHostImpl(proxy_
, shared_bitmap_manager_
.get()));
136 virtual ~TiledLayerTest() {
137 ResourceManagerClearAllMemory(resource_manager_
.get(),
138 resource_provider_
.get());
140 DebugScopedSetImplThreadAndMainThreadBlocked
141 impl_thread_and_main_thread_blocked(proxy_
);
142 resource_provider_
= nullptr;
143 host_impl_
= nullptr;
146 void ResourceManagerClearAllMemory(
147 PrioritizedResourceManager
* resource_manager
,
148 ResourceProvider
* resource_provider
) {
150 DebugScopedSetImplThreadAndMainThreadBlocked
151 impl_thread_and_main_thread_blocked(proxy_
);
152 resource_manager
->ClearAllMemory(resource_provider
);
153 resource_manager
->ReduceMemory(resource_provider
);
155 resource_manager
->UnlinkAndClearEvictedBackings();
158 void UpdateTextures() {
159 DebugScopedSetImplThreadAndMainThreadBlocked
160 impl_thread_and_main_thread_blocked(proxy_
);
162 scoped_ptr
<ResourceUpdateController
> update_controller
=
163 ResourceUpdateController::Create(nullptr,
164 proxy_
->ImplThreadTaskRunner(),
166 resource_provider_
.get());
167 update_controller
->Finalize();
168 queue_
= make_scoped_ptr(new ResourceUpdateQueue
);
171 void LayerPushPropertiesTo(FakeTiledLayer
* layer
,
172 FakeTiledLayerImpl
* layer_impl
) {
173 DebugScopedSetImplThreadAndMainThreadBlocked
174 impl_thread_and_main_thread_blocked(proxy_
);
175 layer
->PushPropertiesTo(layer_impl
);
176 layer
->ResetNumDependentsNeedPushProperties();
179 void LayerUpdate(FakeTiledLayer
* layer
, TestOcclusionTracker
* occluded
) {
180 DebugScopedSetMainThread
main_thread(proxy_
);
181 layer
->Update(queue_
.get(), occluded
);
184 void CalcDrawProps(RenderSurfaceLayerList
* render_surface_layer_list
) {
186 occlusion_
->SetRenderTarget(layer_tree_host_
->root_layer());
188 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting
inputs(
189 layer_tree_host_
->root_layer(),
190 layer_tree_host_
->device_viewport_size(),
191 render_surface_layer_list
);
192 inputs
.device_scale_factor
= layer_tree_host_
->device_scale_factor();
193 inputs
.max_texture_size
=
194 layer_tree_host_
->GetRendererCapabilities().max_texture_size
;
195 inputs
.can_adjust_raster_scales
= true;
196 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
199 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
200 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
) {
201 scoped_refptr
<FakeTiledLayer
> layer2
;
202 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
;
203 return UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
206 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
207 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
,
208 const scoped_refptr
<FakeTiledLayer
>& layer2
,
209 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl2
) {
211 resource_manager_
->ClearPriorities();
213 layer1
->SetTexturePriorities(priority_calculator_
);
215 layer2
->SetTexturePriorities(priority_calculator_
);
216 resource_manager_
->PrioritizeTextures();
218 // Save paint properties
220 layer1
->SavePaintProperties();
222 layer2
->SavePaintProperties();
226 layer1
->Update(queue_
.get(), occlusion_
);
228 layer2
->Update(queue_
.get(), occlusion_
);
230 bool needs_update
= false;
232 needs_update
|= layer1
->NeedsIdlePaint();
234 needs_update
|= layer2
->NeedsIdlePaint();
236 // Update textures and push.
239 LayerPushPropertiesTo(layer1
.get(), layer_impl1
.get());
241 LayerPushPropertiesTo(layer2
.get(), layer_impl2
.get());
248 LayerTreeSettings settings_
;
249 FakeOutputSurfaceClient output_surface_client_
;
250 scoped_ptr
<OutputSurface
> output_surface_
;
251 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
252 scoped_ptr
<ResourceProvider
> resource_provider_
;
253 scoped_ptr
<ResourceUpdateQueue
> queue_
;
254 PriorityCalculator priority_calculator_
;
255 base::Thread impl_thread_
;
256 FakeLayerTreeHostClient fake_layer_tree_host_client_
;
257 scoped_ptr
<SynchronousOutputSurfaceLayerTreeHost
> layer_tree_host_
;
258 scoped_ptr
<FakeLayerTreeHostImpl
> host_impl_
;
259 scoped_ptr
<PrioritizedResourceManager
> resource_manager_
;
260 TestOcclusionTracker
* occlusion_
;
263 TEST_F(TiledLayerTest
, PushDirtyTiles
) {
264 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
266 scoped_refptr
<FakeTiledLayer
> layer
=
267 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
268 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
269 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
270 RenderSurfaceLayerList render_surface_layer_list
;
272 layer_tree_host_
->root_layer()->AddChild(layer
);
274 // The tile size is 100x100, so this invalidates and then paints two tiles.
275 layer
->SetBounds(gfx::Size(100, 200));
276 CalcDrawProps(&render_surface_layer_list
);
277 UpdateAndPush(layer
, layer_impl
);
279 // We should have both tiles on the impl side.
280 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
281 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
283 // Invalidates both tiles, but then only update one of them.
284 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
285 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
286 UpdateAndPush(layer
, layer_impl
);
288 // We should only have the first tile since the other tile was invalidated but
290 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
291 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
294 TEST_F(TiledLayerTest
, Scale
) {
295 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
297 layer_tree_host_
->SetDeviceScaleFactor(1.5);
299 scoped_refptr
<FakeTiledLayer
> layer
=
300 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
301 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
302 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
303 RenderSurfaceLayerList render_surface_layer_list
;
305 layer_tree_host_
->root_layer()->AddChild(layer
);
307 layer
->SetBounds(gfx::Size(100, 200));
308 CalcDrawProps(&render_surface_layer_list
);
310 // Change the width so that it doesn't divide cleanly by the scale.
311 layer
->SetBounds(gfx::Size(101, 200));
312 UpdateAndPush(layer
, layer_impl
);
314 EXPECT_EQ(1.5, layer
->fake_layer_updater()->last_contents_width_scale());
317 TEST_F(TiledLayerTest
, PushOccludedDirtyTiles
) {
318 scoped_refptr
<FakeTiledLayer
> layer
=
319 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
320 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
321 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
322 TestOcclusionTracker occluded
;
323 occlusion_
= &occluded
;
324 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
326 layer_tree_host_
->root_layer()->AddChild(layer
);
329 RenderSurfaceLayerList render_surface_layer_list
;
331 // The tile size is 100x100, so this invalidates and then paints two tiles.
332 layer
->SetBounds(gfx::Size(100, 200));
333 CalcDrawProps(&render_surface_layer_list
);
334 UpdateAndPush(layer
, layer_impl
);
336 // We should have both tiles on the impl side.
337 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
338 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
342 RenderSurfaceLayerList render_surface_layer_list
;
344 // Invalidates part of the top tile...
345 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
346 // ....but the area is occluded.
347 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50)));
348 CalcDrawProps(&render_surface_layer_list
);
349 UpdateAndPush(layer
, layer_impl
);
351 // We should still have both tiles, as part of the top tile is still
353 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
354 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
358 TEST_F(TiledLayerTest
, PushDeletedTiles
) {
359 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
361 scoped_refptr
<FakeTiledLayer
> layer
=
362 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
363 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
364 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
365 RenderSurfaceLayerList render_surface_layer_list
;
367 layer_tree_host_
->root_layer()->AddChild(layer
);
369 // The tile size is 100x100, so this invalidates and then paints two tiles.
370 layer
->SetBounds(gfx::Size(100, 200));
371 CalcDrawProps(&render_surface_layer_list
);
372 UpdateAndPush(layer
, layer_impl
);
374 // We should have both tiles on the impl side.
375 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
376 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
378 resource_manager_
->ClearPriorities();
379 ResourceManagerClearAllMemory(resource_manager_
.get(),
380 resource_provider_
.get());
381 resource_manager_
->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
383 // This should drop the tiles on the impl thread.
384 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
386 // We should now have no textures on the impl thread.
387 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
388 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
390 // This should recreate and update one of the deleted textures.
391 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
392 UpdateAndPush(layer
, layer_impl
);
394 // We should have one tiles on the impl side.
395 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
396 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
399 TEST_F(TiledLayerTest
, PushIdlePaintTiles
) {
400 scoped_refptr
<FakeTiledLayer
> layer
=
401 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
402 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
403 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
404 RenderSurfaceLayerList render_surface_layer_list
;
406 layer_tree_host_
->root_layer()->AddChild(layer
);
408 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the
409 // center. This paints 1 visible of the 25 invalid tiles.
410 layer
->SetBounds(gfx::Size(500, 500));
411 CalcDrawProps(&render_surface_layer_list
);
412 layer
->draw_properties().visible_content_rect
= gfx::Rect(200, 200, 100, 100);
413 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
414 // We should need idle-painting for surrounding tiles.
415 EXPECT_TRUE(needs_update
);
417 // We should have one tile on the impl side.
418 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(2, 2));
420 // For the next four updates, we should detect we still need idle painting.
421 for (int i
= 0; i
< 4; i
++) {
422 needs_update
= UpdateAndPush(layer
, layer_impl
);
423 EXPECT_TRUE(needs_update
);
426 // We should always finish painting eventually.
427 for (int i
= 0; i
< 20; i
++)
428 needs_update
= UpdateAndPush(layer
, layer_impl
);
430 // We should have pre-painted all of the surrounding tiles.
431 for (int i
= 0; i
< 5; i
++) {
432 for (int j
= 0; j
< 5; j
++)
433 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
436 EXPECT_FALSE(needs_update
);
439 TEST_F(TiledLayerTest
, PredictivePainting
) {
440 scoped_refptr
<FakeTiledLayer
> layer
=
441 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
442 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
443 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
445 layer_tree_host_
->root_layer()->AddChild(layer
);
447 // Prepainting should occur in the scroll direction first, and the
448 // visible rect should be extruded only along the dominant axis.
449 gfx::Vector2d directions
[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0),
450 gfx::Vector2d(0, -10), gfx::Vector2d(0, 10),
451 gfx::Vector2d(10, 20),
452 gfx::Vector2d(-20, 10) };
453 // We should push all tiles that touch the extruded visible rect.
454 gfx::Rect pushed_visible_tiles
[6] = {
455 gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2),
456 gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1)
458 // The first pre-paint should also paint first in the scroll
459 // direction so we should find one additional tile in the scroll direction.
460 gfx::Rect pushed_prepaint_tiles
[6] = {
461 gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3),
462 gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1)
464 for (int k
= 0; k
< 6; k
++) {
465 // The tile size is 100x100. Setup 5x5 tiles with one visible tile
467 gfx::Size bounds
= gfx::Size(500, 500);
468 gfx::Rect visible_rect
= gfx::Rect(200, 200, 100, 100);
469 gfx::Rect previous_visible_rect
=
470 gfx::Rect(visible_rect
.origin() + directions
[k
], visible_rect
.size());
471 gfx::Rect next_visible_rect
=
472 gfx::Rect(visible_rect
.origin() - directions
[k
], visible_rect
.size());
474 // Setup. Use the previous_visible_rect to setup the prediction for next
476 layer
->SetBounds(bounds
);
478 RenderSurfaceLayerList render_surface_layer_list
;
479 CalcDrawProps(&render_surface_layer_list
);
480 layer
->draw_properties().visible_content_rect
= previous_visible_rect
;
481 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
483 // Invalidate and move the visible_rect in the scroll direction.
484 // Check that the correct tiles have been painted in the visible pass.
485 layer
->SetNeedsDisplay();
486 layer
->draw_properties().visible_content_rect
= 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_visible_tiles
[k
].Contains(i
, j
));
494 // Move the transform in the same direction without invalidating.
495 // Check that non-visible pre-painting occured in the correct direction.
496 // Ignore diagonal scrolls here (k > 3) as these have new visible content
499 layer
->draw_properties().visible_content_rect
= next_visible_rect
;
500 needs_update
= UpdateAndPush(layer
, layer_impl
);
501 for (int i
= 0; i
< 5; i
++) {
502 for (int j
= 0; j
< 5; j
++)
503 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
504 pushed_prepaint_tiles
[k
].Contains(i
, j
));
508 // We should always finish painting eventually.
509 for (int i
= 0; i
< 20; i
++)
510 needs_update
= UpdateAndPush(layer
, layer_impl
);
511 EXPECT_FALSE(needs_update
);
515 TEST_F(TiledLayerTest
, PushTilesAfterIdlePaintFailed
) {
516 // Start with 2mb of memory, but the test is going to try to use just more
517 // than 1mb, so we reduce to 1mb later.
518 resource_manager_
->SetMaxMemoryLimitBytes(2 * 1024 * 1024);
519 scoped_refptr
<FakeTiledLayer
> layer1
=
520 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
521 scoped_ptr
<FakeTiledLayerImpl
> layer_impl1
=
522 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
523 scoped_refptr
<FakeTiledLayer
> layer2
=
524 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
525 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
=
526 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
527 RenderSurfaceLayerList render_surface_layer_list
;
529 layer_tree_host_
->root_layer()->AddChild(layer1
);
530 layer_tree_host_
->root_layer()->AddChild(layer2
);
532 // For this test we have two layers. layer1 exhausts most texture memory,
533 // leaving room for 2 more tiles from layer2, but not all three tiles. First
534 // we paint layer1, and one tile from layer2. Then when we idle paint layer2,
535 // we will fail on the third tile of layer2, and this should not leave the
536 // second tile in a bad state.
538 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough
539 // for 2 tiles only in the other layer.
540 gfx::Rect
layer1_rect(0, 0, 100, 2400);
542 // This requires 4*30000 bytes of memory.
543 gfx::Rect
layer2_rect(0, 0, 100, 300);
545 // Paint a single tile in layer2 so that it will idle paint.
546 layer1
->SetBounds(layer1_rect
.size());
547 layer2
->SetBounds(layer2_rect
.size());
548 CalcDrawProps(&render_surface_layer_list
);
549 layer1
->draw_properties().visible_content_rect
= layer1_rect
;
550 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
551 bool needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
552 // We should need idle-painting for both remaining tiles in layer2.
553 EXPECT_TRUE(needs_update
);
555 // Reduce our memory limits to 1mb.
556 resource_manager_
->SetMaxMemoryLimitBytes(1024 * 1024);
558 // Now idle paint layer2. We are going to run out of memory though!
559 // Oh well, commit the frame and push.
560 for (int i
= 0; i
< 4; i
++) {
561 needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
564 // Sanity check, we should have textures for the big layer.
565 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 0));
566 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 23));
568 // We should only have the first two tiles from layer2 since
569 // it failed to idle update the last tile.
570 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
571 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
572 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
573 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
575 EXPECT_FALSE(needs_update
);
576 EXPECT_FALSE(layer_impl2
->HasResourceIdForTileAt(0, 2));
579 TEST_F(TiledLayerTest
, PushIdlePaintedOccludedTiles
) {
580 scoped_refptr
<FakeTiledLayer
> layer
=
581 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
582 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
583 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
584 RenderSurfaceLayerList render_surface_layer_list
;
585 TestOcclusionTracker occluded
;
586 occlusion_
= &occluded
;
588 layer_tree_host_
->root_layer()->AddChild(layer
);
590 // The tile size is 100x100, so this invalidates one occluded tile, culls it
591 // during paint, but prepaints it.
592 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100)));
594 layer
->SetBounds(gfx::Size(100, 100));
595 CalcDrawProps(&render_surface_layer_list
);
596 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
597 UpdateAndPush(layer
, layer_impl
);
599 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
602 TEST_F(TiledLayerTest
, PushTilesMarkedDirtyDuringPaint
) {
603 scoped_refptr
<FakeTiledLayer
> layer
=
604 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
605 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
606 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
607 RenderSurfaceLayerList render_surface_layer_list
;
609 layer_tree_host_
->root_layer()->AddChild(layer
);
611 // The tile size is 100x100, so this invalidates and then paints two tiles.
612 // However, during the paint, we invalidate one of the tiles. This should
613 // not prevent the tile from being pushed.
614 layer
->fake_layer_updater()->SetRectToInvalidate(
615 gfx::Rect(0, 50, 100, 50), layer
.get());
616 layer
->SetBounds(gfx::Size(100, 200));
617 CalcDrawProps(&render_surface_layer_list
);
618 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
619 UpdateAndPush(layer
, layer_impl
);
621 // We should have both tiles on the impl side.
622 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
623 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
626 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer
) {
627 scoped_refptr
<FakeTiledLayer
> layer1
=
628 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
629 scoped_refptr
<FakeTiledLayer
> layer2
=
630 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
631 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
632 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
633 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
634 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
635 RenderSurfaceLayerList render_surface_layer_list
;
637 layer_tree_host_
->root_layer()->AddChild(layer1
);
638 layer_tree_host_
->root_layer()->AddChild(layer2
);
640 // Invalidate a tile on layer1, during update of layer 2.
641 layer2
->fake_layer_updater()->SetRectToInvalidate(
642 gfx::Rect(0, 50, 100, 50), layer1
.get());
643 layer1
->SetBounds(gfx::Size(100, 200));
644 layer2
->SetBounds(gfx::Size(100, 200));
645 CalcDrawProps(&render_surface_layer_list
);
646 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
647 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
648 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
650 // We should have both tiles on the impl side for all layers.
651 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
652 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
653 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
654 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
657 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
) {
658 scoped_refptr
<FakeTiledLayer
> layer1
=
659 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
660 scoped_refptr
<FakeTiledLayer
> layer2
=
661 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
662 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
663 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
664 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
665 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
666 RenderSurfaceLayerList render_surface_layer_list
;
668 layer_tree_host_
->root_layer()->AddChild(layer1
);
669 layer_tree_host_
->root_layer()->AddChild(layer2
);
671 layer1
->fake_layer_updater()->SetRectToInvalidate(
672 gfx::Rect(0, 50, 100, 50), layer2
.get());
673 layer1
->SetBounds(gfx::Size(100, 200));
674 layer2
->SetBounds(gfx::Size(100, 200));
675 CalcDrawProps(&render_surface_layer_list
);
676 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
677 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
678 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
680 // We should have both tiles on the impl side for all layers.
681 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
682 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
683 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
684 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
687 TEST_F(TiledLayerTest
, PaintSmallAnimatedLayersImmediately
) {
688 // Create a LayerTreeHost that has the right viewportsize,
689 // so the layer is considered small enough.
690 bool run_out_of_memory
[2] = { false, true };
691 for (int i
= 0; i
< 2; i
++) {
692 // Create a layer with 5x5 tiles, with 4x4 size viewport.
693 int viewport_width
= 4 * FakeTiledLayer::tile_size().width();
694 int viewport_height
= 4 * FakeTiledLayer::tile_size().width();
695 int layer_width
= 5 * FakeTiledLayer::tile_size().width();
696 int layer_height
= 5 * FakeTiledLayer::tile_size().height();
697 int memory_for_layer
= layer_width
* layer_height
* 4;
698 layer_tree_host_
->SetViewportSize(
699 gfx::Size(viewport_width
, viewport_height
));
701 // Use 10x5 tiles to run out of memory.
702 if (run_out_of_memory
[i
])
705 resource_manager_
->SetMaxMemoryLimitBytes(memory_for_layer
);
707 scoped_refptr
<FakeTiledLayer
> layer
=
708 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
709 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
710 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
711 RenderSurfaceLayerList render_surface_layer_list
;
713 layer_tree_host_
->root_layer()->AddChild(layer
);
715 // Full size layer with half being visible.
716 layer
->SetBounds(gfx::Size(layer_width
, layer_height
));
717 gfx::Rect
visible_rect(0, 0, layer_width
/ 2, layer_height
);
718 CalcDrawProps(&render_surface_layer_list
);
720 // Pretend the layer is animating.
721 layer
->draw_properties().target_space_transform_is_animating
= true;
722 layer
->draw_properties().visible_content_rect
= visible_rect
;
723 layer
->SetLayerTreeHost(layer_tree_host_
.get());
725 // The layer should paint its entire contents on the first paint
726 // if it is close to the viewport size and has the available memory.
727 layer
->SetTexturePriorities(priority_calculator_
);
728 resource_manager_
->PrioritizeTextures();
729 layer
->SavePaintProperties();
730 layer
->Update(queue_
.get(), nullptr);
732 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
734 // We should have all the tiles for the small animated layer.
735 // We should still have the visible tiles when we didn't
736 // have enough memory for all the tiles.
737 if (!run_out_of_memory
[i
]) {
738 for (int i
= 0; i
< 5; ++i
) {
739 for (int j
= 0; j
< 5; ++j
)
740 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
743 for (int i
= 0; i
< 10; ++i
) {
744 for (int j
= 0; j
< 5; ++j
)
745 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
), i
< 5);
749 layer
->RemoveFromParent();
753 TEST_F(TiledLayerTest
, IdlePaintOutOfMemory
) {
754 scoped_refptr
<FakeTiledLayer
> layer
=
755 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
756 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
757 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
758 RenderSurfaceLayerList render_surface_layer_list
;
760 layer_tree_host_
->root_layer()->AddChild(layer
);
762 // We have enough memory for only the visible rect, so we will run out of
763 // memory in first idle paint.
764 int memory_limit
= 4 * 100 * 100; // 1 tiles, 4 bytes per pixel.
765 resource_manager_
->SetMaxMemoryLimitBytes(memory_limit
);
767 // The tile size is 100x100, so this invalidates and then paints two tiles.
768 bool needs_update
= false;
769 layer
->SetBounds(gfx::Size(300, 300));
770 CalcDrawProps(&render_surface_layer_list
);
771 layer
->draw_properties().visible_content_rect
= gfx::Rect(100, 100, 100, 100);
772 for (int i
= 0; i
< 2; i
++)
773 needs_update
= UpdateAndPush(layer
, layer_impl
);
775 // Idle-painting should see no more priority tiles for painting.
776 EXPECT_FALSE(needs_update
);
778 // We should have one tile on the impl side.
779 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
782 TEST_F(TiledLayerTest
, IdlePaintZeroSizedLayer
) {
783 scoped_refptr
<FakeTiledLayer
> layer
=
784 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
785 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
786 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
788 layer_tree_host_
->root_layer()->AddChild(layer
);
790 bool animating
[2] = { false, true };
791 for (int i
= 0; i
< 2; i
++) {
792 // Pretend the layer is animating.
793 layer
->draw_properties().target_space_transform_is_animating
= animating
[i
];
795 // The layer's bounds are empty.
796 // Empty layers don't paint or idle-paint.
797 layer
->SetBounds(gfx::Size());
799 RenderSurfaceLayerList render_surface_layer_list
;
800 CalcDrawProps(&render_surface_layer_list
);
801 layer
->draw_properties().visible_content_rect
= gfx::Rect();
802 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
804 // Empty layers don't have tiles.
805 EXPECT_EQ(0u, layer
->NumPaintedTiles());
807 // Empty layers don't need prepaint.
808 EXPECT_FALSE(needs_update
);
810 // Empty layers don't have tiles.
811 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
815 TEST_F(TiledLayerTest
, IdlePaintNonVisibleLayers
) {
816 scoped_refptr
<FakeTiledLayer
> layer
=
817 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
818 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
819 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
821 // Alternate between not visible and visible.
822 gfx::Rect
v(0, 0, 100, 100);
823 gfx::Rect
nv(0, 0, 0, 0);
824 gfx::Rect visible_rect
[10] = { nv
, nv
, v
, v
, nv
, nv
, v
, v
, nv
, nv
};
825 bool invalidate
[10] = { true, true, true, true, true, true, true, true, false,
828 // We should not have any tiles except for when the layer was visible
829 // or after the layer was visible and we didn't invalidate.
830 bool have_tile
[10] = { false, false, true, true, false, false, true, true,
833 layer_tree_host_
->root_layer()->AddChild(layer
);
835 for (int i
= 0; i
< 10; i
++) {
836 layer
->SetBounds(gfx::Size(100, 100));
838 RenderSurfaceLayerList render_surface_layer_list
;
839 CalcDrawProps(&render_surface_layer_list
);
840 layer
->draw_properties().visible_content_rect
= visible_rect
[i
];
843 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
844 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
846 // We should never signal idle paint, as we painted the entire layer
847 // or the layer was not visible.
848 EXPECT_FALSE(needs_update
);
849 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(0, 0), have_tile
[i
]);
853 TEST_F(TiledLayerTest
, InvalidateFromPrepare
) {
854 scoped_refptr
<FakeTiledLayer
> layer
=
855 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
856 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
857 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
858 RenderSurfaceLayerList render_surface_layer_list
;
860 layer_tree_host_
->root_layer()->AddChild(layer
);
862 // The tile size is 100x100, so this invalidates and then paints two tiles.
863 layer
->SetBounds(gfx::Size(100, 200));
864 CalcDrawProps(&render_surface_layer_list
);
865 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
866 UpdateAndPush(layer
, layer_impl
);
868 // We should have both tiles on the impl side.
869 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
870 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
872 layer
->fake_layer_updater()->ClearPrepareCount();
873 // Invoke update again. As the layer is valid update shouldn't be invoked on
875 UpdateAndPush(layer
, layer_impl
);
876 EXPECT_EQ(0, layer
->fake_layer_updater()->prepare_count());
878 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
880 layer
->fake_layer_updater()->SetRectToInvalidate(
881 gfx::Rect(25, 25, 50, 50), layer
.get());
882 layer
->fake_layer_updater()->ClearPrepareCount();
883 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
884 UpdateAndPush(layer
, layer_impl
);
885 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
886 layer
->fake_layer_updater()->ClearPrepareCount();
888 // The layer should still be invalid as update invoked invalidate.
889 UpdateAndPush(layer
, layer_impl
); // visible
890 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
893 TEST_F(TiledLayerTest
, VerifyUpdateRectWhenContentBoundsAreScaled
) {
894 // The update rect (that indicates what was actually painted) should be in
895 // layer space, not the content space.
896 scoped_refptr
<FakeTiledLayerWithScaledBounds
> layer
= make_scoped_refptr(
897 new FakeTiledLayerWithScaledBounds(resource_manager_
.get()));
899 layer_tree_host_
->root_layer()->AddChild(layer
);
901 gfx::Rect
layer_bounds(0, 0, 300, 200);
902 gfx::Rect
content_bounds(0, 0, 150, 250);
904 layer
->SetBounds(layer_bounds
.size());
905 layer
->SetContentBounds(content_bounds
.size());
906 layer
->draw_properties().visible_content_rect
= content_bounds
;
907 layer
->draw_properties().contents_scale_x
= .5f
;
908 layer
->draw_properties().contents_scale_y
= 1.25f
;
910 // On first update, the update_rect includes all tiles, even beyond the
911 // boundaries of the layer.
912 // However, it should still be in layer space, not content space.
913 layer
->InvalidateContentRect(content_bounds
);
915 layer
->SetTexturePriorities(priority_calculator_
);
916 resource_manager_
->PrioritizeTextures();
917 layer
->SavePaintProperties();
918 layer
->Update(queue_
.get(), nullptr);
920 // Update rect is 200x300 (tile size of 100x100). Scaled this gives 400x240.
921 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 400, 240), layer
->update_rect());
924 // After the tiles are updated once, another invalidate only needs to update
925 // the bounds of the layer.
926 layer
->SetTexturePriorities(priority_calculator_
);
927 resource_manager_
->PrioritizeTextures();
928 layer
->InvalidateContentRect(content_bounds
);
929 layer
->SavePaintProperties();
930 layer
->Update(queue_
.get(), nullptr);
931 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds
), layer
->update_rect());
934 // Partial re-paint should also be represented by the update rect in layer
935 // space, not content space.
936 gfx::Rect
partial_damage(30, 100, 10, 10);
937 layer
->InvalidateContentRect(partial_damage
);
938 layer
->SetTexturePriorities(priority_calculator_
);
939 resource_manager_
->PrioritizeTextures();
940 layer
->SavePaintProperties();
941 layer
->Update(queue_
.get(), nullptr);
942 EXPECT_FLOAT_RECT_EQ(gfx::RectF(60, 80, 20, 8), layer
->update_rect());
945 TEST_F(TiledLayerTest
, VerifyInvalidationWhenContentsScaleChanges
) {
946 scoped_refptr
<FakeTiledLayer
> layer
=
947 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
948 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
949 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
950 RenderSurfaceLayerList render_surface_layer_list
;
952 layer_tree_host_
->root_layer()->AddChild(layer
);
954 // Create a layer with one tile.
955 layer
->SetBounds(gfx::Size(100, 100));
956 CalcDrawProps(&render_surface_layer_list
);
957 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
958 layer
->Update(queue_
.get(), nullptr);
960 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
961 layer
->last_needs_display_rect());
963 // Push the tiles to the impl side and check that there is exactly one.
964 layer
->SetTexturePriorities(priority_calculator_
);
965 resource_manager_
->PrioritizeTextures();
966 layer
->SavePaintProperties();
967 layer
->Update(queue_
.get(), nullptr);
969 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
970 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
971 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
972 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
973 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
975 layer
->SetNeedsDisplayRect(gfx::Rect());
976 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer
->last_needs_display_rect());
978 // Change the contents scale.
979 layer
->UpdateContentsScale(2.f
);
980 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 200, 200);
982 // The impl side should get 2x2 tiles now.
983 layer
->SetTexturePriorities(priority_calculator_
);
984 resource_manager_
->PrioritizeTextures();
985 layer
->SavePaintProperties();
986 layer
->Update(queue_
.get(), nullptr);
988 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
989 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
990 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
991 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 0));
992 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
994 // Verify that changing the contents scale caused invalidation, and
995 // that the layer-space rectangle requiring painting is not scaled.
996 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
997 layer
->last_needs_display_rect());
999 // Invalidate the entire layer again, but do not paint. All tiles should be
1000 // gone now from the impl side.
1001 layer
->SetNeedsDisplay();
1002 layer
->SetTexturePriorities(priority_calculator_
);
1003 resource_manager_
->PrioritizeTextures();
1005 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1006 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
1007 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
1008 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
1009 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
1012 TEST_F(TiledLayerTest
, SkipsDrawGetsReset
) {
1013 // Create two 300 x 300 tiled layers.
1014 gfx::Size
content_bounds(300, 300);
1015 gfx::Rect
content_rect(content_bounds
);
1017 // We have enough memory for only one of the two layers.
1018 int memory_limit
= 4 * 300 * 300; // 4 bytes per pixel.
1020 scoped_refptr
<FakeTiledLayer
> root_layer
= make_scoped_refptr(
1021 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1022 scoped_refptr
<FakeTiledLayer
> child_layer
= make_scoped_refptr(
1023 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1024 root_layer
->AddChild(child_layer
);
1026 root_layer
->SetBounds(content_bounds
);
1027 root_layer
->draw_properties().visible_content_rect
= content_rect
;
1028 root_layer
->SetPosition(gfx::PointF(0, 0));
1029 child_layer
->SetBounds(content_bounds
);
1030 child_layer
->draw_properties().visible_content_rect
= content_rect
;
1031 child_layer
->SetPosition(gfx::PointF(0, 0));
1032 root_layer
->InvalidateContentRect(content_rect
);
1033 child_layer
->InvalidateContentRect(content_rect
);
1035 layer_tree_host_
->SetRootLayer(root_layer
);
1036 layer_tree_host_
->SetViewportSize(gfx::Size(300, 300));
1037 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1040 layer_tree_host_
->UpdateLayers(queue_
.get());
1042 // We'll skip the root layer.
1043 EXPECT_TRUE(root_layer
->SkipsDraw());
1044 EXPECT_FALSE(child_layer
->SkipsDraw());
1046 layer_tree_host_
->CommitComplete();
1048 // Remove the child layer.
1049 root_layer
->RemoveAllChildren();
1051 layer_tree_host_
->UpdateLayers(queue_
.get());
1052 EXPECT_FALSE(root_layer
->SkipsDraw());
1054 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1055 resource_provider_
.get());
1056 layer_tree_host_
->SetRootLayer(nullptr);
1059 TEST_F(TiledLayerTest
, ResizeToSmaller
) {
1060 scoped_refptr
<FakeTiledLayer
> layer
=
1061 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1063 layer_tree_host_
->root_layer()->AddChild(layer
);
1065 layer
->SetBounds(gfx::Size(700, 700));
1066 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1067 layer
->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
1069 layer
->SetTexturePriorities(priority_calculator_
);
1070 resource_manager_
->PrioritizeTextures();
1071 layer
->SavePaintProperties();
1072 layer
->Update(queue_
.get(), nullptr);
1074 layer
->SetBounds(gfx::Size(200, 200));
1075 layer
->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
1078 TEST_F(TiledLayerTest
, HugeLayerUpdateCrash
) {
1079 scoped_refptr
<FakeTiledLayer
> layer
=
1080 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1082 layer_tree_host_
->root_layer()->AddChild(layer
);
1085 layer
->SetBounds(gfx::Size(size
, size
));
1086 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1087 layer
->InvalidateContentRect(gfx::Rect(0, 0, size
, size
));
1089 // Ensure no crash for bounds where size * size would overflow an int.
1090 layer
->SetTexturePriorities(priority_calculator_
);
1091 resource_manager_
->PrioritizeTextures();
1092 layer
->SavePaintProperties();
1093 layer
->Update(queue_
.get(), nullptr);
1096 class TiledLayerPartialUpdateTest
: public TiledLayerTest
{
1098 TiledLayerPartialUpdateTest() { settings_
.max_partial_texture_updates
= 4; }
1101 TEST_F(TiledLayerPartialUpdateTest
, PartialUpdates
) {
1102 // Create one 300 x 200 tiled layer with 3 x 2 tiles.
1103 gfx::Size
content_bounds(300, 200);
1104 gfx::Rect
content_rect(content_bounds
);
1106 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
1107 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1108 layer
->SetBounds(content_bounds
);
1109 layer
->SetPosition(gfx::PointF(0, 0));
1110 layer
->draw_properties().visible_content_rect
= content_rect
;
1111 layer
->InvalidateContentRect(content_rect
);
1113 layer_tree_host_
->SetRootLayer(layer
);
1114 layer_tree_host_
->SetViewportSize(gfx::Size(300, 200));
1116 // Full update of all 6 tiles.
1117 layer_tree_host_
->UpdateLayers(queue_
.get());
1119 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1120 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1121 EXPECT_EQ(6u, queue_
->FullUploadSize());
1122 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1124 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1125 EXPECT_FALSE(queue_
->HasMoreUpdates());
1126 layer
->fake_layer_updater()->ClearUpdateCount();
1127 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1129 layer_tree_host_
->CommitComplete();
1131 // Full update of 3 tiles and partial update of 3 tiles.
1132 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
1133 layer_tree_host_
->UpdateLayers(queue_
.get());
1135 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1136 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1137 EXPECT_EQ(3u, queue_
->FullUploadSize());
1138 EXPECT_EQ(3u, queue_
->PartialUploadSize());
1140 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1141 EXPECT_FALSE(queue_
->HasMoreUpdates());
1142 layer
->fake_layer_updater()->ClearUpdateCount();
1143 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1145 layer_tree_host_
->CommitComplete();
1147 // Partial update of 6 tiles.
1148 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1150 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1151 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1152 layer_tree_host_
->UpdateLayers(queue_
.get());
1153 EXPECT_EQ(2u, queue_
->FullUploadSize());
1154 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1156 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1157 EXPECT_FALSE(queue_
->HasMoreUpdates());
1158 layer
->fake_layer_updater()->ClearUpdateCount();
1159 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1161 layer_tree_host_
->CommitComplete();
1163 // Checkerboard all tiles.
1164 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
1166 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1167 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1168 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1170 layer_tree_host_
->CommitComplete();
1172 // Partial update of 6 checkerboard tiles.
1173 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1175 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1176 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1177 layer_tree_host_
->UpdateLayers(queue_
.get());
1178 EXPECT_EQ(6u, queue_
->FullUploadSize());
1179 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1181 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1182 EXPECT_FALSE(queue_
->HasMoreUpdates());
1183 layer
->fake_layer_updater()->ClearUpdateCount();
1184 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1186 layer_tree_host_
->CommitComplete();
1188 // Partial update of 4 tiles.
1189 layer
->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
1191 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1192 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1193 layer_tree_host_
->UpdateLayers(queue_
.get());
1194 EXPECT_EQ(0u, queue_
->FullUploadSize());
1195 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1197 EXPECT_EQ(4, layer
->fake_layer_updater()->update_count());
1198 EXPECT_FALSE(queue_
->HasMoreUpdates());
1199 layer
->fake_layer_updater()->ClearUpdateCount();
1200 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1202 layer_tree_host_
->CommitComplete();
1204 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1205 resource_provider_
.get());
1206 layer_tree_host_
->SetRootLayer(nullptr);
1209 TEST_F(TiledLayerTest
, TilesPaintedWithoutOcclusion
) {
1210 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
1212 scoped_refptr
<FakeTiledLayer
> layer
=
1213 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1214 RenderSurfaceLayerList render_surface_layer_list
;
1216 layer_tree_host_
->root_layer()->AddChild(layer
);
1218 // The tile size is 100x100, so this invalidates and then paints two tiles.
1219 layer
->SetBounds(gfx::Size(100, 200));
1220 CalcDrawProps(&render_surface_layer_list
);
1222 layer
->SetTexturePriorities(priority_calculator_
);
1223 resource_manager_
->PrioritizeTextures();
1224 layer
->SavePaintProperties();
1225 layer
->Update(queue_
.get(), nullptr);
1226 EXPECT_EQ(2, layer
->fake_layer_updater()->update_count());
1229 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusion
) {
1230 scoped_refptr
<FakeTiledLayer
> layer
=
1231 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1232 RenderSurfaceLayerList render_surface_layer_list
;
1233 TestOcclusionTracker occluded
;
1234 occlusion_
= &occluded
;
1236 layer_tree_host_
->root_layer()->AddChild(layer
);
1238 // The tile size is 100x100.
1240 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1241 layer
->SetBounds(gfx::Size(600, 600));
1242 CalcDrawProps(&render_surface_layer_list
);
1244 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1245 layer
->draw_properties().drawable_content_rect
=
1246 gfx::Rect(layer
->content_bounds());
1247 layer
->draw_properties().visible_content_rect
=
1248 gfx::Rect(layer
->content_bounds());
1249 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1251 layer
->SetTexturePriorities(priority_calculator_
);
1252 resource_manager_
->PrioritizeTextures();
1253 layer
->SavePaintProperties();
1254 layer
->Update(queue_
.get(), &occluded
);
1255 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1257 layer
->fake_layer_updater()->ClearUpdateCount();
1258 layer
->SetTexturePriorities(priority_calculator_
);
1259 resource_manager_
->PrioritizeTextures();
1261 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100)));
1262 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1263 layer
->SavePaintProperties();
1264 layer
->Update(queue_
.get(), &occluded
);
1265 EXPECT_EQ(36 - 2, layer
->fake_layer_updater()->update_count());
1267 layer
->fake_layer_updater()->ClearUpdateCount();
1268 layer
->SetTexturePriorities(priority_calculator_
);
1269 resource_manager_
->PrioritizeTextures();
1271 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100)));
1272 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1273 layer
->SavePaintProperties();
1274 layer
->Update(queue_
.get(), &occluded
);
1275 EXPECT_EQ(36, layer
->fake_layer_updater()->update_count());
1278 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndVisiblityConstraints
) {
1279 scoped_refptr
<FakeTiledLayer
> layer
=
1280 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1281 RenderSurfaceLayerList render_surface_layer_list
;
1282 TestOcclusionTracker occluded
;
1283 occlusion_
= &occluded
;
1285 layer_tree_host_
->root_layer()->AddChild(layer
);
1287 // The tile size is 100x100.
1289 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1290 layer
->SetBounds(gfx::Size(600, 600));
1291 CalcDrawProps(&render_surface_layer_list
);
1293 // The partially occluded tiles (by the 150 occlusion height) are visible
1294 // beyond the occlusion, so not culled.
1295 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1296 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 360);
1297 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 360);
1298 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1300 layer
->SetTexturePriorities(priority_calculator_
);
1301 resource_manager_
->PrioritizeTextures();
1302 layer
->SavePaintProperties();
1303 layer
->Update(queue_
.get(), &occluded
);
1304 EXPECT_EQ(24 - 3, layer
->fake_layer_updater()->update_count());
1306 layer
->fake_layer_updater()->ClearUpdateCount();
1308 // Now the visible region stops at the edge of the occlusion so the partly
1309 // visible tiles become fully occluded.
1310 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1311 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 350);
1312 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 350);
1313 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1314 layer
->SetTexturePriorities(priority_calculator_
);
1315 resource_manager_
->PrioritizeTextures();
1316 layer
->SavePaintProperties();
1317 layer
->Update(queue_
.get(), &occluded
);
1318 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1320 layer
->fake_layer_updater()->ClearUpdateCount();
1322 // Now the visible region is even smaller than the occlusion, it should have
1324 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1325 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 340);
1326 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 340);
1327 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1328 layer
->SetTexturePriorities(priority_calculator_
);
1329 resource_manager_
->PrioritizeTextures();
1330 layer
->SavePaintProperties();
1331 layer
->Update(queue_
.get(), &occluded
);
1332 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1335 TEST_F(TiledLayerTest
, TilesNotPaintedWithoutInvalidation
) {
1336 scoped_refptr
<FakeTiledLayer
> layer
=
1337 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1338 RenderSurfaceLayerList render_surface_layer_list
;
1339 TestOcclusionTracker occluded
;
1340 occlusion_
= &occluded
;
1342 layer_tree_host_
->root_layer()->AddChild(layer
);
1344 // The tile size is 100x100.
1346 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1347 layer
->SetBounds(gfx::Size(600, 600));
1348 CalcDrawProps(&render_surface_layer_list
);
1350 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1351 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 600);
1352 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 600);
1353 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1354 layer
->SetTexturePriorities(priority_calculator_
);
1355 resource_manager_
->PrioritizeTextures();
1356 layer
->SavePaintProperties();
1357 layer
->Update(queue_
.get(), &occluded
);
1358 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1361 layer
->fake_layer_updater()->ClearUpdateCount();
1362 layer
->SetTexturePriorities(priority_calculator_
);
1363 resource_manager_
->PrioritizeTextures();
1364 layer
->SavePaintProperties();
1366 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
1368 layer
->Update(queue_
.get(), &occluded
);
1369 EXPECT_EQ(3, layer
->fake_layer_updater()->update_count());
1372 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndTransforms
) {
1373 scoped_refptr
<FakeTiledLayer
> layer
=
1374 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1375 RenderSurfaceLayerList render_surface_layer_list
;
1376 TestOcclusionTracker occluded
;
1377 occlusion_
= &occluded
;
1379 layer_tree_host_
->root_layer()->AddChild(layer
);
1381 // The tile size is 100x100.
1383 // This makes sure the painting works when the occluded region (in screen
1384 // space) is transformed differently than the layer.
1385 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1386 layer
->SetBounds(gfx::Size(600, 600));
1387 CalcDrawProps(&render_surface_layer_list
);
1388 gfx::Transform screen_transform
;
1389 screen_transform
.Scale(0.5, 0.5);
1390 layer
->draw_properties().screen_space_transform
= screen_transform
;
1391 layer
->draw_properties().target_space_transform
= screen_transform
;
1393 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50)));
1394 layer
->draw_properties().drawable_content_rect
=
1395 gfx::Rect(layer
->content_bounds());
1396 layer
->draw_properties().visible_content_rect
=
1397 gfx::Rect(layer
->content_bounds());
1398 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1399 layer
->SetTexturePriorities(priority_calculator_
);
1400 resource_manager_
->PrioritizeTextures();
1401 layer
->SavePaintProperties();
1402 layer
->Update(queue_
.get(), &occluded
);
1403 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1406 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndScaling
) {
1407 scoped_refptr
<FakeTiledLayer
> layer
=
1408 new FakeTiledLayer(resource_manager_
.get());
1409 RenderSurfaceLayerList render_surface_layer_list
;
1410 TestOcclusionTracker occluded
;
1411 occlusion_
= &occluded
;
1413 scoped_refptr
<FakeTiledLayer
> scale_layer
=
1414 new FakeTiledLayer(resource_manager_
.get());
1415 gfx::Transform scale_transform
;
1416 scale_transform
.Scale(2.0, 2.0);
1417 scale_layer
->SetTransform(scale_transform
);
1419 layer_tree_host_
->root_layer()->AddChild(scale_layer
);
1421 // The tile size is 100x100.
1423 // This makes sure the painting works when the content space is scaled to
1424 // a different layer space.
1425 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1426 layer
->SetBounds(gfx::Size(300, 300));
1427 scale_layer
->AddChild(layer
);
1428 CalcDrawProps(&render_surface_layer_list
);
1429 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_x());
1430 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_y());
1431 EXPECT_EQ(gfx::Size(600, 600).ToString(),
1432 layer
->content_bounds().ToString());
1434 // No tiles are covered by the 300x50 occlusion.
1435 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50)));
1436 layer
->draw_properties().drawable_content_rect
=
1437 gfx::Rect(layer
->bounds());
1438 layer
->draw_properties().visible_content_rect
=
1439 gfx::Rect(layer
->content_bounds());
1440 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1441 layer
->SetTexturePriorities(priority_calculator_
);
1442 resource_manager_
->PrioritizeTextures();
1443 layer
->SavePaintProperties();
1444 layer
->Update(queue_
.get(), &occluded
);
1445 int visible_tiles1
= 6 * 6;
1446 EXPECT_EQ(visible_tiles1
, layer
->fake_layer_updater()->update_count());
1448 layer
->fake_layer_updater()->ClearUpdateCount();
1450 // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still.
1451 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1452 layer
->draw_properties().drawable_content_rect
=
1453 gfx::Rect(layer
->bounds());
1454 layer
->draw_properties().visible_content_rect
=
1455 gfx::Rect(layer
->content_bounds());
1456 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1457 layer
->SetTexturePriorities(priority_calculator_
);
1458 resource_manager_
->PrioritizeTextures();
1459 layer
->SavePaintProperties();
1460 layer
->Update(queue_
.get(), &occluded
);
1461 int visible_tiles2
= 6 * 6 - 3;
1462 EXPECT_EQ(visible_tiles2
, layer
->fake_layer_updater()->update_count());
1464 layer
->fake_layer_updater()->ClearUpdateCount();
1466 // This makes sure content scaling and transforms work together.
1467 // When the tiles are scaled down by half, they are 50x50 each in the
1469 gfx::Transform screen_transform
;
1470 screen_transform
.Scale(0.5, 0.5);
1471 layer
->draw_properties().screen_space_transform
= screen_transform
;
1472 layer
->draw_properties().target_space_transform
= screen_transform
;
1474 // An occlusion of 150x100 will cover 3*2 = 6 tiles.
1475 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100)));
1477 gfx::Rect
layer_bounds_rect(layer
->bounds());
1478 layer
->draw_properties().drawable_content_rect
=
1479 gfx::ScaleToEnclosingRect(layer_bounds_rect
, 0.5f
);
1480 layer
->draw_properties().visible_content_rect
=
1481 gfx::Rect(layer
->content_bounds());
1482 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1483 layer
->SetTexturePriorities(priority_calculator_
);
1484 resource_manager_
->PrioritizeTextures();
1485 layer
->SavePaintProperties();
1486 layer
->Update(queue_
.get(), &occluded
);
1487 int visible_tiles3
= 6 * 6 - 6;
1488 EXPECT_EQ(visible_tiles3
, layer
->fake_layer_updater()->update_count());
1491 TEST_F(TiledLayerTest
, DontAllocateContentsWhenTargetSurfaceCantBeAllocated
) {
1492 // Tile size is 100x100.
1493 gfx::Rect
root_rect(0, 0, 300, 200);
1494 gfx::Rect
child_rect(0, 0, 300, 100);
1495 gfx::Rect
child2_rect(0, 100, 300, 100);
1497 scoped_refptr
<FakeTiledLayer
> root
= make_scoped_refptr(
1498 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1499 scoped_refptr
<Layer
> surface
= Layer::Create();
1500 scoped_refptr
<FakeTiledLayer
> child
= make_scoped_refptr(
1501 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1502 scoped_refptr
<FakeTiledLayer
> child2
= make_scoped_refptr(
1503 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1505 root
->SetBounds(root_rect
.size());
1506 root
->draw_properties().drawable_content_rect
= root_rect
;
1507 root
->draw_properties().visible_content_rect
= root_rect
;
1508 root
->AddChild(surface
);
1510 surface
->SetForceRenderSurface(true);
1511 surface
->SetOpacity(0.5);
1512 surface
->AddChild(child
);
1513 surface
->AddChild(child2
);
1515 child
->SetBounds(child_rect
.size());
1516 child
->SetPosition(child_rect
.origin());
1517 child
->draw_properties().visible_content_rect
= child_rect
;
1518 child
->draw_properties().drawable_content_rect
= root_rect
;
1520 child2
->SetBounds(child2_rect
.size());
1521 child2
->SetPosition(child2_rect
.origin());
1522 child2
->draw_properties().visible_content_rect
= child2_rect
;
1523 child2
->draw_properties().drawable_content_rect
= root_rect
;
1525 layer_tree_host_
->SetRootLayer(root
);
1526 layer_tree_host_
->SetViewportSize(root_rect
.size());
1528 // With a huge memory limit, all layers should update and push their textures.
1529 root
->InvalidateContentRect(root_rect
);
1530 child
->InvalidateContentRect(child_rect
);
1531 child2
->InvalidateContentRect(child2_rect
);
1532 layer_tree_host_
->UpdateLayers(queue_
.get());
1535 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1536 EXPECT_EQ(3, child
->fake_layer_updater()->update_count());
1537 EXPECT_EQ(3, child2
->fake_layer_updater()->update_count());
1538 EXPECT_FALSE(queue_
->HasMoreUpdates());
1540 root
->fake_layer_updater()->ClearUpdateCount();
1541 child
->fake_layer_updater()->ClearUpdateCount();
1542 child2
->fake_layer_updater()->ClearUpdateCount();
1544 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1545 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1546 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1547 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1548 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1549 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1550 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1551 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1552 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1554 for (unsigned i
= 0; i
< 3; ++i
) {
1555 for (unsigned j
= 0; j
< 2; ++j
)
1556 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1557 EXPECT_TRUE(child_impl
->HasResourceIdForTileAt(i
, 0));
1558 EXPECT_TRUE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1561 layer_tree_host_
->CommitComplete();
1563 // With a memory limit that includes only the root layer (3x2 tiles) and half
1564 // the surface that the child layers draw into, the child layers will not be
1565 // allocated. If the surface isn't accounted for, then one of the children
1566 // would fit within the memory limit.
1567 root
->InvalidateContentRect(root_rect
);
1568 child
->InvalidateContentRect(child_rect
);
1569 child2
->InvalidateContentRect(child2_rect
);
1571 size_t memory_limit
= (3 * 2 + 3 * 1) * (100 * 100) * 4;
1572 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1574 layer_tree_host_
->UpdateLayers(queue_
.get());
1577 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1578 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1579 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1580 EXPECT_FALSE(queue_
->HasMoreUpdates());
1582 root
->fake_layer_updater()->ClearUpdateCount();
1583 child
->fake_layer_updater()->ClearUpdateCount();
1584 child2
->fake_layer_updater()->ClearUpdateCount();
1586 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1587 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1588 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1589 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1590 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1591 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1592 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1593 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1594 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1596 for (unsigned i
= 0; i
< 3; ++i
) {
1597 for (unsigned j
= 0; j
< 2; ++j
)
1598 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1599 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1600 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1603 layer_tree_host_
->CommitComplete();
1605 // With a memory limit that includes only half the root layer, no contents
1606 // will be allocated. If render surface memory wasn't accounted for, there is
1607 // enough space for one of the children layers, but they draw into a surface
1608 // that can't be allocated.
1609 root
->InvalidateContentRect(root_rect
);
1610 child
->InvalidateContentRect(child_rect
);
1611 child2
->InvalidateContentRect(child2_rect
);
1613 memory_limit
= (3 * 1) * (100 * 100) * 4;
1614 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1616 layer_tree_host_
->UpdateLayers(queue_
.get());
1619 EXPECT_EQ(0, root
->fake_layer_updater()->update_count());
1620 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1621 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1622 EXPECT_FALSE(queue_
->HasMoreUpdates());
1624 root
->fake_layer_updater()->ClearUpdateCount();
1625 child
->fake_layer_updater()->ClearUpdateCount();
1626 child2
->fake_layer_updater()->ClearUpdateCount();
1628 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1629 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1630 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1631 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1632 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1633 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1634 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1635 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1636 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1638 for (unsigned i
= 0; i
< 3; ++i
) {
1639 for (unsigned j
= 0; j
< 2; ++j
)
1640 EXPECT_FALSE(root_impl
->HasResourceIdForTileAt(i
, j
));
1641 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1642 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1645 layer_tree_host_
->CommitComplete();
1647 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1648 resource_provider_
.get());
1649 layer_tree_host_
->SetRootLayer(nullptr);
1652 class TrackingLayerPainter
: public LayerPainter
{
1654 static scoped_ptr
<TrackingLayerPainter
> Create() {
1655 return make_scoped_ptr(new TrackingLayerPainter());
1658 void Paint(SkCanvas
* canvas
, const gfx::Rect
& content_rect
) override
{
1659 painted_rect_
= content_rect
;
1662 gfx::Rect
PaintedRect() const { return painted_rect_
; }
1663 void ResetPaintedRect() { painted_rect_
= gfx::Rect(); }
1666 gfx::Rect painted_rect_
;
1669 class UpdateTrackingTiledLayer
: public FakeTiledLayer
{
1671 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager
* manager
)
1672 : FakeTiledLayer(manager
) {
1673 scoped_ptr
<TrackingLayerPainter
> painter(TrackingLayerPainter::Create());
1674 tracking_layer_painter_
= painter
.get();
1675 layer_updater_
= BitmapContentLayerUpdater::Create(painter
.Pass(), 0);
1678 TrackingLayerPainter
* tracking_layer_painter() const {
1679 return tracking_layer_painter_
;
1683 LayerUpdater
* Updater() const override
{ return layer_updater_
.get(); }
1684 ~UpdateTrackingTiledLayer() override
{}
1686 TrackingLayerPainter
* tracking_layer_painter_
;
1687 scoped_refptr
<BitmapContentLayerUpdater
> layer_updater_
;
1690 TEST_F(TiledLayerTest
, NonIntegerContentsScaleIsNotDistortedDuringPaint
) {
1691 scoped_refptr
<UpdateTrackingTiledLayer
> layer
=
1692 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_
.get()));
1694 layer_tree_host_
->root_layer()->AddChild(layer
);
1696 gfx::Rect
layer_rect(0, 0, 30, 31);
1697 layer
->SetPosition(layer_rect
.origin());
1698 layer
->SetBounds(layer_rect
.size());
1699 layer
->UpdateContentsScale(1.5f
);
1701 gfx::Rect
content_rect(0, 0, 45, 47);
1702 EXPECT_EQ(content_rect
.size(), layer
->content_bounds());
1703 layer
->draw_properties().visible_content_rect
= content_rect
;
1704 layer
->draw_properties().drawable_content_rect
= content_rect
;
1706 layer
->SetTexturePriorities(priority_calculator_
);
1707 resource_manager_
->PrioritizeTextures();
1708 layer
->SavePaintProperties();
1710 // Update the whole tile.
1711 layer
->Update(queue_
.get(), nullptr);
1712 layer
->tracking_layer_painter()->ResetPaintedRect();
1714 EXPECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1717 // Invalidate the entire layer in content space. When painting, the rect given
1718 // to webkit should match the layer's bounds.
1719 layer
->InvalidateContentRect(content_rect
);
1720 layer
->Update(queue_
.get(), nullptr);
1722 // Rounding leads to an extra pixel.
1723 gfx::Rect
expanded_layer_rect(layer_rect
);
1724 expanded_layer_rect
.set_height(32);
1725 EXPECT_EQ(expanded_layer_rect
,
1726 layer
->tracking_layer_painter()->PaintedRect());
1729 TEST_F(TiledLayerTest
,
1730 NonIntegerContentsScaleIsNotDistortedDuringInvalidation
) {
1731 scoped_refptr
<UpdateTrackingTiledLayer
> layer
=
1732 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_
.get()));
1734 layer_tree_host_
->root_layer()->AddChild(layer
);
1736 gfx::Rect
layer_rect(0, 0, 30, 31);
1737 layer
->SetPosition(layer_rect
.origin());
1738 layer
->SetBounds(layer_rect
.size());
1739 layer
->UpdateContentsScale(1.3f
);
1741 gfx::Rect
content_rect(layer
->content_bounds());
1742 layer
->draw_properties().visible_content_rect
= content_rect
;
1743 layer
->draw_properties().drawable_content_rect
= content_rect
;
1745 layer
->SetTexturePriorities(priority_calculator_
);
1746 resource_manager_
->PrioritizeTextures();
1747 layer
->SavePaintProperties();
1749 // Update the whole tile.
1750 layer
->Update(queue_
.get(), nullptr);
1751 layer
->tracking_layer_painter()->ResetPaintedRect();
1753 EXPECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1756 // Invalidate the entire layer in layer space. When painting, the rect given
1757 // to webkit should match the layer's bounds.
1758 layer
->SetNeedsDisplayRect(layer_rect
);
1759 layer
->Update(queue_
.get(), nullptr);
1761 // Rounding leads to an extra pixel.
1762 gfx::Rect
expanded_layer_rect(layer_rect
);
1763 expanded_layer_rect
.set_height(32);
1764 EXPECT_EQ(expanded_layer_rect
,
1765 layer
->tracking_layer_painter()->PaintedRect());