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