Unreviewed, rolling out r110941.
[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     // We should have both tiles on the impl side.
312     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
313     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
314
315     textureManager->unprotectAllTextures();
316
317     // Invalidates part of the top tile...
318     layer->invalidateRect(IntRect(0, 0, 50, 50));
319     // ....but the area is occluded.
320     occluded.setOcclusion(IntRect(0, 0, 50, 50));
321     layer->prepareToUpdate(IntRect(0, 0, 100, 100), &occluded);
322     layer->updateCompositorResources(0, updater);
323     layer->pushPropertiesTo(layerImpl.get());
324
325     // We should still have both tiles, as part of the top tile is still unoccluded.
326     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
327     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
328 }
329
330 TEST(TiledLayerChromiumTest, pushIdlePaintTiles)
331 {
332     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
333     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
334     DebugScopedSetImplThread implThread;
335     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
336
337     FakeTextureAllocator textureAllocator;
338     CCTextureUpdater updater(&textureAllocator);
339
340     // The tile size is 100x100. Setup 5x5 tiles with one visible tile in the center.
341     IntSize contentBounds(500, 500);
342     IntRect contentRect(IntPoint::zero(), contentBounds);
343     IntRect visibleRect(200, 200, 100, 100);
344
345     // This invalidates 25 tiles and then paints one visible tile.
346     layer->setBounds(contentBounds);
347     layer->setVisibleLayerRect(visibleRect);
348     layer->invalidateRect(contentRect);
349     layer->prepareToUpdate(visibleRect, 0);
350
351     // We should need idle-painting for 3x3 tiles in the center.
352     EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
353
354     layer->updateCompositorResources(0, updater);
355     layer->pushPropertiesTo(layerImpl.get());
356
357     // We should have one tile on the impl side.
358     EXPECT_TRUE(layerImpl->hasTileAt(2, 2));
359
360     textureManager->unprotectAllTextures();
361
362     // For the next four updates, we should detect we still need idle painting.
363     for (int i = 0; i < 4; i++) {
364         layer->prepareToUpdate(visibleRect, 0);
365         EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
366         layer->prepareToUpdateIdle(visibleRect, 0);
367         layer->updateCompositorResources(0, updater);
368         layer->pushPropertiesTo(layerImpl.get());
369         textureManager->unprotectAllTextures();
370     }
371
372     // After four passes of idle painting, we should be finished painting
373     EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
374
375     // We should have one tile surrounding the visible tile on all sides, but no other tiles.
376     IntRect idlePaintTiles(1, 1, 3, 3);
377     for (int i = 0; i < 5; i++) {
378         for (int j = 0; j < 5; j++) {
379             if (idlePaintTiles.contains(i, j))
380                 EXPECT_TRUE(layerImpl->hasTileAt(i, j));
381             else
382                 EXPECT_FALSE(layerImpl->hasTileAt(i, j));
383         }
384     }
385 }
386
387 TEST(TiledLayerChromiumTest, pushTilesMarkedDirtyDuringPaint)
388 {
389     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
390     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
391     DebugScopedSetImplThread implThread;
392     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
393
394     FakeTextureAllocator textureAllocator;
395     CCTextureUpdater updater(&textureAllocator);
396
397     // The tile size is 100x100, so this invalidates and then paints two tiles.
398     // However, during the paint, we invalidate one of the tiles. This should
399     // not prevent the tile from being pushed.
400     layer->setBounds(IntSize(100, 200));
401     layer->invalidateRect(IntRect(0, 0, 100, 200));
402     layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer.get());
403     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
404     layer->updateCompositorResources(0, updater);
405     layer->pushPropertiesTo(layerImpl.get());
406
407     // We should have both tiles on the impl side.
408     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
409     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
410 }
411
412 TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnNextLayer)
413 {
414     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
415     RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
416     RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
417     DebugScopedSetImplThread implThread;
418     OwnPtr<FakeCCTiledLayerImpl> layer1Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
419     OwnPtr<FakeCCTiledLayerImpl> layer2Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
420
421     FakeTextureAllocator textureAllocator;
422     CCTextureUpdater updater(&textureAllocator);
423
424     layer1->setBounds(IntSize(100, 200));
425     layer1->invalidateRect(IntRect(0, 0, 100, 200));
426     layer2->setBounds(IntSize(100, 200));
427     layer2->invalidateRect(IntRect(0, 0, 100, 200));
428
429     layer1->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
430
431     // Invalidate a tile on layer1
432     layer2->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer1.get());
433     layer2->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
434
435     layer1->updateCompositorResources(0, updater);
436     layer2->updateCompositorResources(0, updater);
437
438     layer1->pushPropertiesTo(layer1Impl.get());
439     layer2->pushPropertiesTo(layer2Impl.get());
440
441     // We should have both tiles on the impl side for all layers.
442     EXPECT_TRUE(layer1Impl->hasTileAt(0, 0));
443     EXPECT_TRUE(layer1Impl->hasTileAt(0, 1));
444     EXPECT_TRUE(layer2Impl->hasTileAt(0, 0));
445     EXPECT_TRUE(layer2Impl->hasTileAt(0, 1));
446 }
447
448 TEST(TiledLayerChromiumTest, pushTilesLayerMarkedDirtyDuringPaintOnPreviousLayer)
449 {
450     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
451     RefPtr<FakeTiledLayerChromium> layer1 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
452     RefPtr<FakeTiledLayerChromium> layer2 = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
453     DebugScopedSetImplThread implThread;
454     OwnPtr<FakeCCTiledLayerImpl> layer1Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
455     OwnPtr<FakeCCTiledLayerImpl> layer2Impl(adoptPtr(new FakeCCTiledLayerImpl(0)));
456
457     FakeTextureAllocator textureAllocator;
458     CCTextureUpdater updater(&textureAllocator);
459
460     layer1->setBounds(IntSize(100, 200));
461     layer1->invalidateRect(IntRect(0, 0, 100, 200));
462     layer2->setBounds(IntSize(100, 200));
463     layer2->invalidateRect(IntRect(0, 0, 100, 200));
464
465     // Invalidate a tile on layer2
466     layer1->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(0, 50, 100, 50), layer2.get());
467     layer1->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
468
469     layer2->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
470
471     layer1->updateCompositorResources(0, updater);
472     layer2->updateCompositorResources(0, updater);
473
474     layer1->pushPropertiesTo(layer1Impl.get());
475     layer2->pushPropertiesTo(layer2Impl.get());
476
477     // We should have both tiles on the impl side for all layers.
478     EXPECT_TRUE(layer1Impl->hasTileAt(0, 0));
479     EXPECT_TRUE(layer1Impl->hasTileAt(0, 1));
480     EXPECT_TRUE(layer2Impl->hasTileAt(0, 0));
481     EXPECT_TRUE(layer2Impl->hasTileAt(0, 1));
482 }
483
484 TEST(TiledLayerChromiumTest, idlePaintOutOfMemory)
485 {
486     // The tile size is 100x100. Setup 5x5 tiles with one 1x1 visible tile in the center.
487     IntSize contentBounds(300, 300);
488     IntRect contentRect(IntPoint::zero(), contentBounds);
489     IntRect visibleRect(100, 100, 100, 100);
490
491     // We have enough memory for only the visible rect, so we will run out of memory in first idle paint.
492     int memoryLimit = 4 * 100 * 100; // 2 tiles, 4 bytes per pixel.
493
494     OwnPtr<TextureManager> textureManager = TextureManager::create(memoryLimit, memoryLimit / 2, 1024);
495     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
496     DebugScopedSetImplThread implThread;
497     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
498
499     FakeTextureAllocator textureAllocator;
500     CCTextureUpdater updater(&textureAllocator);
501
502     // This invalidates 9 tiles and then paints one visible tile.
503     layer->setBounds(contentBounds);
504     layer->setVisibleLayerRect(visibleRect);
505     layer->invalidateRect(contentRect);
506     layer->prepareToUpdate(visibleRect, 0);
507
508     // We should need idle-painting for 3x3 tiles surounding visible tile.
509     EXPECT_TRUE(layer->needsIdlePaint(visibleRect));
510
511     layer->updateCompositorResources(0, updater);
512     layer->pushPropertiesTo(layerImpl.get());
513
514     // We should have one tile on the impl side.
515     EXPECT_TRUE(layerImpl->hasTileAt(1, 1));
516
517     textureManager->unprotectAllTextures();
518     layer->prepareToUpdate(visibleRect, 0);
519     layer->prepareToUpdateIdle(visibleRect, 0);
520
521     // We shouldn't signal we need another idle paint after we run out of memory.
522     EXPECT_FALSE(layer->needsIdlePaint(visibleRect));
523
524     layer->updateCompositorResources(0, updater);
525     layer->pushPropertiesTo(layerImpl.get());
526 }
527
528 TEST(TiledLayerChromiumTest, invalidateFromPrepare)
529 {
530     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
531     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
532     DebugScopedSetImplThread implThread;
533     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
534
535     FakeTextureAllocator textureAllocator;
536     CCTextureUpdater updater(&textureAllocator);
537
538     // The tile size is 100x100, so this invalidates and then paints two tiles.
539     layer->setBounds(IntSize(100, 200));
540     layer->invalidateRect(IntRect(0, 0, 100, 200));
541     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
542     layer->updateCompositorResources(0, updater);
543     layer->pushPropertiesTo(layerImpl.get());
544
545     // We should have both tiles on the impl side.
546     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
547     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
548
549     textureManager->unprotectAllTextures();
550
551     layer->fakeLayerTextureUpdater()->clearPrepareCount();
552     // Invoke prepareToUpdate again. As the layer is valid prepareToUpdate shouldn't be invoked on
553     // the LayerTextureUpdater.
554     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
555     EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareCount());
556
557     layer->invalidateRect(IntRect(0, 0, 50, 50));
558     // setRectToInvalidate triggers invalidateRect() being invoked from prepareToUpdate.
559     layer->fakeLayerTextureUpdater()->setRectToInvalidate(IntRect(25, 25, 50, 50), layer.get());
560     layer->fakeLayerTextureUpdater()->clearPrepareCount();
561     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
562     EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
563     layer->fakeLayerTextureUpdater()->clearPrepareCount();
564     // The layer should still be invalid as prepareToUpdate invoked invalidate.
565     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
566     EXPECT_EQ(1, layer->fakeLayerTextureUpdater()->prepareCount());
567 }
568
569 TEST(TiledLayerChromiumTest, verifyUpdateRectWhenContentBoundsAreScaled)
570 {
571     // The updateRect (that indicates what was actually painted) should be in
572     // layer space, not the content space.
573
574     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
575     RefPtr<FakeTiledLayerWithScaledBounds> layer = adoptRef(new FakeTiledLayerWithScaledBounds(textureManager.get()));
576
577     FakeTextureAllocator textureAllocator;
578     CCTextureUpdater updater(&textureAllocator);
579
580     IntRect layerBounds(0, 0, 300, 200);
581     IntRect contentBounds(0, 0, 200, 250);
582
583     layer->setBounds(layerBounds.size());
584     layer->setContentBounds(contentBounds.size());
585     layer->setVisibleLayerRect(contentBounds);
586
587     // On first update, the updateRect includes all tiles, even beyond the boundaries of the layer.
588     // However, it should still be in layer space, not content space.
589     layer->invalidateRect(contentBounds);
590     layer->prepareToUpdate(contentBounds, 0);
591     layer->updateCompositorResources(0, updater);
592     EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 300, 300 * 0.8), layer->updateRect());
593
594     // After the tiles are updated once, another invalidate only needs to update the bounds of the layer.
595     layer->invalidateRect(contentBounds);
596     layer->prepareToUpdate(contentBounds, 0);
597     layer->updateCompositorResources(0, updater);
598     EXPECT_FLOAT_RECT_EQ(FloatRect(layerBounds), layer->updateRect());
599
600     // Partial re-paint should also be represented by the updateRect in layer space, not content space.
601     IntRect partialDamage(30, 100, 10, 10);
602     layer->invalidateRect(partialDamage);
603     layer->prepareToUpdate(contentBounds, 0);
604     layer->updateCompositorResources(0, updater);
605     EXPECT_FLOAT_RECT_EQ(FloatRect(45, 80, 15, 8), layer->updateRect());
606 }
607
608 TEST(TiledLayerChromiumTest, verifyInvalidationWhenContentsScaleChanges)
609 {
610     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
611     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
612     DebugScopedSetImplThread implThread;
613     OwnPtr<FakeCCTiledLayerImpl> layerImpl(adoptPtr(new FakeCCTiledLayerImpl(0)));
614
615     FakeTextureAllocator textureAllocator;
616     CCTextureUpdater updater(&textureAllocator);
617
618     // Create a layer with one tile.
619     layer->setBounds(IntSize(100, 100));
620
621     // Invalidate the entire layer.
622     layer->setNeedsDisplay();
623     EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
624
625     // Push the tiles to the impl side and check that there is exactly one.
626     layer->prepareToUpdate(IntRect(0, 0, 100, 100), 0);
627     layer->updateCompositorResources(0, updater);
628     layer->pushPropertiesTo(layerImpl.get());
629     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
630     EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
631     EXPECT_FALSE(layerImpl->hasTileAt(1, 0));
632     EXPECT_FALSE(layerImpl->hasTileAt(1, 1));
633
634     // Change the contents scale and verify that the content rectangle requiring painting
635     // is not scaled.
636     layer->setContentsScale(2);
637     EXPECT_FLOAT_RECT_EQ(FloatRect(0, 0, 100, 100), layer->lastNeedsDisplayRect());
638
639     // The impl side should get 2x2 tiles now.
640     layer->prepareToUpdate(IntRect(0, 0, 200, 200), 0);
641     layer->updateCompositorResources(0, updater);
642     layer->pushPropertiesTo(layerImpl.get());
643     EXPECT_TRUE(layerImpl->hasTileAt(0, 0));
644     EXPECT_TRUE(layerImpl->hasTileAt(0, 1));
645     EXPECT_TRUE(layerImpl->hasTileAt(1, 0));
646     EXPECT_TRUE(layerImpl->hasTileAt(1, 1));
647
648     // Invalidate the entire layer again, but do not paint. All tiles should be gone now from the
649     // impl side.
650     layer->setNeedsDisplay();
651     layer->prepareToUpdate(IntRect(1, 0, 0, 1), 0);
652     layer->updateCompositorResources(0, updater);
653     layer->pushPropertiesTo(layerImpl.get());
654     EXPECT_FALSE(layerImpl->hasTileAt(0, 0));
655     EXPECT_FALSE(layerImpl->hasTileAt(0, 1));
656     EXPECT_FALSE(layerImpl->hasTileAt(1, 0));
657     EXPECT_FALSE(layerImpl->hasTileAt(1, 1));
658 }
659
660 TEST(TiledLayerChromiumTest, skipsDrawGetsReset)
661 {
662     // Initialize without threading support.
663     WebKit::WebCompositor::initialize(0);
664     FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
665     RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, CCSettings());
666
667     // Create two 300 x 300 tiled layers.
668     IntSize contentBounds(300, 300);
669     IntRect contentRect(IntPoint::zero(), contentBounds);
670
671     // We have enough memory for only one of the two layers.
672     int memoryLimit = 4 * 300 * 300; // 4 bytes per pixel.
673     OwnPtr<TextureManager> textureManager = TextureManager::create(memoryLimit, memoryLimit, memoryLimit);
674
675     RefPtr<FakeTiledLayerChromium> rootLayer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
676     RefPtr<FakeTiledLayerChromium> childLayer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
677     rootLayer->addChild(childLayer);
678
679     rootLayer->setBounds(contentBounds);
680     rootLayer->setPosition(FloatPoint(150, 150));
681     childLayer->setBounds(contentBounds);
682     childLayer->setPosition(FloatPoint(150, 150));
683     rootLayer->invalidateRect(contentRect);
684     childLayer->invalidateRect(contentRect);
685
686     FakeTextureAllocator textureAllocator;
687     CCTextureUpdater updater(&textureAllocator);
688
689     ccLayerTreeHost->setRootLayer(rootLayer);
690     ccLayerTreeHost->setViewportSize(IntSize(300, 300));
691     textureManager->setMaxMemoryLimitBytes(memoryLimit);
692     ccLayerTreeHost->updateLayers();
693     ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
694
695     // We'll skip the root layer.
696     EXPECT_TRUE(rootLayer->skipsDraw());
697     EXPECT_FALSE(childLayer->skipsDraw());
698
699     ccLayerTreeHost->commitComplete();
700     textureManager->unprotectAllTextures(); // CCLayerTreeHost::commitComplete() normally does this, but since we're mocking out the manager we have to do it.
701
702     // Remove the child layer.
703     rootLayer->removeAllChildren();
704
705     ccLayerTreeHost->updateLayers();
706     EXPECT_FALSE(rootLayer->skipsDraw());
707
708     ccLayerTreeHost->setRootLayer(0);
709     ccLayerTreeHost.clear();
710     WebKit::WebCompositor::shutdown();
711 }
712
713 TEST(TiledLayerChromiumTest, resizeToSmaller)
714 {
715     OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
716     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
717
718     layer->setBounds(IntSize(700, 700));
719     layer->invalidateRect(IntRect(0, 0, 700, 700));
720     layer->prepareToUpdate(IntRect(0, 0, 700, 700), 0);
721
722     layer->setBounds(IntSize(200, 200));
723     layer->invalidateRect(IntRect(0, 0, 200, 200));
724 }
725
726 TEST(TiledLayerChromiumTest, partialUpdates)
727 {
728     CCSettings settings;
729     settings.maxPartialTextureUpdates = 4;
730     // Initialize without threading support.
731     WebKit::WebCompositor::initialize(0);
732     FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
733     RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, settings);
734
735     // Create one 500 x 300 tiled layer.
736     IntSize contentBounds(300, 200);
737     IntRect contentRect(IntPoint::zero(), contentBounds);
738
739     OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
740     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
741     layer->setBounds(contentBounds);
742     layer->setPosition(FloatPoint(150, 150));
743     layer->invalidateRect(contentRect);
744
745     FakeTextureAllocator textureAllocator;
746     CCTextureUpdater updater(&textureAllocator);
747
748     ccLayerTreeHost->setRootLayer(layer);
749     ccLayerTreeHost->setViewportSize(IntSize(300, 200));
750
751     // Full update of all 6 tiles.
752     ccLayerTreeHost->updateLayers();
753     ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
754     updater.update(0, 4);
755     EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
756     EXPECT_TRUE(updater.hasMoreUpdates());
757     layer->fakeLayerTextureUpdater()->clearUpdateCount();
758     updater.update(0, 4);
759     EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
760     EXPECT_FALSE(updater.hasMoreUpdates());
761     layer->fakeLayerTextureUpdater()->clearUpdateCount();
762     ccLayerTreeHost->commitComplete();
763
764     // Full update of 3 tiles and partial update of 3 tiles.
765     layer->invalidateRect(IntRect(0, 0, 300, 150));
766     ccLayerTreeHost->updateLayers();
767     ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
768     updater.update(0, 4);
769     EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
770     EXPECT_TRUE(updater.hasMoreUpdates());
771     layer->fakeLayerTextureUpdater()->clearUpdateCount();
772     updater.update(0, 4);
773     EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
774     EXPECT_FALSE(updater.hasMoreUpdates());
775     layer->fakeLayerTextureUpdater()->clearUpdateCount();
776     ccLayerTreeHost->commitComplete();
777
778     // Partial update of 6 tiles.
779     layer->invalidateRect(IntRect(50, 50, 200, 100));
780     ccLayerTreeHost->updateLayers();
781     ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
782     updater.update(0, 4);
783     EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
784     EXPECT_TRUE(updater.hasMoreUpdates());
785     layer->fakeLayerTextureUpdater()->clearUpdateCount();
786     updater.update(0, 4);
787     EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
788     EXPECT_FALSE(updater.hasMoreUpdates());
789     layer->fakeLayerTextureUpdater()->clearUpdateCount();
790     ccLayerTreeHost->commitComplete();
791
792     ccLayerTreeHost->setRootLayer(0);
793     ccLayerTreeHost.clear();
794     WebKit::WebCompositor::shutdown();
795 }
796
797 TEST(TiledLayerChromiumTest, tilesPaintedWithoutOcclusion)
798 {
799     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
800     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
801
802     // The tile size is 100x100, so this invalidates and then paints two tiles.
803     layer->setBounds(IntSize(100, 200));
804
805     layer->invalidateRect(IntRect(0, 0, 100, 200));
806     layer->prepareToUpdate(IntRect(0, 0, 100, 200), 0);
807     EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->prepareRectCount());
808 }
809
810 TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusion)
811 {
812     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
813     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
814     TestCCOcclusionTracker occluded;
815
816     // The tile size is 100x100.
817
818     layer->setBounds(IntSize(600, 600));
819     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
820
821     occluded.setOcclusion(IntRect(200, 200, 300, 100));
822     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
823     layer->invalidateRect(IntRect(0, 0, 600, 600));
824     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
825     EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
826
827     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
828
829     occluded.setOcclusion(IntRect(250, 200, 300, 100));
830     layer->invalidateRect(IntRect(0, 0, 600, 600));
831     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
832     EXPECT_EQ(36-2, layer->fakeLayerTextureUpdater()->prepareRectCount());
833
834     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
835
836     occluded.setOcclusion(IntRect(250, 250, 300, 100));
837     layer->invalidateRect(IntRect(0, 0, 600, 600));
838     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
839     EXPECT_EQ(36, layer->fakeLayerTextureUpdater()->prepareRectCount());
840 }
841
842 TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndVisiblityConstraints)
843 {
844     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
845     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
846     TestCCOcclusionTracker occluded;
847
848     // The tile size is 100x100.
849
850     layer->setBounds(IntSize(600, 600));
851     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
852
853     // The partially occluded tiles (by the 150 occlusion height) are visible beyond the occlusion, so not culled.
854     occluded.setOcclusion(IntRect(200, 200, 300, 150));
855     layer->setVisibleLayerRect(IntRect(0, 0, 600, 360));
856     layer->invalidateRect(IntRect(0, 0, 600, 600));
857     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
858     EXPECT_EQ(24-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
859
860     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
861
862     // Now the visible region stops at the edge of the occlusion so the partly visible tiles become fully occluded.
863     occluded.setOcclusion(IntRect(200, 200, 300, 150));
864     layer->setVisibleLayerRect(IntRect(0, 0, 600, 350));
865     layer->invalidateRect(IntRect(0, 0, 600, 600));
866     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
867     EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
868
869     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
870
871     // Now the visible region is even smaller than the occlusion, it should have the same result.
872     occluded.setOcclusion(IntRect(200, 200, 300, 150));
873     layer->setVisibleLayerRect(IntRect(0, 0, 600, 340));
874     layer->invalidateRect(IntRect(0, 0, 600, 600));
875     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
876     EXPECT_EQ(24-6, layer->fakeLayerTextureUpdater()->prepareRectCount());
877 }
878
879 TEST(TiledLayerChromiumTest, tilesNotPaintedWithoutInvalidation)
880 {
881     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
882     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
883     TestCCOcclusionTracker occluded;
884
885     // The tile size is 100x100.
886
887     layer->setBounds(IntSize(600, 600));
888     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
889
890     occluded.setOcclusion(IntRect(200, 200, 300, 100));
891     layer->setVisibleLayerRect(IntRect(0, 0, 600, 600));
892     layer->invalidateRect(IntRect(0, 0, 600, 600));
893     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
894     EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
895
896     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
897
898     // Repaint without marking it dirty.
899     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
900     EXPECT_EQ(0, layer->fakeLayerTextureUpdater()->prepareRectCount());
901 }
902
903 TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndTransforms)
904 {
905     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
906     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
907     TestCCOcclusionTracker occluded;
908
909     // The tile size is 100x100.
910
911     // This makes sure the painting works when the occluded region (in screen space)
912     // is transformed differently than the layer.
913     layer->setBounds(IntSize(600, 600));
914     TransformationMatrix screenTransform;
915     screenTransform.scale(0.5);
916     layer->setScreenSpaceTransform(screenTransform);
917     layer->setDrawTransform(screenTransform * TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
918
919     occluded.setOcclusion(IntRect(100, 100, 150, 50));
920     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
921     layer->invalidateRect(IntRect(0, 0, 600, 600));
922     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
923     EXPECT_EQ(36-3, layer->fakeLayerTextureUpdater()->prepareRectCount());
924 }
925
926 TEST(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
927 {
928     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
929     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
930     TestCCOcclusionTracker occluded;
931
932     // The tile size is 100x100.
933
934     // This makes sure the painting works when the content space is scaled to
935     // a different layer space. In this case tiles are scaled to be 200x200
936     // pixels, which means none should be occluded.
937     layer->setContentsScale(0.5);
938     layer->setBounds(IntSize(600, 600));
939     layer->setDrawTransform(TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
940
941     occluded.setOcclusion(IntRect(200, 200, 300, 100));
942     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
943     layer->invalidateRect(IntRect(0, 0, 600, 600));
944     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
945     // The content is half the size of the layer (so the number of tiles is fewer).
946     // In this case, the content is 300x300, and since the tile size is 100, the
947     // number of tiles 3x3.
948     EXPECT_EQ(9, layer->fakeLayerTextureUpdater()->prepareRectCount());
949
950     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
951
952     // This makes sure the painting works when the content space is scaled to
953     // a different layer space. In this case the occluded region catches the
954     // blown up tiles.
955     occluded.setOcclusion(IntRect(200, 200, 300, 200));
956     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
957     layer->invalidateRect(IntRect(0, 0, 600, 600));
958     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
959     EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount());
960
961     layer->fakeLayerTextureUpdater()->clearPrepareRectCount();
962
963     // This makes sure content scaling and transforms work together.
964     TransformationMatrix screenTransform;
965     screenTransform.scale(0.5);
966     layer->setScreenSpaceTransform(screenTransform);
967     layer->setDrawTransform(screenTransform * TransformationMatrix(1, 0, 0, 1, layer->bounds().width() / 2.0, layer->bounds().height() / 2.0));
968
969     occluded.setOcclusion(IntRect(100, 100, 150, 100));
970     layer->setVisibleLayerRect(IntRect(IntPoint(), layer->bounds()));
971     layer->invalidateRect(IntRect(0, 0, 600, 600));
972     layer->prepareToUpdate(IntRect(0, 0, 600, 600), &occluded);
973     EXPECT_EQ(9-1, layer->fakeLayerTextureUpdater()->prepareRectCount());
974 }
975
976 TEST(TiledLayerChromiumTest, opaqueContentsRegion)
977 {
978     OwnPtr<TextureManager> textureManager = TextureManager::create(4*1024*1024, 2*1024*1024, 1024);
979     RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
980
981     // The tile size is 100x100, so this invalidates and then paints two tiles in various ways.
982
983     IntRect opaquePaintRect;
984     Region opaqueContents;
985
986     IntRect contentBounds = IntRect(0, 0, 100, 200);
987     IntRect visibleBounds = IntRect(0, 0, 100, 150);
988
989     layer->setBounds(contentBounds.size());
990     layer->setVisibleLayerRect(visibleBounds);
991     layer->setDrawOpacity(1);
992
993     // If the layer doesn't paint opaque content, then the opaqueContentsRegion should be empty.
994     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
995     layer->invalidateRect(contentBounds);
996     layer->prepareToUpdate(contentBounds, 0);
997     opaqueContents = layer->opaqueContentsRegion();
998     EXPECT_TRUE(opaqueContents.isEmpty());
999
1000     // opaqueContentsRegion should match the visible part of what is painted opaque.
1001     opaquePaintRect = IntRect(10, 10, 90, 190);
1002     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
1003     layer->invalidateRect(contentBounds);
1004     layer->prepareToUpdate(contentBounds, 0);
1005     opaqueContents = layer->opaqueContentsRegion();
1006     EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
1007     EXPECT_EQ(1u, opaqueContents.rects().size());
1008
1009     // If we paint again without invalidating, the same stuff should be opaque.
1010     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
1011     layer->prepareToUpdate(contentBounds, 0);
1012     opaqueContents = layer->opaqueContentsRegion();
1013     EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
1014     EXPECT_EQ(1u, opaqueContents.rects().size());
1015
1016     // If we repaint a non-opaque part of the tile, then it shouldn't lose its opaque-ness. And other tiles should
1017     // not be affected.
1018     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
1019     layer->invalidateRect(IntRect(0, 0, 1, 1));
1020     layer->prepareToUpdate(contentBounds, 0);
1021     opaqueContents = layer->opaqueContentsRegion();
1022     EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), opaqueContents.bounds());
1023     EXPECT_EQ(1u, opaqueContents.rects().size());
1024
1025     // If we repaint an opaque part of the tile, then it should lose its opaque-ness. But other tiles should still
1026     // not be affected.
1027     layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
1028     layer->invalidateRect(IntRect(10, 10, 1, 1));
1029     layer->prepareToUpdate(contentBounds, 0);
1030     opaqueContents = layer->opaqueContentsRegion();
1031     EXPECT_EQ_RECT(intersection(IntRect(10, 100, 90, 100), visibleBounds), opaqueContents.bounds());
1032     EXPECT_EQ(1u, opaqueContents.rects().size());
1033 }
1034
1035 } // namespace