1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "CCThreadedTest.h"
9 #include "CCActiveAnimation.h"
10 #include "CCAnimationTestCommon.h"
11 #include "CCInputHandler.h"
12 #include "CCLayerAnimationController.h"
13 #include "CCLayerImpl.h"
14 #include "CCLayerTreeHostImpl.h"
15 #include "CCOcclusionTrackerTestCommon.h"
16 #include "CCScopedThreadProxy.h"
17 #include "CCSingleThreadProxy.h"
18 #include "CCTextureUpdateQueue.h"
19 #include "CCThreadTask.h"
20 #include "CCTiledLayerTestCommon.h"
21 #include "CCTimingFunction.h"
22 #include "ContentLayerChromium.h"
23 #include "FakeWebCompositorOutputSurface.h"
24 #include "FakeWebGraphicsContext3D.h"
25 #include "LayerChromium.h"
26 #include <gmock/gmock.h>
27 #include <public/Platform.h>
28 #include <public/WebCompositorSupport.h>
29 #include <public/WebFilterOperation.h>
30 #include <public/WebFilterOperations.h>
31 #include <public/WebThread.h>
32 #include <wtf/Locker.h>
33 #include <wtf/MainThread.h>
34 #include <wtf/PassRefPtr.h>
35 #include <wtf/ThreadingPrimitives.h>
36 #include <wtf/Vector.h>
38 using namespace WebCore
;
39 using namespace WebKit
;
41 namespace WebKitTests
{
43 PassOwnPtr
<CompositorFakeWebGraphicsContext3DWithTextureTracking
> CompositorFakeWebGraphicsContext3DWithTextureTracking::create(Attributes attrs
)
45 return adoptPtr(new CompositorFakeWebGraphicsContext3DWithTextureTracking(attrs
));
48 WebGLId
CompositorFakeWebGraphicsContext3DWithTextureTracking::createTexture()
50 WebGLId texture
= m_textures
.size() + 1;
51 m_textures
.append(texture
);
55 void CompositorFakeWebGraphicsContext3DWithTextureTracking::deleteTexture(WebGLId texture
)
57 for (size_t i
= 0; i
< m_textures
.size(); i
++) {
58 if (m_textures
[i
] == texture
) {
65 void CompositorFakeWebGraphicsContext3DWithTextureTracking::bindTexture(WGC3Denum
/* target */, WebGLId texture
)
67 m_usedTextures
.add(texture
);
70 int CompositorFakeWebGraphicsContext3DWithTextureTracking::numTextures() const { return static_cast<int>(m_textures
.size()); }
71 int CompositorFakeWebGraphicsContext3DWithTextureTracking::texture(int i
) const { return m_textures
[i
]; }
72 void CompositorFakeWebGraphicsContext3DWithTextureTracking::resetTextures() { m_textures
.clear(); }
74 int CompositorFakeWebGraphicsContext3DWithTextureTracking::numUsedTextures() const { return static_cast<int>(m_usedTextures
.size()); }
75 bool CompositorFakeWebGraphicsContext3DWithTextureTracking::usedTexture(int texture
) const { return m_usedTextures
.find(texture
) != m_usedTextures
.end(); }
76 void CompositorFakeWebGraphicsContext3DWithTextureTracking::resetUsedTextures() { m_usedTextures
.clear(); }
78 CompositorFakeWebGraphicsContext3DWithTextureTracking::CompositorFakeWebGraphicsContext3DWithTextureTracking(Attributes attrs
) : CompositorFakeWebGraphicsContext3D(attrs
)
82 PassOwnPtr
<WebCompositorOutputSurface
> TestHooks::createOutputSurface()
84 return FakeWebCompositorOutputSurface::create(CompositorFakeWebGraphicsContext3DWithTextureTracking::create(WebGraphicsContext3D::Attributes()));
87 PassOwnPtr
<MockLayerTreeHostImpl
> MockLayerTreeHostImpl::create(TestHooks
* testHooks
, const CCLayerTreeSettings
& settings
, CCLayerTreeHostImplClient
* client
)
89 return adoptPtr(new MockLayerTreeHostImpl(testHooks
, settings
, client
));
92 void MockLayerTreeHostImpl::beginCommit()
94 CCLayerTreeHostImpl::beginCommit();
95 m_testHooks
->beginCommitOnCCThread(this);
98 void MockLayerTreeHostImpl::commitComplete()
100 CCLayerTreeHostImpl::commitComplete();
101 m_testHooks
->commitCompleteOnCCThread(this);
104 bool MockLayerTreeHostImpl::prepareToDraw(FrameData
& frame
)
106 bool result
= CCLayerTreeHostImpl::prepareToDraw(frame
);
107 if (!m_testHooks
->prepareToDrawOnCCThread(this))
112 void MockLayerTreeHostImpl::drawLayers(const FrameData
& frame
)
114 CCLayerTreeHostImpl::drawLayers(frame
);
115 m_testHooks
->drawLayersOnCCThread(this);
118 void MockLayerTreeHostImpl::animateLayers(double monotonicTime
, double wallClockTime
)
120 m_testHooks
->willAnimateLayers(this, monotonicTime
);
121 CCLayerTreeHostImpl::animateLayers(monotonicTime
, wallClockTime
);
122 m_testHooks
->animateLayers(this, monotonicTime
);
125 double MockLayerTreeHostImpl::lowFrequencyAnimationInterval() const
130 MockLayerTreeHostImpl::MockLayerTreeHostImpl(TestHooks
* testHooks
, const CCLayerTreeSettings
& settings
, CCLayerTreeHostImplClient
* client
)
131 : CCLayerTreeHostImpl(settings
, client
)
132 , m_testHooks(testHooks
)
136 // Adapts CCLayerTreeHost for test. Injects MockLayerTreeHostImpl.
137 class MockLayerTreeHost
: public WebCore::CCLayerTreeHost
{
139 static PassOwnPtr
<MockLayerTreeHost
> create(TestHooks
* testHooks
, WebCore::CCLayerTreeHostClient
* client
, PassRefPtr
<WebCore::LayerChromium
> rootLayer
, const WebCore::CCLayerTreeSettings
& settings
)
141 OwnPtr
<MockLayerTreeHost
> layerTreeHost(adoptPtr(new MockLayerTreeHost(testHooks
, client
, settings
)));
142 bool success
= layerTreeHost
->initialize();
143 EXPECT_TRUE(success
);
144 layerTreeHost
->setRootLayer(rootLayer
);
146 // LayerTreeHostImpl won't draw if it has 1x1 viewport.
147 layerTreeHost
->setViewportSize(IntSize(1, 1), IntSize(1, 1));
149 layerTreeHost
->rootLayer()->setLayerAnimationDelegate(testHooks
);
151 return layerTreeHost
.release();
154 virtual PassOwnPtr
<WebCore::CCLayerTreeHostImpl
> createLayerTreeHostImpl(WebCore::CCLayerTreeHostImplClient
* client
)
156 return MockLayerTreeHostImpl::create(m_testHooks
, settings(), client
);
159 virtual void didAddAnimation() OVERRIDE
161 CCLayerTreeHost::didAddAnimation();
162 m_testHooks
->didAddAnimation();
166 MockLayerTreeHost(TestHooks
* testHooks
, WebCore::CCLayerTreeHostClient
* client
, const WebCore::CCLayerTreeSettings
& settings
)
167 : CCLayerTreeHost(client
, settings
)
168 , m_testHooks(testHooks
)
172 TestHooks
* m_testHooks
;
175 // Implementation of CCLayerTreeHost callback interface.
176 class MockLayerTreeHostClient
: public MockCCLayerTreeHostClient
{
178 static PassOwnPtr
<MockLayerTreeHostClient
> create(TestHooks
* testHooks
)
180 return adoptPtr(new MockLayerTreeHostClient(testHooks
));
183 virtual void willBeginFrame() OVERRIDE
187 virtual void didBeginFrame() OVERRIDE
191 virtual void animate(double monotonicTime
) OVERRIDE
193 m_testHooks
->animate(monotonicTime
);
196 virtual void layout() OVERRIDE
198 m_testHooks
->layout();
201 virtual void applyScrollAndScale(const IntSize
& scrollDelta
, float scale
) OVERRIDE
203 m_testHooks
->applyScrollAndScale(scrollDelta
, scale
);
206 virtual PassOwnPtr
<WebCompositorOutputSurface
> createOutputSurface() OVERRIDE
208 return m_testHooks
->createOutputSurface();
211 virtual void didRecreateOutputSurface(bool succeeded
) OVERRIDE
213 m_testHooks
->didRecreateOutputSurface(succeeded
);
216 virtual PassOwnPtr
<CCInputHandler
> createInputHandler() OVERRIDE
221 virtual void willCommit() OVERRIDE
225 virtual void didCommit() OVERRIDE
227 m_testHooks
->didCommit();
230 virtual void didCommitAndDrawFrame() OVERRIDE
232 m_testHooks
->didCommitAndDrawFrame();
235 virtual void didCompleteSwapBuffers() OVERRIDE
239 virtual void scheduleComposite() OVERRIDE
241 m_testHooks
->scheduleComposite();
245 explicit MockLayerTreeHostClient(TestHooks
* testHooks
) : m_testHooks(testHooks
) { }
247 TestHooks
* m_testHooks
;
250 class TimeoutTask
: public WebThread::Task
{
252 explicit TimeoutTask(CCThreadedTest
* test
)
262 virtual ~TimeoutTask()
265 m_test
->clearTimeout();
275 CCThreadedTest
* m_test
;
278 class BeginTask
: public WebThread::Task
{
280 explicit BeginTask(CCThreadedTest
* test
)
285 virtual ~BeginTask() { }
288 m_test
->doBeginTest();
291 CCThreadedTest
* m_test
;
294 class EndTestTask
: public WebThread::Task
{
296 explicit EndTestTask(CCThreadedTest
* test
)
301 virtual ~EndTestTask()
304 m_test
->clearEndTestTask();
319 CCThreadedTest
* m_test
;
322 CCThreadedTest::CCThreadedTest()
324 , m_endWhenBeginReturns(false)
332 void CCThreadedTest::endTest()
336 // If we are called from the CCThread, re-call endTest on the main thread.
338 m_mainThreadProxy
->postTask(createCCThreadTask(this, &CCThreadedTest::endTest
));
340 // For the case where we endTest during beginTest(), set a flag to indicate that
341 // the test should end the second beginTest regains control.
343 m_endWhenBeginReturns
= true;
345 onEndTest(static_cast<void*>(this));
349 void CCThreadedTest::endTestAfterDelay(int delayMilliseconds
)
351 // If we are called from the CCThread, re-call endTest on the main thread.
353 m_mainThreadProxy
->postTask(createCCThreadTask(this, &CCThreadedTest::endTestAfterDelay
, delayMilliseconds
));
355 m_endTestTask
= new EndTestTask(this);
356 WebKit::Platform::current()->currentThread()->postDelayedTask(m_endTestTask
, delayMilliseconds
);
360 void CCThreadedTest::postSetNeedsAnimateToMainThread()
362 callOnMainThread(CCThreadedTest::dispatchSetNeedsAnimate
, this);
365 void CCThreadedTest::postAddAnimationToMainThread()
367 callOnMainThread(CCThreadedTest::dispatchAddAnimation
, this);
370 void CCThreadedTest::postAddInstantAnimationToMainThread()
372 callOnMainThread(CCThreadedTest::dispatchAddInstantAnimation
, this);
375 void CCThreadedTest::postSetNeedsCommitToMainThread()
377 callOnMainThread(CCThreadedTest::dispatchSetNeedsCommit
, this);
380 void CCThreadedTest::postAcquireLayerTextures()
382 callOnMainThread(CCThreadedTest::dispatchAcquireLayerTextures
, this);
385 void CCThreadedTest::postSetNeedsRedrawToMainThread()
387 callOnMainThread(CCThreadedTest::dispatchSetNeedsRedraw
, this);
390 void CCThreadedTest::postSetNeedsAnimateAndCommitToMainThread()
392 callOnMainThread(CCThreadedTest::dispatchSetNeedsAnimateAndCommit
, this);
395 void CCThreadedTest::postSetVisibleToMainThread(bool visible
)
397 callOnMainThread(visible
? CCThreadedTest::dispatchSetVisible
: CCThreadedTest::dispatchSetInvisible
, this);
400 void CCThreadedTest::postDidAddAnimationToMainThread()
402 callOnMainThread(CCThreadedTest::dispatchDidAddAnimation
, this);
405 void CCThreadedTest::doBeginTest()
407 ASSERT(isMainThread());
408 m_client
= MockLayerTreeHostClient::create(this);
410 RefPtr
<LayerChromium
> rootLayer
= LayerChromium::create();
411 m_layerTreeHost
= MockLayerTreeHost::create(this, m_client
.get(), rootLayer
, m_settings
);
412 ASSERT_TRUE(m_layerTreeHost
);
413 rootLayer
->setLayerTreeHost(m_layerTreeHost
.get());
414 m_layerTreeHost
->setSurfaceReady();
420 if (m_endWhenBeginReturns
)
421 onEndTest(static_cast<void*>(this));
424 void CCThreadedTest::timeout()
430 void CCThreadedTest::scheduleComposite()
432 if (!m_started
|| m_scheduled
|| m_finished
)
435 callOnMainThread(&CCThreadedTest::dispatchComposite
, this);
438 void CCThreadedTest::onEndTest(void* self
)
440 ASSERT(isMainThread());
441 WebKit::Platform::current()->currentThread()->exitRunLoop();
444 void CCThreadedTest::dispatchSetNeedsAnimate(void* self
)
446 ASSERT(isMainThread());
448 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
450 if (test
->m_finished
)
453 if (test
->m_layerTreeHost
)
454 test
->m_layerTreeHost
->setNeedsAnimate();
457 void CCThreadedTest::dispatchAddInstantAnimation(void* self
)
459 ASSERT(isMainThread());
461 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
463 if (test
->m_finished
)
466 if (test
->m_layerTreeHost
&& test
->m_layerTreeHost
->rootLayer())
467 addOpacityTransitionToLayer(*test
->m_layerTreeHost
->rootLayer(), 0, 0, 0.5, false);
470 void CCThreadedTest::dispatchAddAnimation(void* self
)
472 ASSERT(isMainThread());
474 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
476 if (test
->m_finished
)
479 if (test
->m_layerTreeHost
&& test
->m_layerTreeHost
->rootLayer())
480 addOpacityTransitionToLayer(*test
->m_layerTreeHost
->rootLayer(), 10, 0, 0.5, true);
483 void CCThreadedTest::dispatchSetNeedsAnimateAndCommit(void* self
)
485 ASSERT(isMainThread());
487 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
489 if (test
->m_finished
)
492 if (test
->m_layerTreeHost
) {
493 test
->m_layerTreeHost
->setNeedsAnimate();
494 test
->m_layerTreeHost
->setNeedsCommit();
498 void CCThreadedTest::dispatchSetNeedsCommit(void* self
)
500 ASSERT(isMainThread());
502 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
504 if (test
->m_finished
)
507 if (test
->m_layerTreeHost
)
508 test
->m_layerTreeHost
->setNeedsCommit();
511 void CCThreadedTest::dispatchAcquireLayerTextures(void* self
)
513 ASSERT(isMainThread());
515 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
517 if (test
->m_finished
)
520 if (test
->m_layerTreeHost
)
521 test
->m_layerTreeHost
->acquireLayerTextures();
524 void CCThreadedTest::dispatchSetNeedsRedraw(void* self
)
526 ASSERT(isMainThread());
528 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
530 if (test
->m_finished
)
533 if (test
->m_layerTreeHost
)
534 test
->m_layerTreeHost
->setNeedsRedraw();
537 void CCThreadedTest::dispatchSetVisible(void* self
)
539 ASSERT(isMainThread());
541 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
543 if (test
->m_finished
)
546 if (test
->m_layerTreeHost
)
547 test
->m_layerTreeHost
->setVisible(true);
550 void CCThreadedTest::dispatchSetInvisible(void* self
)
552 ASSERT(isMainThread());
554 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
556 if (test
->m_finished
)
559 if (test
->m_layerTreeHost
)
560 test
->m_layerTreeHost
->setVisible(false);
563 void CCThreadedTest::dispatchComposite(void* self
)
565 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
566 ASSERT(isMainThread());
568 test
->m_scheduled
= false;
569 if (test
->m_layerTreeHost
&& !test
->m_finished
)
570 test
->m_layerTreeHost
->composite();
573 void CCThreadedTest::dispatchDidAddAnimation(void* self
)
575 ASSERT(isMainThread());
577 CCThreadedTest
* test
= static_cast<CCThreadedTest
*>(self
);
579 if (test
->m_finished
)
582 if (test
->m_layerTreeHost
)
583 test
->m_layerTreeHost
->didAddAnimation();
586 void CCThreadedTest::runTest(bool threaded
)
588 // For these tests, we will enable threaded animations.
589 Platform::current()->compositorSupport()->setAcceleratedAnimationEnabled(true);
592 m_webThread
= adoptPtr(WebKit::Platform::current()->createThread("CCThreadedTest"));
593 Platform::current()->compositorSupport()->initialize(m_webThread
.get());
595 Platform::current()->compositorSupport()->initialize(0);
597 ASSERT(CCProxy::isMainThread());
598 m_mainThreadProxy
= CCScopedThreadProxy::create(CCProxy::mainThread());
600 initializeSettings(m_settings
);
602 m_beginTask
= new BeginTask(this);
603 WebKit::Platform::current()->currentThread()->postDelayedTask(m_beginTask
, 0); // postDelayedTask takes ownership of the task
604 m_timeoutTask
= new TimeoutTask(this);
605 WebKit::Platform::current()->currentThread()->postDelayedTask(m_timeoutTask
, 5000);
606 WebKit::Platform::current()->currentThread()->enterRunLoop();
608 if (m_layerTreeHost
&& m_layerTreeHost
->rootLayer())
609 m_layerTreeHost
->rootLayer()->setLayerTreeHost(0);
610 m_layerTreeHost
.clear();
613 m_timeoutTask
->clearTest();
616 m_endTestTask
->clearTest();
618 ASSERT_FALSE(m_layerTreeHost
.get());
621 FAIL() << "Test timed out";
622 Platform::current()->compositorSupport()->shutdown();
626 Platform::current()->compositorSupport()->shutdown();
629 } // namespace WebKitTests