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 Region
& 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(impl_task_runner
);
89 bool output_surface_created_
;
90 base::RunLoop run_loop_
;
93 class TiledLayerTest
: public testing::Test
{
97 output_surface_(FakeOutputSurface::Create3d()),
98 queue_(make_scoped_ptr(new ResourceUpdateQueue
)),
99 impl_thread_("ImplThread"),
100 fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D
),
102 settings_
.max_partial_texture_updates
= std::numeric_limits
<size_t>::max();
103 settings_
.layer_transforms_should_scale_layer_contents
= true;
106 virtual void SetUp() {
107 impl_thread_
.Start();
108 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
109 layer_tree_host_
= SynchronousOutputSurfaceLayerTreeHost::Create(
110 &fake_layer_tree_host_client_
,
111 shared_bitmap_manager_
.get(),
113 impl_thread_
.message_loop_proxy());
114 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(
125 output_surface_
.get(), shared_bitmap_manager_
.get(), 0, false, 1,
127 host_impl_
= make_scoped_ptr(
128 new FakeLayerTreeHostImpl(proxy_
, shared_bitmap_manager_
.get()));
131 virtual ~TiledLayerTest() {
132 ResourceManagerClearAllMemory(resource_manager_
.get(),
133 resource_provider_
.get());
135 DebugScopedSetImplThreadAndMainThreadBlocked
136 impl_thread_and_main_thread_blocked(proxy_
);
137 resource_provider_
.reset();
141 void ResourceManagerClearAllMemory(
142 PrioritizedResourceManager
* resource_manager
,
143 ResourceProvider
* resource_provider
) {
145 DebugScopedSetImplThreadAndMainThreadBlocked
146 impl_thread_and_main_thread_blocked(proxy_
);
147 resource_manager
->ClearAllMemory(resource_provider
);
148 resource_manager
->ReduceMemory(resource_provider
);
150 resource_manager
->UnlinkAndClearEvictedBackings();
153 void UpdateTextures() {
154 DebugScopedSetImplThreadAndMainThreadBlocked
155 impl_thread_and_main_thread_blocked(proxy_
);
157 scoped_ptr
<ResourceUpdateController
> update_controller
=
158 ResourceUpdateController::Create(NULL
,
159 proxy_
->ImplThreadTaskRunner(),
161 resource_provider_
.get());
162 update_controller
->Finalize();
163 queue_
= make_scoped_ptr(new ResourceUpdateQueue
);
166 void LayerPushPropertiesTo(FakeTiledLayer
* layer
,
167 FakeTiledLayerImpl
* layer_impl
) {
168 DebugScopedSetImplThreadAndMainThreadBlocked
169 impl_thread_and_main_thread_blocked(proxy_
);
170 layer
->PushPropertiesTo(layer_impl
);
171 layer
->ResetNumDependentsNeedPushProperties();
174 void LayerUpdate(FakeTiledLayer
* layer
, TestOcclusionTracker
* occluded
) {
175 DebugScopedSetMainThread
main_thread(proxy_
);
176 layer
->Update(queue_
.get(), occluded
);
179 void CalcDrawProps(RenderSurfaceLayerList
* render_surface_layer_list
) {
181 occlusion_
->SetRenderTarget(layer_tree_host_
->root_layer());
183 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting
inputs(
184 layer_tree_host_
->root_layer(),
185 layer_tree_host_
->device_viewport_size(),
186 render_surface_layer_list
);
187 inputs
.device_scale_factor
= layer_tree_host_
->device_scale_factor();
188 inputs
.max_texture_size
=
189 layer_tree_host_
->GetRendererCapabilities().max_texture_size
;
190 inputs
.can_adjust_raster_scales
= true;
191 LayerTreeHostCommon::CalculateDrawProperties(&inputs
);
194 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
195 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
) {
196 scoped_refptr
<FakeTiledLayer
> layer2
;
197 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
;
198 return UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
201 bool UpdateAndPush(const scoped_refptr
<FakeTiledLayer
>& layer1
,
202 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl1
,
203 const scoped_refptr
<FakeTiledLayer
>& layer2
,
204 const scoped_ptr
<FakeTiledLayerImpl
>& layer_impl2
) {
206 resource_manager_
->ClearPriorities();
208 layer1
->SetTexturePriorities(priority_calculator_
);
210 layer2
->SetTexturePriorities(priority_calculator_
);
211 resource_manager_
->PrioritizeTextures();
213 // Save paint properties
215 layer1
->SavePaintProperties();
217 layer2
->SavePaintProperties();
221 layer1
->Update(queue_
.get(), occlusion_
);
223 layer2
->Update(queue_
.get(), occlusion_
);
225 bool needs_update
= false;
227 needs_update
|= layer1
->NeedsIdlePaint();
229 needs_update
|= layer2
->NeedsIdlePaint();
231 // Update textures and push.
234 LayerPushPropertiesTo(layer1
.get(), layer_impl1
.get());
236 LayerPushPropertiesTo(layer2
.get(), layer_impl2
.get());
243 LayerTreeSettings settings_
;
244 FakeOutputSurfaceClient output_surface_client_
;
245 scoped_ptr
<OutputSurface
> output_surface_
;
246 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
247 scoped_ptr
<ResourceProvider
> resource_provider_
;
248 scoped_ptr
<ResourceUpdateQueue
> queue_
;
249 PriorityCalculator priority_calculator_
;
250 base::Thread impl_thread_
;
251 FakeLayerTreeHostClient fake_layer_tree_host_client_
;
252 scoped_ptr
<SynchronousOutputSurfaceLayerTreeHost
> layer_tree_host_
;
253 scoped_ptr
<FakeLayerTreeHostImpl
> host_impl_
;
254 scoped_ptr
<PrioritizedResourceManager
> resource_manager_
;
255 TestOcclusionTracker
* occlusion_
;
258 TEST_F(TiledLayerTest
, PushDirtyTiles
) {
259 scoped_refptr
<FakeTiledLayer
> layer
=
260 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
261 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
262 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
263 RenderSurfaceLayerList render_surface_layer_list
;
265 layer_tree_host_
->root_layer()->AddChild(layer
);
267 // The tile size is 100x100, so this invalidates and then paints two tiles.
268 layer
->SetBounds(gfx::Size(100, 200));
269 CalcDrawProps(&render_surface_layer_list
);
270 UpdateAndPush(layer
, layer_impl
);
272 // We should have both tiles on the impl side.
273 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
274 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
276 // Invalidates both tiles, but then only update one of them.
277 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
278 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
279 UpdateAndPush(layer
, layer_impl
);
281 // We should only have the first tile since the other tile was invalidated but
283 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
284 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
287 TEST_F(TiledLayerTest
, PushOccludedDirtyTiles
) {
288 scoped_refptr
<FakeTiledLayer
> layer
=
289 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
290 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
291 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
292 TestOcclusionTracker occluded
;
293 occlusion_
= &occluded
;
294 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
296 layer_tree_host_
->root_layer()->AddChild(layer
);
299 RenderSurfaceLayerList render_surface_layer_list
;
301 // The tile size is 100x100, so this invalidates and then paints two tiles.
302 layer
->SetBounds(gfx::Size(100, 200));
303 CalcDrawProps(&render_surface_layer_list
);
304 UpdateAndPush(layer
, layer_impl
);
306 // We should have both tiles on the impl side.
307 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
308 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
312 RenderSurfaceLayerList render_surface_layer_list
;
314 // Invalidates part of the top tile...
315 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
316 // ....but the area is occluded.
317 occluded
.SetOcclusion(gfx::Rect(0, 0, 50, 50));
318 CalcDrawProps(&render_surface_layer_list
);
319 UpdateAndPush(layer
, layer_impl
);
321 // We should still have both tiles, as part of the top tile is still
323 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
324 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
328 TEST_F(TiledLayerTest
, PushDeletedTiles
) {
329 scoped_refptr
<FakeTiledLayer
> layer
=
330 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
331 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
332 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
333 RenderSurfaceLayerList render_surface_layer_list
;
335 layer_tree_host_
->root_layer()->AddChild(layer
);
337 // The tile size is 100x100, so this invalidates and then paints two tiles.
338 layer
->SetBounds(gfx::Size(100, 200));
339 CalcDrawProps(&render_surface_layer_list
);
340 UpdateAndPush(layer
, layer_impl
);
342 // We should have both tiles on the impl side.
343 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
344 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
346 resource_manager_
->ClearPriorities();
347 ResourceManagerClearAllMemory(resource_manager_
.get(),
348 resource_provider_
.get());
349 resource_manager_
->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
351 // This should drop the tiles on the impl thread.
352 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
354 // We should now have no textures on the impl thread.
355 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
356 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
358 // This should recreate and update one of the deleted textures.
359 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
360 UpdateAndPush(layer
, layer_impl
);
362 // We should have one tiles on the impl side.
363 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
364 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
367 TEST_F(TiledLayerTest
, PushIdlePaintTiles
) {
368 scoped_refptr
<FakeTiledLayer
> layer
=
369 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
370 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
371 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
372 RenderSurfaceLayerList render_surface_layer_list
;
374 layer_tree_host_
->root_layer()->AddChild(layer
);
376 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the
377 // center. This paints 1 visible of the 25 invalid tiles.
378 layer
->SetBounds(gfx::Size(500, 500));
379 CalcDrawProps(&render_surface_layer_list
);
380 layer
->draw_properties().visible_content_rect
= gfx::Rect(200, 200, 100, 100);
381 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
382 // We should need idle-painting for surrounding tiles.
383 EXPECT_TRUE(needs_update
);
385 // We should have one tile on the impl side.
386 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(2, 2));
388 // For the next four updates, we should detect we still need idle painting.
389 for (int i
= 0; i
< 4; i
++) {
390 needs_update
= UpdateAndPush(layer
, layer_impl
);
391 EXPECT_TRUE(needs_update
);
394 // We should always finish painting eventually.
395 for (int i
= 0; i
< 20; i
++)
396 needs_update
= UpdateAndPush(layer
, layer_impl
);
398 // We should have pre-painted all of the surrounding tiles.
399 for (int i
= 0; i
< 5; i
++) {
400 for (int j
= 0; j
< 5; j
++)
401 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
404 EXPECT_FALSE(needs_update
);
407 TEST_F(TiledLayerTest
, PredictivePainting
) {
408 scoped_refptr
<FakeTiledLayer
> layer
=
409 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
410 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
411 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
413 layer_tree_host_
->root_layer()->AddChild(layer
);
415 // Prepainting should occur in the scroll direction first, and the
416 // visible rect should be extruded only along the dominant axis.
417 gfx::Vector2d directions
[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0),
418 gfx::Vector2d(0, -10), gfx::Vector2d(0, 10),
419 gfx::Vector2d(10, 20),
420 gfx::Vector2d(-20, 10) };
421 // We should push all tiles that touch the extruded visible rect.
422 gfx::Rect pushed_visible_tiles
[6] = {
423 gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2),
424 gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1)
426 // The first pre-paint should also paint first in the scroll
427 // direction so we should find one additional tile in the scroll direction.
428 gfx::Rect pushed_prepaint_tiles
[6] = {
429 gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3),
430 gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1)
432 for (int k
= 0; k
< 6; k
++) {
433 // The tile size is 100x100. Setup 5x5 tiles with one visible tile
435 gfx::Size bounds
= gfx::Size(500, 500);
436 gfx::Rect visible_rect
= gfx::Rect(200, 200, 100, 100);
437 gfx::Rect previous_visible_rect
=
438 gfx::Rect(visible_rect
.origin() + directions
[k
], visible_rect
.size());
439 gfx::Rect next_visible_rect
=
440 gfx::Rect(visible_rect
.origin() - directions
[k
], visible_rect
.size());
442 // Setup. Use the previous_visible_rect to setup the prediction for next
444 layer
->SetBounds(bounds
);
446 RenderSurfaceLayerList render_surface_layer_list
;
447 CalcDrawProps(&render_surface_layer_list
);
448 layer
->draw_properties().visible_content_rect
= previous_visible_rect
;
449 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
451 // Invalidate and move the visible_rect in the scroll direction.
452 // Check that the correct tiles have been painted in the visible pass.
453 layer
->SetNeedsDisplay();
454 layer
->draw_properties().visible_content_rect
= visible_rect
;
455 needs_update
= UpdateAndPush(layer
, layer_impl
);
456 for (int i
= 0; i
< 5; i
++) {
457 for (int j
= 0; j
< 5; j
++)
458 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
459 pushed_visible_tiles
[k
].Contains(i
, j
));
462 // Move the transform in the same direction without invalidating.
463 // Check that non-visible pre-painting occured in the correct direction.
464 // Ignore diagonal scrolls here (k > 3) as these have new visible content
467 layer
->draw_properties().visible_content_rect
= next_visible_rect
;
468 needs_update
= UpdateAndPush(layer
, layer_impl
);
469 for (int i
= 0; i
< 5; i
++) {
470 for (int j
= 0; j
< 5; j
++)
471 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
),
472 pushed_prepaint_tiles
[k
].Contains(i
, j
));
476 // We should always finish painting eventually.
477 for (int i
= 0; i
< 20; i
++)
478 needs_update
= UpdateAndPush(layer
, layer_impl
);
479 EXPECT_FALSE(needs_update
);
483 TEST_F(TiledLayerTest
, PushTilesAfterIdlePaintFailed
) {
484 // Start with 2mb of memory, but the test is going to try to use just more
485 // than 1mb, so we reduce to 1mb later.
486 resource_manager_
->SetMaxMemoryLimitBytes(2 * 1024 * 1024);
487 scoped_refptr
<FakeTiledLayer
> layer1
=
488 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
489 scoped_ptr
<FakeTiledLayerImpl
> layer_impl1
=
490 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
491 scoped_refptr
<FakeTiledLayer
> layer2
=
492 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
493 scoped_ptr
<FakeTiledLayerImpl
> layer_impl2
=
494 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
495 RenderSurfaceLayerList render_surface_layer_list
;
497 layer_tree_host_
->root_layer()->AddChild(layer1
);
498 layer_tree_host_
->root_layer()->AddChild(layer2
);
500 // For this test we have two layers. layer1 exhausts most texture memory,
501 // leaving room for 2 more tiles from layer2, but not all three tiles. First
502 // we paint layer1, and one tile from layer2. Then when we idle paint layer2,
503 // we will fail on the third tile of layer2, and this should not leave the
504 // second tile in a bad state.
506 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough
507 // for 2 tiles only in the other layer.
508 gfx::Rect
layer1_rect(0, 0, 100, 2400);
510 // This requires 4*30000 bytes of memory.
511 gfx::Rect
layer2_rect(0, 0, 100, 300);
513 // Paint a single tile in layer2 so that it will idle paint.
514 layer1
->SetBounds(layer1_rect
.size());
515 layer2
->SetBounds(layer2_rect
.size());
516 CalcDrawProps(&render_surface_layer_list
);
517 layer1
->draw_properties().visible_content_rect
= layer1_rect
;
518 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
519 bool needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
520 // We should need idle-painting for both remaining tiles in layer2.
521 EXPECT_TRUE(needs_update
);
523 // Reduce our memory limits to 1mb.
524 resource_manager_
->SetMaxMemoryLimitBytes(1024 * 1024);
526 // Now idle paint layer2. We are going to run out of memory though!
527 // Oh well, commit the frame and push.
528 for (int i
= 0; i
< 4; i
++) {
529 needs_update
= UpdateAndPush(layer1
, layer_impl1
, layer2
, layer_impl2
);
532 // Sanity check, we should have textures for the big layer.
533 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 0));
534 EXPECT_TRUE(layer_impl1
->HasResourceIdForTileAt(0, 23));
536 // We should only have the first two tiles from layer2 since
537 // it failed to idle update the last tile.
538 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
539 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 0));
540 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
541 EXPECT_TRUE(layer_impl2
->HasResourceIdForTileAt(0, 1));
543 EXPECT_FALSE(needs_update
);
544 EXPECT_FALSE(layer_impl2
->HasResourceIdForTileAt(0, 2));
547 TEST_F(TiledLayerTest
, PushIdlePaintedOccludedTiles
) {
548 scoped_refptr
<FakeTiledLayer
> layer
=
549 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
550 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
551 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
552 RenderSurfaceLayerList render_surface_layer_list
;
553 TestOcclusionTracker occluded
;
554 occlusion_
= &occluded
;
556 layer_tree_host_
->root_layer()->AddChild(layer
);
558 // The tile size is 100x100, so this invalidates one occluded tile, culls it
559 // during paint, but prepaints it.
560 occluded
.SetOcclusion(gfx::Rect(0, 0, 100, 100));
562 layer
->SetBounds(gfx::Size(100, 100));
563 CalcDrawProps(&render_surface_layer_list
);
564 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
565 UpdateAndPush(layer
, layer_impl
);
567 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
570 TEST_F(TiledLayerTest
, PushTilesMarkedDirtyDuringPaint
) {
571 scoped_refptr
<FakeTiledLayer
> layer
=
572 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
573 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
574 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
575 RenderSurfaceLayerList render_surface_layer_list
;
577 layer_tree_host_
->root_layer()->AddChild(layer
);
579 // The tile size is 100x100, so this invalidates and then paints two tiles.
580 // However, during the paint, we invalidate one of the tiles. This should
581 // not prevent the tile from being pushed.
582 layer
->fake_layer_updater()->SetRectToInvalidate(
583 gfx::Rect(0, 50, 100, 50), layer
.get());
584 layer
->SetBounds(gfx::Size(100, 200));
585 CalcDrawProps(&render_surface_layer_list
);
586 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
587 UpdateAndPush(layer
, layer_impl
);
589 // We should have both tiles on the impl side.
590 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
591 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
594 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer
) {
595 scoped_refptr
<FakeTiledLayer
> layer1
=
596 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
597 scoped_refptr
<FakeTiledLayer
> layer2
=
598 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
599 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
600 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
601 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
602 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
603 RenderSurfaceLayerList render_surface_layer_list
;
605 layer_tree_host_
->root_layer()->AddChild(layer1
);
606 layer_tree_host_
->root_layer()->AddChild(layer2
);
608 // Invalidate a tile on layer1, during update of layer 2.
609 layer2
->fake_layer_updater()->SetRectToInvalidate(
610 gfx::Rect(0, 50, 100, 50), layer1
.get());
611 layer1
->SetBounds(gfx::Size(100, 200));
612 layer2
->SetBounds(gfx::Size(100, 200));
613 CalcDrawProps(&render_surface_layer_list
);
614 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
615 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
616 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
618 // We should have both tiles on the impl side for all layers.
619 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
620 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
621 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
622 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
625 TEST_F(TiledLayerTest
, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer
) {
626 scoped_refptr
<FakeTiledLayer
> layer1
=
627 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
628 scoped_refptr
<FakeTiledLayer
> layer2
=
629 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
630 scoped_ptr
<FakeTiledLayerImpl
> layer1_impl
=
631 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
632 scoped_ptr
<FakeTiledLayerImpl
> layer2_impl
=
633 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 2));
634 RenderSurfaceLayerList render_surface_layer_list
;
636 layer_tree_host_
->root_layer()->AddChild(layer1
);
637 layer_tree_host_
->root_layer()->AddChild(layer2
);
639 layer1
->fake_layer_updater()->SetRectToInvalidate(
640 gfx::Rect(0, 50, 100, 50), layer2
.get());
641 layer1
->SetBounds(gfx::Size(100, 200));
642 layer2
->SetBounds(gfx::Size(100, 200));
643 CalcDrawProps(&render_surface_layer_list
);
644 layer1
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
645 layer2
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
646 UpdateAndPush(layer1
, layer1_impl
, layer2
, layer2_impl
);
648 // We should have both tiles on the impl side for all layers.
649 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 0));
650 EXPECT_TRUE(layer1_impl
->HasResourceIdForTileAt(0, 1));
651 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 0));
652 EXPECT_TRUE(layer2_impl
->HasResourceIdForTileAt(0, 1));
655 TEST_F(TiledLayerTest
, PaintSmallAnimatedLayersImmediately
) {
656 // Create a LayerTreeHost that has the right viewportsize,
657 // so the layer is considered small enough.
658 bool run_out_of_memory
[2] = { false, true };
659 for (int i
= 0; i
< 2; i
++) {
660 // Create a layer with 5x5 tiles, with 4x4 size viewport.
661 int viewport_width
= 4 * FakeTiledLayer::tile_size().width();
662 int viewport_height
= 4 * FakeTiledLayer::tile_size().width();
663 int layer_width
= 5 * FakeTiledLayer::tile_size().width();
664 int layer_height
= 5 * FakeTiledLayer::tile_size().height();
665 int memory_for_layer
= layer_width
* layer_height
* 4;
666 layer_tree_host_
->SetViewportSize(
667 gfx::Size(viewport_width
, viewport_height
));
669 // Use 10x5 tiles to run out of memory.
670 if (run_out_of_memory
[i
])
673 resource_manager_
->SetMaxMemoryLimitBytes(memory_for_layer
);
675 scoped_refptr
<FakeTiledLayer
> layer
=
676 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
677 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
678 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
679 RenderSurfaceLayerList render_surface_layer_list
;
681 layer_tree_host_
->root_layer()->AddChild(layer
);
683 // Full size layer with half being visible.
684 layer
->SetBounds(gfx::Size(layer_width
, layer_height
));
685 gfx::Rect
visible_rect(0, 0, layer_width
/ 2, layer_height
);
686 CalcDrawProps(&render_surface_layer_list
);
688 // Pretend the layer is animating.
689 layer
->draw_properties().target_space_transform_is_animating
= true;
690 layer
->draw_properties().visible_content_rect
= visible_rect
;
691 layer
->SetLayerTreeHost(layer_tree_host_
.get());
693 // The layer should paint its entire contents on the first paint
694 // if it is close to the viewport size and has the available memory.
695 layer
->SetTexturePriorities(priority_calculator_
);
696 resource_manager_
->PrioritizeTextures();
697 layer
->SavePaintProperties();
698 layer
->Update(queue_
.get(), NULL
);
700 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
702 // We should have all the tiles for the small animated layer.
703 // We should still have the visible tiles when we didn't
704 // have enough memory for all the tiles.
705 if (!run_out_of_memory
[i
]) {
706 for (int i
= 0; i
< 5; ++i
) {
707 for (int j
= 0; j
< 5; ++j
)
708 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(i
, j
));
711 for (int i
= 0; i
< 10; ++i
) {
712 for (int j
= 0; j
< 5; ++j
)
713 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(i
, j
), i
< 5);
717 layer
->RemoveFromParent();
721 TEST_F(TiledLayerTest
, IdlePaintOutOfMemory
) {
722 scoped_refptr
<FakeTiledLayer
> layer
=
723 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
724 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
725 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
726 RenderSurfaceLayerList render_surface_layer_list
;
728 layer_tree_host_
->root_layer()->AddChild(layer
);
730 // We have enough memory for only the visible rect, so we will run out of
731 // memory in first idle paint.
732 int memory_limit
= 4 * 100 * 100; // 1 tiles, 4 bytes per pixel.
733 resource_manager_
->SetMaxMemoryLimitBytes(memory_limit
);
735 // The tile size is 100x100, so this invalidates and then paints two tiles.
736 bool needs_update
= false;
737 layer
->SetBounds(gfx::Size(300, 300));
738 CalcDrawProps(&render_surface_layer_list
);
739 layer
->draw_properties().visible_content_rect
= gfx::Rect(100, 100, 100, 100);
740 for (int i
= 0; i
< 2; i
++)
741 needs_update
= UpdateAndPush(layer
, layer_impl
);
743 // Idle-painting should see no more priority tiles for painting.
744 EXPECT_FALSE(needs_update
);
746 // We should have one tile on the impl side.
747 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
750 TEST_F(TiledLayerTest
, IdlePaintZeroSizedLayer
) {
751 scoped_refptr
<FakeTiledLayer
> layer
=
752 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
753 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
754 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
756 layer_tree_host_
->root_layer()->AddChild(layer
);
758 bool animating
[2] = { false, true };
759 for (int i
= 0; i
< 2; i
++) {
760 // Pretend the layer is animating.
761 layer
->draw_properties().target_space_transform_is_animating
= animating
[i
];
763 // The layer's bounds are empty.
764 // Empty layers don't paint or idle-paint.
765 layer
->SetBounds(gfx::Size());
767 RenderSurfaceLayerList render_surface_layer_list
;
768 CalcDrawProps(&render_surface_layer_list
);
769 layer
->draw_properties().visible_content_rect
= gfx::Rect();
770 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
772 // Empty layers don't have tiles.
773 EXPECT_EQ(0u, layer
->NumPaintedTiles());
775 // Empty layers don't need prepaint.
776 EXPECT_FALSE(needs_update
);
778 // Empty layers don't have tiles.
779 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
783 TEST_F(TiledLayerTest
, IdlePaintNonVisibleLayers
) {
784 scoped_refptr
<FakeTiledLayer
> layer
=
785 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
786 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
787 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
789 // Alternate between not visible and visible.
790 gfx::Rect
v(0, 0, 100, 100);
791 gfx::Rect
nv(0, 0, 0, 0);
792 gfx::Rect visible_rect
[10] = { nv
, nv
, v
, v
, nv
, nv
, v
, v
, nv
, nv
};
793 bool invalidate
[10] = { true, true, true, true, true, true, true, true, false,
796 // We should not have any tiles except for when the layer was visible
797 // or after the layer was visible and we didn't invalidate.
798 bool have_tile
[10] = { false, false, true, true, false, false, true, true,
801 layer_tree_host_
->root_layer()->AddChild(layer
);
803 for (int i
= 0; i
< 10; i
++) {
804 layer
->SetBounds(gfx::Size(100, 100));
806 RenderSurfaceLayerList render_surface_layer_list
;
807 CalcDrawProps(&render_surface_layer_list
);
808 layer
->draw_properties().visible_content_rect
= visible_rect
[i
];
811 layer
->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
812 bool needs_update
= UpdateAndPush(layer
, layer_impl
);
814 // We should never signal idle paint, as we painted the entire layer
815 // or the layer was not visible.
816 EXPECT_FALSE(needs_update
);
817 EXPECT_EQ(layer_impl
->HasResourceIdForTileAt(0, 0), have_tile
[i
]);
821 TEST_F(TiledLayerTest
, InvalidateFromPrepare
) {
822 scoped_refptr
<FakeTiledLayer
> layer
=
823 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
824 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
825 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
826 RenderSurfaceLayerList render_surface_layer_list
;
828 layer_tree_host_
->root_layer()->AddChild(layer
);
830 // The tile size is 100x100, so this invalidates and then paints two tiles.
831 layer
->SetBounds(gfx::Size(100, 200));
832 CalcDrawProps(&render_surface_layer_list
);
833 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 200);
834 UpdateAndPush(layer
, layer_impl
);
836 // We should have both tiles on the impl side.
837 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
838 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
840 layer
->fake_layer_updater()->ClearPrepareCount();
841 // Invoke update again. As the layer is valid update shouldn't be invoked on
843 UpdateAndPush(layer
, layer_impl
);
844 EXPECT_EQ(0, layer
->fake_layer_updater()->prepare_count());
846 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
848 layer
->fake_layer_updater()->SetRectToInvalidate(
849 gfx::Rect(25, 25, 50, 50), layer
.get());
850 layer
->fake_layer_updater()->ClearPrepareCount();
851 layer
->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
852 UpdateAndPush(layer
, layer_impl
);
853 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
854 layer
->fake_layer_updater()->ClearPrepareCount();
856 // The layer should still be invalid as update invoked invalidate.
857 UpdateAndPush(layer
, layer_impl
); // visible
858 EXPECT_EQ(1, layer
->fake_layer_updater()->prepare_count());
861 TEST_F(TiledLayerTest
, VerifyUpdateRectWhenContentBoundsAreScaled
) {
862 // The update rect (that indicates what was actually painted) should be in
863 // layer space, not the content space.
864 scoped_refptr
<FakeTiledLayerWithScaledBounds
> layer
= make_scoped_refptr(
865 new FakeTiledLayerWithScaledBounds(resource_manager_
.get()));
867 layer_tree_host_
->root_layer()->AddChild(layer
);
869 gfx::Rect
layer_bounds(0, 0, 300, 200);
870 gfx::Rect
content_bounds(0, 0, 200, 250);
872 layer
->SetBounds(layer_bounds
.size());
873 layer
->SetContentBounds(content_bounds
.size());
874 layer
->draw_properties().visible_content_rect
= content_bounds
;
876 // On first update, the update_rect includes all tiles, even beyond the
877 // boundaries of the layer.
878 // However, it should still be in layer space, not content space.
879 layer
->InvalidateContentRect(content_bounds
);
881 layer
->SetTexturePriorities(priority_calculator_
);
882 resource_manager_
->PrioritizeTextures();
883 layer
->SavePaintProperties();
884 layer
->Update(queue_
.get(), NULL
);
885 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 300, 300 * 0.8), layer
->update_rect());
888 // After the tiles are updated once, another invalidate only needs to update
889 // the bounds of the layer.
890 layer
->SetTexturePriorities(priority_calculator_
);
891 resource_manager_
->PrioritizeTextures();
892 layer
->InvalidateContentRect(content_bounds
);
893 layer
->SavePaintProperties();
894 layer
->Update(queue_
.get(), NULL
);
895 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds
), layer
->update_rect());
898 // Partial re-paint should also be represented by the update rect in layer
899 // space, not content space.
900 gfx::Rect
partial_damage(30, 100, 10, 10);
901 layer
->InvalidateContentRect(partial_damage
);
902 layer
->SetTexturePriorities(priority_calculator_
);
903 resource_manager_
->PrioritizeTextures();
904 layer
->SavePaintProperties();
905 layer
->Update(queue_
.get(), NULL
);
906 EXPECT_FLOAT_RECT_EQ(gfx::RectF(45, 80, 15, 8), layer
->update_rect());
909 TEST_F(TiledLayerTest
, VerifyInvalidationWhenContentsScaleChanges
) {
910 scoped_refptr
<FakeTiledLayer
> layer
=
911 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
912 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
913 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
914 RenderSurfaceLayerList render_surface_layer_list
;
916 layer_tree_host_
->root_layer()->AddChild(layer
);
918 // Create a layer with one tile.
919 layer
->SetBounds(gfx::Size(100, 100));
920 CalcDrawProps(&render_surface_layer_list
);
921 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 100, 100);
922 layer
->Update(queue_
.get(), NULL
);
924 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
925 layer
->last_needs_display_rect());
927 // Push the tiles to the impl side and check that there is exactly one.
928 layer
->SetTexturePriorities(priority_calculator_
);
929 resource_manager_
->PrioritizeTextures();
930 layer
->SavePaintProperties();
931 layer
->Update(queue_
.get(), NULL
);
933 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
934 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
935 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
936 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
937 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
939 layer
->SetNeedsDisplayRect(gfx::Rect());
940 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer
->last_needs_display_rect());
942 // Change the contents scale.
943 layer
->UpdateContentsScale(2.f
);
944 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 200, 200);
946 // The impl side should get 2x2 tiles now.
947 layer
->SetTexturePriorities(priority_calculator_
);
948 resource_manager_
->PrioritizeTextures();
949 layer
->SavePaintProperties();
950 layer
->Update(queue_
.get(), NULL
);
952 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
953 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 0));
954 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(0, 1));
955 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 0));
956 EXPECT_TRUE(layer_impl
->HasResourceIdForTileAt(1, 1));
958 // Verify that changing the contents scale caused invalidation, and
959 // that the layer-space rectangle requiring painting is not scaled.
960 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
961 layer
->last_needs_display_rect());
963 // Invalidate the entire layer again, but do not paint. All tiles should be
964 // gone now from the impl side.
965 layer
->SetNeedsDisplay();
966 layer
->SetTexturePriorities(priority_calculator_
);
967 resource_manager_
->PrioritizeTextures();
969 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
970 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 0));
971 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(0, 1));
972 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 0));
973 EXPECT_FALSE(layer_impl
->HasResourceIdForTileAt(1, 1));
976 TEST_F(TiledLayerTest
, SkipsDrawGetsReset
) {
977 // Create two 300 x 300 tiled layers.
978 gfx::Size
content_bounds(300, 300);
979 gfx::Rect
content_rect(content_bounds
);
981 // We have enough memory for only one of the two layers.
982 int memory_limit
= 4 * 300 * 300; // 4 bytes per pixel.
984 scoped_refptr
<FakeTiledLayer
> root_layer
= make_scoped_refptr(
985 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
986 scoped_refptr
<FakeTiledLayer
> child_layer
= make_scoped_refptr(
987 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
988 root_layer
->AddChild(child_layer
);
990 root_layer
->SetBounds(content_bounds
);
991 root_layer
->draw_properties().visible_content_rect
= content_rect
;
992 root_layer
->SetPosition(gfx::PointF(0, 0));
993 child_layer
->SetBounds(content_bounds
);
994 child_layer
->draw_properties().visible_content_rect
= content_rect
;
995 child_layer
->SetPosition(gfx::PointF(0, 0));
996 root_layer
->InvalidateContentRect(content_rect
);
997 child_layer
->InvalidateContentRect(content_rect
);
999 layer_tree_host_
->SetRootLayer(root_layer
);
1000 layer_tree_host_
->SetViewportSize(gfx::Size(300, 300));
1001 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1004 layer_tree_host_
->UpdateLayers(queue_
.get());
1006 // We'll skip the root layer.
1007 EXPECT_TRUE(root_layer
->SkipsDraw());
1008 EXPECT_FALSE(child_layer
->SkipsDraw());
1010 layer_tree_host_
->CommitComplete();
1012 // Remove the child layer.
1013 root_layer
->RemoveAllChildren();
1015 layer_tree_host_
->UpdateLayers(queue_
.get());
1016 EXPECT_FALSE(root_layer
->SkipsDraw());
1018 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1019 resource_provider_
.get());
1020 layer_tree_host_
->SetRootLayer(NULL
);
1023 TEST_F(TiledLayerTest
, ResizeToSmaller
) {
1024 scoped_refptr
<FakeTiledLayer
> layer
=
1025 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1027 layer_tree_host_
->root_layer()->AddChild(layer
);
1029 layer
->SetBounds(gfx::Size(700, 700));
1030 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1031 layer
->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
1033 layer
->SetTexturePriorities(priority_calculator_
);
1034 resource_manager_
->PrioritizeTextures();
1035 layer
->SavePaintProperties();
1036 layer
->Update(queue_
.get(), NULL
);
1038 layer
->SetBounds(gfx::Size(200, 200));
1039 layer
->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
1042 TEST_F(TiledLayerTest
, HugeLayerUpdateCrash
) {
1043 scoped_refptr
<FakeTiledLayer
> layer
=
1044 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1046 layer_tree_host_
->root_layer()->AddChild(layer
);
1049 layer
->SetBounds(gfx::Size(size
, size
));
1050 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 700, 700);
1051 layer
->InvalidateContentRect(gfx::Rect(0, 0, size
, size
));
1053 // Ensure no crash for bounds where size * size would overflow an int.
1054 layer
->SetTexturePriorities(priority_calculator_
);
1055 resource_manager_
->PrioritizeTextures();
1056 layer
->SavePaintProperties();
1057 layer
->Update(queue_
.get(), NULL
);
1060 class TiledLayerPartialUpdateTest
: public TiledLayerTest
{
1062 TiledLayerPartialUpdateTest() { settings_
.max_partial_texture_updates
= 4; }
1065 TEST_F(TiledLayerPartialUpdateTest
, PartialUpdates
) {
1066 // Create one 300 x 200 tiled layer with 3 x 2 tiles.
1067 gfx::Size
content_bounds(300, 200);
1068 gfx::Rect
content_rect(content_bounds
);
1070 scoped_refptr
<FakeTiledLayer
> layer
= make_scoped_refptr(
1071 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1072 layer
->SetBounds(content_bounds
);
1073 layer
->SetPosition(gfx::PointF(0, 0));
1074 layer
->draw_properties().visible_content_rect
= content_rect
;
1075 layer
->InvalidateContentRect(content_rect
);
1077 layer_tree_host_
->SetRootLayer(layer
);
1078 layer_tree_host_
->SetViewportSize(gfx::Size(300, 200));
1080 // Full update of all 6 tiles.
1081 layer_tree_host_
->UpdateLayers(queue_
.get());
1083 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1084 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1085 EXPECT_EQ(6u, queue_
->FullUploadSize());
1086 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1088 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1089 EXPECT_FALSE(queue_
->HasMoreUpdates());
1090 layer
->fake_layer_updater()->ClearUpdateCount();
1091 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1093 layer_tree_host_
->CommitComplete();
1095 // Full update of 3 tiles and partial update of 3 tiles.
1096 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
1097 layer_tree_host_
->UpdateLayers(queue_
.get());
1099 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1100 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1101 EXPECT_EQ(3u, queue_
->FullUploadSize());
1102 EXPECT_EQ(3u, queue_
->PartialUploadSize());
1104 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1105 EXPECT_FALSE(queue_
->HasMoreUpdates());
1106 layer
->fake_layer_updater()->ClearUpdateCount();
1107 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1109 layer_tree_host_
->CommitComplete();
1111 // Partial update of 6 tiles.
1112 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1114 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1115 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1116 layer_tree_host_
->UpdateLayers(queue_
.get());
1117 EXPECT_EQ(2u, queue_
->FullUploadSize());
1118 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1120 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1121 EXPECT_FALSE(queue_
->HasMoreUpdates());
1122 layer
->fake_layer_updater()->ClearUpdateCount();
1123 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1125 layer_tree_host_
->CommitComplete();
1127 // Checkerboard all tiles.
1128 layer
->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
1130 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1131 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1132 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1134 layer_tree_host_
->CommitComplete();
1136 // Partial update of 6 checkerboard tiles.
1137 layer
->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1139 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1140 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1141 layer_tree_host_
->UpdateLayers(queue_
.get());
1142 EXPECT_EQ(6u, queue_
->FullUploadSize());
1143 EXPECT_EQ(0u, queue_
->PartialUploadSize());
1145 EXPECT_EQ(6, layer
->fake_layer_updater()->update_count());
1146 EXPECT_FALSE(queue_
->HasMoreUpdates());
1147 layer
->fake_layer_updater()->ClearUpdateCount();
1148 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1150 layer_tree_host_
->CommitComplete();
1152 // Partial update of 4 tiles.
1153 layer
->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
1155 scoped_ptr
<FakeTiledLayerImpl
> layer_impl
=
1156 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_
->active_tree(), 1));
1157 layer_tree_host_
->UpdateLayers(queue_
.get());
1158 EXPECT_EQ(0u, queue_
->FullUploadSize());
1159 EXPECT_EQ(4u, queue_
->PartialUploadSize());
1161 EXPECT_EQ(4, layer
->fake_layer_updater()->update_count());
1162 EXPECT_FALSE(queue_
->HasMoreUpdates());
1163 layer
->fake_layer_updater()->ClearUpdateCount();
1164 LayerPushPropertiesTo(layer
.get(), layer_impl
.get());
1166 layer_tree_host_
->CommitComplete();
1168 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1169 resource_provider_
.get());
1170 layer_tree_host_
->SetRootLayer(NULL
);
1173 TEST_F(TiledLayerTest
, TilesPaintedWithoutOcclusion
) {
1174 scoped_refptr
<FakeTiledLayer
> layer
=
1175 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1176 RenderSurfaceLayerList render_surface_layer_list
;
1178 layer_tree_host_
->root_layer()->AddChild(layer
);
1180 // The tile size is 100x100, so this invalidates and then paints two tiles.
1181 layer
->SetBounds(gfx::Size(100, 200));
1182 CalcDrawProps(&render_surface_layer_list
);
1184 layer
->SetTexturePriorities(priority_calculator_
);
1185 resource_manager_
->PrioritizeTextures();
1186 layer
->SavePaintProperties();
1187 layer
->Update(queue_
.get(), NULL
);
1188 EXPECT_EQ(2, layer
->fake_layer_updater()->update_count());
1191 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusion
) {
1192 scoped_refptr
<FakeTiledLayer
> layer
=
1193 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1194 RenderSurfaceLayerList render_surface_layer_list
;
1195 TestOcclusionTracker occluded
;
1196 occlusion_
= &occluded
;
1198 layer_tree_host_
->root_layer()->AddChild(layer
);
1200 // The tile size is 100x100.
1202 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1203 layer
->SetBounds(gfx::Size(600, 600));
1204 CalcDrawProps(&render_surface_layer_list
);
1206 occluded
.SetOcclusion(gfx::Rect(200, 200, 300, 100));
1207 layer
->draw_properties().drawable_content_rect
=
1208 gfx::Rect(layer
->content_bounds());
1209 layer
->draw_properties().visible_content_rect
=
1210 gfx::Rect(layer
->content_bounds());
1211 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1213 layer
->SetTexturePriorities(priority_calculator_
);
1214 resource_manager_
->PrioritizeTextures();
1215 layer
->SavePaintProperties();
1216 layer
->Update(queue_
.get(), &occluded
);
1217 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1219 layer
->fake_layer_updater()->ClearUpdateCount();
1220 layer
->SetTexturePriorities(priority_calculator_
);
1221 resource_manager_
->PrioritizeTextures();
1223 occluded
.SetOcclusion(gfx::Rect(250, 200, 300, 100));
1224 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1225 layer
->SavePaintProperties();
1226 layer
->Update(queue_
.get(), &occluded
);
1227 EXPECT_EQ(36 - 2, layer
->fake_layer_updater()->update_count());
1229 layer
->fake_layer_updater()->ClearUpdateCount();
1230 layer
->SetTexturePriorities(priority_calculator_
);
1231 resource_manager_
->PrioritizeTextures();
1233 occluded
.SetOcclusion(gfx::Rect(250, 250, 300, 100));
1234 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1235 layer
->SavePaintProperties();
1236 layer
->Update(queue_
.get(), &occluded
);
1237 EXPECT_EQ(36, layer
->fake_layer_updater()->update_count());
1240 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndVisiblityConstraints
) {
1241 scoped_refptr
<FakeTiledLayer
> layer
=
1242 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1243 RenderSurfaceLayerList render_surface_layer_list
;
1244 TestOcclusionTracker occluded
;
1245 occlusion_
= &occluded
;
1247 layer_tree_host_
->root_layer()->AddChild(layer
);
1249 // The tile size is 100x100.
1251 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1252 layer
->SetBounds(gfx::Size(600, 600));
1253 CalcDrawProps(&render_surface_layer_list
);
1255 // The partially occluded tiles (by the 150 occlusion height) are visible
1256 // beyond the occlusion, so not culled.
1257 occluded
.SetOcclusion(gfx::Rect(200, 200, 300, 150));
1258 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 360);
1259 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 360);
1260 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1262 layer
->SetTexturePriorities(priority_calculator_
);
1263 resource_manager_
->PrioritizeTextures();
1264 layer
->SavePaintProperties();
1265 layer
->Update(queue_
.get(), &occluded
);
1266 EXPECT_EQ(24 - 3, layer
->fake_layer_updater()->update_count());
1268 layer
->fake_layer_updater()->ClearUpdateCount();
1270 // Now the visible region stops at the edge of the occlusion so the partly
1271 // visible tiles become fully occluded.
1272 occluded
.SetOcclusion(gfx::Rect(200, 200, 300, 150));
1273 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 350);
1274 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 350);
1275 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1276 layer
->SetTexturePriorities(priority_calculator_
);
1277 resource_manager_
->PrioritizeTextures();
1278 layer
->SavePaintProperties();
1279 layer
->Update(queue_
.get(), &occluded
);
1280 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1282 layer
->fake_layer_updater()->ClearUpdateCount();
1284 // Now the visible region is even smaller than the occlusion, it should have
1286 occluded
.SetOcclusion(gfx::Rect(200, 200, 300, 150));
1287 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 340);
1288 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 340);
1289 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1290 layer
->SetTexturePriorities(priority_calculator_
);
1291 resource_manager_
->PrioritizeTextures();
1292 layer
->SavePaintProperties();
1293 layer
->Update(queue_
.get(), &occluded
);
1294 EXPECT_EQ(24 - 6, layer
->fake_layer_updater()->update_count());
1297 TEST_F(TiledLayerTest
, TilesNotPaintedWithoutInvalidation
) {
1298 scoped_refptr
<FakeTiledLayer
> layer
=
1299 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1300 RenderSurfaceLayerList render_surface_layer_list
;
1301 TestOcclusionTracker occluded
;
1302 occlusion_
= &occluded
;
1304 layer_tree_host_
->root_layer()->AddChild(layer
);
1306 // The tile size is 100x100.
1308 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1309 layer
->SetBounds(gfx::Size(600, 600));
1310 CalcDrawProps(&render_surface_layer_list
);
1312 occluded
.SetOcclusion(gfx::Rect(200, 200, 300, 100));
1313 layer
->draw_properties().drawable_content_rect
= gfx::Rect(0, 0, 600, 600);
1314 layer
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 600, 600);
1315 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1316 layer
->SetTexturePriorities(priority_calculator_
);
1317 resource_manager_
->PrioritizeTextures();
1318 layer
->SavePaintProperties();
1319 layer
->Update(queue_
.get(), &occluded
);
1320 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1323 layer
->fake_layer_updater()->ClearUpdateCount();
1324 layer
->SetTexturePriorities(priority_calculator_
);
1325 resource_manager_
->PrioritizeTextures();
1326 layer
->SavePaintProperties();
1328 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
1330 layer
->Update(queue_
.get(), &occluded
);
1331 EXPECT_EQ(3, layer
->fake_layer_updater()->update_count());
1334 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndTransforms
) {
1335 scoped_refptr
<FakeTiledLayer
> layer
=
1336 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1337 RenderSurfaceLayerList render_surface_layer_list
;
1338 TestOcclusionTracker occluded
;
1339 occlusion_
= &occluded
;
1341 layer_tree_host_
->root_layer()->AddChild(layer
);
1343 // The tile size is 100x100.
1345 // This makes sure the painting works when the occluded region (in screen
1346 // space) is transformed differently than the layer.
1347 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1348 layer
->SetBounds(gfx::Size(600, 600));
1349 CalcDrawProps(&render_surface_layer_list
);
1350 gfx::Transform screen_transform
;
1351 screen_transform
.Scale(0.5, 0.5);
1352 layer
->draw_properties().screen_space_transform
= screen_transform
;
1353 layer
->draw_properties().target_space_transform
= screen_transform
;
1355 occluded
.SetOcclusion(gfx::Rect(100, 100, 150, 50));
1356 layer
->draw_properties().drawable_content_rect
=
1357 gfx::Rect(layer
->content_bounds());
1358 layer
->draw_properties().visible_content_rect
=
1359 gfx::Rect(layer
->content_bounds());
1360 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1361 layer
->SetTexturePriorities(priority_calculator_
);
1362 resource_manager_
->PrioritizeTextures();
1363 layer
->SavePaintProperties();
1364 layer
->Update(queue_
.get(), &occluded
);
1365 EXPECT_EQ(36 - 3, layer
->fake_layer_updater()->update_count());
1368 TEST_F(TiledLayerTest
, TilesPaintedWithOcclusionAndScaling
) {
1369 scoped_refptr
<FakeTiledLayer
> layer
=
1370 new FakeTiledLayer(resource_manager_
.get());
1371 RenderSurfaceLayerList render_surface_layer_list
;
1372 TestOcclusionTracker occluded
;
1373 occlusion_
= &occluded
;
1375 scoped_refptr
<FakeTiledLayer
> scale_layer
=
1376 new FakeTiledLayer(resource_manager_
.get());
1377 gfx::Transform scale_transform
;
1378 scale_transform
.Scale(2.0, 2.0);
1379 scale_layer
->SetTransform(scale_transform
);
1381 layer_tree_host_
->root_layer()->AddChild(scale_layer
);
1383 // The tile size is 100x100.
1385 // This makes sure the painting works when the content space is scaled to
1386 // a different layer space.
1387 layer_tree_host_
->SetViewportSize(gfx::Size(600, 600));
1388 layer
->SetBounds(gfx::Size(300, 300));
1389 scale_layer
->AddChild(layer
);
1390 CalcDrawProps(&render_surface_layer_list
);
1391 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_x());
1392 EXPECT_FLOAT_EQ(2.f
, layer
->contents_scale_y());
1393 EXPECT_EQ(gfx::Size(600, 600).ToString(),
1394 layer
->content_bounds().ToString());
1396 // No tiles are covered by the 300x50 occlusion.
1397 occluded
.SetOcclusion(gfx::Rect(200, 200, 300, 50));
1398 layer
->draw_properties().drawable_content_rect
=
1399 gfx::Rect(layer
->bounds());
1400 layer
->draw_properties().visible_content_rect
=
1401 gfx::Rect(layer
->content_bounds());
1402 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1403 layer
->SetTexturePriorities(priority_calculator_
);
1404 resource_manager_
->PrioritizeTextures();
1405 layer
->SavePaintProperties();
1406 layer
->Update(queue_
.get(), &occluded
);
1407 int visible_tiles1
= 6 * 6;
1408 EXPECT_EQ(visible_tiles1
, layer
->fake_layer_updater()->update_count());
1410 layer
->fake_layer_updater()->ClearUpdateCount();
1412 // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still.
1413 occluded
.SetOcclusion(gfx::Rect(200, 200, 300, 100));
1414 layer
->draw_properties().drawable_content_rect
=
1415 gfx::Rect(layer
->bounds());
1416 layer
->draw_properties().visible_content_rect
=
1417 gfx::Rect(layer
->content_bounds());
1418 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1419 layer
->SetTexturePriorities(priority_calculator_
);
1420 resource_manager_
->PrioritizeTextures();
1421 layer
->SavePaintProperties();
1422 layer
->Update(queue_
.get(), &occluded
);
1423 int visible_tiles2
= 6 * 6 - 3;
1424 EXPECT_EQ(visible_tiles2
, layer
->fake_layer_updater()->update_count());
1426 layer
->fake_layer_updater()->ClearUpdateCount();
1428 // This makes sure content scaling and transforms work together.
1429 // When the tiles are scaled down by half, they are 50x50 each in the
1431 gfx::Transform screen_transform
;
1432 screen_transform
.Scale(0.5, 0.5);
1433 layer
->draw_properties().screen_space_transform
= screen_transform
;
1434 layer
->draw_properties().target_space_transform
= screen_transform
;
1436 // An occlusion of 150x100 will cover 3*2 = 6 tiles.
1437 occluded
.SetOcclusion(gfx::Rect(100, 100, 150, 100));
1439 gfx::Rect
layer_bounds_rect(layer
->bounds());
1440 layer
->draw_properties().drawable_content_rect
=
1441 gfx::ScaleToEnclosingRect(layer_bounds_rect
, 0.5f
);
1442 layer
->draw_properties().visible_content_rect
=
1443 gfx::Rect(layer
->content_bounds());
1444 layer
->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1445 layer
->SetTexturePriorities(priority_calculator_
);
1446 resource_manager_
->PrioritizeTextures();
1447 layer
->SavePaintProperties();
1448 layer
->Update(queue_
.get(), &occluded
);
1449 int visible_tiles3
= 6 * 6 - 6;
1450 EXPECT_EQ(visible_tiles3
, layer
->fake_layer_updater()->update_count());
1453 TEST_F(TiledLayerTest
, VisibleContentOpaqueRegion
) {
1454 scoped_refptr
<FakeTiledLayer
> layer
=
1455 make_scoped_refptr(new FakeTiledLayer(resource_manager_
.get()));
1456 RenderSurfaceLayerList render_surface_layer_list
;
1457 TestOcclusionTracker occluded
;
1458 occlusion_
= &occluded
;
1459 layer_tree_host_
->SetViewportSize(gfx::Size(1000, 1000));
1461 layer_tree_host_
->root_layer()->AddChild(layer
);
1463 // The tile size is 100x100, so this invalidates and then paints two tiles in
1466 gfx::Rect opaque_paint_rect
;
1467 Region opaque_contents
;
1469 gfx::Rect content_bounds
= gfx::Rect(0, 0, 100, 200);
1470 gfx::Rect visible_bounds
= gfx::Rect(0, 0, 100, 150);
1472 layer
->SetBounds(content_bounds
.size());
1473 CalcDrawProps(&render_surface_layer_list
);
1474 layer
->draw_properties().drawable_content_rect
= visible_bounds
;
1475 layer
->draw_properties().visible_content_rect
= visible_bounds
;
1477 // If the layer doesn't paint opaque content, then the
1478 // VisibleContentOpaqueRegion should be empty.
1479 layer
->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1480 layer
->InvalidateContentRect(content_bounds
);
1481 layer
->SetTexturePriorities(priority_calculator_
);
1482 resource_manager_
->PrioritizeTextures();
1483 layer
->SavePaintProperties();
1484 layer
->Update(queue_
.get(), &occluded
);
1485 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1486 EXPECT_TRUE(opaque_contents
.IsEmpty());
1488 // VisibleContentOpaqueRegion should match the visible part of what is painted
1490 opaque_paint_rect
= gfx::Rect(10, 10, 90, 190);
1491 layer
->fake_layer_updater()->SetOpaquePaintRect(opaque_paint_rect
);
1492 layer
->InvalidateContentRect(content_bounds
);
1493 layer
->SetTexturePriorities(priority_calculator_
);
1494 resource_manager_
->PrioritizeTextures();
1495 layer
->SavePaintProperties();
1496 layer
->Update(queue_
.get(), &occluded
);
1498 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1499 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect
, visible_bounds
).ToString(),
1500 opaque_contents
.ToString());
1502 // If we paint again without invalidating, the same stuff should be opaque.
1503 layer
->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1504 layer
->SetTexturePriorities(priority_calculator_
);
1505 resource_manager_
->PrioritizeTextures();
1506 layer
->SavePaintProperties();
1507 layer
->Update(queue_
.get(), &occluded
);
1509 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1510 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect
, visible_bounds
).ToString(),
1511 opaque_contents
.ToString());
1513 // If we repaint a non-opaque part of the tile, then it shouldn't lose its
1514 // opaque-ness. And other tiles should not be affected.
1515 layer
->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1516 layer
->InvalidateContentRect(gfx::Rect(0, 0, 1, 1));
1517 layer
->SetTexturePriorities(priority_calculator_
);
1518 resource_manager_
->PrioritizeTextures();
1519 layer
->SavePaintProperties();
1520 layer
->Update(queue_
.get(), &occluded
);
1522 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1523 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect
, visible_bounds
).ToString(),
1524 opaque_contents
.ToString());
1526 // If we repaint an opaque part of the tile, then it should lose its
1527 // opaque-ness. But other tiles should still not be affected.
1528 layer
->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1529 layer
->InvalidateContentRect(gfx::Rect(10, 10, 1, 1));
1530 layer
->SetTexturePriorities(priority_calculator_
);
1531 resource_manager_
->PrioritizeTextures();
1532 layer
->SavePaintProperties();
1533 layer
->Update(queue_
.get(), &occluded
);
1535 opaque_contents
= layer
->VisibleContentOpaqueRegion();
1536 EXPECT_EQ(gfx::IntersectRects(gfx::Rect(10, 100, 90, 100),
1537 visible_bounds
).ToString(),
1538 opaque_contents
.ToString());
1541 TEST_F(TiledLayerTest
, DontAllocateContentsWhenTargetSurfaceCantBeAllocated
) {
1542 // Tile size is 100x100.
1543 gfx::Rect
root_rect(0, 0, 300, 200);
1544 gfx::Rect
child_rect(0, 0, 300, 100);
1545 gfx::Rect
child2_rect(0, 100, 300, 100);
1547 scoped_refptr
<FakeTiledLayer
> root
= make_scoped_refptr(
1548 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1549 scoped_refptr
<Layer
> surface
= Layer::Create();
1550 scoped_refptr
<FakeTiledLayer
> child
= make_scoped_refptr(
1551 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1552 scoped_refptr
<FakeTiledLayer
> child2
= make_scoped_refptr(
1553 new FakeTiledLayer(layer_tree_host_
->contents_texture_manager()));
1555 root
->SetBounds(root_rect
.size());
1556 root
->draw_properties().drawable_content_rect
= root_rect
;
1557 root
->draw_properties().visible_content_rect
= root_rect
;
1558 root
->AddChild(surface
);
1560 surface
->SetForceRenderSurface(true);
1561 surface
->SetOpacity(0.5);
1562 surface
->AddChild(child
);
1563 surface
->AddChild(child2
);
1565 child
->SetBounds(child_rect
.size());
1566 child
->SetPosition(child_rect
.origin());
1567 child
->draw_properties().visible_content_rect
= child_rect
;
1568 child
->draw_properties().drawable_content_rect
= root_rect
;
1570 child2
->SetBounds(child2_rect
.size());
1571 child2
->SetPosition(child2_rect
.origin());
1572 child2
->draw_properties().visible_content_rect
= child2_rect
;
1573 child2
->draw_properties().drawable_content_rect
= root_rect
;
1575 layer_tree_host_
->SetRootLayer(root
);
1576 layer_tree_host_
->SetViewportSize(root_rect
.size());
1578 // With a huge memory limit, all layers should update and push their textures.
1579 root
->InvalidateContentRect(root_rect
);
1580 child
->InvalidateContentRect(child_rect
);
1581 child2
->InvalidateContentRect(child2_rect
);
1582 layer_tree_host_
->UpdateLayers(queue_
.get());
1585 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1586 EXPECT_EQ(3, child
->fake_layer_updater()->update_count());
1587 EXPECT_EQ(3, child2
->fake_layer_updater()->update_count());
1588 EXPECT_FALSE(queue_
->HasMoreUpdates());
1590 root
->fake_layer_updater()->ClearUpdateCount();
1591 child
->fake_layer_updater()->ClearUpdateCount();
1592 child2
->fake_layer_updater()->ClearUpdateCount();
1594 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1595 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1596 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1597 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1598 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1599 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1600 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1601 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1602 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1604 for (unsigned i
= 0; i
< 3; ++i
) {
1605 for (unsigned j
= 0; j
< 2; ++j
)
1606 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1607 EXPECT_TRUE(child_impl
->HasResourceIdForTileAt(i
, 0));
1608 EXPECT_TRUE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1611 layer_tree_host_
->CommitComplete();
1613 // With a memory limit that includes only the root layer (3x2 tiles) and half
1614 // the surface that the child layers draw into, the child layers will not be
1615 // allocated. If the surface isn't accounted for, then one of the children
1616 // would fit within the memory limit.
1617 root
->InvalidateContentRect(root_rect
);
1618 child
->InvalidateContentRect(child_rect
);
1619 child2
->InvalidateContentRect(child2_rect
);
1621 size_t memory_limit
= (3 * 2 + 3 * 1) * (100 * 100) * 4;
1622 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1624 layer_tree_host_
->UpdateLayers(queue_
.get());
1627 EXPECT_EQ(6, root
->fake_layer_updater()->update_count());
1628 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1629 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1630 EXPECT_FALSE(queue_
->HasMoreUpdates());
1632 root
->fake_layer_updater()->ClearUpdateCount();
1633 child
->fake_layer_updater()->ClearUpdateCount();
1634 child2
->fake_layer_updater()->ClearUpdateCount();
1636 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1637 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1638 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1639 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1640 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1641 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1642 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1643 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1644 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1646 for (unsigned i
= 0; i
< 3; ++i
) {
1647 for (unsigned j
= 0; j
< 2; ++j
)
1648 EXPECT_TRUE(root_impl
->HasResourceIdForTileAt(i
, j
));
1649 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1650 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1653 layer_tree_host_
->CommitComplete();
1655 // With a memory limit that includes only half the root layer, no contents
1656 // will be allocated. If render surface memory wasn't accounted for, there is
1657 // enough space for one of the children layers, but they draw into a surface
1658 // that can't be allocated.
1659 root
->InvalidateContentRect(root_rect
);
1660 child
->InvalidateContentRect(child_rect
);
1661 child2
->InvalidateContentRect(child2_rect
);
1663 memory_limit
= (3 * 1) * (100 * 100) * 4;
1664 layer_tree_host_
->contents_texture_manager()->SetMaxMemoryLimitBytes(
1666 layer_tree_host_
->UpdateLayers(queue_
.get());
1669 EXPECT_EQ(0, root
->fake_layer_updater()->update_count());
1670 EXPECT_EQ(0, child
->fake_layer_updater()->update_count());
1671 EXPECT_EQ(0, child2
->fake_layer_updater()->update_count());
1672 EXPECT_FALSE(queue_
->HasMoreUpdates());
1674 root
->fake_layer_updater()->ClearUpdateCount();
1675 child
->fake_layer_updater()->ClearUpdateCount();
1676 child2
->fake_layer_updater()->ClearUpdateCount();
1678 scoped_ptr
<FakeTiledLayerImpl
> root_impl
= make_scoped_ptr(
1679 new FakeTiledLayerImpl(host_impl_
->active_tree(), root
->id()));
1680 scoped_ptr
<FakeTiledLayerImpl
> child_impl
= make_scoped_ptr(
1681 new FakeTiledLayerImpl(host_impl_
->active_tree(), child
->id()));
1682 scoped_ptr
<FakeTiledLayerImpl
> child2_impl
= make_scoped_ptr(
1683 new FakeTiledLayerImpl(host_impl_
->active_tree(), child2
->id()));
1684 LayerPushPropertiesTo(child2
.get(), child2_impl
.get());
1685 LayerPushPropertiesTo(child
.get(), child_impl
.get());
1686 LayerPushPropertiesTo(root
.get(), root_impl
.get());
1688 for (unsigned i
= 0; i
< 3; ++i
) {
1689 for (unsigned j
= 0; j
< 2; ++j
)
1690 EXPECT_FALSE(root_impl
->HasResourceIdForTileAt(i
, j
));
1691 EXPECT_FALSE(child_impl
->HasResourceIdForTileAt(i
, 0));
1692 EXPECT_FALSE(child2_impl
->HasResourceIdForTileAt(i
, 0));
1695 layer_tree_host_
->CommitComplete();
1697 ResourceManagerClearAllMemory(layer_tree_host_
->contents_texture_manager(),
1698 resource_provider_
.get());
1699 layer_tree_host_
->SetRootLayer(NULL
);
1702 class TrackingLayerPainter
: public LayerPainter
{
1704 static scoped_ptr
<TrackingLayerPainter
> Create() {
1705 return make_scoped_ptr(new TrackingLayerPainter());
1708 virtual void Paint(SkCanvas
* canvas
,
1709 const gfx::Rect
& content_rect
,
1710 gfx::RectF
* opaque
) OVERRIDE
{
1711 painted_rect_
= content_rect
;
1714 gfx::Rect
PaintedRect() const { return painted_rect_
; }
1715 void ResetPaintedRect() { painted_rect_
= gfx::Rect(); }
1718 gfx::Rect painted_rect_
;
1721 class UpdateTrackingTiledLayer
: public FakeTiledLayer
{
1723 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager
* manager
)
1724 : FakeTiledLayer(manager
) {
1725 scoped_ptr
<TrackingLayerPainter
> painter(TrackingLayerPainter::Create());
1726 tracking_layer_painter_
= painter
.get();
1728 BitmapContentLayerUpdater::Create(painter
.PassAs
<LayerPainter
>(),
1729 &stats_instrumentation_
,
1733 TrackingLayerPainter
* tracking_layer_painter() const {
1734 return tracking_layer_painter_
;
1738 virtual LayerUpdater
* Updater() const OVERRIDE
{
1739 return layer_updater_
.get();
1741 virtual ~UpdateTrackingTiledLayer() {}
1743 TrackingLayerPainter
* tracking_layer_painter_
;
1744 scoped_refptr
<BitmapContentLayerUpdater
> layer_updater_
;
1745 FakeRenderingStatsInstrumentation stats_instrumentation_
;
1748 TEST_F(TiledLayerTest
, NonIntegerContentsScaleIsNotDistortedDuringPaint
) {
1749 scoped_refptr
<UpdateTrackingTiledLayer
> layer
=
1750 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_
.get()));
1752 layer_tree_host_
->root_layer()->AddChild(layer
);
1754 gfx::Rect
layer_rect(0, 0, 30, 31);
1755 layer
->SetPosition(layer_rect
.origin());
1756 layer
->SetBounds(layer_rect
.size());
1757 layer
->UpdateContentsScale(1.5f
);
1759 gfx::Rect
content_rect(0, 0, 45, 47);
1760 EXPECT_EQ(content_rect
.size(), layer
->content_bounds());
1761 layer
->draw_properties().visible_content_rect
= content_rect
;
1762 layer
->draw_properties().drawable_content_rect
= content_rect
;
1764 layer
->SetTexturePriorities(priority_calculator_
);
1765 resource_manager_
->PrioritizeTextures();
1766 layer
->SavePaintProperties();
1768 // Update the whole tile.
1769 layer
->Update(queue_
.get(), NULL
);
1770 layer
->tracking_layer_painter()->ResetPaintedRect();
1772 EXPECT_RECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1775 // Invalidate the entire layer in content space. When painting, the rect given
1776 // to webkit should match the layer's bounds.
1777 layer
->InvalidateContentRect(content_rect
);
1778 layer
->Update(queue_
.get(), NULL
);
1780 EXPECT_RECT_EQ(layer_rect
, layer
->tracking_layer_painter()->PaintedRect());
1783 TEST_F(TiledLayerTest
,
1784 NonIntegerContentsScaleIsNotDistortedDuringInvalidation
) {
1785 scoped_refptr
<UpdateTrackingTiledLayer
> layer
=
1786 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_
.get()));
1788 layer_tree_host_
->root_layer()->AddChild(layer
);
1790 gfx::Rect
layer_rect(0, 0, 30, 31);
1791 layer
->SetPosition(layer_rect
.origin());
1792 layer
->SetBounds(layer_rect
.size());
1793 layer
->UpdateContentsScale(1.3f
);
1795 gfx::Rect
content_rect(layer
->content_bounds());
1796 layer
->draw_properties().visible_content_rect
= content_rect
;
1797 layer
->draw_properties().drawable_content_rect
= content_rect
;
1799 layer
->SetTexturePriorities(priority_calculator_
);
1800 resource_manager_
->PrioritizeTextures();
1801 layer
->SavePaintProperties();
1803 // Update the whole tile.
1804 layer
->Update(queue_
.get(), NULL
);
1805 layer
->tracking_layer_painter()->ResetPaintedRect();
1807 EXPECT_RECT_EQ(gfx::Rect(), layer
->tracking_layer_painter()->PaintedRect());
1810 // Invalidate the entire layer in layer space. When painting, the rect given
1811 // to webkit should match the layer's bounds.
1812 layer
->SetNeedsDisplayRect(layer_rect
);
1813 layer
->Update(queue_
.get(), NULL
);
1815 EXPECT_RECT_EQ(layer_rect
, layer
->tracking_layer_painter()->PaintedRect());