Pass gfx::Rect and gfx::RectF by const ref.
[chromium-blink-merge.git] / cc / layers / tiled_layer_unittest.cc
blobb700ebfe21684f9d3593dd4e51a2e61bcda29334
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/tiled_layer.h"
7 #include <limits>
8 #include <vector>
10 #include "cc/debug/overdraw_metrics.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/tiled_layer_test_common.h"
24 #include "cc/trees/single_thread_proxy.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "ui/gfx/rect_conversions.h"
27 #include "ui/gfx/transform.h"
29 namespace cc {
30 namespace {
32 class TestOcclusionTracker : public OcclusionTracker {
33 public:
34 TestOcclusionTracker() : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000), true) {
35 stack_.push_back(StackObject());
38 void SetRenderTarget(Layer* render_target) {
39 stack_.back().target = render_target;
42 void SetOcclusion(const Region& occlusion) {
43 stack_.back().occlusion_from_inside_target = occlusion;
47 class TiledLayerTest : public testing::Test {
48 public:
49 TiledLayerTest()
50 : proxy_(NULL),
51 output_surface_(FakeOutputSurface::Create3d()),
52 queue_(make_scoped_ptr(new ResourceUpdateQueue)),
53 impl_thread_("ImplThread"),
54 fake_layer_tree_host_client_(FakeLayerTreeHostClient::DIRECT_3D),
55 occlusion_(NULL) {
56 settings_.max_partial_texture_updates = std::numeric_limits<size_t>::max();
57 settings_.layer_transforms_should_scale_layer_contents = true;
60 virtual void SetUp() {
61 impl_thread_.Start();
62 layer_tree_host_ = LayerTreeHost::CreateThreaded(
63 &fake_layer_tree_host_client_,
64 NULL,
65 settings_,
66 impl_thread_.message_loop_proxy());
67 proxy_ = layer_tree_host_->proxy();
68 resource_manager_ = PrioritizedResourceManager::Create(proxy_);
69 layer_tree_host_->SetLayerTreeHostClientReady();
70 layer_tree_host_->InitializeOutputSurfaceIfNeeded();
71 layer_tree_host_->SetRootLayer(Layer::Create());
73 CHECK(output_surface_->BindToClient(&output_surface_client_));
75 DebugScopedSetImplThreadAndMainThreadBlocked
76 impl_thread_and_main_thread_blocked(proxy_);
77 resource_provider_ =
78 ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
79 host_impl_ = make_scoped_ptr(new FakeLayerTreeHostImpl(proxy_));
82 virtual ~TiledLayerTest() {
83 ResourceManagerClearAllMemory(resource_manager_.get(),
84 resource_provider_.get());
86 DebugScopedSetImplThreadAndMainThreadBlocked
87 impl_thread_and_main_thread_blocked(proxy_);
88 resource_provider_.reset();
89 host_impl_.reset();
92 void ResourceManagerClearAllMemory(
93 PrioritizedResourceManager* resource_manager,
94 ResourceProvider* resource_provider) {
96 DebugScopedSetImplThreadAndMainThreadBlocked
97 impl_thread_and_main_thread_blocked(proxy_);
98 resource_manager->ClearAllMemory(resource_provider);
99 resource_manager->ReduceMemory(resource_provider);
101 resource_manager->UnlinkAndClearEvictedBackings();
104 void UpdateTextures() {
105 DebugScopedSetImplThreadAndMainThreadBlocked
106 impl_thread_and_main_thread_blocked(proxy_);
107 DCHECK(queue_);
108 scoped_ptr<ResourceUpdateController> update_controller =
109 ResourceUpdateController::Create(NULL,
110 proxy_->ImplThreadTaskRunner(),
111 queue_.Pass(),
112 resource_provider_.get());
113 update_controller->Finalize();
114 queue_ = make_scoped_ptr(new ResourceUpdateQueue);
117 void LayerPushPropertiesTo(FakeTiledLayer* layer,
118 FakeTiledLayerImpl* layer_impl) {
119 DebugScopedSetImplThreadAndMainThreadBlocked
120 impl_thread_and_main_thread_blocked(proxy_);
121 layer->PushPropertiesTo(layer_impl);
122 layer->ResetNumDependentsNeedPushProperties();
125 void LayerUpdate(FakeTiledLayer* layer, TestOcclusionTracker* occluded) {
126 DebugScopedSetMainThread main_thread(proxy_);
127 layer->Update(queue_.get(), occluded);
130 void CalcDrawProps(RenderSurfaceLayerList* render_surface_layer_list) {
131 if (occlusion_)
132 occlusion_->SetRenderTarget(layer_tree_host_->root_layer());
134 LayerTreeHostCommon::CalcDrawPropsMainInputsForTesting inputs(
135 layer_tree_host_->root_layer(),
136 layer_tree_host_->device_viewport_size(),
137 render_surface_layer_list);
138 inputs.device_scale_factor = layer_tree_host_->device_scale_factor();
139 inputs.max_texture_size =
140 layer_tree_host_->GetRendererCapabilities().max_texture_size;
141 inputs.can_adjust_raster_scales = true;
142 LayerTreeHostCommon::CalculateDrawProperties(&inputs);
145 bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1,
146 const scoped_ptr<FakeTiledLayerImpl>& layer_impl1) {
147 scoped_refptr<FakeTiledLayer> layer2;
148 scoped_ptr<FakeTiledLayerImpl> layer_impl2;
149 return UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
152 bool UpdateAndPush(const scoped_refptr<FakeTiledLayer>& layer1,
153 const scoped_ptr<FakeTiledLayerImpl>& layer_impl1,
154 const scoped_refptr<FakeTiledLayer>& layer2,
155 const scoped_ptr<FakeTiledLayerImpl>& layer_impl2) {
156 // Get textures
157 resource_manager_->ClearPriorities();
158 if (layer1.get())
159 layer1->SetTexturePriorities(priority_calculator_);
160 if (layer2.get())
161 layer2->SetTexturePriorities(priority_calculator_);
162 resource_manager_->PrioritizeTextures();
164 // Save paint properties
165 if (layer1.get())
166 layer1->SavePaintProperties();
167 if (layer2.get())
168 layer2->SavePaintProperties();
170 // Update content
171 if (layer1.get())
172 layer1->Update(queue_.get(), occlusion_);
173 if (layer2.get())
174 layer2->Update(queue_.get(), occlusion_);
176 bool needs_update = false;
177 if (layer1.get())
178 needs_update |= layer1->NeedsIdlePaint();
179 if (layer2.get())
180 needs_update |= layer2->NeedsIdlePaint();
182 // Update textures and push.
183 UpdateTextures();
184 if (layer1.get())
185 LayerPushPropertiesTo(layer1.get(), layer_impl1.get());
186 if (layer2.get())
187 LayerPushPropertiesTo(layer2.get(), layer_impl2.get());
189 return needs_update;
192 public:
193 Proxy* proxy_;
194 LayerTreeSettings settings_;
195 FakeOutputSurfaceClient output_surface_client_;
196 scoped_ptr<OutputSurface> output_surface_;
197 scoped_ptr<ResourceProvider> resource_provider_;
198 scoped_ptr<ResourceUpdateQueue> queue_;
199 PriorityCalculator priority_calculator_;
200 base::Thread impl_thread_;
201 FakeLayerTreeHostClient fake_layer_tree_host_client_;
202 scoped_ptr<LayerTreeHost> layer_tree_host_;
203 scoped_ptr<FakeLayerTreeHostImpl> host_impl_;
204 scoped_ptr<PrioritizedResourceManager> resource_manager_;
205 TestOcclusionTracker* occlusion_;
208 TEST_F(TiledLayerTest, PushDirtyTiles) {
209 scoped_refptr<FakeTiledLayer> layer =
210 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
211 scoped_ptr<FakeTiledLayerImpl> layer_impl =
212 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
213 RenderSurfaceLayerList render_surface_layer_list;
215 layer_tree_host_->root_layer()->AddChild(layer);
217 // The tile size is 100x100, so this invalidates and then paints two tiles.
218 layer->SetBounds(gfx::Size(100, 200));
219 CalcDrawProps(&render_surface_layer_list);
220 UpdateAndPush(layer, layer_impl);
222 // We should have both tiles on the impl side.
223 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
224 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
226 // Invalidates both tiles, but then only update one of them.
227 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
228 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
229 UpdateAndPush(layer, layer_impl);
231 // We should only have the first tile since the other tile was invalidated but
232 // not painted.
233 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
234 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
237 TEST_F(TiledLayerTest, PushOccludedDirtyTiles) {
238 scoped_refptr<FakeTiledLayer> layer =
239 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
240 scoped_ptr<FakeTiledLayerImpl> layer_impl =
241 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
242 TestOcclusionTracker occluded;
243 occlusion_ = &occluded;
244 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
246 layer_tree_host_->root_layer()->AddChild(layer);
249 RenderSurfaceLayerList render_surface_layer_list;
251 // The tile size is 100x100, so this invalidates and then paints two tiles.
252 layer->SetBounds(gfx::Size(100, 200));
253 CalcDrawProps(&render_surface_layer_list);
254 UpdateAndPush(layer, layer_impl);
256 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
257 EXPECT_NEAR(
258 occluded.overdraw_metrics()->pixels_uploaded_translucent(), 20000, 1);
259 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
261 // We should have both tiles on the impl side.
262 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
263 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
267 RenderSurfaceLayerList render_surface_layer_list;
269 // Invalidates part of the top tile...
270 layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
271 // ....but the area is occluded.
272 occluded.SetOcclusion(gfx::Rect(0, 0, 50, 50));
273 CalcDrawProps(&render_surface_layer_list);
274 UpdateAndPush(layer, layer_impl);
276 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
277 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
278 20000 + 2500,
280 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
282 // We should still have both tiles, as part of the top tile is still
283 // unoccluded.
284 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
285 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
289 TEST_F(TiledLayerTest, PushDeletedTiles) {
290 scoped_refptr<FakeTiledLayer> layer =
291 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
292 scoped_ptr<FakeTiledLayerImpl> layer_impl =
293 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
294 RenderSurfaceLayerList render_surface_layer_list;
296 layer_tree_host_->root_layer()->AddChild(layer);
298 // The tile size is 100x100, so this invalidates and then paints two tiles.
299 layer->SetBounds(gfx::Size(100, 200));
300 CalcDrawProps(&render_surface_layer_list);
301 UpdateAndPush(layer, layer_impl);
303 // We should have both tiles on the impl side.
304 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
305 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
307 resource_manager_->ClearPriorities();
308 ResourceManagerClearAllMemory(resource_manager_.get(),
309 resource_provider_.get());
310 resource_manager_->SetMaxMemoryLimitBytes(4 * 1024 * 1024);
312 // This should drop the tiles on the impl thread.
313 LayerPushPropertiesTo(layer.get(), layer_impl.get());
315 // We should now have no textures on the impl thread.
316 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
317 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
319 // This should recreate and update one of the deleted textures.
320 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
321 UpdateAndPush(layer, layer_impl);
323 // We should have one tiles on the impl side.
324 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
325 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
328 TEST_F(TiledLayerTest, PushIdlePaintTiles) {
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. Setup 5x5 tiles with one visible tile in the
338 // center. This paints 1 visible of the 25 invalid tiles.
339 layer->SetBounds(gfx::Size(500, 500));
340 CalcDrawProps(&render_surface_layer_list);
341 layer->draw_properties().visible_content_rect = gfx::Rect(200, 200, 100, 100);
342 bool needs_update = UpdateAndPush(layer, layer_impl);
343 // We should need idle-painting for surrounding tiles.
344 EXPECT_TRUE(needs_update);
346 // We should have one tile on the impl side.
347 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(2, 2));
349 // For the next four updates, we should detect we still need idle painting.
350 for (int i = 0; i < 4; i++) {
351 needs_update = UpdateAndPush(layer, layer_impl);
352 EXPECT_TRUE(needs_update);
355 // We should always finish painting eventually.
356 for (int i = 0; i < 20; i++)
357 needs_update = UpdateAndPush(layer, layer_impl);
359 // We should have pre-painted all of the surrounding tiles.
360 for (int i = 0; i < 5; i++) {
361 for (int j = 0; j < 5; j++)
362 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j));
365 EXPECT_FALSE(needs_update);
368 TEST_F(TiledLayerTest, PredictivePainting) {
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));
374 layer_tree_host_->root_layer()->AddChild(layer);
376 // Prepainting should occur in the scroll direction first, and the
377 // visible rect should be extruded only along the dominant axis.
378 gfx::Vector2d directions[6] = { gfx::Vector2d(-10, 0), gfx::Vector2d(10, 0),
379 gfx::Vector2d(0, -10), gfx::Vector2d(0, 10),
380 gfx::Vector2d(10, 20),
381 gfx::Vector2d(-20, 10) };
382 // We should push all tiles that touch the extruded visible rect.
383 gfx::Rect pushed_visible_tiles[6] = {
384 gfx::Rect(2, 2, 2, 1), gfx::Rect(1, 2, 2, 1), gfx::Rect(2, 2, 1, 2),
385 gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 1, 1, 2), gfx::Rect(2, 2, 2, 1)
387 // The first pre-paint should also paint first in the scroll
388 // direction so we should find one additional tile in the scroll direction.
389 gfx::Rect pushed_prepaint_tiles[6] = {
390 gfx::Rect(2, 2, 3, 1), gfx::Rect(0, 2, 3, 1), gfx::Rect(2, 2, 1, 3),
391 gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 0, 1, 3), gfx::Rect(2, 2, 3, 1)
393 for (int k = 0; k < 6; k++) {
394 // The tile size is 100x100. Setup 5x5 tiles with one visible tile
395 // in the center.
396 gfx::Size bounds = gfx::Size(500, 500);
397 gfx::Rect visible_rect = gfx::Rect(200, 200, 100, 100);
398 gfx::Rect previous_visible_rect =
399 gfx::Rect(visible_rect.origin() + directions[k], visible_rect.size());
400 gfx::Rect next_visible_rect =
401 gfx::Rect(visible_rect.origin() - directions[k], visible_rect.size());
403 // Setup. Use the previous_visible_rect to setup the prediction for next
404 // frame.
405 layer->SetBounds(bounds);
407 RenderSurfaceLayerList render_surface_layer_list;
408 CalcDrawProps(&render_surface_layer_list);
409 layer->draw_properties().visible_content_rect = previous_visible_rect;
410 bool needs_update = UpdateAndPush(layer, layer_impl);
412 // Invalidate and move the visible_rect in the scroll direction.
413 // Check that the correct tiles have been painted in the visible pass.
414 layer->SetNeedsDisplay();
415 layer->draw_properties().visible_content_rect = visible_rect;
416 needs_update = UpdateAndPush(layer, layer_impl);
417 for (int i = 0; i < 5; i++) {
418 for (int j = 0; j < 5; j++)
419 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j),
420 pushed_visible_tiles[k].Contains(i, j));
423 // Move the transform in the same direction without invalidating.
424 // Check that non-visible pre-painting occured in the correct direction.
425 // Ignore diagonal scrolls here (k > 3) as these have new visible content
426 // now.
427 if (k <= 3) {
428 layer->draw_properties().visible_content_rect = next_visible_rect;
429 needs_update = UpdateAndPush(layer, layer_impl);
430 for (int i = 0; i < 5; i++) {
431 for (int j = 0; j < 5; j++)
432 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j),
433 pushed_prepaint_tiles[k].Contains(i, j));
437 // We should always finish painting eventually.
438 for (int i = 0; i < 20; i++)
439 needs_update = UpdateAndPush(layer, layer_impl);
440 EXPECT_FALSE(needs_update);
444 TEST_F(TiledLayerTest, PushTilesAfterIdlePaintFailed) {
445 // Start with 2mb of memory, but the test is going to try to use just more
446 // than 1mb, so we reduce to 1mb later.
447 resource_manager_->SetMaxMemoryLimitBytes(2 * 1024 * 1024);
448 scoped_refptr<FakeTiledLayer> layer1 =
449 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
450 scoped_ptr<FakeTiledLayerImpl> layer_impl1 =
451 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
452 scoped_refptr<FakeTiledLayer> layer2 =
453 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
454 scoped_ptr<FakeTiledLayerImpl> layer_impl2 =
455 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
456 RenderSurfaceLayerList render_surface_layer_list;
458 layer_tree_host_->root_layer()->AddChild(layer1);
459 layer_tree_host_->root_layer()->AddChild(layer2);
461 // For this test we have two layers. layer1 exhausts most texture memory,
462 // leaving room for 2 more tiles from layer2, but not all three tiles. First
463 // we paint layer1, and one tile from layer2. Then when we idle paint layer2,
464 // we will fail on the third tile of layer2, and this should not leave the
465 // second tile in a bad state.
467 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enough
468 // for 2 tiles only in the other layer.
469 gfx::Rect layer1_rect(0, 0, 100, 2400);
471 // This requires 4*30000 bytes of memory.
472 gfx::Rect layer2_rect(0, 0, 100, 300);
474 // Paint a single tile in layer2 so that it will idle paint.
475 layer1->SetBounds(layer1_rect.size());
476 layer2->SetBounds(layer2_rect.size());
477 CalcDrawProps(&render_surface_layer_list);
478 layer1->draw_properties().visible_content_rect = layer1_rect;
479 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
480 bool needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
481 // We should need idle-painting for both remaining tiles in layer2.
482 EXPECT_TRUE(needs_update);
484 // Reduce our memory limits to 1mb.
485 resource_manager_->SetMaxMemoryLimitBytes(1024 * 1024);
487 // Now idle paint layer2. We are going to run out of memory though!
488 // Oh well, commit the frame and push.
489 for (int i = 0; i < 4; i++) {
490 needs_update = UpdateAndPush(layer1, layer_impl1, layer2, layer_impl2);
493 // Sanity check, we should have textures for the big layer.
494 EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 0));
495 EXPECT_TRUE(layer_impl1->HasResourceIdForTileAt(0, 23));
497 // We should only have the first two tiles from layer2 since
498 // it failed to idle update the last tile.
499 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0));
500 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 0));
501 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1));
502 EXPECT_TRUE(layer_impl2->HasResourceIdForTileAt(0, 1));
504 EXPECT_FALSE(needs_update);
505 EXPECT_FALSE(layer_impl2->HasResourceIdForTileAt(0, 2));
508 TEST_F(TiledLayerTest, PushIdlePaintedOccludedTiles) {
509 scoped_refptr<FakeTiledLayer> layer =
510 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
511 scoped_ptr<FakeTiledLayerImpl> layer_impl =
512 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
513 RenderSurfaceLayerList render_surface_layer_list;
514 TestOcclusionTracker occluded;
515 occlusion_ = &occluded;
517 layer_tree_host_->root_layer()->AddChild(layer);
519 // The tile size is 100x100, so this invalidates one occluded tile, culls it
520 // during paint, but prepaints it.
521 occluded.SetOcclusion(gfx::Rect(0, 0, 100, 100));
523 layer->SetBounds(gfx::Size(100, 100));
524 CalcDrawProps(&render_surface_layer_list);
525 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
526 UpdateAndPush(layer, layer_impl);
528 // We should have the prepainted tile on the impl side, but culled it during
529 // paint.
530 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
531 EXPECT_EQ(1, occluded.overdraw_metrics()->tiles_culled_for_upload());
534 TEST_F(TiledLayerTest, PushTilesMarkedDirtyDuringPaint) {
535 scoped_refptr<FakeTiledLayer> layer =
536 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
537 scoped_ptr<FakeTiledLayerImpl> layer_impl =
538 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
539 RenderSurfaceLayerList render_surface_layer_list;
541 layer_tree_host_->root_layer()->AddChild(layer);
543 // The tile size is 100x100, so this invalidates and then paints two tiles.
544 // However, during the paint, we invalidate one of the tiles. This should
545 // not prevent the tile from being pushed.
546 layer->fake_layer_updater()->SetRectToInvalidate(
547 gfx::Rect(0, 50, 100, 50), layer.get());
548 layer->SetBounds(gfx::Size(100, 200));
549 CalcDrawProps(&render_surface_layer_list);
550 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
551 UpdateAndPush(layer, layer_impl);
553 // We should have both tiles on the impl side.
554 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
555 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
558 TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnNextLayer) {
559 scoped_refptr<FakeTiledLayer> layer1 =
560 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
561 scoped_refptr<FakeTiledLayer> layer2 =
562 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
563 scoped_ptr<FakeTiledLayerImpl> layer1_impl =
564 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
565 scoped_ptr<FakeTiledLayerImpl> layer2_impl =
566 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
567 RenderSurfaceLayerList render_surface_layer_list;
569 layer_tree_host_->root_layer()->AddChild(layer1);
570 layer_tree_host_->root_layer()->AddChild(layer2);
572 // Invalidate a tile on layer1, during update of layer 2.
573 layer2->fake_layer_updater()->SetRectToInvalidate(
574 gfx::Rect(0, 50, 100, 50), layer1.get());
575 layer1->SetBounds(gfx::Size(100, 200));
576 layer2->SetBounds(gfx::Size(100, 200));
577 CalcDrawProps(&render_surface_layer_list);
578 layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
579 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
580 UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl);
582 // We should have both tiles on the impl side for all layers.
583 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0));
584 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1));
585 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0));
586 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1));
589 TEST_F(TiledLayerTest, PushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer) {
590 scoped_refptr<FakeTiledLayer> layer1 =
591 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
592 scoped_refptr<FakeTiledLayer> layer2 =
593 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
594 scoped_ptr<FakeTiledLayerImpl> layer1_impl =
595 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
596 scoped_ptr<FakeTiledLayerImpl> layer2_impl =
597 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 2));
598 RenderSurfaceLayerList render_surface_layer_list;
600 layer_tree_host_->root_layer()->AddChild(layer1);
601 layer_tree_host_->root_layer()->AddChild(layer2);
603 layer1->fake_layer_updater()->SetRectToInvalidate(
604 gfx::Rect(0, 50, 100, 50), layer2.get());
605 layer1->SetBounds(gfx::Size(100, 200));
606 layer2->SetBounds(gfx::Size(100, 200));
607 CalcDrawProps(&render_surface_layer_list);
608 layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
609 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
610 UpdateAndPush(layer1, layer1_impl, layer2, layer2_impl);
612 // We should have both tiles on the impl side for all layers.
613 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 0));
614 EXPECT_TRUE(layer1_impl->HasResourceIdForTileAt(0, 1));
615 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 0));
616 EXPECT_TRUE(layer2_impl->HasResourceIdForTileAt(0, 1));
619 TEST_F(TiledLayerTest, PaintSmallAnimatedLayersImmediately) {
620 // Create a LayerTreeHost that has the right viewportsize,
621 // so the layer is considered small enough.
622 bool run_out_of_memory[2] = { false, true };
623 for (int i = 0; i < 2; i++) {
624 // Create a layer with 5x5 tiles, with 4x4 size viewport.
625 int viewport_width = 4 * FakeTiledLayer::tile_size().width();
626 int viewport_height = 4 * FakeTiledLayer::tile_size().width();
627 int layer_width = 5 * FakeTiledLayer::tile_size().width();
628 int layer_height = 5 * FakeTiledLayer::tile_size().height();
629 int memory_for_layer = layer_width * layer_height * 4;
630 layer_tree_host_->SetViewportSize(
631 gfx::Size(viewport_width, viewport_height));
633 // Use 10x5 tiles to run out of memory.
634 if (run_out_of_memory[i])
635 layer_width *= 2;
637 resource_manager_->SetMaxMemoryLimitBytes(memory_for_layer);
639 scoped_refptr<FakeTiledLayer> layer =
640 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
641 scoped_ptr<FakeTiledLayerImpl> layer_impl =
642 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
643 RenderSurfaceLayerList render_surface_layer_list;
645 layer_tree_host_->root_layer()->AddChild(layer);
647 // Full size layer with half being visible.
648 layer->SetBounds(gfx::Size(layer_width, layer_height));
649 gfx::Rect visible_rect(0, 0, layer_width / 2, layer_height);
650 CalcDrawProps(&render_surface_layer_list);
652 // Pretend the layer is animating.
653 layer->draw_properties().target_space_transform_is_animating = true;
654 layer->draw_properties().visible_content_rect = visible_rect;
655 layer->SetLayerTreeHost(layer_tree_host_.get());
657 // The layer should paint its entire contents on the first paint
658 // if it is close to the viewport size and has the available memory.
659 layer->SetTexturePriorities(priority_calculator_);
660 resource_manager_->PrioritizeTextures();
661 layer->SavePaintProperties();
662 layer->Update(queue_.get(), NULL);
663 UpdateTextures();
664 LayerPushPropertiesTo(layer.get(), layer_impl.get());
666 // We should have all the tiles for the small animated layer.
667 // We should still have the visible tiles when we didn't
668 // have enough memory for all the tiles.
669 if (!run_out_of_memory[i]) {
670 for (int i = 0; i < 5; ++i) {
671 for (int j = 0; j < 5; ++j)
672 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(i, j));
674 } else {
675 for (int i = 0; i < 10; ++i) {
676 for (int j = 0; j < 5; ++j)
677 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(i, j), i < 5);
681 layer->RemoveFromParent();
685 TEST_F(TiledLayerTest, IdlePaintOutOfMemory) {
686 scoped_refptr<FakeTiledLayer> layer =
687 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
688 scoped_ptr<FakeTiledLayerImpl> layer_impl =
689 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
690 RenderSurfaceLayerList render_surface_layer_list;
692 layer_tree_host_->root_layer()->AddChild(layer);
694 // We have enough memory for only the visible rect, so we will run out of
695 // memory in first idle paint.
696 int memory_limit = 4 * 100 * 100; // 1 tiles, 4 bytes per pixel.
697 resource_manager_->SetMaxMemoryLimitBytes(memory_limit);
699 // The tile size is 100x100, so this invalidates and then paints two tiles.
700 bool needs_update = false;
701 layer->SetBounds(gfx::Size(300, 300));
702 CalcDrawProps(&render_surface_layer_list);
703 layer->draw_properties().visible_content_rect = gfx::Rect(100, 100, 100, 100);
704 for (int i = 0; i < 2; i++)
705 needs_update = UpdateAndPush(layer, layer_impl);
707 // Idle-painting should see no more priority tiles for painting.
708 EXPECT_FALSE(needs_update);
710 // We should have one tile on the impl side.
711 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1));
714 TEST_F(TiledLayerTest, IdlePaintZeroSizedLayer) {
715 scoped_refptr<FakeTiledLayer> layer =
716 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
717 scoped_ptr<FakeTiledLayerImpl> layer_impl =
718 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
720 layer_tree_host_->root_layer()->AddChild(layer);
722 bool animating[2] = { false, true };
723 for (int i = 0; i < 2; i++) {
724 // Pretend the layer is animating.
725 layer->draw_properties().target_space_transform_is_animating = animating[i];
727 // The layer's bounds are empty.
728 // Empty layers don't paint or idle-paint.
729 layer->SetBounds(gfx::Size());
731 RenderSurfaceLayerList render_surface_layer_list;
732 CalcDrawProps(&render_surface_layer_list);
733 layer->draw_properties().visible_content_rect = gfx::Rect();
734 bool needs_update = UpdateAndPush(layer, layer_impl);
736 // Empty layers don't have tiles.
737 EXPECT_EQ(0u, layer->NumPaintedTiles());
739 // Empty layers don't need prepaint.
740 EXPECT_FALSE(needs_update);
742 // Empty layers don't have tiles.
743 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 0));
747 TEST_F(TiledLayerTest, IdlePaintNonVisibleLayers) {
748 scoped_refptr<FakeTiledLayer> layer =
749 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
750 scoped_ptr<FakeTiledLayerImpl> layer_impl =
751 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
753 // Alternate between not visible and visible.
754 gfx::Rect v(0, 0, 100, 100);
755 gfx::Rect nv(0, 0, 0, 0);
756 gfx::Rect visible_rect[10] = { nv, nv, v, v, nv, nv, v, v, nv, nv };
757 bool invalidate[10] = { true, true, true, true, true, true, true, true, false,
758 false };
760 // We should not have any tiles except for when the layer was visible
761 // or after the layer was visible and we didn't invalidate.
762 bool have_tile[10] = { false, false, true, true, false, false, true, true,
763 true, true };
765 layer_tree_host_->root_layer()->AddChild(layer);
767 for (int i = 0; i < 10; i++) {
768 layer->SetBounds(gfx::Size(100, 100));
770 RenderSurfaceLayerList render_surface_layer_list;
771 CalcDrawProps(&render_surface_layer_list);
772 layer->draw_properties().visible_content_rect = visible_rect[i];
774 if (invalidate[i])
775 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
776 bool needs_update = UpdateAndPush(layer, layer_impl);
778 // We should never signal idle paint, as we painted the entire layer
779 // or the layer was not visible.
780 EXPECT_FALSE(needs_update);
781 EXPECT_EQ(layer_impl->HasResourceIdForTileAt(0, 0), have_tile[i]);
785 TEST_F(TiledLayerTest, InvalidateFromPrepare) {
786 scoped_refptr<FakeTiledLayer> layer =
787 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
788 scoped_ptr<FakeTiledLayerImpl> layer_impl =
789 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
790 RenderSurfaceLayerList render_surface_layer_list;
792 layer_tree_host_->root_layer()->AddChild(layer);
794 // The tile size is 100x100, so this invalidates and then paints two tiles.
795 layer->SetBounds(gfx::Size(100, 200));
796 CalcDrawProps(&render_surface_layer_list);
797 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
798 UpdateAndPush(layer, layer_impl);
800 // We should have both tiles on the impl side.
801 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
802 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
804 layer->fake_layer_updater()->ClearPrepareCount();
805 // Invoke update again. As the layer is valid update shouldn't be invoked on
806 // the LayerUpdater.
807 UpdateAndPush(layer, layer_impl);
808 EXPECT_EQ(0, layer->fake_layer_updater()->prepare_count());
810 // SetRectToInvalidate triggers InvalidateContentRect() being invoked from
811 // update.
812 layer->fake_layer_updater()->SetRectToInvalidate(
813 gfx::Rect(25, 25, 50, 50), layer.get());
814 layer->fake_layer_updater()->ClearPrepareCount();
815 layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
816 UpdateAndPush(layer, layer_impl);
817 EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count());
818 layer->fake_layer_updater()->ClearPrepareCount();
820 // The layer should still be invalid as update invoked invalidate.
821 UpdateAndPush(layer, layer_impl); // visible
822 EXPECT_EQ(1, layer->fake_layer_updater()->prepare_count());
825 TEST_F(TiledLayerTest, VerifyUpdateRectWhenContentBoundsAreScaled) {
826 // The update rect (that indicates what was actually painted) should be in
827 // layer space, not the content space.
828 scoped_refptr<FakeTiledLayerWithScaledBounds> layer = make_scoped_refptr(
829 new FakeTiledLayerWithScaledBounds(resource_manager_.get()));
831 layer_tree_host_->root_layer()->AddChild(layer);
833 gfx::Rect layer_bounds(0, 0, 300, 200);
834 gfx::Rect content_bounds(0, 0, 200, 250);
836 layer->SetBounds(layer_bounds.size());
837 layer->SetContentBounds(content_bounds.size());
838 layer->draw_properties().visible_content_rect = content_bounds;
840 // On first update, the update_rect includes all tiles, even beyond the
841 // boundaries of the layer.
842 // However, it should still be in layer space, not content space.
843 layer->InvalidateContentRect(content_bounds);
845 layer->SetTexturePriorities(priority_calculator_);
846 resource_manager_->PrioritizeTextures();
847 layer->SavePaintProperties();
848 layer->Update(queue_.get(), NULL);
849 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 300, 300 * 0.8), layer->update_rect());
850 UpdateTextures();
852 // After the tiles are updated once, another invalidate only needs to update
853 // the bounds of the layer.
854 layer->SetTexturePriorities(priority_calculator_);
855 resource_manager_->PrioritizeTextures();
856 layer->InvalidateContentRect(content_bounds);
857 layer->SavePaintProperties();
858 layer->Update(queue_.get(), NULL);
859 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layer_bounds), layer->update_rect());
860 UpdateTextures();
862 // Partial re-paint should also be represented by the update rect in layer
863 // space, not content space.
864 gfx::Rect partial_damage(30, 100, 10, 10);
865 layer->InvalidateContentRect(partial_damage);
866 layer->SetTexturePriorities(priority_calculator_);
867 resource_manager_->PrioritizeTextures();
868 layer->SavePaintProperties();
869 layer->Update(queue_.get(), NULL);
870 EXPECT_FLOAT_RECT_EQ(gfx::RectF(45, 80, 15, 8), layer->update_rect());
873 TEST_F(TiledLayerTest, VerifyInvalidationWhenContentsScaleChanges) {
874 scoped_refptr<FakeTiledLayer> layer =
875 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
876 scoped_ptr<FakeTiledLayerImpl> layer_impl =
877 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
878 RenderSurfaceLayerList render_surface_layer_list;
880 layer_tree_host_->root_layer()->AddChild(layer);
882 // Create a layer with one tile.
883 layer->SetBounds(gfx::Size(100, 100));
884 CalcDrawProps(&render_surface_layer_list);
885 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
886 layer->Update(queue_.get(), NULL);
887 UpdateTextures();
888 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
889 layer->last_needs_display_rect());
891 // Push the tiles to the impl side and check that there is exactly one.
892 layer->SetTexturePriorities(priority_calculator_);
893 resource_manager_->PrioritizeTextures();
894 layer->SavePaintProperties();
895 layer->Update(queue_.get(), NULL);
896 UpdateTextures();
897 LayerPushPropertiesTo(layer.get(), layer_impl.get());
898 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
899 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(0, 1));
900 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 0));
901 EXPECT_FALSE(layer_impl->HasResourceIdForTileAt(1, 1));
903 layer->SetNeedsDisplayRect(gfx::Rect());
904 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer->last_needs_display_rect());
906 // Change the contents scale.
907 layer->UpdateContentsScale(2.f);
908 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 200, 200);
910 // The impl side should get 2x2 tiles now.
911 layer->SetTexturePriorities(priority_calculator_);
912 resource_manager_->PrioritizeTextures();
913 layer->SavePaintProperties();
914 layer->Update(queue_.get(), NULL);
915 UpdateTextures();
916 LayerPushPropertiesTo(layer.get(), layer_impl.get());
917 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 0));
918 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(0, 1));
919 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 0));
920 EXPECT_TRUE(layer_impl->HasResourceIdForTileAt(1, 1));
922 // Verify that changing the contents scale caused invalidation, and
923 // that the layer-space rectangle requiring painting is not scaled.
924 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100),
925 layer->last_needs_display_rect());
927 // Invalidate the entire layer again, but do not paint. All tiles should be
928 // gone now from the impl side.
929 layer->SetNeedsDisplay();
930 layer->SetTexturePriorities(priority_calculator_);
931 resource_manager_->PrioritizeTextures();
933 LayerPushPropertiesTo(layer.get(), layer_impl.get());
934 EXPECT_FALSE(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));
940 TEST_F(TiledLayerTest, SkipsDrawGetsReset) {
941 // Create two 300 x 300 tiled layers.
942 gfx::Size content_bounds(300, 300);
943 gfx::Rect content_rect(content_bounds);
945 // We have enough memory for only one of the two layers.
946 int memory_limit = 4 * 300 * 300; // 4 bytes per pixel.
948 scoped_refptr<FakeTiledLayer> root_layer = make_scoped_refptr(
949 new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
950 scoped_refptr<FakeTiledLayer> child_layer = make_scoped_refptr(
951 new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
952 root_layer->AddChild(child_layer);
954 root_layer->SetBounds(content_bounds);
955 root_layer->draw_properties().visible_content_rect = content_rect;
956 root_layer->SetPosition(gfx::PointF(0, 0));
957 child_layer->SetBounds(content_bounds);
958 child_layer->draw_properties().visible_content_rect = content_rect;
959 child_layer->SetPosition(gfx::PointF(0, 0));
960 root_layer->InvalidateContentRect(content_rect);
961 child_layer->InvalidateContentRect(content_rect);
963 layer_tree_host_->SetRootLayer(root_layer);
964 layer_tree_host_->SetViewportSize(gfx::Size(300, 300));
965 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
966 memory_limit);
968 layer_tree_host_->UpdateLayers(queue_.get());
970 // We'll skip the root layer.
971 EXPECT_TRUE(root_layer->SkipsDraw());
972 EXPECT_FALSE(child_layer->SkipsDraw());
974 layer_tree_host_->CommitComplete();
976 // Remove the child layer.
977 root_layer->RemoveAllChildren();
979 layer_tree_host_->UpdateLayers(queue_.get());
980 EXPECT_FALSE(root_layer->SkipsDraw());
982 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
983 resource_provider_.get());
984 layer_tree_host_->SetRootLayer(NULL);
987 TEST_F(TiledLayerTest, ResizeToSmaller) {
988 scoped_refptr<FakeTiledLayer> layer =
989 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
991 layer_tree_host_->root_layer()->AddChild(layer);
993 layer->SetBounds(gfx::Size(700, 700));
994 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700);
995 layer->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
997 layer->SetTexturePriorities(priority_calculator_);
998 resource_manager_->PrioritizeTextures();
999 layer->SavePaintProperties();
1000 layer->Update(queue_.get(), NULL);
1002 layer->SetBounds(gfx::Size(200, 200));
1003 layer->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
1006 TEST_F(TiledLayerTest, HugeLayerUpdateCrash) {
1007 scoped_refptr<FakeTiledLayer> layer =
1008 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1010 layer_tree_host_->root_layer()->AddChild(layer);
1012 int size = 1 << 30;
1013 layer->SetBounds(gfx::Size(size, size));
1014 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700);
1015 layer->InvalidateContentRect(gfx::Rect(0, 0, size, size));
1017 // Ensure no crash for bounds where size * size would overflow an int.
1018 layer->SetTexturePriorities(priority_calculator_);
1019 resource_manager_->PrioritizeTextures();
1020 layer->SavePaintProperties();
1021 layer->Update(queue_.get(), NULL);
1024 class TiledLayerPartialUpdateTest : public TiledLayerTest {
1025 public:
1026 TiledLayerPartialUpdateTest() { settings_.max_partial_texture_updates = 4; }
1029 TEST_F(TiledLayerPartialUpdateTest, PartialUpdates) {
1030 // Create one 300 x 200 tiled layer with 3 x 2 tiles.
1031 gfx::Size content_bounds(300, 200);
1032 gfx::Rect content_rect(content_bounds);
1034 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(
1035 new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
1036 layer->SetBounds(content_bounds);
1037 layer->SetPosition(gfx::PointF(0, 0));
1038 layer->draw_properties().visible_content_rect = content_rect;
1039 layer->InvalidateContentRect(content_rect);
1041 layer_tree_host_->SetRootLayer(layer);
1042 layer_tree_host_->SetViewportSize(gfx::Size(300, 200));
1044 // Full update of all 6 tiles.
1045 layer_tree_host_->UpdateLayers(queue_.get());
1047 scoped_ptr<FakeTiledLayerImpl> layer_impl =
1048 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
1049 EXPECT_EQ(6u, queue_->FullUploadSize());
1050 EXPECT_EQ(0u, queue_->PartialUploadSize());
1051 UpdateTextures();
1052 EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
1053 EXPECT_FALSE(queue_->HasMoreUpdates());
1054 layer->fake_layer_updater()->ClearUpdateCount();
1055 LayerPushPropertiesTo(layer.get(), layer_impl.get());
1057 layer_tree_host_->CommitComplete();
1059 // Full update of 3 tiles and partial update of 3 tiles.
1060 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
1061 layer_tree_host_->UpdateLayers(queue_.get());
1063 scoped_ptr<FakeTiledLayerImpl> layer_impl =
1064 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
1065 EXPECT_EQ(3u, queue_->FullUploadSize());
1066 EXPECT_EQ(3u, queue_->PartialUploadSize());
1067 UpdateTextures();
1068 EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
1069 EXPECT_FALSE(queue_->HasMoreUpdates());
1070 layer->fake_layer_updater()->ClearUpdateCount();
1071 LayerPushPropertiesTo(layer.get(), layer_impl.get());
1073 layer_tree_host_->CommitComplete();
1075 // Partial update of 6 tiles.
1076 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1078 scoped_ptr<FakeTiledLayerImpl> layer_impl =
1079 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
1080 layer_tree_host_->UpdateLayers(queue_.get());
1081 EXPECT_EQ(2u, queue_->FullUploadSize());
1082 EXPECT_EQ(4u, queue_->PartialUploadSize());
1083 UpdateTextures();
1084 EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
1085 EXPECT_FALSE(queue_->HasMoreUpdates());
1086 layer->fake_layer_updater()->ClearUpdateCount();
1087 LayerPushPropertiesTo(layer.get(), layer_impl.get());
1089 layer_tree_host_->CommitComplete();
1091 // Checkerboard all tiles.
1092 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
1094 scoped_ptr<FakeTiledLayerImpl> layer_impl =
1095 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
1096 LayerPushPropertiesTo(layer.get(), layer_impl.get());
1098 layer_tree_host_->CommitComplete();
1100 // Partial update of 6 checkerboard tiles.
1101 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
1103 scoped_ptr<FakeTiledLayerImpl> layer_impl =
1104 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
1105 layer_tree_host_->UpdateLayers(queue_.get());
1106 EXPECT_EQ(6u, queue_->FullUploadSize());
1107 EXPECT_EQ(0u, queue_->PartialUploadSize());
1108 UpdateTextures();
1109 EXPECT_EQ(6, layer->fake_layer_updater()->update_count());
1110 EXPECT_FALSE(queue_->HasMoreUpdates());
1111 layer->fake_layer_updater()->ClearUpdateCount();
1112 LayerPushPropertiesTo(layer.get(), layer_impl.get());
1114 layer_tree_host_->CommitComplete();
1116 // Partial update of 4 tiles.
1117 layer->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
1119 scoped_ptr<FakeTiledLayerImpl> layer_impl =
1120 make_scoped_ptr(new FakeTiledLayerImpl(host_impl_->active_tree(), 1));
1121 layer_tree_host_->UpdateLayers(queue_.get());
1122 EXPECT_EQ(0u, queue_->FullUploadSize());
1123 EXPECT_EQ(4u, queue_->PartialUploadSize());
1124 UpdateTextures();
1125 EXPECT_EQ(4, layer->fake_layer_updater()->update_count());
1126 EXPECT_FALSE(queue_->HasMoreUpdates());
1127 layer->fake_layer_updater()->ClearUpdateCount();
1128 LayerPushPropertiesTo(layer.get(), layer_impl.get());
1130 layer_tree_host_->CommitComplete();
1132 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
1133 resource_provider_.get());
1134 layer_tree_host_->SetRootLayer(NULL);
1137 TEST_F(TiledLayerTest, TilesPaintedWithoutOcclusion) {
1138 scoped_refptr<FakeTiledLayer> layer =
1139 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1140 RenderSurfaceLayerList render_surface_layer_list;
1142 layer_tree_host_->root_layer()->AddChild(layer);
1144 // The tile size is 100x100, so this invalidates and then paints two tiles.
1145 layer->SetBounds(gfx::Size(100, 200));
1146 CalcDrawProps(&render_surface_layer_list);
1148 layer->SetTexturePriorities(priority_calculator_);
1149 resource_manager_->PrioritizeTextures();
1150 layer->SavePaintProperties();
1151 layer->Update(queue_.get(), NULL);
1152 EXPECT_EQ(2, layer->fake_layer_updater()->update_count());
1155 TEST_F(TiledLayerTest, TilesPaintedWithOcclusion) {
1156 scoped_refptr<FakeTiledLayer> layer =
1157 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1158 RenderSurfaceLayerList render_surface_layer_list;
1159 TestOcclusionTracker occluded;
1160 occlusion_ = &occluded;
1162 layer_tree_host_->root_layer()->AddChild(layer);
1164 // The tile size is 100x100.
1166 layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
1167 layer->SetBounds(gfx::Size(600, 600));
1168 CalcDrawProps(&render_surface_layer_list);
1170 occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100));
1171 layer->draw_properties().drawable_content_rect =
1172 gfx::Rect(layer->content_bounds());
1173 layer->draw_properties().visible_content_rect =
1174 gfx::Rect(layer->content_bounds());
1175 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1177 layer->SetTexturePriorities(priority_calculator_);
1178 resource_manager_->PrioritizeTextures();
1179 layer->SavePaintProperties();
1180 layer->Update(queue_.get(), &occluded);
1181 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
1183 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1184 EXPECT_NEAR(
1185 occluded.overdraw_metrics()->pixels_uploaded_translucent(), 330000, 1);
1186 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1188 layer->fake_layer_updater()->ClearUpdateCount();
1189 layer->SetTexturePriorities(priority_calculator_);
1190 resource_manager_->PrioritizeTextures();
1192 occluded.SetOcclusion(gfx::Rect(250, 200, 300, 100));
1193 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1194 layer->SavePaintProperties();
1195 layer->Update(queue_.get(), &occluded);
1196 EXPECT_EQ(36 - 2, layer->fake_layer_updater()->update_count());
1198 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1199 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1200 330000 + 340000,
1202 EXPECT_EQ(3 + 2, occluded.overdraw_metrics()->tiles_culled_for_upload());
1204 layer->fake_layer_updater()->ClearUpdateCount();
1205 layer->SetTexturePriorities(priority_calculator_);
1206 resource_manager_->PrioritizeTextures();
1208 occluded.SetOcclusion(gfx::Rect(250, 250, 300, 100));
1209 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1210 layer->SavePaintProperties();
1211 layer->Update(queue_.get(), &occluded);
1212 EXPECT_EQ(36, layer->fake_layer_updater()->update_count());
1214 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1215 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1216 330000 + 340000 + 360000,
1218 EXPECT_EQ(3 + 2, occluded.overdraw_metrics()->tiles_culled_for_upload());
1221 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndVisiblityConstraints) {
1222 scoped_refptr<FakeTiledLayer> layer =
1223 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1224 RenderSurfaceLayerList render_surface_layer_list;
1225 TestOcclusionTracker occluded;
1226 occlusion_ = &occluded;
1228 layer_tree_host_->root_layer()->AddChild(layer);
1230 // The tile size is 100x100.
1232 layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
1233 layer->SetBounds(gfx::Size(600, 600));
1234 CalcDrawProps(&render_surface_layer_list);
1236 // The partially occluded tiles (by the 150 occlusion height) are visible
1237 // beyond the occlusion, so not culled.
1238 occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150));
1239 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 360);
1240 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 360);
1241 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1243 layer->SetTexturePriorities(priority_calculator_);
1244 resource_manager_->PrioritizeTextures();
1245 layer->SavePaintProperties();
1246 layer->Update(queue_.get(), &occluded);
1247 EXPECT_EQ(24 - 3, layer->fake_layer_updater()->update_count());
1249 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1250 EXPECT_NEAR(
1251 occluded.overdraw_metrics()->pixels_uploaded_translucent(), 210000, 1);
1252 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1254 layer->fake_layer_updater()->ClearUpdateCount();
1256 // Now the visible region stops at the edge of the occlusion so the partly
1257 // visible tiles become fully occluded.
1258 occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150));
1259 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 350);
1260 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 350);
1261 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 - 6, layer->fake_layer_updater()->update_count());
1268 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1269 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1270 210000 + 180000,
1272 EXPECT_EQ(3 + 6, occluded.overdraw_metrics()->tiles_culled_for_upload());
1274 layer->fake_layer_updater()->ClearUpdateCount();
1276 // Now the visible region is even smaller than the occlusion, it should have
1277 // the same result.
1278 occluded.SetOcclusion(gfx::Rect(200, 200, 300, 150));
1279 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 340);
1280 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 340);
1281 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1282 layer->SetTexturePriorities(priority_calculator_);
1283 resource_manager_->PrioritizeTextures();
1284 layer->SavePaintProperties();
1285 layer->Update(queue_.get(), &occluded);
1286 EXPECT_EQ(24 - 6, layer->fake_layer_updater()->update_count());
1288 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1289 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1290 210000 + 180000 + 180000,
1292 EXPECT_EQ(3 + 6 + 6, occluded.overdraw_metrics()->tiles_culled_for_upload());
1295 TEST_F(TiledLayerTest, TilesNotPaintedWithoutInvalidation) {
1296 scoped_refptr<FakeTiledLayer> layer =
1297 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1298 RenderSurfaceLayerList render_surface_layer_list;
1299 TestOcclusionTracker occluded;
1300 occlusion_ = &occluded;
1302 layer_tree_host_->root_layer()->AddChild(layer);
1304 // The tile size is 100x100.
1306 layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
1307 layer->SetBounds(gfx::Size(600, 600));
1308 CalcDrawProps(&render_surface_layer_list);
1310 occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100));
1311 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 600);
1312 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 600);
1313 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1314 layer->SetTexturePriorities(priority_calculator_);
1315 resource_manager_->PrioritizeTextures();
1316 layer->SavePaintProperties();
1317 layer->Update(queue_.get(), &occluded);
1318 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
1319 { UpdateTextures(); }
1321 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1322 EXPECT_NEAR(
1323 occluded.overdraw_metrics()->pixels_uploaded_translucent(), 330000, 1);
1324 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1326 layer->fake_layer_updater()->ClearUpdateCount();
1327 layer->SetTexturePriorities(priority_calculator_);
1328 resource_manager_->PrioritizeTextures();
1329 layer->SavePaintProperties();
1331 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
1332 // now.
1333 layer->Update(queue_.get(), &occluded);
1334 EXPECT_EQ(3, layer->fake_layer_updater()->update_count());
1336 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1337 EXPECT_NEAR(
1338 occluded.overdraw_metrics()->pixels_uploaded_translucent(), 330000, 1);
1339 EXPECT_EQ(6, occluded.overdraw_metrics()->tiles_culled_for_upload());
1342 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndTransforms) {
1343 scoped_refptr<FakeTiledLayer> layer =
1344 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1345 RenderSurfaceLayerList render_surface_layer_list;
1346 TestOcclusionTracker occluded;
1347 occlusion_ = &occluded;
1349 layer_tree_host_->root_layer()->AddChild(layer);
1351 // The tile size is 100x100.
1353 // This makes sure the painting works when the occluded region (in screen
1354 // space) is transformed differently than the layer.
1355 layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
1356 layer->SetBounds(gfx::Size(600, 600));
1357 CalcDrawProps(&render_surface_layer_list);
1358 gfx::Transform screen_transform;
1359 screen_transform.Scale(0.5, 0.5);
1360 layer->draw_properties().screen_space_transform = screen_transform;
1361 layer->draw_properties().target_space_transform = screen_transform;
1363 occluded.SetOcclusion(gfx::Rect(100, 100, 150, 50));
1364 layer->draw_properties().drawable_content_rect =
1365 gfx::Rect(layer->content_bounds());
1366 layer->draw_properties().visible_content_rect =
1367 gfx::Rect(layer->content_bounds());
1368 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1369 layer->SetTexturePriorities(priority_calculator_);
1370 resource_manager_->PrioritizeTextures();
1371 layer->SavePaintProperties();
1372 layer->Update(queue_.get(), &occluded);
1373 EXPECT_EQ(36 - 3, layer->fake_layer_updater()->update_count());
1375 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1376 EXPECT_NEAR(
1377 occluded.overdraw_metrics()->pixels_uploaded_translucent(), 330000, 1);
1378 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1381 TEST_F(TiledLayerTest, TilesPaintedWithOcclusionAndScaling) {
1382 scoped_refptr<FakeTiledLayer> layer =
1383 new FakeTiledLayer(resource_manager_.get());
1384 RenderSurfaceLayerList render_surface_layer_list;
1385 TestOcclusionTracker occluded;
1386 occlusion_ = &occluded;
1388 scoped_refptr<FakeTiledLayer> scale_layer =
1389 new FakeTiledLayer(resource_manager_.get());
1390 gfx::Transform scale_transform;
1391 scale_transform.Scale(2.0, 2.0);
1392 scale_layer->SetTransform(scale_transform);
1394 layer_tree_host_->root_layer()->AddChild(scale_layer);
1396 // The tile size is 100x100.
1398 // This makes sure the painting works when the content space is scaled to
1399 // a different layer space.
1400 layer_tree_host_->SetViewportSize(gfx::Size(600, 600));
1401 layer->SetAnchorPoint(gfx::PointF());
1402 layer->SetBounds(gfx::Size(300, 300));
1403 scale_layer->AddChild(layer);
1404 CalcDrawProps(&render_surface_layer_list);
1405 EXPECT_FLOAT_EQ(2.f, layer->contents_scale_x());
1406 EXPECT_FLOAT_EQ(2.f, layer->contents_scale_y());
1407 EXPECT_EQ(gfx::Size(600, 600).ToString(),
1408 layer->content_bounds().ToString());
1410 // No tiles are covered by the 300x50 occlusion.
1411 occluded.SetOcclusion(gfx::Rect(200, 200, 300, 50));
1412 layer->draw_properties().drawable_content_rect =
1413 gfx::Rect(layer->bounds());
1414 layer->draw_properties().visible_content_rect =
1415 gfx::Rect(layer->content_bounds());
1416 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1417 layer->SetTexturePriorities(priority_calculator_);
1418 resource_manager_->PrioritizeTextures();
1419 layer->SavePaintProperties();
1420 layer->Update(queue_.get(), &occluded);
1421 int visible_tiles1 = 6 * 6;
1422 EXPECT_EQ(visible_tiles1, layer->fake_layer_updater()->update_count());
1424 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1425 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1426 visible_tiles1 * 100 * 100,
1428 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1430 layer->fake_layer_updater()->ClearUpdateCount();
1432 // The occlusion of 300x100 will be cover 3 tiles as tiles are 100x100 still.
1433 occluded.SetOcclusion(gfx::Rect(200, 200, 300, 100));
1434 layer->draw_properties().drawable_content_rect =
1435 gfx::Rect(layer->bounds());
1436 layer->draw_properties().visible_content_rect =
1437 gfx::Rect(layer->content_bounds());
1438 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1439 layer->SetTexturePriorities(priority_calculator_);
1440 resource_manager_->PrioritizeTextures();
1441 layer->SavePaintProperties();
1442 layer->Update(queue_.get(), &occluded);
1443 int visible_tiles2 = 6 * 6 - 3;
1444 EXPECT_EQ(visible_tiles2, layer->fake_layer_updater()->update_count());
1446 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1447 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1448 visible_tiles2 * 100 * 100 +
1449 visible_tiles1 * 100 * 100,
1451 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1453 layer->fake_layer_updater()->ClearUpdateCount();
1455 // This makes sure content scaling and transforms work together.
1456 // When the tiles are scaled down by half, they are 50x50 each in the
1457 // screen.
1458 gfx::Transform screen_transform;
1459 screen_transform.Scale(0.5, 0.5);
1460 layer->draw_properties().screen_space_transform = screen_transform;
1461 layer->draw_properties().target_space_transform = screen_transform;
1463 // An occlusion of 150x100 will cover 3*2 = 6 tiles.
1464 occluded.SetOcclusion(gfx::Rect(100, 100, 150, 100));
1466 gfx::Rect layer_bounds_rect(layer->bounds());
1467 layer->draw_properties().drawable_content_rect =
1468 gfx::ScaleToEnclosingRect(layer_bounds_rect, 0.5f);
1469 layer->draw_properties().visible_content_rect =
1470 gfx::Rect(layer->content_bounds());
1471 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1472 layer->SetTexturePriorities(priority_calculator_);
1473 resource_manager_->PrioritizeTextures();
1474 layer->SavePaintProperties();
1475 layer->Update(queue_.get(), &occluded);
1476 int visible_tiles3 = 6 * 6 - 6;
1477 EXPECT_EQ(visible_tiles3, layer->fake_layer_updater()->update_count());
1479 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1480 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1481 visible_tiles3 * 100 * 100 +
1482 visible_tiles2 * 100 * 100 +
1483 visible_tiles1 * 100 * 100,
1485 EXPECT_EQ(6 + 3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1488 TEST_F(TiledLayerTest, VisibleContentOpaqueRegion) {
1489 scoped_refptr<FakeTiledLayer> layer =
1490 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1491 RenderSurfaceLayerList render_surface_layer_list;
1492 TestOcclusionTracker occluded;
1493 occlusion_ = &occluded;
1494 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
1496 layer_tree_host_->root_layer()->AddChild(layer);
1498 // The tile size is 100x100, so this invalidates and then paints two tiles in
1499 // various ways.
1501 gfx::Rect opaque_paint_rect;
1502 Region opaque_contents;
1504 gfx::Rect content_bounds = gfx::Rect(0, 0, 100, 200);
1505 gfx::Rect visible_bounds = gfx::Rect(0, 0, 100, 150);
1507 layer->SetBounds(content_bounds.size());
1508 CalcDrawProps(&render_surface_layer_list);
1509 layer->draw_properties().drawable_content_rect = visible_bounds;
1510 layer->draw_properties().visible_content_rect = visible_bounds;
1512 // If the layer doesn't paint opaque content, then the
1513 // VisibleContentOpaqueRegion should be empty.
1514 layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1515 layer->InvalidateContentRect(content_bounds);
1516 layer->SetTexturePriorities(priority_calculator_);
1517 resource_manager_->PrioritizeTextures();
1518 layer->SavePaintProperties();
1519 layer->Update(queue_.get(), &occluded);
1520 opaque_contents = layer->VisibleContentOpaqueRegion();
1521 EXPECT_TRUE(opaque_contents.IsEmpty());
1523 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000, 1);
1524 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1525 EXPECT_NEAR(
1526 occluded.overdraw_metrics()->pixels_uploaded_translucent(), 20000, 1);
1527 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1529 // VisibleContentOpaqueRegion should match the visible part of what is painted
1530 // opaque.
1531 opaque_paint_rect = gfx::Rect(10, 10, 90, 190);
1532 layer->fake_layer_updater()->SetOpaquePaintRect(opaque_paint_rect);
1533 layer->InvalidateContentRect(content_bounds);
1534 layer->SetTexturePriorities(priority_calculator_);
1535 resource_manager_->PrioritizeTextures();
1536 layer->SavePaintProperties();
1537 layer->Update(queue_.get(), &occluded);
1538 UpdateTextures();
1539 opaque_contents = layer->VisibleContentOpaqueRegion();
1540 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
1541 opaque_contents.ToString());
1543 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000 * 2, 1);
1544 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 17100, 1);
1545 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1546 20000 + 20000 - 17100,
1548 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1550 // If we paint again without invalidating, the same stuff should be opaque.
1551 layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1552 layer->SetTexturePriorities(priority_calculator_);
1553 resource_manager_->PrioritizeTextures();
1554 layer->SavePaintProperties();
1555 layer->Update(queue_.get(), &occluded);
1556 UpdateTextures();
1557 opaque_contents = layer->VisibleContentOpaqueRegion();
1558 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
1559 opaque_contents.ToString());
1561 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000 * 2, 1);
1562 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 17100, 1);
1563 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1564 20000 + 20000 - 17100,
1566 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1568 // If we repaint a non-opaque part of the tile, then it shouldn't lose its
1569 // opaque-ness. And other tiles should not be affected.
1570 layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1571 layer->InvalidateContentRect(gfx::Rect(0, 0, 1, 1));
1572 layer->SetTexturePriorities(priority_calculator_);
1573 resource_manager_->PrioritizeTextures();
1574 layer->SavePaintProperties();
1575 layer->Update(queue_.get(), &occluded);
1576 UpdateTextures();
1577 opaque_contents = layer->VisibleContentOpaqueRegion();
1578 EXPECT_EQ(gfx::IntersectRects(opaque_paint_rect, visible_bounds).ToString(),
1579 opaque_contents.ToString());
1581 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000 * 2 + 1, 1);
1582 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 17100, 1);
1583 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1584 20000 + 20000 - 17100 + 1,
1586 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1588 // If we repaint an opaque part of the tile, then it should lose its
1589 // opaque-ness. But other tiles should still not be affected.
1590 layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1591 layer->InvalidateContentRect(gfx::Rect(10, 10, 1, 1));
1592 layer->SetTexturePriorities(priority_calculator_);
1593 resource_manager_->PrioritizeTextures();
1594 layer->SavePaintProperties();
1595 layer->Update(queue_.get(), &occluded);
1596 UpdateTextures();
1597 opaque_contents = layer->VisibleContentOpaqueRegion();
1598 EXPECT_EQ(gfx::IntersectRects(gfx::Rect(10, 100, 90, 100),
1599 visible_bounds).ToString(),
1600 opaque_contents.ToString());
1602 EXPECT_NEAR(
1603 occluded.overdraw_metrics()->pixels_painted(), 20000 * 2 + 1 + 1, 1);
1604 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 17100, 1);
1605 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1606 20000 + 20000 - 17100 + 1 + 1,
1608 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1611 TEST_F(TiledLayerTest, PixelsPaintedMetrics) {
1612 scoped_refptr<FakeTiledLayer> layer =
1613 make_scoped_refptr(new FakeTiledLayer(resource_manager_.get()));
1614 RenderSurfaceLayerList render_surface_layer_list;
1615 TestOcclusionTracker occluded;
1616 occlusion_ = &occluded;
1617 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000));
1619 layer_tree_host_->root_layer()->AddChild(layer);
1621 // The tile size is 100x100, so this invalidates and then paints two tiles in
1622 // various ways.
1624 gfx::Rect opaque_paint_rect;
1625 Region opaque_contents;
1627 gfx::Rect content_bounds = gfx::Rect(0, 0, 100, 300);
1628 layer->SetBounds(content_bounds.size());
1629 CalcDrawProps(&render_surface_layer_list);
1631 // Invalidates and paints the whole layer.
1632 layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1633 layer->InvalidateContentRect(content_bounds);
1634 layer->SetTexturePriorities(priority_calculator_);
1635 resource_manager_->PrioritizeTextures();
1636 layer->SavePaintProperties();
1637 layer->Update(queue_.get(), &occluded);
1638 UpdateTextures();
1639 opaque_contents = layer->VisibleContentOpaqueRegion();
1640 EXPECT_TRUE(opaque_contents.IsEmpty());
1642 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 30000, 1);
1643 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1644 EXPECT_NEAR(
1645 occluded.overdraw_metrics()->pixels_uploaded_translucent(), 30000, 1);
1646 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1648 // Invalidates an area on the top and bottom tile, which will cause us to
1649 // paint the tile in the middle, even though it is not dirty and will not be
1650 // uploaded.
1651 layer->fake_layer_updater()->SetOpaquePaintRect(gfx::Rect());
1652 layer->InvalidateContentRect(gfx::Rect(0, 0, 1, 1));
1653 layer->InvalidateContentRect(gfx::Rect(50, 200, 10, 10));
1654 layer->SetTexturePriorities(priority_calculator_);
1655 resource_manager_->PrioritizeTextures();
1656 layer->SavePaintProperties();
1657 layer->Update(queue_.get(), &occluded);
1658 UpdateTextures();
1659 opaque_contents = layer->VisibleContentOpaqueRegion();
1660 EXPECT_TRUE(opaque_contents.IsEmpty());
1662 // The middle tile was painted even though not invalidated.
1663 EXPECT_NEAR(
1664 occluded.overdraw_metrics()->pixels_painted(), 30000 + 60 * 210, 1);
1665 // The pixels uploaded will not include the non-invalidated tile in the
1666 // middle.
1667 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1668 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(),
1669 30000 + 1 + 100,
1671 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1674 TEST_F(TiledLayerTest, DontAllocateContentsWhenTargetSurfaceCantBeAllocated) {
1675 // Tile size is 100x100.
1676 gfx::Rect root_rect(0, 0, 300, 200);
1677 gfx::Rect child_rect(0, 0, 300, 100);
1678 gfx::Rect child2_rect(0, 100, 300, 100);
1680 scoped_refptr<FakeTiledLayer> root = make_scoped_refptr(
1681 new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
1682 scoped_refptr<Layer> surface = Layer::Create();
1683 scoped_refptr<FakeTiledLayer> child = make_scoped_refptr(
1684 new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
1685 scoped_refptr<FakeTiledLayer> child2 = make_scoped_refptr(
1686 new FakeTiledLayer(layer_tree_host_->contents_texture_manager()));
1688 root->SetBounds(root_rect.size());
1689 root->SetAnchorPoint(gfx::PointF());
1690 root->draw_properties().drawable_content_rect = root_rect;
1691 root->draw_properties().visible_content_rect = root_rect;
1692 root->AddChild(surface);
1694 surface->SetForceRenderSurface(true);
1695 surface->SetAnchorPoint(gfx::PointF());
1696 surface->SetOpacity(0.5);
1697 surface->AddChild(child);
1698 surface->AddChild(child2);
1700 child->SetBounds(child_rect.size());
1701 child->SetAnchorPoint(gfx::PointF());
1702 child->SetPosition(child_rect.origin());
1703 child->draw_properties().visible_content_rect = child_rect;
1704 child->draw_properties().drawable_content_rect = root_rect;
1706 child2->SetBounds(child2_rect.size());
1707 child2->SetAnchorPoint(gfx::PointF());
1708 child2->SetPosition(child2_rect.origin());
1709 child2->draw_properties().visible_content_rect = child2_rect;
1710 child2->draw_properties().drawable_content_rect = root_rect;
1712 layer_tree_host_->SetRootLayer(root);
1713 layer_tree_host_->SetViewportSize(root_rect.size());
1715 // With a huge memory limit, all layers should update and push their textures.
1716 root->InvalidateContentRect(root_rect);
1717 child->InvalidateContentRect(child_rect);
1718 child2->InvalidateContentRect(child2_rect);
1719 layer_tree_host_->UpdateLayers(queue_.get());
1721 UpdateTextures();
1722 EXPECT_EQ(6, root->fake_layer_updater()->update_count());
1723 EXPECT_EQ(3, child->fake_layer_updater()->update_count());
1724 EXPECT_EQ(3, child2->fake_layer_updater()->update_count());
1725 EXPECT_FALSE(queue_->HasMoreUpdates());
1727 root->fake_layer_updater()->ClearUpdateCount();
1728 child->fake_layer_updater()->ClearUpdateCount();
1729 child2->fake_layer_updater()->ClearUpdateCount();
1731 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
1732 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
1733 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
1734 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
1735 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
1736 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
1737 LayerPushPropertiesTo(child2.get(), child2_impl.get());
1738 LayerPushPropertiesTo(child.get(), child_impl.get());
1739 LayerPushPropertiesTo(root.get(), root_impl.get());
1741 for (unsigned i = 0; i < 3; ++i) {
1742 for (unsigned j = 0; j < 2; ++j)
1743 EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j));
1744 EXPECT_TRUE(child_impl->HasResourceIdForTileAt(i, 0));
1745 EXPECT_TRUE(child2_impl->HasResourceIdForTileAt(i, 0));
1748 layer_tree_host_->CommitComplete();
1750 // With a memory limit that includes only the root layer (3x2 tiles) and half
1751 // the surface that the child layers draw into, the child layers will not be
1752 // allocated. If the surface isn't accounted for, then one of the children
1753 // would fit within the memory limit.
1754 root->InvalidateContentRect(root_rect);
1755 child->InvalidateContentRect(child_rect);
1756 child2->InvalidateContentRect(child2_rect);
1758 size_t memory_limit = (3 * 2 + 3 * 1) * (100 * 100) * 4;
1759 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
1760 memory_limit);
1761 layer_tree_host_->UpdateLayers(queue_.get());
1763 UpdateTextures();
1764 EXPECT_EQ(6, root->fake_layer_updater()->update_count());
1765 EXPECT_EQ(0, child->fake_layer_updater()->update_count());
1766 EXPECT_EQ(0, child2->fake_layer_updater()->update_count());
1767 EXPECT_FALSE(queue_->HasMoreUpdates());
1769 root->fake_layer_updater()->ClearUpdateCount();
1770 child->fake_layer_updater()->ClearUpdateCount();
1771 child2->fake_layer_updater()->ClearUpdateCount();
1773 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
1774 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
1775 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
1776 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
1777 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
1778 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
1779 LayerPushPropertiesTo(child2.get(), child2_impl.get());
1780 LayerPushPropertiesTo(child.get(), child_impl.get());
1781 LayerPushPropertiesTo(root.get(), root_impl.get());
1783 for (unsigned i = 0; i < 3; ++i) {
1784 for (unsigned j = 0; j < 2; ++j)
1785 EXPECT_TRUE(root_impl->HasResourceIdForTileAt(i, j));
1786 EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0));
1787 EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0));
1790 layer_tree_host_->CommitComplete();
1792 // With a memory limit that includes only half the root layer, no contents
1793 // will be allocated. If render surface memory wasn't accounted for, there is
1794 // enough space for one of the children layers, but they draw into a surface
1795 // that can't be allocated.
1796 root->InvalidateContentRect(root_rect);
1797 child->InvalidateContentRect(child_rect);
1798 child2->InvalidateContentRect(child2_rect);
1800 memory_limit = (3 * 1) * (100 * 100) * 4;
1801 layer_tree_host_->contents_texture_manager()->SetMaxMemoryLimitBytes(
1802 memory_limit);
1803 layer_tree_host_->UpdateLayers(queue_.get());
1805 UpdateTextures();
1806 EXPECT_EQ(0, root->fake_layer_updater()->update_count());
1807 EXPECT_EQ(0, child->fake_layer_updater()->update_count());
1808 EXPECT_EQ(0, child2->fake_layer_updater()->update_count());
1809 EXPECT_FALSE(queue_->HasMoreUpdates());
1811 root->fake_layer_updater()->ClearUpdateCount();
1812 child->fake_layer_updater()->ClearUpdateCount();
1813 child2->fake_layer_updater()->ClearUpdateCount();
1815 scoped_ptr<FakeTiledLayerImpl> root_impl = make_scoped_ptr(
1816 new FakeTiledLayerImpl(host_impl_->active_tree(), root->id()));
1817 scoped_ptr<FakeTiledLayerImpl> child_impl = make_scoped_ptr(
1818 new FakeTiledLayerImpl(host_impl_->active_tree(), child->id()));
1819 scoped_ptr<FakeTiledLayerImpl> child2_impl = make_scoped_ptr(
1820 new FakeTiledLayerImpl(host_impl_->active_tree(), child2->id()));
1821 LayerPushPropertiesTo(child2.get(), child2_impl.get());
1822 LayerPushPropertiesTo(child.get(), child_impl.get());
1823 LayerPushPropertiesTo(root.get(), root_impl.get());
1825 for (unsigned i = 0; i < 3; ++i) {
1826 for (unsigned j = 0; j < 2; ++j)
1827 EXPECT_FALSE(root_impl->HasResourceIdForTileAt(i, j));
1828 EXPECT_FALSE(child_impl->HasResourceIdForTileAt(i, 0));
1829 EXPECT_FALSE(child2_impl->HasResourceIdForTileAt(i, 0));
1832 layer_tree_host_->CommitComplete();
1834 ResourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(),
1835 resource_provider_.get());
1836 layer_tree_host_->SetRootLayer(NULL);
1839 class TrackingLayerPainter : public LayerPainter {
1840 public:
1841 static scoped_ptr<TrackingLayerPainter> Create() {
1842 return make_scoped_ptr(new TrackingLayerPainter());
1845 virtual void Paint(SkCanvas* canvas,
1846 const gfx::Rect& content_rect,
1847 gfx::RectF* opaque) OVERRIDE {
1848 painted_rect_ = content_rect;
1851 gfx::Rect PaintedRect() const { return painted_rect_; }
1852 void ResetPaintedRect() { painted_rect_ = gfx::Rect(); }
1854 private:
1855 gfx::Rect painted_rect_;
1858 class UpdateTrackingTiledLayer : public FakeTiledLayer {
1859 public:
1860 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager)
1861 : FakeTiledLayer(manager) {
1862 scoped_ptr<TrackingLayerPainter> painter(TrackingLayerPainter::Create());
1863 tracking_layer_painter_ = painter.get();
1864 layer_updater_ =
1865 BitmapContentLayerUpdater::Create(painter.PassAs<LayerPainter>(),
1866 &stats_instrumentation_,
1870 TrackingLayerPainter* tracking_layer_painter() const {
1871 return tracking_layer_painter_;
1874 private:
1875 virtual LayerUpdater* Updater() const OVERRIDE {
1876 return layer_updater_.get();
1878 virtual ~UpdateTrackingTiledLayer() {}
1880 TrackingLayerPainter* tracking_layer_painter_;
1881 scoped_refptr<BitmapContentLayerUpdater> layer_updater_;
1882 FakeRenderingStatsInstrumentation stats_instrumentation_;
1885 TEST_F(TiledLayerTest, NonIntegerContentsScaleIsNotDistortedDuringPaint) {
1886 scoped_refptr<UpdateTrackingTiledLayer> layer =
1887 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
1889 layer_tree_host_->root_layer()->AddChild(layer);
1891 gfx::Rect layer_rect(0, 0, 30, 31);
1892 layer->SetPosition(layer_rect.origin());
1893 layer->SetBounds(layer_rect.size());
1894 layer->UpdateContentsScale(1.5f);
1896 gfx::Rect content_rect(0, 0, 45, 47);
1897 EXPECT_EQ(content_rect.size(), layer->content_bounds());
1898 layer->draw_properties().visible_content_rect = content_rect;
1899 layer->draw_properties().drawable_content_rect = content_rect;
1901 layer->SetTexturePriorities(priority_calculator_);
1902 resource_manager_->PrioritizeTextures();
1903 layer->SavePaintProperties();
1905 // Update the whole tile.
1906 layer->Update(queue_.get(), NULL);
1907 layer->tracking_layer_painter()->ResetPaintedRect();
1909 EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
1910 UpdateTextures();
1912 // Invalidate the entire layer in content space. When painting, the rect given
1913 // to webkit should match the layer's bounds.
1914 layer->InvalidateContentRect(content_rect);
1915 layer->Update(queue_.get(), NULL);
1917 EXPECT_RECT_EQ(layer_rect, layer->tracking_layer_painter()->PaintedRect());
1920 TEST_F(TiledLayerTest,
1921 NonIntegerContentsScaleIsNotDistortedDuringInvalidation) {
1922 scoped_refptr<UpdateTrackingTiledLayer> layer =
1923 make_scoped_refptr(new UpdateTrackingTiledLayer(resource_manager_.get()));
1925 layer_tree_host_->root_layer()->AddChild(layer);
1927 gfx::Rect layer_rect(0, 0, 30, 31);
1928 layer->SetPosition(layer_rect.origin());
1929 layer->SetBounds(layer_rect.size());
1930 layer->UpdateContentsScale(1.3f);
1932 gfx::Rect content_rect(layer->content_bounds());
1933 layer->draw_properties().visible_content_rect = content_rect;
1934 layer->draw_properties().drawable_content_rect = content_rect;
1936 layer->SetTexturePriorities(priority_calculator_);
1937 resource_manager_->PrioritizeTextures();
1938 layer->SavePaintProperties();
1940 // Update the whole tile.
1941 layer->Update(queue_.get(), NULL);
1942 layer->tracking_layer_painter()->ResetPaintedRect();
1944 EXPECT_RECT_EQ(gfx::Rect(), layer->tracking_layer_painter()->PaintedRect());
1945 UpdateTextures();
1947 // Invalidate the entire layer in layer space. When painting, the rect given
1948 // to webkit should match the layer's bounds.
1949 layer->SetNeedsDisplayRect(layer_rect);
1950 layer->Update(queue_.get(), NULL);
1952 EXPECT_RECT_EQ(layer_rect, layer->tracking_layer_painter()->PaintedRect());
1955 } // namespace
1956 } // namespace cc