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 "CCLayerTreeHostImpl.h"
9 #include "CCAnimationTestCommon.h"
10 #include "CCGeometryTestUtils.h"
11 #include "CCHeadsUpDisplayLayerImpl.h"
12 #include "CCIOSurfaceLayerImpl.h"
13 #include "CCLayerImpl.h"
14 #include "CCLayerTestCommon.h"
15 #include "CCLayerTilingData.h"
16 #include "CCQuadSink.h"
17 #include "CCRenderPassDrawQuad.h"
18 #include "CCRendererGL.h"
19 #include "CCScrollbarGeometryFixedThumb.h"
20 #include "CCScrollbarLayerImpl.h"
21 #include "CCSettings.h"
22 #include "CCSingleThreadProxy.h"
23 #include "CCSolidColorDrawQuad.h"
24 #include "CCTestCommon.h"
25 #include "CCTextureLayerImpl.h"
26 #include "CCTileDrawQuad.h"
27 #include "CCTiledLayerImpl.h"
28 #include "CCVideoLayerImpl.h"
29 #include "FakeWebCompositorOutputSurface.h"
30 #include "FakeWebGraphicsContext3D.h"
31 #include "FakeWebScrollbarThemeGeometry.h"
32 #include <gmock/gmock.h>
33 #include <gtest/gtest.h>
34 #include <public/WebVideoFrame.h>
35 #include <public/WebVideoFrameProvider.h>
37 using namespace CCLayerTestCommon
;
38 using namespace WebCore
;
39 using namespace WebKit
;
40 using namespace WebKitTests
;
42 using ::testing::Mock
;
43 using ::testing::Return
;
44 using ::testing::AnyNumber
;
45 using ::testing::AtLeast
;
50 class CCLayerTreeHostImplTest
: public testing::Test
, public CCLayerTreeHostImplClient
{
52 CCLayerTreeHostImplTest()
53 : m_onCanDrawStateChangedCalled(false)
54 , m_didRequestCommit(false)
55 , m_didRequestRedraw(false)
57 CCLayerTreeSettings settings
;
58 settings
.minimumOcclusionTrackingSize
= IntSize();
60 m_hostImpl
= CCLayerTreeHostImpl::create(settings
, this);
61 m_hostImpl
->initializeRenderer(createContext(), UnthrottledUploader
);
62 m_hostImpl
->setViewportSize(IntSize(10, 10), IntSize(10, 10));
65 virtual void didLoseContextOnImplThread() OVERRIDE
{ }
66 virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE
{ }
67 virtual void onVSyncParametersChanged(double, double) OVERRIDE
{ }
68 virtual void onCanDrawStateChanged(bool canDraw
) OVERRIDE
{ m_onCanDrawStateChangedCalled
= true; }
69 virtual void setNeedsRedrawOnImplThread() OVERRIDE
{ m_didRequestRedraw
= true; }
70 virtual void setNeedsCommitOnImplThread() OVERRIDE
{ m_didRequestCommit
= true; }
71 virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr
<CCAnimationEventsVector
>, double wallClockTime
) OVERRIDE
{ }
73 PassOwnPtr
<CCLayerTreeHostImpl
> createLayerTreeHost(bool partialSwap
, PassOwnPtr
<CCGraphicsContext
> graphicsContext
, PassOwnPtr
<CCLayerImpl
> rootPtr
)
75 CCSettings::setPartialSwapEnabled(partialSwap
);
77 CCLayerTreeSettings settings
;
78 settings
.minimumOcclusionTrackingSize
= IntSize();
80 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
82 myHostImpl
->initializeRenderer(graphicsContext
, UnthrottledUploader
);
83 myHostImpl
->setViewportSize(IntSize(10, 10), IntSize(10, 10));
85 OwnPtr
<CCLayerImpl
> root
= rootPtr
;
87 root
->setAnchorPoint(FloatPoint(0, 0));
88 root
->setPosition(FloatPoint(0, 0));
89 root
->setBounds(IntSize(10, 10));
90 root
->setContentBounds(IntSize(10, 10));
91 root
->setVisibleContentRect(IntRect(0, 0, 10, 10));
92 root
->setDrawsContent(true);
93 myHostImpl
->setRootLayer(root
.release());
94 return myHostImpl
.release();
97 static void expectClearedScrollDeltasRecursive(CCLayerImpl
* layer
)
99 ASSERT_EQ(layer
->scrollDelta(), IntSize());
100 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
101 expectClearedScrollDeltasRecursive(layer
->children()[i
].get());
104 static void expectContains(const CCScrollAndScaleSet
& scrollInfo
, int id
, const IntSize
& scrollDelta
)
106 int timesEncountered
= 0;
108 for (size_t i
= 0; i
< scrollInfo
.scrolls
.size(); ++i
) {
109 if (scrollInfo
.scrolls
[i
].layerId
!= id
)
111 EXPECT_EQ(scrollDelta
.width(), scrollInfo
.scrolls
[i
].scrollDelta
.width());
112 EXPECT_EQ(scrollDelta
.height(), scrollInfo
.scrolls
[i
].scrollDelta
.height());
116 ASSERT_EQ(timesEncountered
, 1);
119 void setupScrollAndContentsLayers(const IntSize
& contentSize
)
121 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
122 root
->setScrollable(true);
123 root
->setScrollPosition(IntPoint(0, 0));
124 root
->setMaxScrollPosition(contentSize
);
125 root
->setBounds(contentSize
);
126 root
->setContentBounds(contentSize
);
127 root
->setPosition(FloatPoint(0, 0));
128 root
->setAnchorPoint(FloatPoint(0, 0));
130 OwnPtr
<CCLayerImpl
> contents
= CCLayerImpl::create(2);
131 contents
->setDrawsContent(true);
132 contents
->setBounds(contentSize
);
133 contents
->setContentBounds(contentSize
);
134 contents
->setPosition(FloatPoint(0, 0));
135 contents
->setAnchorPoint(FloatPoint(0, 0));
136 root
->addChild(contents
.release());
137 m_hostImpl
->setRootLayer(root
.release());
140 static PassOwnPtr
<CCLayerImpl
> createScrollableLayer(int id
, const IntSize
& size
)
142 OwnPtr
<CCLayerImpl
> layer
= CCLayerImpl::create(id
);
143 layer
->setScrollable(true);
144 layer
->setDrawsContent(true);
145 layer
->setBounds(size
);
146 layer
->setContentBounds(size
);
147 layer
->setMaxScrollPosition(IntSize(size
.width() * 2, size
.height() * 2));
148 return layer
.release();
151 void initializeRendererAndDrawFrame()
153 m_hostImpl
->initializeRenderer(createContext(), UnthrottledUploader
);
154 CCLayerTreeHostImpl::FrameData frame
;
155 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
156 m_hostImpl
->drawLayers(frame
);
157 m_hostImpl
->didDrawAllLayers(frame
);
161 PassOwnPtr
<CCGraphicsContext
> createContext()
163 return FakeWebCompositorOutputSurface::create(adoptPtr(new FakeWebGraphicsContext3D
));
166 DebugScopedSetImplThread m_alwaysImplThread
;
167 DebugScopedSetMainThreadBlocked m_alwaysMainThreadBlocked
;
169 OwnPtr
<CCLayerTreeHostImpl
> m_hostImpl
;
170 bool m_onCanDrawStateChangedCalled
;
171 bool m_didRequestCommit
;
172 bool m_didRequestRedraw
;
173 CCScopedSettings m_scopedSettings
;
176 class FakeWebGraphicsContext3DMakeCurrentFails
: public FakeWebGraphicsContext3D
{
178 virtual bool makeContextCurrent() { return false; }
181 TEST_F(CCLayerTreeHostImplTest
, notifyIfCanDrawChanged
)
183 // Note: It is not possible to disable the renderer once it has been set,
184 // so we do not need to test that disabling the renderer notifies us
185 // that canDraw changed.
186 EXPECT_FALSE(m_hostImpl
->canDraw());
187 m_onCanDrawStateChangedCalled
= false;
189 setupScrollAndContentsLayers(IntSize(100, 100));
190 EXPECT_TRUE(m_hostImpl
->canDraw());
191 EXPECT_TRUE(m_onCanDrawStateChangedCalled
);
192 m_onCanDrawStateChangedCalled
= false;
194 // Toggle the root layer to make sure it toggles canDraw
195 m_hostImpl
->setRootLayer(adoptPtr
<CCLayerImpl
>(0));
196 EXPECT_FALSE(m_hostImpl
->canDraw());
197 EXPECT_TRUE(m_onCanDrawStateChangedCalled
);
198 m_onCanDrawStateChangedCalled
= false;
200 setupScrollAndContentsLayers(IntSize(100, 100));
201 EXPECT_TRUE(m_hostImpl
->canDraw());
202 EXPECT_TRUE(m_onCanDrawStateChangedCalled
);
203 m_onCanDrawStateChangedCalled
= false;
205 // Toggle the device viewport size to make sure it toggles canDraw.
206 m_hostImpl
->setViewportSize(IntSize(100, 100), IntSize(0, 0));
207 EXPECT_FALSE(m_hostImpl
->canDraw());
208 EXPECT_TRUE(m_onCanDrawStateChangedCalled
);
209 m_onCanDrawStateChangedCalled
= false;
211 m_hostImpl
->setViewportSize(IntSize(100, 100), IntSize(100, 100));
212 EXPECT_TRUE(m_hostImpl
->canDraw());
213 EXPECT_TRUE(m_onCanDrawStateChangedCalled
);
214 m_onCanDrawStateChangedCalled
= false;
216 // Toggle contents textures purged to make sure it toggles canDraw
217 m_hostImpl
->releaseContentsTextures();
218 EXPECT_FALSE(m_hostImpl
->canDraw());
219 EXPECT_TRUE(m_onCanDrawStateChangedCalled
);
220 m_onCanDrawStateChangedCalled
= false;
222 m_hostImpl
->resetContentsTexturesPurged();
223 EXPECT_TRUE(m_hostImpl
->canDraw());
224 EXPECT_TRUE(m_onCanDrawStateChangedCalled
);
225 m_onCanDrawStateChangedCalled
= false;
228 TEST_F(CCLayerTreeHostImplTest
, scrollDeltaNoLayers
)
230 ASSERT_FALSE(m_hostImpl
->rootLayer());
232 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
233 ASSERT_EQ(scrollInfo
->scrolls
.size(), 0u);
236 TEST_F(CCLayerTreeHostImplTest
, scrollDeltaTreeButNoChanges
)
239 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
240 root
->addChild(CCLayerImpl::create(2));
241 root
->addChild(CCLayerImpl::create(3));
242 root
->children()[1]->addChild(CCLayerImpl::create(4));
243 root
->children()[1]->addChild(CCLayerImpl::create(5));
244 root
->children()[1]->children()[0]->addChild(CCLayerImpl::create(6));
245 m_hostImpl
->setRootLayer(root
.release());
247 CCLayerImpl
* root
= m_hostImpl
->rootLayer();
249 expectClearedScrollDeltasRecursive(root
);
251 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
;
253 scrollInfo
= m_hostImpl
->processScrollDeltas();
254 ASSERT_EQ(scrollInfo
->scrolls
.size(), 0u);
255 expectClearedScrollDeltasRecursive(root
);
257 scrollInfo
= m_hostImpl
->processScrollDeltas();
258 ASSERT_EQ(scrollInfo
->scrolls
.size(), 0u);
259 expectClearedScrollDeltasRecursive(root
);
262 TEST_F(CCLayerTreeHostImplTest
, scrollDeltaRepeatedScrolls
)
264 IntPoint
scrollPosition(20, 30);
265 IntSize
scrollDelta(11, -15);
267 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
268 root
->setScrollPosition(scrollPosition
);
269 root
->setScrollable(true);
270 root
->setMaxScrollPosition(IntSize(100, 100));
271 root
->scrollBy(scrollDelta
);
272 m_hostImpl
->setRootLayer(root
.release());
274 CCLayerImpl
* root
= m_hostImpl
->rootLayer();
276 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
;
278 scrollInfo
= m_hostImpl
->processScrollDeltas();
279 ASSERT_EQ(scrollInfo
->scrolls
.size(), 1u);
280 EXPECT_EQ(root
->sentScrollDelta(), scrollDelta
);
281 expectContains(*scrollInfo
, root
->id(), scrollDelta
);
283 IntSize
scrollDelta2(-5, 27);
284 root
->scrollBy(scrollDelta2
);
285 scrollInfo
= m_hostImpl
->processScrollDeltas();
286 ASSERT_EQ(scrollInfo
->scrolls
.size(), 1u);
287 EXPECT_EQ(root
->sentScrollDelta(), scrollDelta
+ scrollDelta2
);
288 expectContains(*scrollInfo
, root
->id(), scrollDelta
+ scrollDelta2
);
290 root
->scrollBy(IntSize());
291 scrollInfo
= m_hostImpl
->processScrollDeltas();
292 EXPECT_EQ(root
->sentScrollDelta(), scrollDelta
+ scrollDelta2
);
295 TEST_F(CCLayerTreeHostImplTest
, scrollRootCallsCommitAndRedraw
)
297 setupScrollAndContentsLayers(IntSize(100, 100));
298 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
299 initializeRendererAndDrawFrame();
301 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
302 m_hostImpl
->scrollBy(IntPoint(), IntSize(0, 10));
303 m_hostImpl
->scrollEnd();
304 EXPECT_TRUE(m_didRequestRedraw
);
305 EXPECT_TRUE(m_didRequestCommit
);
308 TEST_F(CCLayerTreeHostImplTest
, scrollWithoutRootLayer
)
310 // We should not crash when trying to scroll an empty layer tree.
311 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollIgnored
);
314 TEST_F(CCLayerTreeHostImplTest
, scrollWithoutRenderer
)
316 CCLayerTreeSettings settings
;
317 m_hostImpl
= CCLayerTreeHostImpl::create(settings
, this);
319 // Initialization will fail here.
320 m_hostImpl
->initializeRenderer(FakeWebCompositorOutputSurface::create(adoptPtr(new FakeWebGraphicsContext3DMakeCurrentFails
)), UnthrottledUploader
);
321 m_hostImpl
->setViewportSize(IntSize(10, 10), IntSize(10, 10));
323 setupScrollAndContentsLayers(IntSize(100, 100));
325 // We should not crash when trying to scroll after the renderer initialization fails.
326 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollIgnored
);
329 TEST_F(CCLayerTreeHostImplTest
, replaceTreeWhileScrolling
)
331 const int scrollLayerId
= 1;
333 setupScrollAndContentsLayers(IntSize(100, 100));
334 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
335 initializeRendererAndDrawFrame();
337 // We should not crash if the tree is replaced while we are scrolling.
338 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
339 m_hostImpl
->detachLayerTree();
341 setupScrollAndContentsLayers(IntSize(100, 100));
343 // We should still be scrolling, because the scrolled layer also exists in the new tree.
344 IntSize
scrollDelta(0, 10);
345 m_hostImpl
->scrollBy(IntPoint(), scrollDelta
);
346 m_hostImpl
->scrollEnd();
347 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
348 expectContains(*scrollInfo
, scrollLayerId
, scrollDelta
);
351 TEST_F(CCLayerTreeHostImplTest
, clearRootRenderSurfaceAndScroll
)
353 setupScrollAndContentsLayers(IntSize(100, 100));
354 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
355 initializeRendererAndDrawFrame();
357 // We should be able to scroll even if the root layer loses its render surface after the most
359 m_hostImpl
->rootLayer()->clearRenderSurface();
360 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
363 TEST_F(CCLayerTreeHostImplTest
, wheelEventHandlers
)
365 setupScrollAndContentsLayers(IntSize(100, 100));
366 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
367 initializeRendererAndDrawFrame();
368 CCLayerImpl
* root
= m_hostImpl
->rootLayer();
370 root
->setHaveWheelEventHandlers(true);
372 // With registered event handlers, wheel scrolls have to go to the main thread.
373 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollOnMainThread
);
375 // But gesture scrolls can still be handled.
376 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture
), CCInputHandlerClient::ScrollStarted
);
379 TEST_F(CCLayerTreeHostImplTest
, shouldScrollOnMainThread
)
381 setupScrollAndContentsLayers(IntSize(100, 100));
382 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
383 initializeRendererAndDrawFrame();
384 CCLayerImpl
* root
= m_hostImpl
->rootLayer();
386 root
->setShouldScrollOnMainThread(true);
388 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollOnMainThread
);
389 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture
), CCInputHandlerClient::ScrollOnMainThread
);
392 TEST_F(CCLayerTreeHostImplTest
, nonFastScrollableRegionBasic
)
394 setupScrollAndContentsLayers(IntSize(200, 200));
395 m_hostImpl
->setViewportSize(IntSize(100, 100), IntSize(100, 100));
396 initializeRendererAndDrawFrame();
397 CCLayerImpl
* root
= m_hostImpl
->rootLayer();
399 root
->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
401 // All scroll types inside the non-fast scrollable region should fail.
402 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollOnMainThread
);
403 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Gesture
), CCInputHandlerClient::ScrollOnMainThread
);
405 // All scroll types outside this region should succeed.
406 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
407 m_hostImpl
->scrollBy(IntPoint(), IntSize(0, 10));
408 m_hostImpl
->scrollEnd();
409 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Gesture
), CCInputHandlerClient::ScrollStarted
);
410 m_hostImpl
->scrollBy(IntPoint(), IntSize(0, 10));
411 m_hostImpl
->scrollEnd();
414 TEST_F(CCLayerTreeHostImplTest
, nonFastScrollableRegionWithOffset
)
416 setupScrollAndContentsLayers(IntSize(200, 200));
417 m_hostImpl
->setViewportSize(IntSize(100, 100), IntSize(100, 100));
418 CCLayerImpl
* root
= m_hostImpl
->rootLayer();
420 root
->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
421 root
->setPosition(FloatPoint(-25, 0));
422 initializeRendererAndDrawFrame();
424 // This point would fall into the non-fast scrollable region except that we've moved the layer down by 25 pixels.
425 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(40, 10), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
426 m_hostImpl
->scrollBy(IntPoint(), IntSize(0, 1));
427 m_hostImpl
->scrollEnd();
429 // This point is still inside the non-fast region.
430 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(10, 10), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollOnMainThread
);
433 TEST_F(CCLayerTreeHostImplTest
, maxScrollPositionChangedByDeviceScaleFactor
)
435 setupScrollAndContentsLayers(IntSize(100, 100));
437 float deviceScaleFactor
= 2;
438 IntSize
layoutViewport(25, 25);
439 IntSize
deviceViewport(layoutViewport
);
440 deviceViewport
.scale(deviceScaleFactor
);
441 m_hostImpl
->setViewportSize(layoutViewport
, deviceViewport
);
442 m_hostImpl
->setDeviceScaleFactor(deviceScaleFactor
);
443 EXPECT_EQ(m_hostImpl
->rootLayer()->maxScrollPosition(), IntSize(25, 25));
445 deviceScaleFactor
= 1;
446 m_hostImpl
->setViewportSize(layoutViewport
, layoutViewport
);
447 m_hostImpl
->setDeviceScaleFactor(deviceScaleFactor
);
448 EXPECT_EQ(m_hostImpl
->rootLayer()->maxScrollPosition(), IntSize(75, 75));
451 TEST_F(CCLayerTreeHostImplTest
, pinchGesture
)
453 setupScrollAndContentsLayers(IntSize(100, 100));
454 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
455 initializeRendererAndDrawFrame();
457 CCLayerImpl
* scrollLayer
= m_hostImpl
->rootScrollLayer();
460 const float minPageScale
= 0.5, maxPageScale
= 4;
462 // Basic pinch zoom in gesture
464 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
465 scrollLayer
->setPageScaleDelta(1);
466 scrollLayer
->setScrollDelta(IntSize());
468 float pageScaleDelta
= 2;
469 m_hostImpl
->pinchGestureBegin();
470 m_hostImpl
->pinchGestureUpdate(pageScaleDelta
, IntPoint(50, 50));
471 m_hostImpl
->pinchGestureEnd();
472 EXPECT_TRUE(m_didRequestRedraw
);
473 EXPECT_TRUE(m_didRequestCommit
);
475 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
476 EXPECT_EQ(scrollInfo
->pageScaleDelta
, pageScaleDelta
);
481 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
482 scrollLayer
->setPageScaleDelta(1);
483 scrollLayer
->setScrollDelta(IntSize());
484 float pageScaleDelta
= 10;
486 m_hostImpl
->pinchGestureBegin();
487 m_hostImpl
->pinchGestureUpdate(pageScaleDelta
, IntPoint(50, 50));
488 m_hostImpl
->pinchGestureEnd();
490 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
491 EXPECT_EQ(scrollInfo
->pageScaleDelta
, maxPageScale
);
496 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
497 scrollLayer
->setPageScaleDelta(1);
498 scrollLayer
->setScrollDelta(IntSize());
499 scrollLayer
->setScrollPosition(IntPoint(50, 50));
501 float pageScaleDelta
= 0.1f
;
502 m_hostImpl
->pinchGestureBegin();
503 m_hostImpl
->pinchGestureUpdate(pageScaleDelta
, IntPoint(0, 0));
504 m_hostImpl
->pinchGestureEnd();
506 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
507 EXPECT_EQ(scrollInfo
->pageScaleDelta
, minPageScale
);
509 // Pushed to (0,0) via clamping against contents layer size.
510 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(-50, -50));
513 // Two-finger panning
515 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
516 scrollLayer
->setPageScaleDelta(1);
517 scrollLayer
->setScrollDelta(IntSize());
518 scrollLayer
->setScrollPosition(IntPoint(20, 20));
520 float pageScaleDelta
= 1;
521 m_hostImpl
->pinchGestureBegin();
522 m_hostImpl
->pinchGestureUpdate(pageScaleDelta
, IntPoint(10, 10));
523 m_hostImpl
->pinchGestureUpdate(pageScaleDelta
, IntPoint(20, 20));
524 m_hostImpl
->pinchGestureEnd();
526 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
527 EXPECT_EQ(scrollInfo
->pageScaleDelta
, pageScaleDelta
);
528 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(-10, -10));
532 TEST_F(CCLayerTreeHostImplTest
, pageScaleAnimation
)
534 setupScrollAndContentsLayers(IntSize(100, 100));
535 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
536 initializeRendererAndDrawFrame();
538 CCLayerImpl
* scrollLayer
= m_hostImpl
->rootScrollLayer();
541 const float minPageScale
= 0.5, maxPageScale
= 4;
542 const double startTime
= 1;
543 const double duration
= 0.1;
544 const double halfwayThroughAnimation
= startTime
+ duration
/ 2;
545 const double endTime
= startTime
+ duration
;
547 // Non-anchor zoom-in
549 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
550 scrollLayer
->setPageScaleDelta(1);
551 scrollLayer
->setScrollPosition(IntPoint(50, 50));
553 m_hostImpl
->startPageScaleAnimation(IntSize(0, 0), false, 2, startTime
, duration
);
554 m_hostImpl
->animate(halfwayThroughAnimation
, halfwayThroughAnimation
);
555 EXPECT_TRUE(m_didRequestRedraw
);
556 m_hostImpl
->animate(endTime
, endTime
);
557 EXPECT_TRUE(m_didRequestCommit
);
559 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
560 EXPECT_EQ(scrollInfo
->pageScaleDelta
, 2);
561 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(-50, -50));
566 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
567 scrollLayer
->setPageScaleDelta(1);
568 scrollLayer
->setScrollPosition(IntPoint(50, 50));
570 m_hostImpl
->startPageScaleAnimation(IntSize(25, 25), true, minPageScale
, startTime
, duration
);
571 m_hostImpl
->animate(endTime
, endTime
);
572 EXPECT_TRUE(m_didRequestRedraw
);
573 EXPECT_TRUE(m_didRequestCommit
);
575 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
576 EXPECT_EQ(scrollInfo
->pageScaleDelta
, minPageScale
);
577 // Pushed to (0,0) via clamping against contents layer size.
578 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(-50, -50));
582 TEST_F(CCLayerTreeHostImplTest
, inhibitScrollAndPageScaleUpdatesWhilePinchZooming
)
584 setupScrollAndContentsLayers(IntSize(100, 100));
585 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
586 initializeRendererAndDrawFrame();
588 CCLayerImpl
* scrollLayer
= m_hostImpl
->rootScrollLayer();
591 const float minPageScale
= 0.5, maxPageScale
= 4;
595 // Start a pinch in gesture at the bottom right corner of the viewport.
596 const float zoomInDelta
= 2;
597 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
598 m_hostImpl
->pinchGestureBegin();
599 m_hostImpl
->pinchGestureUpdate(zoomInDelta
, IntPoint(50, 50));
601 // Because we are pinch zooming in, we shouldn't get any scroll or page
603 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
604 EXPECT_EQ(scrollInfo
->pageScaleDelta
, 1);
605 EXPECT_EQ(scrollInfo
->scrolls
.size(), 0u);
607 // Once the gesture ends, we get the final scroll and page scale values.
608 m_hostImpl
->pinchGestureEnd();
609 scrollInfo
= m_hostImpl
->processScrollDeltas();
610 EXPECT_EQ(scrollInfo
->pageScaleDelta
, zoomInDelta
);
611 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(25, 25));
616 // Start a pinch out gesture at the bottom right corner of the viewport.
617 const float zoomOutDelta
= 0.75;
618 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
619 m_hostImpl
->pinchGestureBegin();
620 m_hostImpl
->pinchGestureUpdate(zoomOutDelta
, IntPoint(50, 50));
622 // Since we are pinch zooming out, we should get an update to zoom all
623 // the way out to the minimum page scale.
624 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
625 EXPECT_EQ(scrollInfo
->pageScaleDelta
, minPageScale
);
626 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(0, 0));
628 // Once the gesture ends, we get the final scroll and page scale values.
629 m_hostImpl
->pinchGestureEnd();
630 scrollInfo
= m_hostImpl
->processScrollDeltas();
631 EXPECT_EQ(scrollInfo
->pageScaleDelta
, zoomOutDelta
);
632 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(8, 8));
636 TEST_F(CCLayerTreeHostImplTest
, inhibitScrollAndPageScaleUpdatesWhileAnimatingPageScale
)
638 setupScrollAndContentsLayers(IntSize(100, 100));
639 m_hostImpl
->setViewportSize(IntSize(50, 50), IntSize(50, 50));
640 initializeRendererAndDrawFrame();
642 CCLayerImpl
* scrollLayer
= m_hostImpl
->rootScrollLayer();
645 const float minPageScale
= 0.5, maxPageScale
= 4;
646 const double startTime
= 1;
647 const double duration
= 0.1;
648 const double halfwayThroughAnimation
= startTime
+ duration
/ 2;
649 const double endTime
= startTime
+ duration
;
651 // Start a page scale animation.
652 const float pageScaleDelta
= 2;
653 m_hostImpl
->setPageScaleFactorAndLimits(1, minPageScale
, maxPageScale
);
654 m_hostImpl
->startPageScaleAnimation(IntSize(50, 50), false, pageScaleDelta
, startTime
, duration
);
656 // We should immediately get the final zoom and scroll values for the
658 m_hostImpl
->animate(halfwayThroughAnimation
, halfwayThroughAnimation
);
659 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
660 EXPECT_EQ(scrollInfo
->pageScaleDelta
, pageScaleDelta
);
661 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(25, 25));
663 // Scrolling during the animation is ignored.
664 const IntSize
scrollDelta(0, 10);
665 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
666 m_hostImpl
->scrollBy(IntPoint(), scrollDelta
);
667 m_hostImpl
->scrollEnd();
669 // The final page scale and scroll deltas should match what we got
671 m_hostImpl
->animate(endTime
, endTime
);
672 scrollInfo
= m_hostImpl
->processScrollDeltas();
673 EXPECT_EQ(scrollInfo
->pageScaleDelta
, pageScaleDelta
);
674 expectContains(*scrollInfo
, scrollLayer
->id(), IntSize(25, 25));
677 class DidDrawCheckLayer
: public CCTiledLayerImpl
{
679 static PassOwnPtr
<DidDrawCheckLayer
> create(int id
) { return adoptPtr(new DidDrawCheckLayer(id
)); }
681 virtual void didDraw(CCResourceProvider
*) OVERRIDE
683 m_didDrawCalled
= true;
686 virtual void willDraw(CCResourceProvider
*) OVERRIDE
688 m_willDrawCalled
= true;
691 bool didDrawCalled() const { return m_didDrawCalled
; }
692 bool willDrawCalled() const { return m_willDrawCalled
; }
694 void clearDidDrawCheck()
696 m_didDrawCalled
= false;
697 m_willDrawCalled
= false;
701 explicit DidDrawCheckLayer(int id
)
702 : CCTiledLayerImpl(id
)
703 , m_didDrawCalled(false)
704 , m_willDrawCalled(false)
706 setAnchorPoint(FloatPoint(0, 0));
707 setBounds(IntSize(10, 10));
708 setContentBounds(IntSize(10, 10));
709 setDrawsContent(true);
711 setVisibleContentRect(IntRect(0, 0, 10, 10));
713 OwnPtr
<CCLayerTilingData
> tiler
= CCLayerTilingData::create(IntSize(100, 100), CCLayerTilingData::HasBorderTexels
);
714 tiler
->setBounds(contentBounds());
715 setTilingData(*tiler
.get());
719 bool m_didDrawCalled
;
720 bool m_willDrawCalled
;
723 TEST_F(CCLayerTreeHostImplTest
, didDrawNotCalledOnHiddenLayer
)
725 // The root layer is always drawn, so run this test on a child layer that
726 // will be masked out by the root layer's bounds.
727 m_hostImpl
->setRootLayer(DidDrawCheckLayer::create(1));
728 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(m_hostImpl
->rootLayer());
729 root
->setMasksToBounds(true);
731 root
->addChild(DidDrawCheckLayer::create(2));
732 DidDrawCheckLayer
* layer
= static_cast<DidDrawCheckLayer
*>(root
->children()[0].get());
733 // Ensure visibleContentRect for layer is empty
734 layer
->setPosition(FloatPoint(100, 100));
735 layer
->setBounds(IntSize(10, 10));
736 layer
->setContentBounds(IntSize(10, 10));
738 CCLayerTreeHostImpl::FrameData frame
;
740 EXPECT_FALSE(layer
->willDrawCalled());
741 EXPECT_FALSE(layer
->didDrawCalled());
743 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
744 m_hostImpl
->drawLayers(frame
);
745 m_hostImpl
->didDrawAllLayers(frame
);
747 EXPECT_FALSE(layer
->willDrawCalled());
748 EXPECT_FALSE(layer
->didDrawCalled());
750 EXPECT_TRUE(layer
->visibleContentRect().isEmpty());
752 // Ensure visibleContentRect for layer layer is not empty
753 layer
->setPosition(FloatPoint(0, 0));
755 EXPECT_FALSE(layer
->willDrawCalled());
756 EXPECT_FALSE(layer
->didDrawCalled());
758 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
759 m_hostImpl
->drawLayers(frame
);
760 m_hostImpl
->didDrawAllLayers(frame
);
762 EXPECT_TRUE(layer
->willDrawCalled());
763 EXPECT_TRUE(layer
->didDrawCalled());
765 EXPECT_FALSE(layer
->visibleContentRect().isEmpty());
768 TEST_F(CCLayerTreeHostImplTest
, willDrawNotCalledOnOccludedLayer
)
770 IntSize
bigSize(1000, 1000);
771 m_hostImpl
->setViewportSize(bigSize
, bigSize
);
773 m_hostImpl
->setRootLayer(DidDrawCheckLayer::create(1));
774 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(m_hostImpl
->rootLayer());
776 root
->addChild(DidDrawCheckLayer::create(2));
777 DidDrawCheckLayer
* occludedLayer
= static_cast<DidDrawCheckLayer
*>(root
->children()[0].get());
779 root
->addChild(DidDrawCheckLayer::create(3));
780 DidDrawCheckLayer
* topLayer
= static_cast<DidDrawCheckLayer
*>(root
->children()[1].get());
781 // This layer covers the occludedLayer above. Make this layer large so it can occlude.
782 topLayer
->setBounds(bigSize
);
783 topLayer
->setContentBounds(bigSize
);
784 topLayer
->setOpaque(true);
786 CCLayerTreeHostImpl::FrameData frame
;
788 EXPECT_FALSE(occludedLayer
->willDrawCalled());
789 EXPECT_FALSE(occludedLayer
->didDrawCalled());
790 EXPECT_FALSE(topLayer
->willDrawCalled());
791 EXPECT_FALSE(topLayer
->didDrawCalled());
793 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
794 m_hostImpl
->drawLayers(frame
);
795 m_hostImpl
->didDrawAllLayers(frame
);
797 EXPECT_FALSE(occludedLayer
->willDrawCalled());
798 EXPECT_FALSE(occludedLayer
->didDrawCalled());
799 EXPECT_TRUE(topLayer
->willDrawCalled());
800 EXPECT_TRUE(topLayer
->didDrawCalled());
803 TEST_F(CCLayerTreeHostImplTest
, didDrawCalledOnAllLayers
)
805 m_hostImpl
->setRootLayer(DidDrawCheckLayer::create(1));
806 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(m_hostImpl
->rootLayer());
808 root
->addChild(DidDrawCheckLayer::create(2));
809 DidDrawCheckLayer
* layer1
= static_cast<DidDrawCheckLayer
*>(root
->children()[0].get());
811 layer1
->addChild(DidDrawCheckLayer::create(3));
812 DidDrawCheckLayer
* layer2
= static_cast<DidDrawCheckLayer
*>(layer1
->children()[0].get());
814 layer1
->setOpacity(0.3f
);
815 layer1
->setPreserves3D(false);
817 EXPECT_FALSE(root
->didDrawCalled());
818 EXPECT_FALSE(layer1
->didDrawCalled());
819 EXPECT_FALSE(layer2
->didDrawCalled());
821 CCLayerTreeHostImpl::FrameData frame
;
822 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
823 m_hostImpl
->drawLayers(frame
);
824 m_hostImpl
->didDrawAllLayers(frame
);
826 EXPECT_TRUE(root
->didDrawCalled());
827 EXPECT_TRUE(layer1
->didDrawCalled());
828 EXPECT_TRUE(layer2
->didDrawCalled());
830 EXPECT_NE(root
->renderSurface(), layer1
->renderSurface());
831 EXPECT_TRUE(!!layer1
->renderSurface());
834 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
836 static PassOwnPtr
<MissingTextureAnimatingLayer
> create(int id
, bool tileMissing
, bool skipsDraw
, bool animating
, CCResourceProvider
* resourceProvider
) { return adoptPtr(new MissingTextureAnimatingLayer(id
, tileMissing
, skipsDraw
, animating
, resourceProvider
)); }
839 explicit MissingTextureAnimatingLayer(int id
, bool tileMissing
, bool skipsDraw
, bool animating
, CCResourceProvider
* resourceProvider
)
840 : DidDrawCheckLayer(id
)
842 OwnPtr
<CCLayerTilingData
> tilingData
= CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels
);
843 tilingData
->setBounds(bounds());
844 setTilingData(*tilingData
.get());
845 setSkipsDraw(skipsDraw
);
847 CCResourceProvider::ResourceId resource
= resourceProvider
->createResource(CCRenderer::ContentPool
, IntSize(), GraphicsContext3D::RGBA
, CCResourceProvider::TextureUsageAny
);
848 pushTileProperties(0, 0, resource
, IntRect());
851 addAnimatedTransformToLayer(*this, 10, 3, 0);
855 TEST_F(CCLayerTreeHostImplTest
, prepareToDrawFailsWhenAnimationUsesCheckerboard
)
857 // When the texture is not missing, we draw as usual.
858 m_hostImpl
->setRootLayer(DidDrawCheckLayer::create(1));
859 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(m_hostImpl
->rootLayer());
860 root
->addChild(MissingTextureAnimatingLayer::create(2, false, false, true, m_hostImpl
->resourceProvider()));
862 CCLayerTreeHostImpl::FrameData frame
;
864 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
865 m_hostImpl
->drawLayers(frame
);
866 m_hostImpl
->didDrawAllLayers(frame
);
868 // When a texture is missing and we're not animating, we draw as usual with checkerboarding.
869 m_hostImpl
->setRootLayer(DidDrawCheckLayer::create(1));
870 root
= static_cast<DidDrawCheckLayer
*>(m_hostImpl
->rootLayer());
871 root
->addChild(MissingTextureAnimatingLayer::create(2, true, false, false, m_hostImpl
->resourceProvider()));
873 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
874 m_hostImpl
->drawLayers(frame
);
875 m_hostImpl
->didDrawAllLayers(frame
);
877 // When a texture is missing and we're animating, we don't want to draw anything.
878 m_hostImpl
->setRootLayer(DidDrawCheckLayer::create(1));
879 root
= static_cast<DidDrawCheckLayer
*>(m_hostImpl
->rootLayer());
880 root
->addChild(MissingTextureAnimatingLayer::create(2, true, false, true, m_hostImpl
->resourceProvider()));
882 EXPECT_FALSE(m_hostImpl
->prepareToDraw(frame
));
883 m_hostImpl
->drawLayers(frame
);
884 m_hostImpl
->didDrawAllLayers(frame
);
886 // When the layer skips draw and we're animating, we still draw the frame.
887 m_hostImpl
->setRootLayer(DidDrawCheckLayer::create(1));
888 root
= static_cast<DidDrawCheckLayer
*>(m_hostImpl
->rootLayer());
889 root
->addChild(MissingTextureAnimatingLayer::create(2, false, true, true, m_hostImpl
->resourceProvider()));
891 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
892 m_hostImpl
->drawLayers(frame
);
893 m_hostImpl
->didDrawAllLayers(frame
);
896 TEST_F(CCLayerTreeHostImplTest
, scrollRootIgnored
)
898 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
899 root
->setScrollable(false);
900 m_hostImpl
->setRootLayer(root
.release());
901 initializeRendererAndDrawFrame();
903 // Scroll event is ignored because layer is not scrollable.
904 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollIgnored
);
905 EXPECT_FALSE(m_didRequestRedraw
);
906 EXPECT_FALSE(m_didRequestCommit
);
909 TEST_F(CCLayerTreeHostImplTest
, scrollNonCompositedRoot
)
911 // Test the configuration where a non-composited root layer is embedded in a
912 // scrollable outer layer.
913 IntSize
surfaceSize(10, 10);
915 OwnPtr
<CCLayerImpl
> contentLayer
= CCLayerImpl::create(1);
916 contentLayer
->setUseLCDText(true);
917 contentLayer
->setDrawsContent(true);
918 contentLayer
->setPosition(FloatPoint(0, 0));
919 contentLayer
->setAnchorPoint(FloatPoint(0, 0));
920 contentLayer
->setBounds(surfaceSize
);
921 contentLayer
->setContentBounds(IntSize(surfaceSize
.width() * 2, surfaceSize
.height() * 2));
923 OwnPtr
<CCLayerImpl
> scrollLayer
= CCLayerImpl::create(2);
924 scrollLayer
->setScrollable(true);
925 scrollLayer
->setMaxScrollPosition(surfaceSize
);
926 scrollLayer
->setBounds(surfaceSize
);
927 scrollLayer
->setContentBounds(surfaceSize
);
928 scrollLayer
->setPosition(FloatPoint(0, 0));
929 scrollLayer
->setAnchorPoint(FloatPoint(0, 0));
930 scrollLayer
->addChild(contentLayer
.release());
932 m_hostImpl
->setRootLayer(scrollLayer
.release());
933 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
934 initializeRendererAndDrawFrame();
936 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
937 m_hostImpl
->scrollBy(IntPoint(), IntSize(0, 10));
938 m_hostImpl
->scrollEnd();
939 EXPECT_TRUE(m_didRequestRedraw
);
940 EXPECT_TRUE(m_didRequestCommit
);
943 TEST_F(CCLayerTreeHostImplTest
, scrollChildCallsCommitAndRedraw
)
945 IntSize
surfaceSize(10, 10);
946 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
947 root
->setBounds(surfaceSize
);
948 root
->setContentBounds(surfaceSize
);
949 root
->addChild(createScrollableLayer(2, surfaceSize
));
950 m_hostImpl
->setRootLayer(root
.release());
951 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
952 initializeRendererAndDrawFrame();
954 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
955 m_hostImpl
->scrollBy(IntPoint(), IntSize(0, 10));
956 m_hostImpl
->scrollEnd();
957 EXPECT_TRUE(m_didRequestRedraw
);
958 EXPECT_TRUE(m_didRequestCommit
);
961 TEST_F(CCLayerTreeHostImplTest
, scrollMissesChild
)
963 IntSize
surfaceSize(10, 10);
964 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
965 root
->addChild(createScrollableLayer(2, surfaceSize
));
966 m_hostImpl
->setRootLayer(root
.release());
967 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
968 initializeRendererAndDrawFrame();
970 // Scroll event is ignored because the input coordinate is outside the layer boundaries.
971 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(15, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollIgnored
);
972 EXPECT_FALSE(m_didRequestRedraw
);
973 EXPECT_FALSE(m_didRequestCommit
);
976 TEST_F(CCLayerTreeHostImplTest
, scrollMissesBackfacingChild
)
978 IntSize
surfaceSize(10, 10);
979 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
980 OwnPtr
<CCLayerImpl
> child
= createScrollableLayer(2, surfaceSize
);
981 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
983 WebTransformationMatrix matrix
;
984 matrix
.rotate3d(180, 0, 0);
985 child
->setTransform(matrix
);
986 child
->setDoubleSided(false);
988 root
->addChild(child
.release());
989 m_hostImpl
->setRootLayer(root
.release());
990 initializeRendererAndDrawFrame();
992 // Scroll event is ignored because the scrollable layer is not facing the viewer and there is
993 // nothing scrollable behind it.
994 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollIgnored
);
995 EXPECT_FALSE(m_didRequestRedraw
);
996 EXPECT_FALSE(m_didRequestCommit
);
999 TEST_F(CCLayerTreeHostImplTest
, scrollBlockedByContentLayer
)
1001 IntSize
surfaceSize(10, 10);
1002 OwnPtr
<CCLayerImpl
> contentLayer
= createScrollableLayer(1, surfaceSize
);
1003 contentLayer
->setShouldScrollOnMainThread(true);
1004 contentLayer
->setScrollable(false);
1006 OwnPtr
<CCLayerImpl
> scrollLayer
= createScrollableLayer(2, surfaceSize
);
1007 scrollLayer
->addChild(contentLayer
.release());
1009 m_hostImpl
->setRootLayer(scrollLayer
.release());
1010 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1011 initializeRendererAndDrawFrame();
1013 // Scrolling fails because the content layer is asking to be scrolled on the main thread.
1014 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollOnMainThread
);
1017 TEST_F(CCLayerTreeHostImplTest
, scrollRootAndChangePageScaleOnMainThread
)
1019 IntSize
surfaceSize(10, 10);
1020 float pageScale
= 2;
1021 OwnPtr
<CCLayerImpl
> root
= createScrollableLayer(1, surfaceSize
);
1022 m_hostImpl
->setRootLayer(root
.release());
1023 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1024 initializeRendererAndDrawFrame();
1026 IntSize
scrollDelta(0, 10);
1027 IntSize
expectedScrollDelta(scrollDelta
);
1028 IntSize
expectedMaxScroll(m_hostImpl
->rootLayer()->maxScrollPosition());
1029 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
1030 m_hostImpl
->scrollBy(IntPoint(), scrollDelta
);
1031 m_hostImpl
->scrollEnd();
1033 // Set new page scale from main thread.
1034 m_hostImpl
->setPageScaleFactorAndLimits(pageScale
, pageScale
, pageScale
);
1036 // The scale should apply to the scroll delta.
1037 expectedScrollDelta
.scale(pageScale
);
1038 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1039 expectContains(*scrollInfo
.get(), m_hostImpl
->rootLayer()->id(), expectedScrollDelta
);
1041 // The scroll range should also have been updated.
1042 EXPECT_EQ(m_hostImpl
->rootLayer()->maxScrollPosition(), expectedMaxScroll
);
1044 // The page scale delta remains constant because the impl thread did not scale.
1045 EXPECT_EQ(m_hostImpl
->rootLayer()->pageScaleDelta(), 1);
1048 TEST_F(CCLayerTreeHostImplTest
, scrollRootAndChangePageScaleOnImplThread
)
1050 IntSize
surfaceSize(10, 10);
1051 float pageScale
= 2;
1052 OwnPtr
<CCLayerImpl
> root
= createScrollableLayer(1, surfaceSize
);
1053 m_hostImpl
->setRootLayer(root
.release());
1054 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1055 m_hostImpl
->setPageScaleFactorAndLimits(1, 1, pageScale
);
1056 initializeRendererAndDrawFrame();
1058 IntSize
scrollDelta(0, 10);
1059 IntSize
expectedScrollDelta(scrollDelta
);
1060 IntSize
expectedMaxScroll(m_hostImpl
->rootLayer()->maxScrollPosition());
1061 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
1062 m_hostImpl
->scrollBy(IntPoint(), scrollDelta
);
1063 m_hostImpl
->scrollEnd();
1065 // Set new page scale on impl thread by pinching.
1066 m_hostImpl
->pinchGestureBegin();
1067 m_hostImpl
->pinchGestureUpdate(pageScale
, IntPoint());
1068 m_hostImpl
->pinchGestureEnd();
1070 // The scroll delta is not scaled because the main thread did not scale.
1071 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1072 expectContains(*scrollInfo
.get(), m_hostImpl
->rootLayer()->id(), expectedScrollDelta
);
1074 // The scroll range should also have been updated.
1075 EXPECT_EQ(m_hostImpl
->rootLayer()->maxScrollPosition(), expectedMaxScroll
);
1077 // The page scale delta should match the new scale on the impl side.
1078 EXPECT_EQ(m_hostImpl
->rootLayer()->pageScaleDelta(), pageScale
);
1081 TEST_F(CCLayerTreeHostImplTest
, pageScaleDeltaAppliedToRootScrollLayerOnly
)
1083 IntSize
surfaceSize(10, 10);
1084 float defaultPageScale
= 1;
1085 float newPageScale
= 2;
1087 // Create a normal scrollable root layer and another scrollable child layer.
1088 setupScrollAndContentsLayers(surfaceSize
);
1089 CCLayerImpl
* root
= m_hostImpl
->rootLayer();
1090 CCLayerImpl
* child
= root
->children()[0].get();
1092 OwnPtr
<CCLayerImpl
> scrollableChild
= createScrollableLayer(3, surfaceSize
);
1093 child
->addChild(scrollableChild
.release());
1094 CCLayerImpl
* grandChild
= child
->children()[0].get();
1096 // Set new page scale on impl thread by pinching.
1097 m_hostImpl
->pinchGestureBegin();
1098 m_hostImpl
->pinchGestureUpdate(newPageScale
, IntPoint());
1099 m_hostImpl
->pinchGestureEnd();
1101 // The page scale delta should only be applied to the scrollable root layer.
1102 EXPECT_EQ(root
->pageScaleDelta(), newPageScale
);
1103 EXPECT_EQ(child
->pageScaleDelta(), defaultPageScale
);
1104 EXPECT_EQ(grandChild
->pageScaleDelta(), defaultPageScale
);
1106 // Make sure all the layers are drawn with the page scale delta applied, i.e., the page scale
1107 // delta on the root layer is applied hierarchically.
1108 CCLayerTreeHostImpl::FrameData frame
;
1109 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1110 m_hostImpl
->drawLayers(frame
);
1111 m_hostImpl
->didDrawAllLayers(frame
);
1113 EXPECT_EQ(root
->drawTransform().m11(), newPageScale
);
1114 EXPECT_EQ(root
->drawTransform().m22(), newPageScale
);
1115 EXPECT_EQ(child
->drawTransform().m11(), newPageScale
);
1116 EXPECT_EQ(child
->drawTransform().m22(), newPageScale
);
1117 EXPECT_EQ(grandChild
->drawTransform().m11(), newPageScale
);
1118 EXPECT_EQ(grandChild
->drawTransform().m22(), newPageScale
);
1121 TEST_F(CCLayerTreeHostImplTest
, scrollChildAndChangePageScaleOnMainThread
)
1123 IntSize
surfaceSize(10, 10);
1124 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
1125 root
->setBounds(surfaceSize
);
1126 root
->setContentBounds(surfaceSize
);
1127 // Also mark the root scrollable so it becomes the root scroll layer.
1128 root
->setScrollable(true);
1129 int scrollLayerId
= 2;
1130 root
->addChild(createScrollableLayer(scrollLayerId
, surfaceSize
));
1131 m_hostImpl
->setRootLayer(root
.release());
1132 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1133 initializeRendererAndDrawFrame();
1135 CCLayerImpl
* child
= m_hostImpl
->rootLayer()->children()[0].get();
1137 IntSize
scrollDelta(0, 10);
1138 IntSize
expectedScrollDelta(scrollDelta
);
1139 IntSize
expectedMaxScroll(child
->maxScrollPosition());
1140 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
1141 m_hostImpl
->scrollBy(IntPoint(), scrollDelta
);
1142 m_hostImpl
->scrollEnd();
1144 float pageScale
= 2;
1145 m_hostImpl
->setPageScaleFactorAndLimits(pageScale
, 1, pageScale
);
1147 // The scale should apply to the scroll delta.
1148 expectedScrollDelta
.scale(pageScale
);
1149 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1150 expectContains(*scrollInfo
.get(), scrollLayerId
, expectedScrollDelta
);
1152 // The scroll range should not have changed.
1153 EXPECT_EQ(child
->maxScrollPosition(), expectedMaxScroll
);
1155 // The page scale delta remains constant because the impl thread did not scale.
1156 EXPECT_EQ(child
->pageScaleDelta(), 1);
1159 TEST_F(CCLayerTreeHostImplTest
, scrollChildBeyondLimit
)
1161 // Scroll a child layer beyond its maximum scroll range and make sure the
1162 // parent layer is scrolled on the axis on which the child was unable to
1164 IntSize
surfaceSize(10, 10);
1165 OwnPtr
<CCLayerImpl
> root
= createScrollableLayer(1, surfaceSize
);
1167 OwnPtr
<CCLayerImpl
> grandChild
= createScrollableLayer(3, surfaceSize
);
1168 grandChild
->setScrollPosition(IntPoint(0, 5));
1170 OwnPtr
<CCLayerImpl
> child
= createScrollableLayer(2, surfaceSize
);
1171 child
->setScrollPosition(IntPoint(3, 0));
1172 child
->addChild(grandChild
.release());
1174 root
->addChild(child
.release());
1175 m_hostImpl
->setRootLayer(root
.release());
1176 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1177 initializeRendererAndDrawFrame();
1179 IntSize
scrollDelta(-8, -7);
1180 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
1181 m_hostImpl
->scrollBy(IntPoint(), scrollDelta
);
1182 m_hostImpl
->scrollEnd();
1184 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1186 // The grand child should have scrolled up to its limit.
1187 CCLayerImpl
* child
= m_hostImpl
->rootLayer()->children()[0].get();
1188 CCLayerImpl
* grandChild
= child
->children()[0].get();
1189 expectContains(*scrollInfo
.get(), grandChild
->id(), IntSize(0, -5));
1191 // The child should have only scrolled on the other axis.
1192 expectContains(*scrollInfo
.get(), child
->id(), IntSize(-3, 0));
1196 TEST_F(CCLayerTreeHostImplTest
, scrollEventBubbling
)
1198 // When we try to scroll a non-scrollable child layer, the scroll delta
1199 // should be applied to one of its ancestors if possible.
1200 IntSize
surfaceSize(10, 10);
1201 OwnPtr
<CCLayerImpl
> root
= createScrollableLayer(1, surfaceSize
);
1202 OwnPtr
<CCLayerImpl
> child
= createScrollableLayer(2, surfaceSize
);
1204 child
->setScrollable(false);
1205 root
->addChild(child
.release());
1207 m_hostImpl
->setRootLayer(root
.release());
1208 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1209 initializeRendererAndDrawFrame();
1211 IntSize
scrollDelta(0, 4);
1212 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
1213 m_hostImpl
->scrollBy(IntPoint(), scrollDelta
);
1214 m_hostImpl
->scrollEnd();
1216 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1218 // Only the root should have scrolled.
1219 ASSERT_EQ(scrollInfo
->scrolls
.size(), 1u);
1220 expectContains(*scrollInfo
.get(), m_hostImpl
->rootLayer()->id(), scrollDelta
);
1224 TEST_F(CCLayerTreeHostImplTest
, scrollBeforeRedraw
)
1226 IntSize
surfaceSize(10, 10);
1227 m_hostImpl
->setRootLayer(createScrollableLayer(1, surfaceSize
));
1228 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1230 // Draw one frame and then immediately rebuild the layer tree to mimic a tree synchronization.
1231 initializeRendererAndDrawFrame();
1232 m_hostImpl
->detachLayerTree();
1233 m_hostImpl
->setRootLayer(createScrollableLayer(2, surfaceSize
));
1235 // Scrolling should still work even though we did not draw yet.
1236 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
1239 TEST_F(CCLayerTreeHostImplTest
, scrollAxisAlignedRotatedLayer
)
1241 setupScrollAndContentsLayers(IntSize(100, 100));
1243 // Rotate the root layer 90 degrees counter-clockwise about its center.
1244 WebTransformationMatrix rotateTransform
;
1245 rotateTransform
.rotate(-90);
1246 m_hostImpl
->rootLayer()->setTransform(rotateTransform
);
1248 IntSize
surfaceSize(50, 50);
1249 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1250 initializeRendererAndDrawFrame();
1252 // Scroll to the right in screen coordinates with a gesture.
1253 IntSize
gestureScrollDelta(10, 0);
1254 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture
), CCInputHandlerClient::ScrollStarted
);
1255 m_hostImpl
->scrollBy(IntPoint(), gestureScrollDelta
);
1256 m_hostImpl
->scrollEnd();
1258 // The layer should have scrolled down in its local coordinates.
1259 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1260 expectContains(*scrollInfo
.get(), m_hostImpl
->rootLayer()->id(), IntSize(0, gestureScrollDelta
.width()));
1262 // Reset and scroll down with the wheel.
1263 m_hostImpl
->rootLayer()->setScrollDelta(FloatSize());
1264 IntSize
wheelScrollDelta(0, 10);
1265 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
1266 m_hostImpl
->scrollBy(IntPoint(), wheelScrollDelta
);
1267 m_hostImpl
->scrollEnd();
1269 // The layer should have scrolled down in its local coordinates.
1270 scrollInfo
= m_hostImpl
->processScrollDeltas();
1271 expectContains(*scrollInfo
.get(), m_hostImpl
->rootLayer()->id(), wheelScrollDelta
);
1274 TEST_F(CCLayerTreeHostImplTest
, scrollNonAxisAlignedRotatedLayer
)
1276 setupScrollAndContentsLayers(IntSize(100, 100));
1277 int childLayerId
= 3;
1278 float childLayerAngle
= -20;
1280 // Create a child layer that is rotated to a non-axis-aligned angle.
1281 OwnPtr
<CCLayerImpl
> child
= createScrollableLayer(childLayerId
, m_hostImpl
->rootLayer()->contentBounds());
1282 WebTransformationMatrix rotateTransform
;
1283 rotateTransform
.translate(-50, -50);
1284 rotateTransform
.rotate(childLayerAngle
);
1285 rotateTransform
.translate(50, 50);
1286 child
->setTransform(rotateTransform
);
1288 // Only allow vertical scrolling.
1289 child
->setMaxScrollPosition(IntSize(0, child
->contentBounds().height()));
1290 m_hostImpl
->rootLayer()->addChild(child
.release());
1292 IntSize
surfaceSize(50, 50);
1293 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1294 initializeRendererAndDrawFrame();
1297 // Scroll down in screen coordinates with a gesture.
1298 IntSize
gestureScrollDelta(0, 10);
1299 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture
), CCInputHandlerClient::ScrollStarted
);
1300 m_hostImpl
->scrollBy(IntPoint(), gestureScrollDelta
);
1301 m_hostImpl
->scrollEnd();
1303 // The child layer should have scrolled down in its local coordinates an amount proportional to
1304 // the angle between it and the input scroll delta.
1305 IntSize
expectedScrollDelta(0, gestureScrollDelta
.height() * cosf(deg2rad(childLayerAngle
)));
1306 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1307 expectContains(*scrollInfo
.get(), childLayerId
, expectedScrollDelta
);
1309 // The root layer should not have scrolled, because the input delta was close to the layer's
1310 // axis of movement.
1311 EXPECT_EQ(scrollInfo
->scrolls
.size(), 1u);
1315 // Now reset and scroll the same amount horizontally.
1316 m_hostImpl
->rootLayer()->children()[1]->setScrollDelta(FloatSize());
1317 IntSize
gestureScrollDelta(10, 0);
1318 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture
), CCInputHandlerClient::ScrollStarted
);
1319 m_hostImpl
->scrollBy(IntPoint(), gestureScrollDelta
);
1320 m_hostImpl
->scrollEnd();
1322 // The child layer should have scrolled down in its local coordinates an amount proportional to
1323 // the angle between it and the input scroll delta.
1324 IntSize
expectedScrollDelta(0, -gestureScrollDelta
.width() * sinf(deg2rad(childLayerAngle
)));
1325 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1326 expectContains(*scrollInfo
.get(), childLayerId
, expectedScrollDelta
);
1328 // The root layer should have scrolled more, since the input scroll delta was mostly
1329 // orthogonal to the child layer's vertical scroll axis.
1330 IntSize
expectedRootScrollDelta(gestureScrollDelta
.width() * pow(cosf(deg2rad(childLayerAngle
)), 2), 0);
1331 expectContains(*scrollInfo
.get(), m_hostImpl
->rootLayer()->id(), expectedRootScrollDelta
);
1335 TEST_F(CCLayerTreeHostImplTest
, scrollScaledLayer
)
1337 setupScrollAndContentsLayers(IntSize(100, 100));
1339 // Scale the layer to twice its normal size.
1341 WebTransformationMatrix scaleTransform
;
1342 scaleTransform
.scale(scale
);
1343 m_hostImpl
->rootLayer()->setTransform(scaleTransform
);
1345 IntSize
surfaceSize(50, 50);
1346 m_hostImpl
->setViewportSize(surfaceSize
, surfaceSize
);
1347 initializeRendererAndDrawFrame();
1349 // Scroll down in screen coordinates with a gesture.
1350 IntSize
scrollDelta(0, 10);
1351 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture
), CCInputHandlerClient::ScrollStarted
);
1352 m_hostImpl
->scrollBy(IntPoint(), scrollDelta
);
1353 m_hostImpl
->scrollEnd();
1355 // The layer should have scrolled down in its local coordinates, but half he amount.
1356 OwnPtr
<CCScrollAndScaleSet
> scrollInfo
= m_hostImpl
->processScrollDeltas();
1357 expectContains(*scrollInfo
.get(), m_hostImpl
->rootLayer()->id(), IntSize(0, scrollDelta
.height() / scale
));
1359 // Reset and scroll down with the wheel.
1360 m_hostImpl
->rootLayer()->setScrollDelta(FloatSize());
1361 IntSize
wheelScrollDelta(0, 10);
1362 EXPECT_EQ(m_hostImpl
->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel
), CCInputHandlerClient::ScrollStarted
);
1363 m_hostImpl
->scrollBy(IntPoint(), wheelScrollDelta
);
1364 m_hostImpl
->scrollEnd();
1366 // The scale should not have been applied to the scroll delta.
1367 scrollInfo
= m_hostImpl
->processScrollDeltas();
1368 expectContains(*scrollInfo
.get(), m_hostImpl
->rootLayer()->id(), wheelScrollDelta
);
1371 class BlendStateTrackerContext
: public FakeWebGraphicsContext3D
{
1373 BlendStateTrackerContext() : m_blend(false) { }
1375 virtual void enable(WGC3Denum cap
)
1377 if (cap
== GraphicsContext3D::BLEND
)
1381 virtual void disable(WGC3Denum cap
)
1383 if (cap
== GraphicsContext3D::BLEND
)
1387 bool blend() const { return m_blend
; }
1393 class BlendStateCheckLayer
: public CCLayerImpl
{
1395 static PassOwnPtr
<BlendStateCheckLayer
> create(int id
, CCResourceProvider
* resourceProvider
) { return adoptPtr(new BlendStateCheckLayer(id
, resourceProvider
)); }
1397 virtual void appendQuads(CCQuadSink
& quadSink
, CCAppendQuadsData
& appendQuadsData
) OVERRIDE
1399 m_quadsAppended
= true;
1402 if (opaque() || m_opaqueContents
)
1403 opaqueRect
= m_quadRect
;
1405 opaqueRect
= m_opaqueContentRect
;
1407 CCSharedQuadState
* sharedQuadState
= quadSink
.useSharedQuadState(createSharedQuadState());
1408 OwnPtr
<CCDrawQuad
> testBlendingDrawQuad
= CCTileDrawQuad::create(sharedQuadState
, m_quadRect
, opaqueRect
, m_resourceId
, IntPoint(), IntSize(1, 1), 0, false, false, false, false, false);
1409 testBlendingDrawQuad
->setQuadVisibleRect(m_quadVisibleRect
);
1410 EXPECT_EQ(m_blend
, testBlendingDrawQuad
->needsBlending());
1411 EXPECT_EQ(m_hasRenderSurface
, !!renderSurface());
1412 quadSink
.append(testBlendingDrawQuad
.release(), appendQuadsData
);
1415 void setExpectation(bool blend
, bool hasRenderSurface
)
1418 m_hasRenderSurface
= hasRenderSurface
;
1419 m_quadsAppended
= false;
1422 bool quadsAppended() const { return m_quadsAppended
; }
1424 void setQuadRect(const IntRect
& rect
) { m_quadRect
= rect
; }
1425 void setQuadVisibleRect(const IntRect
& rect
) { m_quadVisibleRect
= rect
; }
1426 void setOpaqueContents(bool opaque
) { m_opaqueContents
= opaque
; }
1427 void setOpaqueContentRect(const IntRect
& rect
) { m_opaqueContentRect
= rect
; }
1430 explicit BlendStateCheckLayer(int id
, CCResourceProvider
* resourceProvider
)
1433 , m_hasRenderSurface(false)
1434 , m_quadsAppended(false)
1435 , m_opaqueContents(false)
1436 , m_quadRect(5, 5, 5, 5)
1437 , m_quadVisibleRect(5, 5, 5, 5)
1438 , m_resourceId(resourceProvider
->createResource(CCRenderer::ContentPool
, IntSize(1, 1), GraphicsContext3D::RGBA
, CCResourceProvider::TextureUsageAny
))
1440 setAnchorPoint(FloatPoint(0, 0));
1441 setBounds(IntSize(10, 10));
1442 setContentBounds(IntSize(10, 10));
1443 setDrawsContent(true);
1447 bool m_hasRenderSurface
;
1448 bool m_quadsAppended
;
1449 bool m_opaqueContents
;
1451 IntRect m_opaqueContentRect
;
1452 IntRect m_quadVisibleRect
;
1453 CCResourceProvider::ResourceId m_resourceId
;
1456 TEST_F(CCLayerTreeHostImplTest
, blendingOffWhenDrawingOpaqueLayers
)
1459 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
1460 root
->setAnchorPoint(FloatPoint(0, 0));
1461 root
->setBounds(IntSize(10, 10));
1462 root
->setContentBounds(root
->bounds());
1463 root
->setDrawsContent(false);
1464 m_hostImpl
->setRootLayer(root
.release());
1466 CCLayerImpl
* root
= m_hostImpl
->rootLayer();
1468 root
->addChild(BlendStateCheckLayer::create(2, m_hostImpl
->resourceProvider()));
1469 BlendStateCheckLayer
* layer1
= static_cast<BlendStateCheckLayer
*>(root
->children()[0].get());
1470 layer1
->setPosition(FloatPoint(2, 2));
1472 CCLayerTreeHostImpl::FrameData frame
;
1474 // Opaque layer, drawn without blending.
1475 layer1
->setOpaque(true);
1476 layer1
->setOpaqueContents(true);
1477 layer1
->setExpectation(false, false);
1478 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1479 m_hostImpl
->drawLayers(frame
);
1480 EXPECT_TRUE(layer1
->quadsAppended());
1481 m_hostImpl
->didDrawAllLayers(frame
);
1483 // Layer with translucent content, but opaque content, so drawn without blending.
1484 layer1
->setOpaque(false);
1485 layer1
->setOpaqueContents(true);
1486 layer1
->setExpectation(false, false);
1487 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1488 m_hostImpl
->drawLayers(frame
);
1489 EXPECT_TRUE(layer1
->quadsAppended());
1490 m_hostImpl
->didDrawAllLayers(frame
);
1492 // Layer with translucent content and painting, so drawn with blending.
1493 layer1
->setOpaque(false);
1494 layer1
->setOpaqueContents(false);
1495 layer1
->setExpectation(true, false);
1496 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1497 m_hostImpl
->drawLayers(frame
);
1498 EXPECT_TRUE(layer1
->quadsAppended());
1499 m_hostImpl
->didDrawAllLayers(frame
);
1501 // Layer with translucent opacity, drawn with blending.
1502 layer1
->setOpaque(true);
1503 layer1
->setOpaqueContents(true);
1504 layer1
->setOpacity(0.5);
1505 layer1
->setExpectation(true, false);
1506 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1507 m_hostImpl
->drawLayers(frame
);
1508 EXPECT_TRUE(layer1
->quadsAppended());
1509 m_hostImpl
->didDrawAllLayers(frame
);
1511 // Layer with translucent opacity and painting, drawn with blending.
1512 layer1
->setOpaque(true);
1513 layer1
->setOpaqueContents(false);
1514 layer1
->setOpacity(0.5);
1515 layer1
->setExpectation(true, false);
1516 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1517 m_hostImpl
->drawLayers(frame
);
1518 EXPECT_TRUE(layer1
->quadsAppended());
1519 m_hostImpl
->didDrawAllLayers(frame
);
1521 layer1
->addChild(BlendStateCheckLayer::create(3, m_hostImpl
->resourceProvider()));
1522 BlendStateCheckLayer
* layer2
= static_cast<BlendStateCheckLayer
*>(layer1
->children()[0].get());
1523 layer2
->setPosition(FloatPoint(4, 4));
1525 // 2 opaque layers, drawn without blending.
1526 layer1
->setOpaque(true);
1527 layer1
->setOpaqueContents(true);
1528 layer1
->setOpacity(1);
1529 layer1
->setExpectation(false, false);
1530 layer2
->setOpaque(true);
1531 layer2
->setOpaqueContents(true);
1532 layer2
->setOpacity(1);
1533 layer2
->setExpectation(false, false);
1534 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1535 m_hostImpl
->drawLayers(frame
);
1536 EXPECT_TRUE(layer1
->quadsAppended());
1537 EXPECT_TRUE(layer2
->quadsAppended());
1538 m_hostImpl
->didDrawAllLayers(frame
);
1540 // Parent layer with translucent content, drawn with blending.
1541 // Child layer with opaque content, drawn without blending.
1542 layer1
->setOpaque(false);
1543 layer1
->setOpaqueContents(false);
1544 layer1
->setExpectation(true, false);
1545 layer2
->setExpectation(false, false);
1546 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1547 m_hostImpl
->drawLayers(frame
);
1548 EXPECT_TRUE(layer1
->quadsAppended());
1549 EXPECT_TRUE(layer2
->quadsAppended());
1550 m_hostImpl
->didDrawAllLayers(frame
);
1552 // Parent layer with translucent content but opaque painting, drawn without blending.
1553 // Child layer with opaque content, drawn without blending.
1554 layer1
->setOpaque(false);
1555 layer1
->setOpaqueContents(true);
1556 layer1
->setExpectation(false, false);
1557 layer2
->setExpectation(false, false);
1558 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1559 m_hostImpl
->drawLayers(frame
);
1560 EXPECT_TRUE(layer1
->quadsAppended());
1561 EXPECT_TRUE(layer2
->quadsAppended());
1562 m_hostImpl
->didDrawAllLayers(frame
);
1564 // Parent layer with translucent opacity and opaque content. Since it has a
1565 // drawing child, it's drawn to a render surface which carries the opacity,
1566 // so it's itself drawn without blending.
1567 // Child layer with opaque content, drawn without blending (parent surface
1568 // carries the inherited opacity).
1569 layer1
->setOpaque(true);
1570 layer1
->setOpaqueContents(true);
1571 layer1
->setOpacity(0.5);
1572 layer1
->setExpectation(false, true);
1573 layer2
->setExpectation(false, false);
1574 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1575 m_hostImpl
->drawLayers(frame
);
1576 EXPECT_TRUE(layer1
->quadsAppended());
1577 EXPECT_TRUE(layer2
->quadsAppended());
1578 m_hostImpl
->didDrawAllLayers(frame
);
1580 // Draw again, but with child non-opaque, to make sure
1581 // layer1 not culled.
1582 layer1
->setOpaque(true);
1583 layer1
->setOpaqueContents(true);
1584 layer1
->setOpacity(1);
1585 layer1
->setExpectation(false, false);
1586 layer2
->setOpaque(true);
1587 layer2
->setOpaqueContents(true);
1588 layer2
->setOpacity(0.5);
1589 layer2
->setExpectation(true, false);
1590 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1591 m_hostImpl
->drawLayers(frame
);
1592 EXPECT_TRUE(layer1
->quadsAppended());
1593 EXPECT_TRUE(layer2
->quadsAppended());
1594 m_hostImpl
->didDrawAllLayers(frame
);
1596 // A second way of making the child non-opaque.
1597 layer1
->setOpaque(true);
1598 layer1
->setOpacity(1);
1599 layer1
->setExpectation(false, false);
1600 layer2
->setOpaque(false);
1601 layer2
->setOpaqueContents(false);
1602 layer2
->setOpacity(1);
1603 layer2
->setExpectation(true, false);
1604 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1605 m_hostImpl
->drawLayers(frame
);
1606 EXPECT_TRUE(layer1
->quadsAppended());
1607 EXPECT_TRUE(layer2
->quadsAppended());
1608 m_hostImpl
->didDrawAllLayers(frame
);
1610 // And when the layer says its not opaque but is painted opaque, it is not blended.
1611 layer1
->setOpaque(true);
1612 layer1
->setOpacity(1);
1613 layer1
->setExpectation(false, false);
1614 layer2
->setOpaque(false);
1615 layer2
->setOpaqueContents(true);
1616 layer2
->setOpacity(1);
1617 layer2
->setExpectation(false, false);
1618 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1619 m_hostImpl
->drawLayers(frame
);
1620 EXPECT_TRUE(layer1
->quadsAppended());
1621 EXPECT_TRUE(layer2
->quadsAppended());
1622 m_hostImpl
->didDrawAllLayers(frame
);
1624 // Layer with partially opaque contents, drawn with blending.
1625 layer1
->setOpaque(false);
1626 layer1
->setQuadRect(IntRect(5, 5, 5, 5));
1627 layer1
->setQuadVisibleRect(IntRect(5, 5, 5, 5));
1628 layer1
->setOpaqueContents(false);
1629 layer1
->setOpaqueContentRect(IntRect(5, 5, 2, 5));
1630 layer1
->setExpectation(true, false);
1631 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1632 m_hostImpl
->drawLayers(frame
);
1633 EXPECT_TRUE(layer1
->quadsAppended());
1634 m_hostImpl
->didDrawAllLayers(frame
);
1636 // Layer with partially opaque contents partially culled, drawn with blending.
1637 layer1
->setOpaque(false);
1638 layer1
->setQuadRect(IntRect(5, 5, 5, 5));
1639 layer1
->setQuadVisibleRect(IntRect(5, 5, 5, 2));
1640 layer1
->setOpaqueContents(false);
1641 layer1
->setOpaqueContentRect(IntRect(5, 5, 2, 5));
1642 layer1
->setExpectation(true, false);
1643 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1644 m_hostImpl
->drawLayers(frame
);
1645 EXPECT_TRUE(layer1
->quadsAppended());
1646 m_hostImpl
->didDrawAllLayers(frame
);
1648 // Layer with partially opaque contents culled, drawn with blending.
1649 layer1
->setOpaque(false);
1650 layer1
->setQuadRect(IntRect(5, 5, 5, 5));
1651 layer1
->setQuadVisibleRect(IntRect(7, 5, 3, 5));
1652 layer1
->setOpaqueContents(false);
1653 layer1
->setOpaqueContentRect(IntRect(5, 5, 2, 5));
1654 layer1
->setExpectation(true, false);
1655 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1656 m_hostImpl
->drawLayers(frame
);
1657 EXPECT_TRUE(layer1
->quadsAppended());
1658 m_hostImpl
->didDrawAllLayers(frame
);
1660 // Layer with partially opaque contents and translucent contents culled, drawn without blending.
1661 layer1
->setOpaque(false);
1662 layer1
->setQuadRect(IntRect(5, 5, 5, 5));
1663 layer1
->setQuadVisibleRect(IntRect(5, 5, 2, 5));
1664 layer1
->setOpaqueContents(false);
1665 layer1
->setOpaqueContentRect(IntRect(5, 5, 2, 5));
1666 layer1
->setExpectation(false, false);
1667 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1668 m_hostImpl
->drawLayers(frame
);
1669 EXPECT_TRUE(layer1
->quadsAppended());
1670 m_hostImpl
->didDrawAllLayers(frame
);
1674 TEST_F(CCLayerTreeHostImplTest
, viewportCovered
)
1676 m_hostImpl
->initializeRenderer(createContext(), UnthrottledUploader
);
1677 m_hostImpl
->setBackgroundColor(SK_ColorGRAY
);
1679 IntSize
viewportSize(1000, 1000);
1680 m_hostImpl
->setViewportSize(viewportSize
, viewportSize
);
1682 m_hostImpl
->setRootLayer(BlendStateCheckLayer::create(1, m_hostImpl
->resourceProvider()));
1683 BlendStateCheckLayer
* root
= static_cast<BlendStateCheckLayer
*>(m_hostImpl
->rootLayer());
1684 root
->setExpectation(false, true);
1685 root
->setOpaque(true);
1689 IntRect
layerRect(0, 0, 1000, 1000);
1690 root
->setPosition(layerRect
.location());
1691 root
->setBounds(layerRect
.size());
1692 root
->setContentBounds(layerRect
.size());
1693 root
->setQuadRect(IntRect(IntPoint(), layerRect
.size()));
1694 root
->setQuadVisibleRect(IntRect(IntPoint(), layerRect
.size()));
1696 CCLayerTreeHostImpl::FrameData frame
;
1697 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1698 ASSERT_EQ(1u, frame
.renderPasses
.size());
1700 size_t numGutterQuads
= 0;
1701 for (size_t i
= 0; i
< frame
.renderPasses
[0]->quadList().size(); ++i
)
1702 numGutterQuads
+= (frame
.renderPasses
[0]->quadList()[i
]->material() == CCDrawQuad::SolidColor
) ? 1 : 0;
1703 EXPECT_EQ(0u, numGutterQuads
);
1704 EXPECT_EQ(1u, frame
.renderPasses
[0]->quadList().size());
1706 verifyQuadsExactlyCoverRect(frame
.renderPasses
[0]->quadList(), IntRect(-layerRect
.location(), viewportSize
));
1707 m_hostImpl
->didDrawAllLayers(frame
);
1710 // Empty visible content area (fullscreen gutter rect)
1712 IntRect
layerRect(0, 0, 0, 0);
1713 root
->setPosition(layerRect
.location());
1714 root
->setBounds(layerRect
.size());
1715 root
->setContentBounds(layerRect
.size());
1716 root
->setQuadRect(IntRect(IntPoint(), layerRect
.size()));
1717 root
->setQuadVisibleRect(IntRect(IntPoint(), layerRect
.size()));
1719 CCLayerTreeHostImpl::FrameData frame
;
1720 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1721 ASSERT_EQ(1u, frame
.renderPasses
.size());
1722 m_hostImpl
->didDrawAllLayers(frame
);
1724 size_t numGutterQuads
= 0;
1725 for (size_t i
= 0; i
< frame
.renderPasses
[0]->quadList().size(); ++i
)
1726 numGutterQuads
+= (frame
.renderPasses
[0]->quadList()[i
]->material() == CCDrawQuad::SolidColor
) ? 1 : 0;
1727 EXPECT_EQ(1u, numGutterQuads
);
1728 EXPECT_EQ(1u, frame
.renderPasses
[0]->quadList().size());
1730 verifyQuadsExactlyCoverRect(frame
.renderPasses
[0]->quadList(), IntRect(-layerRect
.location(), viewportSize
));
1731 m_hostImpl
->didDrawAllLayers(frame
);
1734 // Content area in middle of clip rect (four surrounding gutter rects)
1736 IntRect
layerRect(500, 500, 200, 200);
1737 root
->setPosition(layerRect
.location());
1738 root
->setBounds(layerRect
.size());
1739 root
->setContentBounds(layerRect
.size());
1740 root
->setQuadRect(IntRect(IntPoint(), layerRect
.size()));
1741 root
->setQuadVisibleRect(IntRect(IntPoint(), layerRect
.size()));
1743 CCLayerTreeHostImpl::FrameData frame
;
1744 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1745 ASSERT_EQ(1u, frame
.renderPasses
.size());
1747 size_t numGutterQuads
= 0;
1748 for (size_t i
= 0; i
< frame
.renderPasses
[0]->quadList().size(); ++i
)
1749 numGutterQuads
+= (frame
.renderPasses
[0]->quadList()[i
]->material() == CCDrawQuad::SolidColor
) ? 1 : 0;
1750 EXPECT_EQ(4u, numGutterQuads
);
1751 EXPECT_EQ(5u, frame
.renderPasses
[0]->quadList().size());
1753 verifyQuadsExactlyCoverRect(frame
.renderPasses
[0]->quadList(), IntRect(-layerRect
.location(), viewportSize
));
1754 m_hostImpl
->didDrawAllLayers(frame
);
1760 class ReshapeTrackerContext
: public FakeWebGraphicsContext3D
{
1762 ReshapeTrackerContext() : m_reshapeCalled(false) { }
1764 virtual void reshape(int width
, int height
)
1766 m_reshapeCalled
= true;
1769 bool reshapeCalled() const { return m_reshapeCalled
; }
1772 bool m_reshapeCalled
;
1775 class FakeDrawableCCLayerImpl
: public CCLayerImpl
{
1777 explicit FakeDrawableCCLayerImpl(int id
) : CCLayerImpl(id
) { }
1780 // Only reshape when we know we are going to draw. Otherwise, the reshape
1781 // can leave the window at the wrong size if we never draw and the proper
1782 // viewport size is never set.
1783 TEST_F(CCLayerTreeHostImplTest
, reshapeNotCalledUntilDraw
)
1785 OwnPtr
<CCGraphicsContext
> ccContext
= FakeWebCompositorOutputSurface::create(adoptPtr(new ReshapeTrackerContext
));
1786 ReshapeTrackerContext
* reshapeTracker
= static_cast<ReshapeTrackerContext
*>(ccContext
->context3D());
1787 m_hostImpl
->initializeRenderer(ccContext
.release(), UnthrottledUploader
);
1789 CCLayerImpl
* root
= new FakeDrawableCCLayerImpl(1);
1790 root
->setAnchorPoint(FloatPoint(0, 0));
1791 root
->setBounds(IntSize(10, 10));
1792 root
->setDrawsContent(true);
1793 m_hostImpl
->setRootLayer(adoptPtr(root
));
1794 EXPECT_FALSE(reshapeTracker
->reshapeCalled());
1796 CCLayerTreeHostImpl::FrameData frame
;
1797 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1798 m_hostImpl
->drawLayers(frame
);
1799 EXPECT_TRUE(reshapeTracker
->reshapeCalled());
1800 m_hostImpl
->didDrawAllLayers(frame
);
1803 class PartialSwapTrackerContext
: public FakeWebGraphicsContext3D
{
1805 virtual void postSubBufferCHROMIUM(int x
, int y
, int width
, int height
)
1807 m_partialSwapRect
= IntRect(x
, y
, width
, height
);
1810 virtual WebString
getString(WGC3Denum name
)
1812 if (name
== GraphicsContext3D::EXTENSIONS
)
1813 return WebString("GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
1818 IntRect
partialSwapRect() const { return m_partialSwapRect
; }
1821 IntRect m_partialSwapRect
;
1824 // Make sure damage tracking propagates all the way to the graphics context,
1825 // where it should request to swap only the subBuffer that is damaged.
1826 TEST_F(CCLayerTreeHostImplTest
, partialSwapReceivesDamageRect
)
1828 OwnPtr
<CCGraphicsContext
> ccContext
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapTrackerContext
));
1829 PartialSwapTrackerContext
* partialSwapTracker
= static_cast<PartialSwapTrackerContext
*>(ccContext
->context3D());
1831 // This test creates its own CCLayerTreeHostImpl, so
1832 // that we can force partial swap enabled.
1833 CCLayerTreeSettings settings
;
1834 CCSettings::setPartialSwapEnabled(true);
1835 OwnPtr
<CCLayerTreeHostImpl
> layerTreeHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
1836 layerTreeHostImpl
->initializeRenderer(ccContext
.release(), UnthrottledUploader
);
1837 layerTreeHostImpl
->setViewportSize(IntSize(500, 500), IntSize(500, 500));
1839 CCLayerImpl
* root
= new FakeDrawableCCLayerImpl(1);
1840 CCLayerImpl
* child
= new FakeDrawableCCLayerImpl(2);
1841 child
->setPosition(FloatPoint(12, 13));
1842 child
->setAnchorPoint(FloatPoint(0, 0));
1843 child
->setBounds(IntSize(14, 15));
1844 child
->setContentBounds(IntSize(14, 15));
1845 child
->setDrawsContent(true);
1846 root
->setAnchorPoint(FloatPoint(0, 0));
1847 root
->setBounds(IntSize(500, 500));
1848 root
->setContentBounds(IntSize(500, 500));
1849 root
->setDrawsContent(true);
1850 root
->addChild(adoptPtr(child
));
1851 layerTreeHostImpl
->setRootLayer(adoptPtr(root
));
1853 CCLayerTreeHostImpl::FrameData frame
;
1855 // First frame, the entire screen should get swapped.
1856 EXPECT_TRUE(layerTreeHostImpl
->prepareToDraw(frame
));
1857 layerTreeHostImpl
->drawLayers(frame
);
1858 layerTreeHostImpl
->didDrawAllLayers(frame
);
1859 layerTreeHostImpl
->swapBuffers();
1860 IntRect actualSwapRect
= partialSwapTracker
->partialSwapRect();
1861 IntRect expectedSwapRect
= IntRect(IntPoint::zero(), IntSize(500, 500));
1862 EXPECT_EQ(expectedSwapRect
.x(), actualSwapRect
.x());
1863 EXPECT_EQ(expectedSwapRect
.y(), actualSwapRect
.y());
1864 EXPECT_EQ(expectedSwapRect
.width(), actualSwapRect
.width());
1865 EXPECT_EQ(expectedSwapRect
.height(), actualSwapRect
.height());
1867 // Second frame, only the damaged area should get swapped. Damage should be the union
1868 // of old and new child rects.
1869 // expected damage rect: IntRect(IntPoint::zero(), IntSize(26, 28));
1870 // expected swap rect: vertically flipped, with origin at bottom left corner.
1871 child
->setPosition(FloatPoint(0, 0));
1872 EXPECT_TRUE(layerTreeHostImpl
->prepareToDraw(frame
));
1873 layerTreeHostImpl
->drawLayers(frame
);
1874 m_hostImpl
->didDrawAllLayers(frame
);
1875 layerTreeHostImpl
->swapBuffers();
1876 actualSwapRect
= partialSwapTracker
->partialSwapRect();
1877 expectedSwapRect
= IntRect(IntPoint(0, 500-28), IntSize(26, 28));
1878 EXPECT_EQ(expectedSwapRect
.x(), actualSwapRect
.x());
1879 EXPECT_EQ(expectedSwapRect
.y(), actualSwapRect
.y());
1880 EXPECT_EQ(expectedSwapRect
.width(), actualSwapRect
.width());
1881 EXPECT_EQ(expectedSwapRect
.height(), actualSwapRect
.height());
1883 // Make sure that partial swap is constrained to the viewport dimensions
1884 // expected damage rect: IntRect(IntPoint::zero(), IntSize(500, 500));
1885 // expected swap rect: flipped damage rect, but also clamped to viewport
1886 layerTreeHostImpl
->setViewportSize(IntSize(10, 10), IntSize(10, 10));
1887 root
->setOpacity(0.7f
); // this will damage everything
1888 EXPECT_TRUE(layerTreeHostImpl
->prepareToDraw(frame
));
1889 layerTreeHostImpl
->drawLayers(frame
);
1890 m_hostImpl
->didDrawAllLayers(frame
);
1891 layerTreeHostImpl
->swapBuffers();
1892 actualSwapRect
= partialSwapTracker
->partialSwapRect();
1893 expectedSwapRect
= IntRect(IntPoint::zero(), IntSize(10, 10));
1894 EXPECT_EQ(expectedSwapRect
.x(), actualSwapRect
.x());
1895 EXPECT_EQ(expectedSwapRect
.y(), actualSwapRect
.y());
1896 EXPECT_EQ(expectedSwapRect
.width(), actualSwapRect
.width());
1897 EXPECT_EQ(expectedSwapRect
.height(), actualSwapRect
.height());
1900 TEST_F(CCLayerTreeHostImplTest
, rootLayerDoesntCreateExtraSurface
)
1902 CCLayerImpl
* root
= new FakeDrawableCCLayerImpl(1);
1903 CCLayerImpl
* child
= new FakeDrawableCCLayerImpl(2);
1904 child
->setAnchorPoint(FloatPoint(0, 0));
1905 child
->setBounds(IntSize(10, 10));
1906 child
->setContentBounds(IntSize(10, 10));
1907 child
->setDrawsContent(true);
1908 root
->setAnchorPoint(FloatPoint(0, 0));
1909 root
->setBounds(IntSize(10, 10));
1910 root
->setContentBounds(IntSize(10, 10));
1911 root
->setDrawsContent(true);
1912 root
->setOpacity(0.7f
);
1913 root
->addChild(adoptPtr(child
));
1915 m_hostImpl
->setRootLayer(adoptPtr(root
));
1917 CCLayerTreeHostImpl::FrameData frame
;
1919 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
1920 EXPECT_EQ(1u, frame
.renderSurfaceLayerList
->size());
1921 EXPECT_EQ(1u, frame
.renderPasses
.size());
1922 m_hostImpl
->didDrawAllLayers(frame
);
1927 class FakeLayerWithQuads
: public CCLayerImpl
{
1929 static PassOwnPtr
<FakeLayerWithQuads
> create(int id
) { return adoptPtr(new FakeLayerWithQuads(id
)); }
1931 virtual void appendQuads(CCQuadSink
& quadSink
, CCAppendQuadsData
& appendQuadsData
) OVERRIDE
1933 CCSharedQuadState
* sharedQuadState
= quadSink
.useSharedQuadState(createSharedQuadState());
1935 SkColor gray
= SkColorSetRGB(100, 100, 100);
1936 IntRect
quadRect(IntPoint(0, 0), contentBounds());
1937 OwnPtr
<CCDrawQuad
> myQuad
= CCSolidColorDrawQuad::create(sharedQuadState
, quadRect
, gray
);
1938 quadSink
.append(myQuad
.release(), appendQuadsData
);
1942 FakeLayerWithQuads(int id
)
1950 class MockContext
: public FakeWebGraphicsContext3D
{
1952 MOCK_METHOD1(useProgram
, void(WebGLId program
));
1953 MOCK_METHOD5(uniform4f
, void(WGC3Dint location
, WGC3Dfloat x
, WGC3Dfloat y
, WGC3Dfloat z
, WGC3Dfloat w
));
1954 MOCK_METHOD4(uniformMatrix4fv
, void(WGC3Dint location
, WGC3Dsizei count
, WGC3Dboolean transpose
, const WGC3Dfloat
* value
));
1955 MOCK_METHOD4(drawElements
, void(WGC3Denum mode
, WGC3Dsizei count
, WGC3Denum type
, WGC3Dintptr offset
));
1956 MOCK_METHOD1(getString
, WebString(WGC3Denum name
));
1957 MOCK_METHOD0(getRequestableExtensionsCHROMIUM
, WebString());
1958 MOCK_METHOD1(enable
, void(WGC3Denum cap
));
1959 MOCK_METHOD1(disable
, void(WGC3Denum cap
));
1960 MOCK_METHOD4(scissor
, void(WGC3Dint x
, WGC3Dint y
, WGC3Dsizei width
, WGC3Dsizei height
));
1963 class MockContextHarness
{
1965 MockContext
* m_context
;
1967 MockContextHarness(MockContext
* context
)
1968 : m_context(context
)
1970 // Catch "uninteresting" calls
1971 EXPECT_CALL(*m_context
, useProgram(_
))
1974 EXPECT_CALL(*m_context
, drawElements(_
, _
, _
, _
))
1977 // These are not asserted
1978 EXPECT_CALL(*m_context
, uniformMatrix4fv(_
, _
, _
, _
))
1979 .WillRepeatedly(Return());
1981 EXPECT_CALL(*m_context
, uniform4f(_
, _
, _
, _
, _
))
1982 .WillRepeatedly(Return());
1984 // Any other strings are empty
1985 EXPECT_CALL(*m_context
, getString(_
))
1986 .WillRepeatedly(Return(WebString()));
1988 // Support for partial swap, if needed
1989 EXPECT_CALL(*m_context
, getString(GraphicsContext3D::EXTENSIONS
))
1990 .WillRepeatedly(Return(WebString("GL_CHROMIUM_post_sub_buffer")));
1992 EXPECT_CALL(*m_context
, getRequestableExtensionsCHROMIUM())
1993 .WillRepeatedly(Return(WebString("GL_CHROMIUM_post_sub_buffer")));
1995 // Any un-sanctioned calls to enable() are OK
1996 EXPECT_CALL(*m_context
, enable(_
))
1997 .WillRepeatedly(Return());
1999 // Any un-sanctioned calls to disable() are OK
2000 EXPECT_CALL(*m_context
, disable(_
))
2001 .WillRepeatedly(Return());
2004 void mustDrawSolidQuad()
2006 EXPECT_CALL(*m_context
, drawElements(GraphicsContext3D::TRIANGLES
, 6, GraphicsContext3D::UNSIGNED_SHORT
, 0))
2008 .RetiresOnSaturation();
2010 // 1 is hardcoded return value of fake createProgram()
2011 EXPECT_CALL(*m_context
, useProgram(1))
2013 .RetiresOnSaturation();
2017 void mustSetScissor(int x
, int y
, int width
, int height
)
2019 EXPECT_CALL(*m_context
, enable(GraphicsContext3D::SCISSOR_TEST
))
2020 .WillRepeatedly(Return());
2022 EXPECT_CALL(*m_context
, scissor(x
, y
, width
, height
))
2024 .WillRepeatedly(Return());
2027 void mustSetNoScissor()
2029 EXPECT_CALL(*m_context
, disable(GraphicsContext3D::SCISSOR_TEST
))
2030 .WillRepeatedly(Return());
2032 EXPECT_CALL(*m_context
, enable(GraphicsContext3D::SCISSOR_TEST
))
2035 EXPECT_CALL(*m_context
, scissor(_
, _
, _
, _
))
2040 TEST_F(CCLayerTreeHostImplTest
, noPartialSwap
)
2042 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new MockContext
));
2043 MockContext
* mockContext
= static_cast<MockContext
*>(context
->context3D());
2044 MockContextHarness
harness(mockContext
);
2046 harness
.mustDrawSolidQuad();
2047 harness
.mustSetScissor(0, 0, 10, 10);
2050 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= createLayerTreeHost(false, context
.release(), FakeLayerWithQuads::create(1));
2052 CCLayerTreeHostImpl::FrameData frame
;
2053 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2054 myHostImpl
->drawLayers(frame
);
2055 myHostImpl
->didDrawAllLayers(frame
);
2056 Mock::VerifyAndClearExpectations(&mockContext
);
2059 TEST_F(CCLayerTreeHostImplTest
, partialSwap
)
2061 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new MockContext
));
2062 MockContext
* mockContext
= static_cast<MockContext
*>(context
->context3D());
2063 MockContextHarness
harness(mockContext
);
2065 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= createLayerTreeHost(true, context
.release(), FakeLayerWithQuads::create(1));
2067 // The first frame is not a partially-swapped one.
2068 harness
.mustSetScissor(0, 0, 10, 10);
2069 harness
.mustDrawSolidQuad();
2071 CCLayerTreeHostImpl::FrameData frame
;
2072 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2073 myHostImpl
->drawLayers(frame
);
2074 myHostImpl
->didDrawAllLayers(frame
);
2076 Mock::VerifyAndClearExpectations(&mockContext
);
2078 // Damage a portion of the frame.
2079 myHostImpl
->rootLayer()->setUpdateRect(IntRect(0, 0, 2, 3));
2081 // The second frame will be partially-swapped (the y coordinates are flipped).
2082 harness
.mustSetScissor(0, 7, 2, 3);
2083 harness
.mustDrawSolidQuad();
2085 CCLayerTreeHostImpl::FrameData frame
;
2086 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2087 myHostImpl
->drawLayers(frame
);
2088 myHostImpl
->didDrawAllLayers(frame
);
2090 Mock::VerifyAndClearExpectations(&mockContext
);
2093 class PartialSwapContext
: public FakeWebGraphicsContext3D
{
2095 WebString
getString(WGC3Denum name
)
2097 if (name
== GraphicsContext3D::EXTENSIONS
)
2098 return WebString("GL_CHROMIUM_post_sub_buffer");
2102 WebString
getRequestableExtensionsCHROMIUM()
2104 return WebString("GL_CHROMIUM_post_sub_buffer");
2107 // Unlimited texture size.
2108 virtual void getIntegerv(WGC3Denum pname
, WGC3Dint
* value
)
2110 if (pname
== WebCore::GraphicsContext3D::MAX_TEXTURE_SIZE
)
2115 static PassOwnPtr
<CCLayerTreeHostImpl
> setupLayersForOpacity(bool partialSwap
, CCLayerTreeHostImplClient
* client
)
2117 CCSettings::setPartialSwapEnabled(partialSwap
);
2119 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
2121 CCLayerTreeSettings settings
;
2122 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, client
);
2123 myHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
2124 myHostImpl
->setViewportSize(IntSize(100, 100), IntSize(100, 100));
2127 Layers are created as follows:
2129 +--------------------+
2133 | | +-------------------+
2135 | | +-------------------+
2140 +--------------------+
2142 Layers 1, 2 have render surfaces
2144 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
2145 OwnPtr
<CCLayerImpl
> child
= CCLayerImpl::create(2);
2146 OwnPtr
<CCLayerImpl
> grandChild
= FakeLayerWithQuads::create(3);
2148 IntRect
rootRect(0, 0, 100, 100);
2149 IntRect
childRect(10, 10, 50, 50);
2150 IntRect
grandChildRect(5, 5, 150, 150);
2152 root
->createRenderSurface();
2153 root
->setAnchorPoint(FloatPoint(0, 0));
2154 root
->setPosition(FloatPoint(rootRect
.x(), rootRect
.y()));
2155 root
->setBounds(IntSize(rootRect
.width(), rootRect
.height()));
2156 root
->setContentBounds(root
->bounds());
2157 root
->setVisibleContentRect(rootRect
);
2158 root
->setDrawsContent(false);
2159 root
->renderSurface()->setContentRect(IntRect(IntPoint(), IntSize(rootRect
.width(), rootRect
.height())));
2161 child
->setAnchorPoint(FloatPoint(0, 0));
2162 child
->setPosition(FloatPoint(childRect
.x(), childRect
.y()));
2163 child
->setOpacity(0.5f
);
2164 child
->setBounds(IntSize(childRect
.width(), childRect
.height()));
2165 child
->setContentBounds(child
->bounds());
2166 child
->setVisibleContentRect(childRect
);
2167 child
->setDrawsContent(false);
2169 grandChild
->setAnchorPoint(FloatPoint(0, 0));
2170 grandChild
->setPosition(IntPoint(grandChildRect
.x(), grandChildRect
.y()));
2171 grandChild
->setBounds(IntSize(grandChildRect
.width(), grandChildRect
.height()));
2172 grandChild
->setContentBounds(grandChild
->bounds());
2173 grandChild
->setVisibleContentRect(grandChildRect
);
2174 grandChild
->setDrawsContent(true);
2176 child
->addChild(grandChild
.release());
2177 root
->addChild(child
.release());
2179 myHostImpl
->setRootLayer(root
.release());
2180 return myHostImpl
.release();
2183 TEST_F(CCLayerTreeHostImplTest
, contributingLayerEmptyScissorPartialSwap
)
2185 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= setupLayersForOpacity(true, this);
2188 CCLayerTreeHostImpl::FrameData frame
;
2189 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2191 // Just for consistency, the most interesting stuff already happened
2192 myHostImpl
->drawLayers(frame
);
2193 myHostImpl
->didDrawAllLayers(frame
);
2195 // Verify all quads have been computed
2196 ASSERT_EQ(2U, frame
.renderPasses
.size());
2197 ASSERT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
2198 ASSERT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
2199 EXPECT_EQ(CCDrawQuad::SolidColor
, frame
.renderPasses
[0]->quadList()[0]->material());
2200 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
2204 TEST_F(CCLayerTreeHostImplTest
, contributingLayerEmptyScissorNoPartialSwap
)
2206 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= setupLayersForOpacity(false, this);
2209 CCLayerTreeHostImpl::FrameData frame
;
2210 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2212 // Just for consistency, the most interesting stuff already happened
2213 myHostImpl
->drawLayers(frame
);
2214 myHostImpl
->didDrawAllLayers(frame
);
2216 // Verify all quads have been computed
2217 ASSERT_EQ(2U, frame
.renderPasses
.size());
2218 ASSERT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
2219 ASSERT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
2220 EXPECT_EQ(CCDrawQuad::SolidColor
, frame
.renderPasses
[0]->quadList()[0]->material());
2221 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
2225 // Make sure that context lost notifications are propagated through the tree.
2226 class ContextLostNotificationCheckLayer
: public CCLayerImpl
{
2228 static PassOwnPtr
<ContextLostNotificationCheckLayer
> create(int id
) { return adoptPtr(new ContextLostNotificationCheckLayer(id
)); }
2230 virtual void didLoseContext() OVERRIDE
2232 m_didLoseContextCalled
= true;
2235 bool didLoseContextCalled() const { return m_didLoseContextCalled
; }
2238 explicit ContextLostNotificationCheckLayer(int id
)
2240 , m_didLoseContextCalled(false)
2244 bool m_didLoseContextCalled
;
2247 TEST_F(CCLayerTreeHostImplTest
, contextLostAndRestoredNotificationSentToAllLayers
)
2249 m_hostImpl
->setRootLayer(ContextLostNotificationCheckLayer::create(1));
2250 ContextLostNotificationCheckLayer
* root
= static_cast<ContextLostNotificationCheckLayer
*>(m_hostImpl
->rootLayer());
2252 root
->addChild(ContextLostNotificationCheckLayer::create(1));
2253 ContextLostNotificationCheckLayer
* layer1
= static_cast<ContextLostNotificationCheckLayer
*>(root
->children()[0].get());
2255 layer1
->addChild(ContextLostNotificationCheckLayer::create(2));
2256 ContextLostNotificationCheckLayer
* layer2
= static_cast<ContextLostNotificationCheckLayer
*>(layer1
->children()[0].get());
2258 EXPECT_FALSE(root
->didLoseContextCalled());
2259 EXPECT_FALSE(layer1
->didLoseContextCalled());
2260 EXPECT_FALSE(layer2
->didLoseContextCalled());
2262 m_hostImpl
->initializeRenderer(createContext(), UnthrottledUploader
);
2264 EXPECT_TRUE(root
->didLoseContextCalled());
2265 EXPECT_TRUE(layer1
->didLoseContextCalled());
2266 EXPECT_TRUE(layer2
->didLoseContextCalled());
2269 TEST_F(CCLayerTreeHostImplTest
, finishAllRenderingAfterContextLost
)
2271 CCLayerTreeSettings settings
;
2272 m_hostImpl
= CCLayerTreeHostImpl::create(settings
, this);
2274 // The context initialization will fail, but we should still be able to call finishAllRendering() without any ill effects.
2275 m_hostImpl
->initializeRenderer(FakeWebCompositorOutputSurface::create(adoptPtr(new FakeWebGraphicsContext3DMakeCurrentFails
)), UnthrottledUploader
);
2276 m_hostImpl
->finishAllRendering();
2279 // Fake WebGraphicsContext3D that will cause a failure if trying to use a
2280 // resource that wasn't created by it (resources created by
2281 // FakeWebGraphicsContext3D have an id of 1).
2282 class StrictWebGraphicsContext3D
: public FakeWebGraphicsContext3D
{
2284 StrictWebGraphicsContext3D()
2285 : FakeWebGraphicsContext3D()
2287 m_nextTextureId
= 7; // Start allocating texture ids larger than any other resource IDs so we can tell if someone's mixing up their resource types.
2290 virtual WebGLId
createBuffer() { return 2; }
2291 virtual WebGLId
createFramebuffer() { return 3; }
2292 virtual WebGLId
createProgram() { return 4; }
2293 virtual WebGLId
createRenderbuffer() { return 5; }
2294 virtual WebGLId
createShader(WGC3Denum
) { return 6; }
2296 virtual void deleteBuffer(WebGLId id
)
2299 ADD_FAILURE() << "Trying to delete buffer id " << id
;
2302 virtual void deleteFramebuffer(WebGLId id
)
2305 ADD_FAILURE() << "Trying to delete framebuffer id " << id
;
2308 virtual void deleteProgram(WebGLId id
)
2311 ADD_FAILURE() << "Trying to delete program id " << id
;
2314 virtual void deleteRenderbuffer(WebGLId id
)
2317 ADD_FAILURE() << "Trying to delete renderbuffer id " << id
;
2320 virtual void deleteShader(WebGLId id
)
2323 ADD_FAILURE() << "Trying to delete shader id " << id
;
2326 virtual WebGLId
createTexture()
2328 unsigned textureId
= FakeWebGraphicsContext3D::createTexture();
2329 m_allocatedTextureIds
.add(textureId
);
2332 virtual void deleteTexture(WebGLId id
)
2334 if (!m_allocatedTextureIds
.contains(id
))
2335 ADD_FAILURE() << "Trying to delete texture id " << id
;
2336 m_allocatedTextureIds
.remove(id
);
2339 virtual void bindBuffer(WGC3Denum
, WebGLId id
)
2342 ADD_FAILURE() << "Trying to bind buffer id " << id
;
2345 virtual void bindFramebuffer(WGC3Denum
, WebGLId id
)
2348 ADD_FAILURE() << "Trying to bind framebuffer id " << id
;
2351 virtual void useProgram(WebGLId id
)
2354 ADD_FAILURE() << "Trying to use program id " << id
;
2357 virtual void bindRenderbuffer(WGC3Denum
, WebGLId id
)
2360 ADD_FAILURE() << "Trying to bind renderbuffer id " << id
;
2363 virtual void attachShader(WebGLId program
, WebGLId shader
)
2365 if ((program
!= 4) || (shader
!= 6))
2366 ADD_FAILURE() << "Trying to attach shader id " << shader
<< " to program id " << program
;
2369 virtual void bindTexture(WGC3Denum
, WebGLId id
)
2371 if (id
&& !m_allocatedTextureIds
.contains(id
))
2372 ADD_FAILURE() << "Trying to bind texture id " << id
;
2376 HashSet
<unsigned> m_allocatedTextureIds
;
2379 // Fake video frame that represents a 4x4 YUV video frame.
2380 class FakeVideoFrame
: public WebVideoFrame
{
2382 FakeVideoFrame() : m_textureId(0) { memset(m_data
, 0x80, sizeof(m_data
)); }
2383 virtual ~FakeVideoFrame() { }
2384 virtual Format
format() const { return m_textureId
? FormatNativeTexture
: FormatYV12
; }
2385 virtual unsigned width() const { return 4; }
2386 virtual unsigned height() const { return 4; }
2387 virtual unsigned planes() const { return 3; }
2388 virtual int stride(unsigned plane
) const { return 4; }
2389 virtual const void* data(unsigned plane
) const { return m_data
; }
2390 virtual unsigned textureId() const { return m_textureId
; }
2391 virtual unsigned textureTarget() const { return m_textureId
? GraphicsContext3D::TEXTURE_2D
: 0; }
2393 void setTextureId(unsigned id
) { m_textureId
= id
; }
2397 unsigned m_textureId
;
2400 // Fake video frame provider that always provides the same FakeVideoFrame.
2401 class FakeVideoFrameProvider
: public WebVideoFrameProvider
{
2403 FakeVideoFrameProvider() : m_frame(0), m_client(0) { }
2404 virtual ~FakeVideoFrameProvider()
2407 m_client
->stopUsingProvider();
2410 virtual void setVideoFrameProviderClient(Client
* client
) { m_client
= client
; }
2411 virtual WebVideoFrame
* getCurrentFrame() { return m_frame
; }
2412 virtual void putCurrentFrame(WebVideoFrame
*) { }
2414 void setFrame(WebVideoFrame
* frame
) { m_frame
= frame
; }
2417 WebVideoFrame
* m_frame
;
2421 class StrictWebGraphicsContext3DWithIOSurface
: public StrictWebGraphicsContext3D
{
2423 virtual WebString
getString(WGC3Denum name
) OVERRIDE
2425 if (name
== WebCore::GraphicsContext3D::EXTENSIONS
)
2426 return WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2432 class FakeWebGraphicsContext3DWithIOSurface
: public FakeWebGraphicsContext3D
{
2434 virtual WebString
getString(WGC3Denum name
) OVERRIDE
2436 if (name
== WebCore::GraphicsContext3D::EXTENSIONS
)
2437 return WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2443 class FakeWebScrollbarThemeGeometryNonEmpty
: public FakeWebScrollbarThemeGeometry
{
2444 virtual WebRect
trackRect(WebScrollbar
*) OVERRIDE
{ return WebRect(0, 0, 10, 10); }
2445 virtual WebRect
thumbRect(WebScrollbar
*) OVERRIDE
{ return WebRect(0, 5, 5, 2); }
2446 virtual void splitTrack(WebScrollbar
*, const WebRect
& track
, WebRect
& startTrack
, WebRect
& thumb
, WebRect
& endTrack
) OVERRIDE
2448 thumb
= WebRect(0, 5, 5, 2);
2449 startTrack
= WebRect(0, 5, 0, 5);
2450 endTrack
= WebRect(0, 0, 0, 5);
2454 class FakeScrollbarLayerImpl
: public CCScrollbarLayerImpl
{
2456 static PassOwnPtr
<FakeScrollbarLayerImpl
> create(int id
)
2458 return adoptPtr(new FakeScrollbarLayerImpl(id
));
2461 void createResources(CCResourceProvider
* provider
)
2465 IntSize
size(10, 10);
2466 GC3Denum format
= GraphicsContext3D::RGBA
;
2467 CCResourceProvider::TextureUsageHint hint
= CCResourceProvider::TextureUsageAny
;
2468 setScrollbarGeometry(CCScrollbarGeometryFixedThumb::create(FakeWebScrollbarThemeGeometryNonEmpty::create()));
2470 setBackTrackResourceId(provider
->createResource(pool
, size
, format
, hint
));
2471 setForeTrackResourceId(provider
->createResource(pool
, size
, format
, hint
));
2472 setThumbResourceId(provider
->createResource(pool
, size
, format
, hint
));
2476 explicit FakeScrollbarLayerImpl(int id
)
2477 : CCScrollbarLayerImpl(id
)
2482 TEST_F(CCLayerTreeHostImplTest
, dontUseOldResourcesAfterLostContext
)
2484 OwnPtr
<CCLayerImpl
> rootLayer(CCLayerImpl::create(1));
2485 rootLayer
->setBounds(IntSize(10, 10));
2486 rootLayer
->setAnchorPoint(FloatPoint(0, 0));
2488 OwnPtr
<CCTiledLayerImpl
> tileLayer
= CCTiledLayerImpl::create(2);
2489 tileLayer
->setBounds(IntSize(10, 10));
2490 tileLayer
->setAnchorPoint(FloatPoint(0, 0));
2491 tileLayer
->setContentBounds(IntSize(10, 10));
2492 tileLayer
->setDrawsContent(true);
2493 tileLayer
->setSkipsDraw(false);
2494 OwnPtr
<CCLayerTilingData
> tilingData(CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels
));
2495 tilingData
->setBounds(IntSize(10, 10));
2496 tileLayer
->setTilingData(*tilingData
);
2497 tileLayer
->pushTileProperties(0, 0, 1, IntRect(0, 0, 10, 10));
2498 rootLayer
->addChild(tileLayer
.release());
2500 OwnPtr
<CCTextureLayerImpl
> textureLayer
= CCTextureLayerImpl::create(3);
2501 textureLayer
->setBounds(IntSize(10, 10));
2502 textureLayer
->setAnchorPoint(FloatPoint(0, 0));
2503 textureLayer
->setContentBounds(IntSize(10, 10));
2504 textureLayer
->setDrawsContent(true);
2505 textureLayer
->setTextureId(1);
2506 rootLayer
->addChild(textureLayer
.release());
2508 FakeVideoFrame videoFrame
;
2509 FakeVideoFrameProvider provider
;
2510 provider
.setFrame(&videoFrame
);
2511 OwnPtr
<CCVideoLayerImpl
> videoLayer
= CCVideoLayerImpl::create(4, &provider
);
2512 videoLayer
->setBounds(IntSize(10, 10));
2513 videoLayer
->setAnchorPoint(FloatPoint(0, 0));
2514 videoLayer
->setContentBounds(IntSize(10, 10));
2515 videoLayer
->setDrawsContent(true);
2516 videoLayer
->setLayerTreeHostImpl(m_hostImpl
.get());
2517 rootLayer
->addChild(videoLayer
.release());
2519 FakeVideoFrame hwVideoFrame
;
2520 FakeVideoFrameProvider hwProvider
;
2521 hwProvider
.setFrame(&hwVideoFrame
);
2522 OwnPtr
<CCVideoLayerImpl
> hwVideoLayer
= CCVideoLayerImpl::create(5, &hwProvider
);
2523 hwVideoLayer
->setBounds(IntSize(10, 10));
2524 hwVideoLayer
->setAnchorPoint(FloatPoint(0, 0));
2525 hwVideoLayer
->setContentBounds(IntSize(10, 10));
2526 hwVideoLayer
->setDrawsContent(true);
2527 hwVideoLayer
->setLayerTreeHostImpl(m_hostImpl
.get());
2528 rootLayer
->addChild(hwVideoLayer
.release());
2530 OwnPtr
<CCIOSurfaceLayerImpl
> ioSurfaceLayer
= CCIOSurfaceLayerImpl::create(6);
2531 ioSurfaceLayer
->setBounds(IntSize(10, 10));
2532 ioSurfaceLayer
->setAnchorPoint(FloatPoint(0, 0));
2533 ioSurfaceLayer
->setContentBounds(IntSize(10, 10));
2534 ioSurfaceLayer
->setDrawsContent(true);
2535 ioSurfaceLayer
->setIOSurfaceProperties(1, IntSize(10, 10));
2536 ioSurfaceLayer
->setLayerTreeHostImpl(m_hostImpl
.get());
2537 rootLayer
->addChild(ioSurfaceLayer
.release());
2539 OwnPtr
<CCHeadsUpDisplayLayerImpl
> hudLayer
= CCHeadsUpDisplayLayerImpl::create(7);
2540 hudLayer
->setBounds(IntSize(10, 10));
2541 hudLayer
->setAnchorPoint(FloatPoint(0, 0));
2542 hudLayer
->setContentBounds(IntSize(10, 10));
2543 hudLayer
->setDrawsContent(true);
2544 hudLayer
->setLayerTreeHostImpl(m_hostImpl
.get());
2545 rootLayer
->addChild(hudLayer
.release());
2547 OwnPtr
<FakeScrollbarLayerImpl
> scrollbarLayer(FakeScrollbarLayerImpl::create(8));
2548 scrollbarLayer
->setLayerTreeHostImpl(m_hostImpl
.get());
2549 scrollbarLayer
->setBounds(IntSize(10, 10));
2550 scrollbarLayer
->setContentBounds(IntSize(10, 10));
2551 scrollbarLayer
->setDrawsContent(true);
2552 scrollbarLayer
->setLayerTreeHostImpl(m_hostImpl
.get());
2553 scrollbarLayer
->createResources(m_hostImpl
->resourceProvider());
2554 rootLayer
->addChild(scrollbarLayer
.release());
2556 // Use a context that supports IOSurfaces
2557 m_hostImpl
->initializeRenderer(FakeWebCompositorOutputSurface::create(adoptPtr(new FakeWebGraphicsContext3DWithIOSurface
)), UnthrottledUploader
);
2559 hwVideoFrame
.setTextureId(m_hostImpl
->resourceProvider()->graphicsContext3D()->createTexture());
2561 m_hostImpl
->setRootLayer(rootLayer
.release());
2563 CCLayerTreeHostImpl::FrameData frame
;
2564 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
2565 m_hostImpl
->drawLayers(frame
);
2566 m_hostImpl
->didDrawAllLayers(frame
);
2567 m_hostImpl
->swapBuffers();
2569 unsigned numResources
= m_hostImpl
->resourceProvider()->numResources();
2571 // Lose the context, replacing it with a StrictWebGraphicsContext3DWithIOSurface,
2572 // that will warn if any resource from the previous context gets used.
2573 m_hostImpl
->initializeRenderer(FakeWebCompositorOutputSurface::create(adoptPtr(new StrictWebGraphicsContext3DWithIOSurface
)), UnthrottledUploader
);
2575 // Create dummy resources so that looking up an old resource will get an
2576 // invalid texture id mapping.
2577 for (unsigned i
= 0; i
< numResources
; ++i
)
2578 m_hostImpl
->resourceProvider()->createResourceFromExternalTexture(1);
2580 // The WebVideoFrameProvider is expected to recreate its textures after a
2581 // lost context (or not serve a frame).
2582 hwProvider
.setFrame(0);
2584 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
2585 m_hostImpl
->drawLayers(frame
);
2586 m_hostImpl
->didDrawAllLayers(frame
);
2587 m_hostImpl
->swapBuffers();
2589 hwVideoFrame
.setTextureId(m_hostImpl
->resourceProvider()->graphicsContext3D()->createTexture());
2590 hwProvider
.setFrame(&hwVideoFrame
);
2592 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
2593 m_hostImpl
->drawLayers(frame
);
2594 m_hostImpl
->didDrawAllLayers(frame
);
2595 m_hostImpl
->swapBuffers();
2598 // Fake WebGraphicsContext3D that tracks the number of textures in use.
2599 class TrackingWebGraphicsContext3D
: public FakeWebGraphicsContext3D
{
2601 TrackingWebGraphicsContext3D()
2602 : FakeWebGraphicsContext3D()
2606 virtual WebGLId
createTexture() OVERRIDE
2608 WebGLId id
= FakeWebGraphicsContext3D::createTexture();
2610 m_textures
.set(id
, true);
2615 virtual void deleteTexture(WebGLId id
) OVERRIDE
2617 if (!m_textures
.get(id
))
2620 m_textures
.set(id
, false);
2624 virtual WebString
getString(WGC3Denum name
) OVERRIDE
2626 if (name
== WebCore::GraphicsContext3D::EXTENSIONS
)
2627 return WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2632 unsigned numTextures() const { return m_numTextures
; }
2635 HashMap
<WebGLId
, bool> m_textures
;
2636 unsigned m_numTextures
;
2639 TEST_F(CCLayerTreeHostImplTest
, layersFreeTextures
)
2641 OwnPtr
<CCLayerImpl
> rootLayer(CCLayerImpl::create(1));
2642 rootLayer
->setBounds(IntSize(10, 10));
2643 rootLayer
->setAnchorPoint(FloatPoint(0, 0));
2645 OwnPtr
<CCTiledLayerImpl
> tileLayer
= CCTiledLayerImpl::create(2);
2646 tileLayer
->setBounds(IntSize(10, 10));
2647 tileLayer
->setAnchorPoint(FloatPoint(0, 0));
2648 tileLayer
->setContentBounds(IntSize(10, 10));
2649 tileLayer
->setDrawsContent(true);
2650 tileLayer
->setSkipsDraw(false);
2651 OwnPtr
<CCLayerTilingData
> tilingData(CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels
));
2652 tilingData
->setBounds(IntSize(10, 10));
2653 tileLayer
->setTilingData(*tilingData
);
2654 tileLayer
->pushTileProperties(0, 0, 1, IntRect(0, 0, 10, 10));
2655 rootLayer
->addChild(tileLayer
.release());
2657 OwnPtr
<CCTextureLayerImpl
> textureLayer
= CCTextureLayerImpl::create(3);
2658 textureLayer
->setBounds(IntSize(10, 10));
2659 textureLayer
->setAnchorPoint(FloatPoint(0, 0));
2660 textureLayer
->setContentBounds(IntSize(10, 10));
2661 textureLayer
->setDrawsContent(true);
2662 textureLayer
->setTextureId(1);
2663 rootLayer
->addChild(textureLayer
.release());
2665 FakeVideoFrameProvider provider
;
2666 OwnPtr
<CCVideoLayerImpl
> videoLayer
= CCVideoLayerImpl::create(4, &provider
);
2667 videoLayer
->setBounds(IntSize(10, 10));
2668 videoLayer
->setAnchorPoint(FloatPoint(0, 0));
2669 videoLayer
->setContentBounds(IntSize(10, 10));
2670 videoLayer
->setDrawsContent(true);
2671 videoLayer
->setLayerTreeHostImpl(m_hostImpl
.get());
2672 rootLayer
->addChild(videoLayer
.release());
2674 OwnPtr
<CCIOSurfaceLayerImpl
> ioSurfaceLayer
= CCIOSurfaceLayerImpl::create(5);
2675 ioSurfaceLayer
->setBounds(IntSize(10, 10));
2676 ioSurfaceLayer
->setAnchorPoint(FloatPoint(0, 0));
2677 ioSurfaceLayer
->setContentBounds(IntSize(10, 10));
2678 ioSurfaceLayer
->setDrawsContent(true);
2679 ioSurfaceLayer
->setIOSurfaceProperties(1, IntSize(10, 10));
2680 ioSurfaceLayer
->setLayerTreeHostImpl(m_hostImpl
.get());
2681 rootLayer
->addChild(ioSurfaceLayer
.release());
2683 // Lose the context, replacing it with a TrackingWebGraphicsContext3D (which the CCLayerTreeHostImpl takes ownership of).
2684 OwnPtr
<CCGraphicsContext
> ccContext(FakeWebCompositorOutputSurface::create(adoptPtr(new TrackingWebGraphicsContext3D
)));
2685 TrackingWebGraphicsContext3D
* trackingWebGraphicsContext
= static_cast<TrackingWebGraphicsContext3D
*>(ccContext
->context3D());
2686 m_hostImpl
->initializeRenderer(ccContext
.release(), UnthrottledUploader
);
2688 m_hostImpl
->setRootLayer(rootLayer
.release());
2690 CCLayerTreeHostImpl::FrameData frame
;
2691 EXPECT_TRUE(m_hostImpl
->prepareToDraw(frame
));
2692 m_hostImpl
->drawLayers(frame
);
2693 m_hostImpl
->didDrawAllLayers(frame
);
2694 m_hostImpl
->swapBuffers();
2696 EXPECT_GT(trackingWebGraphicsContext
->numTextures(), 0u);
2698 // Kill the layer tree.
2699 m_hostImpl
->setRootLayer(CCLayerImpl::create(100));
2700 // There should be no textures left in use after.
2701 EXPECT_EQ(0u, trackingWebGraphicsContext
->numTextures());
2704 class MockDrawQuadsToFillScreenContext
: public FakeWebGraphicsContext3D
{
2706 MOCK_METHOD1(useProgram
, void(WebGLId program
));
2707 MOCK_METHOD4(drawElements
, void(WGC3Denum mode
, WGC3Dsizei count
, WGC3Denum type
, WGC3Dintptr offset
));
2710 TEST_F(CCLayerTreeHostImplTest
, hasTransparentBackground
)
2712 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new MockDrawQuadsToFillScreenContext
));
2713 MockDrawQuadsToFillScreenContext
* mockContext
= static_cast<MockDrawQuadsToFillScreenContext
*>(context
->context3D());
2716 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= createLayerTreeHost(false, context
.release(), CCLayerImpl::create(1));
2717 myHostImpl
->setBackgroundColor(SK_ColorWHITE
);
2719 // Verify one quad is drawn when transparent background set is not set.
2720 myHostImpl
->setHasTransparentBackground(false);
2721 EXPECT_CALL(*mockContext
, useProgram(_
))
2723 EXPECT_CALL(*mockContext
, drawElements(_
, _
, _
, _
))
2725 CCLayerTreeHostImpl::FrameData frame
;
2726 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2727 myHostImpl
->drawLayers(frame
);
2728 myHostImpl
->didDrawAllLayers(frame
);
2729 Mock::VerifyAndClearExpectations(&mockContext
);
2731 // Verify no quads are drawn when transparent background is set.
2732 myHostImpl
->setHasTransparentBackground(true);
2733 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2734 myHostImpl
->drawLayers(frame
);
2735 myHostImpl
->didDrawAllLayers(frame
);
2736 Mock::VerifyAndClearExpectations(&mockContext
);
2739 static void addDrawingLayerTo(CCLayerImpl
* parent
, int id
, const IntRect
& layerRect
, CCLayerImpl
** result
)
2741 OwnPtr
<CCLayerImpl
> layer
= FakeLayerWithQuads::create(id
);
2742 CCLayerImpl
* layerPtr
= layer
.get();
2743 layerPtr
->setAnchorPoint(FloatPoint(0, 0));
2744 layerPtr
->setPosition(FloatPoint(layerRect
.location()));
2745 layerPtr
->setBounds(layerRect
.size());
2746 layerPtr
->setContentBounds(layerRect
.size());
2747 layerPtr
->setDrawsContent(true); // only children draw content
2748 layerPtr
->setOpaque(true);
2749 parent
->addChild(layer
.release());
2754 static void setupLayersForTextureCaching(CCLayerTreeHostImpl
* layerTreeHostImpl
, CCLayerImpl
*& rootPtr
, CCLayerImpl
*& intermediateLayerPtr
, CCLayerImpl
*& surfaceLayerPtr
, CCLayerImpl
*& childPtr
, const IntSize
& rootSize
)
2756 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
2758 layerTreeHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
2759 layerTreeHostImpl
->setViewportSize(rootSize
, rootSize
);
2761 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
2762 rootPtr
= root
.get();
2764 root
->setAnchorPoint(FloatPoint(0, 0));
2765 root
->setPosition(FloatPoint(0, 0));
2766 root
->setBounds(rootSize
);
2767 root
->setContentBounds(rootSize
);
2768 root
->setDrawsContent(true);
2769 layerTreeHostImpl
->setRootLayer(root
.release());
2771 addDrawingLayerTo(rootPtr
, 2, IntRect(10, 10, rootSize
.width(), rootSize
.height()), &intermediateLayerPtr
);
2772 intermediateLayerPtr
->setDrawsContent(false); // only children draw content
2774 // Surface layer is the layer that changes its opacity
2775 // It will contain other layers that draw content.
2776 addDrawingLayerTo(intermediateLayerPtr
, 3, IntRect(10, 10, rootSize
.width(), rootSize
.height()), &surfaceLayerPtr
);
2777 surfaceLayerPtr
->setDrawsContent(false); // only children draw content
2778 surfaceLayerPtr
->setOpacity(0.5f
); // This will cause it to have a surface
2780 // Child of the surface layer will produce some quads
2781 addDrawingLayerTo(surfaceLayerPtr
, 4, IntRect(5, 5, rootSize
.width() - 25, rootSize
.height() - 25), &childPtr
);
2784 class CCRendererGLWithReleaseTextures
: public CCRendererGL
{
2786 using CCRendererGL::releaseRenderPassTextures
;
2789 TEST_F(CCLayerTreeHostImplTest
, textureCachingWithClipping
)
2791 CCSettings::setPartialSwapEnabled(true);
2793 CCLayerTreeSettings settings
;
2794 settings
.minimumOcclusionTrackingSize
= IntSize();
2795 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
2797 CCLayerImpl
* rootPtr
;
2798 CCLayerImpl
* surfaceLayerPtr
;
2800 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
2802 IntSize
rootSize(100, 100);
2804 myHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
2805 myHostImpl
->setViewportSize(IntSize(rootSize
.width(), rootSize
.height()), IntSize(rootSize
.width(), rootSize
.height()));
2807 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
2808 rootPtr
= root
.get();
2810 root
->setAnchorPoint(FloatPoint(0, 0));
2811 root
->setPosition(FloatPoint(0, 0));
2812 root
->setBounds(rootSize
);
2813 root
->setContentBounds(rootSize
);
2814 root
->setDrawsContent(true);
2815 root
->setMasksToBounds(true);
2816 myHostImpl
->setRootLayer(root
.release());
2818 addDrawingLayerTo(rootPtr
, 3, IntRect(0, 0, rootSize
.width(), rootSize
.height()), &surfaceLayerPtr
);
2819 surfaceLayerPtr
->setDrawsContent(false);
2821 // Surface layer is the layer that changes its opacity
2822 // It will contain other layers that draw content.
2823 surfaceLayerPtr
->setOpacity(0.5f
); // This will cause it to have a surface
2825 addDrawingLayerTo(surfaceLayerPtr
, 4, IntRect(0, 0, 100, 3), 0);
2826 addDrawingLayerTo(surfaceLayerPtr
, 5, IntRect(0, 97, 100, 3), 0);
2828 // Rotation will put part of the child ouside the bounds of the root layer.
2829 // Nevertheless, the child layers should be drawn.
2830 WebTransformationMatrix transform
= surfaceLayerPtr
->transform();
2831 transform
.translate(50, 50);
2832 transform
.rotate(35);
2833 transform
.translate(-50, -50);
2834 surfaceLayerPtr
->setTransform(transform
);
2837 CCLayerTreeHostImpl::FrameData frame
;
2838 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2840 // Must receive two render passes, each with one quad
2841 ASSERT_EQ(2U, frame
.renderPasses
.size());
2842 EXPECT_EQ(2U, frame
.renderPasses
[0]->quadList().size());
2843 ASSERT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
2845 // Verify that the child layers are being clipped.
2846 IntRect quadVisibleRect
= frame
.renderPasses
[0]->quadList()[0]->quadVisibleRect();
2847 EXPECT_LT(quadVisibleRect
.width(), 100);
2849 quadVisibleRect
= frame
.renderPasses
[0]->quadList()[1]->quadVisibleRect();
2850 EXPECT_LT(quadVisibleRect
.width(), 100);
2852 // Verify that the render surface texture is *not* clipped.
2853 EXPECT_RECT_EQ(IntRect(0, 0, 100, 100), frame
.renderPasses
[0]->outputRect());
2855 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
2856 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[1]->quadList()[0].get());
2857 EXPECT_FALSE(quad
->contentsChangedSinceLastFrame().isEmpty());
2859 myHostImpl
->drawLayers(frame
);
2860 myHostImpl
->didDrawAllLayers(frame
);
2863 transform
= surfaceLayerPtr
->transform();
2864 transform
.translate(50, 50);
2865 transform
.rotate(-35);
2866 transform
.translate(-50, -50);
2867 surfaceLayerPtr
->setTransform(transform
);
2869 // The surface is now aligned again, and the clipped parts are exposed.
2870 // Since the layers were clipped, even though the render surface size
2871 // was not changed, the texture should not be saved.
2873 CCLayerTreeHostImpl::FrameData frame
;
2874 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2876 // Must receive two render passes, each with one quad
2877 ASSERT_EQ(2U, frame
.renderPasses
.size());
2878 EXPECT_EQ(2U, frame
.renderPasses
[0]->quadList().size());
2879 ASSERT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
2881 myHostImpl
->drawLayers(frame
);
2882 myHostImpl
->didDrawAllLayers(frame
);
2886 TEST_F(CCLayerTreeHostImplTest
, textureCachingWithOcclusion
)
2888 CCSettings::setPartialSwapEnabled(false);
2890 CCLayerTreeSettings settings
;
2891 settings
.minimumOcclusionTrackingSize
= IntSize();
2892 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
2894 // Layers are structure as follows:
2896 // R +-- S1 +- L10 (owning)
2900 // +-- S2 +- L20 (owning)
2904 // L12 occludes L11 (internal)
2905 // L20 occludes L10 (external)
2906 // L21 occludes L20 (internal)
2908 CCLayerImpl
* rootPtr
;
2909 CCLayerImpl
* layerS1Ptr
;
2910 CCLayerImpl
* layerS2Ptr
;
2912 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
2914 IntSize
rootSize(1000, 1000);
2916 myHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
2917 myHostImpl
->setViewportSize(IntSize(rootSize
.width(), rootSize
.height()), IntSize(rootSize
.width(), rootSize
.height()));
2919 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
2920 rootPtr
= root
.get();
2922 root
->setAnchorPoint(FloatPoint(0, 0));
2923 root
->setPosition(FloatPoint(0, 0));
2924 root
->setBounds(rootSize
);
2925 root
->setContentBounds(rootSize
);
2926 root
->setDrawsContent(true);
2927 root
->setMasksToBounds(true);
2928 myHostImpl
->setRootLayer(root
.release());
2930 addDrawingLayerTo(rootPtr
, 2, IntRect(300, 300, 300, 300), &layerS1Ptr
);
2931 layerS1Ptr
->setForceRenderSurface(true);
2933 addDrawingLayerTo(layerS1Ptr
, 3, IntRect(10, 10, 10, 10), 0); // L11
2934 addDrawingLayerTo(layerS1Ptr
, 4, IntRect(0, 0, 30, 30), 0); // L12
2936 addDrawingLayerTo(rootPtr
, 5, IntRect(550, 250, 300, 400), &layerS2Ptr
);
2937 layerS2Ptr
->setForceRenderSurface(true);
2939 addDrawingLayerTo(layerS2Ptr
, 6, IntRect(20, 20, 5, 5), 0); // L21
2941 // Initial draw - must receive all quads
2943 CCLayerTreeHostImpl::FrameData frame
;
2944 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2946 // Must receive 3 render passes.
2947 // For Root, there are 2 quads; for S1, there are 2 quads (1 is occluded); for S2, there is 2 quads.
2948 ASSERT_EQ(3U, frame
.renderPasses
.size());
2950 EXPECT_EQ(2U, frame
.renderPasses
[0]->quadList().size());
2951 EXPECT_EQ(2U, frame
.renderPasses
[1]->quadList().size());
2952 EXPECT_EQ(2U, frame
.renderPasses
[2]->quadList().size());
2954 myHostImpl
->drawLayers(frame
);
2955 myHostImpl
->didDrawAllLayers(frame
);
2958 // "Unocclude" surface S1 and repeat draw.
2959 // Must remove S2's render pass since it's cached;
2960 // Must keep S1 quads because texture contained external occlusion.
2961 WebTransformationMatrix transform
= layerS2Ptr
->transform();
2962 transform
.translate(150, 150);
2963 layerS2Ptr
->setTransform(transform
);
2965 CCLayerTreeHostImpl::FrameData frame
;
2966 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2968 // Must receive 2 render passes.
2969 // For Root, there are 2 quads
2970 // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
2971 // For S2, there is no render pass
2972 ASSERT_EQ(2U, frame
.renderPasses
.size());
2974 EXPECT_GT(frame
.renderPasses
[0]->quadList().size(), 0U);
2975 EXPECT_EQ(2U, frame
.renderPasses
[1]->quadList().size());
2977 myHostImpl
->drawLayers(frame
);
2978 myHostImpl
->didDrawAllLayers(frame
);
2981 // "Re-occlude" surface S1 and repeat draw.
2982 // Must remove S1's render pass since it is now available in full.
2983 // S2 has no change so must also be removed.
2984 transform
= layerS2Ptr
->transform();
2985 transform
.translate(-15, -15);
2986 layerS2Ptr
->setTransform(transform
);
2988 CCLayerTreeHostImpl::FrameData frame
;
2989 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
2991 // Must receive 1 render pass - for the root.
2992 ASSERT_EQ(1U, frame
.renderPasses
.size());
2994 EXPECT_EQ(2U, frame
.renderPasses
[0]->quadList().size());
2996 myHostImpl
->drawLayers(frame
);
2997 myHostImpl
->didDrawAllLayers(frame
);
3002 TEST_F(CCLayerTreeHostImplTest
, textureCachingWithOcclusionEarlyOut
)
3004 CCSettings::setPartialSwapEnabled(false);
3006 CCLayerTreeSettings settings
;
3007 settings
.minimumOcclusionTrackingSize
= IntSize();
3008 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
3010 // Layers are structure as follows:
3012 // R +-- S1 +- L10 (owning, non drawing)
3013 // | +- L11 (corner, unoccluded)
3014 // | +- L12 (corner, unoccluded)
3015 // | +- L13 (corner, unoccluded)
3016 // | +- L14 (corner, entirely occluded)
3018 // +-- S2 +- L20 (owning, drawing)
3021 CCLayerImpl
* rootPtr
;
3022 CCLayerImpl
* layerS1Ptr
;
3023 CCLayerImpl
* layerS2Ptr
;
3025 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
3027 IntSize
rootSize(1000, 1000);
3029 myHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
3030 myHostImpl
->setViewportSize(IntSize(rootSize
.width(), rootSize
.height()), IntSize(rootSize
.width(), rootSize
.height()));
3032 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
3033 rootPtr
= root
.get();
3035 root
->setAnchorPoint(FloatPoint(0, 0));
3036 root
->setPosition(FloatPoint(0, 0));
3037 root
->setBounds(rootSize
);
3038 root
->setContentBounds(rootSize
);
3039 root
->setDrawsContent(true);
3040 root
->setMasksToBounds(true);
3041 myHostImpl
->setRootLayer(root
.release());
3043 addDrawingLayerTo(rootPtr
, 2, IntRect(0, 0, 800, 800), &layerS1Ptr
);
3044 layerS1Ptr
->setForceRenderSurface(true);
3045 layerS1Ptr
->setDrawsContent(false);
3047 addDrawingLayerTo(layerS1Ptr
, 3, IntRect(0, 0, 300, 300), 0); // L11
3048 addDrawingLayerTo(layerS1Ptr
, 4, IntRect(0, 500, 300, 300), 0); // L12
3049 addDrawingLayerTo(layerS1Ptr
, 5, IntRect(500, 0, 300, 300), 0); // L13
3050 addDrawingLayerTo(layerS1Ptr
, 6, IntRect(500, 500, 300, 300), 0); // L14
3051 addDrawingLayerTo(layerS1Ptr
, 9, IntRect(500, 500, 300, 300), 0); // L14
3053 addDrawingLayerTo(rootPtr
, 7, IntRect(450, 450, 450, 450), &layerS2Ptr
);
3054 layerS2Ptr
->setForceRenderSurface(true);
3056 // Initial draw - must receive all quads
3058 CCLayerTreeHostImpl::FrameData frame
;
3059 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3061 // Must receive 3 render passes.
3062 // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is 1 quad.
3063 ASSERT_EQ(3U, frame
.renderPasses
.size());
3065 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3067 // L14 is culled, so only 3 quads.
3068 EXPECT_EQ(3U, frame
.renderPasses
[1]->quadList().size());
3069 EXPECT_EQ(2U, frame
.renderPasses
[2]->quadList().size());
3071 myHostImpl
->drawLayers(frame
);
3072 myHostImpl
->didDrawAllLayers(frame
);
3075 // "Unocclude" surface S1 and repeat draw.
3076 // Must remove S2's render pass since it's cached;
3077 // Must keep S1 quads because texture contained external occlusion.
3078 WebTransformationMatrix transform
= layerS2Ptr
->transform();
3079 transform
.translate(100, 100);
3080 layerS2Ptr
->setTransform(transform
);
3082 CCLayerTreeHostImpl::FrameData frame
;
3083 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3085 // Must receive 2 render passes.
3086 // For Root, there are 2 quads
3087 // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
3088 // For S2, there is no render pass
3089 ASSERT_EQ(2U, frame
.renderPasses
.size());
3091 EXPECT_GT(frame
.renderPasses
[0]->quadList().size(), 0U);
3092 EXPECT_EQ(2U, frame
.renderPasses
[1]->quadList().size());
3094 myHostImpl
->drawLayers(frame
);
3095 myHostImpl
->didDrawAllLayers(frame
);
3098 // "Re-occlude" surface S1 and repeat draw.
3099 // Must remove S1's render pass since it is now available in full.
3100 // S2 has no change so must also be removed.
3101 transform
= layerS2Ptr
->transform();
3102 transform
.translate(-15, -15);
3103 layerS2Ptr
->setTransform(transform
);
3105 CCLayerTreeHostImpl::FrameData frame
;
3106 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3108 // Must receive 1 render pass - for the root.
3109 ASSERT_EQ(1U, frame
.renderPasses
.size());
3111 EXPECT_EQ(2U, frame
.renderPasses
[0]->quadList().size());
3113 myHostImpl
->drawLayers(frame
);
3114 myHostImpl
->didDrawAllLayers(frame
);
3118 TEST_F(CCLayerTreeHostImplTest
, textureCachingWithOcclusionExternalOverInternal
)
3120 CCSettings::setPartialSwapEnabled(false);
3122 CCLayerTreeSettings settings
;
3123 settings
.minimumOcclusionTrackingSize
= IntSize();
3124 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
3126 // Layers are structured as follows:
3128 // R +-- S1 +- L10 (owning, drawing)
3129 // | +- L11 (corner, occluded by L12)
3130 // | +- L12 (opposite corner)
3132 // +-- S2 +- L20 (owning, drawing)
3135 CCLayerImpl
* rootPtr
;
3136 CCLayerImpl
* layerS1Ptr
;
3137 CCLayerImpl
* layerS2Ptr
;
3139 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
3141 IntSize
rootSize(1000, 1000);
3143 myHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
3144 myHostImpl
->setViewportSize(IntSize(rootSize
.width(), rootSize
.height()), IntSize(rootSize
.width(), rootSize
.height()));
3146 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
3147 rootPtr
= root
.get();
3149 root
->setAnchorPoint(FloatPoint(0, 0));
3150 root
->setPosition(FloatPoint(0, 0));
3151 root
->setBounds(rootSize
);
3152 root
->setContentBounds(rootSize
);
3153 root
->setDrawsContent(true);
3154 root
->setMasksToBounds(true);
3155 myHostImpl
->setRootLayer(root
.release());
3157 addDrawingLayerTo(rootPtr
, 2, IntRect(0, 0, 400, 400), &layerS1Ptr
);
3158 layerS1Ptr
->setForceRenderSurface(true);
3160 addDrawingLayerTo(layerS1Ptr
, 3, IntRect(0, 0, 300, 300), 0); // L11
3161 addDrawingLayerTo(layerS1Ptr
, 4, IntRect(100, 0, 300, 300), 0); // L12
3163 addDrawingLayerTo(rootPtr
, 7, IntRect(200, 0, 300, 300), &layerS2Ptr
);
3164 layerS2Ptr
->setForceRenderSurface(true);
3166 // Initial draw - must receive all quads
3168 CCLayerTreeHostImpl::FrameData frame
;
3169 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3171 // Must receive 3 render passes.
3172 // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is 1 quad.
3173 ASSERT_EQ(3U, frame
.renderPasses
.size());
3175 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3176 EXPECT_EQ(3U, frame
.renderPasses
[1]->quadList().size());
3177 EXPECT_EQ(2U, frame
.renderPasses
[2]->quadList().size());
3179 myHostImpl
->drawLayers(frame
);
3180 myHostImpl
->didDrawAllLayers(frame
);
3183 // "Unocclude" surface S1 and repeat draw.
3184 // Must remove S2's render pass since it's cached;
3185 // Must keep S1 quads because texture contained external occlusion.
3186 WebTransformationMatrix transform
= layerS2Ptr
->transform();
3187 transform
.translate(300, 0);
3188 layerS2Ptr
->setTransform(transform
);
3190 CCLayerTreeHostImpl::FrameData frame
;
3191 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3193 // Must receive 2 render passes.
3194 // For Root, there are 2 quads
3195 // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
3196 // For S2, there is no render pass
3197 ASSERT_EQ(2U, frame
.renderPasses
.size());
3199 EXPECT_GT(frame
.renderPasses
[0]->quadList().size(), 0U);
3200 EXPECT_EQ(2U, frame
.renderPasses
[1]->quadList().size());
3202 myHostImpl
->drawLayers(frame
);
3203 myHostImpl
->didDrawAllLayers(frame
);
3207 TEST_F(CCLayerTreeHostImplTest
, textureCachingWithOcclusionExternalNotAligned
)
3209 CCSettings::setPartialSwapEnabled(false);
3211 CCLayerTreeSettings settings
;
3212 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
3214 // Layers are structured as follows:
3216 // R +-- S1 +- L10 (rotated, drawing)
3217 // +- L11 (occupies half surface)
3219 CCLayerImpl
* rootPtr
;
3220 CCLayerImpl
* layerS1Ptr
;
3222 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
3224 IntSize
rootSize(1000, 1000);
3226 myHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
3227 myHostImpl
->setViewportSize(IntSize(rootSize
.width(), rootSize
.height()), IntSize(rootSize
.width(), rootSize
.height()));
3229 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
3230 rootPtr
= root
.get();
3232 root
->setAnchorPoint(FloatPoint(0, 0));
3233 root
->setPosition(FloatPoint(0, 0));
3234 root
->setBounds(rootSize
);
3235 root
->setContentBounds(rootSize
);
3236 root
->setDrawsContent(true);
3237 root
->setMasksToBounds(true);
3238 myHostImpl
->setRootLayer(root
.release());
3240 addDrawingLayerTo(rootPtr
, 2, IntRect(0, 0, 400, 400), &layerS1Ptr
);
3241 layerS1Ptr
->setForceRenderSurface(true);
3242 WebTransformationMatrix transform
= layerS1Ptr
->transform();
3243 transform
.translate(200, 200);
3244 transform
.rotate(45);
3245 transform
.translate(-200, -200);
3246 layerS1Ptr
->setTransform(transform
);
3248 addDrawingLayerTo(layerS1Ptr
, 3, IntRect(200, 0, 200, 400), 0); // L11
3250 // Initial draw - must receive all quads
3252 CCLayerTreeHostImpl::FrameData frame
;
3253 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3255 // Must receive 2 render passes.
3256 ASSERT_EQ(2U, frame
.renderPasses
.size());
3258 EXPECT_EQ(2U, frame
.renderPasses
[0]->quadList().size());
3259 EXPECT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
3261 myHostImpl
->drawLayers(frame
);
3262 myHostImpl
->didDrawAllLayers(frame
);
3265 // Change opacity and draw. Verify we used cached texture.
3266 layerS1Ptr
->setOpacity(0.2f
);
3268 CCLayerTreeHostImpl::FrameData frame
;
3269 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3271 // One render pass must be gone due to cached texture.
3272 ASSERT_EQ(1U, frame
.renderPasses
.size());
3274 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3276 myHostImpl
->drawLayers(frame
);
3277 myHostImpl
->didDrawAllLayers(frame
);
3281 TEST_F(CCLayerTreeHostImplTest
, textureCachingWithOcclusionPartialSwap
)
3283 CCSettings::setPartialSwapEnabled(true);
3285 CCLayerTreeSettings settings
;
3286 settings
.minimumOcclusionTrackingSize
= IntSize();
3287 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
3289 // Layers are structure as follows:
3291 // R +-- S1 +- L10 (owning)
3295 // +-- S2 +- L20 (owning)
3299 // L12 occludes L11 (internal)
3300 // L20 occludes L10 (external)
3301 // L21 occludes L20 (internal)
3303 CCLayerImpl
* rootPtr
;
3304 CCLayerImpl
* layerS1Ptr
;
3305 CCLayerImpl
* layerS2Ptr
;
3307 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
3309 IntSize
rootSize(1000, 1000);
3311 myHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
3312 myHostImpl
->setViewportSize(IntSize(rootSize
.width(), rootSize
.height()), IntSize(rootSize
.width(), rootSize
.height()));
3314 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
3315 rootPtr
= root
.get();
3317 root
->setAnchorPoint(FloatPoint(0, 0));
3318 root
->setPosition(FloatPoint(0, 0));
3319 root
->setBounds(rootSize
);
3320 root
->setContentBounds(rootSize
);
3321 root
->setDrawsContent(true);
3322 root
->setMasksToBounds(true);
3323 myHostImpl
->setRootLayer(root
.release());
3325 addDrawingLayerTo(rootPtr
, 2, IntRect(300, 300, 300, 300), &layerS1Ptr
);
3326 layerS1Ptr
->setForceRenderSurface(true);
3328 addDrawingLayerTo(layerS1Ptr
, 3, IntRect(10, 10, 10, 10), 0); // L11
3329 addDrawingLayerTo(layerS1Ptr
, 4, IntRect(0, 0, 30, 30), 0); // L12
3331 addDrawingLayerTo(rootPtr
, 5, IntRect(550, 250, 300, 400), &layerS2Ptr
);
3332 layerS2Ptr
->setForceRenderSurface(true);
3334 addDrawingLayerTo(layerS2Ptr
, 6, IntRect(20, 20, 5, 5), 0); // L21
3336 // Initial draw - must receive all quads
3338 CCLayerTreeHostImpl::FrameData frame
;
3339 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3341 // Must receive 3 render passes.
3342 // For Root, there are 2 quads; for S1, there are 2 quads (one is occluded); for S2, there is 2 quads.
3343 ASSERT_EQ(3U, frame
.renderPasses
.size());
3345 EXPECT_EQ(2U, frame
.renderPasses
[0]->quadList().size());
3346 EXPECT_EQ(2U, frame
.renderPasses
[1]->quadList().size());
3347 EXPECT_EQ(2U, frame
.renderPasses
[2]->quadList().size());
3349 myHostImpl
->drawLayers(frame
);
3350 myHostImpl
->didDrawAllLayers(frame
);
3353 // "Unocclude" surface S1 and repeat draw.
3354 // Must remove S2's render pass since it's cached;
3355 // Must keep S1 quads because texture contained external occlusion.
3356 WebTransformationMatrix transform
= layerS2Ptr
->transform();
3357 transform
.translate(150, 150);
3358 layerS2Ptr
->setTransform(transform
);
3360 CCLayerTreeHostImpl::FrameData frame
;
3361 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3363 // Must receive 2 render passes.
3364 // For Root, there are 2 quads.
3365 // For S1, there are 2 quads.
3366 // For S2, there is no render pass
3367 ASSERT_EQ(2U, frame
.renderPasses
.size());
3369 EXPECT_EQ(2U, frame
.renderPasses
[0]->quadList().size());
3370 EXPECT_EQ(2U, frame
.renderPasses
[1]->quadList().size());
3372 myHostImpl
->drawLayers(frame
);
3373 myHostImpl
->didDrawAllLayers(frame
);
3376 // "Re-occlude" surface S1 and repeat draw.
3377 // Must remove S1's render pass since it is now available in full.
3378 // S2 has no change so must also be removed.
3379 transform
= layerS2Ptr
->transform();
3380 transform
.translate(-15, -15);
3381 layerS2Ptr
->setTransform(transform
);
3383 CCLayerTreeHostImpl::FrameData frame
;
3384 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3386 // Root render pass only.
3387 ASSERT_EQ(1U, frame
.renderPasses
.size());
3389 myHostImpl
->drawLayers(frame
);
3390 myHostImpl
->didDrawAllLayers(frame
);
3394 TEST_F(CCLayerTreeHostImplTest
, textureCachingWithScissor
)
3396 CCSettings::setPartialSwapEnabled(false);
3398 CCLayerTreeSettings settings
;
3399 settings
.minimumOcclusionTrackingSize
= IntSize();
3400 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
3403 Layers are created as follows:
3405 +--------------------+
3409 | | +-------------------+
3411 | | +-------------------+
3416 +--------------------+
3418 Layers 1, 2 have render surfaces
3420 OwnPtr
<CCLayerImpl
> root
= CCLayerImpl::create(1);
3421 OwnPtr
<CCTiledLayerImpl
> child
= CCTiledLayerImpl::create(2);
3422 OwnPtr
<CCLayerImpl
> grandChild
= CCLayerImpl::create(3);
3424 IntRect
rootRect(0, 0, 100, 100);
3425 IntRect
childRect(10, 10, 50, 50);
3426 IntRect
grandChildRect(5, 5, 150, 150);
3428 OwnPtr
<CCGraphicsContext
> context
= FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext
));
3429 myHostImpl
->initializeRenderer(context
.release(), UnthrottledUploader
);
3431 root
->setAnchorPoint(FloatPoint(0, 0));
3432 root
->setPosition(FloatPoint(rootRect
.x(), rootRect
.y()));
3433 root
->setBounds(IntSize(rootRect
.width(), rootRect
.height()));
3434 root
->setContentBounds(root
->bounds());
3435 root
->setDrawsContent(true);
3436 root
->setMasksToBounds(true);
3438 child
->setAnchorPoint(FloatPoint(0, 0));
3439 child
->setPosition(FloatPoint(childRect
.x(), childRect
.y()));
3440 child
->setOpacity(0.5);
3441 child
->setBounds(IntSize(childRect
.width(), childRect
.height()));
3442 child
->setContentBounds(child
->bounds());
3443 child
->setDrawsContent(true);
3444 child
->setSkipsDraw(false);
3446 // child layer has 10x10 tiles.
3447 OwnPtr
<CCLayerTilingData
> tiler
= CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::HasBorderTexels
);
3448 tiler
->setBounds(child
->contentBounds());
3449 child
->setTilingData(*tiler
.get());
3451 grandChild
->setAnchorPoint(FloatPoint(0, 0));
3452 grandChild
->setPosition(IntPoint(grandChildRect
.x(), grandChildRect
.y()));
3453 grandChild
->setBounds(IntSize(grandChildRect
.width(), grandChildRect
.height()));
3454 grandChild
->setContentBounds(grandChild
->bounds());
3455 grandChild
->setDrawsContent(true);
3457 CCTiledLayerImpl
* childPtr
= child
.get();
3458 CCRenderPass::Id
childPassId(childPtr
->id(), 0);
3460 child
->addChild(grandChild
.release());
3461 root
->addChild(child
.release());
3462 myHostImpl
->setRootLayer(root
.release());
3463 myHostImpl
->setViewportSize(rootRect
.size(), rootRect
.size());
3465 EXPECT_FALSE(myHostImpl
->renderer()->haveCachedResourcesForRenderPassId(childPassId
));
3468 CCLayerTreeHostImpl::FrameData frame
;
3469 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3470 myHostImpl
->drawLayers(frame
);
3471 myHostImpl
->didDrawAllLayers(frame
);
3474 // We should have cached textures for surface 2.
3475 EXPECT_TRUE(myHostImpl
->renderer()->haveCachedResourcesForRenderPassId(childPassId
));
3478 CCLayerTreeHostImpl::FrameData frame
;
3479 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3480 myHostImpl
->drawLayers(frame
);
3481 myHostImpl
->didDrawAllLayers(frame
);
3484 // We should still have cached textures for surface 2 after drawing with no damage.
3485 EXPECT_TRUE(myHostImpl
->renderer()->haveCachedResourcesForRenderPassId(childPassId
));
3487 // Damage a single tile of surface 2.
3488 childPtr
->setUpdateRect(IntRect(10, 10, 10, 10));
3491 CCLayerTreeHostImpl::FrameData frame
;
3492 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3493 myHostImpl
->drawLayers(frame
);
3494 myHostImpl
->didDrawAllLayers(frame
);
3497 // We should have a cached texture for surface 2 again even though it was damaged.
3498 EXPECT_TRUE(myHostImpl
->renderer()->haveCachedResourcesForRenderPassId(childPassId
));
3501 TEST_F(CCLayerTreeHostImplTest
, surfaceTextureCaching
)
3503 CCSettings::setPartialSwapEnabled(true);
3505 CCLayerTreeSettings settings
;
3506 settings
.minimumOcclusionTrackingSize
= IntSize();
3507 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
3509 CCLayerImpl
* rootPtr
;
3510 CCLayerImpl
* intermediateLayerPtr
;
3511 CCLayerImpl
* surfaceLayerPtr
;
3512 CCLayerImpl
* childPtr
;
3514 setupLayersForTextureCaching(myHostImpl
.get(), rootPtr
, intermediateLayerPtr
, surfaceLayerPtr
, childPtr
, IntSize(100, 100));
3517 CCLayerTreeHostImpl::FrameData frame
;
3518 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3520 // Must receive two render passes, each with one quad
3521 ASSERT_EQ(2U, frame
.renderPasses
.size());
3522 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3523 EXPECT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
3525 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
3526 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[1]->quadList()[0].get());
3527 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3528 EXPECT_FALSE(targetPass
->damageRect().isEmpty());
3530 myHostImpl
->drawLayers(frame
);
3531 myHostImpl
->didDrawAllLayers(frame
);
3534 // Draw without any change
3536 CCLayerTreeHostImpl::FrameData frame
;
3537 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3539 // Must receive one render pass, as the other one should be culled
3540 ASSERT_EQ(1U, frame
.renderPasses
.size());
3542 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3543 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[0]->quadList()[0]->material());
3544 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[0]->quadList()[0].get());
3545 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3546 EXPECT_TRUE(targetPass
->damageRect().isEmpty());
3548 myHostImpl
->drawLayers(frame
);
3549 myHostImpl
->didDrawAllLayers(frame
);
3552 // Change opacity and draw
3553 surfaceLayerPtr
->setOpacity(0.6f
);
3555 CCLayerTreeHostImpl::FrameData frame
;
3556 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3558 // Must receive one render pass, as the other one should be culled
3559 ASSERT_EQ(1U, frame
.renderPasses
.size());
3561 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3562 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[0]->quadList()[0]->material());
3563 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[0]->quadList()[0].get());
3564 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3565 EXPECT_TRUE(targetPass
->damageRect().isEmpty());
3567 myHostImpl
->drawLayers(frame
);
3568 myHostImpl
->didDrawAllLayers(frame
);
3571 // Change less benign property and draw - should have contents changed flag
3572 surfaceLayerPtr
->setStackingOrderChanged(true);
3574 CCLayerTreeHostImpl::FrameData frame
;
3575 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3577 // Must receive two render passes, each with one quad
3578 ASSERT_EQ(2U, frame
.renderPasses
.size());
3580 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3581 EXPECT_EQ(CCDrawQuad::SolidColor
, frame
.renderPasses
[0]->quadList()[0]->material());
3583 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
3584 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[1]->quadList()[0].get());
3585 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3586 EXPECT_FALSE(targetPass
->damageRect().isEmpty());
3588 myHostImpl
->drawLayers(frame
);
3589 myHostImpl
->didDrawAllLayers(frame
);
3592 // Change opacity again, and evict the cached surface texture.
3593 surfaceLayerPtr
->setOpacity(0.5f
);
3594 static_cast<CCRendererGLWithReleaseTextures
*>(myHostImpl
->renderer())->releaseRenderPassTextures();
3596 // Change opacity and draw
3597 surfaceLayerPtr
->setOpacity(0.6f
);
3599 CCLayerTreeHostImpl::FrameData frame
;
3600 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3602 // Must receive two render passes
3603 ASSERT_EQ(2U, frame
.renderPasses
.size());
3605 // Even though not enough properties changed, the entire thing must be
3606 // redrawn as we don't have cached textures
3607 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3608 EXPECT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
3610 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
3611 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[1]->quadList()[0].get());
3612 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3613 EXPECT_TRUE(targetPass
->damageRect().isEmpty());
3615 // Was our surface evicted?
3616 EXPECT_FALSE(myHostImpl
->renderer()->haveCachedResourcesForRenderPassId(targetPass
->id()));
3618 myHostImpl
->drawLayers(frame
);
3619 myHostImpl
->didDrawAllLayers(frame
);
3622 // Draw without any change, to make sure the state is clear
3624 CCLayerTreeHostImpl::FrameData frame
;
3625 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3627 // Must receive one render pass, as the other one should be culled
3628 ASSERT_EQ(1U, frame
.renderPasses
.size());
3630 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3631 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[0]->quadList()[0]->material());
3632 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[0]->quadList()[0].get());
3633 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3634 EXPECT_TRUE(targetPass
->damageRect().isEmpty());
3636 myHostImpl
->drawLayers(frame
);
3637 myHostImpl
->didDrawAllLayers(frame
);
3640 // Change opacity on the intermediate layer
3641 WebTransformationMatrix transform
= intermediateLayerPtr
->transform();
3642 transform
.setM11(1.0001);
3643 intermediateLayerPtr
->setTransform(transform
);
3645 CCLayerTreeHostImpl::FrameData frame
;
3646 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3648 // Must receive one render pass, as the other one should be culled.
3649 ASSERT_EQ(1U, frame
.renderPasses
.size());
3650 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3652 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[0]->quadList()[0]->material());
3653 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[0]->quadList()[0].get());
3654 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3655 EXPECT_TRUE(targetPass
->damageRect().isEmpty());
3657 myHostImpl
->drawLayers(frame
);
3658 myHostImpl
->didDrawAllLayers(frame
);
3662 TEST_F(CCLayerTreeHostImplTest
, surfaceTextureCachingNoPartialSwap
)
3664 CCSettings::setPartialSwapEnabled(false);
3666 CCLayerTreeSettings settings
;
3667 settings
.minimumOcclusionTrackingSize
= IntSize();
3668 OwnPtr
<CCLayerTreeHostImpl
> myHostImpl
= CCLayerTreeHostImpl::create(settings
, this);
3670 CCLayerImpl
* rootPtr
;
3671 CCLayerImpl
* intermediateLayerPtr
;
3672 CCLayerImpl
* surfaceLayerPtr
;
3673 CCLayerImpl
* childPtr
;
3675 setupLayersForTextureCaching(myHostImpl
.get(), rootPtr
, intermediateLayerPtr
, surfaceLayerPtr
, childPtr
, IntSize(100, 100));
3678 CCLayerTreeHostImpl::FrameData frame
;
3679 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3681 // Must receive two render passes, each with one quad
3682 ASSERT_EQ(2U, frame
.renderPasses
.size());
3683 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3684 EXPECT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
3686 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
3687 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[1]->quadList()[0].get());
3688 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3689 EXPECT_FALSE(targetPass
->damageRect().isEmpty());
3691 EXPECT_FALSE(frame
.renderPasses
[0]->damageRect().isEmpty());
3692 EXPECT_FALSE(frame
.renderPasses
[1]->damageRect().isEmpty());
3694 EXPECT_FALSE(frame
.renderPasses
[0]->hasOcclusionFromOutsideTargetSurface());
3695 EXPECT_FALSE(frame
.renderPasses
[1]->hasOcclusionFromOutsideTargetSurface());
3697 myHostImpl
->drawLayers(frame
);
3698 myHostImpl
->didDrawAllLayers(frame
);
3701 // Draw without any change
3703 CCLayerTreeHostImpl::FrameData frame
;
3704 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3706 // Even though there was no change, we set the damage to entire viewport.
3707 // One of the passes should be culled as a result, since contents didn't change
3708 // and we have cached texture.
3709 ASSERT_EQ(1U, frame
.renderPasses
.size());
3710 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3712 EXPECT_TRUE(frame
.renderPasses
[0]->damageRect().isEmpty());
3714 myHostImpl
->drawLayers(frame
);
3715 myHostImpl
->didDrawAllLayers(frame
);
3718 // Change opacity and draw
3719 surfaceLayerPtr
->setOpacity(0.6f
);
3721 CCLayerTreeHostImpl::FrameData frame
;
3722 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3724 // Must receive one render pass, as the other one should be culled
3725 ASSERT_EQ(1U, frame
.renderPasses
.size());
3727 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3728 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[0]->quadList()[0]->material());
3729 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[0]->quadList()[0].get());
3730 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3731 EXPECT_TRUE(targetPass
->damageRect().isEmpty());
3733 myHostImpl
->drawLayers(frame
);
3734 myHostImpl
->didDrawAllLayers(frame
);
3737 // Change less benign property and draw - should have contents changed flag
3738 surfaceLayerPtr
->setStackingOrderChanged(true);
3740 CCLayerTreeHostImpl::FrameData frame
;
3741 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3743 // Must receive two render passes, each with one quad
3744 ASSERT_EQ(2U, frame
.renderPasses
.size());
3746 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3747 EXPECT_EQ(CCDrawQuad::SolidColor
, frame
.renderPasses
[0]->quadList()[0]->material());
3749 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
3750 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[1]->quadList()[0].get());
3751 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3752 EXPECT_FALSE(targetPass
->damageRect().isEmpty());
3754 myHostImpl
->drawLayers(frame
);
3755 myHostImpl
->didDrawAllLayers(frame
);
3758 // Change opacity again, and evict the cached surface texture.
3759 surfaceLayerPtr
->setOpacity(0.5f
);
3760 static_cast<CCRendererGLWithReleaseTextures
*>(myHostImpl
->renderer())->releaseRenderPassTextures();
3762 // Change opacity and draw
3763 surfaceLayerPtr
->setOpacity(0.6f
);
3765 CCLayerTreeHostImpl::FrameData frame
;
3766 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3768 // Must receive two render passes
3769 ASSERT_EQ(2U, frame
.renderPasses
.size());
3771 // Even though not enough properties changed, the entire thing must be
3772 // redrawn as we don't have cached textures
3773 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3774 EXPECT_EQ(1U, frame
.renderPasses
[1]->quadList().size());
3776 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[1]->quadList()[0]->material());
3777 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[1]->quadList()[0].get());
3778 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3779 EXPECT_TRUE(targetPass
->damageRect().isEmpty());
3781 // Was our surface evicted?
3782 EXPECT_FALSE(myHostImpl
->renderer()->haveCachedResourcesForRenderPassId(targetPass
->id()));
3784 myHostImpl
->drawLayers(frame
);
3785 myHostImpl
->didDrawAllLayers(frame
);
3788 // Draw without any change, to make sure the state is clear
3790 CCLayerTreeHostImpl::FrameData frame
;
3791 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3793 // Even though there was no change, we set the damage to entire viewport.
3794 // One of the passes should be culled as a result, since contents didn't change
3795 // and we have cached texture.
3796 ASSERT_EQ(1U, frame
.renderPasses
.size());
3797 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3799 myHostImpl
->drawLayers(frame
);
3800 myHostImpl
->didDrawAllLayers(frame
);
3803 // Change opacity on the intermediate layer
3804 WebTransformationMatrix transform
= intermediateLayerPtr
->transform();
3805 transform
.setM11(1.0001);
3806 intermediateLayerPtr
->setTransform(transform
);
3808 CCLayerTreeHostImpl::FrameData frame
;
3809 EXPECT_TRUE(myHostImpl
->prepareToDraw(frame
));
3811 // Must receive one render pass, as the other one should be culled.
3812 ASSERT_EQ(1U, frame
.renderPasses
.size());
3813 EXPECT_EQ(1U, frame
.renderPasses
[0]->quadList().size());
3815 EXPECT_EQ(CCDrawQuad::RenderPass
, frame
.renderPasses
[0]->quadList()[0]->material());
3816 CCRenderPassDrawQuad
* quad
= static_cast<CCRenderPassDrawQuad
*>(frame
.renderPasses
[0]->quadList()[0].get());
3817 CCRenderPass
* targetPass
= frame
.renderPassesById
.get(quad
->renderPassId());
3818 EXPECT_TRUE(targetPass
->damageRect().isEmpty());
3820 myHostImpl
->drawLayers(frame
);
3821 myHostImpl
->didDrawAllLayers(frame
);
3825 TEST_F(CCLayerTreeHostImplTest
, releaseContentsTextureShouldTriggerCommit
)
3827 m_hostImpl
->releaseContentsTextures();
3828 EXPECT_TRUE(m_didRequestCommit
);
3831 struct RenderPassCacheEntry
{
3832 mutable OwnPtr
<CCRenderPass
> renderPassPtr
;
3833 CCRenderPass
* renderPass
;
3835 RenderPassCacheEntry(PassOwnPtr
<CCRenderPass
> r
)
3837 renderPass(renderPassPtr
.get())
3841 RenderPassCacheEntry()
3845 RenderPassCacheEntry(const RenderPassCacheEntry
& entry
)
3846 : renderPassPtr(entry
.renderPassPtr
.release()),
3847 renderPass(entry
.renderPass
)
3851 RenderPassCacheEntry
& operator=(const RenderPassCacheEntry
& entry
)
3853 renderPassPtr
= entry
.renderPassPtr
.release();
3854 renderPass
= entry
.renderPass
;
3859 struct RenderPassRemovalTestData
: public CCLayerTreeHostImpl::FrameData
{
3860 std::map
<CCRenderPass::Id
, RenderPassCacheEntry
> renderPassCache
;
3861 OwnPtr
<CCSharedQuadState
> sharedQuadState
;
3864 class CCTestRenderPass
: public CCRenderPass
{
3866 static PassOwnPtr
<CCRenderPass
> create(CCRenderPass::Id id
, IntRect outputRect
, const WebTransformationMatrix
& rootTransform
) { return adoptPtr(new CCTestRenderPass(id
, outputRect
, rootTransform
)); }
3868 void appendQuad(PassOwnPtr
<CCDrawQuad
> quad
) { m_quadList
.append(quad
); }
3871 CCTestRenderPass(CCRenderPass::Id id
, IntRect outputRect
, const WebTransformationMatrix
& rootTransform
) : CCRenderPass(id
, outputRect
, rootTransform
) { }
3874 class CCTestRenderer
: public CCRendererGL
, public CCRendererClient
{
3876 static PassOwnPtr
<CCTestRenderer
> create(CCResourceProvider
* resourceProvider
)
3878 OwnPtr
<CCTestRenderer
> renderer(adoptPtr(new CCTestRenderer(resourceProvider
)));
3879 if (!renderer
->initialize())
3882 return renderer
.release();
3885 void clearCachedTextures() { m_textures
.clear(); }
3886 void setHaveCachedResourcesForRenderPassId(CCRenderPass::Id id
) { m_textures
.add(id
); }
3888 virtual bool haveCachedResourcesForRenderPassId(CCRenderPass::Id id
) const OVERRIDE
{ return m_textures
.contains(id
); }
3890 // CCRendererClient implementation.
3891 virtual const IntSize
& deviceViewportSize() const OVERRIDE
{ return m_viewportSize
; }
3892 virtual const CCLayerTreeSettings
& settings() const OVERRIDE
{ return m_settings
; }
3893 virtual void didLoseContext() OVERRIDE
{ }
3894 virtual void onSwapBuffersComplete() OVERRIDE
{ }
3895 virtual void setFullRootLayerDamage() OVERRIDE
{ }
3896 virtual void releaseContentsTextures() OVERRIDE
{ }
3897 virtual void setMemoryAllocationLimitBytes(size_t) OVERRIDE
{ }
3900 CCTestRenderer(CCResourceProvider
* resourceProvider
) : CCRendererGL(this, resourceProvider
, UnthrottledUploader
) { }
3903 CCLayerTreeSettings m_settings
;
3904 IntSize m_viewportSize
;
3905 HashSet
<CCRenderPass::Id
> m_textures
;
3908 static void configureRenderPassTestData(const char* testScript
, RenderPassRemovalTestData
& testData
, CCTestRenderer
* renderer
)
3910 renderer
->clearCachedTextures();
3912 // One shared state for all quads - we don't need the correct details
3913 testData
.sharedQuadState
= CCSharedQuadState::create(WebTransformationMatrix(), IntRect(), IntRect(), 1.0, true);
3915 const char* currentChar
= testScript
;
3917 // Pre-create root pass
3918 CCRenderPass::Id rootRenderPassId
= CCRenderPass::Id(testScript
[0], testScript
[1]);
3919 OwnPtr
<CCRenderPass
> rootRenderPass
= CCTestRenderPass::create(rootRenderPassId
, IntRect(), WebTransformationMatrix());
3920 testData
.renderPassCache
.insert(std::pair
<CCRenderPass::Id
, RenderPassCacheEntry
>(rootRenderPassId
, RenderPassCacheEntry(rootRenderPass
.release())));
3921 while (*currentChar
) {
3922 int layerId
= *currentChar
;
3924 ASSERT_TRUE(currentChar
);
3925 int index
= *currentChar
;
3928 CCRenderPass::Id renderPassId
= CCRenderPass::Id(layerId
, index
);
3930 OwnPtr
<CCRenderPass
> renderPass
;
3932 bool isReplica
= false;
3933 if (!testData
.renderPassCache
[renderPassId
].renderPassPtr
.get())
3936 renderPass
= testData
.renderPassCache
[renderPassId
].renderPassPtr
.release();
3938 // Cycle through quad data and create all quads
3939 while (*currentChar
&& *currentChar
!= '\n') {
3940 if (*currentChar
== 's') {
3941 // Solid color draw quad
3942 OwnPtr
<CCDrawQuad
> quad
= CCSolidColorDrawQuad::create(testData
.sharedQuadState
.get(), IntRect(0, 0, 10, 10), SK_ColorWHITE
);
3944 static_cast<CCTestRenderPass
*>(renderPass
.get())->appendQuad(quad
.release());
3946 } else if ((*currentChar
>= 'A') && (*currentChar
<= 'Z')) {
3947 // RenderPass draw quad
3948 int layerId
= *currentChar
;
3950 ASSERT_TRUE(currentChar
);
3951 int index
= *currentChar
;
3953 CCRenderPass::Id newRenderPassId
= CCRenderPass::Id(layerId
, index
);
3954 ASSERT_NE(rootRenderPassId
, newRenderPassId
);
3955 bool hasTexture
= false;
3956 bool contentsChanged
= true;
3958 if (*currentChar
== '[') {
3960 while (*currentChar
&& *currentChar
!= ']') {
3961 switch (*currentChar
) {
3963 contentsChanged
= false;
3971 if (*currentChar
== ']')
3975 if (testData
.renderPassCache
.find(newRenderPassId
) == testData
.renderPassCache
.end()) {
3977 renderer
->setHaveCachedResourcesForRenderPassId(newRenderPassId
);
3979 OwnPtr
<CCRenderPass
> renderPass
= CCTestRenderPass::create(newRenderPassId
, IntRect(), WebTransformationMatrix());
3980 testData
.renderPassCache
.insert(std::pair
<CCRenderPass::Id
, RenderPassCacheEntry
>(newRenderPassId
, RenderPassCacheEntry(renderPass
.release())));
3983 IntRect quadRect
= IntRect(0, 0, 1, 1);
3984 IntRect contentsChangedRect
= contentsChanged
? quadRect
: IntRect();
3985 OwnPtr
<CCRenderPassDrawQuad
> quad
= CCRenderPassDrawQuad::create(testData
.sharedQuadState
.get(), quadRect
, newRenderPassId
, isReplica
, 1, contentsChangedRect
, 1, 1, 0, 0);
3986 static_cast<CCTestRenderPass
*>(renderPass
.get())->appendQuad(quad
.release());
3989 testData
.renderPasses
.insert(0, renderPass
.get());
3990 testData
.renderPassesById
.add(renderPassId
, renderPass
.release());
3996 void dumpRenderPassTestData(const RenderPassRemovalTestData
& testData
, char* buffer
)
3999 for (CCRenderPassList::const_reverse_iterator it
= testData
.renderPasses
.rbegin(); it
!= testData
.renderPasses
.rend(); ++it
) {
4000 const CCRenderPass
* currentPass
= *it
;
4001 *pos
= currentPass
->id().layerId
;
4003 *pos
= currentPass
->id().index
;
4006 CCQuadList::const_iterator quadListIterator
= currentPass
->quadList().begin();
4007 while (quadListIterator
!= currentPass
->quadList().end()) {
4008 CCDrawQuad
* currentQuad
= (*quadListIterator
).get();
4009 switch (currentQuad
->material()) {
4010 case CCDrawQuad::SolidColor
:
4014 case CCDrawQuad::RenderPass
:
4015 *pos
= CCRenderPassDrawQuad::materialCast(currentQuad
)->renderPassId().layerId
;
4017 *pos
= CCRenderPassDrawQuad::materialCast(currentQuad
)->renderPassId().index
;
4034 // Each CCRenderPassList is represented by a string which describes the configuration.
4035 // The syntax of the string is as follows:
4037 // RsssssX[c]ssYsssZ[t]ssW[ct]
4038 // Identifies the render pass---------------------------^ ^^^ ^ ^ ^ ^ ^
4039 // These are solid color quads-----------------------------+ | | | | |
4040 // Identifies RenderPassDrawQuad's RenderPass-----------------+ | | | |
4041 // This quad's contents didn't change---------------------------+ | | |
4042 // This quad's contents changed and it has no texture---------------+ | |
4043 // This quad has texture but its contents changed-------------------------+ |
4044 // This quad's contents didn't change and it has texture - will be removed------+
4046 // Expected results have exactly the same syntax, except they do not use square brackets,
4047 // since we only check the structure, not attributes.
4049 // Test case configuration consists of initialization script and expected results,
4050 // all in the same format.
4053 const char* initScript
;
4054 const char* expectedResult
;
4057 TestCase removeRenderPassesCases
[] =
4064 "Single pass - no quads",
4068 "Two passes, no removal",
4074 "Two passes, remove last",
4079 "Have texture but contents changed - leave pass",
4085 "Contents didn't change but no texture - leave pass",
4091 "Replica: two quads reference the same pass; remove",
4092 "R0ssssA0[ct]A0[ct]sss\n"
4096 "Replica: two quads reference the same pass; leave",
4097 "R0ssssA0[c]A0[c]sss\n"
4102 "Many passes, remove all",
4104 "A0sssB0[ct]C0[ct]s\n"
4105 "B0sssD0[ct]ssE0[ct]F0[ct]\n"
4114 "Deep recursion, remove all",
4116 "R0sssssA0[ct]ssss\n"
4130 "Wide recursion, remove all",
4131 "R0A0[ct]B0[ct]C0[ct]D0[ct]E0[ct]F0[ct]G0[ct]H0[ct]I0[ct]J0[ct]\n"
4143 "R0A0B0C0D0E0F0G0H0I0J0\n"
4145 "Remove passes regardless of cache state",
4148 "B0sssD0[c]ssE0[t]F0\n"
4157 "Leave some passes, remove others",
4160 "A0sssB0[t]C0[ct]s\n"
4175 static void verifyRenderPassTestData(TestCase
& testCase
, RenderPassRemovalTestData
& testData
)
4177 char actualResult
[1024];
4178 dumpRenderPassTestData(testData
, actualResult
);
4179 EXPECT_STREQ(testCase
.expectedResult
, actualResult
) << "In test case: " << testCase
.name
;
4182 TEST_F(CCLayerTreeHostImplTest
, testRemoveRenderPasses
)
4184 OwnPtr
<CCGraphicsContext
> context(createContext());
4185 ASSERT_TRUE(context
->context3D());
4186 OwnPtr
<CCResourceProvider
> resourceProvider(CCResourceProvider::create(context
.get()));
4188 OwnPtr
<CCTestRenderer
> renderer(CCTestRenderer::create(resourceProvider
.get()));
4190 int testCaseIndex
= 0;
4191 while (removeRenderPassesCases
[testCaseIndex
].name
) {
4192 RenderPassRemovalTestData testData
;
4193 configureRenderPassTestData(removeRenderPassesCases
[testCaseIndex
].initScript
, testData
, renderer
.get());
4194 CCLayerTreeHostImpl::removeRenderPasses(CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures(*renderer
), testData
);
4195 verifyRenderPassTestData(removeRenderPassesCases
[testCaseIndex
], testData
);