[chromium] Clean up includes in compositor unit tests
[WebKit-https.git] / Source / WebKit / chromium / tests / CCThreadedTest.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 "CCThreadedTest.h"
28
29 #include "CCAnimationTestCommon.h"
30 #include "CCOcclusionTrackerTestCommon.h"
31 #include "CCTiledLayerTestCommon.h"
32 #include "ContentLayerChromium.h"
33 #include "FakeWebGraphicsContext3D.h"
34 #include "LayerChromium.h"
35 #include "cc/CCActiveAnimation.h"
36 #include "cc/CCLayerAnimationController.h"
37 #include "cc/CCLayerImpl.h"
38 #include "cc/CCLayerTreeHostImpl.h"
39 #include "cc/CCScopedThreadProxy.h"
40 #include "cc/CCSingleThreadProxy.h"
41 #include "cc/CCTextureUpdateQueue.h"
42 #include "cc/CCThreadTask.h"
43 #include "cc/CCTimingFunction.h"
44 #include <gmock/gmock.h>
45 #include <public/Platform.h>
46 #include <public/WebCompositor.h>
47 #include <public/WebFilterOperation.h>
48 #include <public/WebFilterOperations.h>
49 #include <public/WebThread.h>
50 #include <wtf/Locker.h>
51 #include <wtf/MainThread.h>
52 #include <wtf/PassRefPtr.h>
53 #include <wtf/ThreadingPrimitives.h>
54 #include <wtf/Vector.h>
55
56 using namespace WebCore;
57 using namespace WebKit;
58 using namespace WTF;
59
60 namespace WebKitTests {
61
62 PassOwnPtr<CompositorFakeWebGraphicsContext3DWithTextureTracking> CompositorFakeWebGraphicsContext3DWithTextureTracking::create(Attributes attrs)
63 {
64     return adoptPtr(new CompositorFakeWebGraphicsContext3DWithTextureTracking(attrs));
65 }
66
67 WebGLId CompositorFakeWebGraphicsContext3DWithTextureTracking::createTexture()
68 {
69     WebGLId texture = m_textures.size() + 1;
70     m_textures.append(texture);
71     return texture;
72 }
73
74 void CompositorFakeWebGraphicsContext3DWithTextureTracking::deleteTexture(WebGLId texture)
75 {
76     for (size_t i = 0; i < m_textures.size(); i++) {
77         if (m_textures[i] == texture) {
78             m_textures.remove(i);
79             break;
80         }
81     }
82 }
83
84 void CompositorFakeWebGraphicsContext3DWithTextureTracking::bindTexture(WGC3Denum /* target */, WebGLId texture)
85 {
86     m_usedTextures.add(texture);
87 }
88
89 int CompositorFakeWebGraphicsContext3DWithTextureTracking::numTextures() const { return static_cast<int>(m_textures.size()); }
90 int CompositorFakeWebGraphicsContext3DWithTextureTracking::texture(int i) const { return m_textures[i]; }
91 void CompositorFakeWebGraphicsContext3DWithTextureTracking::resetTextures() { m_textures.clear(); }
92
93 int CompositorFakeWebGraphicsContext3DWithTextureTracking::numUsedTextures() const { return static_cast<int>(m_usedTextures.size()); }
94 bool CompositorFakeWebGraphicsContext3DWithTextureTracking::usedTexture(int texture) const { return m_usedTextures.find(texture) != m_usedTextures.end(); }
95 void CompositorFakeWebGraphicsContext3DWithTextureTracking::resetUsedTextures() { m_usedTextures.clear(); }
96
97 CompositorFakeWebGraphicsContext3DWithTextureTracking::CompositorFakeWebGraphicsContext3DWithTextureTracking(Attributes attrs) : CompositorFakeWebGraphicsContext3D(attrs)
98 {
99 }
100
101 PassOwnPtr<WebGraphicsContext3D> TestHooks::createContext()
102 {
103     return CompositorFakeWebGraphicsContext3DWithTextureTracking::create(WebGraphicsContext3D::Attributes());
104 }
105
106 PassOwnPtr<MockLayerTreeHostImpl> MockLayerTreeHostImpl::create(TestHooks* testHooks, const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
107 {
108     return adoptPtr(new MockLayerTreeHostImpl(testHooks, settings, client));
109 }
110
111 void MockLayerTreeHostImpl::beginCommit()
112 {
113     CCLayerTreeHostImpl::beginCommit();
114     m_testHooks->beginCommitOnCCThread(this);
115 }
116
117 void MockLayerTreeHostImpl::commitComplete()
118 {
119     CCLayerTreeHostImpl::commitComplete();
120     m_testHooks->commitCompleteOnCCThread(this);
121 }
122
123 bool MockLayerTreeHostImpl::prepareToDraw(FrameData& frame)
124 {
125     bool result = CCLayerTreeHostImpl::prepareToDraw(frame);
126     if (!m_testHooks->prepareToDrawOnCCThread(this))
127         result = false;
128     return result;
129 }
130
131 void MockLayerTreeHostImpl::drawLayers(const FrameData& frame)
132 {
133     CCLayerTreeHostImpl::drawLayers(frame);
134     m_testHooks->drawLayersOnCCThread(this);
135 }
136
137 void MockLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
138 {
139     m_testHooks->willAnimateLayers(this, monotonicTime);
140     CCLayerTreeHostImpl::animateLayers(monotonicTime, wallClockTime);
141     m_testHooks->animateLayers(this, monotonicTime);
142 }
143
144 double MockLayerTreeHostImpl::lowFrequencyAnimationInterval() const
145 {
146     return 1.0 / 60;
147 }
148
149 MockLayerTreeHostImpl::MockLayerTreeHostImpl(TestHooks* testHooks, const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
150     : CCLayerTreeHostImpl(settings, client)
151     , m_testHooks(testHooks)
152 {
153 }
154
155 // Adapts CCLayerTreeHost for test. Injects MockLayerTreeHostImpl.
156 class MockLayerTreeHost : public WebCore::CCLayerTreeHost {
157 public:
158     static PassOwnPtr<MockLayerTreeHost> create(TestHooks* testHooks, WebCore::CCLayerTreeHostClient* client, PassRefPtr<WebCore::LayerChromium> rootLayer, const WebCore::CCLayerTreeSettings& settings)
159     {
160         OwnPtr<MockLayerTreeHost> layerTreeHost(adoptPtr(new MockLayerTreeHost(testHooks, client, settings)));
161         bool success = layerTreeHost->initialize();
162         EXPECT_TRUE(success);
163         layerTreeHost->setRootLayer(rootLayer);
164
165         // LayerTreeHostImpl won't draw if it has 1x1 viewport.
166         layerTreeHost->setViewportSize(IntSize(1, 1), IntSize(1, 1));
167
168         layerTreeHost->rootLayer()->setLayerAnimationDelegate(testHooks);
169
170         return layerTreeHost.release();
171     }
172
173     virtual PassOwnPtr<WebCore::CCLayerTreeHostImpl> createLayerTreeHostImpl(WebCore::CCLayerTreeHostImplClient* client)
174     {
175         return MockLayerTreeHostImpl::create(m_testHooks, settings(), client);
176     }
177
178     virtual void didAddAnimation() OVERRIDE
179     {
180         CCLayerTreeHost::didAddAnimation();
181         m_testHooks->didAddAnimation();
182     }
183
184 private:
185     MockLayerTreeHost(TestHooks* testHooks, WebCore::CCLayerTreeHostClient* client, const WebCore::CCLayerTreeSettings& settings)
186         : CCLayerTreeHost(client, settings)
187         , m_testHooks(testHooks)
188     {
189     }
190
191     TestHooks* m_testHooks;
192 };
193
194 // Implementation of CCLayerTreeHost callback interface.
195 class MockLayerTreeHostClient : public MockCCLayerTreeHostClient {
196 public:
197     static PassOwnPtr<MockLayerTreeHostClient> create(TestHooks* testHooks)
198     {
199         return adoptPtr(new MockLayerTreeHostClient(testHooks));
200     }
201
202     virtual void willBeginFrame() OVERRIDE
203     {
204     }
205
206     virtual void didBeginFrame() OVERRIDE
207     {
208     }
209
210     virtual void updateAnimations(double monotonicTime) OVERRIDE
211     {
212         m_testHooks->updateAnimations(monotonicTime);
213     }
214
215     virtual void layout() OVERRIDE
216     {
217         m_testHooks->layout();
218     }
219
220     virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale) OVERRIDE
221     {
222         m_testHooks->applyScrollAndScale(scrollDelta, scale);
223     }
224
225     virtual PassOwnPtr<WebGraphicsContext3D> createContext3D() OVERRIDE
226     {
227         return m_testHooks->createContext();
228     }
229
230     virtual void willCommit() OVERRIDE
231     {
232     }
233
234     virtual void didCommit() OVERRIDE
235     {
236         m_testHooks->didCommit();
237     }
238
239     virtual void didCommitAndDrawFrame() OVERRIDE
240     {
241         m_testHooks->didCommitAndDrawFrame();
242     }
243
244     virtual void didCompleteSwapBuffers() OVERRIDE
245     {
246     }
247
248     virtual void didRecreateContext(bool succeeded) OVERRIDE
249     {
250         m_testHooks->didRecreateContext(succeeded);
251     }
252
253     virtual void scheduleComposite() OVERRIDE
254     {
255         m_testHooks->scheduleComposite();
256     }
257
258 private:
259     explicit MockLayerTreeHostClient(TestHooks* testHooks) : m_testHooks(testHooks) { }
260
261     TestHooks* m_testHooks;
262 };
263
264 class TimeoutTask : public WebThread::Task {
265 public:
266     explicit TimeoutTask(CCThreadedTest* test)
267         : m_test(test)
268     {
269     }
270
271     void clearTest()
272     {
273         m_test = 0;
274     }
275
276     virtual ~TimeoutTask()
277     {
278         if (m_test)
279             m_test->clearTimeout();
280     }
281
282     virtual void run()
283     {
284         if (m_test)
285             m_test->timeout();
286     }
287
288 private:
289     CCThreadedTest* m_test;
290 };
291
292 class BeginTask : public WebThread::Task {
293 public:
294     explicit BeginTask(CCThreadedTest* test)
295         : m_test(test)
296     {
297     }
298
299     virtual ~BeginTask() { }
300     virtual void run()
301     {
302         m_test->doBeginTest();
303     }
304 private:
305     CCThreadedTest* m_test;
306 };
307
308 class EndTestTask : public WebThread::Task {
309 public:
310     explicit EndTestTask(CCThreadedTest* test)
311         : m_test(test)
312     {
313     }
314
315     virtual ~EndTestTask()
316     {
317         if (m_test)
318             m_test->clearEndTestTask();
319     }
320
321     void clearTest()
322     {
323         m_test = 0;
324     }
325
326     virtual void run()
327     {
328         if (m_test)
329             m_test->endTest();
330     }
331
332 private:
333     CCThreadedTest* m_test;
334 };
335
336 CCThreadedTest::CCThreadedTest()
337     : m_beginning(false)
338     , m_endWhenBeginReturns(false)
339     , m_timedOut(false)
340     , m_finished(false)
341     , m_scheduled(false)
342     , m_started(false)
343     , m_endTestTask(0)
344 { }
345
346 void CCThreadedTest::endTest()
347 {
348     m_finished = true;
349
350     // If we are called from the CCThread, re-call endTest on the main thread.
351     if (!isMainThread())
352         m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::endTest));
353     else {
354         // For the case where we endTest during beginTest(), set a flag to indicate that
355         // the test should end the second beginTest regains control.
356         if (m_beginning)
357             m_endWhenBeginReturns = true;
358         else
359             onEndTest(static_cast<void*>(this));
360     }
361 }
362
363 void CCThreadedTest::endTestAfterDelay(int delayMilliseconds)
364 {
365     // If we are called from the CCThread, re-call endTest on the main thread.
366     if (!isMainThread())
367         m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::endTestAfterDelay, delayMilliseconds));
368     else {
369         m_endTestTask = new EndTestTask(this);
370         WebKit::Platform::current()->currentThread()->postDelayedTask(m_endTestTask, delayMilliseconds);
371     }
372 }
373
374 void CCThreadedTest::postSetNeedsAnimateToMainThread()
375 {
376     callOnMainThread(CCThreadedTest::dispatchSetNeedsAnimate, this);
377 }
378
379 void CCThreadedTest::postAddAnimationToMainThread()
380 {
381     callOnMainThread(CCThreadedTest::dispatchAddAnimation, this);
382 }
383
384 void CCThreadedTest::postAddInstantAnimationToMainThread()
385 {
386     callOnMainThread(CCThreadedTest::dispatchAddInstantAnimation, this);
387 }
388
389 void CCThreadedTest::postSetNeedsCommitToMainThread()
390 {
391     callOnMainThread(CCThreadedTest::dispatchSetNeedsCommit, this);
392 }
393
394 void CCThreadedTest::postAcquireLayerTextures()
395 {
396     callOnMainThread(CCThreadedTest::dispatchAcquireLayerTextures, this);
397 }
398
399 void CCThreadedTest::postSetNeedsRedrawToMainThread()
400 {
401     callOnMainThread(CCThreadedTest::dispatchSetNeedsRedraw, this);
402 }
403
404 void CCThreadedTest::postSetNeedsAnimateAndCommitToMainThread()
405 {
406     callOnMainThread(CCThreadedTest::dispatchSetNeedsAnimateAndCommit, this);
407 }
408
409 void CCThreadedTest::postSetVisibleToMainThread(bool visible)
410 {
411     callOnMainThread(visible ? CCThreadedTest::dispatchSetVisible : CCThreadedTest::dispatchSetInvisible, this);
412 }
413
414 void CCThreadedTest::postDidAddAnimationToMainThread()
415 {
416     callOnMainThread(CCThreadedTest::dispatchDidAddAnimation, this);
417 }
418
419 void CCThreadedTest::doBeginTest()
420 {
421     ASSERT(isMainThread());
422     m_client = MockLayerTreeHostClient::create(this);
423
424     RefPtr<LayerChromium> rootLayer = LayerChromium::create();
425     m_layerTreeHost = MockLayerTreeHost::create(this, m_client.get(), rootLayer, m_settings);
426     ASSERT_TRUE(m_layerTreeHost);
427     rootLayer->setLayerTreeHost(m_layerTreeHost.get());
428     m_layerTreeHost->setSurfaceReady();
429
430     m_started = true;
431     m_beginning = true;
432     beginTest();
433     m_beginning = false;
434     if (m_endWhenBeginReturns)
435         onEndTest(static_cast<void*>(this));
436 }
437
438 void CCThreadedTest::timeout()
439 {
440     m_timedOut = true;
441     endTest();
442 }
443
444 void CCThreadedTest::scheduleComposite()
445 {
446     if (!m_started || m_scheduled || m_finished)
447         return;
448     m_scheduled = true;
449     callOnMainThread(&CCThreadedTest::dispatchComposite, this);
450 }
451
452 void CCThreadedTest::onEndTest(void* self)
453 {
454     ASSERT(isMainThread());
455     WebKit::Platform::current()->currentThread()->exitRunLoop();
456 }
457
458 void CCThreadedTest::dispatchSetNeedsAnimate(void* self)
459 {
460     ASSERT(isMainThread());
461
462     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
463     ASSERT(test);
464     if (test->m_finished)
465         return;
466
467     if (test->m_layerTreeHost)
468         test->m_layerTreeHost->setNeedsAnimate();
469 }
470
471 void CCThreadedTest::dispatchAddInstantAnimation(void* self)
472 {
473     ASSERT(isMainThread());
474
475     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
476     ASSERT(test);
477     if (test->m_finished)
478         return;
479
480     if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
481         addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 0.5, false);
482 }
483
484 void CCThreadedTest::dispatchAddAnimation(void* self)
485 {
486     ASSERT(isMainThread());
487
488     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
489     ASSERT(test);
490     if (test->m_finished)
491         return;
492
493     if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
494         addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 10, 0, 0.5, true);
495 }
496
497 void CCThreadedTest::dispatchSetNeedsAnimateAndCommit(void* self)
498 {
499     ASSERT(isMainThread());
500
501     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
502     ASSERT(test);
503     if (test->m_finished)
504         return;
505
506     if (test->m_layerTreeHost) {
507         test->m_layerTreeHost->setNeedsAnimate();
508         test->m_layerTreeHost->setNeedsCommit();
509     }
510 }
511
512 void CCThreadedTest::dispatchSetNeedsCommit(void* self)
513 {
514     ASSERT(isMainThread());
515
516     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
517     ASSERT_TRUE(test);
518     if (test->m_finished)
519         return;
520
521     if (test->m_layerTreeHost)
522         test->m_layerTreeHost->setNeedsCommit();
523 }
524
525 void CCThreadedTest::dispatchAcquireLayerTextures(void* self)
526 {
527     ASSERT(isMainThread());
528
529     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
530     ASSERT_TRUE(test);
531     if (test->m_finished)
532         return;
533
534     if (test->m_layerTreeHost)
535         test->m_layerTreeHost->acquireLayerTextures();
536 }
537
538 void CCThreadedTest::dispatchSetNeedsRedraw(void* self)
539 {
540     ASSERT(isMainThread());
541
542     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
543     ASSERT_TRUE(test);
544     if (test->m_finished)
545         return;
546
547     if (test->m_layerTreeHost)
548         test->m_layerTreeHost->setNeedsRedraw();
549 }
550
551 void CCThreadedTest::dispatchSetVisible(void* self)
552 {
553     ASSERT(isMainThread());
554
555     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
556     ASSERT(test);
557     if (test->m_finished)
558         return;
559
560     if (test->m_layerTreeHost)
561         test->m_layerTreeHost->setVisible(true);
562 }
563
564 void CCThreadedTest::dispatchSetInvisible(void* self)
565 {
566     ASSERT(isMainThread());
567
568     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
569     ASSERT(test);
570     if (test->m_finished)
571         return;
572
573     if (test->m_layerTreeHost)
574         test->m_layerTreeHost->setVisible(false);
575 }
576
577 void CCThreadedTest::dispatchComposite(void* self)
578 {
579     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
580     ASSERT(isMainThread());
581     ASSERT(test);
582     test->m_scheduled = false;
583     if (test->m_layerTreeHost && !test->m_finished)
584         test->m_layerTreeHost->composite();
585 }
586
587 void CCThreadedTest::dispatchDidAddAnimation(void* self)
588 {
589     ASSERT(isMainThread());
590
591     CCThreadedTest* test = static_cast<CCThreadedTest*>(self);
592     ASSERT(test);
593     if (test->m_finished)
594         return;
595
596     if (test->m_layerTreeHost)
597         test->m_layerTreeHost->didAddAnimation();
598 }
599
600 void CCThreadedTest::runTest(bool threaded)
601 {
602     // For these tests, we will enable threaded animations.
603     WebCompositor::setAcceleratedAnimationEnabled(true);
604
605     if (threaded) {
606         m_webThread = adoptPtr(WebKit::Platform::current()->createThread("CCThreadedTest"));
607         WebCompositor::initialize(m_webThread.get());
608     } else
609         WebCompositor::initialize(0);
610
611     ASSERT(CCProxy::isMainThread());
612     m_mainThreadProxy = CCScopedThreadProxy::create(CCProxy::mainThread());
613
614     m_beginTask = new BeginTask(this);
615     WebKit::Platform::current()->currentThread()->postDelayedTask(m_beginTask, 0); // postDelayedTask takes ownership of the task
616     m_timeoutTask = new TimeoutTask(this);
617     WebKit::Platform::current()->currentThread()->postDelayedTask(m_timeoutTask, 5000);
618     WebKit::Platform::current()->currentThread()->enterRunLoop();
619
620     if (m_layerTreeHost && m_layerTreeHost->rootLayer())
621         m_layerTreeHost->rootLayer()->setLayerTreeHost(0);
622     m_layerTreeHost.clear();
623
624     if (m_timeoutTask)
625         m_timeoutTask->clearTest();
626
627     if (m_endTestTask)
628         m_endTestTask->clearTest();
629
630     ASSERT_FALSE(m_layerTreeHost.get());
631     m_client.clear();
632     if (m_timedOut) {
633         FAIL() << "Test timed out";
634         WebCompositor::shutdown();
635         return;
636     }
637     afterTest();
638     WebCompositor::shutdown();
639 }
640
641 } // namespace WebKitTests