[chromium] Use opaque contents for paint culling
[WebKit-https.git] / Source / WebKit / chromium / tests / CCLayerTreeHostTest.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 "cc/CCLayerTreeHost.h"
28
29 #include "CCAnimationTestCommon.h"
30 #include "CompositorFakeWebGraphicsContext3D.h"
31 #include "ContentLayerChromium.h"
32 #include "FilterOperations.h"
33 #include "GraphicsContext3DPrivate.h"
34 #include "LayerChromium.h"
35 #include "TextureManager.h"
36 #include "WebCompositor.h"
37 #include "WebKit.h"
38 #include "cc/CCActiveAnimation.h"
39 #include "cc/CCLayerAnimationController.h"
40 #include "cc/CCLayerAnimationDelegate.h"
41 #include "cc/CCLayerImpl.h"
42 #include "cc/CCLayerTreeHostImpl.h"
43 #include "cc/CCScopedThreadProxy.h"
44 #include "cc/CCTextureUpdater.h"
45 #include "cc/CCThreadTask.h"
46 #include "platform/WebKitPlatformSupport.h"
47 #include "platform/WebThread.h"
48 #include <gmock/gmock.h>
49 #include <gtest/gtest.h>
50 #include <wtf/MainThread.h>
51 #include <wtf/PassRefPtr.h>
52 #include <wtf/Vector.h>
53
54 using namespace WebCore;
55 using namespace WebKit;
56 using namespace WebKitTests;
57 using namespace WTF;
58
59 namespace {
60
61 // Used by test stubs to notify the test when something interesting happens.
62 class TestHooks : public CCLayerAnimationDelegate {
63 public:
64     virtual void beginCommitOnCCThread(CCLayerTreeHostImpl*) { }
65     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*) { }
66     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl*) { }
67     virtual void animateLayers(CCLayerTreeHostImpl*, double monotonicTime) { }
68     virtual void applyScrollAndScale(const IntSize&, float) { }
69     virtual void updateAnimations(double monotonicTime) { }
70     virtual void layout() { }
71     virtual void didRecreateContext(bool succeded) { }
72     virtual void didCommitAndDrawFrame() { }
73
74     // Implementation of CCLayerAnimationDelegate
75     virtual void notifyAnimationStarted(double time) { }
76 };
77
78 // Adapts CCLayerTreeHostImpl for test. Runs real code, then invokes test hooks.
79 class MockLayerTreeHostImpl : public CCLayerTreeHostImpl {
80 public:
81     static PassOwnPtr<MockLayerTreeHostImpl> create(TestHooks* testHooks, const CCSettings& settings, CCLayerTreeHostImplClient* client)
82     {
83         return adoptPtr(new MockLayerTreeHostImpl(testHooks, settings, client));
84     }
85
86     virtual void beginCommit()
87     {
88         CCLayerTreeHostImpl::beginCommit();
89         m_testHooks->beginCommitOnCCThread(this);
90     }
91
92     virtual void commitComplete()
93     {
94         CCLayerTreeHostImpl::commitComplete();
95         m_testHooks->commitCompleteOnCCThread(this);
96     }
97
98     virtual void drawLayers()
99     {
100         CCLayerTreeHostImpl::drawLayers();
101         m_testHooks->drawLayersOnCCThread(this);
102     }
103
104 protected:
105     virtual void animateLayers(double monotonicTime, double wallClockTime)
106     {
107         CCLayerTreeHostImpl::animateLayers(monotonicTime, wallClockTime);
108         m_testHooks->animateLayers(this, monotonicTime);
109     }
110
111 private:
112     MockLayerTreeHostImpl(TestHooks* testHooks, const CCSettings& settings, CCLayerTreeHostImplClient* client)
113         : CCLayerTreeHostImpl(settings, client)
114         , m_testHooks(testHooks)
115     {
116     }
117
118     TestHooks* m_testHooks;
119 };
120
121 // Adapts CCLayerTreeHost for test. Injects MockLayerTreeHostImpl.
122 class MockLayerTreeHost : public CCLayerTreeHost {
123 public:
124     static PassRefPtr<MockLayerTreeHost> create(TestHooks* testHooks, CCLayerTreeHostClient* client, PassRefPtr<LayerChromium> rootLayer, const CCSettings& settings)
125     {
126         // For these tests, we will enable threaded animations.
127         CCSettings settingsCopy = settings;
128         settingsCopy.threadedAnimationEnabled = true;
129
130         RefPtr<MockLayerTreeHost> layerTreeHost = adoptRef(new MockLayerTreeHost(testHooks, client, settingsCopy));
131         bool success = layerTreeHost->initialize();
132         EXPECT_TRUE(success);
133         layerTreeHost->setRootLayer(rootLayer);
134
135         // LayerTreeHostImpl won't draw if it has 1x1 viewport.
136         layerTreeHost->setViewportSize(IntSize(1, 1));
137
138         layerTreeHost->rootLayer()->setLayerAnimationDelegate(testHooks);
139
140         return layerTreeHost.release();
141     }
142
143     virtual PassOwnPtr<CCLayerTreeHostImpl> createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
144     {
145         // For these tests, we will enable threaded animations.
146         CCSettings settings;
147         settings.threadedAnimationEnabled = true;
148         return MockLayerTreeHostImpl::create(m_testHooks, settings, client);
149     }
150
151 private:
152     MockLayerTreeHost(TestHooks* testHooks, CCLayerTreeHostClient* client, const CCSettings& settings)
153         : CCLayerTreeHost(client, settings)
154         , m_testHooks(testHooks)
155     {
156     }
157
158     TestHooks* m_testHooks;
159 };
160
161 class CompositorFakeWebGraphicsContext3DWithTextureTracking : public CompositorFakeWebGraphicsContext3D {
162 public:
163     static PassOwnPtr<CompositorFakeWebGraphicsContext3DWithTextureTracking> create(Attributes attrs)
164     {
165         return adoptPtr(new CompositorFakeWebGraphicsContext3DWithTextureTracking(attrs));
166     }
167
168     virtual WebGLId createTexture()
169     {
170         WebGLId texture = m_textures.size() + 1;
171         m_textures.append(texture);
172         return texture;
173     }
174
175     virtual void deleteTexture(WebGLId texture)
176     {
177         for (size_t i = 0; i < m_textures.size(); i++) {
178             if (m_textures[i] == texture) {
179                 m_textures.remove(i);
180                 break;
181             }
182         }
183     }
184
185     virtual void bindTexture(WGC3Denum /* target */, WebGLId texture)
186     {
187         m_usedTextures.add(texture);
188     }
189
190     int numTextures() const { return static_cast<int>(m_textures.size()); }
191     int texture(int i) const { return m_textures[i]; }
192     void resetTextures() { m_textures.clear(); }
193
194     int numUsedTextures() const { return static_cast<int>(m_usedTextures.size()); }
195     bool usedTexture(int texture) const { return m_usedTextures.find(texture) != m_usedTextures.end(); }
196     void resetUsedTextures() { m_usedTextures.clear(); }
197
198 private:
199     explicit CompositorFakeWebGraphicsContext3DWithTextureTracking(Attributes attrs) : CompositorFakeWebGraphicsContext3D(attrs)
200     {
201     }
202
203     Vector<WebGLId> m_textures;
204     HashSet<WebGLId> m_usedTextures;
205 };
206
207 // Implementation of CCLayerTreeHost callback interface.
208 class MockLayerTreeHostClient : public CCLayerTreeHostClient {
209 public:
210     static PassOwnPtr<MockLayerTreeHostClient> create(TestHooks* testHooks)
211     {
212         return adoptPtr(new MockLayerTreeHostClient(testHooks));
213     }
214
215     virtual void updateAnimations(double monotonicTime)
216     {
217         m_testHooks->updateAnimations(monotonicTime);
218     }
219
220     virtual void layout()
221     {
222         m_testHooks->layout();
223     }
224
225     virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale)
226     {
227         m_testHooks->applyScrollAndScale(scrollDelta, scale);
228     }
229
230     virtual PassRefPtr<GraphicsContext3D> createContext()
231     {
232         GraphicsContext3D::Attributes attrs;
233         WebGraphicsContext3D::Attributes webAttrs;
234         webAttrs.alpha = attrs.alpha;
235
236         OwnPtr<WebGraphicsContext3D> webContext = CompositorFakeWebGraphicsContext3DWithTextureTracking::create(webAttrs);
237         return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(webContext.release(), GraphicsContext3D::RenderDirectlyToHostWindow);
238     }
239
240     virtual void didCommitAndDrawFrame()
241     {
242         m_testHooks->didCommitAndDrawFrame();
243     }
244
245     virtual void didCompleteSwapBuffers()
246     {
247     }
248
249     virtual void didRecreateContext(bool succeeded)
250     {
251         m_testHooks->didRecreateContext(succeeded);
252     }
253
254     virtual void scheduleComposite()
255     {
256     }
257
258 private:
259     explicit MockLayerTreeHostClient(TestHooks* testHooks) : m_testHooks(testHooks) { }
260
261     TestHooks* m_testHooks;
262 };
263
264 // The CCLayerTreeHostTest runs with the main loop running. It instantiates a single MockLayerTreeHost and associated
265 // MockLayerTreeHostImpl/MockLayerTreeHostClient.
266 //
267 // beginTest() is called once the main message loop is running and the layer tree host is initialized.
268 //
269 // Key stages of the drawing loop, e.g. drawing or commiting, redirect to CCLayerTreeHostTest methods of similar names.
270 // To track the commit process, override these functions.
271 //
272 // The test continues until someone calls endTest. endTest can be called on any thread, but be aware that
273 // ending the test is an asynchronous process.
274 class CCLayerTreeHostTest : public testing::Test, TestHooks {
275 public:
276     virtual void afterTest() = 0;
277     virtual void beginTest() = 0;
278
279     void endTest();
280
281     void postSetNeedsAnimateToMainThread()
282     {
283         callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsAnimate, this);
284     }
285
286     void postAddAnimationToMainThread()
287     {
288         callOnMainThread(CCLayerTreeHostTest::dispatchAddAnimation, this);
289     }
290
291     void postAddInstantAnimationToMainThread()
292     {
293         callOnMainThread(CCLayerTreeHostTest::dispatchAddInstantAnimation, this);
294     }
295
296     void postSetNeedsCommitToMainThread()
297     {
298         callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsCommit, this);
299     }
300
301     void postSetNeedsRedrawToMainThread()
302     {
303         callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsRedraw, this);
304     }
305
306     void postSetNeedsAnimateAndCommitToMainThread()
307     {
308         callOnMainThread(CCLayerTreeHostTest::dispatchSetNeedsAnimateAndCommit, this);
309     }
310
311     void postSetVisibleToMainThread(bool visible)
312     {
313         callOnMainThread(visible ? CCLayerTreeHostTest::dispatchSetVisible : CCLayerTreeHostTest::dispatchSetInvisible, this);
314     }
315
316     void timeout()
317     {
318         m_timedOut = true;
319         endTest();
320     }
321
322     void clearTimeout()
323     {
324         m_timeoutTask = 0;
325     }
326
327     CCLayerTreeHost* layerTreeHost() { return m_layerTreeHost.get(); }
328
329
330 protected:
331     CCLayerTreeHostTest()
332         : m_beginning(false)
333         , m_endWhenBeginReturns(false)
334         , m_timedOut(false) { }
335
336     void doBeginTest();
337
338     static void onEndTest(void* self)
339     {
340         ASSERT(isMainThread());
341         webKitPlatformSupport()->currentThread()->exitRunLoop();
342     }
343
344     static void dispatchSetNeedsAnimate(void* self)
345     {
346         ASSERT(isMainThread());
347         CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
348         ASSERT(test);
349         if (test->m_layerTreeHost)
350             test->m_layerTreeHost->setNeedsAnimate();
351     }
352
353     static void dispatchAddInstantAnimation(void* self)
354     {
355         ASSERT(isMainThread());
356         CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
357         ASSERT(test);
358         if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
359             addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 0.5);
360     }
361
362     static void dispatchAddAnimation(void* self)
363     {
364         ASSERT(isMainThread());
365         CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
366         ASSERT(test);
367         if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
368             addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 10, 0, 0.5);
369     }
370
371     static void dispatchSetNeedsAnimateAndCommit(void* self)
372     {
373         ASSERT(isMainThread());
374         CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
375         ASSERT(test);
376         if (test->m_layerTreeHost) {
377             test->m_layerTreeHost->setNeedsAnimate();
378             test->m_layerTreeHost->setNeedsCommit();
379         }
380     }
381
382     static void dispatchSetNeedsCommit(void* self)
383     {
384         ASSERT(isMainThread());
385         CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
386         ASSERT_TRUE(test);
387         if (test->m_layerTreeHost)
388             test->m_layerTreeHost->setNeedsCommit();
389     }
390
391     static void dispatchSetNeedsRedraw(void* self)
392     {
393         ASSERT(isMainThread());
394         CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
395         ASSERT_TRUE(test);
396         if (test->m_layerTreeHost)
397             test->m_layerTreeHost->setNeedsRedraw();
398     }
399
400     static void dispatchSetVisible(void* self)
401     {
402         ASSERT(isMainThread());
403         CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
404         ASSERT(test);
405         if (test->m_layerTreeHost)
406             test->m_layerTreeHost->setVisible(true);
407     }
408
409     static void dispatchSetInvisible(void* self)
410     {
411         ASSERT(isMainThread());
412         CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
413         ASSERT(test);
414         if (test->m_layerTreeHost)
415             test->m_layerTreeHost->setVisible(false);
416     }
417
418     class TimeoutTask : public WebThread::Task {
419     public:
420         explicit TimeoutTask(CCLayerTreeHostTest* test)
421             : m_test(test)
422         {
423         }
424
425         void clearTest()
426         {
427             m_test = 0;
428         }
429
430         virtual ~TimeoutTask()
431         {
432             if (m_test)
433                 m_test->clearTimeout();
434         }
435
436         virtual void run()
437         {
438             if (m_test)
439                 m_test->timeout();
440         }
441
442     private:
443         CCLayerTreeHostTest* m_test;
444     };
445
446     class BeginTask : public WebThread::Task {
447     public:
448         explicit BeginTask(CCLayerTreeHostTest* test)
449             : m_test(test)
450         {
451         }
452
453         virtual ~BeginTask() { }
454         virtual void run()
455         {
456             m_test->doBeginTest();
457         }
458     private:
459         CCLayerTreeHostTest* m_test;
460     };
461
462     virtual void runTest(bool threaded)
463     {
464         if (threaded) {
465             m_webThread = adoptPtr(webKitPlatformSupport()->createThread("CCLayerTreeHostTest"));
466             WebCompositor::initialize(m_webThread.get());
467         } else
468             WebCompositor::initialize(0);
469
470         ASSERT(CCProxy::isMainThread());
471         m_mainThreadProxy = CCScopedThreadProxy::create(CCProxy::mainThread());
472
473         m_beginTask = new BeginTask(this);
474         webKitPlatformSupport()->currentThread()->postDelayedTask(m_beginTask, 0); // postDelayedTask takes ownership of the task
475         m_timeoutTask = new TimeoutTask(this);
476         webKitPlatformSupport()->currentThread()->postDelayedTask(m_timeoutTask, 5000);
477         webKitPlatformSupport()->currentThread()->enterRunLoop();
478
479         if (m_layerTreeHost && m_layerTreeHost->rootLayer())
480             m_layerTreeHost->rootLayer()->setLayerTreeHost(0);
481         m_layerTreeHost.clear();
482
483         if (m_timeoutTask)
484             m_timeoutTask->clearTest();
485
486         ASSERT_FALSE(m_layerTreeHost.get());
487         m_client.clear();
488         if (m_timedOut) {
489             FAIL() << "Test timed out";
490             WebCompositor::shutdown();
491             return;
492         }
493         afterTest();
494         WebCompositor::shutdown();
495     }
496
497     CCSettings m_settings;
498     OwnPtr<MockLayerTreeHostClient> m_client;
499     RefPtr<CCLayerTreeHost> m_layerTreeHost;
500
501 private:
502     bool m_beginning;
503     bool m_endWhenBeginReturns;
504     bool m_timedOut;
505
506     OwnPtr<WebThread> m_webThread;
507     RefPtr<CCScopedThreadProxy> m_mainThreadProxy;
508     TimeoutTask* m_timeoutTask;
509     BeginTask* m_beginTask;
510 };
511
512 void CCLayerTreeHostTest::doBeginTest()
513 {
514     ASSERT(isMainThread());
515     m_client = MockLayerTreeHostClient::create(this);
516
517     RefPtr<LayerChromium> rootLayer = LayerChromium::create();
518     m_layerTreeHost = MockLayerTreeHost::create(this, m_client.get(), rootLayer, m_settings);
519     ASSERT_TRUE(m_layerTreeHost);
520     rootLayer->setLayerTreeHost(m_layerTreeHost.get());
521
522     m_beginning = true;
523     beginTest();
524     m_beginning = false;
525     if (m_endWhenBeginReturns)
526         onEndTest(static_cast<void*>(this));
527 }
528
529 void CCLayerTreeHostTest::endTest()
530 {
531     // If we are called from the CCThread, re-call endTest on the main thread.
532     if (!isMainThread())
533         m_mainThreadProxy->postTask(createCCThreadTask(this, &CCLayerTreeHostTest::endTest));
534     else {
535         // For the case where we endTest during beginTest(), set a flag to indicate that
536         // the test should end the second beginTest regains control.
537         if (m_beginning)
538             m_endWhenBeginReturns = true;
539         else
540             onEndTest(static_cast<void*>(this));
541     }
542 }
543
544 class CCLayerTreeHostTestThreadOnly : public CCLayerTreeHostTest {
545 public:
546     void runTestThreaded()
547     {
548         CCLayerTreeHostTest::runTest(true);
549     }
550 };
551
552 // Shortlived layerTreeHosts shouldn't die.
553 class CCLayerTreeHostTestShortlived1 : public CCLayerTreeHostTest {
554 public:
555     CCLayerTreeHostTestShortlived1() { }
556
557     virtual void beginTest()
558     {
559         // Kill the layerTreeHost immediately.
560         m_layerTreeHost->setRootLayer(0);
561         m_layerTreeHost.clear();
562
563         endTest();
564     }
565
566     virtual void afterTest()
567     {
568     }
569 };
570
571 #define SINGLE_AND_MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) \
572     TEST_F(TEST_FIXTURE_NAME, runSingleThread)            \
573     {                                                     \
574         runTest(false);                                   \
575     }                                                     \
576     TEST_F(TEST_FIXTURE_NAME, runMultiThread)             \
577     {                                                     \
578         runTest(true);                                    \
579     }
580
581 SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestShortlived1)
582
583 // Shortlived layerTreeHosts shouldn't die with a commit in flight.
584 class CCLayerTreeHostTestShortlived2 : public CCLayerTreeHostTest {
585 public:
586     CCLayerTreeHostTestShortlived2() { }
587
588     virtual void beginTest()
589     {
590         postSetNeedsCommitToMainThread();
591
592         // Kill the layerTreeHost immediately.
593         m_layerTreeHost->setRootLayer(0);
594         m_layerTreeHost.clear();
595
596         endTest();
597     }
598
599     virtual void afterTest()
600     {
601     }
602 };
603
604 SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestShortlived2)
605
606 // Shortlived layerTreeHosts shouldn't die with a redraw in flight.
607 class CCLayerTreeHostTestShortlived3 : public CCLayerTreeHostTest {
608 public:
609     CCLayerTreeHostTestShortlived3() { }
610
611     virtual void beginTest()
612     {
613         postSetNeedsRedrawToMainThread();
614
615         // Kill the layerTreeHost immediately.
616         m_layerTreeHost->setRootLayer(0);
617         m_layerTreeHost.clear();
618
619         endTest();
620     }
621
622     virtual void afterTest()
623     {
624     }
625 };
626
627 SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestShortlived3)
628
629 // Test interleaving of redraws and commits
630 class CCLayerTreeHostTestCommitingWithContinuousRedraw : public CCLayerTreeHostTestThreadOnly {
631 public:
632     CCLayerTreeHostTestCommitingWithContinuousRedraw()
633         : m_numCompleteCommits(0)
634         , m_numDraws(0)
635     {
636     }
637
638     virtual void beginTest()
639     {
640         postSetNeedsCommitToMainThread();
641     }
642
643     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
644     {
645         m_numCompleteCommits++;
646         if (m_numCompleteCommits == 2)
647             endTest();
648     }
649
650     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl*)
651     {
652         if (m_numDraws == 1)
653           postSetNeedsCommitToMainThread();
654         m_numDraws++;
655         postSetNeedsRedrawToMainThread();
656     }
657
658     virtual void afterTest()
659     {
660     }
661
662 private:
663     int m_numCompleteCommits;
664     int m_numDraws;
665 };
666
667 TEST_F(CCLayerTreeHostTestCommitingWithContinuousRedraw, runMultiThread)
668 {
669     runTestThreaded();
670 }
671
672 // Two setNeedsCommits in a row should lead to at least 1 commit and at least 1
673 // draw with frame 0.
674 class CCLayerTreeHostTestSetNeedsCommit1 : public CCLayerTreeHostTestThreadOnly {
675 public:
676     CCLayerTreeHostTestSetNeedsCommit1()
677         : m_numCommits(0)
678         , m_numDraws(0)
679     {
680     }
681
682     virtual void beginTest()
683     {
684         postSetNeedsCommitToMainThread();
685         postSetNeedsCommitToMainThread();
686     }
687
688     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
689     {
690         m_numDraws++;
691         if (!impl->sourceFrameNumber())
692             endTest();
693     }
694
695     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
696     {
697         m_numCommits++;
698     }
699
700     virtual void afterTest()
701     {
702         EXPECT_GE(1, m_numCommits);
703         EXPECT_GE(1, m_numDraws);
704     }
705
706 private:
707     int m_numCommits;
708     int m_numDraws;
709 };
710
711 TEST_F(CCLayerTreeHostTestSetNeedsCommit1, DISABLED_runMultiThread)
712 {
713     runTestThreaded();
714 }
715
716 // A setNeedsCommit should lead to 1 commit. Issuing a second commit after that
717 // first committed frame draws should lead to another commit.
718 class CCLayerTreeHostTestSetNeedsCommit2 : public CCLayerTreeHostTestThreadOnly {
719 public:
720     CCLayerTreeHostTestSetNeedsCommit2()
721         : m_numCommits(0)
722         , m_numDraws(0)
723     {
724     }
725
726     virtual void beginTest()
727     {
728         postSetNeedsCommitToMainThread();
729     }
730
731     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
732     {
733         if (!impl->sourceFrameNumber())
734             postSetNeedsCommitToMainThread();
735         else if (impl->sourceFrameNumber() == 1)
736             endTest();
737     }
738
739     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
740     {
741         m_numCommits++;
742     }
743
744     virtual void afterTest()
745     {
746         EXPECT_EQ(2, m_numCommits);
747         EXPECT_GE(2, m_numDraws);
748     }
749
750 private:
751     int m_numCommits;
752     int m_numDraws;
753 };
754
755 TEST_F(CCLayerTreeHostTestSetNeedsCommit2, runMultiThread)
756 {
757     runTestThreaded();
758 }
759
760 // 1 setNeedsRedraw after the first commit has completed should lead to 1
761 // additional draw.
762 class CCLayerTreeHostTestSetNeedsRedraw : public CCLayerTreeHostTestThreadOnly {
763 public:
764     CCLayerTreeHostTestSetNeedsRedraw()
765         : m_numCommits(0)
766         , m_numDraws(0)
767     {
768     }
769
770     virtual void beginTest()
771     {
772         postSetNeedsCommitToMainThread();
773     }
774
775     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
776     {
777         EXPECT_EQ(0, impl->sourceFrameNumber());
778         if (!m_numDraws)
779             postSetNeedsRedrawToMainThread(); // Redraw again to verify that the second redraw doesn't commit.
780         else
781             endTest();
782         m_numDraws++;
783     }
784
785     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
786     {
787         EXPECT_EQ(0, m_numDraws);
788         m_numCommits++;
789     }
790
791     virtual void afterTest()
792     {
793         EXPECT_GE(2, m_numDraws);
794         EXPECT_EQ(1, m_numCommits);
795     }
796
797 private:
798     int m_numCommits;
799     int m_numDraws;
800 };
801
802 TEST_F(CCLayerTreeHostTestSetNeedsRedraw, runMultiThread)
803 {
804     runTestThreaded();
805 }
806
807 // A compositeAndReadback while invisible should force a normal commit without assertion.
808 class CCLayerTreeHostTestCompositeAndReadbackWhileInvisible : public CCLayerTreeHostTestThreadOnly {
809 public:
810     CCLayerTreeHostTestCompositeAndReadbackWhileInvisible()
811         : m_numCommits(0)
812     {
813     }
814
815     virtual void beginTest()
816     {
817     }
818
819     virtual void didCommitAndDrawFrame()
820     {
821         m_numCommits++;
822         if (m_numCommits == 1) {
823             m_layerTreeHost->setVisible(false);
824             m_layerTreeHost->setNeedsCommit();
825             m_layerTreeHost->setNeedsCommit();
826             OwnArrayPtr<char> pixels(adoptArrayPtr(new char[4]));
827             m_layerTreeHost->compositeAndReadback(static_cast<void*>(pixels.get()), IntRect(0, 0, 1, 1));
828         } else
829             endTest();
830
831     }
832
833     virtual void afterTest()
834     {
835     }
836
837 private:
838     int m_numCommits;
839 };
840
841 TEST_F(CCLayerTreeHostTestCompositeAndReadbackWhileInvisible, runMultiThread)
842 {
843     runTestThreaded();
844 }
845
846
847 // Trigger a frame with setNeedsCommit. Then, inside the resulting animate
848 // callback, requet another frame using setNeedsAnimate. End the test when
849 // animate gets called yet-again, indicating that the proxy is correctly
850 // handling the case where setNeedsAnimate() is called inside the begin frame
851 // flow.
852 class CCLayerTreeHostTestSetNeedsAnimateInsideAnimationCallback : public CCLayerTreeHostTestThreadOnly {
853 public:
854     CCLayerTreeHostTestSetNeedsAnimateInsideAnimationCallback()
855         : m_numAnimates(0)
856     {
857     }
858
859     virtual void beginTest()
860     {
861         postSetNeedsAnimateToMainThread();
862     }
863
864     virtual void updateAnimations(double)
865     {
866         if (!m_numAnimates) {
867             m_layerTreeHost->setNeedsAnimate();
868             m_numAnimates++;
869             return;
870         }
871         endTest();
872     }
873
874     virtual void afterTest()
875     {
876     }
877
878 private:
879     int m_numAnimates;
880 };
881
882 TEST_F(CCLayerTreeHostTestSetNeedsAnimateInsideAnimationCallback, runMultiThread)
883 {
884     runTestThreaded();
885 }
886
887 // Add a layer animation and confirm that CCLayerTreeHostImpl::animateLayers does get
888 // called and continues to get called.
889 class CCLayerTreeHostTestAddAnimation : public CCLayerTreeHostTestThreadOnly {
890 public:
891     CCLayerTreeHostTestAddAnimation()
892         : m_numAnimates(0)
893         , m_receivedAnimationStartedNotification(false)
894         , m_startTime(0)
895         , m_firstMonotonicTime(0)
896     {
897     }
898
899     virtual void beginTest()
900     {
901         postAddInstantAnimationToMainThread();
902     }
903
904     virtual void animateLayers(CCLayerTreeHostImpl* layerTreeHostImpl, double monotonicTime)
905     {
906         if (!m_numAnimates) {
907             // The animation had zero duration so layerTreeHostImpl should no
908             // longer need to animate its layers.
909             EXPECT_FALSE(layerTreeHostImpl->needsAnimateLayers());
910             m_numAnimates++;
911             m_firstMonotonicTime = monotonicTime;
912             return;
913         }
914         EXPECT_LT(0, m_startTime);
915         EXPECT_LT(0, m_firstMonotonicTime);
916         EXPECT_NE(m_startTime, m_firstMonotonicTime);
917         EXPECT_TRUE(m_receivedAnimationStartedNotification);
918         endTest();
919     }
920
921     virtual void notifyAnimationStarted(double wallClockTime)
922     {
923         m_receivedAnimationStartedNotification = true;
924         m_startTime = wallClockTime;
925     }
926
927     virtual void afterTest()
928     {
929     }
930
931 private:
932     int m_numAnimates;
933     bool m_receivedAnimationStartedNotification;
934     double m_startTime;
935     double m_firstMonotonicTime;
936 };
937
938 TEST_F(CCLayerTreeHostTestAddAnimation, runMultiThread)
939 {
940     runTestThreaded();
941 }
942
943 // Ensures that animations continue to be ticked when we are backgrounded.
944 class CCLayerTreeHostTestTickAnimationWhileBackgrounded : public CCLayerTreeHostTestThreadOnly {
945 public:
946     CCLayerTreeHostTestTickAnimationWhileBackgrounded()
947         : m_numAnimates(0)
948     {
949     }
950
951     virtual void beginTest()
952     {
953         postAddAnimationToMainThread();
954     }
955
956     virtual void animateLayers(CCLayerTreeHostImpl* layerTreeHostImpl, double monotonicTime)
957     {
958         if (!m_numAnimates) {
959             // We have a long animation running. It should continue to tick even if we are not visible.
960             postSetVisibleToMainThread(false);
961             m_numAnimates++;
962             return;
963         }
964         endTest();
965     }
966
967     virtual void afterTest()
968     {
969     }
970
971 private:
972     int m_numAnimates;
973 };
974
975 TEST_F(CCLayerTreeHostTestTickAnimationWhileBackgrounded, runMultiThread)
976 {
977     runTestThreaded();
978 }
979
980 // Ensures that when opacity is being animated, this value does not cause the subtree to be skipped.
981 class CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity : public CCLayerTreeHostTestThreadOnly {
982 public:
983     CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity()
984     {
985     }
986
987     virtual void beginTest()
988     {
989         m_layerTreeHost->rootLayer()->setDrawOpacity(1);
990         m_layerTreeHost->setViewportSize(IntSize(10, 10));
991         m_layerTreeHost->rootLayer()->setOpacity(0);
992         postAddAnimationToMainThread();
993     }
994
995     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
996     {
997         // If the subtree was skipped when preparing to draw, the layer's draw opacity
998         // will not have been updated. It should be set to 0 due to the animation.
999         // Without the animation, the layer will be skipped since it has zero opacity.
1000         EXPECT_EQ(0, m_layerTreeHost->rootLayer()->drawOpacity());
1001         endTest();
1002     }
1003
1004     virtual void afterTest()
1005     {
1006     }
1007 };
1008
1009 TEST_F(CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity, runMultiThread)
1010 {
1011     runTestThreaded();
1012 }
1013
1014 class CCLayerTreeHostTestScrollSimple : public CCLayerTreeHostTestThreadOnly {
1015 public:
1016     CCLayerTreeHostTestScrollSimple()
1017         : m_initialScroll(IntPoint(10, 20))
1018         , m_secondScroll(IntPoint(40, 5))
1019         , m_scrollAmount(2, -1)
1020         , m_scrolls(0)
1021     {
1022     }
1023
1024     virtual void beginTest()
1025     {
1026         m_layerTreeHost->rootLayer()->setScrollable(true);
1027         m_layerTreeHost->rootLayer()->setScrollPosition(m_initialScroll);
1028         postSetNeedsCommitToMainThread();
1029     }
1030
1031     virtual void layout()
1032     {
1033         LayerChromium* root = m_layerTreeHost->rootLayer();
1034         if (!m_layerTreeHost->frameNumber())
1035             EXPECT_EQ(root->scrollPosition(), m_initialScroll);
1036         else {
1037             EXPECT_EQ(root->scrollPosition(), m_initialScroll + m_scrollAmount);
1038
1039             // Pretend like Javascript updated the scroll position itself.
1040             root->setScrollPosition(m_secondScroll);
1041         }
1042     }
1043
1044     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
1045     {
1046         CCLayerImpl* root = impl->rootLayer();
1047         EXPECT_EQ(root->scrollDelta(), IntSize());
1048
1049         root->setScrollable(true);
1050         root->setMaxScrollPosition(IntSize(100, 100));
1051         root->scrollBy(m_scrollAmount);
1052
1053         if (impl->frameNumber() == 1) {
1054             EXPECT_EQ(root->scrollPosition(), m_initialScroll);
1055             EXPECT_EQ(root->scrollDelta(), m_scrollAmount);
1056             postSetNeedsCommitToMainThread();
1057         } else if (impl->frameNumber() == 2) {
1058             EXPECT_EQ(root->scrollPosition(), m_secondScroll);
1059             EXPECT_EQ(root->scrollDelta(), m_scrollAmount);
1060             endTest();
1061         }
1062     }
1063
1064     virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale)
1065     {
1066         IntPoint position = m_layerTreeHost->rootLayer()->scrollPosition();
1067         m_layerTreeHost->rootLayer()->setScrollPosition(position + scrollDelta);
1068         m_scrolls++;
1069     }
1070
1071     virtual void afterTest()
1072     {
1073         EXPECT_EQ(1, m_scrolls);
1074     }
1075 private:
1076     IntPoint m_initialScroll;
1077     IntPoint m_secondScroll;
1078     IntSize m_scrollAmount;
1079     int m_scrolls;
1080 };
1081
1082 TEST_F(CCLayerTreeHostTestScrollSimple, DISABLED_runMultiThread)
1083 {
1084     runTestThreaded();
1085 }
1086
1087 class CCLayerTreeHostTestScrollMultipleRedraw : public CCLayerTreeHostTestThreadOnly {
1088 public:
1089     CCLayerTreeHostTestScrollMultipleRedraw()
1090         : m_initialScroll(IntPoint(40, 10))
1091         , m_scrollAmount(-3, 17)
1092         , m_scrolls(0)
1093     {
1094     }
1095
1096     virtual void beginTest()
1097     {
1098         m_layerTreeHost->rootLayer()->setScrollable(true);
1099         m_layerTreeHost->rootLayer()->setScrollPosition(m_initialScroll);
1100         postSetNeedsCommitToMainThread();
1101     }
1102
1103     virtual void beginCommitOnCCThread(CCLayerTreeHostImpl* impl)
1104     {
1105         LayerChromium* root = m_layerTreeHost->rootLayer();
1106         if (!m_layerTreeHost->frameNumber())
1107             EXPECT_EQ(root->scrollPosition(), m_initialScroll);
1108         else if (m_layerTreeHost->frameNumber() == 1)
1109             EXPECT_EQ(root->scrollPosition(), m_initialScroll + m_scrollAmount + m_scrollAmount);
1110         else if (m_layerTreeHost->frameNumber() == 2)
1111             EXPECT_EQ(root->scrollPosition(), m_initialScroll + m_scrollAmount + m_scrollAmount);
1112     }
1113
1114     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
1115     {
1116         CCLayerImpl* root = impl->rootLayer();
1117         root->setScrollable(true);
1118         root->setMaxScrollPosition(IntSize(100, 100));
1119
1120         if (impl->frameNumber() == 1) {
1121             EXPECT_EQ(root->scrollDelta(), IntSize());
1122             root->scrollBy(m_scrollAmount);
1123             EXPECT_EQ(root->scrollDelta(), m_scrollAmount);
1124
1125             EXPECT_EQ(root->scrollPosition(), m_initialScroll);
1126             postSetNeedsRedrawToMainThread();
1127         } else if (impl->frameNumber() == 2) {
1128             EXPECT_EQ(root->scrollDelta(), m_scrollAmount);
1129             root->scrollBy(m_scrollAmount);
1130             EXPECT_EQ(root->scrollDelta(), m_scrollAmount + m_scrollAmount);
1131
1132             EXPECT_EQ(root->scrollPosition(), m_initialScroll);
1133             postSetNeedsCommitToMainThread();
1134         } else if (impl->frameNumber() == 3) {
1135             EXPECT_EQ(root->scrollDelta(), IntSize());
1136             EXPECT_EQ(root->scrollPosition(), m_initialScroll + m_scrollAmount + m_scrollAmount);
1137             endTest();
1138         }
1139     }
1140
1141     virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale)
1142     {
1143         IntPoint position = m_layerTreeHost->rootLayer()->scrollPosition();
1144         m_layerTreeHost->rootLayer()->setScrollPosition(position + scrollDelta);
1145         m_scrolls++;
1146     }
1147
1148     virtual void afterTest()
1149     {
1150         EXPECT_EQ(1, m_scrolls);
1151     }
1152 private:
1153     IntPoint m_initialScroll;
1154     IntSize m_scrollAmount;
1155     int m_scrolls;
1156 };
1157
1158 TEST_F(CCLayerTreeHostTestScrollMultipleRedraw, DISABLED_runMultiThread)
1159 {
1160     runTestThreaded();
1161 }
1162
1163 // Verifies that startPageScaleAnimation events propagate correctly from CCLayerTreeHost to
1164 // CCLayerTreeHostImpl in the MT compositor.
1165 class CCLayerTreeHostTestStartPageScaleAnimation : public CCLayerTreeHostTest {
1166 public:
1167
1168     CCLayerTreeHostTestStartPageScaleAnimation()
1169         : m_animationRequested(false)
1170     {
1171     }
1172
1173     virtual void beginTest()
1174     {
1175         m_layerTreeHost->rootLayer()->setScrollable(true);
1176         m_layerTreeHost->rootLayer()->setScrollPosition(IntPoint());
1177         postSetNeedsRedrawToMainThread();
1178     }
1179
1180     static void requestStartPageScaleAnimation(void* self)
1181     {
1182         CCLayerTreeHostTestStartPageScaleAnimation* test = static_cast<CCLayerTreeHostTestStartPageScaleAnimation*>(self);
1183         if (test->layerTreeHost())
1184             test->layerTreeHost()->startPageScaleAnimation(IntSize(), false, 1.25, 0);
1185     }
1186
1187     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
1188     {
1189         impl->rootLayer()->setScrollable(true);
1190         impl->rootLayer()->setScrollPosition(IntPoint());
1191         impl->setPageScaleFactorAndLimits(impl->pageScale(), 0.5, 2);
1192
1193         // We request animation only once.
1194         if (!m_animationRequested) {
1195             callOnMainThread(CCLayerTreeHostTestStartPageScaleAnimation::requestStartPageScaleAnimation, this);
1196             m_animationRequested = true;
1197         }
1198     }
1199
1200     virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale)
1201     {
1202         IntPoint position = m_layerTreeHost->rootLayer()->scrollPosition();
1203         m_layerTreeHost->rootLayer()->setScrollPosition(position + scrollDelta);
1204         m_layerTreeHost->setPageScaleFactorAndLimits(scale, 0.5, 2);
1205     }
1206
1207     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl* impl)
1208     {
1209         impl->processScrollDeltas();
1210         // We get one commit before the first draw, and the animation doesn't happen until the second draw,
1211         // so results available on the third commit.
1212         if (impl->frameNumber() == 2) {
1213             EXPECT_EQ(1.25, impl->pageScale());
1214             endTest();
1215         } else
1216             postSetNeedsRedrawToMainThread();
1217     }
1218
1219     virtual void afterTest()
1220     {
1221     }
1222
1223 private:
1224     bool m_animationRequested;
1225 };
1226
1227 TEST_F(CCLayerTreeHostTestStartPageScaleAnimation, runTest)
1228 {
1229     runTest(true);
1230 }
1231
1232 class CCLayerTreeHostTestSetVisible : public CCLayerTreeHostTest {
1233 public:
1234
1235     CCLayerTreeHostTestSetVisible()
1236         : m_numCommits(0)
1237         , m_numDraws(0)
1238     {
1239     }
1240
1241     virtual void beginTest()
1242     {
1243         postSetVisibleToMainThread(false);
1244         postSetNeedsRedrawToMainThread(); // This is suppressed while we're invisible.
1245         postSetVisibleToMainThread(true); // Triggers the redraw.
1246     }
1247
1248     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
1249     {
1250         EXPECT_TRUE(impl->visible());
1251         ++m_numDraws;
1252         endTest();
1253     }
1254
1255     virtual void afterTest()
1256     {
1257         EXPECT_EQ(1, m_numDraws);
1258     }
1259
1260 private:
1261     int m_numCommits;
1262     int m_numDraws;
1263 };
1264
1265 TEST_F(CCLayerTreeHostTestSetVisible, runMultiThread)
1266 {
1267     runTest(true);
1268 }
1269
1270 class TestOpacityChangeLayerDelegate : public ContentLayerDelegate {
1271 public:
1272     TestOpacityChangeLayerDelegate(CCLayerTreeHostTest* test)
1273         : m_test(test)
1274     {
1275     }
1276
1277     virtual void paintContents(GraphicsContext&, const IntRect&)
1278     {
1279         // Set layer opacity to 0.
1280         m_test->layerTreeHost()->rootLayer()->setOpacity(0);
1281     }
1282
1283     virtual bool preserves3D() { return false; }
1284
1285 private:
1286     CCLayerTreeHostTest* m_test;
1287 };
1288
1289 class ContentLayerChromiumWithUpdateTracking : public ContentLayerChromium {
1290 public:
1291     static PassRefPtr<ContentLayerChromiumWithUpdateTracking> create(ContentLayerDelegate *delegate) { return adoptRef(new ContentLayerChromiumWithUpdateTracking(delegate)); }
1292
1293     int paintContentsCount() { return m_paintContentsCount; }
1294     int idlePaintContentsCount() { return m_idlePaintContentsCount; }
1295     void resetPaintContentsCount() { m_paintContentsCount = 0; m_idlePaintContentsCount = 0;}
1296
1297     int updateCount() { return m_updateCount; }
1298     void resetUpdateCount() { m_updateCount = 0; }
1299
1300     virtual void paintContentsIfDirty(const CCOcclusionTracker* occlusion)
1301     {
1302         ContentLayerChromium::paintContentsIfDirty(occlusion);
1303         m_paintContentsCount++;
1304     }
1305
1306     virtual void idlePaintContentsIfDirty(const CCOcclusionTracker* occlusion)
1307     {
1308         ContentLayerChromium::idlePaintContentsIfDirty(occlusion);
1309         m_idlePaintContentsCount++;
1310     }
1311
1312     virtual void updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
1313     {
1314         ContentLayerChromium::updateCompositorResources(context, updater);
1315         m_updateCount++;
1316     }
1317
1318 private:
1319     explicit ContentLayerChromiumWithUpdateTracking(ContentLayerDelegate* delegate)
1320         : ContentLayerChromium(delegate)
1321         , m_paintContentsCount(0)
1322         , m_idlePaintContentsCount(0)
1323         , m_updateCount(0)
1324     {
1325         setBounds(IntSize(10, 10));
1326         setIsDrawable(true);
1327     }
1328
1329     int m_paintContentsCount;
1330     int m_idlePaintContentsCount;
1331     int m_updateCount;
1332 };
1333
1334 // Layer opacity change during paint should not prevent compositor resources from being updated during commit.
1335 class CCLayerTreeHostTestOpacityChange : public CCLayerTreeHostTest {
1336 public:
1337     CCLayerTreeHostTestOpacityChange()
1338         : m_testOpacityChangeDelegate(this)
1339         , m_updateCheckLayer(ContentLayerChromiumWithUpdateTracking::create(&m_testOpacityChangeDelegate))
1340     {
1341     }
1342
1343     virtual void beginTest()
1344     {
1345         m_layerTreeHost->setRootLayer(m_updateCheckLayer);
1346         m_layerTreeHost->setViewportSize(IntSize(10, 10));
1347
1348         postSetNeedsCommitToMainThread();
1349     }
1350
1351     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
1352     {
1353         endTest();
1354     }
1355
1356     virtual void afterTest()
1357     {
1358         // paintContentsIfDirty() should have been called once.
1359         EXPECT_EQ(1, m_updateCheckLayer->paintContentsCount());
1360
1361         // idlePaintContentsIfDirty() should have been called once
1362         EXPECT_EQ(1, m_updateCheckLayer->idlePaintContentsCount());
1363
1364         // updateCompositorResources() should have been called the same
1365         // amout of times as paintContentsIfDirty().
1366         EXPECT_EQ(m_updateCheckLayer->paintContentsCount(),
1367                   m_updateCheckLayer->updateCount());
1368
1369         // clear m_updateCheckLayer so CCLayerTreeHost dies.
1370         m_updateCheckLayer.clear();
1371     }
1372
1373 private:
1374     TestOpacityChangeLayerDelegate m_testOpacityChangeDelegate;
1375     RefPtr<ContentLayerChromiumWithUpdateTracking> m_updateCheckLayer;
1376 };
1377
1378 TEST_F(CCLayerTreeHostTestOpacityChange, runMultiThread)
1379 {
1380     runTest(true);
1381 }
1382
1383 class CCLayerTreeHostTestSetViewportSize : public CCLayerTreeHostTest {
1384 public:
1385
1386     CCLayerTreeHostTestSetViewportSize()
1387         : m_numCommits(0)
1388         , m_numDraws(0)
1389     {
1390     }
1391
1392     virtual void beginTest()
1393     {
1394         IntSize viewportSize(10, 10);
1395         layerTreeHost()->setViewportSize(viewportSize);
1396
1397         layerTreeHost()->updateLayers();
1398
1399         EXPECT_EQ(viewportSize, layerTreeHost()->viewportSize());
1400         EXPECT_EQ(TextureManager::highLimitBytes(viewportSize), layerTreeHost()->contentsTextureManager()->maxMemoryLimitBytes());
1401         EXPECT_EQ(TextureManager::reclaimLimitBytes(viewportSize), layerTreeHost()->contentsTextureManager()->preferredMemoryLimitBytes());
1402
1403         // setViewportSize() should not call TextureManager::setMaxMemoryLimitBytes() or TextureManager::setPreferredMemoryLimitBytes()
1404         // if the viewport size is not changed.
1405         IntSize fakeSize(5, 5);
1406         layerTreeHost()->contentsTextureManager()->setMaxMemoryLimitBytes(TextureManager::highLimitBytes(fakeSize));
1407         layerTreeHost()->contentsTextureManager()->setPreferredMemoryLimitBytes(TextureManager::reclaimLimitBytes(fakeSize));
1408         layerTreeHost()->setViewportSize(viewportSize);
1409         EXPECT_EQ(TextureManager::highLimitBytes(fakeSize), layerTreeHost()->contentsTextureManager()->maxMemoryLimitBytes());
1410         EXPECT_EQ(TextureManager::reclaimLimitBytes(fakeSize), layerTreeHost()->contentsTextureManager()->preferredMemoryLimitBytes());
1411
1412         endTest();
1413     }
1414
1415     virtual void afterTest()
1416     {
1417     }
1418
1419 private:
1420     int m_numCommits;
1421     int m_numDraws;
1422 };
1423
1424 TEST_F(CCLayerTreeHostTestSetViewportSize, runSingleThread)
1425 {
1426     runTest(false);
1427 }
1428
1429 class MockContentLayerDelegate : public ContentLayerDelegate {
1430 public:
1431     bool drawsContent() const { return true; }
1432     MOCK_CONST_METHOD0(preserves3D, bool());
1433     void paintContents(GraphicsContext&, const IntRect&) { }
1434     void notifySyncRequired() { }
1435 };
1436
1437 // Verify atomicity of commits and reuse of textures.
1438 class CCLayerTreeHostTestAtomicCommit : public CCLayerTreeHostTest {
1439 public:
1440     CCLayerTreeHostTestAtomicCommit()
1441         : m_layer(ContentLayerChromiumWithUpdateTracking::create(&m_delegate))
1442     {
1443         // Make sure partial texture updates are turned off.
1444         m_settings.maxPartialTextureUpdates = 0;
1445     }
1446
1447     virtual void beginTest()
1448     {
1449         m_layerTreeHost->setRootLayer(m_layer);
1450         m_layerTreeHost->setViewportSize(IntSize(10, 10));
1451
1452         postSetNeedsCommitToMainThread();
1453         postSetNeedsRedrawToMainThread();
1454     }
1455
1456     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl* impl)
1457     {
1458         CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
1459
1460         switch (impl->frameNumber()) {
1461         case 0:
1462             // Number of textures should be one.
1463             EXPECT_EQ(1, context->numTextures());
1464             // Number of textures used for commit should be one.
1465             EXPECT_EQ(1, context->numUsedTextures());
1466             // Verify that used texture is correct.
1467             EXPECT_TRUE(context->usedTexture(context->texture(0)));
1468
1469             context->resetUsedTextures();
1470             break;
1471         case 1:
1472             // Number of textures should be two as the first texture
1473             // is used by impl thread and cannot by used for update.
1474             EXPECT_EQ(2, context->numTextures());
1475             // Number of textures used for commit should still be one.
1476             EXPECT_EQ(1, context->numUsedTextures());
1477             // First texture should not have been used.
1478             EXPECT_FALSE(context->usedTexture(context->texture(0)));
1479             // New texture should have been used.
1480             EXPECT_TRUE(context->usedTexture(context->texture(1)));
1481
1482             context->resetUsedTextures();
1483             break;
1484         default:
1485             ASSERT_NOT_REACHED();
1486             break;
1487         }
1488     }
1489
1490     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
1491     {
1492         CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
1493
1494         // Number of textures used for draw should always be one.
1495         EXPECT_EQ(1, context->numUsedTextures());
1496
1497         if (impl->frameNumber() < 2) {
1498             context->resetUsedTextures();
1499             postSetNeedsAnimateAndCommitToMainThread();
1500             postSetNeedsRedrawToMainThread();
1501         } else
1502             endTest();
1503     }
1504
1505     virtual void layout()
1506     {
1507         m_layer->setNeedsDisplay();
1508     }
1509
1510     virtual void afterTest()
1511     {
1512     }
1513
1514 private:
1515     MockContentLayerDelegate m_delegate;
1516     RefPtr<ContentLayerChromiumWithUpdateTracking> m_layer;
1517 };
1518
1519 TEST_F(CCLayerTreeHostTestAtomicCommit, runMultiThread)
1520 {
1521     runTest(true);
1522 }
1523
1524 class CCLayerTreeHostTestAtomicCommitWithPartialUpdate : public CCLayerTreeHostTest {
1525 public:
1526     CCLayerTreeHostTestAtomicCommitWithPartialUpdate()
1527         : m_parent(ContentLayerChromiumWithUpdateTracking::create(&m_delegate))
1528         , m_child(ContentLayerChromiumWithUpdateTracking::create(&m_delegate))
1529         , m_numCommits(0)
1530     {
1531         // Allow one partial texture update.
1532         m_settings.maxPartialTextureUpdates = 1;
1533     }
1534
1535     virtual void beginTest()
1536     {
1537         m_layerTreeHost->setRootLayer(m_parent);
1538         m_layerTreeHost->setViewportSize(IntSize(10, 10));
1539         m_parent->addChild(m_child);
1540         m_child->setOpacity(0.5);
1541         m_child->setBounds(IntSize(20, 20));
1542
1543         postSetNeedsCommitToMainThread();
1544         postSetNeedsRedrawToMainThread();
1545     }
1546
1547     virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl* impl)
1548     {
1549         CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
1550
1551         switch (impl->frameNumber()) {
1552         case 0:
1553             // Number of textures should be two.
1554             EXPECT_EQ(2, context->numTextures());
1555             // Number of textures used for commit should be two.
1556             EXPECT_EQ(2, context->numUsedTextures());
1557             // Verify that used textures are correct.
1558             EXPECT_TRUE(context->usedTexture(context->texture(0)));
1559             EXPECT_TRUE(context->usedTexture(context->texture(1)));
1560
1561             context->resetUsedTextures();
1562             break;
1563         case 1:
1564             // Number of textures should be four as the first two
1565             // textures are used by the impl thread.
1566             EXPECT_EQ(4, context->numTextures());
1567             // Number of textures used for commit should still be two.
1568             EXPECT_EQ(2, context->numUsedTextures());
1569             // First two textures should not have been used.
1570             EXPECT_FALSE(context->usedTexture(context->texture(0)));
1571             EXPECT_FALSE(context->usedTexture(context->texture(1)));
1572             // New textures should have been used.
1573             EXPECT_TRUE(context->usedTexture(context->texture(2)));
1574             EXPECT_TRUE(context->usedTexture(context->texture(3)));
1575
1576             context->resetUsedTextures();
1577             break;
1578         case 2:
1579             // Number of textures should be three as we allow one
1580             // partial update and the first two textures are used by
1581             // the impl thread.
1582             EXPECT_EQ(3, context->numTextures());
1583             // Number of textures used for commit should still be two.
1584             EXPECT_EQ(2, context->numUsedTextures());
1585             // First texture should not have been used.
1586             EXPECT_FALSE(context->usedTexture(context->texture(0)));
1587             // Second texture should have been used.
1588             EXPECT_TRUE(context->usedTexture(context->texture(1)));
1589             // New textures should have been used.
1590             EXPECT_TRUE(context->usedTexture(context->texture(2)));
1591
1592             context->resetUsedTextures();
1593             break;
1594         default:
1595             ASSERT_NOT_REACHED();
1596             break;
1597         }
1598     }
1599
1600     virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
1601     {
1602         CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
1603
1604         // Number of textures used for drawing should always be two.
1605         EXPECT_EQ(2, context->numUsedTextures());
1606
1607         if (impl->frameNumber() < 3) {
1608             context->resetUsedTextures();
1609             postSetNeedsAnimateAndCommitToMainThread();
1610             postSetNeedsRedrawToMainThread();
1611         } else
1612             endTest();
1613     }
1614
1615     virtual void layout()
1616     {
1617         switch (m_numCommits++) {
1618         case 0:
1619         case 1:
1620             m_parent->setNeedsDisplay();
1621             m_child->setNeedsDisplay();
1622             break;
1623         case 2:
1624             // Damage part of layers.
1625             m_parent->setNeedsDisplayRect(FloatRect(0, 0, 5, 5));
1626             m_child->setNeedsDisplayRect(FloatRect(0, 0, 5, 5));
1627             break;
1628         default:
1629             ASSERT_NOT_REACHED();
1630             break;
1631         }
1632     }
1633
1634     virtual void afterTest()
1635     {
1636     }
1637
1638 private:
1639     MockContentLayerDelegate m_delegate;
1640     RefPtr<ContentLayerChromiumWithUpdateTracking> m_parent;
1641     RefPtr<ContentLayerChromiumWithUpdateTracking> m_child;
1642     int m_numCommits;
1643 };
1644
1645 TEST_F(CCLayerTreeHostTestAtomicCommitWithPartialUpdate, runMultiThread)
1646 {
1647     runTest(true);
1648 }
1649
1650 #define EXPECT_EQ_RECT(a, b) \
1651     EXPECT_EQ(a.x(), b.x()); \
1652     EXPECT_EQ(a.y(), b.y()); \
1653     EXPECT_EQ(a.width(), b.width()); \
1654     EXPECT_EQ(a.height(), b.height());
1655
1656 class TestLayerChromium : public LayerChromium {
1657 public:
1658     static PassRefPtr<TestLayerChromium> create() { return adoptRef(new TestLayerChromium()); }
1659
1660     virtual void paintContentsIfDirty(const CCOcclusionTracker* occlusion)
1661     {
1662         m_occludedScreenSpace = occlusion ? occlusion->currentOcclusionInScreenSpace() : Region();
1663     }
1664
1665     virtual bool drawsContent() const { return true; }
1666
1667     virtual Region opaqueContentsRegion() const { return intersection(m_opaqueContentsRect, visibleLayerRect()); }
1668     void setOpaqueContentsRect(const IntRect& opaqueContentsRect) { m_opaqueContentsRect = opaqueContentsRect; }
1669
1670     const Region& occludedScreenSpace() const { return m_occludedScreenSpace; }
1671     void clearOccludedScreenSpace() { m_occludedScreenSpace = Region(); }
1672
1673 private:
1674     TestLayerChromium() : LayerChromium() { }
1675
1676     Region m_occludedScreenSpace;
1677     IntRect m_opaqueContentsRect;
1678 };
1679
1680 static void setLayerPropertiesForTesting(TestLayerChromium* layer, LayerChromium* parent, const TransformationMatrix& transform, const FloatPoint& anchor, const FloatPoint& position, const IntSize& bounds, bool opaque)
1681 {
1682     layer->removeAllChildren();
1683     if (parent)
1684         parent->addChild(layer);
1685     layer->setTransform(transform);
1686     layer->setAnchorPoint(anchor);
1687     layer->setPosition(position);
1688     layer->setBounds(bounds);
1689     layer->setOpaque(opaque);
1690     layer->clearOccludedScreenSpace();
1691 }
1692
1693 class CCLayerTreeHostTestLayerOcclusion : public CCLayerTreeHostTest {
1694 public:
1695     CCLayerTreeHostTestLayerOcclusion() { }
1696
1697     virtual void beginTest()
1698     {
1699         RefPtr<TestLayerChromium> rootLayer = TestLayerChromium::create();
1700         RefPtr<TestLayerChromium> child = TestLayerChromium::create();
1701         RefPtr<TestLayerChromium> child2 = TestLayerChromium::create();
1702         RefPtr<TestLayerChromium> grandChild = TestLayerChromium::create();
1703         RefPtr<TestLayerChromium> mask = TestLayerChromium::create();
1704
1705         TransformationMatrix identityMatrix;
1706         TransformationMatrix childTransform;
1707         childTransform.translate(250, 250);
1708         childTransform.rotate(90);
1709         childTransform.translate(-250, -250);
1710
1711         child->setMasksToBounds(true);
1712
1713         // See CCLayerTreeHostCommonTest.layerAddsSelfToOccludedRegionWithRotatedSurface for a nice visual of these layers and how they end up
1714         // positioned on the screen.
1715
1716         // The child layer is rotated and the grandChild is opaque, but clipped to the child and rootLayer
1717         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1718         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), false);
1719         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1720
1721         m_layerTreeHost->setRootLayer(rootLayer);
1722         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1723         m_layerTreeHost->updateLayers();
1724         m_layerTreeHost->commitComplete();
1725
1726         EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
1727         EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
1728         EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
1729         EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
1730         EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), rootLayer->occludedScreenSpace().bounds());
1731         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
1732
1733         // If the child layer is opaque, then it adds to the occlusion seen by the rootLayer.
1734         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1735         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1736         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1737
1738         m_layerTreeHost->setRootLayer(rootLayer);
1739         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1740         m_layerTreeHost->updateLayers();
1741         m_layerTreeHost->commitComplete();
1742
1743         EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
1744         EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
1745         EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
1746         EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
1747         EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), rootLayer->occludedScreenSpace().bounds());
1748         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
1749
1750         // Add a second child to the root layer and the regions should merge
1751         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1752         setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(70, 20), IntSize(500, 500), true);
1753         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1754         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1755
1756         m_layerTreeHost->setRootLayer(rootLayer);
1757         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1758         m_layerTreeHost->updateLayers();
1759         m_layerTreeHost->commitComplete();
1760
1761         EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
1762         EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
1763         EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
1764         EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
1765         EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), child2->occludedScreenSpace().bounds());
1766         EXPECT_EQ(1u, child2->occludedScreenSpace().rects().size());
1767         EXPECT_EQ_RECT(IntRect(30, 20, 70, 80), rootLayer->occludedScreenSpace().bounds());
1768         EXPECT_EQ(2u, rootLayer->occludedScreenSpace().rects().size());
1769
1770         // Move the second child to be sure.
1771         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1772         setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
1773         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1774         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1775
1776         m_layerTreeHost->setRootLayer(rootLayer);
1777         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1778         m_layerTreeHost->updateLayers();
1779         m_layerTreeHost->commitComplete();
1780
1781         EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
1782         EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
1783         EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
1784         EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
1785         EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), child2->occludedScreenSpace().bounds());
1786         EXPECT_EQ(1u, child2->occludedScreenSpace().rects().size());
1787         EXPECT_EQ_RECT(IntRect(10, 30, 90, 70), rootLayer->occludedScreenSpace().bounds());
1788         EXPECT_EQ(2u, rootLayer->occludedScreenSpace().rects().size());
1789
1790         // If the child layer has a mask on it, then it shouldn't contribute to occlusion on stuff below it
1791         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1792         setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
1793         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1794         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1795
1796         child->setMaskLayer(mask.get());
1797
1798         m_layerTreeHost->setRootLayer(rootLayer);
1799         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1800         m_layerTreeHost->updateLayers();
1801         m_layerTreeHost->commitComplete();
1802
1803         EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
1804         EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
1805         EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
1806         EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
1807         EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
1808         EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
1809         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
1810         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
1811
1812         // If the child layer with a mask is below child2, then child2 should contribute to occlusion on everything, and child shouldn't contribute to the rootLayer
1813         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1814         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1815         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1816         setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
1817
1818         child->setMaskLayer(mask.get());
1819
1820         m_layerTreeHost->setRootLayer(rootLayer);
1821         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1822         m_layerTreeHost->updateLayers();
1823         m_layerTreeHost->commitComplete();
1824
1825         EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
1826         EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
1827         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), grandChild->occludedScreenSpace().bounds());
1828         EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
1829         EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
1830         EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
1831         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
1832         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
1833
1834         // If the child layer has a non-opaque drawOpacity, then it shouldn't contribute to occlusion on stuff below it
1835         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1836         setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
1837         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1838         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1839
1840         child->setMaskLayer(0);
1841         child->setOpacity(0.5);
1842
1843         m_layerTreeHost->setRootLayer(rootLayer);
1844         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1845         m_layerTreeHost->updateLayers();
1846         m_layerTreeHost->commitComplete();
1847
1848         EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
1849         EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
1850         EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
1851         EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
1852         EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
1853         EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
1854         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
1855         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
1856
1857         // If the child layer with non-opaque drawOpacity is below child2, then child2 should contribute to occlusion on everything, and child shouldn't contribute to the rootLayer
1858         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1859         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1860         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1861         setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
1862
1863         child->setMaskLayer(0);
1864         child->setOpacity(0.5);
1865
1866         m_layerTreeHost->setRootLayer(rootLayer);
1867         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1868         m_layerTreeHost->updateLayers();
1869         m_layerTreeHost->commitComplete();
1870
1871         EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
1872         EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
1873         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), grandChild->occludedScreenSpace().bounds());
1874         EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
1875         EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
1876         EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
1877         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
1878         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
1879
1880         // Kill the layerTreeHost immediately.
1881         m_layerTreeHost->setRootLayer(0);
1882         m_layerTreeHost.clear();
1883
1884         endTest();
1885     }
1886
1887     virtual void afterTest()
1888     {
1889     }
1890 };
1891
1892 SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusion)
1893
1894 class CCLayerTreeHostTestContentLayerOcclusion : public CCLayerTreeHostTest {
1895 public:
1896     CCLayerTreeHostTestContentLayerOcclusion() { }
1897
1898     virtual void beginTest()
1899     {
1900         RefPtr<TestLayerChromium> rootLayer = TestLayerChromium::create();
1901         RefPtr<TestLayerChromium> child = TestLayerChromium::create();
1902
1903         TransformationMatrix identityMatrix;
1904         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1905         setLayerPropertiesForTesting(child.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(50, 50), false);
1906
1907         child->setOpaqueContentsRect(IntRect(10, 10, 20, 20));
1908
1909         m_layerTreeHost->setRootLayer(rootLayer);
1910         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1911         m_layerTreeHost->updateLayers();
1912         m_layerTreeHost->commitComplete();
1913
1914         EXPECT_EQ_RECT(IntRect(), child->occludedScreenSpace().bounds());
1915         EXPECT_EQ(0u, child->occludedScreenSpace().rects().size());
1916
1917         EXPECT_EQ_RECT(IntRect(40, 40, 20, 20), rootLayer->occludedScreenSpace().bounds());
1918         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
1919
1920         // Kill the layerTreeHost immediately.
1921         m_layerTreeHost->setRootLayer(0);
1922         m_layerTreeHost.clear();
1923
1924         endTest();
1925     }
1926
1927     virtual void afterTest()
1928     {
1929     }
1930 };
1931
1932 SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestContentLayerOcclusion)
1933
1934 class CCLayerTreeHostTestLayerOcclusionWithFilters : public CCLayerTreeHostTest {
1935 public:
1936     CCLayerTreeHostTestLayerOcclusionWithFilters() { }
1937
1938     virtual void beginTest()
1939     {
1940         RefPtr<TestLayerChromium> rootLayer = TestLayerChromium::create();
1941         RefPtr<TestLayerChromium> child = TestLayerChromium::create();
1942         RefPtr<TestLayerChromium> child2 = TestLayerChromium::create();
1943         RefPtr<TestLayerChromium> grandChild = TestLayerChromium::create();
1944         RefPtr<TestLayerChromium> mask = TestLayerChromium::create();
1945
1946         TransformationMatrix identityMatrix;
1947         TransformationMatrix childTransform;
1948         childTransform.translate(250, 250);
1949         childTransform.rotate(90);
1950         childTransform.translate(-250, -250);
1951
1952         child->setMasksToBounds(true);
1953
1954         // If the child layer has a filter that changes alpha values, and is below child2, then child2 should contribute to occlusion on everything,
1955         // and child shouldn't contribute to the rootLayer
1956         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1957         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1958         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1959         setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
1960
1961         {
1962             FilterOperations filters;
1963             filters.operations().append(BasicComponentTransferFilterOperation::create(0.5, FilterOperation::OPACITY));
1964             child->setFilters(filters);
1965         }
1966
1967         m_layerTreeHost->setRootLayer(rootLayer);
1968         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1969         m_layerTreeHost->updateLayers();
1970         m_layerTreeHost->commitComplete();
1971
1972         EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
1973         EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
1974         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), grandChild->occludedScreenSpace().bounds());
1975         EXPECT_EQ(1u, grandChild->occludedScreenSpace().rects().size());
1976         EXPECT_EQ_RECT(IntRect(10, 40, 90, 60), child->occludedScreenSpace().bounds());
1977         EXPECT_EQ(2u, child->occludedScreenSpace().rects().size());
1978         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
1979         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
1980
1981         // If the child layer has a filter that moves pixels/changes alpha, and is below child2, then child should not inherit occlusion from outside its subtree,
1982         // and should not contribute to the rootLayer
1983         setLayerPropertiesForTesting(rootLayer.get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
1984         setLayerPropertiesForTesting(child.get(), rootLayer.get(), childTransform, FloatPoint(0, 0), FloatPoint(30, 30), IntSize(500, 500), true);
1985         setLayerPropertiesForTesting(grandChild.get(), child.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 10), IntSize(500, 500), true);
1986         setLayerPropertiesForTesting(child2.get(), rootLayer.get(), identityMatrix, FloatPoint(0, 0), FloatPoint(10, 70), IntSize(500, 500), true);
1987
1988         {
1989             FilterOperations filters;
1990             filters.operations().append(BlurFilterOperation::create(Length(10, WebCore::Percent), FilterOperation::BLUR));
1991             child->setFilters(filters);
1992         }
1993
1994         m_layerTreeHost->setRootLayer(rootLayer);
1995         m_layerTreeHost->setViewportSize(rootLayer->bounds());
1996         m_layerTreeHost->updateLayers();
1997         m_layerTreeHost->commitComplete();
1998
1999         EXPECT_EQ_RECT(IntRect(), child2->occludedScreenSpace().bounds());
2000         EXPECT_EQ(0u, child2->occludedScreenSpace().rects().size());
2001         EXPECT_EQ_RECT(IntRect(), grandChild->occludedScreenSpace().bounds());
2002         EXPECT_EQ(0u, grandChild->occludedScreenSpace().rects().size());
2003         EXPECT_EQ_RECT(IntRect(30, 40, 70, 60), child->occludedScreenSpace().bounds());
2004         EXPECT_EQ(1u, child->occludedScreenSpace().rects().size());
2005         EXPECT_EQ_RECT(IntRect(10, 70, 90, 30), rootLayer->occludedScreenSpace().bounds());
2006         EXPECT_EQ(1u, rootLayer->occludedScreenSpace().rects().size());
2007
2008         // Kill the layerTreeHost immediately.
2009         m_layerTreeHost->setRootLayer(0);
2010         m_layerTreeHost.clear();
2011
2012         endTest();
2013     }
2014
2015     virtual void afterTest()
2016     {
2017     }
2018 };
2019
2020 SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestLayerOcclusionWithFilters)
2021
2022 class CCLayerTreeHostTestManySurfaces : public CCLayerTreeHostTest {
2023 public:
2024     CCLayerTreeHostTestManySurfaces() { }
2025
2026     virtual void beginTest()
2027     {
2028         // We create enough RenderSurfaces that it will trigger Vector reallocation while computing occlusion.
2029         Region occluded;
2030         const TransformationMatrix identityMatrix;
2031         Vector<RefPtr<TestLayerChromium> > layers;
2032         Vector<RefPtr<TestLayerChromium> > children;
2033         int numSurfaces = 20;
2034         RefPtr<TestLayerChromium> replica = TestLayerChromium::create();
2035
2036         for (int i = 0; i < numSurfaces; ++i) {
2037             layers.append(TestLayerChromium::create());
2038             if (!i) {
2039                 setLayerPropertiesForTesting(layers.last().get(), 0, identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(100, 100), true);
2040                 layers.last()->createRenderSurface();
2041             } else {
2042                 setLayerPropertiesForTesting(layers.last().get(), layers[layers.size()-2].get(), identityMatrix, FloatPoint(0, 0), FloatPoint(1, 1), IntSize(100-i, 100-i), true);
2043                 layers.last()->setMasksToBounds(true);
2044                 layers.last()->setReplicaLayer(replica.get()); // Make it have a RenderSurface
2045             }
2046         }
2047
2048         for (int i = 1; i < numSurfaces; ++i) {
2049             children.append(TestLayerChromium::create());
2050             setLayerPropertiesForTesting(children.last().get(), layers[i].get(), identityMatrix, FloatPoint(0, 0), FloatPoint(0, 0), IntSize(500, 500), false);
2051         }
2052
2053         m_layerTreeHost->setRootLayer(layers[0].get());
2054         m_layerTreeHost->setViewportSize(layers[0]->bounds());
2055         m_layerTreeHost->updateLayers();
2056         m_layerTreeHost->commitComplete();
2057
2058         for (int i = 0; i < numSurfaces-1; ++i) {
2059             IntRect expectedOcclusion(i+1, i+1, 100-i-1, 100-i-1);
2060
2061             EXPECT_EQ_RECT(expectedOcclusion, layers[i]->occludedScreenSpace().bounds());
2062             EXPECT_EQ(1u, layers[i]->occludedScreenSpace().rects().size());
2063         }
2064
2065         // Kill the layerTreeHost immediately.
2066         m_layerTreeHost->setRootLayer(0);
2067         m_layerTreeHost.clear();
2068
2069         endTest();
2070     }
2071
2072     virtual void afterTest()
2073     {
2074     }
2075 };
2076
2077 SINGLE_AND_MULTI_THREAD_TEST_F(CCLayerTreeHostTestManySurfaces)
2078
2079 // A loseContext(1) should lead to a didRecreateContext(true)
2080 class CCLayerTreeHostTestSetSingleLostContext : public CCLayerTreeHostTestThreadOnly {
2081 public:
2082     CCLayerTreeHostTestSetSingleLostContext()
2083     {
2084     }
2085
2086     virtual void beginTest()
2087     {
2088         postSetNeedsCommitToMainThread();
2089     }
2090
2091     virtual void didCommitAndDrawFrame()
2092     {
2093         m_layerTreeHost->loseContext(1);
2094     }
2095
2096     virtual void didRecreateContext(bool succeeded)
2097     {
2098         EXPECT_TRUE(succeeded);
2099         endTest();
2100     }
2101
2102     virtual void afterTest()
2103     {
2104     }
2105 };
2106
2107 TEST_F(CCLayerTreeHostTestSetSingleLostContext, runMultiThread)
2108 {
2109     runTestThreaded();
2110 }
2111
2112 // A loseContext(10) should lead to a didRecreateContext(false), and
2113 // a finishAllRendering() should not hang.
2114 class CCLayerTreeHostTestSetRepeatedLostContext : public CCLayerTreeHostTestThreadOnly {
2115 public:
2116     CCLayerTreeHostTestSetRepeatedLostContext()
2117     {
2118     }
2119
2120     virtual void beginTest()
2121     {
2122         postSetNeedsCommitToMainThread();
2123     }
2124
2125     virtual void didCommitAndDrawFrame()
2126     {
2127         m_layerTreeHost->loseContext(10);
2128     }
2129
2130     virtual void didRecreateContext(bool succeeded)
2131     {
2132         EXPECT_FALSE(succeeded);
2133         m_layerTreeHost->finishAllRendering();
2134         endTest();
2135     }
2136
2137     virtual void afterTest()
2138     {
2139     }
2140 };
2141
2142 TEST_F(CCLayerTreeHostTestSetRepeatedLostContext, runMultiThread)
2143 {
2144     runTestThreaded();
2145 }
2146
2147 } // namespace