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