[chromium] Push culled tiles that are prepainted
[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 "CCLayerTreeTestCommon.h"
30 #include "FakeCCLayerTreeHostClient.h"
31 #include "LayerTextureUpdater.h"
32 #include "Region.h"
33 #include "TextureManager.h"
34 #include "WebCompositor.h"
35 #include "cc/CCSingleThreadProxy.h" // For DebugScopedSetImplThread
36 #include "cc/CCTextureUpdater.h"
37 #include "cc/CCTiledLayerImpl.h"
38 #include <gtest/gtest.h>
39
40 using namespace WebCore;
41 using namespace WTF;
42
43 #define EXPECT_EQ_RECT(a, b) \
44     EXPECT_EQ(a.x(), b.x()); \
45     EXPECT_EQ(a.y(), b.y()); \
46     EXPECT_EQ(a.width(), b.width()); \
47     EXPECT_EQ(a.height(), b.height());
48
49 namespace {
50
51 class TestCCOcclusionTracker : public CCOcclusionTracker {
52 public:
53     TestCCOcclusionTracker()
54         : CCOcclusionTracker(IntRect(0, 0, 1000, 1000))
55         , m_scissorRectInScreen(IntRect(0, 0, 1000, 1000))
56     {
57         // Pretend we have visited a render surface.
58         m_stack.append(StackObject());
59     }
60
61     void setOcclusion(const Region& occlusion) { m_stack.last().occlusionInScreen = occlusion; }
62
63 protected:
64     virtual IntRect layerScissorRectInTargetSurface(const LayerChromium* layer) const { return m_scissorRectInScreen; }
65
66 private:
67     IntRect m_scissorRectInScreen;
68 };
69
70 class FakeTextureAllocator : public TextureAllocator {
71 public:
72     virtual unsigned createTexture(const IntSize&, GC3Denum) { return 0; }
73     virtual void deleteTexture(unsigned, const IntSize&, GC3Denum) { }
74 };
75
76 class FakeTiledLayerChromium;
77
78 class FakeLayerTextureUpdater : public LayerTextureUpdater {
79 public:
80     class Texture : public LayerTextureUpdater::Texture {
81     public:
82         Texture(FakeLayerTextureUpdater* layer, PassOwnPtr<ManagedTexture> texture)
83             : LayerTextureUpdater::Texture(texture)
84             , m_layer(layer)
85         {
86         }
87         virtual ~Texture() { }
88
89         virtual void updateRect(GraphicsContext3D*, TextureAllocator*, const IntRect&, const IntRect&) { m_layer->updateRect(); }
90         virtual void prepareRect(const IntRect&) { m_layer->prepareRect(); }
91
92     private:
93         FakeLayerTextureUpdater* m_layer;
94     };
95
96     FakeLayerTextureUpdater()
97         : m_prepareCount(0)
98         , m_updateCount(0)
99         , m_prepareRectCount(0)
100     {
101     }
102     virtual ~FakeLayerTextureUpdater() { }
103
104     // Sets the rect to invalidate during the next call to prepareToUpdate(). After the next
105     // call to prepareToUpdate() the rect is reset.
106     void setRectToInvalidate(const IntRect&, FakeTiledLayerChromium*);
107
108     // Number of times prepareToUpdate has been invoked.
109     int prepareCount() const { return m_prepareCount; }
110     void clearPrepareCount() { m_prepareCount = 0; }
111
112     // Number of times updateRect has been invoked.
113     int updateCount() const { return m_updateCount; }
114     void clearUpdateCount() { m_updateCount = 0; }
115     void updateRect() { m_updateCount++; }
116
117     // Number of times prepareRect() has been invoked on a texture.
118     int prepareRectCount() const { return m_prepareRectCount; }
119     void clearPrepareRectCount() { m_prepareRectCount = 0; }
120     void prepareRect() { m_prepareRectCount++; }
121
122     void setOpaquePaintRect(const IntRect& opaquePaintRect) { m_opaquePaintRect = opaquePaintRect; }
123
124     // Last rect passed to prepareToUpdate().
125     const IntRect& lastUpdateRect()  const { return m_lastUpdateRect; }
126
127     virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager* manager) { return adoptPtr(new Texture(this, ManagedTexture::create(manager))); }
128     virtual SampledTexelFormat sampledTexelFormat(GC3Denum) { return SampledTexelFormatRGBA; }
129     virtual void prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect);
130
131 private:
132     int m_prepareCount;
133     int m_updateCount;
134     int m_prepareRectCount;
135     IntRect m_rectToInvalidate;
136     IntRect m_lastUpdateRect;
137     IntRect m_opaquePaintRect;
138     RefPtr<FakeTiledLayerChromium> m_layer;
139 };
140
141 class FakeCCTiledLayerImpl : public CCTiledLayerImpl {
142 public:
143     explicit FakeCCTiledLayerImpl(int id)
144         : CCTiledLayerImpl(id) { }
145     virtual ~FakeCCTiledLayerImpl() { }
146
147     bool hasTileAt(int i, int j)
148     {
149         return CCTiledLayerImpl::hasTileAt(i, j);
150     }
151 };
152
153 class FakeTiledLayerChromium : public TiledLayerChromium {
154 public:
155     explicit FakeTiledLayerChromium(TextureManager* textureManager)
156         : TiledLayerChromium()
157         , m_fakeTextureUpdater(adoptRef(new FakeLayerTextureUpdater))
158         , m_textureManager(textureManager)
159     {
160         setTileSize(IntSize(100, 100));
161         setTextureFormat(GraphicsContext3D::RGBA);
162         setBorderTexelOption(CCLayerTilingData::NoBorderTexels);
163         setIsDrawable(true); // So that we don't get false positives if any of these tests expect to return false from drawsContent() for other reasons.
164     }
165     virtual ~FakeTiledLayerChromium() { }
166
167     void invalidateRect(const IntRect& rect)
168     {
169         TiledLayerChromium::invalidateRect(rect);
170     }
171
172     void prepareToUpdate(const IntRect& rect, const CCOcclusionTracker* occlusion)
173     {
174         TiledLayerChromium::prepareToUpdate(rect, occlusion);
175     }
176
177     void prepareToUpdateIdle(const IntRect& rect, const CCOcclusionTracker* occlusion)
178     {
179         TiledLayerChromium::prepareToUpdateIdle(rect, occlusion);
180     }
181
182     bool needsIdlePaint(const IntRect& rect)
183     {
184         return TiledLayerChromium::needsIdlePaint(rect);
185     }
186
187     bool skipsDraw() const
188     {
189         return TiledLayerChromium::skipsDraw();
190     }
191
192     virtual void setNeedsDisplayRect(const FloatRect& rect)
193     {
194         m_lastNeedsDisplayRect = rect;
195         TiledLayerChromium::setNeedsDisplayRect(rect);
196     }
197
198     const FloatRect& lastNeedsDisplayRect() const { return m_lastNeedsDisplayRect; }
199
200     FakeLayerTextureUpdater* fakeLayerTextureUpdater() { return m_fakeTextureUpdater.get(); }
201
202     virtual TextureManager* textureManager() const { return m_textureManager; }
203
204     virtual void paintContentsIfDirty(const CCOcclusionTracker* occlusion)
205     {
206         prepareToUpdate(visibleLayerRect(), occlusion);
207     }
208
209 private:
210     virtual LayerTextureUpdater* textureUpdater() const
211     {
212         return m_fakeTextureUpdater.get();
213     }
214
215     virtual void createTextureUpdaterIfNeeded() { }
216
217     RefPtr<FakeLayerTextureUpdater> m_fakeTextureUpdater;
218     TextureManager* m_textureManager;
219     FloatRect m_lastNeedsDisplayRect;
220 };
221
222 class FakeTiledLayerWithScaledBounds : public FakeTiledLayerChromium {
223 public:
224     explicit FakeTiledLayerWithScaledBounds(TextureManager* textureManager)
225         : FakeTiledLayerChromium(textureManager)
226     {
227     }
228
229     void setContentBounds(const IntSize& contentBounds) { m_forcedContentBounds = contentBounds; }
230     virtual IntSize contentBounds() const { return m_forcedContentBounds; }
231
232     FloatRect updateRect() { return m_updateRect; }
233
234 protected:
235     IntSize m_forcedContentBounds;
236 };
237
238 void FakeLayerTextureUpdater::setRectToInvalidate(const IntRect& rect, FakeTiledLayerChromium* layer)
239 {
240     m_rectToInvalidate = rect;
241     m_layer = layer;
242 }
243
244 void FakeLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect)
245 {
246     m_prepareCount++;
247     m_lastUpdateRect = contentRect;
248     if (!m_rectToInvalidate.isEmpty()) {
249         m_layer->invalidateRect(m_rectToInvalidate);
250         m_rectToInvalidate = IntRect();
251         m_layer = 0;
252     }
253     *resultingOpaqueRect = m_opaquePaintRect;
254 }
255
256 TEST(TiledLayerChromiumTest, pushDirtyTiles)
257 {
258     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
259     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
260     DebugScopedSetImplThread implThread;
261     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
262
263     FakeTextureAllocator textureAllocator;
264     CCTextureUpdater updater(&textureAllocator);
265
266     // The tile size is 100x100, so this invalidates and then paints two tiles.
267     layer->setBounds(IntSize(100, 200));
268     layer->invalidateRect(IntRect(0, 0, 100, 200));
269     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
270     layer->updateCompositorResources(0, updater);
271     layer->pushPropertiesTo(layerImpl.get());
272
273     // We should have both tiles on the impl side.
274     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
275     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
276
277     textureManager->unprotectAllTextures();
278
279     // Invalidates both tiles...
280     layer->invalidateRect(IntRect(0, 0, 100, 200));
281     // ....but then only update one of them.
282     layer->prepareToUpdate(IntRect(0, 0, 100, 100), 0);
283     layer->updateCompositorResources(0, updater);
284     layer->pushPropertiesTo(layerImpl.get());
285
286     // We should only have the first tile since the other tile was invalidated but not painted.
287     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
288     EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
289 }
290
291 TEST(TiledLayerChromiumTest, pushOccludedDirtyTiles)
292 {
293     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
294     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
295     DebugScopedSetImplThread implThread;
296     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
297     TestCCOcclusionTracker occluded;
298
299     FakeTextureAllocator textureAllocator;
300     CCTextureUpdater updater(&textureAllocator);
301
302     // The tile size is 100x100, so this invalidates and then paints two tiles.
303     layer->setBounds(IntSize(100, 200));
304     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
305     layer->setVisibleLayerRect(IntRect(0, 0, 100, 200));
306     layer->invalidateRect(IntRect(0, 0, 100, 200));
307     layer->prepareToUpdate(IntRect(0, 0, 100, 200), &occluded);
308     layer->updateCompositorResources(0, updater);
309     layer->pushPropertiesTo(layerImpl.get());
310
311     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
312     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 20000, 1);
313     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 0, 1);
314
315     // We should have both tiles on the impl side.
316     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
317     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
318
319     textureManager->unprotectAllTextures();
320
321     // Invalidates part of the top tile...
322     layer->invalidateRect(IntRect(0, 0, 50, 50));
323     // ....but the area is occluded.
324     occluded.setOcclusion(IntRect(0, 0, 50, 50));
325     layer->prepareToUpdate(IntRect(0, 0, 100, 100), &occluded);
326     layer->updateCompositorResources(0, updater);
327     layer->pushPropertiesTo(layerImpl.get());
328
329     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
330     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 20000 + 2500, 1);
331     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 0, 1);
332
333     // We should still have both tiles, as part of the top tile is still unoccluded.
334     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
335     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
336 }
337
338 TEST(TiledLayerChromiumTest, pushDeletedTiles)
339 {
340     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
341     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
342     DebugScopedSetImplThread implThread;
343     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
344
345     FakeTextureAllocator textureAllocator;
346     CCTextureUpdater updater(&textureAllocator);
347
348     // The tile size is 100x100, so this invalidates and then paints two tiles.
349     layer->setBounds(IntSize(100, 200));
350     layer->invalidateRect(IntRect(0, 0, 100, 200));
351     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
352     layer->updateCompositorResources(0, updater);
353     layer->pushPropertiesTo(layerImpl.get());
354
355     // We should have both tiles on the impl side.
356     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
357     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
358
359     textureManager->evictAndDeleteAllTextures(&textureAllocator);
360     textureManager->setMaxMemoryLimitBytes(4*1024*1024);
361     textureManager->setPreferredMemoryLimitBytes(4*1024*1024);
362
363     // This should drop the tiles on the impl thread.
364     layer->pushPropertiesTo(layerImpl.get());
365
366     // We should now have no textures on the impl thread.
367     EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
368     EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
369
370     // This should recreate and update the deleted textures.
371     layer->prepareToUpdate(IntRect(0, 0, 100, 100), 0);
372     layer->updateCompositorResources(0, updater);
373     layer->pushPropertiesTo(layerImpl.get());
374
375     // We should only have the first tile since the other tile was invalidated but not painted.
376     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
377     EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
378 }
379
380 TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
381 {
382     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
383     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
384     DebugScopedSetImplThread implThread;
385     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
386
387     FakeTextureAllocator textureAllocator;
388     CCTextureUpdater updater(&textureAllocator);
389
390     // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the center.
391     IntSize contentBounds(500, 500);
392     IntRect contentRect(IntPoint::zero(), contentBounds);
393     IntRect visibleRect(200, 200, 100, 100);
394
395     // This invalidates 25 tiles and then paints one visible tile.
396     layer->setBounds(contentBounds);
397     layer->setVisibleLayerRect(visibleRect);
398     layer->invalidateRect(contentRect);
399     layer->prepareToUpdate(visibleRect, 0);
400
401     // We should need idle-painting for 3x3 tiles in the center.
402     EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
403
404     layer->updateCompositorResources(0, updater);
405     layer->pushPropertiesTo(layerImpl.get());
406
407     // We should have one tile on the impl side.
408     EXPECT_TRUE(layerImpl->hasTileAt(2, 2));
409
410     textureManager->unprotectAllTextures();
411
412     // For the next four updates, we should detect we still need idle painting.
413     for (int i = 0; i < 4; i++) {
414         layer->prepareToUpdate(visibleRect, 0);
415         EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
416         layer->prepareToUpdateIdle(visibleRect, 0);
417         layer->updateCompositorResources(0, updater);
418         layer->pushPropertiesTo(layerImpl.get());
419         textureManager->unprotectAllTextures();
420     }
421
422     // After four passes of idle painting, we should be finished painting
423     EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
424
425     // We should have one tile surrounding the visible tile on all sides, but no other tiles.
426     IntRect idlePaintTiles(1, 1, 3, 3);
427     for (int i = 0; i < 5; i++) {
428         for (int j = 0; j < 5; j++) {
429             if (idlePaintTiles.contains(i, j))
430                 EXPECT_TRUE(layerImpl->hasTileAt(i, j));
431             else
432                 EXPECT_FALSE(layerImpl->hasTileAt(i, j));
433         }
434     }
435 }
436
437 TEST(TiledLayerChromiumTest, pushIdlePaintedOccludedTiles)
438 {
439     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
440     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
441     DebugScopedSetImplThread implThread;
442     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
443     TestCCOcclusionTracker occluded;
444
445     FakeTextureAllocator textureAllocator;
446     CCTextureUpdater updater(&textureAllocator);
447
448     // The tile size is 100x100, so this invalidates one occluded tile, culls it during paint, but prepaints it.
449     occluded.setOcclusion(IntRect(0, 0, 100, 100));
450
451     layer->setBounds(IntSize(100, 100));
452     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
453     layer->setVisibleLayerRect(IntRect(0, 0, 100, 100));
454     layer->invalidateRect(IntRect(0, 0, 100, 100));
455     layer->prepareToUpdate(IntRect(0, 0, 100, 100), &occluded);
456     layer->prepareToUpdateIdle(IntRect(0, 0, 100, 100), &occluded);
457     layer->updateCompositorResources(0, updater);
458     layer->pushPropertiesTo(layerImpl.get());
459
460     // We should have the prepainted tile on the impl side.
461     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
462 }
463
464 TEST(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint)
465 {
466     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
467     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
468     DebugScopedSetImplThread implThread;
469     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
470
471     FakeTextureAllocator textureAllocator;
472     CCTextureUpdater updater(&textureAllocator);
473
474     // The tile size is 100x100, so this invalidates and then paints two tiles.
475     // However, during the paint, we invalidate one of the tiles. This should
476     // not prevent the tile from being pushed.
477     layer->setBounds(IntSize(100, 200));
478     layer->invalidateRect(IntRect(0, 0, 100, 200));
479     layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer.get());
480     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
481     layer->updateCompositorResources(0, updater);
482     layer->pushPropertiesTo(layerImpl.get());
483
484     // We should have both tiles on the impl side.
485     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
486     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
487 }
488
489 TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnNextLayer)
490 {
491     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
492     RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
493     RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
494     DebugScopedSetImplThread implThread;
495     OwnPtr<FakeCCTiledLayerImpl> layer1Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
496     OwnPtr<FakeCCTiledLayerImpl> layer2Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
497
498     FakeTextureAllocator textureAllocator;
499     CCTextureUpdater updater(&textureAllocator);
500
501     layer1->setBounds(IntSize(100, 200));
502     layer1->invalidateRect(IntRect(0, 0, 100, 200));
503     layer2->setBounds(IntSize(100, 200));
504     layer2->invalidateRect(IntRect(0, 0, 100, 200));
505
506     layer1->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
507
508     // Invalidate a tile on layer1
509     layer2->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer1.get());
510     layer2->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
511
512     layer1->updateCompositorResources(0, updater);
513     layer2->updateCompositorResources(0, updater);
514
515     layer1->pushPropertiesTo(layer1Impl.get());
516     layer2->pushPropertiesTo(layer2Impl.get());
517
518     // We should have both tiles on the impl side for all layers.
519     EXPECT_TRUE(layer1Impl->hasTileAt(0, 0));
520     EXPECT_TRUE(layer1Impl->hasTileAt(0, 1));
521     EXPECT_TRUE(layer2Impl->hasTileAt(0, 0));
522     EXPECT_TRUE(layer2Impl->hasTileAt(0, 1));
523 }
524
525 TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer)
526 {
527     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
528     RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
529     RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
530     DebugScopedSetImplThread implThread;
531     OwnPtr<FakeCCTiledLayerImpl> layer1Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
532     OwnPtr<FakeCCTiledLayerImpl> layer2Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
533
534     FakeTextureAllocator textureAllocator;
535     CCTextureUpdater updater(&textureAllocator);
536
537     layer1->setBounds(IntSize(100, 200));
538     layer1->invalidateRect(IntRect(0, 0, 100, 200));
539     layer2->setBounds(IntSize(100, 200));
540     layer2->invalidateRect(IntRect(0, 0, 100, 200));
541
542     // Invalidate a tile on layer2
543     layer1->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer2.get());
544     layer1->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
545
546     layer2->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
547
548     layer1->updateCompositorResources(0, updater);
549     layer2->updateCompositorResources(0, updater);
550
551     layer1->pushPropertiesTo(layer1Impl.get());
552     layer2->pushPropertiesTo(layer2Impl.get());
553
554     // We should have both tiles on the impl side for all layers.
555     EXPECT_TRUE(layer1Impl->hasTileAt(0, 0));
556     EXPECT_TRUE(layer1Impl->hasTileAt(0, 1));
557     EXPECT_TRUE(layer2Impl->hasTileAt(0, 0));
558     EXPECT_TRUE(layer2Impl->hasTileAt(0, 1));
559 }
560
561 TEST(TiledLayerChromiumTest, idlePaintOutOfMemory)
562 {
563     // The tile size is 100x100. Setup 5x5 tiles with one 1x1 visible tile in the center.
564     IntSize contentBounds(300, 300);
565     IntRect contentRect(IntPoint::zero(), contentBounds);
566     IntRect visibleRect(100, 100, 100, 100);
567
568     // We have enough memory for only the visible rect, so we will run out of memory in first idle paint.
569     int memoryLimit = 4 * 100 * 100; // 2 tiles, 4 bytes per pixel.
570
571     OwnPtr<TextureManager> textureManager = TextureManager::create(memoryLimit, memoryLimit / 2, 1024);
572     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
573     DebugScopedSetImplThread implThread;
574     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
575
576     FakeTextureAllocator textureAllocator;
577     CCTextureUpdater updater(&textureAllocator);
578
579     // This invalidates 9 tiles and then paints one visible tile.
580     layer->setBounds(contentBounds);
581     layer->setVisibleLayerRect(visibleRect);
582     layer->invalidateRect(contentRect);
583     layer->prepareToUpdate(visibleRect, 0);
584
585     // We should need idle-painting for 3x3 tiles surounding visible tile.
586     EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
587
588     layer->updateCompositorResources(0, updater);
589     layer->pushPropertiesTo(layerImpl.get());
590
591     // We should have one tile on the impl side.
592     EXPECT_TRUE(layerImpl->hasTileAt(1, 1));
593
594     textureManager->unprotectAllTextures();
595     layer->prepareToUpdate(visibleRect, 0);
596     layer->prepareToUpdateIdle(visibleRect, 0);
597
598     // We shouldn't signal we need another idle paint after we run out of memory.
599     EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
600
601     layer->updateCompositorResources(0, updater);
602     layer->pushPropertiesTo(layerImpl.get());
603 }
604
605 TEST(TiledLayerChromiumTest, invalidateFromPrepare)
606 {
607     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
608     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
609     DebugScopedSetImplThread implThread;
610     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
611
612     FakeTextureAllocator textureAllocator;
613     CCTextureUpdater updater(&textureAllocator);
614
615     // The tile size is 100x100, so this invalidates and then paints two tiles.
616     layer->setBounds(IntSize(100, 200));
617     layer->invalidateRect(IntRect(0, 0, 100, 200));
618     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
619     layer->updateCompositorResources(0, updater);
620     layer->pushPropertiesTo(layerImpl.get());
621
622     // We should have both tiles on the impl side.
623     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
624     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
625
626     textureManager->unprotectAllTextures();
627
628     layer->fakeLayerTextureUpdater()->clearPrepareCount();
629     // Invoke prepareToUpdate again. As the layer is valid prepareToUpdate shouldn't be invoked on
630     // the LayerTextureUpdater.
631     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
632     EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareCount());
633
634     layer->invalidateRect(IntRect(0, 0, 50, 50));
635     // setRectToInvalidate triggers invalidateRect() being invoked from prepareToUpdate.
636     layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(25, 25, 50, 50), layer.get());
637     layer->fakeLayerTextureUpdater()->clearPrepareCount();
638     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
639     EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
640     layer->fakeLayerTextureUpdater()->clearPrepareCount();
641     // The layer should still be invalid as prepareToUpdate invoked invalidate.
642     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
643     EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
644 }
645
646 TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled)
647 {
648     // The updateRect (that indicates what was actually painted) should be in
649     // layer space, not the content space.
650
651     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
652     RefPtr<FakeTiledLayerWithScaledBounds> layer = adoptRef(new FakeTiledLayerWithScaledBounds(textureManager.get()));
653
654     FakeTextureAllocator textureAllocator;
655     CCTextureUpdater updater(&textureAllocator);
656
657     IntRect layerBounds(0, 0, 300, 200);
658     IntRect contentBounds(0, 0, 200, 250);
659
660     layer->setBounds(layerBounds.size());
661     layer->setContentBounds(contentBounds.size());
662     layer->setVisibleLayerRect(contentBounds);
663
664     // On first update, the updateRect includes all tiles, even beyond the boundaries of the layer.
665     // However, it should still be in layer space, not content space.
666     layer->invalidateRect(contentBounds);
667     layer->prepareToUpdate(contentBounds, 0);
668     layer->updateCompositorResources(0, updater);
669     EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 300, 300 * 0.8), layer->updateRect());
670
671     // After the tiles are updated once, another invalidate only needs to update the bounds of the layer.
672     layer->invalidateRect(contentBounds);
673     layer->prepareToUpdate(contentBounds, 0);
674     layer->updateCompositorResources(0, updater);
675     EXPECT_FLOAT_RECT_EQ(FloatRect(layerBounds), layer->updateRect());
676
677     // Partial re-paint should also be represented by the updateRect in layer space, not content space.
678     IntRect partialDamage(30, 100, 10, 10);
679     layer->invalidateRect(partialDamage);
680     layer->prepareToUpdate(contentBounds, 0);
681     layer->updateCompositorResources(0, updater);
682     EXPECT_FLOAT_RECT_EQ(FloatRect(45, 80, 15, 8), layer->updateRect());
683 }
684
685 TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
686 {
687     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
688     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
689     DebugScopedSetImplThread implThread;
690     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
691
692     FakeTextureAllocator textureAllocator;
693     CCTextureUpdater updater(&textureAllocator);
694
695     // Create a layer with one tile.
696     layer->setBounds(IntSize(100, 100));
697
698     // Invalidate the entire layer.
699     layer->setNeedsDisplay();
700     EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
701
702     // Push the tiles to the impl side and check that there is exactly one.
703     layer->prepareToUpdate(IntRect(0, 0, 100, 100), 0);
704     layer->updateCompositorResources(0, updater);
705     layer->pushPropertiesTo(layerImpl.get());
706     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
707     EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
708     EXPECT_FALSE(layerImpl->hasTileAt(1, 0));
709     EXPECT_FALSE(layerImpl->hasTileAt(1, 1));
710
711     // Change the contents scale and verify that the content rectangle requiring painting
712     // is not scaled.
713     layer->setContentsScale(2);
714     EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
715
716     // The impl side should get 2x2 tiles now.
717     layer->prepareToUpdate(IntRect(0, 0, 200, 200), 0);
718     layer->updateCompositorResources(0, updater);
719     layer->pushPropertiesTo(layerImpl.get());
720     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
721     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
722     EXPECT_TRUE(layerImpl->hasTileAt(1, 0));
723     EXPECT_TRUE(layerImpl->hasTileAt(1, 1));
724
725     // Invalidate the entire layer again, but do not paint. All tiles should be gone now from the
726     // impl side.
727     layer->setNeedsDisplay();
728     layer->prepareToUpdate(IntRect(1, 0, 0, 1), 0);
729     layer->updateCompositorResources(0, updater);
730     layer->pushPropertiesTo(layerImpl.get());
731     EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
732     EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
733     EXPECT_FALSE(layerImpl->hasTileAt(1, 0));
734     EXPECT_FALSE(layerImpl->hasTileAt(1, 1));
735 }
736
737 TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
738 {
739     // Initialize without threading support.
740     WebKit::WebCompositor::initialize(0);
741     FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
742     RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, CCSettings());
743
744     // Create two 300 x 300 tiled layers.
745     IntSize contentBounds(300, 300);
746     IntRect contentRect(IntPoint::zero(), contentBounds);
747
748     // We have enough memory for only one of the two layers.
749     int memoryLimit = 4 * 300 * 300; // 4 bytes per pixel.
750     OwnPtr<TextureManager> textureManager = TextureManager::create(memoryLimit, memoryLimit, memoryLimit);
751
752     RefPtr<FakeTiledLayerChromium> rootLayer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
753     RefPtr<FakeTiledLayerChromium> childLayer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
754     rootLayer->addChild(childLayer);
755
756     rootLayer->setBounds(contentBounds);
757     rootLayer->setPosition(FloatPoint(150, 150));
758     childLayer->setBounds(contentBounds);
759     childLayer->setPosition(FloatPoint(150, 150));
760     rootLayer->invalidateRect(contentRect);
761     childLayer->invalidateRect(contentRect);
762
763     FakeTextureAllocator textureAllocator;
764     CCTextureUpdater updater(&textureAllocator);
765
766     ccLayerTreeHost->setRootLayer(rootLayer);
767     ccLayerTreeHost->setViewportSize(IntSize(300, 300));
768     textureManager->setMaxMemoryLimitBytes(memoryLimit);
769     ccLayerTreeHost->updateLayers();
770     ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
771
772     // We'll skip the root layer.
773     EXPECT_TRUE(rootLayer->skipsDraw());
774     EXPECT_FALSE(childLayer->skipsDraw());
775
776     ccLayerTreeHost->commitComplete();
777     textureManager->unprotectAllTextures(); // CCLayerTreeHost::commitComplete() normally does this, but since we're mocking out the manager we have to do it.
778
779     // Remove the child layer.
780     rootLayer->removeAllChildren();
781
782     ccLayerTreeHost->updateLayers();
783     EXPECT_FALSE(rootLayer->skipsDraw());
784
785     ccLayerTreeHost->setRootLayer(0);
786     ccLayerTreeHost.clear();
787     WebKit::WebCompositor::shutdown();
788 }
789
790 TEST(TiledLayerChromiumTest, resizeToSmaller)
791 {
792     OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
793     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
794
795     layer->setBounds(IntSize(700, 700));
796     layer->invalidateRect(IntRect(0, 0, 700, 700));
797     layer->prepareToUpdate(IntRect(0, 0, 700, 700), 0);
798
799     layer->setBounds(IntSize(200, 200));
800     layer->invalidateRect(IntRect(0, 0, 200, 200));
801 }
802
803 TEST(TiledLayerChromiumTest, partialUpdates)
804 {
805     CCSettings settings;
806     settings.maxPartialTextureUpdates = 4;
807     // Initialize without threading support.
808     WebKit::WebCompositor::initialize(0);
809     FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
810     RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, settings);
811
812     // Create one 500 x 300 tiled layer.
813     IntSize contentBounds(300, 200);
814     IntRect contentRect(IntPoint::zero(), contentBounds);
815
816     OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
817     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
818     layer->setBounds(contentBounds);
819     layer->setPosition(FloatPoint(150, 150));
820     layer->invalidateRect(contentRect);
821
822     FakeTextureAllocator textureAllocator;
823     CCTextureUpdater updater(&textureAllocator);
824
825     ccLayerTreeHost->setRootLayer(layer);
826     ccLayerTreeHost->setViewportSize(IntSize(300, 200));
827
828     // Full update of all 6 tiles.
829     ccLayerTreeHost->updateLayers();
830     ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
831     updater.update(0, 4);
832     EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
833     EXPECT_TRUE(updater.hasMoreUpdates());
834     layer->fakeLayerTextureUpdater()->clearUpdateCount();
835     updater.update(0, 4);
836     EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
837     EXPECT_FALSE(updater.hasMoreUpdates());
838     layer->fakeLayerTextureUpdater()->clearUpdateCount();
839     ccLayerTreeHost->commitComplete();
840
841     // Full update of 3 tiles and partial update of 3 tiles.
842     layer->invalidateRect(IntRect(0, 0, 300, 150));
843     ccLayerTreeHost->updateLayers();
844     ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
845     updater.update(0, 4);
846     EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
847     EXPECT_TRUE(updater.hasMoreUpdates());
848     layer->fakeLayerTextureUpdater()->clearUpdateCount();
849     updater.update(0, 4);
850     EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
851     EXPECT_FALSE(updater.hasMoreUpdates());
852     layer->fakeLayerTextureUpdater()->clearUpdateCount();
853     ccLayerTreeHost->commitComplete();
854
855     // Partial update of 6 tiles.
856     layer->invalidateRect(IntRect(50, 50, 200, 100));
857     ccLayerTreeHost->updateLayers();
858     ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
859     updater.update(0, 4);
860     EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
861     EXPECT_TRUE(updater.hasMoreUpdates());
862     layer->fakeLayerTextureUpdater()->clearUpdateCount();
863     updater.update(0, 4);
864     EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
865     EXPECT_FALSE(updater.hasMoreUpdates());
866     layer->fakeLayerTextureUpdater()->clearUpdateCount();
867     ccLayerTreeHost->commitComplete();
868
869     ccLayerTreeHost->setRootLayer(0);
870     ccLayerTreeHost.clear();
871     WebKit::WebCompositor::shutdown();
872 }
873
874 TEST(TiledLayerChromiumTest, tilesPaintedWithoutOcclusion)
875 {
876     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
877     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
878
879     // The tile size is 100x100, so this invalidates and then paints two tiles.
880     layer->setBounds(IntSize(100, 200));
881
882     layer->invalidateRect(IntRect(0, 0, 100, 200));
883     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
884     EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->prepareRectCount());
885 }
886
887 TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusion)
888 {
889     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
890     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
891     TestCCOcclusionTracker occluded;
892
893     // The tile size is 100x100.
894
895     layer->setBounds(IntSize(600, 600));
896     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
897
898     occluded.setOcclusion(IntRect(200, 200, 300, 100));
899     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
900     layer->invalidateRect(IntRect(0, 0, 600, 600));
901     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
902     EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
903
904     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
905     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 330000, 1);
906     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000, 1);
907
908     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
909
910     occluded.setOcclusion(IntRect(250, 200, 300, 100));
911     layer->invalidateRect(IntRect(0, 0, 600, 600));
912     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
913     EXPECT_EQ(36-2, layer->fakeLayerTextureUpdater()->prepareRectCount());
914
915     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
916     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 330000 + 340000, 1);
917     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000 + 20000, 1);
918
919     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
920
921     occluded.setOcclusion(IntRect(250, 250, 300, 100));
922     layer->invalidateRect(IntRect(0, 0, 600, 600));
923     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
924     EXPECT_EQ(36, layer->fakeLayerTextureUpdater()->prepareRectCount());
925
926     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
927     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 330000 + 340000 + 360000, 1);
928     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000 + 20000, 1);
929 }
930
931 TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndVisiblityConstraints)
932 {
933     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
934     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
935     TestCCOcclusionTracker occluded;
936
937     // The tile size is 100x100.
938
939     layer->setBounds(IntSize(600, 600));
940     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
941
942     // The partially occluded tiles (by the 150 occlusion height) are visible beyond the occlusion, so not culled.
943     occluded.setOcclusion(IntRect(200, 200, 300, 150));
944     layer->setVisibleLayerRect(IntRect(0, 0, 600, 360));
945     layer->invalidateRect(IntRect(0, 0, 600, 600));
946     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
947     EXPECT_EQ(24-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
948
949     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
950     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 210000, 1);
951     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000, 1);
952
953     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
954
955     // Now the visible region stops at the edge of the occlusion so the partly visible tiles become fully occluded.
956     occluded.setOcclusion(IntRect(200, 200, 300, 150));
957     layer->setVisibleLayerRect(IntRect(0, 0, 600, 350));
958     layer->invalidateRect(IntRect(0, 0, 600, 600));
959     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
960     EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
961
962     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
963     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 210000 + 180000, 1);
964     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000 + 60000, 1);
965
966     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
967
968     // Now the visible region is even smaller than the occlusion, it should have the same result.
969     occluded.setOcclusion(IntRect(200, 200, 300, 150));
970     layer->setVisibleLayerRect(IntRect(0, 0, 600, 340));
971     layer->invalidateRect(IntRect(0, 0, 600, 600));
972     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
973     EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
974
975     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
976     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 210000 + 180000 + 180000, 1);
977     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000 + 60000 + 60000, 1);
978
979 }
980
981 TEST(TiledLayerChromiumTest, tilesNotPaintedWithoutInvalidation)
982 {
983     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
984     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
985     TestCCOcclusionTracker occluded;
986
987     // The tile size is 100x100.
988
989     layer->setBounds(IntSize(600, 600));
990     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
991
992     occluded.setOcclusion(IntRect(200, 200, 300, 100));
993     layer->setVisibleLayerRect(IntRect(0, 0, 600, 600));
994     layer->invalidateRect(IntRect(0, 0, 600, 600));
995     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
996     EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
997
998     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
999     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 330000, 1);
1000     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000, 1);
1001
1002     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
1003
1004     // Repaint without marking it dirty.
1005     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
1006     EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareRectCount());
1007
1008     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
1009     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 330000, 1);
1010     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000, 1);
1011 }
1012
1013 TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndTransforms)
1014 {
1015     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
1016     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
1017     TestCCOcclusionTracker occluded;
1018
1019     // The tile size is 100x100.
1020
1021     // This makes sure the painting works when the occluded region (in screen space)
1022     // is transformed differently than the layer.
1023     layer->setBounds(IntSize(600, 600));
1024     TransformationMatrix screenTransform;
1025     screenTransform.scale(0.5);
1026     layer->setScreenSpaceTransform(screenTransform);
1027     layer->setDrawTransform(screenTransform * TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
1028
1029     occluded.setOcclusion(IntRect(100, 100, 150, 50));
1030     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
1031     layer->invalidateRect(IntRect(0, 0, 600, 600));
1032     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
1033     EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
1034
1035     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
1036     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 330000, 1);
1037     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 30000, 1);
1038 }
1039
1040 TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
1041 {
1042     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
1043     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
1044     TestCCOcclusionTracker occluded;
1045
1046     // The tile size is 100x100.
1047
1048     // This makes sure the painting works when the content space is scaled to
1049     // a different layer space. In this case tiles are scaled to be 200x200
1050     // pixels, which means none should be occluded.
1051     layer->setContentsScale(0.5);
1052     layer->setBounds(IntSize(600, 600));
1053     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
1054
1055     occluded.setOcclusion(IntRect(200, 200, 300, 100));
1056     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
1057     layer->invalidateRect(IntRect(0, 0, 600, 600));
1058     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
1059     // The content is half the size of the layer (so the number of tiles is fewer).
1060     // In this case, the content is 300x300, and since the tile size is 100, the
1061     // number of tiles 3x3.
1062     EXPECT_EQ(9, layer->fakeLayerTextureUpdater()->prepareRectCount());
1063
1064     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
1065     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 90000, 1);
1066     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 0, 1);
1067
1068     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
1069
1070     // This makes sure the painting works when the content space is scaled to
1071     // a different layer space. In this case the occluded region catches the
1072     // blown up tiles.
1073     occluded.setOcclusion(IntRect(200, 200, 300, 200));
1074     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
1075     layer->invalidateRect(IntRect(0, 0, 600, 600));
1076     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
1077     EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount());
1078
1079     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
1080     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 90000 + 80000, 1);
1081     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 10000, 1);
1082
1083     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
1084
1085     // This makes sure content scaling and transforms work together.
1086     TransformationMatrix screenTransform;
1087     screenTransform.scale(0.5);
1088     layer->setScreenSpaceTransform(screenTransform);
1089     layer->setDrawTransform(screenTransform * TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
1090
1091     occluded.setOcclusion(IntRect(100, 100, 150, 100));
1092     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
1093     layer->invalidateRect(IntRect(0, 0, 600, 600));
1094     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
1095     EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount());
1096
1097     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
1098     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 90000 + 80000 + 80000, 1);
1099     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 10000 + 10000, 1);
1100 }
1101
1102 TEST(TiledLayerChromiumTest, opaqueContentsRegion)
1103 {
1104     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
1105     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
1106     TestCCOcclusionTracker occluded;
1107
1108     // The tile size is 100x100, so this invalidates and then paints two tiles in various ways.
1109
1110     IntRect opaquePaintRect;
1111     Region opaqueContents;
1112
1113     IntRect contentBounds = IntRect(0, 0, 100, 200);
1114     IntRect visibleBounds = IntRect(0, 0, 100, 150);
1115
1116     layer->setBounds(contentBounds.size());
1117     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
1118     layer->setVisibleLayerRect(visibleBounds);
1119     layer->setDrawOpacity(1);
1120
1121     // If the layer doesn't paint opaque content, then the opaqueContentsRegion should be empty.
1122     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
1123     layer->invalidateRect(contentBounds);
1124     layer->prepareToUpdate(contentBounds, &occluded);
1125     opaqueContents = layer->opaqueContentsRegion();
1126     EXPECT_TRUE(opaqueContents.isEmpty());
1127
1128     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 0, 1);
1129     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 20000, 1);
1130     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 0, 1);
1131
1132     // opaqueContentsRegion should match the visible part of what is painted opaque.
1133     opaquePaintRect = IntRect(10, 10, 90, 190);
1134     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
1135     layer->invalidateRect(contentBounds);
1136     layer->prepareToUpdate(contentBounds, &occluded);
1137     opaqueContents = layer->opaqueContentsRegion();
1138     EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
1139     EXPECT_EQ(1u, opaqueContents.rects().size());
1140
1141     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 17100, 1);
1142     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 20000 + 20000 - 17100, 1);
1143     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 0, 1);
1144
1145     // If we paint again without invalidating, the same stuff should be opaque.
1146     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
1147     layer->prepareToUpdate(contentBounds, &occluded);
1148     opaqueContents = layer->opaqueContentsRegion();
1149     EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
1150     EXPECT_EQ(1u, opaqueContents.rects().size());
1151
1152     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 17100, 1);
1153     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 20000 + 20000 - 17100, 1);
1154     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 0, 1);
1155
1156     // If we repaint a non-opaque part of the tile, then it shouldn't lose its opaque-ness. And other tiles should
1157     // not be affected.
1158     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
1159     layer->invalidateRect(IntRect(0, 0, 1, 1));
1160     layer->prepareToUpdate(contentBounds, &occluded);
1161     opaqueContents = layer->opaqueContentsRegion();
1162     EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
1163     EXPECT_EQ(1u, opaqueContents.rects().size());
1164
1165     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 17100, 1);
1166     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 20000 + 20000 - 17100 + 1, 1);
1167     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 0, 1);
1168
1169     // If we repaint an opaque part of the tile, then it should lose its opaque-ness. But other tiles should still
1170     // not be affected.
1171     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
1172     layer->invalidateRect(IntRect(10, 10, 1, 1));
1173     layer->prepareToUpdate(contentBounds, &occluded);
1174     opaqueContents = layer->opaqueContentsRegion();
1175     EXPECT_EQ_RECT(intersection(IntRect(10, 100, 90, 100), visibleBounds), opaqueContents.bounds());
1176     EXPECT_EQ(1u, opaqueContents.rects().size());
1177
1178     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnOpaque(), 17100, 1);
1179     EXPECT_NEAR(occluded.overdrawMetrics().pixelsDrawnTranslucent(), 20000 + 20000 - 17100 + 1 + 1, 1);
1180     EXPECT_NEAR(occluded.overdrawMetrics().pixelsCulled(), 0, 1);
1181 }
1182
1183 } // namespace