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 "config.h" | |
6 | |
7 #include "TiledLayerChromium.h" | |
8 | |
9 #include "BitmapCanvasLayerTextureUpdater.h" | |
10 #include "CCAnimationTestCommon.h" | |
11 #include "CCGeometryTestUtils.h" | |
12 #include "CCOverdrawMetrics.h" | |
13 #include "CCRenderingStats.h" | |
14 #include "CCSingleThreadProxy.h" // For DebugScopedSetImplThread | |
15 #include "CCTextureUpdateController.h" | |
16 #include "CCTiledLayerTestCommon.h" | |
17 #include "FakeCCGraphicsContext.h" | |
18 #include "FakeCCLayerTreeHostClient.h" | |
19 #include "LayerPainterChromium.h" | |
20 #include <gtest/gtest.h> | |
21 #include <public/WebCompositor.h> | |
22 #include <public/WebTransformationMatrix.h> | |
23 | |
24 using namespace WebCore; | |
25 using namespace WebKitTests; | |
26 using namespace WTF; | |
27 using WebKit::WebTransformationMatrix; | |
28 | |
29 namespace { | |
30 | |
31 class TestCCOcclusionTracker : public CCOcclusionTracker { | |
32 public: | |
33 TestCCOcclusionTracker() | |
34 : CCOcclusionTracker(IntRect(0, 0, 1000, 1000), true) | |
35 , m_layerClipRectInTarget(IntRect(0, 0, 1000, 1000)) | |
36 { | |
37 // Pretend we have visited a render surface. | |
38 m_stack.append(StackObject()); | |
39 } | |
40 | |
41 void setOcclusion(const Region& occlusion) { m_stack.last().occlusionInScree
n = occlusion; } | |
42 | |
43 protected: | |
44 virtual IntRect layerClipRectInTarget(const LayerChromium* layer) const OVER
RIDE { return m_layerClipRectInTarget; } | |
45 | |
46 private: | |
47 IntRect m_layerClipRectInTarget; | |
48 }; | |
49 | |
50 class TiledLayerChromiumTest : public testing::Test { | |
51 public: | |
52 TiledLayerChromiumTest() | |
53 : m_context(WebKit::createFakeCCGraphicsContext()) | |
54 , m_textureManager(CCPrioritizedTextureManager::create(60*1024*1024, 102
4, CCRenderer::ContentPool)) | |
55 , m_occlusion(0) | |
56 { | |
57 WebKit::WebCompositor::initialize(0); | |
58 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked; | |
59 m_resourceProvider = CCResourceProvider::create(m_context.get()); | |
60 } | |
61 | |
62 virtual ~TiledLayerChromiumTest() | |
63 { | |
64 textureManagerClearAllMemory(m_textureManager.get(), m_resourceProvider.
get()); | |
65 { | |
66 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThread
Blocked; | |
67 m_resourceProvider.clear(); | |
68 } | |
69 WebKit::WebCompositor::shutdown(); | |
70 } | |
71 | |
72 // Helper classes and functions that set the current thread to be the impl t
hread | |
73 // before doing the action that they wrap. | |
74 class ScopedFakeCCTiledLayerImpl { | |
75 public: | |
76 ScopedFakeCCTiledLayerImpl(int id) | |
77 { | |
78 DebugScopedSetImplThread implThread; | |
79 m_layerImpl = new FakeCCTiledLayerImpl(id); | |
80 } | |
81 ~ScopedFakeCCTiledLayerImpl() | |
82 { | |
83 DebugScopedSetImplThread implThread; | |
84 delete m_layerImpl; | |
85 } | |
86 FakeCCTiledLayerImpl* get() | |
87 { | |
88 return m_layerImpl; | |
89 } | |
90 FakeCCTiledLayerImpl* operator->() | |
91 { | |
92 return m_layerImpl; | |
93 } | |
94 private: | |
95 FakeCCTiledLayerImpl* m_layerImpl; | |
96 }; | |
97 void textureManagerClearAllMemory(CCPrioritizedTextureManager* textureManage
r, CCResourceProvider* resourceProvider) | |
98 { | |
99 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked; | |
100 textureManager->clearAllMemory(resourceProvider); | |
101 } | |
102 void updateTextures(int count = 500) | |
103 { | |
104 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked; | |
105 CCTextureUpdateController::updateTextures(m_resourceProvider.get(), &m_c
opier, &m_uploader, &m_queue, count); | |
106 } | |
107 void layerPushPropertiesTo(FakeTiledLayerChromium* layer, FakeCCTiledLayerIm
pl* layerImpl) | |
108 { | |
109 DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBloc
ked; | |
110 layer->pushPropertiesTo(layerImpl); | |
111 } | |
112 void layerUpdate(FakeTiledLayerChromium* layer, TestCCOcclusionTracker* occl
uded) | |
113 { | |
114 DebugScopedSetMainThread mainThread; | |
115 layer->update(m_queue, occluded, m_stats); | |
116 } | |
117 | |
118 bool updateAndPush(FakeTiledLayerChromium* layer1, | |
119 FakeCCTiledLayerImpl* layerImpl1, | |
120 FakeTiledLayerChromium* layer2 = 0, | |
121 FakeCCTiledLayerImpl* layerImpl2 = 0) | |
122 { | |
123 // Get textures | |
124 m_textureManager->clearPriorities(); | |
125 if (layer1) | |
126 layer1->setTexturePriorities(m_priorityCalculator); | |
127 if (layer2) | |
128 layer2->setTexturePriorities(m_priorityCalculator); | |
129 m_textureManager->prioritizeTextures(); | |
130 | |
131 // Update content | |
132 if (layer1) | |
133 layer1->update(m_queue, m_occlusion, m_stats); | |
134 if (layer2) | |
135 layer2->update(m_queue, m_occlusion, m_stats); | |
136 | |
137 bool needsUpdate = false; | |
138 if (layer1) | |
139 needsUpdate |= layer1->needsIdlePaint(); | |
140 if (layer2) | |
141 needsUpdate |= layer2->needsIdlePaint(); | |
142 | |
143 // Update textures and push. | |
144 updateTextures(); | |
145 if (layer1) | |
146 layerPushPropertiesTo(layer1, layerImpl1); | |
147 if (layer2) | |
148 layerPushPropertiesTo(layer2, layerImpl2); | |
149 | |
150 return needsUpdate; | |
151 } | |
152 | |
153 public: | |
154 OwnPtr<CCGraphicsContext> m_context; | |
155 OwnPtr<CCResourceProvider> m_resourceProvider; | |
156 CCTextureUpdateQueue m_queue; | |
157 CCRenderingStats m_stats; | |
158 FakeTextureCopier m_copier; | |
159 FakeTextureUploader m_uploader; | |
160 CCPriorityCalculator m_priorityCalculator; | |
161 OwnPtr<CCPrioritizedTextureManager> m_textureManager; | |
162 TestCCOcclusionTracker* m_occlusion; | |
163 }; | |
164 | |
165 TEST_F(TiledLayerChromiumTest, pushDirtyTiles) | |
166 { | |
167 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
168 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
169 | |
170 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
171 layer->setBounds(IntSize(100, 200)); | |
172 layer->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
173 layer->invalidateContentRect(IntRect(0, 0, 100, 200)); | |
174 updateAndPush(layer.get(), layerImpl.get()); | |
175 | |
176 // We should have both tiles on the impl side. | |
177 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
178 EXPECT_TRUE(layerImpl->hasTileAt(0, 1)); | |
179 | |
180 // Invalidates both tiles, but then only update one of them. | |
181 layer->setBounds(IntSize(100, 200)); | |
182 layer->setVisibleContentRect(IntRect(0, 0, 100, 100)); | |
183 layer->invalidateContentRect(IntRect(0, 0, 100, 200)); | |
184 updateAndPush(layer.get(), layerImpl.get()); | |
185 | |
186 // We should only have the first tile since the other tile was invalidated b
ut not painted. | |
187 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
188 EXPECT_FALSE(layerImpl->hasTileAt(0, 1)); | |
189 } | |
190 | |
191 TEST_F(TiledLayerChromiumTest, pushOccludedDirtyTiles) | |
192 { | |
193 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
194 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
195 TestCCOcclusionTracker occluded; | |
196 m_occlusion = &occluded; | |
197 | |
198 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
199 layer->setBounds(IntSize(100, 200)); | |
200 layer->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
201 layer->invalidateContentRect(IntRect(0, 0, 100, 200)); | |
202 updateAndPush(layer.get(), layerImpl.get()); | |
203 | |
204 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
205 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000, 1
); | |
206 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
207 | |
208 // We should have both tiles on the impl side. | |
209 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
210 EXPECT_TRUE(layerImpl->hasTileAt(0, 1)); | |
211 | |
212 // Invalidates part of the top tile... | |
213 layer->invalidateContentRect(IntRect(0, 0, 50, 50)); | |
214 // ....but the area is occluded. | |
215 occluded.setOcclusion(IntRect(0, 0, 50, 50)); | |
216 updateAndPush(layer.get(), layerImpl.get()); | |
217 | |
218 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
219 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 +
2500, 1); | |
220 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
221 | |
222 // We should still have both tiles, as part of the top tile is still unocclu
ded. | |
223 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
224 EXPECT_TRUE(layerImpl->hasTileAt(0, 1)); | |
225 } | |
226 | |
227 TEST_F(TiledLayerChromiumTest, pushDeletedTiles) | |
228 { | |
229 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
230 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
231 | |
232 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
233 layer->setBounds(IntSize(100, 200)); | |
234 layer->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
235 layer->invalidateContentRect(IntRect(0, 0, 100, 200)); | |
236 updateAndPush(layer.get(), layerImpl.get()); | |
237 | |
238 // We should have both tiles on the impl side. | |
239 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
240 EXPECT_TRUE(layerImpl->hasTileAt(0, 1)); | |
241 | |
242 m_textureManager->clearPriorities(); | |
243 textureManagerClearAllMemory(m_textureManager.get(), m_resourceProvider.get(
)); | |
244 m_textureManager->setMaxMemoryLimitBytes(4*1024*1024); | |
245 | |
246 // This should drop the tiles on the impl thread. | |
247 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
248 | |
249 // We should now have no textures on the impl thread. | |
250 EXPECT_FALSE(layerImpl->hasTileAt(0, 0)); | |
251 EXPECT_FALSE(layerImpl->hasTileAt(0, 1)); | |
252 | |
253 // This should recreate and update one of the deleted textures. | |
254 layer->setVisibleContentRect(IntRect(0, 0, 100, 100)); | |
255 updateAndPush(layer.get(), layerImpl.get()); | |
256 | |
257 // We should have one tiles on the impl side. | |
258 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
259 EXPECT_FALSE(layerImpl->hasTileAt(0, 1)); | |
260 } | |
261 | |
262 TEST_F(TiledLayerChromiumTest, pushIdlePaintTiles) | |
263 { | |
264 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
265 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
266 | |
267 // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the ce
nter. | |
268 // This paints 1 visible of the 25 invalid tiles. | |
269 layer->setBounds(IntSize(500, 500)); | |
270 layer->setVisibleContentRect(IntRect(200, 200, 100, 100)); | |
271 layer->invalidateContentRect(IntRect(0, 0, 500, 500)); | |
272 bool needsUpdate = updateAndPush(layer.get(), layerImpl.get()); | |
273 // We should need idle-painting for surrounding tiles. | |
274 EXPECT_TRUE(needsUpdate); | |
275 | |
276 // We should have one tile on the impl side. | |
277 EXPECT_TRUE(layerImpl->hasTileAt(2, 2)); | |
278 | |
279 // For the next four updates, we should detect we still need idle painting. | |
280 for (int i = 0; i < 4; i++) { | |
281 needsUpdate = updateAndPush(layer.get(), layerImpl.get()); | |
282 EXPECT_TRUE(needsUpdate); | |
283 } | |
284 | |
285 // We should have one tile surrounding the visible tile on all sides, but no
other tiles. | |
286 IntRect idlePaintTiles(1, 1, 3, 3); | |
287 for (int i = 0; i < 5; i++) { | |
288 for (int j = 0; j < 5; j++) | |
289 EXPECT_EQ(layerImpl->hasTileAt(i, j), idlePaintTiles.contains(i, j))
; | |
290 } | |
291 | |
292 // We should always finish painting eventually. | |
293 for (int i = 0; i < 20; i++) | |
294 needsUpdate = updateAndPush(layer.get(), layerImpl.get()); | |
295 EXPECT_FALSE(needsUpdate); | |
296 } | |
297 | |
298 TEST_F(TiledLayerChromiumTest, pushTilesAfterIdlePaintFailed) | |
299 { | |
300 // 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. | |
301 m_textureManager->setMaxMemoryLimitBytes(2 * 1024 * 1024); | |
302 RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(
m_textureManager.get())); | |
303 ScopedFakeCCTiledLayerImpl layerImpl1(1); | |
304 RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(
m_textureManager.get())); | |
305 ScopedFakeCCTiledLayerImpl layerImpl2(2); | |
306 | |
307 // For this test we have two layers. layer1 exhausts most texture memory, le
aving room for 2 more tiles from | |
308 // layer2, but not all three tiles. First we paint layer1, and one tile from
layer2. Then when we idle paint | |
309 // layer2, we will fail on the third tile of layer2, and this should not lea
ve the second tile in a bad state. | |
310 | |
311 // This uses 960000 bytes, leaving 88576 bytes of memory left, which is enou
gh for 2 tiles only in the other layer. | |
312 IntRect layer1Rect(0, 0, 100, 2400); | |
313 | |
314 // This requires 4*30000 bytes of memory. | |
315 IntRect layer2Rect(0, 0, 100, 300); | |
316 | |
317 // Paint a single tile in layer2 so that it will idle paint. | |
318 layer1->setBounds(layer1Rect.size()); | |
319 layer1->setVisibleContentRect(layer1Rect); | |
320 layer2->setBounds(layer2Rect.size()); | |
321 layer2->setVisibleContentRect(IntRect(0, 0, 100, 100)); | |
322 bool needsUpdate = updateAndPush(layer1.get(), layerImpl1.get(), | |
323 layer2.get(), layerImpl2.get()); | |
324 // We should need idle-painting for both remaining tiles in layer2. | |
325 EXPECT_TRUE(needsUpdate); | |
326 | |
327 // Reduce our memory limits to 1mb. | |
328 m_textureManager->setMaxMemoryLimitBytes(1024 * 1024); | |
329 | |
330 // Now idle paint layer2. We are going to run out of memory though! | |
331 // Oh well, commit the frame and push. | |
332 for (int i = 0; i < 4; i++) { | |
333 needsUpdate = updateAndPush(layer1.get(), layerImpl1.get(), | |
334 layer2.get(), layerImpl2.get()); | |
335 } | |
336 | |
337 // Sanity check, we should have textures for the big layer. | |
338 EXPECT_TRUE(layerImpl1->hasTextureIdForTileAt(0, 0)); | |
339 EXPECT_TRUE(layerImpl1->hasTextureIdForTileAt(0, 23)); | |
340 | |
341 // We should only have the first two tiles from layer2 since | |
342 // it failed to idle update the last tile. | |
343 EXPECT_TRUE(layerImpl2->hasTileAt(0, 0)); | |
344 EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 0)); | |
345 EXPECT_TRUE(layerImpl2->hasTileAt(0, 1)); | |
346 EXPECT_TRUE(layerImpl2->hasTextureIdForTileAt(0, 1)); | |
347 | |
348 EXPECT_FALSE(needsUpdate); | |
349 EXPECT_FALSE(layerImpl2->hasTileAt(0, 2)); | |
350 } | |
351 | |
352 TEST_F(TiledLayerChromiumTest, pushIdlePaintedOccludedTiles) | |
353 { | |
354 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
355 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
356 TestCCOcclusionTracker occluded; | |
357 m_occlusion = &occluded; | |
358 | |
359 // The tile size is 100x100, so this invalidates one occluded tile, culls it
during paint, but prepaints it. | |
360 occluded.setOcclusion(IntRect(0, 0, 100, 100)); | |
361 | |
362 layer->setBounds(IntSize(100, 100)); | |
363 layer->setVisibleContentRect(IntRect(0, 0, 100, 100)); | |
364 updateAndPush(layer.get(), layerImpl.get()); | |
365 | |
366 // We should have the prepainted tile on the impl side, but culled it during
paint. | |
367 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
368 EXPECT_EQ(1, occluded.overdrawMetrics().tilesCulledForUpload()); | |
369 } | |
370 | |
371 TEST_F(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint) | |
372 { | |
373 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
374 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
375 | |
376 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
377 // However, during the paint, we invalidate one of the tiles. This should | |
378 // not prevent the tile from being pushed. | |
379 layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50
), layer.get()); | |
380 layer->setBounds(IntSize(100, 200)); | |
381 layer->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
382 updateAndPush(layer.get(), layerImpl.get()); | |
383 | |
384 // We should have both tiles on the impl side. | |
385 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
386 EXPECT_TRUE(layerImpl->hasTileAt(0, 1)); | |
387 } | |
388 | |
389 TEST_F(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnNextLayer) | |
390 { | |
391 RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(
m_textureManager.get())); | |
392 RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(
m_textureManager.get())); | |
393 ScopedFakeCCTiledLayerImpl layer1Impl(1); | |
394 ScopedFakeCCTiledLayerImpl layer2Impl(2); | |
395 | |
396 // Invalidate a tile on layer1, during update of layer 2. | |
397 layer2->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 5
0), layer1.get()); | |
398 layer1->setBounds(IntSize(100, 200)); | |
399 layer1->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
400 layer2->setBounds(IntSize(100, 200)); | |
401 layer2->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
402 updateAndPush(layer1.get(), layer1Impl.get(), | |
403 layer2.get(), layer2Impl.get()); | |
404 | |
405 // We should have both tiles on the impl side for all layers. | |
406 EXPECT_TRUE(layer1Impl->hasTileAt(0, 0)); | |
407 EXPECT_TRUE(layer1Impl->hasTileAt(0, 1)); | |
408 EXPECT_TRUE(layer2Impl->hasTileAt(0, 0)); | |
409 EXPECT_TRUE(layer2Impl->hasTileAt(0, 1)); | |
410 } | |
411 | |
412 TEST_F(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnPreviousLay
er) | |
413 { | |
414 RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(
m_textureManager.get())); | |
415 RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(
m_textureManager.get())); | |
416 ScopedFakeCCTiledLayerImpl layer1Impl(1); | |
417 ScopedFakeCCTiledLayerImpl layer2Impl(2); | |
418 | |
419 layer1->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 5
0), layer2.get()); | |
420 layer1->setBounds(IntSize(100, 200)); | |
421 layer1->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
422 layer2->setBounds(IntSize(100, 200)); | |
423 layer2->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
424 updateAndPush(layer1.get(), layer1Impl.get(), | |
425 layer2.get(), layer2Impl.get()); | |
426 | |
427 // We should have both tiles on the impl side for all layers. | |
428 EXPECT_TRUE(layer1Impl->hasTileAt(0, 0)); | |
429 EXPECT_TRUE(layer1Impl->hasTileAt(0, 1)); | |
430 EXPECT_TRUE(layer2Impl->hasTileAt(0, 0)); | |
431 EXPECT_TRUE(layer2Impl->hasTileAt(0, 1)); | |
432 } | |
433 | |
434 TEST_F(TiledLayerChromiumTest, paintSmallAnimatedLayersImmediately) | |
435 { | |
436 // Create a CCLayerTreeHost that has the right viewportsize, | |
437 // so the layer is considered small enough. | |
438 FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient; | |
439 OwnPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLay
erTreeHostClient, CCLayerTreeSettings()); | |
440 | |
441 bool runOutOfMemory[2] = {false, true}; | |
442 for (int i = 0; i < 2; i++) { | |
443 // Create a layer with 4x4 tiles. | |
444 int layerWidth = 4 * FakeTiledLayerChromium::tileSize().width(); | |
445 int layerHeight = 4 * FakeTiledLayerChromium::tileSize().height(); | |
446 int memoryForLayer = layerWidth * layerHeight * 4; | |
447 IntSize viewportSize = IntSize(layerWidth, layerHeight); | |
448 ccLayerTreeHost->setViewportSize(viewportSize, viewportSize); | |
449 | |
450 // Use 8x4 tiles to run out of memory. | |
451 if (runOutOfMemory[i]) | |
452 layerWidth *= 2; | |
453 | |
454 m_textureManager->setMaxMemoryLimitBytes(memoryForLayer); | |
455 | |
456 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromi
um(m_textureManager.get())); | |
457 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
458 | |
459 // Full size layer with half being visible. | |
460 IntSize contentBounds(layerWidth, layerHeight); | |
461 IntRect contentRect(IntPoint::zero(), contentBounds); | |
462 IntRect visibleRect(IntPoint::zero(), IntSize(layerWidth / 2, layerHeigh
t)); | |
463 | |
464 // Pretend the layer is animating. | |
465 layer->setDrawTransformIsAnimating(true); | |
466 layer->setBounds(contentBounds); | |
467 layer->setVisibleContentRect(visibleRect); | |
468 layer->invalidateContentRect(contentRect); | |
469 layer->setLayerTreeHost(ccLayerTreeHost.get()); | |
470 | |
471 // The layer should paint it's entire contents on the first paint | |
472 // if it is close to the viewport size and has the available memory. | |
473 layer->setTexturePriorities(m_priorityCalculator); | |
474 m_textureManager->prioritizeTextures(); | |
475 layer->update(m_queue, 0, m_stats); | |
476 updateTextures(); | |
477 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
478 | |
479 // We should have all the tiles for the small animated layer. | |
480 // We should still have the visible tiles when we didn't | |
481 // have enough memory for all the tiles. | |
482 if (!runOutOfMemory[i]) { | |
483 for (int i = 0; i < 4; ++i) { | |
484 for (int j = 0; j < 4; ++j) | |
485 EXPECT_TRUE(layerImpl->hasTileAt(i, j)); | |
486 } | |
487 } else { | |
488 for (int i = 0; i < 8; ++i) { | |
489 for (int j = 0; j < 4; ++j) | |
490 EXPECT_EQ(layerImpl->hasTileAt(i, j), i < 4); | |
491 } | |
492 } | |
493 } | |
494 ccLayerTreeHost.clear(); | |
495 } | |
496 | |
497 TEST_F(TiledLayerChromiumTest, idlePaintOutOfMemory) | |
498 { | |
499 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
500 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
501 | |
502 // We have enough memory for only the visible rect, so we will run out of me
mory in first idle paint. | |
503 int memoryLimit = 4 * 100 * 100; // 1 tiles, 4 bytes per pixel. | |
504 m_textureManager->setMaxMemoryLimitBytes(memoryLimit); | |
505 | |
506 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
507 bool needsUpdate = false; | |
508 layer->setBounds(IntSize(300, 300)); | |
509 layer->setVisibleContentRect(IntRect(100, 100, 100, 100)); | |
510 for (int i = 0; i < 2; i++) | |
511 needsUpdate = updateAndPush(layer.get(), layerImpl.get()); | |
512 | |
513 // Idle-painting should see no more priority tiles for painting. | |
514 EXPECT_FALSE(needsUpdate); | |
515 | |
516 // We should have one tile on the impl side. | |
517 EXPECT_TRUE(layerImpl->hasTileAt(1, 1)); | |
518 } | |
519 | |
520 TEST_F(TiledLayerChromiumTest, idlePaintZeroSizedLayer) | |
521 { | |
522 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
523 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
524 | |
525 bool animating[2] = {false, true}; | |
526 for (int i = 0; i < 2; i++) { | |
527 // Pretend the layer is animating. | |
528 layer->setDrawTransformIsAnimating(animating[i]); | |
529 | |
530 // The layer's bounds are empty. | |
531 // Empty layers don't paint or idle-paint. | |
532 layer->setBounds(IntSize()); | |
533 layer->setVisibleContentRect(IntRect()); | |
534 bool needsUpdate = updateAndPush(layer.get(), layerImpl.get()); | |
535 | |
536 // Empty layers don't have tiles. | |
537 EXPECT_EQ(0u, layer->numPaintedTiles()); | |
538 | |
539 // Empty layers don't need prepaint. | |
540 EXPECT_FALSE(needsUpdate); | |
541 | |
542 // Empty layers don't have tiles. | |
543 EXPECT_FALSE(layerImpl->hasTileAt(0, 0)); | |
544 } | |
545 } | |
546 | |
547 TEST_F(TiledLayerChromiumTest, idlePaintNonVisibleLayers) | |
548 { | |
549 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
550 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
551 | |
552 // Alternate between not visible and visible. | |
553 IntRect v(0, 0, 100, 100); | |
554 IntRect nv(0, 0, 0, 0); | |
555 IntRect visibleRect[10] = {nv, nv, v, v, nv, nv, v, v, nv, nv}; | |
556 bool invalidate[10] = {true, true, true, true, true, true, true, true, fals
e, false }; | |
557 | |
558 // We should not have any tiles except for when the layer was visible | |
559 // or after the layer was visible and we didn't invalidate. | |
560 bool haveTile[10] = { false, false, true, true, false, false, true, true, tr
ue, true }; | |
561 | |
562 for (int i = 0; i < 10; i++) { | |
563 layer->setBounds(IntSize(100, 100)); | |
564 layer->setVisibleContentRect(visibleRect[i]); | |
565 | |
566 if (invalidate[i]) | |
567 layer->invalidateContentRect(IntRect(0, 0, 100, 100)); | |
568 bool needsUpdate = updateAndPush(layer.get(), layerImpl.get()); | |
569 | |
570 // We should never signal idle paint, as we painted the entire layer | |
571 // or the layer was not visible. | |
572 EXPECT_FALSE(needsUpdate); | |
573 EXPECT_EQ(layerImpl->hasTileAt(0, 0), haveTile[i]); | |
574 } | |
575 } | |
576 | |
577 TEST_F(TiledLayerChromiumTest, invalidateFromPrepare) | |
578 { | |
579 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
580 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
581 | |
582 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
583 layer->setBounds(IntSize(100, 200)); | |
584 layer->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
585 updateAndPush(layer.get(), layerImpl.get()); | |
586 | |
587 // We should have both tiles on the impl side. | |
588 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
589 EXPECT_TRUE(layerImpl->hasTileAt(0, 1)); | |
590 | |
591 layer->fakeLayerTextureUpdater()->clearPrepareCount(); | |
592 // Invoke update again. As the layer is valid update shouldn't be invoked on | |
593 // the LayerTextureUpdater. | |
594 updateAndPush(layer.get(), layerImpl.get()); | |
595 EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareCount()); | |
596 | |
597 // setRectToInvalidate triggers invalidateContentRect() being invoked from u
pdate. | |
598 layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(25, 25, 50, 50
), layer.get()); | |
599 layer->fakeLayerTextureUpdater()->clearPrepareCount(); | |
600 layer->invalidateContentRect(IntRect(0, 0, 50, 50)); | |
601 updateAndPush(layer.get(), layerImpl.get()); | |
602 EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount()); | |
603 layer->fakeLayerTextureUpdater()->clearPrepareCount(); | |
604 | |
605 // The layer should still be invalid as update invoked invalidate. | |
606 updateAndPush(layer.get(), layerImpl.get()); // visible | |
607 EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount()); | |
608 } | |
609 | |
610 TEST_F(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled) | |
611 { | |
612 // The updateRect (that indicates what was actually painted) should be in | |
613 // layer space, not the content space. | |
614 RefPtr<FakeTiledLayerWithScaledBounds> layer = adoptRef(new FakeTiledLayerWi
thScaledBounds(m_textureManager.get())); | |
615 | |
616 IntRect layerBounds(0, 0, 300, 200); | |
617 IntRect contentBounds(0, 0, 200, 250); | |
618 | |
619 layer->setBounds(layerBounds.size()); | |
620 layer->setContentBounds(contentBounds.size()); | |
621 layer->setVisibleContentRect(contentBounds); | |
622 | |
623 // On first update, the updateRect includes all tiles, even beyond the bound
aries of the layer. | |
624 // However, it should still be in layer space, not content space. | |
625 layer->invalidateContentRect(contentBounds); | |
626 | |
627 layer->setTexturePriorities(m_priorityCalculator); | |
628 m_textureManager->prioritizeTextures(); | |
629 layer->update(m_queue, 0, m_stats); | |
630 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 300, 300 * 0.8), layer->updateRect()); | |
631 updateTextures(); | |
632 | |
633 // After the tiles are updated once, another invalidate only needs to update
the bounds of the layer. | |
634 layer->setTexturePriorities(m_priorityCalculator); | |
635 m_textureManager->prioritizeTextures(); | |
636 layer->invalidateContentRect(contentBounds); | |
637 layer->update(m_queue, 0, m_stats); | |
638 EXPECT_FLOAT_RECT_EQ(FloatRect(layerBounds), layer->updateRect()); | |
639 updateTextures(); | |
640 | |
641 // Partial re-paint should also be represented by the updateRect in layer sp
ace, not content space. | |
642 IntRect partialDamage(30, 100, 10, 10); | |
643 layer->invalidateContentRect(partialDamage); | |
644 layer->setTexturePriorities(m_priorityCalculator); | |
645 m_textureManager->prioritizeTextures(); | |
646 layer->update(m_queue, 0, m_stats); | |
647 EXPECT_FLOAT_RECT_EQ(FloatRect(45, 80, 15, 8), layer->updateRect()); | |
648 } | |
649 | |
650 TEST_F(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges) | |
651 { | |
652 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
653 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
654 | |
655 // Create a layer with one tile. | |
656 layer->setBounds(IntSize(100, 100)); | |
657 layer->setVisibleContentRect(IntRect(0, 0, 100, 100)); | |
658 | |
659 // Invalidate the entire layer. | |
660 layer->setNeedsDisplay(); | |
661 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect(
)); | |
662 | |
663 // Push the tiles to the impl side and check that there is exactly one. | |
664 layer->setTexturePriorities(m_priorityCalculator); | |
665 m_textureManager->prioritizeTextures(); | |
666 layer->update(m_queue, 0, m_stats); | |
667 updateTextures(); | |
668 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
669 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
670 EXPECT_FALSE(layerImpl->hasTileAt(0, 1)); | |
671 EXPECT_FALSE(layerImpl->hasTileAt(1, 0)); | |
672 EXPECT_FALSE(layerImpl->hasTileAt(1, 1)); | |
673 | |
674 // Change the contents scale and verify that the content rectangle requiring
painting | |
675 // is not scaled. | |
676 layer->setContentsScale(2); | |
677 layer->setVisibleContentRect(IntRect(0, 0, 200, 200)); | |
678 EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect(
)); | |
679 | |
680 // The impl side should get 2x2 tiles now. | |
681 layer->setTexturePriorities(m_priorityCalculator); | |
682 m_textureManager->prioritizeTextures(); | |
683 layer->update(m_queue, 0, m_stats); | |
684 updateTextures(); | |
685 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
686 EXPECT_TRUE(layerImpl->hasTileAt(0, 0)); | |
687 EXPECT_TRUE(layerImpl->hasTileAt(0, 1)); | |
688 EXPECT_TRUE(layerImpl->hasTileAt(1, 0)); | |
689 EXPECT_TRUE(layerImpl->hasTileAt(1, 1)); | |
690 | |
691 // Invalidate the entire layer again, but do not paint. All tiles should be
gone now from the | |
692 // impl side. | |
693 layer->setNeedsDisplay(); | |
694 layer->setTexturePriorities(m_priorityCalculator); | |
695 m_textureManager->prioritizeTextures(); | |
696 | |
697 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
698 EXPECT_FALSE(layerImpl->hasTileAt(0, 0)); | |
699 EXPECT_FALSE(layerImpl->hasTileAt(0, 1)); | |
700 EXPECT_FALSE(layerImpl->hasTileAt(1, 0)); | |
701 EXPECT_FALSE(layerImpl->hasTileAt(1, 1)); | |
702 } | |
703 | |
704 TEST_F(TiledLayerChromiumTest, skipsDrawGetsReset) | |
705 { | |
706 FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient; | |
707 OwnPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLay
erTreeHostClient, CCLayerTreeSettings()); | |
708 ASSERT_TRUE(ccLayerTreeHost->initializeRendererIfNeeded()); | |
709 | |
710 // Create two 300 x 300 tiled layers. | |
711 IntSize contentBounds(300, 300); | |
712 IntRect contentRect(IntPoint::zero(), contentBounds); | |
713 | |
714 // We have enough memory for only one of the two layers. | |
715 int memoryLimit = 4 * 300 * 300; // 4 bytes per pixel. | |
716 | |
717 RefPtr<FakeTiledLayerChromium> rootLayer = adoptRef(new FakeTiledLayerChromi
um(ccLayerTreeHost->contentsTextureManager())); | |
718 RefPtr<FakeTiledLayerChromium> childLayer = adoptRef(new FakeTiledLayerChrom
ium(ccLayerTreeHost->contentsTextureManager())); | |
719 rootLayer->addChild(childLayer); | |
720 | |
721 rootLayer->setBounds(contentBounds); | |
722 rootLayer->setVisibleContentRect(contentRect); | |
723 rootLayer->setPosition(FloatPoint(0, 0)); | |
724 childLayer->setBounds(contentBounds); | |
725 childLayer->setVisibleContentRect(contentRect); | |
726 childLayer->setPosition(FloatPoint(0, 0)); | |
727 rootLayer->invalidateContentRect(contentRect); | |
728 childLayer->invalidateContentRect(contentRect); | |
729 | |
730 ccLayerTreeHost->setRootLayer(rootLayer); | |
731 ccLayerTreeHost->setViewportSize(IntSize(300, 300), IntSize(300, 300)); | |
732 | |
733 ccLayerTreeHost->updateLayers(m_queue, memoryLimit); | |
734 | |
735 // We'll skip the root layer. | |
736 EXPECT_TRUE(rootLayer->skipsDraw()); | |
737 EXPECT_FALSE(childLayer->skipsDraw()); | |
738 | |
739 ccLayerTreeHost->commitComplete(); | |
740 | |
741 // Remove the child layer. | |
742 rootLayer->removeAllChildren(); | |
743 | |
744 ccLayerTreeHost->updateLayers(m_queue, memoryLimit); | |
745 EXPECT_FALSE(rootLayer->skipsDraw()); | |
746 | |
747 textureManagerClearAllMemory(ccLayerTreeHost->contentsTextureManager(), m_re
sourceProvider.get()); | |
748 ccLayerTreeHost->setRootLayer(0); | |
749 ccLayerTreeHost.clear(); | |
750 } | |
751 | |
752 TEST_F(TiledLayerChromiumTest, resizeToSmaller) | |
753 { | |
754 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
755 | |
756 layer->setBounds(IntSize(700, 700)); | |
757 layer->setVisibleContentRect(IntRect(0, 0, 700, 700)); | |
758 layer->invalidateContentRect(IntRect(0, 0, 700, 700)); | |
759 | |
760 layer->setTexturePriorities(m_priorityCalculator); | |
761 m_textureManager->prioritizeTextures(); | |
762 layer->update(m_queue, 0, m_stats); | |
763 | |
764 layer->setBounds(IntSize(200, 200)); | |
765 layer->invalidateContentRect(IntRect(0, 0, 200, 200)); | |
766 } | |
767 | |
768 TEST_F(TiledLayerChromiumTest, hugeLayerUpdateCrash) | |
769 { | |
770 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
771 | |
772 int size = 1 << 30; | |
773 layer->setBounds(IntSize(size, size)); | |
774 layer->setVisibleContentRect(IntRect(0, 0, 700, 700)); | |
775 layer->invalidateContentRect(IntRect(0, 0, size, size)); | |
776 | |
777 // Ensure no crash for bounds where size * size would overflow an int. | |
778 layer->setTexturePriorities(m_priorityCalculator); | |
779 m_textureManager->prioritizeTextures(); | |
780 layer->update(m_queue, 0, m_stats); | |
781 } | |
782 | |
783 TEST_F(TiledLayerChromiumTest, partialUpdates) | |
784 { | |
785 CCLayerTreeSettings settings; | |
786 settings.maxPartialTextureUpdates = 4; | |
787 | |
788 FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient; | |
789 OwnPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLay
erTreeHostClient, settings); | |
790 ASSERT_TRUE(ccLayerTreeHost->initializeRendererIfNeeded()); | |
791 | |
792 // Create one 300 x 200 tiled layer with 3 x 2 tiles. | |
793 IntSize contentBounds(300, 200); | |
794 IntRect contentRect(IntPoint::zero(), contentBounds); | |
795 | |
796 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(c
cLayerTreeHost->contentsTextureManager())); | |
797 layer->setBounds(contentBounds); | |
798 layer->setPosition(FloatPoint(0, 0)); | |
799 layer->setVisibleContentRect(contentRect); | |
800 layer->invalidateContentRect(contentRect); | |
801 | |
802 ccLayerTreeHost->setRootLayer(layer); | |
803 ccLayerTreeHost->setViewportSize(IntSize(300, 200), IntSize(300, 200)); | |
804 | |
805 // Full update of all 6 tiles. | |
806 ccLayerTreeHost->updateLayers(m_queue, std::numeric_limits<size_t>::max()); | |
807 { | |
808 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
809 updateTextures(4); | |
810 EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount()); | |
811 EXPECT_TRUE(m_queue.hasMoreUpdates()); | |
812 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
813 updateTextures(4); | |
814 EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount()); | |
815 EXPECT_FALSE(m_queue.hasMoreUpdates()); | |
816 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
817 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
818 } | |
819 ccLayerTreeHost->commitComplete(); | |
820 | |
821 // Full update of 3 tiles and partial update of 3 tiles. | |
822 layer->invalidateContentRect(IntRect(0, 0, 300, 150)); | |
823 ccLayerTreeHost->updateLayers(m_queue, std::numeric_limits<size_t>::max()); | |
824 { | |
825 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
826 updateTextures(4); | |
827 EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount()); | |
828 EXPECT_TRUE(m_queue.hasMoreUpdates()); | |
829 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
830 updateTextures(4); | |
831 EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount()); | |
832 EXPECT_FALSE(m_queue.hasMoreUpdates()); | |
833 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
834 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
835 } | |
836 ccLayerTreeHost->commitComplete(); | |
837 | |
838 // Partial update of 6 tiles. | |
839 layer->invalidateContentRect(IntRect(50, 50, 200, 100)); | |
840 { | |
841 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
842 ccLayerTreeHost->updateLayers(m_queue, std::numeric_limits<size_t>::max(
)); | |
843 updateTextures(4); | |
844 EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount()); | |
845 EXPECT_TRUE(m_queue.hasMoreUpdates()); | |
846 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
847 updateTextures(4); | |
848 EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount()); | |
849 EXPECT_FALSE(m_queue.hasMoreUpdates()); | |
850 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
851 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
852 } | |
853 ccLayerTreeHost->commitComplete(); | |
854 | |
855 // Checkerboard all tiles. | |
856 layer->invalidateContentRect(IntRect(0, 0, 300, 200)); | |
857 { | |
858 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
859 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
860 } | |
861 ccLayerTreeHost->commitComplete(); | |
862 | |
863 // Partial update of 6 checkerboard tiles. | |
864 layer->invalidateContentRect(IntRect(50, 50, 200, 100)); | |
865 { | |
866 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
867 ccLayerTreeHost->updateLayers(m_queue, std::numeric_limits<size_t>::max(
)); | |
868 updateTextures(4); | |
869 EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount()); | |
870 EXPECT_TRUE(m_queue.hasMoreUpdates()); | |
871 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
872 updateTextures(4); | |
873 EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount()); | |
874 EXPECT_FALSE(m_queue.hasMoreUpdates()); | |
875 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
876 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
877 } | |
878 ccLayerTreeHost->commitComplete(); | |
879 | |
880 // Partial update of 4 tiles. | |
881 layer->invalidateContentRect(IntRect(50, 50, 100, 100)); | |
882 { | |
883 ScopedFakeCCTiledLayerImpl layerImpl(1); | |
884 ccLayerTreeHost->updateLayers(m_queue, std::numeric_limits<size_t>::max(
)); | |
885 updateTextures(4); | |
886 EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount()); | |
887 EXPECT_FALSE(m_queue.hasMoreUpdates()); | |
888 layer->fakeLayerTextureUpdater()->clearUpdateCount(); | |
889 layerPushPropertiesTo(layer.get(), layerImpl.get()); | |
890 } | |
891 ccLayerTreeHost->commitComplete(); | |
892 | |
893 textureManagerClearAllMemory(ccLayerTreeHost->contentsTextureManager(), m_re
sourceProvider.get()); | |
894 ccLayerTreeHost->setRootLayer(0); | |
895 ccLayerTreeHost.clear(); | |
896 } | |
897 | |
898 TEST_F(TiledLayerChromiumTest, tilesPaintedWithoutOcclusion) | |
899 { | |
900 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
901 | |
902 // The tile size is 100x100, so this invalidates and then paints two tiles. | |
903 layer->setBounds(IntSize(100, 200)); | |
904 layer->setDrawableContentRect(IntRect(0, 0, 100, 200)); | |
905 layer->setVisibleContentRect(IntRect(0, 0, 100, 200)); | |
906 layer->invalidateContentRect(IntRect(0, 0, 100, 200)); | |
907 | |
908 layer->setTexturePriorities(m_priorityCalculator); | |
909 m_textureManager->prioritizeTextures(); | |
910 layer->update(m_queue, 0, m_stats); | |
911 EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
912 } | |
913 | |
914 TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusion) | |
915 { | |
916 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
917 TestCCOcclusionTracker occluded; | |
918 | |
919 // The tile size is 100x100. | |
920 | |
921 layer->setBounds(IntSize(600, 600)); | |
922 | |
923 occluded.setOcclusion(IntRect(200, 200, 300, 100)); | |
924 layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
925 layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
926 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
927 | |
928 layer->setTexturePriorities(m_priorityCalculator); | |
929 m_textureManager->prioritizeTextures(); | |
930 layer->update(m_queue, &occluded, m_stats); | |
931 EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
932 | |
933 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
934 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000,
1); | |
935 EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload()); | |
936 | |
937 layer->fakeLayerTextureUpdater()->clearPrepareRectCount(); | |
938 layer->setTexturePriorities(m_priorityCalculator); | |
939 m_textureManager->prioritizeTextures(); | |
940 | |
941 occluded.setOcclusion(IntRect(250, 200, 300, 100)); | |
942 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
943 layer->update(m_queue, &occluded, m_stats); | |
944 EXPECT_EQ(36-2, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
945 | |
946 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
947 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000 +
340000, 1); | |
948 EXPECT_EQ(3 + 2, occluded.overdrawMetrics().tilesCulledForUpload()); | |
949 | |
950 layer->fakeLayerTextureUpdater()->clearPrepareRectCount(); | |
951 layer->setTexturePriorities(m_priorityCalculator); | |
952 m_textureManager->prioritizeTextures(); | |
953 | |
954 occluded.setOcclusion(IntRect(250, 250, 300, 100)); | |
955 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
956 layer->update(m_queue, &occluded, m_stats); | |
957 EXPECT_EQ(36, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
958 | |
959 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
960 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000 +
340000 + 360000, 1); | |
961 EXPECT_EQ(3 + 2, occluded.overdrawMetrics().tilesCulledForUpload()); | |
962 } | |
963 | |
964 TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndVisiblityConstraints) | |
965 { | |
966 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
967 TestCCOcclusionTracker occluded; | |
968 | |
969 // The tile size is 100x100. | |
970 | |
971 layer->setBounds(IntSize(600, 600)); | |
972 | |
973 // The partially occluded tiles (by the 150 occlusion height) are visible be
yond the occlusion, so not culled. | |
974 occluded.setOcclusion(IntRect(200, 200, 300, 150)); | |
975 layer->setDrawableContentRect(IntRect(0, 0, 600, 360)); | |
976 layer->setVisibleContentRect(IntRect(0, 0, 600, 360)); | |
977 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
978 | |
979 layer->setTexturePriorities(m_priorityCalculator); | |
980 m_textureManager->prioritizeTextures(); | |
981 layer->update(m_queue, &occluded, m_stats); | |
982 EXPECT_EQ(24-3, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
983 | |
984 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
985 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000,
1); | |
986 EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload()); | |
987 | |
988 layer->fakeLayerTextureUpdater()->clearPrepareRectCount(); | |
989 | |
990 // Now the visible region stops at the edge of the occlusion so the partly v
isible tiles become fully occluded. | |
991 occluded.setOcclusion(IntRect(200, 200, 300, 150)); | |
992 layer->setDrawableContentRect(IntRect(0, 0, 600, 350)); | |
993 layer->setVisibleContentRect(IntRect(0, 0, 600, 350)); | |
994 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
995 layer->setTexturePriorities(m_priorityCalculator); | |
996 m_textureManager->prioritizeTextures(); | |
997 layer->update(m_queue, &occluded, m_stats); | |
998 EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
999 | |
1000 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1001 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000 +
180000, 1); | |
1002 EXPECT_EQ(3 + 6, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1003 | |
1004 layer->fakeLayerTextureUpdater()->clearPrepareRectCount(); | |
1005 | |
1006 // Now the visible region is even smaller than the occlusion, it should have
the same result. | |
1007 occluded.setOcclusion(IntRect(200, 200, 300, 150)); | |
1008 layer->setDrawableContentRect(IntRect(0, 0, 600, 340)); | |
1009 layer->setVisibleContentRect(IntRect(0, 0, 600, 340)); | |
1010 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
1011 layer->setTexturePriorities(m_priorityCalculator); | |
1012 m_textureManager->prioritizeTextures(); | |
1013 layer->update(m_queue, &occluded, m_stats); | |
1014 EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
1015 | |
1016 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1017 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 210000 +
180000 + 180000, 1); | |
1018 EXPECT_EQ(3 + 6 + 6, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1019 | |
1020 } | |
1021 | |
1022 TEST_F(TiledLayerChromiumTest, tilesNotPaintedWithoutInvalidation) | |
1023 { | |
1024 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
1025 TestCCOcclusionTracker occluded; | |
1026 | |
1027 // The tile size is 100x100. | |
1028 | |
1029 layer->setBounds(IntSize(600, 600)); | |
1030 | |
1031 occluded.setOcclusion(IntRect(200, 200, 300, 100)); | |
1032 layer->setDrawableContentRect(IntRect(0, 0, 600, 600)); | |
1033 layer->setVisibleContentRect(IntRect(0, 0, 600, 600)); | |
1034 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
1035 layer->setTexturePriorities(m_priorityCalculator); | |
1036 m_textureManager->prioritizeTextures(); | |
1037 layer->update(m_queue, &occluded, m_stats); | |
1038 EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
1039 { | |
1040 updateTextures(); | |
1041 } | |
1042 | |
1043 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1044 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000,
1); | |
1045 EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1046 | |
1047 layer->fakeLayerTextureUpdater()->clearPrepareRectCount(); | |
1048 layer->setTexturePriorities(m_priorityCalculator); | |
1049 m_textureManager->prioritizeTextures(); | |
1050 | |
1051 // Repaint without marking it dirty. The 3 culled tiles will be pre-painted
now. | |
1052 layer->update(m_queue, &occluded, m_stats); | |
1053 EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
1054 | |
1055 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1056 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000,
1); | |
1057 EXPECT_EQ(6, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1058 } | |
1059 | |
1060 TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndTransforms) | |
1061 { | |
1062 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
1063 TestCCOcclusionTracker occluded; | |
1064 | |
1065 // The tile size is 100x100. | |
1066 | |
1067 // This makes sure the painting works when the occluded region (in screen sp
ace) | |
1068 // is transformed differently than the layer. | |
1069 layer->setBounds(IntSize(600, 600)); | |
1070 WebTransformationMatrix screenTransform; | |
1071 screenTransform.scale(0.5); | |
1072 layer->setScreenSpaceTransform(screenTransform); | |
1073 layer->setDrawTransform(screenTransform); | |
1074 | |
1075 occluded.setOcclusion(IntRect(100, 100, 150, 50)); | |
1076 layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
1077 layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
1078 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
1079 layer->setTexturePriorities(m_priorityCalculator); | |
1080 m_textureManager->prioritizeTextures(); | |
1081 layer->update(m_queue, &occluded, m_stats); | |
1082 EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
1083 | |
1084 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1085 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 330000,
1); | |
1086 EXPECT_EQ(3, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1087 } | |
1088 | |
1089 TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling) | |
1090 { | |
1091 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
1092 TestCCOcclusionTracker occluded; | |
1093 | |
1094 // The tile size is 100x100. | |
1095 | |
1096 // This makes sure the painting works when the content space is scaled to | |
1097 // a different layer space. In this case tiles are scaled to be 200x200 | |
1098 // pixels, which means none should be occluded. | |
1099 layer->setContentsScale(0.5); | |
1100 layer->setBounds(IntSize(600, 600)); | |
1101 WebTransformationMatrix drawTransform; | |
1102 drawTransform.scale(1 / layer->contentsScale()); | |
1103 layer->setDrawTransform(drawTransform); | |
1104 layer->setScreenSpaceTransform(drawTransform); | |
1105 | |
1106 occluded.setOcclusion(IntRect(200, 200, 300, 100)); | |
1107 layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
1108 layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
1109 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
1110 layer->setTexturePriorities(m_priorityCalculator); | |
1111 m_textureManager->prioritizeTextures(); | |
1112 layer->update(m_queue, &occluded, m_stats); | |
1113 // The content is half the size of the layer (so the number of tiles is fewe
r). | |
1114 // In this case, the content is 300x300, and since the tile size is 100, the | |
1115 // number of tiles 3x3. | |
1116 EXPECT_EQ(9, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
1117 | |
1118 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1119 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000, 1
); | |
1120 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1121 | |
1122 layer->fakeLayerTextureUpdater()->clearPrepareRectCount(); | |
1123 | |
1124 // This makes sure the painting works when the content space is scaled to | |
1125 // a different layer space. In this case the occluded region catches the | |
1126 // blown up tiles. | |
1127 occluded.setOcclusion(IntRect(200, 200, 300, 200)); | |
1128 layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
1129 layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
1130 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
1131 layer->setTexturePriorities(m_priorityCalculator); | |
1132 m_textureManager->prioritizeTextures(); | |
1133 layer->update(m_queue, &occluded, m_stats); | |
1134 EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
1135 | |
1136 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1137 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000 +
80000, 1); | |
1138 EXPECT_EQ(1, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1139 | |
1140 layer->fakeLayerTextureUpdater()->clearPrepareRectCount(); | |
1141 | |
1142 // This makes sure content scaling and transforms work together. | |
1143 WebTransformationMatrix screenTransform; | |
1144 screenTransform.scale(0.5); | |
1145 layer->setScreenSpaceTransform(screenTransform); | |
1146 layer->setDrawTransform(screenTransform); | |
1147 | |
1148 occluded.setOcclusion(IntRect(100, 100, 150, 100)); | |
1149 layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
1150 layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds())); | |
1151 layer->invalidateContentRect(IntRect(0, 0, 600, 600)); | |
1152 layer->setTexturePriorities(m_priorityCalculator); | |
1153 m_textureManager->prioritizeTextures(); | |
1154 layer->update(m_queue, &occluded, m_stats); | |
1155 EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount()); | |
1156 | |
1157 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1158 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 90000 +
80000 + 80000, 1); | |
1159 EXPECT_EQ(1 + 1, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1160 } | |
1161 | |
1162 TEST_F(TiledLayerChromiumTest, visibleContentOpaqueRegion) | |
1163 { | |
1164 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
1165 TestCCOcclusionTracker occluded; | |
1166 | |
1167 // The tile size is 100x100, so this invalidates and then paints two tiles i
n various ways. | |
1168 | |
1169 IntRect opaquePaintRect; | |
1170 Region opaqueContents; | |
1171 | |
1172 IntRect contentBounds = IntRect(0, 0, 100, 200); | |
1173 IntRect visibleBounds = IntRect(0, 0, 100, 150); | |
1174 | |
1175 layer->setBounds(contentBounds.size()); | |
1176 layer->setDrawableContentRect(visibleBounds); | |
1177 layer->setVisibleContentRect(visibleBounds); | |
1178 layer->setDrawOpacity(1); | |
1179 | |
1180 layer->setTexturePriorities(m_priorityCalculator); | |
1181 m_textureManager->prioritizeTextures(); | |
1182 | |
1183 // If the layer doesn't paint opaque content, then the visibleContentOpaqueR
egion should be empty. | |
1184 layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect()); | |
1185 layer->invalidateContentRect(contentBounds); | |
1186 layer->update(m_queue, &occluded, m_stats); | |
1187 opaqueContents = layer->visibleContentOpaqueRegion(); | |
1188 EXPECT_TRUE(opaqueContents.isEmpty()); | |
1189 | |
1190 EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000, 1); | |
1191 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1192 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000, 1
); | |
1193 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1194 | |
1195 // visibleContentOpaqueRegion should match the visible part of what is paint
ed opaque. | |
1196 opaquePaintRect = IntRect(10, 10, 90, 190); | |
1197 layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect); | |
1198 layer->invalidateContentRect(contentBounds); | |
1199 layer->update(m_queue, &occluded, m_stats); | |
1200 updateTextures(); | |
1201 opaqueContents = layer->visibleContentOpaqueRegion(); | |
1202 EXPECT_RECT_EQ(intersection(opaquePaintRect, visibleBounds), opaqueContents.
bounds()); | |
1203 EXPECT_EQ(1u, opaqueContents.rects().size()); | |
1204 | |
1205 EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2, 1); | |
1206 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1); | |
1207 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 +
20000 - 17100, 1); | |
1208 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1209 | |
1210 // If we paint again without invalidating, the same stuff should be opaque. | |
1211 layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect()); | |
1212 layer->update(m_queue, &occluded, m_stats); | |
1213 updateTextures(); | |
1214 opaqueContents = layer->visibleContentOpaqueRegion(); | |
1215 EXPECT_RECT_EQ(intersection(opaquePaintRect, visibleBounds), opaqueContents.
bounds()); | |
1216 EXPECT_EQ(1u, opaqueContents.rects().size()); | |
1217 | |
1218 EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2, 1); | |
1219 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1); | |
1220 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 +
20000 - 17100, 1); | |
1221 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1222 | |
1223 // If we repaint a non-opaque part of the tile, then it shouldn't lose its o
paque-ness. And other tiles should | |
1224 // not be affected. | |
1225 layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect()); | |
1226 layer->invalidateContentRect(IntRect(0, 0, 1, 1)); | |
1227 layer->update(m_queue, &occluded, m_stats); | |
1228 updateTextures(); | |
1229 opaqueContents = layer->visibleContentOpaqueRegion(); | |
1230 EXPECT_RECT_EQ(intersection(opaquePaintRect, visibleBounds), opaqueContents.
bounds()); | |
1231 EXPECT_EQ(1u, opaqueContents.rects().size()); | |
1232 | |
1233 EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2 + 1, 1); | |
1234 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1); | |
1235 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 +
20000 - 17100 + 1, 1); | |
1236 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1237 | |
1238 // If we repaint an opaque part of the tile, then it should lose its opaque-
ness. But other tiles should still | |
1239 // not be affected. | |
1240 layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect()); | |
1241 layer->invalidateContentRect(IntRect(10, 10, 1, 1)); | |
1242 layer->update(m_queue, &occluded, m_stats); | |
1243 updateTextures(); | |
1244 opaqueContents = layer->visibleContentOpaqueRegion(); | |
1245 EXPECT_RECT_EQ(intersection(IntRect(10, 100, 90, 100), visibleBounds), opaqu
eContents.bounds()); | |
1246 EXPECT_EQ(1u, opaqueContents.rects().size()); | |
1247 | |
1248 EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 20000 * 2 + 1 + 1,
1); | |
1249 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 17100, 1); | |
1250 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 20000 +
20000 - 17100 + 1 + 1, 1); | |
1251 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1252 } | |
1253 | |
1254 TEST_F(TiledLayerChromiumTest, pixelsPaintedMetrics) | |
1255 { | |
1256 RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(m
_textureManager.get())); | |
1257 TestCCOcclusionTracker occluded; | |
1258 | |
1259 // The tile size is 100x100, so this invalidates and then paints two tiles i
n various ways. | |
1260 | |
1261 IntRect opaquePaintRect; | |
1262 Region opaqueContents; | |
1263 | |
1264 IntRect contentBounds = IntRect(0, 0, 100, 300); | |
1265 IntRect visibleBounds = IntRect(0, 0, 100, 300); | |
1266 | |
1267 layer->setBounds(contentBounds.size()); | |
1268 layer->setDrawableContentRect(visibleBounds); | |
1269 layer->setVisibleContentRect(visibleBounds); | |
1270 layer->setDrawOpacity(1); | |
1271 | |
1272 layer->setTexturePriorities(m_priorityCalculator); | |
1273 m_textureManager->prioritizeTextures(); | |
1274 | |
1275 // Invalidates and paints the whole layer. | |
1276 layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect()); | |
1277 layer->invalidateContentRect(contentBounds); | |
1278 layer->update(m_queue, &occluded, m_stats); | |
1279 updateTextures(); | |
1280 opaqueContents = layer->visibleContentOpaqueRegion(); | |
1281 EXPECT_TRUE(opaqueContents.isEmpty()); | |
1282 | |
1283 EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 30000, 1); | |
1284 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1285 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 30000, 1
); | |
1286 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1287 | |
1288 // Invalidates an area on the top and bottom tile, which will cause us to pa
int the tile in the middle, | |
1289 // even though it is not dirty and will not be uploaded. | |
1290 layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect()); | |
1291 layer->invalidateContentRect(IntRect(0, 0, 1, 1)); | |
1292 layer->invalidateContentRect(IntRect(50, 200, 10, 10)); | |
1293 layer->update(m_queue, &occluded, m_stats); | |
1294 updateTextures(); | |
1295 opaqueContents = layer->visibleContentOpaqueRegion(); | |
1296 EXPECT_TRUE(opaqueContents.isEmpty()); | |
1297 | |
1298 // The middle tile was painted even though not invalidated. | |
1299 EXPECT_NEAR(occluded.overdrawMetrics().pixelsPainted(), 30000 + 60 * 210, 1)
; | |
1300 // The pixels uploaded will not include the non-invalidated tile in the midd
le. | |
1301 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedOpaque(), 0, 1); | |
1302 EXPECT_NEAR(occluded.overdrawMetrics().pixelsUploadedTranslucent(), 30000 +
1 + 100, 1); | |
1303 EXPECT_EQ(0, occluded.overdrawMetrics().tilesCulledForUpload()); | |
1304 } | |
1305 | |
1306 TEST_F(TiledLayerChromiumTest, dontAllocateContentsWhenTargetSurfaceCantBeAlloca
ted) | |
1307 { | |
1308 // Tile size is 100x100. | |
1309 IntRect rootRect(0, 0, 300, 200); | |
1310 IntRect childRect(0, 0, 300, 100); | |
1311 IntRect child2Rect(0, 100, 300, 100); | |
1312 | |
1313 CCLayerTreeSettings settings; | |
1314 FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient; | |
1315 OwnPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLay
erTreeHostClient, settings); | |
1316 ASSERT_TRUE(ccLayerTreeHost->initializeRendererIfNeeded()); | |
1317 | |
1318 RefPtr<FakeTiledLayerChromium> root = adoptRef(new FakeTiledLayerChromium(cc
LayerTreeHost->contentsTextureManager())); | |
1319 RefPtr<LayerChromium> surface = LayerChromium::create(); | |
1320 RefPtr<FakeTiledLayerChromium> child = adoptRef(new FakeTiledLayerChromium(c
cLayerTreeHost->contentsTextureManager())); | |
1321 RefPtr<FakeTiledLayerChromium> child2 = adoptRef(new FakeTiledLayerChromium(
ccLayerTreeHost->contentsTextureManager())); | |
1322 | |
1323 root->setBounds(rootRect.size()); | |
1324 root->setAnchorPoint(FloatPoint()); | |
1325 root->setDrawableContentRect(rootRect); | |
1326 root->setVisibleContentRect(rootRect); | |
1327 root->addChild(surface); | |
1328 | |
1329 surface->setForceRenderSurface(true); | |
1330 surface->setAnchorPoint(FloatPoint()); | |
1331 surface->setOpacity(0.5); | |
1332 surface->addChild(child); | |
1333 surface->addChild(child2); | |
1334 | |
1335 child->setBounds(childRect.size()); | |
1336 child->setAnchorPoint(FloatPoint()); | |
1337 child->setPosition(childRect.location()); | |
1338 child->setVisibleContentRect(childRect); | |
1339 child->setDrawableContentRect(rootRect); | |
1340 | |
1341 child2->setBounds(child2Rect.size()); | |
1342 child2->setAnchorPoint(FloatPoint()); | |
1343 child2->setPosition(child2Rect.location()); | |
1344 child2->setVisibleContentRect(child2Rect); | |
1345 child2->setDrawableContentRect(rootRect); | |
1346 | |
1347 ccLayerTreeHost->setRootLayer(root); | |
1348 ccLayerTreeHost->setViewportSize(rootRect.size(), rootRect.size()); | |
1349 | |
1350 // With a huge memory limit, all layers should update and push their texture
s. | |
1351 root->invalidateContentRect(rootRect); | |
1352 child->invalidateContentRect(childRect); | |
1353 child2->invalidateContentRect(child2Rect); | |
1354 ccLayerTreeHost->updateLayers(m_queue, std::numeric_limits<size_t>::max()); | |
1355 { | |
1356 updateTextures(1000); | |
1357 EXPECT_EQ(6, root->fakeLayerTextureUpdater()->updateCount()); | |
1358 EXPECT_EQ(3, child->fakeLayerTextureUpdater()->updateCount()); | |
1359 EXPECT_EQ(3, child2->fakeLayerTextureUpdater()->updateCount()); | |
1360 EXPECT_FALSE(m_queue.hasMoreUpdates()); | |
1361 | |
1362 root->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1363 child->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1364 child2->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1365 | |
1366 ScopedFakeCCTiledLayerImpl rootImpl(root->id()); | |
1367 ScopedFakeCCTiledLayerImpl childImpl(child->id()); | |
1368 ScopedFakeCCTiledLayerImpl child2Impl(child2->id()); | |
1369 layerPushPropertiesTo(root.get(), rootImpl.get()); | |
1370 layerPushPropertiesTo(child.get(), childImpl.get()); | |
1371 layerPushPropertiesTo(child2.get(), child2Impl.get()); | |
1372 | |
1373 for (unsigned i = 0; i < 3; ++i) { | |
1374 for (unsigned j = 0; j < 2; ++j) | |
1375 EXPECT_TRUE(rootImpl->hasTextureIdForTileAt(i, j)); | |
1376 EXPECT_TRUE(childImpl->hasTextureIdForTileAt(i, 0)); | |
1377 EXPECT_TRUE(child2Impl->hasTextureIdForTileAt(i, 0)); | |
1378 } | |
1379 } | |
1380 ccLayerTreeHost->commitComplete(); | |
1381 | |
1382 // With a memory limit that includes only the root layer (3x2 tiles) and hal
f the surface that | |
1383 // the child layers draw into, the child layers will not be allocated. If th
e surface isn't | |
1384 // accounted for, then one of the children would fit within the memory limit
. | |
1385 root->invalidateContentRect(rootRect); | |
1386 child->invalidateContentRect(childRect); | |
1387 child2->invalidateContentRect(child2Rect); | |
1388 ccLayerTreeHost->updateLayers(m_queue, (3 * 2 + 3 * 1) * (100 * 100) * 4); | |
1389 { | |
1390 updateTextures(1000); | |
1391 EXPECT_EQ(6, root->fakeLayerTextureUpdater()->updateCount()); | |
1392 EXPECT_EQ(0, child->fakeLayerTextureUpdater()->updateCount()); | |
1393 EXPECT_EQ(0, child2->fakeLayerTextureUpdater()->updateCount()); | |
1394 EXPECT_FALSE(m_queue.hasMoreUpdates()); | |
1395 | |
1396 root->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1397 child->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1398 child2->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1399 | |
1400 ScopedFakeCCTiledLayerImpl rootImpl(root->id()); | |
1401 ScopedFakeCCTiledLayerImpl childImpl(child->id()); | |
1402 ScopedFakeCCTiledLayerImpl child2Impl(child2->id()); | |
1403 layerPushPropertiesTo(root.get(), rootImpl.get()); | |
1404 layerPushPropertiesTo(child.get(), childImpl.get()); | |
1405 layerPushPropertiesTo(child2.get(), child2Impl.get()); | |
1406 | |
1407 for (unsigned i = 0; i < 3; ++i) { | |
1408 for (unsigned j = 0; j < 2; ++j) | |
1409 EXPECT_TRUE(rootImpl->hasTextureIdForTileAt(i, j)); | |
1410 EXPECT_FALSE(childImpl->hasTextureIdForTileAt(i, 0)); | |
1411 EXPECT_FALSE(child2Impl->hasTextureIdForTileAt(i, 0)); | |
1412 } | |
1413 } | |
1414 ccLayerTreeHost->commitComplete(); | |
1415 | |
1416 // With a memory limit that includes only half the root layer, no contents w
ill be | |
1417 // allocated. If render surface memory wasn't accounted for, there is enough
space | |
1418 // for one of the children layers, but they draw into a surface that can't b
e | |
1419 // allocated. | |
1420 root->invalidateContentRect(rootRect); | |
1421 child->invalidateContentRect(childRect); | |
1422 child2->invalidateContentRect(child2Rect); | |
1423 ccLayerTreeHost->updateLayers(m_queue, (3 * 1) * (100 * 100) * 4); | |
1424 { | |
1425 updateTextures(1000); | |
1426 EXPECT_EQ(0, root->fakeLayerTextureUpdater()->updateCount()); | |
1427 EXPECT_EQ(0, child->fakeLayerTextureUpdater()->updateCount()); | |
1428 EXPECT_EQ(0, child2->fakeLayerTextureUpdater()->updateCount()); | |
1429 EXPECT_FALSE(m_queue.hasMoreUpdates()); | |
1430 | |
1431 root->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1432 child->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1433 child2->fakeLayerTextureUpdater()->clearUpdateCount(); | |
1434 | |
1435 ScopedFakeCCTiledLayerImpl rootImpl(root->id()); | |
1436 ScopedFakeCCTiledLayerImpl childImpl(child->id()); | |
1437 ScopedFakeCCTiledLayerImpl child2Impl(child2->id()); | |
1438 layerPushPropertiesTo(root.get(), rootImpl.get()); | |
1439 layerPushPropertiesTo(child.get(), childImpl.get()); | |
1440 layerPushPropertiesTo(child2.get(), child2Impl.get()); | |
1441 | |
1442 for (unsigned i = 0; i < 3; ++i) { | |
1443 for (unsigned j = 0; j < 2; ++j) | |
1444 EXPECT_FALSE(rootImpl->hasTextureIdForTileAt(i, j)); | |
1445 EXPECT_FALSE(childImpl->hasTextureIdForTileAt(i, 0)); | |
1446 EXPECT_FALSE(child2Impl->hasTextureIdForTileAt(i, 0)); | |
1447 } | |
1448 } | |
1449 ccLayerTreeHost->commitComplete(); | |
1450 | |
1451 textureManagerClearAllMemory(ccLayerTreeHost->contentsTextureManager(), m_re
sourceProvider.get()); | |
1452 ccLayerTreeHost->setRootLayer(0); | |
1453 ccLayerTreeHost.clear(); | |
1454 } | |
1455 | |
1456 class TrackingLayerPainter : public LayerPainterChromium { | |
1457 public: | |
1458 static PassOwnPtr<TrackingLayerPainter> create() { return adoptPtr(new Track
ingLayerPainter()); } | |
1459 | |
1460 virtual void paint(SkCanvas*, const IntRect& contentRect, FloatRect&) OVERRI
DE | |
1461 { | |
1462 m_paintedRect = contentRect; | |
1463 } | |
1464 | |
1465 const IntRect& paintedRect() const { return m_paintedRect; } | |
1466 void resetPaintedRect() { m_paintedRect = IntRect(); } | |
1467 | |
1468 private: | |
1469 TrackingLayerPainter() { } | |
1470 | |
1471 IntRect m_paintedRect; | |
1472 }; | |
1473 | |
1474 class UpdateTrackingTiledLayerChromium : public FakeTiledLayerChromium { | |
1475 public: | |
1476 explicit UpdateTrackingTiledLayerChromium(WebCore::CCPrioritizedTextureManag
er* manager) | |
1477 : FakeTiledLayerChromium(manager) | |
1478 { | |
1479 OwnPtr<TrackingLayerPainter> trackingLayerPainter(TrackingLayerPainter::
create()); | |
1480 m_trackingLayerPainter = trackingLayerPainter.get(); | |
1481 m_layerTextureUpdater = BitmapCanvasLayerTextureUpdater::create(tracking
LayerPainter.release()); | |
1482 } | |
1483 virtual ~UpdateTrackingTiledLayerChromium() { } | |
1484 | |
1485 TrackingLayerPainter* trackingLayerPainter() const { return m_trackingLayerP
ainter; } | |
1486 | |
1487 protected: | |
1488 virtual WebCore::LayerTextureUpdater* textureUpdater() const OVERRIDE { retu
rn m_layerTextureUpdater.get(); } | |
1489 | |
1490 private: | |
1491 TrackingLayerPainter* m_trackingLayerPainter; | |
1492 RefPtr<BitmapCanvasLayerTextureUpdater> m_layerTextureUpdater; | |
1493 }; | |
1494 | |
1495 TEST_F(TiledLayerChromiumTest, nonIntegerContentsScaleIsNotDistortedDuringPaint) | |
1496 { | |
1497 RefPtr<UpdateTrackingTiledLayerChromium> layer = adoptRef(new UpdateTracking
TiledLayerChromium(m_textureManager.get())); | |
1498 | |
1499 IntRect layerRect(0, 0, 30, 31); | |
1500 layer->setPosition(layerRect.location()); | |
1501 layer->setBounds(layerRect.size()); | |
1502 layer->setContentsScale(1.5); | |
1503 | |
1504 IntRect contentRect(0, 0, 45, 47); | |
1505 EXPECT_EQ(contentRect.size(), layer->contentBounds()); | |
1506 layer->setVisibleContentRect(contentRect); | |
1507 layer->setDrawableContentRect(contentRect); | |
1508 | |
1509 layer->setTexturePriorities(m_priorityCalculator); | |
1510 m_textureManager->prioritizeTextures(); | |
1511 | |
1512 // Update the whole tile. | |
1513 layer->update(m_queue, 0, m_stats); | |
1514 layer->trackingLayerPainter()->resetPaintedRect(); | |
1515 | |
1516 EXPECT_RECT_EQ(IntRect(), layer->trackingLayerPainter()->paintedRect()); | |
1517 updateTextures(); | |
1518 | |
1519 // Invalidate the entire layer in content space. When painting, the rect giv
en to webkit should match the layer's bounds. | |
1520 layer->invalidateContentRect(contentRect); | |
1521 layer->update(m_queue, 0, m_stats); | |
1522 | |
1523 EXPECT_RECT_EQ(layerRect, layer->trackingLayerPainter()->paintedRect()); | |
1524 } | |
1525 | |
1526 TEST_F(TiledLayerChromiumTest, nonIntegerContentsScaleIsNotDistortedDuringInvali
dation) | |
1527 { | |
1528 RefPtr<UpdateTrackingTiledLayerChromium> layer = adoptRef(new UpdateTracking
TiledLayerChromium(m_textureManager.get())); | |
1529 | |
1530 IntRect layerRect(0, 0, 30, 31); | |
1531 layer->setPosition(layerRect.location()); | |
1532 layer->setBounds(layerRect.size()); | |
1533 layer->setContentsScale(1.3f); | |
1534 | |
1535 IntRect contentRect(IntPoint(), layer->contentBounds()); | |
1536 layer->setVisibleContentRect(contentRect); | |
1537 layer->setDrawableContentRect(contentRect); | |
1538 | |
1539 layer->setTexturePriorities(m_priorityCalculator); | |
1540 m_textureManager->prioritizeTextures(); | |
1541 | |
1542 // Update the whole tile. | |
1543 layer->update(m_queue, 0, m_stats); | |
1544 layer->trackingLayerPainter()->resetPaintedRect(); | |
1545 | |
1546 EXPECT_RECT_EQ(IntRect(), layer->trackingLayerPainter()->paintedRect()); | |
1547 updateTextures(); | |
1548 | |
1549 // Invalidate the entire layer in layer space. When painting, the rect given
to webkit should match the layer's bounds. | |
1550 layer->setNeedsDisplayRect(layerRect); | |
1551 layer->update(m_queue, 0, m_stats); | |
1552 | |
1553 EXPECT_RECT_EQ(layerRect, layer->trackingLayerPainter()->paintedRect()); | |
1554 } | |
1555 | |
1556 } // namespace | |
OLD | NEW |