Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(343)

Side by Side Diff: cc/tiled_layer_unittest.cc

Issue 12603013: Part 10 of cc/ directory shuffles: layers (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/tiled_layer_impl_unittest.cc ('k') | cc/trees/damage_tracker.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "cc/tiled_layer.h"
6
7 #include "cc/debug/overdraw_metrics.h"
8 #include "cc/resources/bitmap_content_layer_updater.h"
9 #include "cc/resources/layer_painter.h"
10 #include "cc/resources/prioritized_resource_manager.h"
11 #include "cc/resources/resource_update_controller.h"
12 #include "cc/test/animation_test_common.h"
13 #include "cc/test/fake_layer_tree_host_client.h"
14 #include "cc/test/fake_layer_tree_host_impl.h"
15 #include "cc/test/fake_output_surface.h"
16 #include "cc/test/fake_proxy.h"
17 #include "cc/test/geometry_test_utils.h"
18 #include "cc/test/tiled_layer_test_common.h"
19 #include "cc/trees/single_thread_proxy.h" // For DebugScopedSetImplThread
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/gfx/rect_conversions.h"
22 #include "ui/gfx/transform.h"
23
24 namespace cc {
25 namespace {
26
27 class TestOcclusionTracker : public OcclusionTracker {
28 public:
29 TestOcclusionTracker()
30 : OcclusionTracker(gfx::Rect(0, 0, 1000, 1000), true)
31 {
32 stack_.push_back(StackObject());
33 }
34
35 void setRenderTarget(Layer* renderTarget)
36 {
37 stack_.back().target = renderTarget;
38 }
39
40 void setOcclusion(const Region& occlusion)
41 {
42 stack_.back().occlusion_from_inside_target = occlusion;
43 }
44 };
45
46 class TiledLayerTest : public testing::Test {
47 public:
48 TiledLayerTest()
49 : m_proxy(NULL)
50 , m_outputSurface(createFakeOutputSurface())
51 , m_queue(make_scoped_ptr(new ResourceUpdateQueue))
52 , m_occlusion(0)
53 {
54 m_settings.maxPartialTextureUpdates = std::numeric_limits<size_t>::max() ;
55 }
56
57 virtual void SetUp()
58 {
59 layer_tree_host_ = LayerTreeHost::Create(&m_fakeLayerImplTreeHostClient, m_settings, scoped_ptr<Thread>(NULL));
60 m_proxy = layer_tree_host_->proxy();
61 m_resourceManager = PrioritizedResourceManager::create(m_proxy);
62 layer_tree_host_->InitializeRendererIfNeeded();
63 layer_tree_host_->SetRootLayer(Layer::Create());
64
65 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc ked(m_proxy);
66 m_resourceProvider = ResourceProvider::Create(m_outputSurface.get());
67 m_hostImpl = make_scoped_ptr(new FakeLayerTreeHostImpl(m_proxy));
68 }
69
70 virtual ~TiledLayerTest()
71 {
72 resourceManagerClearAllMemory(m_resourceManager.get(), m_resourceProvide r.get());
73
74 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc ked(m_proxy);
75 m_resourceProvider.reset();
76 m_hostImpl.reset();
77 }
78
79 void resourceManagerClearAllMemory(PrioritizedResourceManager* resourceManag er, ResourceProvider* resourceProvider)
80 {
81 {
82 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThread Blocked(m_proxy);
83 resourceManager->clearAllMemory(resourceProvider);
84 resourceManager->reduceMemory(resourceProvider);
85 }
86 resourceManager->unlinkAndClearEvictedBackings();
87 }
88 void updateTextures()
89 {
90 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc ked(m_proxy);
91 DCHECK(m_queue);
92 scoped_ptr<ResourceUpdateController> updateController =
93 ResourceUpdateController::Create(
94 NULL,
95 m_proxy->ImplThread(),
96 m_queue.Pass(),
97 m_resourceProvider.get());
98 updateController->Finalize();
99 m_queue = make_scoped_ptr(new ResourceUpdateQueue);
100 }
101 void layerPushPropertiesTo(FakeTiledLayer* layer, FakeTiledLayerImpl* layerI mpl)
102 {
103 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc ked(m_proxy);
104 layer->PushPropertiesTo(layerImpl);
105 }
106 void layerUpdate(FakeTiledLayer* layer, TestOcclusionTracker* occluded)
107 {
108 DebugScopedSetMainThread mainThread(m_proxy);
109 layer->Update(m_queue.get(), occluded, NULL);
110 }
111
112 void calcDrawProps(const scoped_refptr<FakeTiledLayer>& layer1)
113 {
114 scoped_refptr<FakeTiledLayer> layer2;
115 calcDrawProps(layer1, layer2);
116 }
117
118 void calcDrawProps(const scoped_refptr<FakeTiledLayer>& layer1,
119 const scoped_refptr<FakeTiledLayer>& layer2)
120 {
121 if (layer1 && !layer1->parent())
122 layer_tree_host_->root_layer()->AddChild(layer1);
123 if (layer2 && !layer2->parent())
124 layer_tree_host_->root_layer()->AddChild(layer2);
125 if (m_occlusion)
126 m_occlusion->setRenderTarget(layer_tree_host_->root_layer());
127
128 std::vector<scoped_refptr<Layer> > renderSurfaceLayerList;
129 LayerTreeHostCommon::calculateDrawProperties(
130 layer_tree_host_->root_layer(),
131 layer_tree_host_->device_viewport_size(),
132 layer_tree_host_->device_scale_factor(),
133 1, // page_scale_factor
134 layer_tree_host_->GetRendererCapabilities().max_texture_size,
135 false, // can_use_lcd_text
136 renderSurfaceLayerList);
137 }
138
139 bool updateAndPush(const scoped_refptr<FakeTiledLayer>& layer1,
140 const scoped_ptr<FakeTiledLayerImpl>& layerImpl1)
141 {
142 scoped_refptr<FakeTiledLayer> layer2;
143 scoped_ptr<FakeTiledLayerImpl> layerImpl2;
144 return updateAndPush(layer1, layerImpl1, layer2, layerImpl2);
145 }
146
147 bool updateAndPush(const scoped_refptr<FakeTiledLayer>& layer1,
148 const scoped_ptr<FakeTiledLayerImpl>& layerImpl1,
149 const scoped_refptr<FakeTiledLayer>& layer2,
150 const scoped_ptr<FakeTiledLayerImpl>& layerImpl2)
151 {
152 // Get textures
153 m_resourceManager->clearPriorities();
154 if (layer1)
155 layer1->SetTexturePriorities(m_priorityCalculator);
156 if (layer2)
157 layer2->SetTexturePriorities(m_priorityCalculator);
158 m_resourceManager->prioritizeTextures();
159
160 // Update content
161 if (layer1)
162 layer1->Update(m_queue.get(), m_occlusion, NULL);
163 if (layer2)
164 layer2->Update(m_queue.get(), m_occlusion, NULL);
165
166 bool needsUpdate = false;
167 if (layer1)
168 needsUpdate |= layer1->NeedsIdlePaint();
169 if (layer2)
170 needsUpdate |= layer2->NeedsIdlePaint();
171
172 // Update textures and push.
173 updateTextures();
174 if (layer1)
175 layerPushPropertiesTo(layer1.get(), layerImpl1.get());
176 if (layer2)
177 layerPushPropertiesTo(layer2.get(), layerImpl2.get());
178
179 return needsUpdate;
180 }
181
182 public:
183 Proxy* m_proxy;
184 LayerTreeSettings m_settings;
185 scoped_ptr<OutputSurface> m_outputSurface;
186 scoped_ptr<ResourceProvider> m_resourceProvider;
187 scoped_ptr<ResourceUpdateQueue> m_queue;
188 PriorityCalculator m_priorityCalculator;
189 FakeLayerImplTreeHostClient m_fakeLayerImplTreeHostClient;
190 scoped_ptr<LayerTreeHost> layer_tree_host_;
191 scoped_ptr<FakeLayerTreeHostImpl> m_hostImpl;
192 scoped_ptr<PrioritizedResourceManager> m_resourceManager;
193 TestOcclusionTracker* m_occlusion;
194 };
195
196 TEST_F(TiledLayerTest, pushDirtyTiles)
197 {
198 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
199 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
200
201 // The tile size is 100x100, so this invalidates and then paints two tiles.
202 layer->SetBounds(gfx::Size(100, 200));
203 calcDrawProps(layer);
204 updateAndPush(layer, layerImpl);
205
206 // We should have both tiles on the impl side.
207 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
208 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 1));
209
210 // Invalidates both tiles, but then only update one of them.
211 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 200));
212 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
213 updateAndPush(layer, layerImpl);
214
215 // We should only have the first tile since the other tile was invalidated b ut not painted.
216 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
217 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(0, 1));
218 }
219
220 TEST_F(TiledLayerTest, pushOccludedDirtyTiles)
221 {
222 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
223 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
224 TestOcclusionTracker occluded;
225 m_occlusion = &occluded;
226 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000), gfx::Size(1000, 100 0));
227
228 // The tile size is 100x100, so this invalidates and then paints two tiles.
229 layer->SetBounds(gfx::Size(100, 200));
230 calcDrawProps(layer);
231 updateAndPush(layer, layerImpl);
232
233 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
234 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2000 0, 1);
235 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
236
237 // We should have both tiles on the impl side.
238 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
239 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 1));
240
241 // Invalidates part of the top tile...
242 layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
243 // ....but the area is occluded.
244 occluded.setOcclusion(gfx::Rect(0, 0, 50, 50));
245 calcDrawProps(layer);
246 updateAndPush(layer, layerImpl);
247
248 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
249 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2000 0 + 2500, 1);
250 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
251
252 // We should still have both tiles, as part of the top tile is still unocclu ded.
253 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
254 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 1));
255 }
256
257 TEST_F(TiledLayerTest, pushDeletedTiles)
258 {
259 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
260 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
261
262 // The tile size is 100x100, so this invalidates and then paints two tiles.
263 layer->SetBounds(gfx::Size(100, 200));
264 calcDrawProps(layer);
265 updateAndPush(layer, layerImpl);
266
267 // We should have both tiles on the impl side.
268 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
269 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 1));
270
271 m_resourceManager->clearPriorities();
272 resourceManagerClearAllMemory(m_resourceManager.get(), m_resourceProvider.ge t());
273 m_resourceManager->setMaxMemoryLimitBytes(4*1024*1024);
274
275 // This should drop the tiles on the impl thread.
276 layerPushPropertiesTo(layer.get(), layerImpl.get());
277
278 // We should now have no textures on the impl thread.
279 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(0, 0));
280 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(0, 1));
281
282 // This should recreate and update one of the deleted textures.
283 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
284 updateAndPush(layer, layerImpl);
285
286 // We should have one tiles on the impl side.
287 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
288 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(0, 1));
289 }
290
291 TEST_F(TiledLayerTest, pushIdlePaintTiles)
292 {
293 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
294 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
295
296 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the ce nter.
297 // This paints 1 visible of the 25 invalid tiles.
298 layer->SetBounds(gfx::Size(500, 500));
299 calcDrawProps(layer);
300 layer->draw_properties().visible_content_rect = gfx::Rect(200, 200, 100, 100 );
301 bool needsUpdate = updateAndPush(layer, layerImpl);
302 // We should need idle-painting for surrounding tiles.
303 EXPECT_TRUE(needsUpdate);
304
305 // We should have one tile on the impl side.
306 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(2, 2));
307
308 // For the next four updates, we should detect we still need idle painting.
309 for (int i = 0; i < 4; i++) {
310 needsUpdate = updateAndPush(layer, layerImpl);
311 EXPECT_TRUE(needsUpdate);
312 }
313
314 // We should always finish painting eventually.
315 for (int i = 0; i < 20; i++)
316 needsUpdate = updateAndPush(layer, layerImpl);
317
318 // We should have pre-painted all of the surrounding tiles.
319 for (int i = 0; i < 5; i++) {
320 for (int j = 0; j < 5; j++)
321 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(i, j));
322 }
323
324 EXPECT_FALSE(needsUpdate);
325 }
326
327 TEST_F(TiledLayerTest, predictivePainting)
328 {
329 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
330 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
331
332 // Prepainting should occur in the scroll direction first, and the
333 // visible rect should be extruded only along the dominant axis.
334 gfx::Vector2d directions[6] = { gfx::Vector2d(-10, 0),
335 gfx::Vector2d(10, 0),
336 gfx::Vector2d(0, -10),
337 gfx::Vector2d(0, 10),
338 gfx::Vector2d(10, 20),
339 gfx::Vector2d(-20, 10) };
340 // We should push all tiles that touch the extruded visible rect.
341 gfx::Rect pushedVisibleTiles[6] = { gfx::Rect(2, 2, 2, 1),
342 gfx::Rect(1, 2, 2, 1),
343 gfx::Rect(2, 2, 1, 2),
344 gfx::Rect(2, 1, 1, 2),
345 gfx::Rect(2, 1, 1, 2),
346 gfx::Rect(2, 2, 2, 1) };
347 // The first pre-paint should also paint first in the scroll
348 // direction so we should find one additional tile in the scroll direction.
349 gfx::Rect pushedPrepaintTiles[6] = { gfx::Rect(2, 2, 3, 1),
350 gfx::Rect(0, 2, 3, 1),
351 gfx::Rect(2, 2, 1, 3),
352 gfx::Rect(2, 0, 1, 3),
353 gfx::Rect(2, 0, 1, 3),
354 gfx::Rect(2, 2, 3, 1) };
355 for(int k = 0; k < 6; k++) {
356 // The tile size is 100x100. Setup 5x5 tiles with one visible tile
357 // in the center.
358 gfx::Size bounds = gfx::Size(500, 500);
359 gfx::Rect visibleRect = gfx::Rect(200, 200, 100, 100);
360 gfx::Rect previousVisibleRect = gfx::Rect(visibleRect.origin() + directi ons[k], visibleRect.size());
361 gfx::Rect nextVisibleRect = gfx::Rect(visibleRect.origin() - directions[ k], visibleRect.size());
362
363 // Setup. Use the previousVisibleRect to setup the prediction for next f rame.
364 layer->SetBounds(bounds);
365 calcDrawProps(layer);
366 layer->draw_properties().visible_content_rect = previousVisibleRect;
367 bool needsUpdate = updateAndPush(layer, layerImpl);
368
369 // Invalidate and move the visibleRect in the scroll direction.
370 // Check that the correct tiles have been painted in the visible pass.
371 layer->SetNeedsDisplay();
372 layer->draw_properties().visible_content_rect = visibleRect;
373 needsUpdate = updateAndPush(layer, layerImpl);
374 for (int i = 0; i < 5; i++) {
375 for (int j = 0; j < 5; j++)
376 EXPECT_EQ(layerImpl->HasResourceIdForTileAt(i, j), pushedVisible Tiles[k].Contains(i, j));
377 }
378
379 // Move the transform in the same direction without invalidating.
380 // Check that non-visible pre-painting occured in the correct direction.
381 // Ignore diagonal scrolls here (k > 3) as these have new visible conten t now.
382 if (k <= 3) {
383 layer->draw_properties().visible_content_rect = nextVisibleRect;
384 needsUpdate = updateAndPush(layer, layerImpl);
385 for (int i = 0; i < 5; i++) {
386 for (int j = 0; j < 5; j++)
387 EXPECT_EQ(layerImpl->HasResourceIdForTileAt(i, j), pushedPre paintTiles[k].Contains(i, j));
388 }
389 }
390
391 // We should always finish painting eventually.
392 for (int i = 0; i < 20; i++)
393 needsUpdate = updateAndPush(layer, layerImpl);
394 EXPECT_FALSE(needsUpdate);
395 }
396 }
397
398 TEST_F(TiledLayerTest, pushTilesAfterIdlePaintFailed)
399 {
400 // Start with 2mb of memory, but the test is going to try to use just more t han 1mb, so we reduce to 1mb later.
401 m_resourceManager->setMaxMemoryLimitBytes(2 * 1024 * 1024);
402 scoped_refptr<FakeTiledLayer> layer1 = make_scoped_refptr(new FakeTiledLayer (m_resourceManager.get()));
403 scoped_ptr<FakeTiledLayerImpl> layerImpl1 = make_scoped_ptr(new FakeTiledLay erImpl(m_hostImpl->active_tree(), 1));
404 scoped_refptr<FakeTiledLayer> layer2 = make_scoped_refptr(new FakeTiledLayer (m_resourceManager.get()));
405 scoped_ptr<FakeTiledLayerImpl> layerImpl2 = make_scoped_ptr(new FakeTiledLay erImpl(m_hostImpl->active_tree(), 2));
406
407 // For this test we have two layers. layer1 exhausts most texture memory, le aving room for 2 more tiles from
408 // layer2, but not all three tiles. First we paint layer1, and one tile from layer2. Then when we idle paint
409 // layer2, we will fail on the third tile of layer2, and this should not lea ve the second tile in a bad state.
410
411 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enou gh for 2 tiles only in the other layer.
412 gfx::Rect layer1Rect(0, 0, 100, 2400);
413
414 // This requires 4*30000 bytes of memory.
415 gfx::Rect layer2Rect(0, 0, 100, 300);
416
417 // Paint a single tile in layer2 so that it will idle paint.
418 layer1->SetBounds(layer1Rect.size());
419 layer2->SetBounds(layer2Rect.size());
420 calcDrawProps(layer1, layer2);
421 layer1->draw_properties().visible_content_rect = layer1Rect;
422 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
423 bool needsUpdate = updateAndPush(layer1, layerImpl1,
424 layer2, layerImpl2);
425 // We should need idle-painting for both remaining tiles in layer2.
426 EXPECT_TRUE(needsUpdate);
427
428 // Reduce our memory limits to 1mb.
429 m_resourceManager->setMaxMemoryLimitBytes(1024 * 1024);
430
431 // Now idle paint layer2. We are going to run out of memory though!
432 // Oh well, commit the frame and push.
433 for (int i = 0; i < 4; i++) {
434 needsUpdate = updateAndPush(layer1, layerImpl1,
435 layer2, layerImpl2);
436 }
437
438 // Sanity check, we should have textures for the big layer.
439 EXPECT_TRUE(layerImpl1->HasResourceIdForTileAt(0, 0));
440 EXPECT_TRUE(layerImpl1->HasResourceIdForTileAt(0, 23));
441
442 // We should only have the first two tiles from layer2 since
443 // it failed to idle update the last tile.
444 EXPECT_TRUE(layerImpl2->HasResourceIdForTileAt(0, 0));
445 EXPECT_TRUE(layerImpl2->HasResourceIdForTileAt(0, 0));
446 EXPECT_TRUE(layerImpl2->HasResourceIdForTileAt(0, 1));
447 EXPECT_TRUE(layerImpl2->HasResourceIdForTileAt(0, 1));
448
449 EXPECT_FALSE(needsUpdate);
450 EXPECT_FALSE(layerImpl2->HasResourceIdForTileAt(0, 2));
451 }
452
453 TEST_F(TiledLayerTest, pushIdlePaintedOccludedTiles)
454 {
455 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
456 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
457 TestOcclusionTracker occluded;
458 m_occlusion = &occluded;
459
460 // The tile size is 100x100, so this invalidates one occluded tile, culls it during paint, but prepaints it.
461 occluded.setOcclusion(gfx::Rect(0, 0, 100, 100));
462
463 layer->SetBounds(gfx::Size(100, 100));
464 calcDrawProps(layer);
465 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
466 updateAndPush(layer, layerImpl);
467
468 // We should have the prepainted tile on the impl side, but culled it during paint.
469 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
470 EXPECT_EQ(1, occluded.overdraw_metrics()->tiles_culled_for_upload());
471 }
472
473 TEST_F(TiledLayerTest, pushTilesMarkedDirtyDuringPaint)
474 {
475 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
476 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
477
478 // The tile size is 100x100, so this invalidates and then paints two tiles.
479 // However, during the paint, we invalidate one of the tiles. This should
480 // not prevent the tile from being pushed.
481 layer->fakeLayerUpdater()->setRectToInvalidate(gfx::Rect(0, 50, 100, 50), la yer.get());
482 layer->SetBounds(gfx::Size(100, 200));
483 calcDrawProps(layer);
484 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
485 updateAndPush(layer, layerImpl);
486
487 // We should have both tiles on the impl side.
488 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
489 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 1));
490 }
491
492 TEST_F(TiledLayerTest, pushTilesLayerMarkedDirtyDuringPaintOnNextLayer)
493 {
494 scoped_refptr<FakeTiledLayer> layer1 = make_scoped_refptr(new FakeTiledLayer (m_resourceManager.get()));
495 scoped_refptr<FakeTiledLayer> layer2 = make_scoped_refptr(new FakeTiledLayer (m_resourceManager.get()));
496 scoped_ptr<FakeTiledLayerImpl> layer1Impl = make_scoped_ptr(new FakeTiledLay erImpl(m_hostImpl->active_tree(), 1));
497 scoped_ptr<FakeTiledLayerImpl> layer2Impl = make_scoped_ptr(new FakeTiledLay erImpl(m_hostImpl->active_tree(), 2));
498
499 // Invalidate a tile on layer1, during update of layer 2.
500 layer2->fakeLayerUpdater()->setRectToInvalidate(gfx::Rect(0, 50, 100, 50), l ayer1.get());
501 layer1->SetBounds(gfx::Size(100, 200));
502 layer2->SetBounds(gfx::Size(100, 200));
503 calcDrawProps(layer1, layer2);
504 layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
505 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
506 updateAndPush(layer1, layer1Impl,
507 layer2, layer2Impl);
508
509 // We should have both tiles on the impl side for all layers.
510 EXPECT_TRUE(layer1Impl->HasResourceIdForTileAt(0, 0));
511 EXPECT_TRUE(layer1Impl->HasResourceIdForTileAt(0, 1));
512 EXPECT_TRUE(layer2Impl->HasResourceIdForTileAt(0, 0));
513 EXPECT_TRUE(layer2Impl->HasResourceIdForTileAt(0, 1));
514 }
515
516 TEST_F(TiledLayerTest, pushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer)
517 {
518 scoped_refptr<FakeTiledLayer> layer1 = make_scoped_refptr(new FakeTiledLayer (m_resourceManager.get()));
519 scoped_refptr<FakeTiledLayer> layer2 = make_scoped_refptr(new FakeTiledLayer (m_resourceManager.get()));
520 scoped_ptr<FakeTiledLayerImpl> layer1Impl = make_scoped_ptr(new FakeTiledLay erImpl(m_hostImpl->active_tree(), 1));
521 scoped_ptr<FakeTiledLayerImpl> layer2Impl = make_scoped_ptr(new FakeTiledLay erImpl(m_hostImpl->active_tree(), 2));
522
523 layer1->fakeLayerUpdater()->setRectToInvalidate(gfx::Rect(0, 50, 100, 50), l ayer2.get());
524 layer1->SetBounds(gfx::Size(100, 200));
525 layer2->SetBounds(gfx::Size(100, 200));
526 calcDrawProps(layer1, layer2);
527 layer1->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
528 layer2->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
529 updateAndPush(layer1, layer1Impl,
530 layer2, layer2Impl);
531
532 // We should have both tiles on the impl side for all layers.
533 EXPECT_TRUE(layer1Impl->HasResourceIdForTileAt(0, 0));
534 EXPECT_TRUE(layer1Impl->HasResourceIdForTileAt(0, 1));
535 EXPECT_TRUE(layer2Impl->HasResourceIdForTileAt(0, 0));
536 EXPECT_TRUE(layer2Impl->HasResourceIdForTileAt(0, 1));
537 }
538
539 TEST_F(TiledLayerTest, paintSmallAnimatedLayersImmediately)
540 {
541 // Create a LayerTreeHost that has the right viewportsize,
542 // so the layer is considered small enough.
543 FakeLayerImplTreeHostClient fakeLayerImplTreeHostClient;
544
545 bool runOutOfMemory[2] = {false, true};
546 for (int i = 0; i < 2; i++) {
547 // Create a layer with 5x5 tiles, with 4x4 size viewport.
548 int viewportWidth = 4 * FakeTiledLayer::tileSize().width();
549 int viewportHeight = 4 * FakeTiledLayer::tileSize().width();
550 int layerWidth = 5 * FakeTiledLayer::tileSize().width();
551 int layerHeight = 5 * FakeTiledLayer::tileSize().height();
552 int memoryForLayer = layerWidth * layerHeight * 4;
553 layer_tree_host_->SetViewportSize(gfx::Size(layerWidth, layerHeight), gf x::Size(layerWidth, layerHeight));
554
555 // Use 10x5 tiles to run out of memory.
556 if (runOutOfMemory[i])
557 layerWidth *= 2;
558
559 m_resourceManager->setMaxMemoryLimitBytes(memoryForLayer);
560
561 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLa yer(m_resourceManager.get()));
562 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), 1));
563
564 // Full size layer with half being visible.
565 layer->SetBounds(gfx::Size(layerWidth, layerHeight));
566 gfx::Rect visibleRect(gfx::Point(), gfx::Size(layerWidth / 2, layerHeigh t));
567 calcDrawProps(layer);
568
569 // Pretend the layer is animating.
570 layer->draw_properties().target_space_transform_is_animating = true;
571 layer->draw_properties().visible_content_rect = visibleRect;
572 layer->SetLayerTreeHost(layer_tree_host_.get());
573
574 // The layer should paint its entire contents on the first paint
575 // if it is close to the viewport size and has the available memory.
576 layer->SetTexturePriorities(m_priorityCalculator);
577 m_resourceManager->prioritizeTextures();
578 layer->Update(m_queue.get(), 0, NULL);
579 updateTextures();
580 layerPushPropertiesTo(layer.get(), layerImpl.get());
581
582 // We should have all the tiles for the small animated layer.
583 // We should still have the visible tiles when we didn't
584 // have enough memory for all the tiles.
585 if (!runOutOfMemory[i]) {
586 for (int i = 0; i < 5; ++i) {
587 for (int j = 0; j < 5; ++j)
588 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(i, j));
589 }
590 } else {
591 for (int i = 0; i < 10; ++i) {
592 for (int j = 0; j < 5; ++j)
593 EXPECT_EQ(layerImpl->HasResourceIdForTileAt(i, j), i < 5);
594 }
595 }
596 }
597 }
598
599 TEST_F(TiledLayerTest, idlePaintOutOfMemory)
600 {
601 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
602 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
603
604 // We have enough memory for only the visible rect, so we will run out of me mory in first idle paint.
605 int memoryLimit = 4 * 100 * 100; // 1 tiles, 4 bytes per pixel.
606 m_resourceManager->setMaxMemoryLimitBytes(memoryLimit);
607
608 // The tile size is 100x100, so this invalidates and then paints two tiles.
609 bool needsUpdate = false;
610 layer->SetBounds(gfx::Size(300, 300));
611 calcDrawProps(layer);
612 layer->draw_properties().visible_content_rect = gfx::Rect(100, 100, 100, 100 );
613 for (int i = 0; i < 2; i++)
614 needsUpdate = updateAndPush(layer, layerImpl);
615
616 // Idle-painting should see no more priority tiles for painting.
617 EXPECT_FALSE(needsUpdate);
618
619 // We should have one tile on the impl side.
620 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(1, 1));
621 }
622
623 TEST_F(TiledLayerTest, idlePaintZeroSizedLayer)
624 {
625 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
626 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
627
628 bool animating[2] = {false, true};
629 for (int i = 0; i < 2; i++) {
630 // Pretend the layer is animating.
631 layer->draw_properties().target_space_transform_is_animating = animating [i];
632
633 // The layer's bounds are empty.
634 // Empty layers don't paint or idle-paint.
635 layer->SetBounds(gfx::Size());
636 calcDrawProps(layer);
637 layer->draw_properties().visible_content_rect = gfx::Rect();
638 bool needsUpdate = updateAndPush(layer, layerImpl);
639
640 // Empty layers don't have tiles.
641 EXPECT_EQ(0u, layer->NumPaintedTiles());
642
643 // Empty layers don't need prepaint.
644 EXPECT_FALSE(needsUpdate);
645
646 // Empty layers don't have tiles.
647 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(0, 0));
648 }
649 }
650
651 TEST_F(TiledLayerTest, idlePaintNonVisibleLayers)
652 {
653 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
654 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
655
656 // Alternate between not visible and visible.
657 gfx::Rect v(0, 0, 100, 100);
658 gfx::Rect nv(0, 0, 0, 0);
659 gfx::Rect visibleRect[10] = {nv, nv, v, v, nv, nv, v, v, nv, nv};
660 bool invalidate[10] = {true, true, true, true, true, true, true, true, fals e, false };
661
662 // We should not have any tiles except for when the layer was visible
663 // or after the layer was visible and we didn't invalidate.
664 bool haveTile[10] = { false, false, true, true, false, false, true, true, tr ue, true };
665
666 for (int i = 0; i < 10; i++) {
667 layer->SetBounds(gfx::Size(100, 100));
668 calcDrawProps(layer);
669 layer->draw_properties().visible_content_rect = visibleRect[i];
670
671 if (invalidate[i])
672 layer->InvalidateContentRect(gfx::Rect(0, 0, 100, 100));
673 bool needsUpdate = updateAndPush(layer, layerImpl);
674
675 // We should never signal idle paint, as we painted the entire layer
676 // or the layer was not visible.
677 EXPECT_FALSE(needsUpdate);
678 EXPECT_EQ(layerImpl->HasResourceIdForTileAt(0, 0), haveTile[i]);
679 }
680 }
681
682 TEST_F(TiledLayerTest, invalidateFromPrepare)
683 {
684 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
685 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
686
687 // The tile size is 100x100, so this invalidates and then paints two tiles.
688 layer->SetBounds(gfx::Size(100, 200));
689 calcDrawProps(layer);
690 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 200);
691 updateAndPush(layer, layerImpl);
692
693 // We should have both tiles on the impl side.
694 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
695 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 1));
696
697 layer->fakeLayerUpdater()->clearPrepareCount();
698 // Invoke update again. As the layer is valid update shouldn't be invoked on
699 // the LayerUpdater.
700 updateAndPush(layer, layerImpl);
701 EXPECT_EQ(0, layer->fakeLayerUpdater()->prepareCount());
702
703 // setRectToInvalidate triggers InvalidateContentRect() being invoked from u pdate.
704 layer->fakeLayerUpdater()->setRectToInvalidate(gfx::Rect(25, 25, 50, 50), la yer.get());
705 layer->fakeLayerUpdater()->clearPrepareCount();
706 layer->InvalidateContentRect(gfx::Rect(0, 0, 50, 50));
707 updateAndPush(layer, layerImpl);
708 EXPECT_EQ(1, layer->fakeLayerUpdater()->prepareCount());
709 layer->fakeLayerUpdater()->clearPrepareCount();
710
711 // The layer should still be invalid as update invoked invalidate.
712 updateAndPush(layer, layerImpl); // visible
713 EXPECT_EQ(1, layer->fakeLayerUpdater()->prepareCount());
714 }
715
716 TEST_F(TiledLayerTest, verifyUpdateRectWhenContentBoundsAreScaled)
717 {
718 // The updateRect (that indicates what was actually painted) should be in
719 // layer space, not the content space.
720 scoped_refptr<FakeTiledLayerWithScaledBounds> layer = make_scoped_refptr(new FakeTiledLayerWithScaledBounds(m_resourceManager.get()));
721
722 gfx::Rect layerBounds(0, 0, 300, 200);
723 gfx::Rect contentBounds(0, 0, 200, 250);
724
725 layer->SetBounds(layerBounds.size());
726 layer->setContentBounds(contentBounds.size());
727 layer->draw_properties().visible_content_rect = contentBounds;
728
729 // On first update, the updateRect includes all tiles, even beyond the bound aries of the layer.
730 // However, it should still be in layer space, not content space.
731 layer->InvalidateContentRect(contentBounds);
732
733 layer->SetTexturePriorities(m_priorityCalculator);
734 m_resourceManager->prioritizeTextures();
735 layer->Update(m_queue.get(), 0, NULL);
736 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 300, 300 * 0.8), layer->updateRect());
737 updateTextures();
738
739 // After the tiles are updated once, another invalidate only needs to update the bounds of the layer.
740 layer->SetTexturePriorities(m_priorityCalculator);
741 m_resourceManager->prioritizeTextures();
742 layer->InvalidateContentRect(contentBounds);
743 layer->Update(m_queue.get(), 0, NULL);
744 EXPECT_FLOAT_RECT_EQ(gfx::RectF(layerBounds), layer->updateRect());
745 updateTextures();
746
747 // Partial re-paint should also be represented by the updateRect in layer sp ace, not content space.
748 gfx::Rect partialDamage(30, 100, 10, 10);
749 layer->InvalidateContentRect(partialDamage);
750 layer->SetTexturePriorities(m_priorityCalculator);
751 m_resourceManager->prioritizeTextures();
752 layer->Update(m_queue.get(), 0, NULL);
753 EXPECT_FLOAT_RECT_EQ(gfx::RectF(45, 80, 15, 8), layer->updateRect());
754 }
755
756 TEST_F(TiledLayerTest, verifyInvalidationWhenContentsScaleChanges)
757 {
758 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
759 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiledLaye rImpl(m_hostImpl->active_tree(), 1));
760
761 // Create a layer with one tile.
762 layer->SetBounds(gfx::Size(100, 100));
763 calcDrawProps(layer);
764 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 100, 100);
765 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), layer->lastNeedsDisplayRect ());
766
767 // Push the tiles to the impl side and check that there is exactly one.
768 layer->SetTexturePriorities(m_priorityCalculator);
769 m_resourceManager->prioritizeTextures();
770 layer->Update(m_queue.get(), 0, NULL);
771 updateTextures();
772 layerPushPropertiesTo(layer.get(), layerImpl.get());
773 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
774 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(0, 1));
775 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(1, 0));
776 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(1, 1));
777
778 layer->SetNeedsDisplayRect(gfx::Rect());
779 EXPECT_FLOAT_RECT_EQ(gfx::RectF(), layer->lastNeedsDisplayRect());
780
781 // Change the contents scale.
782 layer->updateContentsScale(2);
783 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 200, 200);
784
785 // The impl side should get 2x2 tiles now.
786 layer->SetTexturePriorities(m_priorityCalculator);
787 m_resourceManager->prioritizeTextures();
788 layer->Update(m_queue.get(), 0, NULL);
789 updateTextures();
790 layerPushPropertiesTo(layer.get(), layerImpl.get());
791 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 0));
792 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(0, 1));
793 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(1, 0));
794 EXPECT_TRUE(layerImpl->HasResourceIdForTileAt(1, 1));
795
796 // Verify that changing the contents scale caused invalidation, and
797 // that the layer-space rectangle requiring painting is not scaled.
798 EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), layer->lastNeedsDisplayRect ());
799
800 // Invalidate the entire layer again, but do not paint. All tiles should be gone now from the
801 // impl side.
802 layer->SetNeedsDisplay();
803 layer->SetTexturePriorities(m_priorityCalculator);
804 m_resourceManager->prioritizeTextures();
805
806 layerPushPropertiesTo(layer.get(), layerImpl.get());
807 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(0, 0));
808 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(0, 1));
809 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(1, 0));
810 EXPECT_FALSE(layerImpl->HasResourceIdForTileAt(1, 1));
811 }
812
813 TEST_F(TiledLayerTest, skipsDrawGetsReset)
814 {
815 // Create two 300 x 300 tiled layers.
816 gfx::Size contentBounds(300, 300);
817 gfx::Rect contentRect(gfx::Point(), contentBounds);
818
819 // We have enough memory for only one of the two layers.
820 int memoryLimit = 4 * 300 * 300; // 4 bytes per pixel.
821
822 scoped_refptr<FakeTiledLayer> root_layer = make_scoped_refptr(new FakeTiledL ayer(layer_tree_host_->contents_texture_manager()));
823 scoped_refptr<FakeTiledLayer> childLayer = make_scoped_refptr(new FakeTiledL ayer(layer_tree_host_->contents_texture_manager()));
824 root_layer->AddChild(childLayer);
825
826 root_layer->SetBounds(contentBounds);
827 root_layer->draw_properties().visible_content_rect = contentRect;
828 root_layer->SetPosition(gfx::PointF(0, 0));
829 childLayer->SetBounds(contentBounds);
830 childLayer->draw_properties().visible_content_rect = contentRect;
831 childLayer->SetPosition(gfx::PointF(0, 0));
832 root_layer->InvalidateContentRect(contentRect);
833 childLayer->InvalidateContentRect(contentRect);
834
835 layer_tree_host_->SetRootLayer(root_layer);
836 layer_tree_host_->SetViewportSize(gfx::Size(300, 300), gfx::Size(300, 300));
837
838 layer_tree_host_->UpdateLayers(m_queue.get(), memoryLimit);
839
840 // We'll skip the root layer.
841 EXPECT_TRUE(root_layer->SkipsDraw());
842 EXPECT_FALSE(childLayer->SkipsDraw());
843
844 layer_tree_host_->CommitComplete();
845
846 // Remove the child layer.
847 root_layer->RemoveAllChildren();
848
849 layer_tree_host_->UpdateLayers(m_queue.get(), memoryLimit);
850 EXPECT_FALSE(root_layer->SkipsDraw());
851
852 resourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), m_resourceProvider.get());
853 layer_tree_host_->SetRootLayer(NULL);
854 }
855
856 TEST_F(TiledLayerTest, resizeToSmaller)
857 {
858 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
859
860 layer->SetBounds(gfx::Size(700, 700));
861 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700);
862 layer->InvalidateContentRect(gfx::Rect(0, 0, 700, 700));
863
864 layer->SetTexturePriorities(m_priorityCalculator);
865 m_resourceManager->prioritizeTextures();
866 layer->Update(m_queue.get(), 0, NULL);
867
868 layer->SetBounds(gfx::Size(200, 200));
869 layer->InvalidateContentRect(gfx::Rect(0, 0, 200, 200));
870 }
871
872 TEST_F(TiledLayerTest, hugeLayerUpdateCrash)
873 {
874 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
875
876 int size = 1 << 30;
877 layer->SetBounds(gfx::Size(size, size));
878 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 700, 700);
879 layer->InvalidateContentRect(gfx::Rect(0, 0, size, size));
880
881 // Ensure no crash for bounds where size * size would overflow an int.
882 layer->SetTexturePriorities(m_priorityCalculator);
883 m_resourceManager->prioritizeTextures();
884 layer->Update(m_queue.get(), 0, NULL);
885 }
886
887 class TiledLayerPartialUpdateTest : public TiledLayerTest {
888 public:
889 TiledLayerPartialUpdateTest()
890 {
891 m_settings.maxPartialTextureUpdates = 4;
892 }
893 };
894
895 TEST_F(TiledLayerPartialUpdateTest, partialUpdates)
896 {
897 // Create one 300 x 200 tiled layer with 3 x 2 tiles.
898 gfx::Size contentBounds(300, 200);
899 gfx::Rect contentRect(gfx::Point(), contentBounds);
900
901 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( layer_tree_host_->contents_texture_manager()));
902 layer->SetBounds(contentBounds);
903 layer->SetPosition(gfx::PointF(0, 0));
904 layer->draw_properties().visible_content_rect = contentRect;
905 layer->InvalidateContentRect(contentRect);
906
907 layer_tree_host_->SetRootLayer(layer);
908 layer_tree_host_->SetViewportSize(gfx::Size(300, 200), gfx::Size(300, 200));
909
910 // Full update of all 6 tiles.
911 layer_tree_host_->UpdateLayers(m_queue.get(),
912 std::numeric_limits<size_t>::max());
913 {
914 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), 1));
915 EXPECT_EQ(6, m_queue->fullUploadSize());
916 EXPECT_EQ(0, m_queue->partialUploadSize());
917 updateTextures();
918 EXPECT_EQ(6, layer->fakeLayerUpdater()->updateCount());
919 EXPECT_FALSE(m_queue->hasMoreUpdates());
920 layer->fakeLayerUpdater()->clearUpdateCount();
921 layerPushPropertiesTo(layer.get(), layerImpl.get());
922 }
923 layer_tree_host_->CommitComplete();
924
925 // Full update of 3 tiles and partial update of 3 tiles.
926 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 150));
927 layer_tree_host_->UpdateLayers(m_queue.get(), std::numeric_limits<size_t>::m ax());
928 {
929 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), 1));
930 EXPECT_EQ(3, m_queue->fullUploadSize());
931 EXPECT_EQ(3, m_queue->partialUploadSize());
932 updateTextures();
933 EXPECT_EQ(6, layer->fakeLayerUpdater()->updateCount());
934 EXPECT_FALSE(m_queue->hasMoreUpdates());
935 layer->fakeLayerUpdater()->clearUpdateCount();
936 layerPushPropertiesTo(layer.get(), layerImpl.get());
937 }
938 layer_tree_host_->CommitComplete();
939
940 // Partial update of 6 tiles.
941 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
942 {
943 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), 1));
944 layer_tree_host_->UpdateLayers(m_queue.get(), std::numeric_limits<size_t >::max());
945 EXPECT_EQ(2, m_queue->fullUploadSize());
946 EXPECT_EQ(4, m_queue->partialUploadSize());
947 updateTextures();
948 EXPECT_EQ(6, layer->fakeLayerUpdater()->updateCount());
949 EXPECT_FALSE(m_queue->hasMoreUpdates());
950 layer->fakeLayerUpdater()->clearUpdateCount();
951 layerPushPropertiesTo(layer.get(), layerImpl.get());
952 }
953 layer_tree_host_->CommitComplete();
954
955 // Checkerboard all tiles.
956 layer->InvalidateContentRect(gfx::Rect(0, 0, 300, 200));
957 {
958 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), 1));
959 layerPushPropertiesTo(layer.get(), layerImpl.get());
960 }
961 layer_tree_host_->CommitComplete();
962
963 // Partial update of 6 checkerboard tiles.
964 layer->InvalidateContentRect(gfx::Rect(50, 50, 200, 100));
965 {
966 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), 1));
967 layer_tree_host_->UpdateLayers(m_queue.get(), std::numeric_limits<size_t >::max());
968 EXPECT_EQ(6, m_queue->fullUploadSize());
969 EXPECT_EQ(0, m_queue->partialUploadSize());
970 updateTextures();
971 EXPECT_EQ(6, layer->fakeLayerUpdater()->updateCount());
972 EXPECT_FALSE(m_queue->hasMoreUpdates());
973 layer->fakeLayerUpdater()->clearUpdateCount();
974 layerPushPropertiesTo(layer.get(), layerImpl.get());
975 }
976 layer_tree_host_->CommitComplete();
977
978 // Partial update of 4 tiles.
979 layer->InvalidateContentRect(gfx::Rect(50, 50, 100, 100));
980 {
981 scoped_ptr<FakeTiledLayerImpl> layerImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), 1));
982 layer_tree_host_->UpdateLayers(m_queue.get(), std::numeric_limits<size_t >::max());
983 EXPECT_EQ(0, m_queue->fullUploadSize());
984 EXPECT_EQ(4, m_queue->partialUploadSize());
985 updateTextures();
986 EXPECT_EQ(4, layer->fakeLayerUpdater()->updateCount());
987 EXPECT_FALSE(m_queue->hasMoreUpdates());
988 layer->fakeLayerUpdater()->clearUpdateCount();
989 layerPushPropertiesTo(layer.get(), layerImpl.get());
990 }
991 layer_tree_host_->CommitComplete();
992
993 resourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), m_resourceProvider.get());
994 layer_tree_host_->SetRootLayer(NULL);
995 }
996
997 TEST_F(TiledLayerTest, tilesPaintedWithoutOcclusion)
998 {
999 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
1000
1001 // The tile size is 100x100, so this invalidates and then paints two tiles.
1002 layer->SetBounds(gfx::Size(100, 200));
1003 calcDrawProps(layer);
1004
1005 layer->SetTexturePriorities(m_priorityCalculator);
1006 m_resourceManager->prioritizeTextures();
1007 layer->Update(m_queue.get(), 0, NULL);
1008 EXPECT_EQ(2, layer->fakeLayerUpdater()->updateCount());
1009 }
1010
1011 TEST_F(TiledLayerTest, tilesPaintedWithOcclusion)
1012 {
1013 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
1014 TestOcclusionTracker occluded;
1015 m_occlusion = &occluded;
1016
1017 // The tile size is 100x100.
1018
1019 layer_tree_host_->SetViewportSize(gfx::Size(600, 600), gfx::Size(600, 600));
1020 layer->SetBounds(gfx::Size(600, 600));
1021 calcDrawProps(layer);
1022
1023 occluded.setOcclusion(gfx::Rect(200, 200, 300, 100));
1024 layer->draw_properties().drawable_content_rect = gfx::Rect(gfx::Point(), lay er->content_bounds());
1025 layer->draw_properties().visible_content_rect = gfx::Rect(gfx::Point(), laye r->content_bounds());
1026 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1027
1028 layer->SetTexturePriorities(m_priorityCalculator);
1029 m_resourceManager->prioritizeTextures();
1030 layer->Update(m_queue.get(), &occluded, NULL);
1031 EXPECT_EQ(36-3, layer->fakeLayerUpdater()->updateCount());
1032
1033 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1034 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 3300 00, 1);
1035 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1036
1037 layer->fakeLayerUpdater()->clearUpdateCount();
1038 layer->SetTexturePriorities(m_priorityCalculator);
1039 m_resourceManager->prioritizeTextures();
1040
1041 occluded.setOcclusion(gfx::Rect(250, 200, 300, 100));
1042 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1043 layer->Update(m_queue.get(), &occluded, NULL);
1044 EXPECT_EQ(36-2, layer->fakeLayerUpdater()->updateCount());
1045
1046 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1047 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 3300 00 + 340000, 1);
1048 EXPECT_EQ(3 + 2, occluded.overdraw_metrics()->tiles_culled_for_upload());
1049
1050 layer->fakeLayerUpdater()->clearUpdateCount();
1051 layer->SetTexturePriorities(m_priorityCalculator);
1052 m_resourceManager->prioritizeTextures();
1053
1054 occluded.setOcclusion(gfx::Rect(250, 250, 300, 100));
1055 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1056 layer->Update(m_queue.get(), &occluded, NULL);
1057 EXPECT_EQ(36, layer->fakeLayerUpdater()->updateCount());
1058
1059 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1060 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 3300 00 + 340000 + 360000, 1);
1061 EXPECT_EQ(3 + 2, occluded.overdraw_metrics()->tiles_culled_for_upload());
1062 }
1063
1064 TEST_F(TiledLayerTest, tilesPaintedWithOcclusionAndVisiblityConstraints)
1065 {
1066 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
1067 TestOcclusionTracker occluded;
1068 m_occlusion = &occluded;
1069
1070 // The tile size is 100x100.
1071
1072 layer_tree_host_->SetViewportSize(gfx::Size(600, 600), gfx::Size(600, 600));
1073 layer->SetBounds(gfx::Size(600, 600));
1074 calcDrawProps(layer);
1075
1076 // The partially occluded tiles (by the 150 occlusion height) are visible be yond the occlusion, so not culled.
1077 occluded.setOcclusion(gfx::Rect(200, 200, 300, 150));
1078 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 360);
1079 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 360);
1080 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1081
1082 layer->SetTexturePriorities(m_priorityCalculator);
1083 m_resourceManager->prioritizeTextures();
1084 layer->Update(m_queue.get(), &occluded, NULL);
1085 EXPECT_EQ(24-3, layer->fakeLayerUpdater()->updateCount());
1086
1087 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1088 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2100 00, 1);
1089 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1090
1091 layer->fakeLayerUpdater()->clearUpdateCount();
1092
1093 // Now the visible region stops at the edge of the occlusion so the partly v isible tiles become fully occluded.
1094 occluded.setOcclusion(gfx::Rect(200, 200, 300, 150));
1095 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 350);
1096 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 350);
1097 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1098 layer->SetTexturePriorities(m_priorityCalculator);
1099 m_resourceManager->prioritizeTextures();
1100 layer->Update(m_queue.get(), &occluded, NULL);
1101 EXPECT_EQ(24-6, layer->fakeLayerUpdater()->updateCount());
1102
1103 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1104 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2100 00 + 180000, 1);
1105 EXPECT_EQ(3 + 6, occluded.overdraw_metrics()->tiles_culled_for_upload());
1106
1107 layer->fakeLayerUpdater()->clearUpdateCount();
1108
1109 // Now the visible region is even smaller than the occlusion, it should have the same result.
1110 occluded.setOcclusion(gfx::Rect(200, 200, 300, 150));
1111 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 340);
1112 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 340);
1113 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1114 layer->SetTexturePriorities(m_priorityCalculator);
1115 m_resourceManager->prioritizeTextures();
1116 layer->Update(m_queue.get(), &occluded, NULL);
1117 EXPECT_EQ(24-6, layer->fakeLayerUpdater()->updateCount());
1118
1119 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1120 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2100 00 + 180000 + 180000, 1);
1121 EXPECT_EQ(3 + 6 + 6, occluded.overdraw_metrics()->tiles_culled_for_upload()) ;
1122
1123 }
1124
1125 TEST_F(TiledLayerTest, tilesNotPaintedWithoutInvalidation)
1126 {
1127 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
1128 TestOcclusionTracker occluded;
1129 m_occlusion = &occluded;
1130
1131 // The tile size is 100x100.
1132
1133 layer_tree_host_->SetViewportSize(gfx::Size(600, 600), gfx::Size(600, 600));
1134 layer->SetBounds(gfx::Size(600, 600));
1135 calcDrawProps(layer);
1136
1137 occluded.setOcclusion(gfx::Rect(200, 200, 300, 100));
1138 layer->draw_properties().drawable_content_rect = gfx::Rect(0, 0, 600, 600);
1139 layer->draw_properties().visible_content_rect = gfx::Rect(0, 0, 600, 600);
1140 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1141 layer->SetTexturePriorities(m_priorityCalculator);
1142 m_resourceManager->prioritizeTextures();
1143 layer->Update(m_queue.get(), &occluded, NULL);
1144 EXPECT_EQ(36-3, layer->fakeLayerUpdater()->updateCount());
1145 {
1146 updateTextures();
1147 }
1148
1149 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1150 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 3300 00, 1);
1151 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1152
1153 layer->fakeLayerUpdater()->clearUpdateCount();
1154 layer->SetTexturePriorities(m_priorityCalculator);
1155 m_resourceManager->prioritizeTextures();
1156
1157 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted now.
1158 layer->Update(m_queue.get(), &occluded, NULL);
1159 EXPECT_EQ(3, layer->fakeLayerUpdater()->updateCount());
1160
1161 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1162 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 3300 00, 1);
1163 EXPECT_EQ(6, occluded.overdraw_metrics()->tiles_culled_for_upload());
1164 }
1165
1166 TEST_F(TiledLayerTest, tilesPaintedWithOcclusionAndTransforms)
1167 {
1168 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
1169 TestOcclusionTracker occluded;
1170 m_occlusion = &occluded;
1171
1172 // The tile size is 100x100.
1173
1174 // This makes sure the painting works when the occluded region (in screen sp ace)
1175 // is transformed differently than the layer.
1176 layer_tree_host_->SetViewportSize(gfx::Size(600, 600), gfx::Size(600, 600));
1177 layer->SetBounds(gfx::Size(600, 600));
1178 calcDrawProps(layer);
1179 gfx::Transform screenTransform;
1180 screenTransform.Scale(0.5, 0.5);
1181 layer->draw_properties().screen_space_transform = screenTransform;
1182 layer->draw_properties().target_space_transform = screenTransform;
1183
1184 occluded.setOcclusion(gfx::Rect(100, 100, 150, 50));
1185 layer->draw_properties().drawable_content_rect = gfx::Rect(gfx::Point(), lay er->content_bounds());
1186 layer->draw_properties().visible_content_rect = gfx::Rect(gfx::Point(), laye r->content_bounds());
1187 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1188 layer->SetTexturePriorities(m_priorityCalculator);
1189 m_resourceManager->prioritizeTextures();
1190 layer->Update(m_queue.get(), &occluded, NULL);
1191 EXPECT_EQ(36-3, layer->fakeLayerUpdater()->updateCount());
1192
1193 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1194 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 3300 00, 1);
1195 EXPECT_EQ(3, occluded.overdraw_metrics()->tiles_culled_for_upload());
1196 }
1197
1198 TEST_F(TiledLayerTest, tilesPaintedWithOcclusionAndScaling)
1199 {
1200 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
1201 TestOcclusionTracker occluded;
1202 m_occlusion = &occluded;
1203
1204 // The tile size is 100x100.
1205
1206 // This makes sure the painting works when the content space is scaled to
1207 // a different layer space. In this case tiles are scaled to be 200x200
1208 // pixels, which means none should be occluded.
1209 layer_tree_host_->SetViewportSize(gfx::Size(600, 600), gfx::Size(600, 600));
1210 layer->SetBounds(gfx::Size(600, 600));
1211 layer->SetRasterScale(0.5);
1212 calcDrawProps(layer);
1213 EXPECT_FLOAT_EQ(layer->contents_scale_x(), layer->contents_scale_y());
1214 gfx::Transform drawTransform;
1215 double invScaleFactor = 1 / layer->contents_scale_x();
1216 drawTransform.Scale(invScaleFactor, invScaleFactor);
1217 layer->draw_properties().target_space_transform = drawTransform;
1218 layer->draw_properties().screen_space_transform = drawTransform;
1219
1220 occluded.setOcclusion(gfx::Rect(200, 200, 300, 100));
1221 layer->draw_properties().drawable_content_rect = gfx::Rect(gfx::Point(), lay er->bounds());
1222 layer->draw_properties().visible_content_rect = gfx::Rect(gfx::Point(), laye r->content_bounds());
1223 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1224 layer->SetTexturePriorities(m_priorityCalculator);
1225 m_resourceManager->prioritizeTextures();
1226 layer->Update(m_queue.get(), &occluded, NULL);
1227 // The content is half the size of the layer (so the number of tiles is fewe r).
1228 // In this case, the content is 300x300, and since the tile size is 100, the
1229 // number of tiles 3x3.
1230 EXPECT_EQ(9, layer->fakeLayerUpdater()->updateCount());
1231
1232 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1233 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 9000 0, 1);
1234 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1235
1236 layer->fakeLayerUpdater()->clearUpdateCount();
1237
1238 // This makes sure the painting works when the content space is scaled to
1239 // a different layer space. In this case the occluded region catches the
1240 // blown up tiles.
1241 occluded.setOcclusion(gfx::Rect(200, 200, 300, 200));
1242 layer->draw_properties().drawable_content_rect = gfx::Rect(gfx::Point(), lay er->bounds());
1243 layer->draw_properties().visible_content_rect = gfx::Rect(gfx::Point(), laye r->content_bounds());
1244 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1245 layer->SetTexturePriorities(m_priorityCalculator);
1246 m_resourceManager->prioritizeTextures();
1247 layer->Update(m_queue.get(), &occluded, NULL);
1248 EXPECT_EQ(9-1, layer->fakeLayerUpdater()->updateCount());
1249
1250 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1251 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 9000 0 + 80000, 1);
1252 EXPECT_EQ(1, occluded.overdraw_metrics()->tiles_culled_for_upload());
1253
1254 layer->fakeLayerUpdater()->clearUpdateCount();
1255
1256 // This makes sure content scaling and transforms work together.
1257 gfx::Transform screenTransform;
1258 screenTransform.Scale(0.5, 0.5);
1259 layer->draw_properties().screen_space_transform = screenTransform;
1260 layer->draw_properties().target_space_transform = screenTransform;
1261
1262 occluded.setOcclusion(gfx::Rect(100, 100, 150, 100));
1263
1264 gfx::Rect layerBoundsRect(gfx::Point(), layer->bounds());
1265 layer->draw_properties().drawable_content_rect = gfx::ToEnclosingRect(gfx::S caleRect(layerBoundsRect, 0.5));
1266 layer->draw_properties().visible_content_rect = gfx::Rect(gfx::Point(), laye r->content_bounds());
1267 layer->InvalidateContentRect(gfx::Rect(0, 0, 600, 600));
1268 layer->SetTexturePriorities(m_priorityCalculator);
1269 m_resourceManager->prioritizeTextures();
1270 layer->Update(m_queue.get(), &occluded, NULL);
1271 EXPECT_EQ(9-1, layer->fakeLayerUpdater()->updateCount());
1272
1273 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1274 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 9000 0 + 80000 + 80000, 1);
1275 EXPECT_EQ(1 + 1, occluded.overdraw_metrics()->tiles_culled_for_upload());
1276 }
1277
1278 TEST_F(TiledLayerTest, visibleContentOpaqueRegion)
1279 {
1280 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
1281 TestOcclusionTracker occluded;
1282 m_occlusion = &occluded;
1283 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000), gfx::Size(1000, 100 0));
1284
1285 // The tile size is 100x100, so this invalidates and then paints two tiles i n various ways.
1286
1287 gfx::Rect opaquePaintRect;
1288 Region opaqueContents;
1289
1290 gfx::Rect contentBounds = gfx::Rect(0, 0, 100, 200);
1291 gfx::Rect visibleBounds = gfx::Rect(0, 0, 100, 150);
1292
1293 layer->SetBounds(contentBounds.size());
1294 calcDrawProps(layer);
1295 layer->draw_properties().drawable_content_rect = visibleBounds;
1296 layer->draw_properties().visible_content_rect = visibleBounds;
1297
1298 // If the layer doesn't paint opaque content, then the visibleContentOpaqueR egion should be empty.
1299 layer->fakeLayerUpdater()->setOpaquePaintRect(gfx::Rect());
1300 layer->InvalidateContentRect(contentBounds);
1301 layer->SetTexturePriorities(m_priorityCalculator);
1302 m_resourceManager->prioritizeTextures();
1303 layer->Update(m_queue.get(), &occluded, NULL);
1304 opaqueContents = layer->VisibleContentOpaqueRegion();
1305 EXPECT_TRUE(opaqueContents.IsEmpty());
1306
1307 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000, 1);
1308 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1309 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2000 0, 1);
1310 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1311
1312 // visibleContentOpaqueRegion should match the visible part of what is paint ed opaque.
1313 opaquePaintRect = gfx::Rect(10, 10, 90, 190);
1314 layer->fakeLayerUpdater()->setOpaquePaintRect(opaquePaintRect);
1315 layer->InvalidateContentRect(contentBounds);
1316 layer->SetTexturePriorities(m_priorityCalculator);
1317 m_resourceManager->prioritizeTextures();
1318 layer->Update(m_queue.get(), &occluded, NULL);
1319 updateTextures();
1320 opaqueContents = layer->VisibleContentOpaqueRegion();
1321 EXPECT_EQ(gfx::IntersectRects(opaquePaintRect, visibleBounds).ToString(), op aqueContents.ToString());
1322
1323 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000 * 2, 1);
1324 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 17100, 1) ;
1325 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2000 0 + 20000 - 17100, 1);
1326 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1327
1328 // If we paint again without invalidating, the same stuff should be opaque.
1329 layer->fakeLayerUpdater()->setOpaquePaintRect(gfx::Rect());
1330 layer->SetTexturePriorities(m_priorityCalculator);
1331 m_resourceManager->prioritizeTextures();
1332 layer->Update(m_queue.get(), &occluded, NULL);
1333 updateTextures();
1334 opaqueContents = layer->VisibleContentOpaqueRegion();
1335 EXPECT_EQ(gfx::IntersectRects(opaquePaintRect, visibleBounds).ToString(), op aqueContents.ToString());
1336
1337 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000 * 2, 1);
1338 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 17100, 1) ;
1339 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2000 0 + 20000 - 17100, 1);
1340 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1341
1342 // If we repaint a non-opaque part of the tile, then it shouldn't lose its o paque-ness. And other tiles should
1343 // not be affected.
1344 layer->fakeLayerUpdater()->setOpaquePaintRect(gfx::Rect());
1345 layer->InvalidateContentRect(gfx::Rect(0, 0, 1, 1));
1346 layer->SetTexturePriorities(m_priorityCalculator);
1347 m_resourceManager->prioritizeTextures();
1348 layer->Update(m_queue.get(), &occluded, NULL);
1349 updateTextures();
1350 opaqueContents = layer->VisibleContentOpaqueRegion();
1351 EXPECT_EQ(gfx::IntersectRects(opaquePaintRect, visibleBounds).ToString(), op aqueContents.ToString());
1352
1353 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000 * 2 + 1, 1) ;
1354 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 17100, 1) ;
1355 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2000 0 + 20000 - 17100 + 1, 1);
1356 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1357
1358 // If we repaint an opaque part of the tile, then it should lose its opaque- ness. But other tiles should still
1359 // not be affected.
1360 layer->fakeLayerUpdater()->setOpaquePaintRect(gfx::Rect());
1361 layer->InvalidateContentRect(gfx::Rect(10, 10, 1, 1));
1362 layer->SetTexturePriorities(m_priorityCalculator);
1363 m_resourceManager->prioritizeTextures();
1364 layer->Update(m_queue.get(), &occluded, NULL);
1365 updateTextures();
1366 opaqueContents = layer->VisibleContentOpaqueRegion();
1367 EXPECT_EQ(gfx::IntersectRects(gfx::Rect(10, 100, 90, 100), visibleBounds).To String(), opaqueContents.ToString());
1368
1369 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 20000 * 2 + 1 + 1, 1);
1370 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 17100, 1) ;
1371 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 2000 0 + 20000 - 17100 + 1 + 1, 1);
1372 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1373 }
1374
1375 TEST_F(TiledLayerTest, pixels_paintedMetrics)
1376 {
1377 scoped_refptr<FakeTiledLayer> layer = make_scoped_refptr(new FakeTiledLayer( m_resourceManager.get()));
1378 TestOcclusionTracker occluded;
1379 m_occlusion = &occluded;
1380 layer_tree_host_->SetViewportSize(gfx::Size(1000, 1000), gfx::Size(1000, 100 0));
1381
1382 // The tile size is 100x100, so this invalidates and then paints two tiles i n various ways.
1383
1384 gfx::Rect opaquePaintRect;
1385 Region opaqueContents;
1386
1387 gfx::Rect contentBounds = gfx::Rect(0, 0, 100, 300);
1388 layer->SetBounds(contentBounds.size());
1389 calcDrawProps(layer);
1390
1391 // Invalidates and paints the whole layer.
1392 layer->fakeLayerUpdater()->setOpaquePaintRect(gfx::Rect());
1393 layer->InvalidateContentRect(contentBounds);
1394 layer->SetTexturePriorities(m_priorityCalculator);
1395 m_resourceManager->prioritizeTextures();
1396 layer->Update(m_queue.get(), &occluded, NULL);
1397 updateTextures();
1398 opaqueContents = layer->VisibleContentOpaqueRegion();
1399 EXPECT_TRUE(opaqueContents.IsEmpty());
1400
1401 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 30000, 1);
1402 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1403 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 3000 0, 1);
1404 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1405
1406 // Invalidates an area on the top and bottom tile, which will cause us to pa int the tile in the middle,
1407 // even though it is not dirty and will not be uploaded.
1408 layer->fakeLayerUpdater()->setOpaquePaintRect(gfx::Rect());
1409 layer->InvalidateContentRect(gfx::Rect(0, 0, 1, 1));
1410 layer->InvalidateContentRect(gfx::Rect(50, 200, 10, 10));
1411 layer->SetTexturePriorities(m_priorityCalculator);
1412 m_resourceManager->prioritizeTextures();
1413 layer->Update(m_queue.get(), &occluded, NULL);
1414 updateTextures();
1415 opaqueContents = layer->VisibleContentOpaqueRegion();
1416 EXPECT_TRUE(opaqueContents.IsEmpty());
1417
1418 // The middle tile was painted even though not invalidated.
1419 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_painted(), 30000 + 60 * 210, 1);
1420 // The pixels uploaded will not include the non-invalidated tile in the midd le.
1421 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_opaque(), 0, 1);
1422 EXPECT_NEAR(occluded.overdraw_metrics()->pixels_uploaded_translucent(), 3000 0 + 1 + 100, 1);
1423 EXPECT_EQ(0, occluded.overdraw_metrics()->tiles_culled_for_upload());
1424 }
1425
1426 TEST_F(TiledLayerTest, dontAllocateContentsWhenTargetSurfaceCantBeAllocated)
1427 {
1428 // Tile size is 100x100.
1429 gfx::Rect rootRect(0, 0, 300, 200);
1430 gfx::Rect childRect(0, 0, 300, 100);
1431 gfx::Rect child2Rect(0, 100, 300, 100);
1432
1433 scoped_refptr<FakeTiledLayer> root = make_scoped_refptr(new FakeTiledLayer(l ayer_tree_host_->contents_texture_manager()));
1434 scoped_refptr<Layer> surface = Layer::Create();
1435 scoped_refptr<FakeTiledLayer> child = make_scoped_refptr(new FakeTiledLayer( layer_tree_host_->contents_texture_manager()));
1436 scoped_refptr<FakeTiledLayer> child2 = make_scoped_refptr(new FakeTiledLayer (layer_tree_host_->contents_texture_manager()));
1437
1438 root->SetBounds(rootRect.size());
1439 root->SetAnchorPoint(gfx::PointF());
1440 root->draw_properties().drawable_content_rect = rootRect;
1441 root->draw_properties().visible_content_rect = rootRect;
1442 root->AddChild(surface);
1443
1444 surface->SetForceRenderSurface(true);
1445 surface->SetAnchorPoint(gfx::PointF());
1446 surface->SetOpacity(0.5);
1447 surface->AddChild(child);
1448 surface->AddChild(child2);
1449
1450 child->SetBounds(childRect.size());
1451 child->SetAnchorPoint(gfx::PointF());
1452 child->SetPosition(childRect.origin());
1453 child->draw_properties().visible_content_rect = childRect;
1454 child->draw_properties().drawable_content_rect = rootRect;
1455
1456 child2->SetBounds(child2Rect.size());
1457 child2->SetAnchorPoint(gfx::PointF());
1458 child2->SetPosition(child2Rect.origin());
1459 child2->draw_properties().visible_content_rect = child2Rect;
1460 child2->draw_properties().drawable_content_rect = rootRect;
1461
1462 layer_tree_host_->SetRootLayer(root);
1463 layer_tree_host_->SetViewportSize(rootRect.size(), rootRect.size());
1464
1465 // With a huge memory limit, all layers should update and push their texture s.
1466 root->InvalidateContentRect(rootRect);
1467 child->InvalidateContentRect(childRect);
1468 child2->InvalidateContentRect(child2Rect);
1469 layer_tree_host_->UpdateLayers(m_queue.get(), std::numeric_limits<size_t>::m ax());
1470 {
1471 updateTextures();
1472 EXPECT_EQ(6, root->fakeLayerUpdater()->updateCount());
1473 EXPECT_EQ(3, child->fakeLayerUpdater()->updateCount());
1474 EXPECT_EQ(3, child2->fakeLayerUpdater()->updateCount());
1475 EXPECT_FALSE(m_queue->hasMoreUpdates());
1476
1477 root->fakeLayerUpdater()->clearUpdateCount();
1478 child->fakeLayerUpdater()->clearUpdateCount();
1479 child2->fakeLayerUpdater()->clearUpdateCount();
1480
1481 scoped_ptr<FakeTiledLayerImpl> rootImpl = make_scoped_ptr(new FakeTiledL ayerImpl(m_hostImpl->active_tree(), root->id()));
1482 scoped_ptr<FakeTiledLayerImpl> childImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), child->id()));
1483 scoped_ptr<FakeTiledLayerImpl> child2Impl = make_scoped_ptr(new FakeTile dLayerImpl(m_hostImpl->active_tree(), child2->id()));
1484 layerPushPropertiesTo(root.get(), rootImpl.get());
1485 layerPushPropertiesTo(child.get(), childImpl.get());
1486 layerPushPropertiesTo(child2.get(), child2Impl.get());
1487
1488 for (unsigned i = 0; i < 3; ++i) {
1489 for (unsigned j = 0; j < 2; ++j)
1490 EXPECT_TRUE(rootImpl->HasResourceIdForTileAt(i, j));
1491 EXPECT_TRUE(childImpl->HasResourceIdForTileAt(i, 0));
1492 EXPECT_TRUE(child2Impl->HasResourceIdForTileAt(i, 0));
1493 }
1494 }
1495 layer_tree_host_->CommitComplete();
1496
1497 // With a memory limit that includes only the root layer (3x2 tiles) and hal f the surface that
1498 // the child layers draw into, the child layers will not be allocated. If th e surface isn't
1499 // accounted for, then one of the children would fit within the memory limit .
1500 root->InvalidateContentRect(rootRect);
1501 child->InvalidateContentRect(childRect);
1502 child2->InvalidateContentRect(child2Rect);
1503 layer_tree_host_->UpdateLayers(m_queue.get(), (3 * 2 + 3 * 1) * (100 * 100) * 4);
1504 {
1505 updateTextures();
1506 EXPECT_EQ(6, root->fakeLayerUpdater()->updateCount());
1507 EXPECT_EQ(0, child->fakeLayerUpdater()->updateCount());
1508 EXPECT_EQ(0, child2->fakeLayerUpdater()->updateCount());
1509 EXPECT_FALSE(m_queue->hasMoreUpdates());
1510
1511 root->fakeLayerUpdater()->clearUpdateCount();
1512 child->fakeLayerUpdater()->clearUpdateCount();
1513 child2->fakeLayerUpdater()->clearUpdateCount();
1514
1515 scoped_ptr<FakeTiledLayerImpl> rootImpl = make_scoped_ptr(new FakeTiledL ayerImpl(m_hostImpl->active_tree(), root->id()));
1516 scoped_ptr<FakeTiledLayerImpl> childImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), child->id()));
1517 scoped_ptr<FakeTiledLayerImpl> child2Impl = make_scoped_ptr(new FakeTile dLayerImpl(m_hostImpl->active_tree(), child2->id()));
1518 layerPushPropertiesTo(root.get(), rootImpl.get());
1519 layerPushPropertiesTo(child.get(), childImpl.get());
1520 layerPushPropertiesTo(child2.get(), child2Impl.get());
1521
1522 for (unsigned i = 0; i < 3; ++i) {
1523 for (unsigned j = 0; j < 2; ++j)
1524 EXPECT_TRUE(rootImpl->HasResourceIdForTileAt(i, j));
1525 EXPECT_FALSE(childImpl->HasResourceIdForTileAt(i, 0));
1526 EXPECT_FALSE(child2Impl->HasResourceIdForTileAt(i, 0));
1527 }
1528 }
1529 layer_tree_host_->CommitComplete();
1530
1531 // With a memory limit that includes only half the root layer, no contents w ill be
1532 // allocated. If render surface memory wasn't accounted for, there is enough space
1533 // for one of the children layers, but they draw into a surface that can't b e
1534 // allocated.
1535 root->InvalidateContentRect(rootRect);
1536 child->InvalidateContentRect(childRect);
1537 child2->InvalidateContentRect(child2Rect);
1538 layer_tree_host_->UpdateLayers(m_queue.get(), (3 * 1) * (100 * 100) * 4);
1539 {
1540 updateTextures();
1541 EXPECT_EQ(0, root->fakeLayerUpdater()->updateCount());
1542 EXPECT_EQ(0, child->fakeLayerUpdater()->updateCount());
1543 EXPECT_EQ(0, child2->fakeLayerUpdater()->updateCount());
1544 EXPECT_FALSE(m_queue->hasMoreUpdates());
1545
1546 root->fakeLayerUpdater()->clearUpdateCount();
1547 child->fakeLayerUpdater()->clearUpdateCount();
1548 child2->fakeLayerUpdater()->clearUpdateCount();
1549
1550 scoped_ptr<FakeTiledLayerImpl> rootImpl = make_scoped_ptr(new FakeTiledL ayerImpl(m_hostImpl->active_tree(), root->id()));
1551 scoped_ptr<FakeTiledLayerImpl> childImpl = make_scoped_ptr(new FakeTiled LayerImpl(m_hostImpl->active_tree(), child->id()));
1552 scoped_ptr<FakeTiledLayerImpl> child2Impl = make_scoped_ptr(new FakeTile dLayerImpl(m_hostImpl->active_tree(), child2->id()));
1553 layerPushPropertiesTo(root.get(), rootImpl.get());
1554 layerPushPropertiesTo(child.get(), childImpl.get());
1555 layerPushPropertiesTo(child2.get(), child2Impl.get());
1556
1557 for (unsigned i = 0; i < 3; ++i) {
1558 for (unsigned j = 0; j < 2; ++j)
1559 EXPECT_FALSE(rootImpl->HasResourceIdForTileAt(i, j));
1560 EXPECT_FALSE(childImpl->HasResourceIdForTileAt(i, 0));
1561 EXPECT_FALSE(child2Impl->HasResourceIdForTileAt(i, 0));
1562 }
1563 }
1564 layer_tree_host_->CommitComplete();
1565
1566 resourceManagerClearAllMemory(layer_tree_host_->contents_texture_manager(), m_resourceProvider.get());
1567 layer_tree_host_->SetRootLayer(NULL);
1568 }
1569
1570 class TrackingLayerPainter : public LayerPainter {
1571 public:
1572 static scoped_ptr<TrackingLayerPainter> Create() { return make_scoped_ptr(ne w TrackingLayerPainter()); }
1573
1574 virtual void Paint(SkCanvas* canvas, gfx::Rect content_rect, gfx::RectF* opa que) OVERRIDE
1575 {
1576 m_paintedRect = content_rect;
1577 }
1578
1579 const gfx::Rect& paintedRect() const { return m_paintedRect; }
1580 void resetPaintedRect() { m_paintedRect = gfx::Rect(); }
1581
1582 private:
1583 TrackingLayerPainter() { }
1584
1585 gfx::Rect m_paintedRect;
1586 };
1587
1588 class UpdateTrackingTiledLayer : public FakeTiledLayer {
1589 public:
1590 explicit UpdateTrackingTiledLayer(PrioritizedResourceManager* manager)
1591 : FakeTiledLayer(manager)
1592 {
1593 scoped_ptr<TrackingLayerPainter> trackingLayerPainter(TrackingLayerPaint er::Create());
1594 m_trackingLayerPainter = trackingLayerPainter.get();
1595 m_layerUpdater = BitmapContentLayerUpdater::Create(trackingLayerPainter. PassAs<LayerPainter>());
1596 }
1597
1598 TrackingLayerPainter* trackingLayerPainter() const { return m_trackingLayerP ainter; }
1599
1600 protected:
1601 virtual ~UpdateTrackingTiledLayer() { }
1602
1603 virtual LayerUpdater* Updater() const OVERRIDE { return m_layerUpdater.get() ; }
1604
1605 private:
1606 TrackingLayerPainter* m_trackingLayerPainter;
1607 scoped_refptr<BitmapContentLayerUpdater> m_layerUpdater;
1608 };
1609
1610 TEST_F(TiledLayerTest, nonIntegerContentsScaleIsNotDistortedDuringPaint)
1611 {
1612 scoped_refptr<UpdateTrackingTiledLayer> layer = make_scoped_refptr(new Updat eTrackingTiledLayer(m_resourceManager.get()));
1613
1614 gfx::Rect layerRect(0, 0, 30, 31);
1615 layer->SetPosition(layerRect.origin());
1616 layer->SetBounds(layerRect.size());
1617 layer->updateContentsScale(1.5);
1618
1619 gfx::Rect contentRect(0, 0, 45, 47);
1620 EXPECT_EQ(contentRect.size(), layer->content_bounds());
1621 layer->draw_properties().visible_content_rect = contentRect;
1622 layer->draw_properties().drawable_content_rect = contentRect;
1623
1624 layer->SetTexturePriorities(m_priorityCalculator);
1625 m_resourceManager->prioritizeTextures();
1626
1627 // Update the whole tile.
1628 layer->Update(m_queue.get(), 0, NULL);
1629 layer->trackingLayerPainter()->resetPaintedRect();
1630
1631 EXPECT_RECT_EQ(gfx::Rect(), layer->trackingLayerPainter()->paintedRect());
1632 updateTextures();
1633
1634 // Invalidate the entire layer in content space. When painting, the rect giv en to webkit should match the layer's bounds.
1635 layer->InvalidateContentRect(contentRect);
1636 layer->Update(m_queue.get(), 0, NULL);
1637
1638 EXPECT_RECT_EQ(layerRect, layer->trackingLayerPainter()->paintedRect());
1639 }
1640
1641 TEST_F(TiledLayerTest, nonIntegerContentsScaleIsNotDistortedDuringInvalidation)
1642 {
1643 scoped_refptr<UpdateTrackingTiledLayer> layer = make_scoped_refptr(new Updat eTrackingTiledLayer(m_resourceManager.get()));
1644
1645 gfx::Rect layerRect(0, 0, 30, 31);
1646 layer->SetPosition(layerRect.origin());
1647 layer->SetBounds(layerRect.size());
1648 layer->updateContentsScale(1.3f);
1649
1650 gfx::Rect contentRect(gfx::Point(), layer->content_bounds());
1651 layer->draw_properties().visible_content_rect = contentRect;
1652 layer->draw_properties().drawable_content_rect = contentRect;
1653
1654 layer->SetTexturePriorities(m_priorityCalculator);
1655 m_resourceManager->prioritizeTextures();
1656
1657 // Update the whole tile.
1658 layer->Update(m_queue.get(), 0, NULL);
1659 layer->trackingLayerPainter()->resetPaintedRect();
1660
1661 EXPECT_RECT_EQ(gfx::Rect(), layer->trackingLayerPainter()->paintedRect());
1662 updateTextures();
1663
1664 // Invalidate the entire layer in layer space. When painting, the rect given to webkit should match the layer's bounds.
1665 layer->SetNeedsDisplayRect(layerRect);
1666 layer->Update(m_queue.get(), 0, NULL);
1667
1668 EXPECT_RECT_EQ(layerRect, layer->trackingLayerPainter()->paintedRect());
1669 }
1670
1671 } // namespace
1672 } // namespace cc
OLDNEW
« no previous file with comments | « cc/tiled_layer_impl_unittest.cc ('k') | cc/trees/damage_tracker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698