OLD | NEW |
| (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 | |
OLD | NEW |