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/fake_rendering_stats_instrumentation.h"
22 #include "cc/test/geometry_test_utils.h"
23 #include "cc/test/test_shared_bitmap_manager.h"
24 #include "cc/test/tiled_layer_test_common.h"
25 #include "cc/trees/occlusion_tracker.h"
26 #include "cc/trees/single_thread_proxy.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "ui/gfx/rect_conversions.h"
29 #include "ui/gfx/transform.h"
34 class TestOcclusionTracker
: public OcclusionTracker
<Layer
> {
36 TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000)) {
37 stack_
.push_back(StackObject());
40 void SetRenderTarget(Layer
* render_target
) {
41 stack_
.back().target
= render_target
;
44 void SetOcclusion(const SimpleEnclosedRegion
& occlusion
) {
45 stack_
.back().occlusion_from_inside_target
= occlusion
;
49 class SynchronousOutputSurfaceLayerTreeHost
: public LayerTreeHost
{
51 static scoped_ptr
<SynchronousOutputSurfaceLayerTreeHost
> Create(
52 LayerTreeHostClient
* client
,
53 SharedBitmapManager
* manager
,
54 const LayerTreeSettings
& settings
,
55 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
) {
56 return make_scoped_ptr(new SynchronousOutputSurfaceLayerTreeHost(
57 client
, manager
, settings
, impl_task_runner
));
60 virtual ~SynchronousOutputSurfaceLayerTreeHost() {}
62 bool EnsureOutputSurfaceCreated() {
63 base::MessageLoop::current()->PostDelayedTask(
65 run_loop_
.QuitClosure(),
66 base::TimeDelta::FromSeconds(5));
68 return output_surface_created_
;
71 virtual void OnCreateAndInitializeOutputSurfaceAttempted(
72 bool success
) OVERRIDE
{
73 LayerTreeHost::OnCreateAndInitializeOutputSurfaceAttempted(success
);
74 output_surface_created_
= success
;
79 SynchronousOutputSurfaceLayerTreeHost(
80 LayerTreeHostClient
* client
,
81 SharedBitmapManager
* manager
,
82 const LayerTreeSettings
& settings
,
83 scoped_refptr
<base::SingleThreadTaskRunner
> impl_task_runner
)
84 : LayerTreeHost(client
, manager
, settings
),
85 output_surface_created_(false) {
86 LayerTreeHost::InitializeThreaded(base::MessageLoopProxy::current(),
90 bool output_surface_created_
;
91 base::RunLoop run_loop_
;
94 class TiledLayerTest
: public testing::Test
{
98 output_surface_(FakeOutputSurface::Create3d()),
99 queue_(make_scoped_ptr(new ResourceUpdateQueue
)),
100 impl_thread_("ImplThread"),
101 fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D
),
103 settings_
.max_partial_texture_updates
= std::numeric_limits
<size_t>::max();
104 settings_
.layer_transforms_should_scale_layer_contents
= true;
107 virtual void SetUp() {
108 impl_thread_
.Start();
109 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
110 layer_tree_host_
= SynchronousOutputSurfaceLayerTreeHost::Create(
111 &fake_layer_tree_host_client_
,
112 shared_bitmap_manager_
.get(),
114 impl_thread_
.message_loop_proxy());
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(
126 output_surface_
.get(), shared_bitmap_manager_
.get(), 0, false, 1,
128 host_impl_
= make_scoped_ptr(
129 new FakeLayerTreeHostImpl(proxy_
, shared_bitmap_manager_
.get()));
132 virtual ~TiledLayerTest() {
133 ResourceManagerClearAllMemory(resource_manager_
.get(),
134 resource_provider_
.get());
136 DebugScopedSetImplThreadAndMainThreadBlocked
137 impl_thread_and_main_thread_blocked(proxy_
);
138 resource_provider_
.reset();
142 void ResourceManagerClearAllMemory(
143 PrioritizedResourceManager
* resource_manager
,
144 ResourceProvider
* resource_provider
) {
146 DebugScopedSetImplThreadAndMainThreadBlocked
147 impl_thread_and_main_thread_blocked(proxy_
);
148 resource_manager
->ClearAllMemory(resource_provider
);
149 resource_manager
->ReduceMemory(resource_provider
);
151 resource_manager
->UnlinkAndClearEvictedBackings();
154 void UpdateTextures() {
155 DebugScopedSetImplThreadAndMainThreadBlocked
156 impl_thread_and_main_thread_blocked(proxy_
);
158 scoped_ptr
<ResourceUpdateController
> update_controller
=
159 ResourceUpdateController::Create(NULL
,
160 proxy_
->ImplThreadTaskRunner(),
162 resource_provider_
.get());
163 update_controller
->Finalize();
164 queue_
= make_scoped_ptr(new ResourceUpdateQueue
);
167 void LayerPushPropertiesTo(FakeTiledLayer
* layer
,
168 FakeTiledLayerImpl
* layer_impl
) {
169 DebugScopedSetImplThreadAndMainThreadBlocked
170 impl_thread_and_main_thread_blocked(proxy_
);
171 layer
->PushPropertiesTo(layer_impl
);
172 layer
->ResetNumDependentsNeedPushProperties();
175 void LayerUpdate(FakeTiledLayer
* layer
, TestOcclusionTracker
* occluded
) {
176 DebugScopedSetMainThread
main_thread(proxy_
);
177 layer
->Update(queue_
.get(), occluded
);
180 void CalcDrawProps(RenderSurfaceLayerList
* render_surface_layer_list
) {
182 occlusion_
->SetRenderTarget(layer_tree_host_
->root_layer());
184 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting
inputs(
185 layer_tree_host_
->root_layer(),
186 layer_tree_host_
->device_viewport_size(),
187 render_surface_layer_list
);
188 inputs
.device_scale_factor
= layer_tree_host_
->device_scale_factor();
189 inputs
.max_texture_size
=
190 layer_tree_host_
->GetRendererCapabilities().max_texture_size
;
191 inputs
.can_adjust_raster_scales
= true;
192 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
195 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
196 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
) {
197 scoped_refptr
<FakeTiledLayer
> layer2
;
198 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
;
199 return UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
202 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
203 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
,
204 const scoped_refptr
<FakeTiledLayer
>& layer2
,
205 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl2
) {
207 resource_manager_
->ClearPriorities();
209 layer1
->SetTexturePriorities(priority_calculator_
);
211 layer2
->SetTexturePriorities(priority_calculator_
);
212 resource_manager_
->PrioritizeTextures();
214 // Save paint properties
216 layer1
->SavePaintProperties();
218 layer2
->SavePaintProperties();
222 layer1
->Update(queue_
.get(), occlusion_
);
224 layer2
->Update(queue_
.get(), occlusion_
);
226 bool needs_update
= false;
228 needs_update
|= layer1
->NeedsIdlePaint();
230 needs_update
|= layer2
->NeedsIdlePaint();
232 // Update textures and push.
235 LayerPushPropertiesTo(layer1
.get(), layer_impl1
.get());
237 LayerPushPropertiesTo(layer2
.get(), layer_impl2
.get());
244 LayerTreeSettings settings_
;
245 FakeOutputSurfaceClient output_surface_client_
;
246 scoped_ptr
<OutputSurface
> output_surface_
;
247 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
248 scoped_ptr
<ResourceProvider
> resource_provider_
;
249 scoped_ptr
<ResourceUpdateQueue
> queue_
;
250 PriorityCalculator priority_calculator_
;
251 base::Thread impl_thread_
;
252 FakeLayerTreeHostClient fake_layer_tree_host_client_
;
253 scoped_ptr
<SynchronousOutputSurfaceLayerTreeHost
> layer_tree_host_
;
254 scoped_ptr
<FakeLayerTreeHostImpl
> host_impl_
;
255 scoped_ptr
<PrioritizedResourceManager
> resource_manager_
;
256 TestOcclusionTracker
* occlusion_
;
259 TEST_F(TiledLayerTest
, PushDirtyTiles
) {
260 scoped_refptr
<FakeTiledLayer
> layer
=
261 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
262 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
263 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
264 RenderSurfaceLayerList render_surface_layer_list
;
266 layer_tree_host_
->root_layer()->AddChild(layer
);
268 // The tile size is 100x100, so this invalidates and then paints two tiles.
269 layer
->SetBounds(gfx::Size(100, 200));
270 CalcDrawProps(&render_surface_layer_list
);
271 UpdateAndPush(layer
, layer_impl
);
273 // We should have both tiles on the impl side.
274 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
275 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
277 // Invalidates both tiles, but then only update one of them.
278 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
279 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
280 UpdateAndPush(layer
, layer_impl
);
282 // We should only have the first tile since the other tile was invalidated but
284 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
285 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
288 TEST_F(TiledLayerTest
, PushOccludedDirtyTiles
) {
289 scoped_refptr
<FakeTiledLayer
> layer
=
290 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
291 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
292 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
293 TestOcclusionTracker occluded
;
294 occlusion_
= &occluded
;
295 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
297 layer_tree_host_
->root_layer()->AddChild(layer
);
300 RenderSurfaceLayerList render_surface_layer_list
;
302 // The tile size is 100x100, so this invalidates and then paints two tiles.
303 layer
->SetBounds(gfx::Size(100, 200));
304 CalcDrawProps(&render_surface_layer_list
);
305 UpdateAndPush(layer
, layer_impl
);
307 // We should have both tiles on the impl side.
308 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
309 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
313 RenderSurfaceLayerList render_surface_layer_list
;
315 // Invalidates part of the top tile...
316 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
317 // ....but the area is occluded.
318 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 50, 50)));
319 CalcDrawProps(&render_surface_layer_list
);
320 UpdateAndPush(layer
, layer_impl
);
322 // We should still have both tiles, as part of the top tile is still
324 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
325 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
329 TEST_F(TiledLayerTest
, PushDeletedTiles
) {
330 scoped_refptr
<FakeTiledLayer
> layer
=
331 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
332 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
333 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
334 RenderSurfaceLayerList render_surface_layer_list
;
336 layer_tree_host_
->root_layer()->AddChild(layer
);
338 // The tile size is 100x100, so this invalidates and then paints two tiles.
339 layer
->SetBounds(gfx::Size(100, 200));
340 CalcDrawProps(&render_surface_layer_list
);
341 UpdateAndPush(layer
, layer_impl
);
343 // We should have both tiles on the impl side.
344 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
345 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
347 resource_manager_
->ClearPriorities();
348 ResourceManagerClearAllMemory(resource_manager_
.get(),
349 resource_provider_
.get());
350 resource_manager_
->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
352 // This should drop the tiles on the impl thread.
353 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
355 // We should now have no textures on the impl thread.
356 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
357 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
359 // This should recreate and update one of the deleted textures.
360 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
361 UpdateAndPush(layer
, layer_impl
);
363 // We should have one tiles on the impl side.
364 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
365 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
368 TEST_F(TiledLayerTest
, PushIdlePaintTiles
) {
369 scoped_refptr
<FakeTiledLayer
> layer
=
370 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
371 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
372 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
373 RenderSurfaceLayerList render_surface_layer_list
;
375 layer_tree_host_
->root_layer()->AddChild(layer
);
377 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the
378 // center. This paints 1 visible of the 25 invalid tiles.
379 layer
->SetBounds(gfx::Size(500, 500));
380 CalcDrawProps(&render_surface_layer_list
);
381 layer
->draw_properties().visible_content_rect
= gfx::Rect(200, 200, 100, 100);
382 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
383 // We should need idle-painting for surrounding tiles.
384 EXPECT_TRUE(needs_update
);
386 // We should have one tile on the impl side.
387 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(2, 2));
389 // For the next four updates, we should detect we still need idle painting.
390 for (int i
= 0; i
< 4; i
++) {
391 needs_update
= UpdateAndPush(layer
, layer_impl
);
392 EXPECT_TRUE(needs_update
);
395 // We should always finish painting eventually.
396 for (int i
= 0; i
< 20; i
++)
397 needs_update
= UpdateAndPush(layer
, layer_impl
);
399 // We should have pre-painted all of the surrounding tiles.
400 for (int i
= 0; i
< 5; i
++) {
401 for (int j
= 0; j
< 5; j
++)
402 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
405 EXPECT_FALSE(needs_update
);
408 TEST_F(TiledLayerTest
, PredictivePainting
) {
409 scoped_refptr
<FakeTiledLayer
> layer
=
410 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
411 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
412 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
414 layer_tree_host_
->root_layer()->AddChild(layer
);
416 // Prepainting should occur in the scroll direction first, and the
417 // visible rect should be extruded only along the dominant axis.
418 gfx::Vector2d directions
[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0),
419 gfx::Vector2d(0, -10), gfx::Vector2d(0, 10),
420 gfx::Vector2d(10, 20),
421 gfx::Vector2d(-20, 10) };
422 // We should push all tiles that touch the extruded visible rect.
423 gfx::Rect pushed_visible_tiles
[6] = {
424 gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2),
425 gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1)
427 // The first pre-paint should also paint first in the scroll
428 // direction so we should find one additional tile in the scroll direction.
429 gfx::Rect pushed_prepaint_tiles
[6] = {
430 gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3),
431 gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1)
433 for (int k
= 0; k
< 6; k
++) {
434 // The tile size is 100x100. Setup 5x5 tiles with one visible tile
436 gfx::Size bounds
= gfx::Size(500, 500);
437 gfx::Rect visible_rect
= gfx::Rect(200, 200, 100, 100);
438 gfx::Rect previous_visible_rect
=
439 gfx::Rect(visible_rect
.origin() + directions
[k
], visible_rect
.size());
440 gfx::Rect next_visible_rect
=
441 gfx::Rect(visible_rect
.origin() - directions
[k
], visible_rect
.size());
443 // Setup. Use the previous_visible_rect to setup the prediction for next
445 layer
->SetBounds(bounds
);
447 RenderSurfaceLayerList render_surface_layer_list
;
448 CalcDrawProps(&render_surface_layer_list
);
449 layer
->draw_properties().visible_content_rect
= previous_visible_rect
;
450 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
452 // Invalidate and move the visible_rect in the scroll direction.
453 // Check that the correct tiles have been painted in the visible pass.
454 layer
->SetNeedsDisplay();
455 layer
->draw_properties().visible_content_rect
= visible_rect
;
456 needs_update
= UpdateAndPush(layer
, layer_impl
);
457 for (int i
= 0; i
< 5; i
++) {
458 for (int j
= 0; j
< 5; j
++)
459 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
460 pushed_visible_tiles
[k
].Contains(i
, j
));
463 // Move the transform in the same direction without invalidating.
464 // Check that non-visible pre-painting occured in the correct direction.
465 // Ignore diagonal scrolls here (k > 3) as these have new visible content
468 layer
->draw_properties().visible_content_rect
= next_visible_rect
;
469 needs_update
= UpdateAndPush(layer
, layer_impl
);
470 for (int i
= 0; i
< 5; i
++) {
471 for (int j
= 0; j
< 5; j
++)
472 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
473 pushed_prepaint_tiles
[k
].Contains(i
, j
));
477 // We should always finish painting eventually.
478 for (int i
= 0; i
< 20; i
++)
479 needs_update
= UpdateAndPush(layer
, layer_impl
);
480 EXPECT_FALSE(needs_update
);
484 TEST_F(TiledLayerTest
, PushTilesAfterIdlePaintFailed
) {
485 // Start with 2mb of memory, but the test is going to try to use just more
486 // than 1mb, so we reduce to 1mb later.
487 resource_manager_
->SetMaxMemoryLimitBytes(2 * 1024 * 1024);
488 scoped_refptr
<FakeTiledLayer
> layer1
=
489 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
490 scoped_ptr
<FakeTiledLayerImpl
> layer_impl1
=
491 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
492 scoped_refptr
<FakeTiledLayer
> layer2
=
493 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
494 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
=
495 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
496 RenderSurfaceLayerList render_surface_layer_list
;
498 layer_tree_host_
->root_layer()->AddChild(layer1
);
499 layer_tree_host_
->root_layer()->AddChild(layer2
);
501 // For this test we have two layers. layer1 exhausts most texture memory,
502 // leaving room for 2 more tiles from layer2, but not all three tiles. First
503 // we paint layer1, and one tile from layer2. Then when we idle paint layer2,
504 // we will fail on the third tile of layer2, and this should not leave the
505 // second tile in a bad state.
507 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough
508 // for 2 tiles only in the other layer.
509 gfx::Rect
layer1_rect(0, 0, 100, 2400);
511 // This requires 4*30000 bytes of memory.
512 gfx::Rect
layer2_rect(0, 0, 100, 300);
514 // Paint a single tile in layer2 so that it will idle paint.
515 layer1
->SetBounds(layer1_rect
.size());
516 layer2
->SetBounds(layer2_rect
.size());
517 CalcDrawProps(&render_surface_layer_list
);
518 layer1
->draw_properties().visible_content_rect
= layer1_rect
;
519 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
520 bool needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
521 // We should need idle-painting for both remaining tiles in layer2.
522 EXPECT_TRUE(needs_update
);
524 // Reduce our memory limits to 1mb.
525 resource_manager_
->SetMaxMemoryLimitBytes(1024 * 1024);
527 // Now idle paint layer2. We are going to run out of memory though!
528 // Oh well, commit the frame and push.
529 for (int i
= 0; i
< 4; i
++) {
530 needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
533 // Sanity check, we should have textures for the big layer.
534 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 0));
535 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 23));
537 // We should only have the first two tiles from layer2 since
538 // it failed to idle update the last tile.
539 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
540 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
541 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
542 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
544 EXPECT_FALSE(needs_update
);
545 EXPECT_FALSE(layer_impl2
->HasResourceIdForTileAt(0, 2));
548 TEST_F(TiledLayerTest
, PushIdlePaintedOccludedTiles
) {
549 scoped_refptr
<FakeTiledLayer
> layer
=
550 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
551 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
552 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
553 RenderSurfaceLayerList render_surface_layer_list
;
554 TestOcclusionTracker occluded
;
555 occlusion_
= &occluded
;
557 layer_tree_host_
->root_layer()->AddChild(layer
);
559 // The tile size is 100x100, so this invalidates one occluded tile, culls it
560 // during paint, but prepaints it.
561 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(0, 0, 100, 100)));
563 layer
->SetBounds(gfx::Size(100, 100));
564 CalcDrawProps(&render_surface_layer_list
);
565 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
566 UpdateAndPush(layer
, layer_impl
);
568 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
571 TEST_F(TiledLayerTest
, PushTilesMarkedDirtyDuringPaint
) {
572 scoped_refptr
<FakeTiledLayer
> layer
=
573 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
574 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
575 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
576 RenderSurfaceLayerList render_surface_layer_list
;
578 layer_tree_host_
->root_layer()->AddChild(layer
);
580 // The tile size is 100x100, so this invalidates and then paints two tiles.
581 // However, during the paint, we invalidate one of the tiles. This should
582 // not prevent the tile from being pushed.
583 layer
->fake_layer_updater()->SetRectToInvalidate(
584 gfx::Rect(0, 50, 100, 50), layer
.get());
585 layer
->SetBounds(gfx::Size(100, 200));
586 CalcDrawProps(&render_surface_layer_list
);
587 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
588 UpdateAndPush(layer
, layer_impl
);
590 // We should have both tiles on the impl side.
591 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
592 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
595 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer
) {
596 scoped_refptr
<FakeTiledLayer
> layer1
=
597 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
598 scoped_refptr
<FakeTiledLayer
> layer2
=
599 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
600 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
601 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
602 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
603 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
604 RenderSurfaceLayerList render_surface_layer_list
;
606 layer_tree_host_
->root_layer()->AddChild(layer1
);
607 layer_tree_host_
->root_layer()->AddChild(layer2
);
609 // Invalidate a tile on layer1, during update of layer 2.
610 layer2
->fake_layer_updater()->SetRectToInvalidate(
611 gfx::Rect(0, 50, 100, 50), layer1
.get());
612 layer1
->SetBounds(gfx::Size(100, 200));
613 layer2
->SetBounds(gfx::Size(100, 200));
614 CalcDrawProps(&render_surface_layer_list
);
615 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
616 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
617 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
619 // We should have both tiles on the impl side for all layers.
620 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
621 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
622 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
623 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
626 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
) {
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 layer1
->fake_layer_updater()->SetRectToInvalidate(
641 gfx::Rect(0, 50, 100, 50), layer2
.get());
642 layer1
->SetBounds(gfx::Size(100, 200));
643 layer2
->SetBounds(gfx::Size(100, 200));
644 CalcDrawProps(&render_surface_layer_list
);
645 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
646 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
647 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
649 // We should have both tiles on the impl side for all layers.
650 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
651 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
652 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
653 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
656 TEST_F(TiledLayerTest
, PaintSmallAnimatedLayersImmediately
) {
657 // Create a LayerTreeHost that has the right viewportsize,
658 // so the layer is considered small enough.
659 bool run_out_of_memory
[2] = { false, true };
660 for (int i
= 0; i
< 2; i
++) {
661 // Create a layer with 5x5 tiles, with 4x4 size viewport.
662 int viewport_width
= 4 * FakeTiledLayer::tile_size().width();
663 int viewport_height
= 4 * FakeTiledLayer::tile_size().width();
664 int layer_width
= 5 * FakeTiledLayer::tile_size().width();
665 int layer_height
= 5 * FakeTiledLayer::tile_size().height();
666 int memory_for_layer
= layer_width
* layer_height
* 4;
667 layer_tree_host_
->SetViewportSize(
668 gfx::Size(viewport_width
, viewport_height
));
670 // Use 10x5 tiles to run out of memory.
671 if (run_out_of_memory
[i
])
674 resource_manager_
->SetMaxMemoryLimitBytes(memory_for_layer
);
676 scoped_refptr
<FakeTiledLayer
> layer
=
677 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
678 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
679 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
680 RenderSurfaceLayerList render_surface_layer_list
;
682 layer_tree_host_
->root_layer()->AddChild(layer
);
684 // Full size layer with half being visible.
685 layer
->SetBounds(gfx::Size(layer_width
, layer_height
));
686 gfx::Rect
visible_rect(0, 0, layer_width
/ 2, layer_height
);
687 CalcDrawProps(&render_surface_layer_list
);
689 // Pretend the layer is animating.
690 layer
->draw_properties().target_space_transform_is_animating
= true;
691 layer
->draw_properties().visible_content_rect
= visible_rect
;
692 layer
->SetLayerTreeHost(layer_tree_host_
.get());
694 // The layer should paint its entire contents on the first paint
695 // if it is close to the viewport size and has the available memory.
696 layer
->SetTexturePriorities(priority_calculator_
);
697 resource_manager_
->PrioritizeTextures();
698 layer
->SavePaintProperties();
699 layer
->Update(queue_
.get(), NULL
);
701 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
703 // We should have all the tiles for the small animated layer.
704 // We should still have the visible tiles when we didn't
705 // have enough memory for all the tiles.
706 if (!run_out_of_memory
[i
]) {
707 for (int i
= 0; i
< 5; ++i
) {
708 for (int j
= 0; j
< 5; ++j
)
709 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
712 for (int i
= 0; i
< 10; ++i
) {
713 for (int j
= 0; j
< 5; ++j
)
714 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
), i
< 5);
718 layer
->RemoveFromParent();
722 TEST_F(TiledLayerTest
, IdlePaintOutOfMemory
) {
723 scoped_refptr
<FakeTiledLayer
> layer
=
724 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
725 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
726 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
727 RenderSurfaceLayerList render_surface_layer_list
;
729 layer_tree_host_
->root_layer()->AddChild(layer
);
731 // We have enough memory for only the visible rect, so we will run out of
732 // memory in first idle paint.
733 int memory_limit
= 4 * 100 * 100; // 1 tiles, 4 bytes per pixel.
734 resource_manager_
->SetMaxMemoryLimitBytes(memory_limit
);
736 // The tile size is 100x100, so this invalidates and then paints two tiles.
737 bool needs_update
= false;
738 layer
->SetBounds(gfx::Size(300, 300));
739 CalcDrawProps(&render_surface_layer_list
);
740 layer
->draw_properties().visible_content_rect
= gfx::Rect(100, 100, 100, 100);
741 for (int i
= 0; i
< 2; i
++)
742 needs_update
= UpdateAndPush(layer
, layer_impl
);
744 // Idle-painting should see no more priority tiles for painting.
745 EXPECT_FALSE(needs_update
);
747 // We should have one tile on the impl side.
748 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
751 TEST_F(TiledLayerTest
, IdlePaintZeroSizedLayer
) {
752 scoped_refptr
<FakeTiledLayer
> layer
=
753 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
754 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
755 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
757 layer_tree_host_
->root_layer()->AddChild(layer
);
759 bool animating
[2] = { false, true };
760 for (int i
= 0; i
< 2; i
++) {
761 // Pretend the layer is animating.
762 layer
->draw_properties().target_space_transform_is_animating
= animating
[i
];
764 // The layer's bounds are empty.
765 // Empty layers don't paint or idle-paint.
766 layer
->SetBounds(gfx::Size());
768 RenderSurfaceLayerList render_surface_layer_list
;
769 CalcDrawProps(&render_surface_layer_list
);
770 layer
->draw_properties().visible_content_rect
= gfx::Rect();
771 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
773 // Empty layers don't have tiles.
774 EXPECT_EQ(0u, layer
->NumPaintedTiles());
776 // Empty layers don't need prepaint.
777 EXPECT_FALSE(needs_update
);
779 // Empty layers don't have tiles.
780 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
784 TEST_F(TiledLayerTest
, IdlePaintNonVisibleLayers
) {
785 scoped_refptr
<FakeTiledLayer
> layer
=
786 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
787 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
788 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
790 // Alternate between not visible and visible.
791 gfx::Rect
v(0, 0, 100, 100);
792 gfx::Rect
nv(0, 0, 0, 0);
793 gfx::Rect visible_rect
[10] = { nv
, nv
, v
, v
, nv
, nv
, v
, v
, nv
, nv
};
794 bool invalidate
[10] = { true, true, true, true, true, true, true, true, false,
797 // We should not have any tiles except for when the layer was visible
798 // or after the layer was visible and we didn't invalidate.
799 bool have_tile
[10] = { false, false, true, true, false, false, true, true,
802 layer_tree_host_
->root_layer()->AddChild(layer
);
804 for (int i
= 0; i
< 10; i
++) {
805 layer
->SetBounds(gfx::Size(100, 100));
807 RenderSurfaceLayerList render_surface_layer_list
;
808 CalcDrawProps(&render_surface_layer_list
);
809 layer
->draw_properties().visible_content_rect
= visible_rect
[i
];
812 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
813 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
815 // We should never signal idle paint, as we painted the entire layer
816 // or the layer was not visible.
817 EXPECT_FALSE(needs_update
);
818 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(0, 0), have_tile
[i
]);
822 TEST_F(TiledLayerTest
, InvalidateFromPrepare
) {
823 scoped_refptr
<FakeTiledLayer
> layer
=
824 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
825 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
826 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
827 RenderSurfaceLayerList render_surface_layer_list
;
829 layer_tree_host_
->root_layer()->AddChild(layer
);
831 // The tile size is 100x100, so this invalidates and then paints two tiles.
832 layer
->SetBounds(gfx::Size(100, 200));
833 CalcDrawProps(&render_surface_layer_list
);
834 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
835 UpdateAndPush(layer
, layer_impl
);
837 // We should have both tiles on the impl side.
838 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
839 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
841 layer
->fake_layer_updater()->ClearPrepareCount();
842 // Invoke update again. As the layer is valid update shouldn't be invoked on
844 UpdateAndPush(layer
, layer_impl
);
845 EXPECT_EQ(0, layer
->fake_layer_updater()->prepare_count());
847 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
849 layer
->fake_layer_updater()->SetRectToInvalidate(
850 gfx::Rect(25, 25, 50, 50), layer
.get());
851 layer
->fake_layer_updater()->ClearPrepareCount();
852 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
853 UpdateAndPush(layer
, layer_impl
);
854 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
855 layer
->fake_layer_updater()->ClearPrepareCount();
857 // The layer should still be invalid as update invoked invalidate.
858 UpdateAndPush(layer
, layer_impl
); // visible
859 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
862 TEST_F(TiledLayerTest
, VerifyUpdateRectWhenContentBoundsAreScaled
) {
863 // The update rect (that indicates what was actually painted) should be in
864 // layer space, not the content space.
865 scoped_refptr
<FakeTiledLayerWithScaledBounds
> layer
= make_scoped_refptr(
866 new FakeTiledLayerWithScaledBounds(resource_manager_
.get()));
868 layer_tree_host_
->root_layer()->AddChild(layer
);
870 gfx::Rect
layer_bounds(0, 0, 300, 200);
871 gfx::Rect
content_bounds(0, 0, 200, 250);
873 layer
->SetBounds(layer_bounds
.size());
874 layer
->SetContentBounds(content_bounds
.size());
875 layer
->draw_properties().visible_content_rect
= content_bounds
;
877 // On first update, the update_rect includes all tiles, even beyond the
878 // boundaries of the layer.
879 // However, it should still be in layer space, not content space.
880 layer
->InvalidateContentRect(content_bounds
);
882 layer
->SetTexturePriorities(priority_calculator_
);
883 resource_manager_
->PrioritizeTextures();
884 layer
->SavePaintProperties();
885 layer
->Update(queue_
.get(), NULL
);
886 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 300, 300 * 0.8), layer
->update_rect());
889 // After the tiles are updated once, another invalidate only needs to update
890 // the bounds of the layer.
891 layer
->SetTexturePriorities(priority_calculator_
);
892 resource_manager_
->PrioritizeTextures();
893 layer
->InvalidateContentRect(content_bounds
);
894 layer
->SavePaintProperties();
895 layer
->Update(queue_
.get(), NULL
);
896 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds
), layer
->update_rect());
899 // Partial re-paint should also be represented by the update rect in layer
900 // space, not content space.
901 gfx::Rect
partial_damage(30, 100, 10, 10);
902 layer
->InvalidateContentRect(partial_damage
);
903 layer
->SetTexturePriorities(priority_calculator_
);
904 resource_manager_
->PrioritizeTextures();
905 layer
->SavePaintProperties();
906 layer
->Update(queue_
.get(), NULL
);
907 EXPECT_FLOAT_RECT_EQ(gfx::RectF(45, 80, 15, 8), layer
->update_rect());
910 TEST_F(TiledLayerTest
, VerifyInvalidationWhenContentsScaleChanges
) {
911 scoped_refptr
<FakeTiledLayer
> layer
=
912 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
913 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
914 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
915 RenderSurfaceLayerList render_surface_layer_list
;
917 layer_tree_host_
->root_layer()->AddChild(layer
);
919 // Create a layer with one tile.
920 layer
->SetBounds(gfx::Size(100, 100));
921 CalcDrawProps(&render_surface_layer_list
);
922 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
923 layer
->Update(queue_
.get(), NULL
);
925 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
926 layer
->last_needs_display_rect());
928 // Push the tiles to the impl side and check that there is exactly one.
929 layer
->SetTexturePriorities(priority_calculator_
);
930 resource_manager_
->PrioritizeTextures();
931 layer
->SavePaintProperties();
932 layer
->Update(queue_
.get(), NULL
);
934 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
935 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
936 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
937 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
938 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
940 layer
->SetNeedsDisplayRect(gfx::Rect());
941 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer
->last_needs_display_rect());
943 // Change the contents scale.
944 layer
->UpdateContentsScale(2.f
);
945 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 200, 200);
947 // The impl side should get 2x2 tiles now.
948 layer
->SetTexturePriorities(priority_calculator_
);
949 resource_manager_
->PrioritizeTextures();
950 layer
->SavePaintProperties();
951 layer
->Update(queue_
.get(), NULL
);
953 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
954 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
955 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
956 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 0));
957 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
959 // Verify that changing the contents scale caused invalidation, and
960 // that the layer-space rectangle requiring painting is not scaled.
961 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
962 layer
->last_needs_display_rect());
964 // Invalidate the entire layer again, but do not paint. All tiles should be
965 // gone now from the impl side.
966 layer
->SetNeedsDisplay();
967 layer
->SetTexturePriorities(priority_calculator_
);
968 resource_manager_
->PrioritizeTextures();
970 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
971 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
972 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
973 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
974 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
977 TEST_F(TiledLayerTest
, SkipsDrawGetsReset
) {
978 // Create two 300 x 300 tiled layers.
979 gfx::Size
content_bounds(300, 300);
980 gfx::Rect
content_rect(content_bounds
);
982 // We have enough memory for only one of the two layers.
983 int memory_limit
= 4 * 300 * 300; // 4 bytes per pixel.
985 scoped_refptr
<FakeTiledLayer
> root_layer
= make_scoped_refptr(
986 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
987 scoped_refptr
<FakeTiledLayer
> child_layer
= make_scoped_refptr(
988 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
989 root_layer
->AddChild(child_layer
);
991 root_layer
->SetBounds(content_bounds
);
992 root_layer
->draw_properties().visible_content_rect
= content_rect
;
993 root_layer
->SetPosition(gfx::PointF(0, 0));
994 child_layer
->SetBounds(content_bounds
);
995 child_layer
->draw_properties().visible_content_rect
= content_rect
;
996 child_layer
->SetPosition(gfx::PointF(0, 0));
997 root_layer
->InvalidateContentRect(content_rect
);
998 child_layer
->InvalidateContentRect(content_rect
);
1000 layer_tree_host_
->SetRootLayer(root_layer
);
1001 layer_tree_host_
->SetViewportSize(gfx::Size(300, 300));
1002 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1005 layer_tree_host_
->UpdateLayers(queue_
.get());
1007 // We'll skip the root layer.
1008 EXPECT_TRUE(root_layer
->SkipsDraw());
1009 EXPECT_FALSE(child_layer
->SkipsDraw());
1011 layer_tree_host_
->CommitComplete();
1013 // Remove the child layer.
1014 root_layer
->RemoveAllChildren();
1016 layer_tree_host_
->UpdateLayers(queue_
.get());
1017 EXPECT_FALSE(root_layer
->SkipsDraw());
1019 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1020 resource_provider_
.get());
1021 layer_tree_host_
->SetRootLayer(NULL
);
1024 TEST_F(TiledLayerTest
, ResizeToSmaller
) {
1025 scoped_refptr
<FakeTiledLayer
> layer
=
1026 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1028 layer_tree_host_
->root_layer()->AddChild(layer
);
1030 layer
->SetBounds(gfx::Size(700, 700));
1031 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1032 layer
->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
1034 layer
->SetTexturePriorities(priority_calculator_
);
1035 resource_manager_
->PrioritizeTextures();
1036 layer
->SavePaintProperties();
1037 layer
->Update(queue_
.get(), NULL
);
1039 layer
->SetBounds(gfx::Size(200, 200));
1040 layer
->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
1043 TEST_F(TiledLayerTest
, HugeLayerUpdateCrash
) {
1044 scoped_refptr
<FakeTiledLayer
> layer
=
1045 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1047 layer_tree_host_
->root_layer()->AddChild(layer
);
1050 layer
->SetBounds(gfx::Size(size
, size
));
1051 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1052 layer
->InvalidateContentRect(gfx::Rect(0, 0, size
, size
));
1054 // Ensure no crash for bounds where size * size would overflow an int.
1055 layer
->SetTexturePriorities(priority_calculator_
);
1056 resource_manager_
->PrioritizeTextures();
1057 layer
->SavePaintProperties();
1058 layer
->Update(queue_
.get(), NULL
);
1061 class TiledLayerPartialUpdateTest
: public TiledLayerTest
{
1063 TiledLayerPartialUpdateTest() { settings_
.max_partial_texture_updates
= 4; }
1066 TEST_F(TiledLayerPartialUpdateTest
, PartialUpdates
) {
1067 // Create one 300 x 200 tiled layer with 3 x 2 tiles.
1068 gfx::Size
content_bounds(300, 200);
1069 gfx::Rect
content_rect(content_bounds
);
1071 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
1072 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1073 layer
->SetBounds(content_bounds
);
1074 layer
->SetPosition(gfx::PointF(0, 0));
1075 layer
->draw_properties().visible_content_rect
= content_rect
;
1076 layer
->InvalidateContentRect(content_rect
);
1078 layer_tree_host_
->SetRootLayer(layer
);
1079 layer_tree_host_
->SetViewportSize(gfx::Size(300, 200));
1081 // Full update of all 6 tiles.
1082 layer_tree_host_
->UpdateLayers(queue_
.get());
1084 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1085 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1086 EXPECT_EQ(6u, queue_
->FullUploadSize());
1087 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1089 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1090 EXPECT_FALSE(queue_
->HasMoreUpdates());
1091 layer
->fake_layer_updater()->ClearUpdateCount();
1092 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1094 layer_tree_host_
->CommitComplete();
1096 // Full update of 3 tiles and partial update of 3 tiles.
1097 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
1098 layer_tree_host_
->UpdateLayers(queue_
.get());
1100 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1101 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1102 EXPECT_EQ(3u, queue_
->FullUploadSize());
1103 EXPECT_EQ(3u, queue_
->PartialUploadSize());
1105 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1106 EXPECT_FALSE(queue_
->HasMoreUpdates());
1107 layer
->fake_layer_updater()->ClearUpdateCount();
1108 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1110 layer_tree_host_
->CommitComplete();
1112 // Partial update of 6 tiles.
1113 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1115 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1116 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1117 layer_tree_host_
->UpdateLayers(queue_
.get());
1118 EXPECT_EQ(2u, queue_
->FullUploadSize());
1119 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1121 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1122 EXPECT_FALSE(queue_
->HasMoreUpdates());
1123 layer
->fake_layer_updater()->ClearUpdateCount();
1124 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1126 layer_tree_host_
->CommitComplete();
1128 // Checkerboard all tiles.
1129 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
1131 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1132 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1133 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1135 layer_tree_host_
->CommitComplete();
1137 // Partial update of 6 checkerboard tiles.
1138 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1140 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1141 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1142 layer_tree_host_
->UpdateLayers(queue_
.get());
1143 EXPECT_EQ(6u, queue_
->FullUploadSize());
1144 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1146 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1147 EXPECT_FALSE(queue_
->HasMoreUpdates());
1148 layer
->fake_layer_updater()->ClearUpdateCount();
1149 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1151 layer_tree_host_
->CommitComplete();
1153 // Partial update of 4 tiles.
1154 layer
->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
1156 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1157 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1158 layer_tree_host_
->UpdateLayers(queue_
.get());
1159 EXPECT_EQ(0u, queue_
->FullUploadSize());
1160 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1162 EXPECT_EQ(4, layer
->fake_layer_updater()->update_count());
1163 EXPECT_FALSE(queue_
->HasMoreUpdates());
1164 layer
->fake_layer_updater()->ClearUpdateCount();
1165 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1167 layer_tree_host_
->CommitComplete();
1169 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1170 resource_provider_
.get());
1171 layer_tree_host_
->SetRootLayer(NULL
);
1174 TEST_F(TiledLayerTest
, TilesPaintedWithoutOcclusion
) {
1175 scoped_refptr
<FakeTiledLayer
> layer
=
1176 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1177 RenderSurfaceLayerList render_surface_layer_list
;
1179 layer_tree_host_
->root_layer()->AddChild(layer
);
1181 // The tile size is 100x100, so this invalidates and then paints two tiles.
1182 layer
->SetBounds(gfx::Size(100, 200));
1183 CalcDrawProps(&render_surface_layer_list
);
1185 layer
->SetTexturePriorities(priority_calculator_
);
1186 resource_manager_
->PrioritizeTextures();
1187 layer
->SavePaintProperties();
1188 layer
->Update(queue_
.get(), NULL
);
1189 EXPECT_EQ(2, layer
->fake_layer_updater()->update_count());
1192 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusion
) {
1193 scoped_refptr
<FakeTiledLayer
> layer
=
1194 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1195 RenderSurfaceLayerList render_surface_layer_list
;
1196 TestOcclusionTracker occluded
;
1197 occlusion_
= &occluded
;
1199 layer_tree_host_
->root_layer()->AddChild(layer
);
1201 // The tile size is 100x100.
1203 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1204 layer
->SetBounds(gfx::Size(600, 600));
1205 CalcDrawProps(&render_surface_layer_list
);
1207 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1208 layer
->draw_properties().drawable_content_rect
=
1209 gfx::Rect(layer
->content_bounds());
1210 layer
->draw_properties().visible_content_rect
=
1211 gfx::Rect(layer
->content_bounds());
1212 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1214 layer
->SetTexturePriorities(priority_calculator_
);
1215 resource_manager_
->PrioritizeTextures();
1216 layer
->SavePaintProperties();
1217 layer
->Update(queue_
.get(), &occluded
);
1218 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1220 layer
->fake_layer_updater()->ClearUpdateCount();
1221 layer
->SetTexturePriorities(priority_calculator_
);
1222 resource_manager_
->PrioritizeTextures();
1224 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 200, 300, 100)));
1225 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1226 layer
->SavePaintProperties();
1227 layer
->Update(queue_
.get(), &occluded
);
1228 EXPECT_EQ(36 - 2, layer
->fake_layer_updater()->update_count());
1230 layer
->fake_layer_updater()->ClearUpdateCount();
1231 layer
->SetTexturePriorities(priority_calculator_
);
1232 resource_manager_
->PrioritizeTextures();
1234 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(250, 250, 300, 100)));
1235 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1236 layer
->SavePaintProperties();
1237 layer
->Update(queue_
.get(), &occluded
);
1238 EXPECT_EQ(36, layer
->fake_layer_updater()->update_count());
1241 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndVisiblityConstraints
) {
1242 scoped_refptr
<FakeTiledLayer
> layer
=
1243 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1244 RenderSurfaceLayerList render_surface_layer_list
;
1245 TestOcclusionTracker occluded
;
1246 occlusion_
= &occluded
;
1248 layer_tree_host_
->root_layer()->AddChild(layer
);
1250 // The tile size is 100x100.
1252 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1253 layer
->SetBounds(gfx::Size(600, 600));
1254 CalcDrawProps(&render_surface_layer_list
);
1256 // The partially occluded tiles (by the 150 occlusion height) are visible
1257 // beyond the occlusion, so not culled.
1258 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1259 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 360);
1260 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 360);
1261 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1263 layer
->SetTexturePriorities(priority_calculator_
);
1264 resource_manager_
->PrioritizeTextures();
1265 layer
->SavePaintProperties();
1266 layer
->Update(queue_
.get(), &occluded
);
1267 EXPECT_EQ(24 - 3, layer
->fake_layer_updater()->update_count());
1269 layer
->fake_layer_updater()->ClearUpdateCount();
1271 // Now the visible region stops at the edge of the occlusion so the partly
1272 // visible tiles become fully occluded.
1273 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1274 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 350);
1275 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 350);
1276 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1277 layer
->SetTexturePriorities(priority_calculator_
);
1278 resource_manager_
->PrioritizeTextures();
1279 layer
->SavePaintProperties();
1280 layer
->Update(queue_
.get(), &occluded
);
1281 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1283 layer
->fake_layer_updater()->ClearUpdateCount();
1285 // Now the visible region is even smaller than the occlusion, it should have
1287 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 150)));
1288 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 340);
1289 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 340);
1290 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 - 6, layer
->fake_layer_updater()->update_count());
1298 TEST_F(TiledLayerTest
, TilesNotPaintedWithoutInvalidation
) {
1299 scoped_refptr
<FakeTiledLayer
> layer
=
1300 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1301 RenderSurfaceLayerList render_surface_layer_list
;
1302 TestOcclusionTracker occluded
;
1303 occlusion_
= &occluded
;
1305 layer_tree_host_
->root_layer()->AddChild(layer
);
1307 // The tile size is 100x100.
1309 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1310 layer
->SetBounds(gfx::Size(600, 600));
1311 CalcDrawProps(&render_surface_layer_list
);
1313 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1314 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 600);
1315 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 600);
1316 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1317 layer
->SetTexturePriorities(priority_calculator_
);
1318 resource_manager_
->PrioritizeTextures();
1319 layer
->SavePaintProperties();
1320 layer
->Update(queue_
.get(), &occluded
);
1321 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1324 layer
->fake_layer_updater()->ClearUpdateCount();
1325 layer
->SetTexturePriorities(priority_calculator_
);
1326 resource_manager_
->PrioritizeTextures();
1327 layer
->SavePaintProperties();
1329 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
1331 layer
->Update(queue_
.get(), &occluded
);
1332 EXPECT_EQ(3, layer
->fake_layer_updater()->update_count());
1335 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndTransforms
) {
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 // This makes sure the painting works when the occluded region (in screen
1347 // space) is transformed differently than the layer.
1348 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1349 layer
->SetBounds(gfx::Size(600, 600));
1350 CalcDrawProps(&render_surface_layer_list
);
1351 gfx::Transform screen_transform
;
1352 screen_transform
.Scale(0.5, 0.5);
1353 layer
->draw_properties().screen_space_transform
= screen_transform
;
1354 layer
->draw_properties().target_space_transform
= screen_transform
;
1356 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 50)));
1357 layer
->draw_properties().drawable_content_rect
=
1358 gfx::Rect(layer
->content_bounds());
1359 layer
->draw_properties().visible_content_rect
=
1360 gfx::Rect(layer
->content_bounds());
1361 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1362 layer
->SetTexturePriorities(priority_calculator_
);
1363 resource_manager_
->PrioritizeTextures();
1364 layer
->SavePaintProperties();
1365 layer
->Update(queue_
.get(), &occluded
);
1366 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1369 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndScaling
) {
1370 scoped_refptr
<FakeTiledLayer
> layer
=
1371 new FakeTiledLayer(resource_manager_
.get());
1372 RenderSurfaceLayerList render_surface_layer_list
;
1373 TestOcclusionTracker occluded
;
1374 occlusion_
= &occluded
;
1376 scoped_refptr
<FakeTiledLayer
> scale_layer
=
1377 new FakeTiledLayer(resource_manager_
.get());
1378 gfx::Transform scale_transform
;
1379 scale_transform
.Scale(2.0, 2.0);
1380 scale_layer
->SetTransform(scale_transform
);
1382 layer_tree_host_
->root_layer()->AddChild(scale_layer
);
1384 // The tile size is 100x100.
1386 // This makes sure the painting works when the content space is scaled to
1387 // a different layer space.
1388 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1389 layer
->SetBounds(gfx::Size(300, 300));
1390 scale_layer
->AddChild(layer
);
1391 CalcDrawProps(&render_surface_layer_list
);
1392 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_x());
1393 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_y());
1394 EXPECT_EQ(gfx::Size(600, 600).ToString(),
1395 layer
->content_bounds().ToString());
1397 // No tiles are covered by the 300x50 occlusion.
1398 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 50)));
1399 layer
->draw_properties().drawable_content_rect
=
1400 gfx::Rect(layer
->bounds());
1401 layer
->draw_properties().visible_content_rect
=
1402 gfx::Rect(layer
->content_bounds());
1403 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1404 layer
->SetTexturePriorities(priority_calculator_
);
1405 resource_manager_
->PrioritizeTextures();
1406 layer
->SavePaintProperties();
1407 layer
->Update(queue_
.get(), &occluded
);
1408 int visible_tiles1
= 6 * 6;
1409 EXPECT_EQ(visible_tiles1
, layer
->fake_layer_updater()->update_count());
1411 layer
->fake_layer_updater()->ClearUpdateCount();
1413 // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still.
1414 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(200, 200, 300, 100)));
1415 layer
->draw_properties().drawable_content_rect
=
1416 gfx::Rect(layer
->bounds());
1417 layer
->draw_properties().visible_content_rect
=
1418 gfx::Rect(layer
->content_bounds());
1419 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1420 layer
->SetTexturePriorities(priority_calculator_
);
1421 resource_manager_
->PrioritizeTextures();
1422 layer
->SavePaintProperties();
1423 layer
->Update(queue_
.get(), &occluded
);
1424 int visible_tiles2
= 6 * 6 - 3;
1425 EXPECT_EQ(visible_tiles2
, layer
->fake_layer_updater()->update_count());
1427 layer
->fake_layer_updater()->ClearUpdateCount();
1429 // This makes sure content scaling and transforms work together.
1430 // When the tiles are scaled down by half, they are 50x50 each in the
1432 gfx::Transform screen_transform
;
1433 screen_transform
.Scale(0.5, 0.5);
1434 layer
->draw_properties().screen_space_transform
= screen_transform
;
1435 layer
->draw_properties().target_space_transform
= screen_transform
;
1437 // An occlusion of 150x100 will cover 3*2 = 6 tiles.
1438 occluded
.SetOcclusion(SimpleEnclosedRegion(gfx::Rect(100, 100, 150, 100)));
1440 gfx::Rect
layer_bounds_rect(layer
->bounds());
1441 layer
->draw_properties().drawable_content_rect
=
1442 gfx::ScaleToEnclosingRect(layer_bounds_rect
, 0.5f
);
1443 layer
->draw_properties().visible_content_rect
=
1444 gfx::Rect(layer
->content_bounds());
1445 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1446 layer
->SetTexturePriorities(priority_calculator_
);
1447 resource_manager_
->PrioritizeTextures();
1448 layer
->SavePaintProperties();
1449 layer
->Update(queue_
.get(), &occluded
);
1450 int visible_tiles3
= 6 * 6 - 6;
1451 EXPECT_EQ(visible_tiles3
, layer
->fake_layer_updater()->update_count());
1454 TEST_F(TiledLayerTest
, VisibleContentOpaqueRegion
) {
1455 scoped_refptr
<FakeTiledLayer
> layer
=
1456 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1457 RenderSurfaceLayerList render_surface_layer_list
;
1458 TestOcclusionTracker occluded
;
1459 occlusion_
= &occluded
;
1460 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
1462 layer_tree_host_
->root_layer()->AddChild(layer
);
1464 // The tile size is 100x100, so this invalidates and then paints two tiles in
1467 gfx::Rect opaque_paint_rect
;
1468 SimpleEnclosedRegion opaque_contents
;
1470 gfx::Rect content_bounds
= gfx::Rect(0, 0, 100, 200);
1471 gfx::Rect visible_bounds
= gfx::Rect(0, 0, 100, 150);
1473 layer
->SetBounds(content_bounds
.size());
1474 CalcDrawProps(&render_surface_layer_list
);
1475 layer
->draw_properties().drawable_content_rect
= visible_bounds
;
1476 layer
->draw_properties().visible_content_rect
= visible_bounds
;
1478 // If the layer doesn't paint opaque content, then the
1479 // VisibleContentOpaqueRegion should be empty.
1480 layer
->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1481 layer
->InvalidateContentRect(content_bounds
);
1482 layer
->SetTexturePriorities(priority_calculator_
);
1483 resource_manager_
->PrioritizeTextures();
1484 layer
->SavePaintProperties();
1485 layer
->Update(queue_
.get(), &occluded
);
1486 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1487 EXPECT_TRUE(opaque_contents
.IsEmpty());
1489 // VisibleContentOpaqueRegion should match the visible part of what is painted
1491 opaque_paint_rect
= gfx::Rect(10, 10, 90, 190);
1492 layer
->fake_layer_updater()->SetOpaquePaintRect(opaque_paint_rect
);
1493 layer
->InvalidateContentRect(content_bounds
);
1494 layer
->SetTexturePriorities(priority_calculator_
);
1495 resource_manager_
->PrioritizeTextures();
1496 layer
->SavePaintProperties();
1497 layer
->Update(queue_
.get(), &occluded
);
1499 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1500 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect
, visible_bounds
).ToString(),
1501 opaque_contents
.ToString());
1503 // If we paint again without invalidating, the same stuff should be opaque.
1504 layer
->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1505 layer
->SetTexturePriorities(priority_calculator_
);
1506 resource_manager_
->PrioritizeTextures();
1507 layer
->SavePaintProperties();
1508 layer
->Update(queue_
.get(), &occluded
);
1510 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1511 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect
, visible_bounds
).ToString(),
1512 opaque_contents
.ToString());
1514 // If we repaint a non-opaque part of the tile, then it shouldn't lose its
1515 // opaque-ness. And other tiles should not be affected.
1516 layer
->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1517 layer
->InvalidateContentRect(gfx::Rect(0, 0, 1, 1));
1518 layer
->SetTexturePriorities(priority_calculator_
);
1519 resource_manager_
->PrioritizeTextures();
1520 layer
->SavePaintProperties();
1521 layer
->Update(queue_
.get(), &occluded
);
1523 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1524 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect
, visible_bounds
).ToString(),
1525 opaque_contents
.ToString());
1527 // If we repaint an opaque part of the tile, then it should lose its
1528 // opaque-ness. But other tiles should still not be affected.
1529 layer
->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1530 layer
->InvalidateContentRect(gfx::Rect(10, 10, 1, 1));
1531 layer
->SetTexturePriorities(priority_calculator_
);
1532 resource_manager_
->PrioritizeTextures();
1533 layer
->SavePaintProperties();
1534 layer
->Update(queue_
.get(), &occluded
);
1536 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1537 EXPECT_EQ(gfx::IntersectRects(gfx::Rect(10, 100, 90, 100),
1538 visible_bounds
).ToString(),
1539 opaque_contents
.ToString());
1542 TEST_F(TiledLayerTest
, DontAllocateContentsWhenTargetSurfaceCantBeAllocated
) {
1543 // Tile size is 100x100.
1544 gfx::Rect
root_rect(0, 0, 300, 200);
1545 gfx::Rect
child_rect(0, 0, 300, 100);
1546 gfx::Rect
child2_rect(0, 100, 300, 100);
1548 scoped_refptr
<FakeTiledLayer
> root
= make_scoped_refptr(
1549 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1550 scoped_refptr
<Layer
> surface
= Layer::Create();
1551 scoped_refptr
<FakeTiledLayer
> child
= make_scoped_refptr(
1552 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1553 scoped_refptr
<FakeTiledLayer
> child2
= make_scoped_refptr(
1554 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1556 root
->SetBounds(root_rect
.size());
1557 root
->draw_properties().drawable_content_rect
= root_rect
;
1558 root
->draw_properties().visible_content_rect
= root_rect
;
1559 root
->AddChild(surface
);
1561 surface
->SetForceRenderSurface(true);
1562 surface
->SetOpacity(0.5);
1563 surface
->AddChild(child
);
1564 surface
->AddChild(child2
);
1566 child
->SetBounds(child_rect
.size());
1567 child
->SetPosition(child_rect
.origin());
1568 child
->draw_properties().visible_content_rect
= child_rect
;
1569 child
->draw_properties().drawable_content_rect
= root_rect
;
1571 child2
->SetBounds(child2_rect
.size());
1572 child2
->SetPosition(child2_rect
.origin());
1573 child2
->draw_properties().visible_content_rect
= child2_rect
;
1574 child2
->draw_properties().drawable_content_rect
= root_rect
;
1576 layer_tree_host_
->SetRootLayer(root
);
1577 layer_tree_host_
->SetViewportSize(root_rect
.size());
1579 // With a huge memory limit, all layers should update and push their textures.
1580 root
->InvalidateContentRect(root_rect
);
1581 child
->InvalidateContentRect(child_rect
);
1582 child2
->InvalidateContentRect(child2_rect
);
1583 layer_tree_host_
->UpdateLayers(queue_
.get());
1586 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1587 EXPECT_EQ(3, child
->fake_layer_updater()->update_count());
1588 EXPECT_EQ(3, child2
->fake_layer_updater()->update_count());
1589 EXPECT_FALSE(queue_
->HasMoreUpdates());
1591 root
->fake_layer_updater()->ClearUpdateCount();
1592 child
->fake_layer_updater()->ClearUpdateCount();
1593 child2
->fake_layer_updater()->ClearUpdateCount();
1595 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1596 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1597 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1598 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1599 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1600 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1601 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1602 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1603 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1605 for (unsigned i
= 0; i
< 3; ++i
) {
1606 for (unsigned j
= 0; j
< 2; ++j
)
1607 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1608 EXPECT_TRUE(child_impl
->HasResourceIdForTileAt(i
, 0));
1609 EXPECT_TRUE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1612 layer_tree_host_
->CommitComplete();
1614 // With a memory limit that includes only the root layer (3x2 tiles) and half
1615 // the surface that the child layers draw into, the child layers will not be
1616 // allocated. If the surface isn't accounted for, then one of the children
1617 // would fit within the memory limit.
1618 root
->InvalidateContentRect(root_rect
);
1619 child
->InvalidateContentRect(child_rect
);
1620 child2
->InvalidateContentRect(child2_rect
);
1622 size_t memory_limit
= (3 * 2 + 3 * 1) * (100 * 100) * 4;
1623 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1625 layer_tree_host_
->UpdateLayers(queue_
.get());
1628 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1629 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1630 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1631 EXPECT_FALSE(queue_
->HasMoreUpdates());
1633 root
->fake_layer_updater()->ClearUpdateCount();
1634 child
->fake_layer_updater()->ClearUpdateCount();
1635 child2
->fake_layer_updater()->ClearUpdateCount();
1637 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1638 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1639 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1640 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1641 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1642 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1643 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1644 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1645 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1647 for (unsigned i
= 0; i
< 3; ++i
) {
1648 for (unsigned j
= 0; j
< 2; ++j
)
1649 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1650 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1651 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1654 layer_tree_host_
->CommitComplete();
1656 // With a memory limit that includes only half the root layer, no contents
1657 // will be allocated. If render surface memory wasn't accounted for, there is
1658 // enough space for one of the children layers, but they draw into a surface
1659 // that can't be allocated.
1660 root
->InvalidateContentRect(root_rect
);
1661 child
->InvalidateContentRect(child_rect
);
1662 child2
->InvalidateContentRect(child2_rect
);
1664 memory_limit
= (3 * 1) * (100 * 100) * 4;
1665 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1667 layer_tree_host_
->UpdateLayers(queue_
.get());
1670 EXPECT_EQ(0, root
->fake_layer_updater()->update_count());
1671 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1672 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1673 EXPECT_FALSE(queue_
->HasMoreUpdates());
1675 root
->fake_layer_updater()->ClearUpdateCount();
1676 child
->fake_layer_updater()->ClearUpdateCount();
1677 child2
->fake_layer_updater()->ClearUpdateCount();
1679 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1680 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1681 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1682 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1683 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1684 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1685 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1686 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1687 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1689 for (unsigned i
= 0; i
< 3; ++i
) {
1690 for (unsigned j
= 0; j
< 2; ++j
)
1691 EXPECT_FALSE(root_impl
->HasResourceIdForTileAt(i
, j
));
1692 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1693 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1696 layer_tree_host_
->CommitComplete();
1698 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1699 resource_provider_
.get());
1700 layer_tree_host_
->SetRootLayer(NULL
);
1703 class TrackingLayerPainter
: public LayerPainter
{
1705 static scoped_ptr
<TrackingLayerPainter
> Create() {
1706 return make_scoped_ptr(new TrackingLayerPainter());
1709 virtual void Paint(SkCanvas
* canvas
,
1710 const gfx::Rect
& content_rect
,
1711 gfx::RectF
* opaque
) OVERRIDE
{
1712 painted_rect_
= content_rect
;
1715 gfx::Rect
PaintedRect() const { return painted_rect_
; }
1716 void ResetPaintedRect() { painted_rect_
= gfx::Rect(); }
1719 gfx::Rect painted_rect_
;
1722 class UpdateTrackingTiledLayer
: public FakeTiledLayer
{
1724 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager
* manager
)
1725 : FakeTiledLayer(manager
) {
1726 scoped_ptr
<TrackingLayerPainter
> painter(TrackingLayerPainter::Create());
1727 tracking_layer_painter_
= painter
.get();
1729 BitmapContentLayerUpdater::Create(painter
.PassAs
<LayerPainter
>(),
1730 &stats_instrumentation_
,
1734 TrackingLayerPainter
* tracking_layer_painter() const {
1735 return tracking_layer_painter_
;
1739 virtual LayerUpdater
* Updater() const OVERRIDE
{
1740 return layer_updater_
.get();
1742 virtual ~UpdateTrackingTiledLayer() {}
1744 TrackingLayerPainter
* tracking_layer_painter_
;
1745 scoped_refptr
<BitmapContentLayerUpdater
> layer_updater_
;
1746 FakeRenderingStatsInstrumentation stats_instrumentation_
;
1749 TEST_F(TiledLayerTest
, NonIntegerContentsScaleIsNotDistortedDuringPaint
) {
1750 scoped_refptr
<UpdateTrackingTiledLayer
> layer
=
1751 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_
.get()));
1753 layer_tree_host_
->root_layer()->AddChild(layer
);
1755 gfx::Rect
layer_rect(0, 0, 30, 31);
1756 layer
->SetPosition(layer_rect
.origin());
1757 layer
->SetBounds(layer_rect
.size());
1758 layer
->UpdateContentsScale(1.5f
);
1760 gfx::Rect
content_rect(0, 0, 45, 47);
1761 EXPECT_EQ(content_rect
.size(), layer
->content_bounds());
1762 layer
->draw_properties().visible_content_rect
= content_rect
;
1763 layer
->draw_properties().drawable_content_rect
= content_rect
;
1765 layer
->SetTexturePriorities(priority_calculator_
);
1766 resource_manager_
->PrioritizeTextures();
1767 layer
->SavePaintProperties();
1769 // Update the whole tile.
1770 layer
->Update(queue_
.get(), NULL
);
1771 layer
->tracking_layer_painter()->ResetPaintedRect();
1773 EXPECT_RECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1776 // Invalidate the entire layer in content space. When painting, the rect given
1777 // to webkit should match the layer's bounds.
1778 layer
->InvalidateContentRect(content_rect
);
1779 layer
->Update(queue_
.get(), NULL
);
1781 EXPECT_RECT_EQ(layer_rect
, layer
->tracking_layer_painter()->PaintedRect());
1784 TEST_F(TiledLayerTest
,
1785 NonIntegerContentsScaleIsNotDistortedDuringInvalidation
) {
1786 scoped_refptr
<UpdateTrackingTiledLayer
> layer
=
1787 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_
.get()));
1789 layer_tree_host_
->root_layer()->AddChild(layer
);
1791 gfx::Rect
layer_rect(0, 0, 30, 31);
1792 layer
->SetPosition(layer_rect
.origin());
1793 layer
->SetBounds(layer_rect
.size());
1794 layer
->UpdateContentsScale(1.3f
);
1796 gfx::Rect
content_rect(layer
->content_bounds());
1797 layer
->draw_properties().visible_content_rect
= content_rect
;
1798 layer
->draw_properties().drawable_content_rect
= content_rect
;
1800 layer
->SetTexturePriorities(priority_calculator_
);
1801 resource_manager_
->PrioritizeTextures();
1802 layer
->SavePaintProperties();
1804 // Update the whole tile.
1805 layer
->Update(queue_
.get(), NULL
);
1806 layer
->tracking_layer_painter()->ResetPaintedRect();
1808 EXPECT_RECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1811 // Invalidate the entire layer in layer space. When painting, the rect given
1812 // to webkit should match the layer's bounds.
1813 layer
->SetNeedsDisplayRect(layer_rect
);
1814 layer
->Update(queue_
.get(), NULL
);
1816 EXPECT_RECT_EQ(layer_rect
, layer
->tracking_layer_painter()->PaintedRect());