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