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