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.
5 #include "cc/test/layer_tree_test_common.h"
7 #include "cc/animation.h"
8 #include "cc/animation_registrar.h"
9 #include "cc/content_layer.h"
10 #include "cc/input_handler.h"
12 #include "cc/layer_animation_controller.h"
13 #include "cc/layer_impl.h"
14 #include "cc/layer_tree_host_impl.h"
15 #include "cc/single_thread_proxy.h"
16 #include "cc/thread_impl.h"
17 #include "cc/test/animation_test_common.h"
18 #include "cc/test/fake_layer_tree_host_client.h"
19 #include "cc/test/fake_output_surface.h"
20 #include "cc/test/occlusion_tracker_test_common.h"
21 #include "cc/test/tiled_layer_test_common.h"
22 #include "cc/timing_function.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperation.h"
25 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations.h"
26 #include "ui/gfx/size_conversions.h"
28 using namespace WebKit
;
32 TestHooks::TestHooks()
34 bool useSoftwareRendering
= false;
35 bool useDelegatingRenderer
= false;
36 m_fakeClient
.reset(new FakeLayerImplTreeHostClient(useSoftwareRendering
, useDelegatingRenderer
));
39 TestHooks::~TestHooks() { }
41 bool TestHooks::prepareToDrawOnThread(cc::LayerTreeHostImpl
*, LayerTreeHostImpl::FrameData
&, bool)
46 bool TestHooks::canActivatePendingTree()
51 scoped_ptr
<OutputSurface
> TestHooks::createOutputSurface()
53 return createFakeOutputSurface();
56 scoped_refptr
<cc::ContextProvider
> TestHooks::OffscreenContextProviderForMainThread()
58 return m_fakeClient
->OffscreenContextProviderForMainThread();
61 scoped_refptr
<cc::ContextProvider
> TestHooks::OffscreenContextProviderForCompositorThread()
63 return m_fakeClient
->OffscreenContextProviderForCompositorThread();
66 scoped_ptr
<MockLayerTreeHostImpl
> MockLayerTreeHostImpl::create(TestHooks
* testHooks
, const LayerTreeSettings
& settings
, LayerTreeHostImplClient
* client
, Proxy
* proxy
)
68 return make_scoped_ptr(new MockLayerTreeHostImpl(testHooks
, settings
, client
, proxy
));
71 void MockLayerTreeHostImpl::beginCommit()
73 LayerTreeHostImpl::beginCommit();
74 m_testHooks
->beginCommitOnThread(this);
77 void MockLayerTreeHostImpl::commitComplete()
79 LayerTreeHostImpl::commitComplete();
80 m_testHooks
->commitCompleteOnThread(this);
82 if (!settings().implSidePainting
)
83 m_testHooks
->treeActivatedOnThread(this);
87 bool MockLayerTreeHostImpl::prepareToDraw(FrameData
& frame
)
89 bool result
= LayerTreeHostImpl::prepareToDraw(frame
);
90 if (!m_testHooks
->prepareToDrawOnThread(this, frame
, result
))
95 void MockLayerTreeHostImpl::drawLayers(FrameData
& frame
)
97 LayerTreeHostImpl::drawLayers(frame
);
98 m_testHooks
->drawLayersOnThread(this);
101 bool MockLayerTreeHostImpl::activatePendingTreeIfNeeded()
106 if (!m_testHooks
->canActivatePendingTree())
109 bool activated
= LayerTreeHostImpl::activatePendingTreeIfNeeded();
111 m_testHooks
->treeActivatedOnThread(this);
115 bool MockLayerTreeHostImpl::initializeRenderer(scoped_ptr
<OutputSurface
> outputSurface
)
117 bool success
= LayerTreeHostImpl::initializeRenderer(outputSurface
.Pass());
118 m_testHooks
->initializedRendererOnThread(this, success
);
122 void MockLayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime
, base::Time wallClockTime
)
124 m_testHooks
->willAnimateLayers(this, monotonicTime
);
125 LayerTreeHostImpl::animateLayers(monotonicTime
, wallClockTime
);
126 m_testHooks
->animateLayers(this, monotonicTime
);
129 void MockLayerTreeHostImpl::updateAnimationState()
131 LayerTreeHostImpl::updateAnimationState();
132 bool hasUnfinishedAnimation
= false;
133 AnimationRegistrar::AnimationControllerMap::const_iterator iter
= activeAnimationControllers().begin();
134 for (; iter
!= activeAnimationControllers().end(); ++iter
) {
135 if (iter
->second
->hasActiveAnimation()) {
136 hasUnfinishedAnimation
= true;
140 m_testHooks
->updateAnimationState(this, hasUnfinishedAnimation
);
143 base::TimeDelta
MockLayerTreeHostImpl::lowFrequencyAnimationInterval() const
145 return base::TimeDelta::FromMilliseconds(16);
148 MockLayerTreeHostImpl::MockLayerTreeHostImpl(TestHooks
* testHooks
, const LayerTreeSettings
& settings
, LayerTreeHostImplClient
* client
, Proxy
* proxy
)
149 : LayerTreeHostImpl(settings
, client
, proxy
)
150 , m_testHooks(testHooks
)
154 // Adapts LayerTreeHost for test. Injects MockLayerTreeHostImpl.
155 class MockLayerTreeHost
: public cc::LayerTreeHost
{
157 static scoped_ptr
<MockLayerTreeHost
> create(TestHooks
* testHooks
, cc::LayerTreeHostClient
* client
, const cc::LayerTreeSettings
& settings
, scoped_ptr
<cc::Thread
> implThread
)
159 scoped_ptr
<MockLayerTreeHost
> layerTreeHost(new MockLayerTreeHost(testHooks
, client
, settings
));
160 bool success
= layerTreeHost
->initialize(implThread
.Pass());
161 EXPECT_TRUE(success
);
162 return layerTreeHost
.Pass();
165 virtual scoped_ptr
<cc::LayerTreeHostImpl
> createLayerTreeHostImpl(cc::LayerTreeHostImplClient
* client
) OVERRIDE
167 return MockLayerTreeHostImpl::create(m_testHooks
, settings(), client
, proxy()).PassAs
<cc::LayerTreeHostImpl
>();
170 virtual void setNeedsCommit() OVERRIDE
174 LayerTreeHost::setNeedsCommit();
177 void setTestStarted(bool started
) { m_testStarted
= started
; }
179 virtual void didDeferCommit() OVERRIDE
181 m_testHooks
->didDeferCommit();
185 MockLayerTreeHost(TestHooks
* testHooks
, cc::LayerTreeHostClient
* client
, const cc::LayerTreeSettings
& settings
)
186 : LayerTreeHost(client
, settings
)
187 , m_testHooks(testHooks
)
188 , m_testStarted(false)
192 TestHooks
* m_testHooks
;
196 // Implementation of LayerTreeHost callback interface.
197 class ThreadedMockLayerTreeHostClient
: public MockLayerImplTreeHostClient
{
199 static scoped_ptr
<ThreadedMockLayerTreeHostClient
> create(TestHooks
* testHooks
)
201 return make_scoped_ptr(new ThreadedMockLayerTreeHostClient(testHooks
));
204 virtual void willBeginFrame() OVERRIDE
208 virtual void didBeginFrame() OVERRIDE
212 virtual void animate(double monotonicTime
) OVERRIDE
214 m_testHooks
->animate(base::TimeTicks::FromInternalValue(monotonicTime
* base::Time::kMicrosecondsPerSecond
));
217 virtual void layout() OVERRIDE
219 m_testHooks
->layout();
222 virtual void applyScrollAndScale(gfx::Vector2d scrollDelta
, float scale
) OVERRIDE
224 m_testHooks
->applyScrollAndScale(scrollDelta
, scale
);
227 virtual scoped_ptr
<OutputSurface
> createOutputSurface() OVERRIDE
229 return m_testHooks
->createOutputSurface();
232 virtual void didRecreateOutputSurface(bool succeeded
) OVERRIDE
234 m_testHooks
->didRecreateOutputSurface(succeeded
);
237 virtual void willRetryRecreateOutputSurface() OVERRIDE
239 m_testHooks
->willRetryRecreateOutputSurface();
242 virtual scoped_ptr
<InputHandler
> createInputHandler() OVERRIDE
244 return scoped_ptr
<InputHandler
>();
247 virtual void willCommit() OVERRIDE
251 virtual void didCommit() OVERRIDE
253 m_testHooks
->didCommit();
256 virtual void didCommitAndDrawFrame() OVERRIDE
258 m_testHooks
->didCommitAndDrawFrame();
261 virtual void didCompleteSwapBuffers() OVERRIDE
265 virtual void scheduleComposite() OVERRIDE
267 m_testHooks
->scheduleComposite();
270 virtual scoped_refptr
<cc::ContextProvider
> OffscreenContextProviderForMainThread() OVERRIDE
272 return m_testHooks
->OffscreenContextProviderForMainThread();
275 virtual scoped_refptr
<cc::ContextProvider
> OffscreenContextProviderForCompositorThread() OVERRIDE
277 return m_testHooks
->OffscreenContextProviderForCompositorThread();
281 explicit ThreadedMockLayerTreeHostClient(TestHooks
* testHooks
) : m_testHooks(testHooks
) { }
283 TestHooks
* m_testHooks
;
286 ThreadedTest::ThreadedTest()
288 , m_endWhenBeginReturns(false)
293 , m_weakFactory(ALLOW_THIS_IN_INITIALIZER_LIST(this))
295 m_mainThreadWeakPtr
= m_weakFactory
.GetWeakPtr();
298 ThreadedTest::~ThreadedTest()
302 void ThreadedTest::endTest()
304 // For the case where we endTest during beginTest(), set a flag to indicate that
305 // the test should end the second beginTest regains control.
307 m_endWhenBeginReturns
= true;
309 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::realEndTest
, m_mainThreadWeakPtr
));
312 void ThreadedTest::endTestAfterDelay(int delayMilliseconds
)
314 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::endTest
, m_mainThreadWeakPtr
));
317 void ThreadedTest::postAddAnimationToMainThread(Layer
* layerToReceiveAnimation
)
319 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::dispatchAddAnimation
, m_mainThreadWeakPtr
, base::Unretained(layerToReceiveAnimation
)));
322 void ThreadedTest::postAddInstantAnimationToMainThread()
324 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::dispatchAddInstantAnimation
, m_mainThreadWeakPtr
));
327 void ThreadedTest::postSetNeedsCommitToMainThread()
329 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::dispatchSetNeedsCommit
, m_mainThreadWeakPtr
));
332 void ThreadedTest::postAcquireLayerTextures()
334 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::dispatchAcquireLayerTextures
, m_mainThreadWeakPtr
));
337 void ThreadedTest::postSetNeedsRedrawToMainThread()
339 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::dispatchSetNeedsRedraw
, m_mainThreadWeakPtr
));
342 void ThreadedTest::postSetVisibleToMainThread(bool visible
)
344 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::dispatchSetVisible
, m_mainThreadWeakPtr
, visible
));
347 void ThreadedTest::doBeginTest()
349 m_client
= ThreadedMockLayerTreeHostClient::create(this);
351 scoped_ptr
<cc::Thread
> implCCThread(NULL
);
353 implCCThread
= cc::ThreadImpl::createForDifferentThread(m_implThread
->message_loop_proxy());
354 m_layerTreeHost
= MockLayerTreeHost::create(this, m_client
.get(), m_settings
, implCCThread
.Pass());
355 ASSERT_TRUE(m_layerTreeHost
.get());
360 m_layerTreeHost
->setSurfaceReady();
363 if (m_endWhenBeginReturns
)
366 // Allow commits to happen once beginTest() has had a chance to post tasks
367 // so that those tasks will happen before the first commit.
369 static_cast<MockLayerTreeHost
*>(m_layerTreeHost
.get())->setTestStarted(true);
372 void ThreadedTest::setupTree()
374 if (!m_layerTreeHost
->rootLayer()) {
375 scoped_refptr
<Layer
> rootLayer
= Layer::create();
376 rootLayer
->setBounds(gfx::Size(1, 1));
377 m_layerTreeHost
->setRootLayer(rootLayer
);
380 gfx::Size rootBounds
= m_layerTreeHost
->rootLayer()->bounds();
381 gfx::Size deviceRootBounds
= gfx::ToCeiledSize(
382 gfx::ScaleSize(rootBounds
, m_layerTreeHost
->deviceScaleFactor()));
383 m_layerTreeHost
->setViewportSize(rootBounds
, deviceRootBounds
);
386 void ThreadedTest::timeout()
392 void ThreadedTest::scheduleComposite()
394 if (!m_started
|| m_scheduled
)
397 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::dispatchComposite
, m_mainThreadWeakPtr
));
400 void ThreadedTest::realEndTest()
402 if (m_layerTreeHost
&& proxy()->commitPendingForTesting()) {
403 proxy()->mainThread()->postTask(base::Bind(&ThreadedTest::realEndTest
, m_mainThreadWeakPtr
));
407 MessageLoop::current()->Quit();
410 void ThreadedTest::dispatchAddInstantAnimation()
412 DCHECK(!proxy() || proxy()->isMainThread());
414 if (m_layerTreeHost
.get() && m_layerTreeHost
->rootLayer())
415 addOpacityTransitionToLayer(*m_layerTreeHost
->rootLayer(), 0, 0, 0.5, false);
418 void ThreadedTest::dispatchAddAnimation(Layer
* layerToReceiveAnimation
)
420 DCHECK(!proxy() || proxy()->isMainThread());
422 if (layerToReceiveAnimation
)
423 addOpacityTransitionToLayer(*layerToReceiveAnimation
, 10, 0, 0.5, true);
426 void ThreadedTest::dispatchSetNeedsCommit()
428 DCHECK(!proxy() || proxy()->isMainThread());
430 if (m_layerTreeHost
.get())
431 m_layerTreeHost
->setNeedsCommit();
434 void ThreadedTest::dispatchAcquireLayerTextures()
436 DCHECK(!proxy() || proxy()->isMainThread());
438 if (m_layerTreeHost
.get())
439 m_layerTreeHost
->acquireLayerTextures();
442 void ThreadedTest::dispatchSetNeedsRedraw()
444 DCHECK(!proxy() || proxy()->isMainThread());
446 if (m_layerTreeHost
.get())
447 m_layerTreeHost
->setNeedsRedraw();
450 void ThreadedTest::dispatchSetVisible(bool visible
)
452 DCHECK(!proxy() || proxy()->isMainThread());
454 if (m_layerTreeHost
.get())
455 m_layerTreeHost
->setVisible(visible
);
458 void ThreadedTest::dispatchComposite()
461 if (m_layerTreeHost
.get())
462 m_layerTreeHost
->composite();
465 void ThreadedTest::runTest(bool threaded
)
468 m_implThread
.reset(new base::Thread("ThreadedTest"));
469 ASSERT_TRUE(m_implThread
->Start());
472 m_mainCCThread
= cc::ThreadImpl::createForCurrentThread();
474 initializeSettings(m_settings
);
476 m_mainCCThread
->postTask(base::Bind(&ThreadedTest::doBeginTest
, base::Unretained(this)));
477 m_timeout
.Reset(base::Bind(&ThreadedTest::timeout
, base::Unretained(this)));
478 m_mainCCThread
->postDelayedTask(m_timeout
.callback(), 5000);
479 MessageLoop::current()->Run();
480 if (m_layerTreeHost
.get() && m_layerTreeHost
->rootLayer())
481 m_layerTreeHost
->rootLayer()->setLayerTreeHost(0);
482 m_layerTreeHost
.reset();
486 ASSERT_FALSE(m_layerTreeHost
.get());
489 FAIL() << "Test timed out";