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(),
88 bool output_surface_created_
;
89 base::RunLoop run_loop_
;
92 class TiledLayerTest
: public testing::Test
{
96 output_surface_(FakeOutputSurface::Create3d()),
97 queue_(make_scoped_ptr(new ResourceUpdateQueue
)),
98 impl_thread_("ImplThread"),
99 fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D
),
100 occlusion_(nullptr) {
101 settings_
.max_partial_texture_updates
= std::numeric_limits
<size_t>::max();
102 settings_
.layer_transforms_should_scale_layer_contents
= true;
105 virtual void SetUp() {
106 impl_thread_
.Start();
107 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
108 layer_tree_host_
= SynchronousOutputSurfaceLayerTreeHost::Create(
109 &fake_layer_tree_host_client_
,
110 shared_bitmap_manager_
.get(),
112 impl_thread_
.message_loop_proxy());
113 fake_layer_tree_host_client_
.SetLayerTreeHost(layer_tree_host_
.get());
114 proxy_
= layer_tree_host_
->proxy();
115 resource_manager_
= PrioritizedResourceManager::Create(proxy_
);
116 layer_tree_host_
->SetLayerTreeHostClientReady();
117 CHECK(layer_tree_host_
->EnsureOutputSurfaceCreated());
118 layer_tree_host_
->SetRootLayer(Layer::Create());
120 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
122 DebugScopedSetImplThreadAndMainThreadBlocked
123 impl_thread_and_main_thread_blocked(proxy_
);
124 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
125 shared_bitmap_manager_
.get(),
131 host_impl_
= make_scoped_ptr(
132 new FakeLayerTreeHostImpl(proxy_
, shared_bitmap_manager_
.get()));
135 virtual ~TiledLayerTest() {
136 ResourceManagerClearAllMemory(resource_manager_
.get(),
137 resource_provider_
.get());
139 DebugScopedSetImplThreadAndMainThreadBlocked
140 impl_thread_and_main_thread_blocked(proxy_
);
141 resource_provider_
= nullptr;
142 host_impl_
= nullptr;
145 void ResourceManagerClearAllMemory(
146 PrioritizedResourceManager
* resource_manager
,
147 ResourceProvider
* resource_provider
) {
149 DebugScopedSetImplThreadAndMainThreadBlocked
150 impl_thread_and_main_thread_blocked(proxy_
);
151 resource_manager
->ClearAllMemory(resource_provider
);
152 resource_manager
->ReduceMemory(resource_provider
);
154 resource_manager
->UnlinkAndClearEvictedBackings();
157 void UpdateTextures() {
158 DebugScopedSetImplThreadAndMainThreadBlocked
159 impl_thread_and_main_thread_blocked(proxy_
);
161 scoped_ptr
<ResourceUpdateController
> update_controller
=
162 ResourceUpdateController::Create(nullptr,
163 proxy_
->ImplThreadTaskRunner(),
165 resource_provider_
.get());
166 update_controller
->Finalize();
167 queue_
= make_scoped_ptr(new ResourceUpdateQueue
);
170 void LayerPushPropertiesTo(FakeTiledLayer
* layer
,
171 FakeTiledLayerImpl
* layer_impl
) {
172 DebugScopedSetImplThreadAndMainThreadBlocked
173 impl_thread_and_main_thread_blocked(proxy_
);
174 layer
->PushPropertiesTo(layer_impl
);
175 layer
->ResetNumDependentsNeedPushProperties();
178 void LayerUpdate(FakeTiledLayer
* layer
, TestOcclusionTracker
* occluded
) {
179 DebugScopedSetMainThread
main_thread(proxy_
);
180 layer
->Update(queue_
.get(), occluded
);
183 void CalcDrawProps(RenderSurfaceLayerList
* render_surface_layer_list
) {
185 occlusion_
->SetRenderTarget(layer_tree_host_
->root_layer());
187 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting
inputs(
188 layer_tree_host_
->root_layer(),
189 layer_tree_host_
->device_viewport_size(),
190 render_surface_layer_list
);
191 inputs
.device_scale_factor
= layer_tree_host_
->device_scale_factor();
192 inputs
.max_texture_size
=
193 layer_tree_host_
->GetRendererCapabilities().max_texture_size
;
194 inputs
.can_adjust_raster_scales
= true;
195 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
198 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
199 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
) {
200 scoped_refptr
<FakeTiledLayer
> layer2
;
201 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
;
202 return UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
205 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
206 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
,
207 const scoped_refptr
<FakeTiledLayer
>& layer2
,
208 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl2
) {
210 resource_manager_
->ClearPriorities();
212 layer1
->SetTexturePriorities(priority_calculator_
);
214 layer2
->SetTexturePriorities(priority_calculator_
);
215 resource_manager_
->PrioritizeTextures();
217 // Save paint properties
219 layer1
->SavePaintProperties();
221 layer2
->SavePaintProperties();
225 layer1
->Update(queue_
.get(), occlusion_
);
227 layer2
->Update(queue_
.get(), occlusion_
);
229 bool needs_update
= false;
231 needs_update
|= layer1
->NeedsIdlePaint();
233 needs_update
|= layer2
->NeedsIdlePaint();
235 // Update textures and push.
238 LayerPushPropertiesTo(layer1
.get(), layer_impl1
.get());
240 LayerPushPropertiesTo(layer2
.get(), layer_impl2
.get());
247 LayerTreeSettings settings_
;
248 FakeOutputSurfaceClient output_surface_client_
;
249 scoped_ptr
<OutputSurface
> output_surface_
;
250 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
251 scoped_ptr
<ResourceProvider
> resource_provider_
;
252 scoped_ptr
<ResourceUpdateQueue
> queue_
;
253 PriorityCalculator priority_calculator_
;
254 base::Thread impl_thread_
;
255 FakeLayerTreeHostClient fake_layer_tree_host_client_
;
256 scoped_ptr
<SynchronousOutputSurfaceLayerTreeHost
> layer_tree_host_
;
257 scoped_ptr
<FakeLayerTreeHostImpl
> host_impl_
;
258 scoped_ptr
<PrioritizedResourceManager
> resource_manager_
;
259 TestOcclusionTracker
* occlusion_
;
262 TEST_F(TiledLayerTest
, PushDirtyTiles
) {
263 scoped_refptr
<FakeTiledLayer
> layer
=
264 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
265 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
266 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
267 RenderSurfaceLayerList render_surface_layer_list
;
269 layer_tree_host_
->root_layer()->AddChild(layer
);
271 // The tile size is 100x100, so this invalidates and then paints two tiles.
272 layer
->SetBounds(gfx::Size(100, 200));
273 CalcDrawProps(&render_surface_layer_list
);
274 UpdateAndPush(layer
, layer_impl
);
276 // We should have both tiles on the impl side.
277 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
278 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
280 // Invalidates both tiles, but then only update one of them.
281 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
282 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
283 UpdateAndPush(layer
, layer_impl
);
285 // We should only have the first tile since the other tile was invalidated but
287 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
288 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
291 TEST_F(TiledLayerTest
, Scale
) {
292 layer_tree_host_
->SetDeviceScaleFactor(1.5);
294 scoped_refptr
<FakeTiledLayer
> layer
=
295 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
296 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
297 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
298 RenderSurfaceLayerList render_surface_layer_list
;
300 layer_tree_host_
->root_layer()->AddChild(layer
);
302 layer
->SetBounds(gfx::Size(100, 200));
303 CalcDrawProps(&render_surface_layer_list
);
305 // Change the width so that it doesn't divide cleanly by the scale.
306 layer
->SetBounds(gfx::Size(101, 200));
307 UpdateAndPush(layer
, layer_impl
);
309 EXPECT_EQ(1.5, layer
->fake_layer_updater()->last_contents_width_scale());
312 TEST_F(TiledLayerTest
, PushOccludedDirtyTiles
) {
313 scoped_refptr
<FakeTiledLayer
> layer
=
314 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
315 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
316 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
317 TestOcclusionTracker occluded
;
318 occlusion_
= &occluded
;
319 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
321 layer_tree_host_
->root_layer()->AddChild(layer
);
324 RenderSurfaceLayerList render_surface_layer_list
;
326 // The tile size is 100x100, so this invalidates and then paints two tiles.
327 layer
->SetBounds(gfx::Size(100, 200));
328 CalcDrawProps(&render_surface_layer_list
);
329 UpdateAndPush(layer
, layer_impl
);
331 // We should have both tiles on the impl side.
332 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
333 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
337 RenderSurfaceLayerList render_surface_layer_list
;
339 // Invalidates part of the top tile...
340 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
341 // ....but the area is occluded.
342 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50)));
343 CalcDrawProps(&render_surface_layer_list
);
344 UpdateAndPush(layer
, layer_impl
);
346 // We should still have both tiles, as part of the top tile is still
348 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
349 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
353 TEST_F(TiledLayerTest
, PushDeletedTiles
) {
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
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
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
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
])
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);
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
));
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,
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,
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
];
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
868 UpdateAndPush(layer
, layer_impl
);
869 EXPECT_EQ(0, layer
->fake_layer_updater()->prepare_count());
871 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
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());
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());
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);
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);
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);
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(
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
);
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
{
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());
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());
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());
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());
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());
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 scoped_refptr
<FakeTiledLayer
> layer
=
1204 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1205 RenderSurfaceLayerList render_surface_layer_list
;
1207 layer_tree_host_
->root_layer()->AddChild(layer
);
1209 // The tile size is 100x100, so this invalidates and then paints two tiles.
1210 layer
->SetBounds(gfx::Size(100, 200));
1211 CalcDrawProps(&render_surface_layer_list
);
1213 layer
->SetTexturePriorities(priority_calculator_
);
1214 resource_manager_
->PrioritizeTextures();
1215 layer
->SavePaintProperties();
1216 layer
->Update(queue_
.get(), nullptr);
1217 EXPECT_EQ(2, layer
->fake_layer_updater()->update_count());
1220 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusion
) {
1221 scoped_refptr
<FakeTiledLayer
> layer
=
1222 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1223 RenderSurfaceLayerList render_surface_layer_list
;
1224 TestOcclusionTracker occluded
;
1225 occlusion_
= &occluded
;
1227 layer_tree_host_
->root_layer()->AddChild(layer
);
1229 // The tile size is 100x100.
1231 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1232 layer
->SetBounds(gfx::Size(600, 600));
1233 CalcDrawProps(&render_surface_layer_list
);
1235 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1236 layer
->draw_properties().drawable_content_rect
=
1237 gfx::Rect(layer
->content_bounds());
1238 layer
->draw_properties().visible_content_rect
=
1239 gfx::Rect(layer
->content_bounds());
1240 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1242 layer
->SetTexturePriorities(priority_calculator_
);
1243 resource_manager_
->PrioritizeTextures();
1244 layer
->SavePaintProperties();
1245 layer
->Update(queue_
.get(), &occluded
);
1246 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1248 layer
->fake_layer_updater()->ClearUpdateCount();
1249 layer
->SetTexturePriorities(priority_calculator_
);
1250 resource_manager_
->PrioritizeTextures();
1252 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100)));
1253 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1254 layer
->SavePaintProperties();
1255 layer
->Update(queue_
.get(), &occluded
);
1256 EXPECT_EQ(36 - 2, layer
->fake_layer_updater()->update_count());
1258 layer
->fake_layer_updater()->ClearUpdateCount();
1259 layer
->SetTexturePriorities(priority_calculator_
);
1260 resource_manager_
->PrioritizeTextures();
1262 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100)));
1263 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1264 layer
->SavePaintProperties();
1265 layer
->Update(queue_
.get(), &occluded
);
1266 EXPECT_EQ(36, layer
->fake_layer_updater()->update_count());
1269 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndVisiblityConstraints
) {
1270 scoped_refptr
<FakeTiledLayer
> layer
=
1271 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1272 RenderSurfaceLayerList render_surface_layer_list
;
1273 TestOcclusionTracker occluded
;
1274 occlusion_
= &occluded
;
1276 layer_tree_host_
->root_layer()->AddChild(layer
);
1278 // The tile size is 100x100.
1280 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1281 layer
->SetBounds(gfx::Size(600, 600));
1282 CalcDrawProps(&render_surface_layer_list
);
1284 // The partially occluded tiles (by the 150 occlusion height) are visible
1285 // beyond the occlusion, so not culled.
1286 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1287 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 360);
1288 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 360);
1289 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1291 layer
->SetTexturePriorities(priority_calculator_
);
1292 resource_manager_
->PrioritizeTextures();
1293 layer
->SavePaintProperties();
1294 layer
->Update(queue_
.get(), &occluded
);
1295 EXPECT_EQ(24 - 3, layer
->fake_layer_updater()->update_count());
1297 layer
->fake_layer_updater()->ClearUpdateCount();
1299 // Now the visible region stops at the edge of the occlusion so the partly
1300 // visible tiles become fully occluded.
1301 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1302 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 350);
1303 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 350);
1304 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1305 layer
->SetTexturePriorities(priority_calculator_
);
1306 resource_manager_
->PrioritizeTextures();
1307 layer
->SavePaintProperties();
1308 layer
->Update(queue_
.get(), &occluded
);
1309 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1311 layer
->fake_layer_updater()->ClearUpdateCount();
1313 // Now the visible region is even smaller than the occlusion, it should have
1315 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1316 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 340);
1317 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 340);
1318 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1319 layer
->SetTexturePriorities(priority_calculator_
);
1320 resource_manager_
->PrioritizeTextures();
1321 layer
->SavePaintProperties();
1322 layer
->Update(queue_
.get(), &occluded
);
1323 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1326 TEST_F(TiledLayerTest
, TilesNotPaintedWithoutInvalidation
) {
1327 scoped_refptr
<FakeTiledLayer
> layer
=
1328 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1329 RenderSurfaceLayerList render_surface_layer_list
;
1330 TestOcclusionTracker occluded
;
1331 occlusion_
= &occluded
;
1333 layer_tree_host_
->root_layer()->AddChild(layer
);
1335 // The tile size is 100x100.
1337 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1338 layer
->SetBounds(gfx::Size(600, 600));
1339 CalcDrawProps(&render_surface_layer_list
);
1341 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1342 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 600);
1343 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 600);
1344 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1345 layer
->SetTexturePriorities(priority_calculator_
);
1346 resource_manager_
->PrioritizeTextures();
1347 layer
->SavePaintProperties();
1348 layer
->Update(queue_
.get(), &occluded
);
1349 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1352 layer
->fake_layer_updater()->ClearUpdateCount();
1353 layer
->SetTexturePriorities(priority_calculator_
);
1354 resource_manager_
->PrioritizeTextures();
1355 layer
->SavePaintProperties();
1357 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
1359 layer
->Update(queue_
.get(), &occluded
);
1360 EXPECT_EQ(3, layer
->fake_layer_updater()->update_count());
1363 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndTransforms
) {
1364 scoped_refptr
<FakeTiledLayer
> layer
=
1365 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1366 RenderSurfaceLayerList render_surface_layer_list
;
1367 TestOcclusionTracker occluded
;
1368 occlusion_
= &occluded
;
1370 layer_tree_host_
->root_layer()->AddChild(layer
);
1372 // The tile size is 100x100.
1374 // This makes sure the painting works when the occluded region (in screen
1375 // space) is transformed differently than the layer.
1376 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1377 layer
->SetBounds(gfx::Size(600, 600));
1378 CalcDrawProps(&render_surface_layer_list
);
1379 gfx::Transform screen_transform
;
1380 screen_transform
.Scale(0.5, 0.5);
1381 layer
->draw_properties().screen_space_transform
= screen_transform
;
1382 layer
->draw_properties().target_space_transform
= screen_transform
;
1384 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50)));
1385 layer
->draw_properties().drawable_content_rect
=
1386 gfx::Rect(layer
->content_bounds());
1387 layer
->draw_properties().visible_content_rect
=
1388 gfx::Rect(layer
->content_bounds());
1389 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1390 layer
->SetTexturePriorities(priority_calculator_
);
1391 resource_manager_
->PrioritizeTextures();
1392 layer
->SavePaintProperties();
1393 layer
->Update(queue_
.get(), &occluded
);
1394 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1397 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndScaling
) {
1398 scoped_refptr
<FakeTiledLayer
> layer
=
1399 new FakeTiledLayer(resource_manager_
.get());
1400 RenderSurfaceLayerList render_surface_layer_list
;
1401 TestOcclusionTracker occluded
;
1402 occlusion_
= &occluded
;
1404 scoped_refptr
<FakeTiledLayer
> scale_layer
=
1405 new FakeTiledLayer(resource_manager_
.get());
1406 gfx::Transform scale_transform
;
1407 scale_transform
.Scale(2.0, 2.0);
1408 scale_layer
->SetTransform(scale_transform
);
1410 layer_tree_host_
->root_layer()->AddChild(scale_layer
);
1412 // The tile size is 100x100.
1414 // This makes sure the painting works when the content space is scaled to
1415 // a different layer space.
1416 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1417 layer
->SetBounds(gfx::Size(300, 300));
1418 scale_layer
->AddChild(layer
);
1419 CalcDrawProps(&render_surface_layer_list
);
1420 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_x());
1421 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_y());
1422 EXPECT_EQ(gfx::Size(600, 600).ToString(),
1423 layer
->content_bounds().ToString());
1425 // No tiles are covered by the 300x50 occlusion.
1426 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50)));
1427 layer
->draw_properties().drawable_content_rect
=
1428 gfx::Rect(layer
->bounds());
1429 layer
->draw_properties().visible_content_rect
=
1430 gfx::Rect(layer
->content_bounds());
1431 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1432 layer
->SetTexturePriorities(priority_calculator_
);
1433 resource_manager_
->PrioritizeTextures();
1434 layer
->SavePaintProperties();
1435 layer
->Update(queue_
.get(), &occluded
);
1436 int visible_tiles1
= 6 * 6;
1437 EXPECT_EQ(visible_tiles1
, layer
->fake_layer_updater()->update_count());
1439 layer
->fake_layer_updater()->ClearUpdateCount();
1441 // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still.
1442 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1443 layer
->draw_properties().drawable_content_rect
=
1444 gfx::Rect(layer
->bounds());
1445 layer
->draw_properties().visible_content_rect
=
1446 gfx::Rect(layer
->content_bounds());
1447 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1448 layer
->SetTexturePriorities(priority_calculator_
);
1449 resource_manager_
->PrioritizeTextures();
1450 layer
->SavePaintProperties();
1451 layer
->Update(queue_
.get(), &occluded
);
1452 int visible_tiles2
= 6 * 6 - 3;
1453 EXPECT_EQ(visible_tiles2
, layer
->fake_layer_updater()->update_count());
1455 layer
->fake_layer_updater()->ClearUpdateCount();
1457 // This makes sure content scaling and transforms work together.
1458 // When the tiles are scaled down by half, they are 50x50 each in the
1460 gfx::Transform screen_transform
;
1461 screen_transform
.Scale(0.5, 0.5);
1462 layer
->draw_properties().screen_space_transform
= screen_transform
;
1463 layer
->draw_properties().target_space_transform
= screen_transform
;
1465 // An occlusion of 150x100 will cover 3*2 = 6 tiles.
1466 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100)));
1468 gfx::Rect
layer_bounds_rect(layer
->bounds());
1469 layer
->draw_properties().drawable_content_rect
=
1470 gfx::ScaleToEnclosingRect(layer_bounds_rect
, 0.5f
);
1471 layer
->draw_properties().visible_content_rect
=
1472 gfx::Rect(layer
->content_bounds());
1473 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1474 layer
->SetTexturePriorities(priority_calculator_
);
1475 resource_manager_
->PrioritizeTextures();
1476 layer
->SavePaintProperties();
1477 layer
->Update(queue_
.get(), &occluded
);
1478 int visible_tiles3
= 6 * 6 - 6;
1479 EXPECT_EQ(visible_tiles3
, layer
->fake_layer_updater()->update_count());
1482 TEST_F(TiledLayerTest
, DontAllocateContentsWhenTargetSurfaceCantBeAllocated
) {
1483 // Tile size is 100x100.
1484 gfx::Rect
root_rect(0, 0, 300, 200);
1485 gfx::Rect
child_rect(0, 0, 300, 100);
1486 gfx::Rect
child2_rect(0, 100, 300, 100);
1488 scoped_refptr
<FakeTiledLayer
> root
= make_scoped_refptr(
1489 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1490 scoped_refptr
<Layer
> surface
= Layer::Create();
1491 scoped_refptr
<FakeTiledLayer
> child
= make_scoped_refptr(
1492 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1493 scoped_refptr
<FakeTiledLayer
> child2
= make_scoped_refptr(
1494 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1496 root
->SetBounds(root_rect
.size());
1497 root
->draw_properties().drawable_content_rect
= root_rect
;
1498 root
->draw_properties().visible_content_rect
= root_rect
;
1499 root
->AddChild(surface
);
1501 surface
->SetForceRenderSurface(true);
1502 surface
->SetOpacity(0.5);
1503 surface
->AddChild(child
);
1504 surface
->AddChild(child2
);
1506 child
->SetBounds(child_rect
.size());
1507 child
->SetPosition(child_rect
.origin());
1508 child
->draw_properties().visible_content_rect
= child_rect
;
1509 child
->draw_properties().drawable_content_rect
= root_rect
;
1511 child2
->SetBounds(child2_rect
.size());
1512 child2
->SetPosition(child2_rect
.origin());
1513 child2
->draw_properties().visible_content_rect
= child2_rect
;
1514 child2
->draw_properties().drawable_content_rect
= root_rect
;
1516 layer_tree_host_
->SetRootLayer(root
);
1517 layer_tree_host_
->SetViewportSize(root_rect
.size());
1519 // With a huge memory limit, all layers should update and push their textures.
1520 root
->InvalidateContentRect(root_rect
);
1521 child
->InvalidateContentRect(child_rect
);
1522 child2
->InvalidateContentRect(child2_rect
);
1523 layer_tree_host_
->UpdateLayers(queue_
.get());
1526 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1527 EXPECT_EQ(3, child
->fake_layer_updater()->update_count());
1528 EXPECT_EQ(3, child2
->fake_layer_updater()->update_count());
1529 EXPECT_FALSE(queue_
->HasMoreUpdates());
1531 root
->fake_layer_updater()->ClearUpdateCount();
1532 child
->fake_layer_updater()->ClearUpdateCount();
1533 child2
->fake_layer_updater()->ClearUpdateCount();
1535 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1536 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1537 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1538 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1539 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1540 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1541 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1542 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1543 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1545 for (unsigned i
= 0; i
< 3; ++i
) {
1546 for (unsigned j
= 0; j
< 2; ++j
)
1547 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1548 EXPECT_TRUE(child_impl
->HasResourceIdForTileAt(i
, 0));
1549 EXPECT_TRUE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1552 layer_tree_host_
->CommitComplete();
1554 // With a memory limit that includes only the root layer (3x2 tiles) and half
1555 // the surface that the child layers draw into, the child layers will not be
1556 // allocated. If the surface isn't accounted for, then one of the children
1557 // would fit within the memory limit.
1558 root
->InvalidateContentRect(root_rect
);
1559 child
->InvalidateContentRect(child_rect
);
1560 child2
->InvalidateContentRect(child2_rect
);
1562 size_t memory_limit
= (3 * 2 + 3 * 1) * (100 * 100) * 4;
1563 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1565 layer_tree_host_
->UpdateLayers(queue_
.get());
1568 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1569 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1570 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1571 EXPECT_FALSE(queue_
->HasMoreUpdates());
1573 root
->fake_layer_updater()->ClearUpdateCount();
1574 child
->fake_layer_updater()->ClearUpdateCount();
1575 child2
->fake_layer_updater()->ClearUpdateCount();
1577 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1578 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1579 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1580 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1581 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1582 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1583 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1584 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1585 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1587 for (unsigned i
= 0; i
< 3; ++i
) {
1588 for (unsigned j
= 0; j
< 2; ++j
)
1589 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1590 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1591 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1594 layer_tree_host_
->CommitComplete();
1596 // With a memory limit that includes only half the root layer, no contents
1597 // will be allocated. If render surface memory wasn't accounted for, there is
1598 // enough space for one of the children layers, but they draw into a surface
1599 // that can't be allocated.
1600 root
->InvalidateContentRect(root_rect
);
1601 child
->InvalidateContentRect(child_rect
);
1602 child2
->InvalidateContentRect(child2_rect
);
1604 memory_limit
= (3 * 1) * (100 * 100) * 4;
1605 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1607 layer_tree_host_
->UpdateLayers(queue_
.get());
1610 EXPECT_EQ(0, root
->fake_layer_updater()->update_count());
1611 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1612 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1613 EXPECT_FALSE(queue_
->HasMoreUpdates());
1615 root
->fake_layer_updater()->ClearUpdateCount();
1616 child
->fake_layer_updater()->ClearUpdateCount();
1617 child2
->fake_layer_updater()->ClearUpdateCount();
1619 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1620 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1621 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1622 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1623 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1624 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1625 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1626 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1627 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1629 for (unsigned i
= 0; i
< 3; ++i
) {
1630 for (unsigned j
= 0; j
< 2; ++j
)
1631 EXPECT_FALSE(root_impl
->HasResourceIdForTileAt(i
, j
));
1632 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1633 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1636 layer_tree_host_
->CommitComplete();
1638 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1639 resource_provider_
.get());
1640 layer_tree_host_
->SetRootLayer(nullptr);
1643 class TrackingLayerPainter
: public LayerPainter
{
1645 static scoped_ptr
<TrackingLayerPainter
> Create() {
1646 return make_scoped_ptr(new TrackingLayerPainter());
1649 void Paint(SkCanvas
* canvas
, const gfx::Rect
& content_rect
) override
{
1650 painted_rect_
= content_rect
;
1653 gfx::Rect
PaintedRect() const { return painted_rect_
; }
1654 void ResetPaintedRect() { painted_rect_
= gfx::Rect(); }
1657 gfx::Rect painted_rect_
;
1660 class UpdateTrackingTiledLayer
: public FakeTiledLayer
{
1662 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager
* manager
)
1663 : FakeTiledLayer(manager
) {
1664 scoped_ptr
<TrackingLayerPainter
> painter(TrackingLayerPainter::Create());
1665 tracking_layer_painter_
= painter
.get();
1666 layer_updater_
= BitmapContentLayerUpdater::Create(
1667 painter
.Pass(), &stats_instrumentation_
, 0);
1670 TrackingLayerPainter
* tracking_layer_painter() const {
1671 return tracking_layer_painter_
;
1675 LayerUpdater
* Updater() const override
{ return layer_updater_
.get(); }
1676 ~UpdateTrackingTiledLayer() override
{}
1678 TrackingLayerPainter
* tracking_layer_painter_
;
1679 scoped_refptr
<BitmapContentLayerUpdater
> layer_updater_
;
1680 FakeRenderingStatsInstrumentation stats_instrumentation_
;
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_RECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
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_RECT_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_RECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
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_RECT_EQ(expanded_layer_rect
,
1758 layer
->tracking_layer_painter()->PaintedRect());