OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "config.h" | |
6 | |
7 #include "CCThreadedTest.h" | |
8 | |
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 "base/stl_util.h" | |
27 #include "testing/gmock/include/gmock/gmock.h" | |
28 #include <public/Platform.h> | |
29 #include <public/WebCompositorSupport.h> | |
30 #include <public/WebFilterOperation.h> | |
31 #include <public/WebFilterOperations.h> | |
32 #include <public/WebThread.h> | |
33 #include <wtf/Locker.h> | |
34 | |
35 using namespace cc; | |
36 using namespace WebKit; | |
37 | |
38 namespace WebKitTests { | |
39 | |
40 PassOwnPtr<CompositorFakeWebGraphicsContext3DWithTextureTracking> CompositorFake
WebGraphicsContext3DWithTextureTracking::create(Attributes attrs) | |
41 { | |
42 return adoptPtr(new CompositorFakeWebGraphicsContext3DWithTextureTracking(at
trs)); | |
43 } | |
44 | |
45 WebGLId CompositorFakeWebGraphicsContext3DWithTextureTracking::createTexture() | |
46 { | |
47 WebGLId texture = m_textures.size() + 1; | |
48 m_textures.append(texture); | |
49 return texture; | |
50 } | |
51 | |
52 void CompositorFakeWebGraphicsContext3DWithTextureTracking::deleteTexture(WebGLI
d texture) | |
53 { | |
54 for (size_t i = 0; i < m_textures.size(); i++) { | |
55 if (m_textures[i] == texture) { | |
56 m_textures.remove(i); | |
57 break; | |
58 } | |
59 } | |
60 } | |
61 | |
62 void CompositorFakeWebGraphicsContext3DWithTextureTracking::bindTexture(WGC3Denu
m /* target */, WebGLId texture) | |
63 { | |
64 m_usedTextures.insert(texture); | |
65 } | |
66 | |
67 int CompositorFakeWebGraphicsContext3DWithTextureTracking::numTextures() const {
return static_cast<int>(m_textures.size()); } | |
68 int CompositorFakeWebGraphicsContext3DWithTextureTracking::texture(int i) const
{ return m_textures[i]; } | |
69 void CompositorFakeWebGraphicsContext3DWithTextureTracking::resetTextures() { m_
textures.clear(); } | |
70 | |
71 int CompositorFakeWebGraphicsContext3DWithTextureTracking::numUsedTextures() con
st { return static_cast<int>(m_usedTextures.size()); } | |
72 bool CompositorFakeWebGraphicsContext3DWithTextureTracking::usedTexture(int text
ure) const | |
73 { | |
74 return ContainsKey(m_usedTextures, texture); | |
75 } | |
76 | |
77 void CompositorFakeWebGraphicsContext3DWithTextureTracking::resetUsedTextures()
{ m_usedTextures.clear(); } | |
78 | |
79 CompositorFakeWebGraphicsContext3DWithTextureTracking::CompositorFakeWebGraphics
Context3DWithTextureTracking(Attributes attrs) : CompositorFakeWebGraphicsContex
t3D(attrs) | |
80 { | |
81 } | |
82 | |
83 CompositorFakeWebGraphicsContext3DWithTextureTracking::~CompositorFakeWebGraphic
sContext3DWithTextureTracking() | |
84 { | |
85 } | |
86 | |
87 bool TestHooks::prepareToDrawOnCCThread(cc::CCLayerTreeHostImpl*) | |
88 { | |
89 return true; | |
90 } | |
91 | |
92 scoped_ptr<WebCompositorOutputSurface> TestHooks::createOutputSurface() | |
93 { | |
94 return FakeWebCompositorOutputSurface::create(CompositorFakeWebGraphicsConte
xt3DWithTextureTracking::create(WebGraphicsContext3D::Attributes())).PassAs<WebC
ompositorOutputSurface>(); | |
95 } | |
96 | |
97 scoped_ptr<MockLayerTreeHostImpl> MockLayerTreeHostImpl::create(TestHooks* testH
ooks, const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client) | |
98 { | |
99 return make_scoped_ptr(new MockLayerTreeHostImpl(testHooks, settings, client
)); | |
100 } | |
101 | |
102 void MockLayerTreeHostImpl::beginCommit() | |
103 { | |
104 CCLayerTreeHostImpl::beginCommit(); | |
105 m_testHooks->beginCommitOnCCThread(this); | |
106 } | |
107 | |
108 void MockLayerTreeHostImpl::commitComplete() | |
109 { | |
110 CCLayerTreeHostImpl::commitComplete(); | |
111 m_testHooks->commitCompleteOnCCThread(this); | |
112 } | |
113 | |
114 bool MockLayerTreeHostImpl::prepareToDraw(FrameData& frame) | |
115 { | |
116 bool result = CCLayerTreeHostImpl::prepareToDraw(frame); | |
117 if (!m_testHooks->prepareToDrawOnCCThread(this)) | |
118 result = false; | |
119 return result; | |
120 } | |
121 | |
122 void MockLayerTreeHostImpl::drawLayers(const FrameData& frame) | |
123 { | |
124 CCLayerTreeHostImpl::drawLayers(frame); | |
125 m_testHooks->drawLayersOnCCThread(this); | |
126 } | |
127 | |
128 void MockLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClock
Time) | |
129 { | |
130 m_testHooks->willAnimateLayers(this, monotonicTime); | |
131 CCLayerTreeHostImpl::animateLayers(monotonicTime, wallClockTime); | |
132 m_testHooks->animateLayers(this, monotonicTime); | |
133 } | |
134 | |
135 base::TimeDelta MockLayerTreeHostImpl::lowFrequencyAnimationInterval() const | |
136 { | |
137 return base::TimeDelta::FromMilliseconds(16); | |
138 } | |
139 | |
140 MockLayerTreeHostImpl::MockLayerTreeHostImpl(TestHooks* testHooks, const CCLayer
TreeSettings& settings, CCLayerTreeHostImplClient* client) | |
141 : CCLayerTreeHostImpl(settings, client) | |
142 , m_testHooks(testHooks) | |
143 { | |
144 } | |
145 | |
146 // Adapts CCLayerTreeHost for test. Injects MockLayerTreeHostImpl. | |
147 class MockLayerTreeHost : public cc::CCLayerTreeHost { | |
148 public: | |
149 static scoped_ptr<MockLayerTreeHost> create(TestHooks* testHooks, cc::CCLaye
rTreeHostClient* client, scoped_refptr<cc::LayerChromium> rootLayer, const cc::C
CLayerTreeSettings& settings) | |
150 { | |
151 scoped_ptr<MockLayerTreeHost> layerTreeHost(new MockLayerTreeHost(testHo
oks, client, settings)); | |
152 bool success = layerTreeHost->initialize(); | |
153 EXPECT_TRUE(success); | |
154 layerTreeHost->setRootLayer(rootLayer); | |
155 | |
156 // LayerTreeHostImpl won't draw if it has 1x1 viewport. | |
157 layerTreeHost->setViewportSize(IntSize(1, 1), IntSize(1, 1)); | |
158 | |
159 layerTreeHost->rootLayer()->setLayerAnimationDelegate(testHooks); | |
160 | |
161 return layerTreeHost.Pass(); | |
162 } | |
163 | |
164 virtual scoped_ptr<cc::CCLayerTreeHostImpl> createLayerTreeHostImpl(cc::CCLa
yerTreeHostImplClient* client) | |
165 { | |
166 return MockLayerTreeHostImpl::create(m_testHooks, settings(), client).Pa
ssAs<cc::CCLayerTreeHostImpl>(); | |
167 } | |
168 | |
169 virtual void didAddAnimation() OVERRIDE | |
170 { | |
171 CCLayerTreeHost::didAddAnimation(); | |
172 m_testHooks->didAddAnimation(); | |
173 } | |
174 | |
175 private: | |
176 MockLayerTreeHost(TestHooks* testHooks, cc::CCLayerTreeHostClient* client, c
onst cc::CCLayerTreeSettings& settings) | |
177 : CCLayerTreeHost(client, settings) | |
178 , m_testHooks(testHooks) | |
179 { | |
180 } | |
181 | |
182 TestHooks* m_testHooks; | |
183 }; | |
184 | |
185 // Implementation of CCLayerTreeHost callback interface. | |
186 class MockLayerTreeHostClient : public MockCCLayerTreeHostClient { | |
187 public: | |
188 static PassOwnPtr<MockLayerTreeHostClient> create(TestHooks* testHooks) | |
189 { | |
190 return adoptPtr(new MockLayerTreeHostClient(testHooks)); | |
191 } | |
192 | |
193 virtual void willBeginFrame() OVERRIDE | |
194 { | |
195 } | |
196 | |
197 virtual void didBeginFrame() OVERRIDE | |
198 { | |
199 } | |
200 | |
201 virtual void animate(double monotonicTime) OVERRIDE | |
202 { | |
203 m_testHooks->animate(monotonicTime); | |
204 } | |
205 | |
206 virtual void layout() OVERRIDE | |
207 { | |
208 m_testHooks->layout(); | |
209 } | |
210 | |
211 virtual void applyScrollAndScale(const IntSize& scrollDelta, float scale) OV
ERRIDE | |
212 { | |
213 m_testHooks->applyScrollAndScale(scrollDelta, scale); | |
214 } | |
215 | |
216 virtual scoped_ptr<WebCompositorOutputSurface> createOutputSurface() OVERRID
E | |
217 { | |
218 return m_testHooks->createOutputSurface(); | |
219 } | |
220 | |
221 virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE | |
222 { | |
223 m_testHooks->didRecreateOutputSurface(succeeded); | |
224 } | |
225 | |
226 virtual scoped_ptr<CCInputHandler> createInputHandler() OVERRIDE | |
227 { | |
228 return scoped_ptr<CCInputHandler>(); | |
229 } | |
230 | |
231 virtual void willCommit() OVERRIDE | |
232 { | |
233 } | |
234 | |
235 virtual void didCommit() OVERRIDE | |
236 { | |
237 m_testHooks->didCommit(); | |
238 } | |
239 | |
240 virtual void didCommitAndDrawFrame() OVERRIDE | |
241 { | |
242 m_testHooks->didCommitAndDrawFrame(); | |
243 } | |
244 | |
245 virtual void didCompleteSwapBuffers() OVERRIDE | |
246 { | |
247 } | |
248 | |
249 virtual void scheduleComposite() OVERRIDE | |
250 { | |
251 m_testHooks->scheduleComposite(); | |
252 } | |
253 | |
254 private: | |
255 explicit MockLayerTreeHostClient(TestHooks* testHooks) : m_testHooks(testHoo
ks) { } | |
256 | |
257 TestHooks* m_testHooks; | |
258 }; | |
259 | |
260 class TimeoutTask : public WebThread::Task { | |
261 public: | |
262 explicit TimeoutTask(CCThreadedTest* test) | |
263 : m_test(test) | |
264 { | |
265 } | |
266 | |
267 void clearTest() | |
268 { | |
269 m_test = 0; | |
270 } | |
271 | |
272 virtual ~TimeoutTask() | |
273 { | |
274 if (m_test) | |
275 m_test->clearTimeout(); | |
276 } | |
277 | |
278 virtual void run() | |
279 { | |
280 if (m_test) | |
281 m_test->timeout(); | |
282 } | |
283 | |
284 private: | |
285 CCThreadedTest* m_test; | |
286 }; | |
287 | |
288 class BeginTask : public WebThread::Task { | |
289 public: | |
290 explicit BeginTask(CCThreadedTest* test) | |
291 : m_test(test) | |
292 { | |
293 } | |
294 | |
295 virtual ~BeginTask() { } | |
296 virtual void run() | |
297 { | |
298 m_test->doBeginTest(); | |
299 } | |
300 private: | |
301 CCThreadedTest* m_test; | |
302 }; | |
303 | |
304 CCThreadedTest::CCThreadedTest() | |
305 : m_beginning(false) | |
306 , m_endWhenBeginReturns(false) | |
307 , m_timedOut(false) | |
308 , m_finished(false) | |
309 , m_scheduled(false) | |
310 , m_started(false) | |
311 { | |
312 } | |
313 | |
314 CCThreadedTest::~CCThreadedTest() | |
315 { | |
316 } | |
317 | |
318 void CCThreadedTest::endTest() | |
319 { | |
320 m_finished = true; | |
321 | |
322 // For the case where we endTest during beginTest(), set a flag to indicate
that | |
323 // the test should end the second beginTest regains control. | |
324 if (m_beginning) | |
325 m_endWhenBeginReturns = true; | |
326 else | |
327 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::re
alEndTest)); | |
328 } | |
329 | |
330 void CCThreadedTest::endTestAfterDelay(int delayMilliseconds) | |
331 { | |
332 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::endTes
t)); | |
333 } | |
334 | |
335 void CCThreadedTest::postSetNeedsAnimateToMainThread() | |
336 { | |
337 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chSetNeedsAnimate)); | |
338 } | |
339 | |
340 void CCThreadedTest::postAddAnimationToMainThread() | |
341 { | |
342 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chAddAnimation)); | |
343 } | |
344 | |
345 void CCThreadedTest::postAddInstantAnimationToMainThread() | |
346 { | |
347 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chAddInstantAnimation)); | |
348 } | |
349 | |
350 void CCThreadedTest::postSetNeedsCommitToMainThread() | |
351 { | |
352 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chSetNeedsCommit)); | |
353 } | |
354 | |
355 void CCThreadedTest::postAcquireLayerTextures() | |
356 { | |
357 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chAcquireLayerTextures)); | |
358 } | |
359 | |
360 void CCThreadedTest::postSetNeedsRedrawToMainThread() | |
361 { | |
362 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chSetNeedsRedraw)); | |
363 } | |
364 | |
365 void CCThreadedTest::postSetNeedsAnimateAndCommitToMainThread() | |
366 { | |
367 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chSetNeedsAnimateAndCommit)); | |
368 } | |
369 | |
370 void CCThreadedTest::postSetVisibleToMainThread(bool visible) | |
371 { | |
372 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chSetVisible, visible)); | |
373 } | |
374 | |
375 void CCThreadedTest::postDidAddAnimationToMainThread() | |
376 { | |
377 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chDidAddAnimation)); | |
378 } | |
379 | |
380 void CCThreadedTest::doBeginTest() | |
381 { | |
382 ASSERT(CCProxy::isMainThread()); | |
383 m_client = MockLayerTreeHostClient::create(this); | |
384 | |
385 scoped_refptr<LayerChromium> rootLayer = LayerChromium::create(); | |
386 m_layerTreeHost = MockLayerTreeHost::create(this, m_client.get(), rootLayer,
m_settings); | |
387 ASSERT_TRUE(m_layerTreeHost.get()); | |
388 rootLayer->setLayerTreeHost(m_layerTreeHost.get()); | |
389 m_layerTreeHost->setSurfaceReady(); | |
390 | |
391 m_started = true; | |
392 m_beginning = true; | |
393 beginTest(); | |
394 m_beginning = false; | |
395 if (m_endWhenBeginReturns) | |
396 realEndTest(); | |
397 } | |
398 | |
399 void CCThreadedTest::timeout() | |
400 { | |
401 m_timedOut = true; | |
402 endTest(); | |
403 } | |
404 | |
405 void CCThreadedTest::scheduleComposite() | |
406 { | |
407 if (!m_started || m_scheduled || m_finished) | |
408 return; | |
409 m_scheduled = true; | |
410 m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadedTest::dispat
chComposite)); | |
411 } | |
412 | |
413 void CCThreadedTest::realEndTest() | |
414 { | |
415 ASSERT(CCProxy::isMainThread()); | |
416 WebKit::Platform::current()->currentThread()->exitRunLoop(); | |
417 } | |
418 | |
419 void CCThreadedTest::dispatchSetNeedsAnimate() | |
420 { | |
421 ASSERT(CCProxy::isMainThread()); | |
422 | |
423 if (m_finished) | |
424 return; | |
425 | |
426 if (m_layerTreeHost.get()) | |
427 m_layerTreeHost->setNeedsAnimate(); | |
428 } | |
429 | |
430 void CCThreadedTest::dispatchAddInstantAnimation() | |
431 { | |
432 ASSERT(CCProxy::isMainThread()); | |
433 | |
434 if (m_finished) | |
435 return; | |
436 | |
437 if (m_layerTreeHost.get() && m_layerTreeHost->rootLayer()) | |
438 addOpacityTransitionToLayer(*m_layerTreeHost->rootLayer(), 0, 0, 0.5, fa
lse); | |
439 } | |
440 | |
441 void CCThreadedTest::dispatchAddAnimation() | |
442 { | |
443 ASSERT(CCProxy::isMainThread()); | |
444 | |
445 if (m_finished) | |
446 return; | |
447 | |
448 if (m_layerTreeHost.get() && m_layerTreeHost->rootLayer()) | |
449 addOpacityTransitionToLayer(*m_layerTreeHost->rootLayer(), 10, 0, 0.5, t
rue); | |
450 } | |
451 | |
452 void CCThreadedTest::dispatchSetNeedsAnimateAndCommit() | |
453 { | |
454 ASSERT(CCProxy::isMainThread()); | |
455 | |
456 if (m_finished) | |
457 return; | |
458 | |
459 if (m_layerTreeHost.get()) { | |
460 m_layerTreeHost->setNeedsAnimate(); | |
461 m_layerTreeHost->setNeedsCommit(); | |
462 } | |
463 } | |
464 | |
465 void CCThreadedTest::dispatchSetNeedsCommit() | |
466 { | |
467 ASSERT(CCProxy::isMainThread()); | |
468 | |
469 if (m_finished) | |
470 return; | |
471 | |
472 if (m_layerTreeHost.get()) | |
473 m_layerTreeHost->setNeedsCommit(); | |
474 } | |
475 | |
476 void CCThreadedTest::dispatchAcquireLayerTextures() | |
477 { | |
478 ASSERT(CCProxy::isMainThread()); | |
479 | |
480 if (m_finished) | |
481 return; | |
482 | |
483 if (m_layerTreeHost.get()) | |
484 m_layerTreeHost->acquireLayerTextures(); | |
485 } | |
486 | |
487 void CCThreadedTest::dispatchSetNeedsRedraw() | |
488 { | |
489 ASSERT(CCProxy::isMainThread()); | |
490 | |
491 if (m_finished) | |
492 return; | |
493 | |
494 if (m_layerTreeHost.get()) | |
495 m_layerTreeHost->setNeedsRedraw(); | |
496 } | |
497 | |
498 void CCThreadedTest::dispatchSetVisible(bool visible) | |
499 { | |
500 ASSERT(CCProxy::isMainThread()); | |
501 | |
502 if (m_finished) | |
503 return; | |
504 | |
505 if (m_layerTreeHost.get()) | |
506 m_layerTreeHost->setVisible(visible); | |
507 } | |
508 | |
509 void CCThreadedTest::dispatchComposite() | |
510 { | |
511 m_scheduled = false; | |
512 if (m_layerTreeHost.get() && !m_finished) | |
513 m_layerTreeHost->composite(); | |
514 } | |
515 | |
516 void CCThreadedTest::dispatchDidAddAnimation() | |
517 { | |
518 ASSERT(CCProxy::isMainThread()); | |
519 | |
520 if (m_finished) | |
521 return; | |
522 | |
523 if (m_layerTreeHost.get()) | |
524 m_layerTreeHost->didAddAnimation(); | |
525 } | |
526 | |
527 void CCThreadedTest::runTest(bool threaded) | |
528 { | |
529 // For these tests, we will enable threaded animations. | |
530 Platform::current()->compositorSupport()->setAcceleratedAnimationEnabled(tru
e); | |
531 | |
532 if (threaded) { | |
533 m_webThread = adoptPtr(WebKit::Platform::current()->createThread("CCThre
adedTest")); | |
534 Platform::current()->compositorSupport()->initialize(m_webThread.get()); | |
535 } else | |
536 Platform::current()->compositorSupport()->initialize(0); | |
537 | |
538 ASSERT(CCProxy::isMainThread()); | |
539 m_mainThreadProxy = CCScopedThreadProxy::create(CCProxy::mainThread()); | |
540 | |
541 initializeSettings(m_settings); | |
542 | |
543 m_beginTask = new BeginTask(this); | |
544 WebKit::Platform::current()->currentThread()->postDelayedTask(m_beginTask, 0
); // postDelayedTask takes ownership of the task | |
545 m_timeoutTask = new TimeoutTask(this); | |
546 WebKit::Platform::current()->currentThread()->postDelayedTask(m_timeoutTask,
5000); | |
547 WebKit::Platform::current()->currentThread()->enterRunLoop(); | |
548 | |
549 if (m_layerTreeHost.get() && m_layerTreeHost->rootLayer()) | |
550 m_layerTreeHost->rootLayer()->setLayerTreeHost(0); | |
551 m_layerTreeHost.reset(); | |
552 | |
553 if (m_timeoutTask) | |
554 m_timeoutTask->clearTest(); | |
555 | |
556 ASSERT_FALSE(m_layerTreeHost.get()); | |
557 m_client.clear(); | |
558 if (m_timedOut) { | |
559 FAIL() << "Test timed out"; | |
560 Platform::current()->compositorSupport()->shutdown(); | |
561 return; | |
562 } | |
563 afterTest(); | |
564 Platform::current()->compositorSupport()->shutdown(); | |
565 } | |
566 | |
567 } // namespace WebKitTests | |
OLD | NEW |