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