[chromium] Convert screen space scroll gestures to layer space
[WebKit-https.git] / Source / WebKit / chromium / tests / CCLayerTreeHostImplTest.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "CCLayerTreeHostImpl.h"
28
29 #include "CCAnimationTestCommon.h"
30 #include "CCHeadsUpDisplayLayerImpl.h"
31 #include "CCIOSurfaceLayerImpl.h"
32 #include "CCLayerImpl.h"
33 #include "CCLayerTestCommon.h"
34 #include "CCLayerTilingData.h"
35 #include "CCLayerTreeTestCommon.h"
36 #include "CCQuadCuller.h"
37 #include "CCRenderPassDrawQuad.h"
38 #include "CCScrollbarLayerImpl.h"
39 #include "CCSettings.h"
40 #include "CCSingleThreadProxy.h"
41 #include "CCSolidColorDrawQuad.h"
42 #include "CCTestCommon.h"
43 #include "CCTextureLayerImpl.h"
44 #include "CCTileDrawQuad.h"
45 #include "CCTiledLayerImpl.h"
46 #include "CCVideoLayerImpl.h"
47 #include "FakeWebCompositorOutputSurface.h"
48 #include "FakeWebGraphicsContext3D.h"
49 #include "FakeWebScrollbarThemeGeometry.h"
50 #include "LayerRendererChromium.h"
51 #include <gmock/gmock.h>
52 #include <gtest/gtest.h>
53 #include <public/WebVideoFrame.h>
54 #include <public/WebVideoFrameProvider.h>
55
56 using namespace CCLayerTestCommon;
57 using namespace WebCore;
58 using namespace WebKit;
59 using namespace WebKitTests;
60
61 using ::testing::Mock;
62 using ::testing::Return;
63 using ::testing::AnyNumber;
64 using ::testing::AtLeast;
65 using ::testing::_;
66
67 namespace {
68
69 class CCLayerTreeHostImplTest : public testing::Test, public CCLayerTreeHostImplClient {
70 public:
71     CCLayerTreeHostImplTest()
72         : m_didRequestCommit(false)
73         , m_didRequestRedraw(false)
74     {
75         CCLayerTreeSettings settings;
76         settings.minimumOcclusionTrackingSize = IntSize();
77
78         m_hostImpl = CCLayerTreeHostImpl::create(settings, this);
79         m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
80         m_hostImpl->setViewportSize(IntSize(10, 10), IntSize(10, 10));
81     }
82
83     virtual void didLoseContextOnImplThread() OVERRIDE { }
84     virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE { }
85     virtual void onVSyncParametersChanged(double, double) OVERRIDE { }
86     virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_didRequestRedraw = true; }
87     virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; }
88     virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE { }
89
90     PassOwnPtr<CCLayerTreeHostImpl> createLayerTreeHost(bool partialSwap, PassOwnPtr<CCGraphicsContext> graphicsContext, PassOwnPtr<CCLayerImpl> rootPtr)
91     {
92         CCSettings::setPartialSwapEnabled(partialSwap);
93
94         CCLayerTreeSettings settings;
95         settings.minimumOcclusionTrackingSize = IntSize();
96
97         OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
98
99         myHostImpl->initializeLayerRenderer(graphicsContext, UnthrottledUploader);
100         myHostImpl->setViewportSize(IntSize(10, 10), IntSize(10, 10));
101
102         OwnPtr<CCLayerImpl> root = rootPtr;
103
104         root->setAnchorPoint(FloatPoint(0, 0));
105         root->setPosition(FloatPoint(0, 0));
106         root->setBounds(IntSize(10, 10));
107         root->setContentBounds(IntSize(10, 10));
108         root->setVisibleContentRect(IntRect(0, 0, 10, 10));
109         root->setDrawsContent(true);
110         myHostImpl->setRootLayer(root.release());
111         return myHostImpl.release();
112     }
113
114     static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer)
115     {
116         ASSERT_EQ(layer->scrollDelta(), IntSize());
117         for (size_t i = 0; i < layer->children().size(); ++i)
118             expectClearedScrollDeltasRecursive(layer->children()[i].get());
119     }
120
121     static void expectContains(const CCScrollAndScaleSet& scrollInfo, int id, const IntSize& scrollDelta)
122     {
123         int timesEncountered = 0;
124
125         for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) {
126             if (scrollInfo.scrolls[i].layerId != id)
127                 continue;
128             EXPECT_EQ(scrollDelta.width(), scrollInfo.scrolls[i].scrollDelta.width());
129             EXPECT_EQ(scrollDelta.height(), scrollInfo.scrolls[i].scrollDelta.height());
130             timesEncountered++;
131         }
132
133         ASSERT_EQ(timesEncountered, 1);
134     }
135
136     void setupScrollAndContentsLayers(const IntSize& contentSize)
137     {
138         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
139         root->setScrollable(true);
140         root->setScrollPosition(IntPoint(0, 0));
141         root->setMaxScrollPosition(contentSize);
142         root->setBounds(contentSize);
143         root->setContentBounds(contentSize);
144         root->setPosition(FloatPoint(0, 0));
145         root->setAnchorPoint(FloatPoint(0, 0));
146
147         OwnPtr<CCLayerImpl> contents = CCLayerImpl::create(2);
148         contents->setDrawsContent(true);
149         contents->setBounds(contentSize);
150         contents->setContentBounds(contentSize);
151         contents->setPosition(FloatPoint(0, 0));
152         contents->setAnchorPoint(FloatPoint(0, 0));
153         root->addChild(contents.release());
154         m_hostImpl->setRootLayer(root.release());
155     }
156
157     static PassOwnPtr<CCLayerImpl> createScrollableLayer(int id, const IntSize& size)
158     {
159         OwnPtr<CCLayerImpl> layer = CCLayerImpl::create(id);
160         layer->setScrollable(true);
161         layer->setDrawsContent(true);
162         layer->setBounds(size);
163         layer->setContentBounds(size);
164         layer->setMaxScrollPosition(IntSize(size.width() * 2, size.height() * 2));
165         return layer.release();
166     }
167
168     void initializeLayerRendererAndDrawFrame()
169     {
170         m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
171         CCLayerTreeHostImpl::FrameData frame;
172         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
173         m_hostImpl->drawLayers(frame);
174         m_hostImpl->didDrawAllLayers(frame);
175     }
176
177 protected:
178     PassOwnPtr<CCGraphicsContext> createContext()
179     {
180         return FakeWebCompositorOutputSurface::create(adoptPtr(new FakeWebGraphicsContext3D));
181     }
182
183     DebugScopedSetImplThread m_alwaysImplThread;
184     DebugScopedSetMainThreadBlocked m_alwaysMainThreadBlocked;
185
186     OwnPtr<CCLayerTreeHostImpl> m_hostImpl;
187     bool m_didRequestCommit;
188     bool m_didRequestRedraw;
189     CCScopedSettings m_scopedSettings;
190 };
191
192 class FakeWebGraphicsContext3DMakeCurrentFails : public FakeWebGraphicsContext3D {
193 public:
194     virtual bool makeContextCurrent() { return false; }
195 };
196
197 TEST_F(CCLayerTreeHostImplTest, scrollDeltaNoLayers)
198 {
199     ASSERT_FALSE(m_hostImpl->rootLayer());
200
201     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
202     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
203 }
204
205 TEST_F(CCLayerTreeHostImplTest, scrollDeltaTreeButNoChanges)
206 {
207     {
208         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
209         root->addChild(CCLayerImpl::create(2));
210         root->addChild(CCLayerImpl::create(3));
211         root->children()[1]->addChild(CCLayerImpl::create(4));
212         root->children()[1]->addChild(CCLayerImpl::create(5));
213         root->children()[1]->children()[0]->addChild(CCLayerImpl::create(6));
214         m_hostImpl->setRootLayer(root.release());
215     }
216     CCLayerImpl* root = m_hostImpl->rootLayer();
217
218     expectClearedScrollDeltasRecursive(root);
219
220     OwnPtr<CCScrollAndScaleSet> scrollInfo;
221
222     scrollInfo = m_hostImpl->processScrollDeltas();
223     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
224     expectClearedScrollDeltasRecursive(root);
225
226     scrollInfo = m_hostImpl->processScrollDeltas();
227     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
228     expectClearedScrollDeltasRecursive(root);
229 }
230
231 TEST_F(CCLayerTreeHostImplTest, scrollDeltaRepeatedScrolls)
232 {
233     IntPoint scrollPosition(20, 30);
234     IntSize scrollDelta(11, -15);
235     {
236         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
237         root->setScrollPosition(scrollPosition);
238         root->setScrollable(true);
239         root->setMaxScrollPosition(IntSize(100, 100));
240         root->scrollBy(scrollDelta);
241         m_hostImpl->setRootLayer(root.release());
242     }
243     CCLayerImpl* root = m_hostImpl->rootLayer();
244
245     OwnPtr<CCScrollAndScaleSet> scrollInfo;
246
247     scrollInfo = m_hostImpl->processScrollDeltas();
248     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
249     EXPECT_EQ(root->sentScrollDelta(), scrollDelta);
250     expectContains(*scrollInfo, root->id(), scrollDelta);
251
252     IntSize scrollDelta2(-5, 27);
253     root->scrollBy(scrollDelta2);
254     scrollInfo = m_hostImpl->processScrollDeltas();
255     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
256     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
257     expectContains(*scrollInfo, root->id(), scrollDelta + scrollDelta2);
258
259     root->scrollBy(IntSize());
260     scrollInfo = m_hostImpl->processScrollDeltas();
261     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
262 }
263
264 TEST_F(CCLayerTreeHostImplTest, scrollRootCallsCommitAndRedraw)
265 {
266     setupScrollAndContentsLayers(IntSize(100, 100));
267     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
268     initializeLayerRendererAndDrawFrame();
269
270     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
271     m_hostImpl->scrollBy(IntPoint(), IntSize(0, 10));
272     m_hostImpl->scrollEnd();
273     EXPECT_TRUE(m_didRequestRedraw);
274     EXPECT_TRUE(m_didRequestCommit);
275 }
276
277 TEST_F(CCLayerTreeHostImplTest, scrollWithoutRootLayer)
278 {
279     // We should not crash when trying to scroll an empty layer tree.
280     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollIgnored);
281 }
282
283 TEST_F(CCLayerTreeHostImplTest, scrollWithoutRenderer)
284 {
285     CCLayerTreeSettings settings;
286     m_hostImpl = CCLayerTreeHostImpl::create(settings, this);
287
288     // Initialization will fail here.
289     m_hostImpl->initializeLayerRenderer(FakeWebCompositorOutputSurface::create(adoptPtr(new FakeWebGraphicsContext3DMakeCurrentFails)), UnthrottledUploader);
290     m_hostImpl->setViewportSize(IntSize(10, 10), IntSize(10, 10));
291
292     setupScrollAndContentsLayers(IntSize(100, 100));
293
294     // We should not crash when trying to scroll after the renderer initialization fails.
295     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollIgnored);
296 }
297
298 TEST_F(CCLayerTreeHostImplTest, replaceTreeWhileScrolling)
299 {
300     const int scrollLayerId = 1;
301
302     setupScrollAndContentsLayers(IntSize(100, 100));
303     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
304     initializeLayerRendererAndDrawFrame();
305
306     // We should not crash if the tree is replaced while we are scrolling.
307     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
308     m_hostImpl->detachLayerTree();
309
310     setupScrollAndContentsLayers(IntSize(100, 100));
311
312     // We should still be scrolling, because the scrolled layer also exists in the new tree.
313     IntSize scrollDelta(0, 10);
314     m_hostImpl->scrollBy(IntPoint(), scrollDelta);
315     m_hostImpl->scrollEnd();
316     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
317     expectContains(*scrollInfo, scrollLayerId, scrollDelta);
318 }
319
320 TEST_F(CCLayerTreeHostImplTest, clearRootRenderSurfaceAndScroll)
321 {
322     setupScrollAndContentsLayers(IntSize(100, 100));
323     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
324     initializeLayerRendererAndDrawFrame();
325
326     // We should be able to scroll even if the root layer loses its render surface after the most
327     // recent render.
328     m_hostImpl->rootLayer()->clearRenderSurface();
329     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
330 }
331
332 TEST_F(CCLayerTreeHostImplTest, wheelEventHandlers)
333 {
334     setupScrollAndContentsLayers(IntSize(100, 100));
335     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
336     initializeLayerRendererAndDrawFrame();
337     CCLayerImpl* root = m_hostImpl->rootLayer();
338
339     root->setHaveWheelEventHandlers(true);
340
341     // With registered event handlers, wheel scrolls have to go to the main thread.
342     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollOnMainThread);
343
344     // But gesture scrolls can still be handled.
345     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
346 }
347
348 TEST_F(CCLayerTreeHostImplTest, shouldScrollOnMainThread)
349 {
350     setupScrollAndContentsLayers(IntSize(100, 100));
351     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
352     initializeLayerRendererAndDrawFrame();
353     CCLayerImpl* root = m_hostImpl->rootLayer();
354
355     root->setShouldScrollOnMainThread(true);
356
357     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollOnMainThread);
358     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollOnMainThread);
359 }
360
361 TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionBasic)
362 {
363     setupScrollAndContentsLayers(IntSize(200, 200));
364     m_hostImpl->setViewportSize(IntSize(100, 100), IntSize(100, 100));
365     initializeLayerRendererAndDrawFrame();
366     CCLayerImpl* root = m_hostImpl->rootLayer();
367
368     root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
369
370     // All scroll types inside the non-fast scrollable region should fail.
371     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollOnMainThread);
372     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollOnMainThread);
373
374     // All scroll types outside this region should succeed.
375     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
376     m_hostImpl->scrollBy(IntPoint(), IntSize(0, 10));
377     m_hostImpl->scrollEnd();
378     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
379     m_hostImpl->scrollBy(IntPoint(), IntSize(0, 10));
380     m_hostImpl->scrollEnd();
381 }
382
383 TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionWithOffset)
384 {
385     setupScrollAndContentsLayers(IntSize(200, 200));
386     m_hostImpl->setViewportSize(IntSize(100, 100), IntSize(100, 100));
387     CCLayerImpl* root = m_hostImpl->rootLayer();
388
389     root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
390     root->setPosition(FloatPoint(-25, 0));
391     initializeLayerRendererAndDrawFrame();
392
393     // This point would fall into the non-fast scrollable region except that we've moved the layer down by 25 pixels.
394     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(40, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
395     m_hostImpl->scrollBy(IntPoint(), IntSize(0, 1));
396     m_hostImpl->scrollEnd();
397
398     // This point is still inside the non-fast region.
399     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(10, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollOnMainThread);
400 }
401
402 TEST_F(CCLayerTreeHostImplTest, pinchGesture)
403 {
404     setupScrollAndContentsLayers(IntSize(100, 100));
405     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
406     initializeLayerRendererAndDrawFrame();
407
408     CCLayerImpl* scrollLayer = m_hostImpl->rootScrollLayer();
409     ASSERT(scrollLayer);
410
411     const float minPageScale = 0.5, maxPageScale = 4;
412
413     // Basic pinch zoom in gesture
414     {
415         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
416         scrollLayer->setPageScaleDelta(1);
417         scrollLayer->setScrollDelta(IntSize());
418
419         float pageScaleDelta = 2;
420         m_hostImpl->pinchGestureBegin();
421         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
422         m_hostImpl->pinchGestureEnd();
423         EXPECT_TRUE(m_didRequestRedraw);
424         EXPECT_TRUE(m_didRequestCommit);
425
426         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
427         EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
428     }
429
430     // Zoom-in clamping
431     {
432         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
433         scrollLayer->setPageScaleDelta(1);
434         scrollLayer->setScrollDelta(IntSize());
435         float pageScaleDelta = 10;
436
437         m_hostImpl->pinchGestureBegin();
438         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
439         m_hostImpl->pinchGestureEnd();
440
441         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
442         EXPECT_EQ(scrollInfo->pageScaleDelta, maxPageScale);
443     }
444
445     // Zoom-out clamping
446     {
447         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
448         scrollLayer->setPageScaleDelta(1);
449         scrollLayer->setScrollDelta(IntSize());
450         scrollLayer->setScrollPosition(IntPoint(50, 50));
451
452         float pageScaleDelta = 0.1f;
453         m_hostImpl->pinchGestureBegin();
454         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(0, 0));
455         m_hostImpl->pinchGestureEnd();
456
457         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
458         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
459
460         // Pushed to (0,0) via clamping against contents layer size.
461         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
462     }
463
464     // Two-finger panning
465     {
466         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
467         scrollLayer->setPageScaleDelta(1);
468         scrollLayer->setScrollDelta(IntSize());
469         scrollLayer->setScrollPosition(IntPoint(20, 20));
470
471         float pageScaleDelta = 1;
472         m_hostImpl->pinchGestureBegin();
473         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(10, 10));
474         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(20, 20));
475         m_hostImpl->pinchGestureEnd();
476
477         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
478         EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
479         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-10, -10));
480     }
481 }
482
483 TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation)
484 {
485     setupScrollAndContentsLayers(IntSize(100, 100));
486     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
487     initializeLayerRendererAndDrawFrame();
488
489     CCLayerImpl* scrollLayer = m_hostImpl->rootScrollLayer();
490     ASSERT(scrollLayer);
491
492     const float minPageScale = 0.5, maxPageScale = 4;
493     const double startTime = 1;
494     const double duration = 0.1;
495     const double halfwayThroughAnimation = startTime + duration / 2;
496     const double endTime = startTime + duration;
497
498     // Non-anchor zoom-in
499     {
500         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
501         scrollLayer->setPageScaleDelta(1);
502         scrollLayer->setScrollPosition(IntPoint(50, 50));
503
504         m_hostImpl->startPageScaleAnimation(IntSize(0, 0), false, 2, startTime, duration);
505         m_hostImpl->animate(halfwayThroughAnimation, halfwayThroughAnimation);
506         EXPECT_TRUE(m_didRequestRedraw);
507         m_hostImpl->animate(endTime, endTime);
508         EXPECT_TRUE(m_didRequestCommit);
509
510         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
511         EXPECT_EQ(scrollInfo->pageScaleDelta, 2);
512         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
513     }
514
515     // Anchor zoom-out
516     {
517         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
518         scrollLayer->setPageScaleDelta(1);
519         scrollLayer->setScrollPosition(IntPoint(50, 50));
520
521         m_hostImpl->startPageScaleAnimation(IntSize(25, 25), true, minPageScale, startTime, duration);
522         m_hostImpl->animate(endTime, endTime);
523         EXPECT_TRUE(m_didRequestRedraw);
524         EXPECT_TRUE(m_didRequestCommit);
525
526         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
527         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
528         // Pushed to (0,0) via clamping against contents layer size.
529         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
530     }
531 }
532
533 TEST_F(CCLayerTreeHostImplTest, inhibitScrollAndPageScaleUpdatesWhilePinchZooming)
534 {
535     setupScrollAndContentsLayers(IntSize(100, 100));
536     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
537     initializeLayerRendererAndDrawFrame();
538
539     CCLayerImpl* scrollLayer = m_hostImpl->rootScrollLayer();
540     ASSERT(scrollLayer);
541
542     const float minPageScale = 0.5, maxPageScale = 4;
543
544     // Pinch zoom in.
545     {
546         // Start a pinch in gesture at the bottom right corner of the viewport.
547         const float zoomInDelta = 2;
548         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
549         m_hostImpl->pinchGestureBegin();
550         m_hostImpl->pinchGestureUpdate(zoomInDelta, IntPoint(50, 50));
551
552         // Because we are pinch zooming in, we shouldn't get any scroll or page
553         // scale deltas.
554         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
555         EXPECT_EQ(scrollInfo->pageScaleDelta, 1);
556         EXPECT_EQ(scrollInfo->scrolls.size(), 0u);
557
558         // Once the gesture ends, we get the final scroll and page scale values.
559         m_hostImpl->pinchGestureEnd();
560         scrollInfo = m_hostImpl->processScrollDeltas();
561         EXPECT_EQ(scrollInfo->pageScaleDelta, zoomInDelta);
562         expectContains(*scrollInfo, scrollLayer->id(), IntSize(25, 25));
563     }
564
565     // Pinch zoom out.
566     {
567         // Start a pinch out gesture at the bottom right corner of the viewport.
568         const float zoomOutDelta = 0.75;
569         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
570         m_hostImpl->pinchGestureBegin();
571         m_hostImpl->pinchGestureUpdate(zoomOutDelta, IntPoint(50, 50));
572
573         // Since we are pinch zooming out, we should get an update to zoom all
574         // the way out to the minimum page scale.
575         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
576         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
577         expectContains(*scrollInfo, scrollLayer->id(), IntSize(0, 0));
578
579         // Once the gesture ends, we get the final scroll and page scale values.
580         m_hostImpl->pinchGestureEnd();
581         scrollInfo = m_hostImpl->processScrollDeltas();
582         EXPECT_EQ(scrollInfo->pageScaleDelta, zoomOutDelta);
583         expectContains(*scrollInfo, scrollLayer->id(), IntSize(8, 8));
584     }
585 }
586
587 TEST_F(CCLayerTreeHostImplTest, inhibitScrollAndPageScaleUpdatesWhileAnimatingPageScale)
588 {
589     setupScrollAndContentsLayers(IntSize(100, 100));
590     m_hostImpl->setViewportSize(IntSize(50, 50), IntSize(50, 50));
591     initializeLayerRendererAndDrawFrame();
592
593     CCLayerImpl* scrollLayer = m_hostImpl->rootScrollLayer();
594     ASSERT(scrollLayer);
595
596     const float minPageScale = 0.5, maxPageScale = 4;
597     const double startTime = 1;
598     const double duration = 0.1;
599     const double halfwayThroughAnimation = startTime + duration / 2;
600     const double endTime = startTime + duration;
601
602     // Start a page scale animation.
603     const float pageScaleDelta = 2;
604     m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
605     m_hostImpl->startPageScaleAnimation(IntSize(50, 50), false, pageScaleDelta, startTime, duration);
606
607     // We should immediately get the final zoom and scroll values for the
608     // animation.
609     m_hostImpl->animate(halfwayThroughAnimation, halfwayThroughAnimation);
610     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
611     EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
612     expectContains(*scrollInfo, scrollLayer->id(), IntSize(25, 25));
613
614     // Scrolling during the animation is ignored.
615     const IntSize scrollDelta(0, 10);
616     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
617     m_hostImpl->scrollBy(IntPoint(), scrollDelta);
618     m_hostImpl->scrollEnd();
619
620     // The final page scale and scroll deltas should match what we got
621     // earlier.
622     m_hostImpl->animate(endTime, endTime);
623     scrollInfo = m_hostImpl->processScrollDeltas();
624     EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
625     expectContains(*scrollInfo, scrollLayer->id(), IntSize(25, 25));
626 }
627
628 class DidDrawCheckLayer : public CCTiledLayerImpl {
629 public:
630     static PassOwnPtr<DidDrawCheckLayer> create(int id) { return adoptPtr(new DidDrawCheckLayer(id)); }
631
632     virtual void didDraw(CCResourceProvider*) OVERRIDE
633     {
634         m_didDrawCalled = true;
635     }
636
637     virtual void willDraw(CCResourceProvider*) OVERRIDE
638     {
639         m_willDrawCalled = true;
640     }
641
642     bool didDrawCalled() const { return m_didDrawCalled; }
643     bool willDrawCalled() const { return m_willDrawCalled; }
644
645     void clearDidDrawCheck()
646     {
647         m_didDrawCalled = false;
648         m_willDrawCalled = false;
649     }
650
651 protected:
652     explicit DidDrawCheckLayer(int id)
653         : CCTiledLayerImpl(id)
654         , m_didDrawCalled(false)
655         , m_willDrawCalled(false)
656     {
657         setAnchorPoint(FloatPoint(0, 0));
658         setBounds(IntSize(10, 10));
659         setContentBounds(IntSize(10, 10));
660         setDrawsContent(true);
661         setSkipsDraw(false);
662         setVisibleContentRect(IntRect(0, 0, 10, 10));
663
664         OwnPtr<CCLayerTilingData> tiler = CCLayerTilingData::create(IntSize(100, 100), CCLayerTilingData::HasBorderTexels);
665         tiler->setBounds(contentBounds());
666         setTilingData(*tiler.get());
667     }
668
669 private:
670     bool m_didDrawCalled;
671     bool m_willDrawCalled;
672 };
673
674 TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer)
675 {
676     // The root layer is always drawn, so run this test on a child layer that
677     // will be masked out by the root layer's bounds.
678     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(1));
679     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
680     root->setMasksToBounds(true);
681
682     root->addChild(DidDrawCheckLayer::create(2));
683     DidDrawCheckLayer* layer = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
684     // Ensure visibleContentRect for layer is empty
685     layer->setPosition(FloatPoint(100, 100));
686     layer->setBounds(IntSize(10, 10));
687     layer->setContentBounds(IntSize(10, 10));
688
689     CCLayerTreeHostImpl::FrameData frame;
690
691     EXPECT_FALSE(layer->willDrawCalled());
692     EXPECT_FALSE(layer->didDrawCalled());
693
694     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
695     m_hostImpl->drawLayers(frame);
696     m_hostImpl->didDrawAllLayers(frame);
697
698     EXPECT_FALSE(layer->willDrawCalled());
699     EXPECT_FALSE(layer->didDrawCalled());
700
701     EXPECT_TRUE(layer->visibleContentRect().isEmpty());
702
703     // Ensure visibleContentRect for layer layer is not empty
704     layer->setPosition(FloatPoint(0, 0));
705
706     EXPECT_FALSE(layer->willDrawCalled());
707     EXPECT_FALSE(layer->didDrawCalled());
708
709     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
710     m_hostImpl->drawLayers(frame);
711     m_hostImpl->didDrawAllLayers(frame);
712
713     EXPECT_TRUE(layer->willDrawCalled());
714     EXPECT_TRUE(layer->didDrawCalled());
715
716     EXPECT_FALSE(layer->visibleContentRect().isEmpty());
717 }
718
719 TEST_F(CCLayerTreeHostImplTest, willDrawNotCalledOnOccludedLayer)
720 {
721     IntSize bigSize(1000, 1000);
722     m_hostImpl->setViewportSize(bigSize, bigSize);
723
724     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(1));
725     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
726
727     root->addChild(DidDrawCheckLayer::create(2));
728     DidDrawCheckLayer* occludedLayer = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
729
730     root->addChild(DidDrawCheckLayer::create(3));
731     DidDrawCheckLayer* topLayer = static_cast<DidDrawCheckLayer*>(root->children()[1].get());
732     // This layer covers the occludedLayer above. Make this layer large so it can occlude.
733     topLayer->setBounds(bigSize);
734     topLayer->setContentBounds(bigSize);
735     topLayer->setOpaque(true);
736
737     CCLayerTreeHostImpl::FrameData frame;
738
739     EXPECT_FALSE(occludedLayer->willDrawCalled());
740     EXPECT_FALSE(occludedLayer->didDrawCalled());
741     EXPECT_FALSE(topLayer->willDrawCalled());
742     EXPECT_FALSE(topLayer->didDrawCalled());
743
744     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
745     m_hostImpl->drawLayers(frame);
746     m_hostImpl->didDrawAllLayers(frame);
747
748     EXPECT_FALSE(occludedLayer->willDrawCalled());
749     EXPECT_FALSE(occludedLayer->didDrawCalled());
750     EXPECT_TRUE(topLayer->willDrawCalled());
751     EXPECT_TRUE(topLayer->didDrawCalled());
752 }
753
754 TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
755 {
756     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(1));
757     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
758
759     root->addChild(DidDrawCheckLayer::create(2));
760     DidDrawCheckLayer* layer1 = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
761
762     layer1->addChild(DidDrawCheckLayer::create(3));
763     DidDrawCheckLayer* layer2 = static_cast<DidDrawCheckLayer*>(layer1->children()[0].get());
764
765     layer1->setOpacity(0.3f);
766     layer1->setPreserves3D(false);
767
768     EXPECT_FALSE(root->didDrawCalled());
769     EXPECT_FALSE(layer1->didDrawCalled());
770     EXPECT_FALSE(layer2->didDrawCalled());
771
772     CCLayerTreeHostImpl::FrameData frame;
773     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
774     m_hostImpl->drawLayers(frame);
775     m_hostImpl->didDrawAllLayers(frame);
776
777     EXPECT_TRUE(root->didDrawCalled());
778     EXPECT_TRUE(layer1->didDrawCalled());
779     EXPECT_TRUE(layer2->didDrawCalled());
780
781     EXPECT_NE(root->renderSurface(), layer1->renderSurface());
782     EXPECT_TRUE(!!layer1->renderSurface());
783 }
784
785 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
786 public:
787     static PassOwnPtr<MissingTextureAnimatingLayer> create(int id, bool tileMissing, bool skipsDraw, bool animating, CCResourceProvider* resourceProvider) { return adoptPtr(new MissingTextureAnimatingLayer(id, tileMissing, skipsDraw, animating, resourceProvider)); }
788
789 private:
790     explicit MissingTextureAnimatingLayer(int id, bool tileMissing, bool skipsDraw, bool animating, CCResourceProvider* resourceProvider)
791         : DidDrawCheckLayer(id)
792     {
793         OwnPtr<CCLayerTilingData> tilingData = CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels);
794         tilingData->setBounds(bounds());
795         setTilingData(*tilingData.get());
796         setSkipsDraw(skipsDraw);
797         if (!tileMissing) {
798             CCResourceProvider::ResourceId resource = resourceProvider->createResource(CCRenderer::ContentPool, IntSize(), GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageAny);
799             pushTileProperties(0, 0, resource, IntRect());
800         }
801         if (animating)
802             addAnimatedTransformToLayer(*this, 10, 3, 0);
803     }
804 };
805
806 TEST_F(CCLayerTreeHostImplTest, prepareToDrawFailsWhenAnimationUsesCheckerboard)
807 {
808     // When the texture is not missing, we draw as usual.
809     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(1));
810     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
811     root->addChild(MissingTextureAnimatingLayer::create(2, false, false, true, m_hostImpl->resourceProvider()));
812
813     CCLayerTreeHostImpl::FrameData frame;
814
815     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
816     m_hostImpl->drawLayers(frame);
817     m_hostImpl->didDrawAllLayers(frame);
818
819     // When a texture is missing and we're not animating, we draw as usual with checkerboarding.
820     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(1));
821     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
822     root->addChild(MissingTextureAnimatingLayer::create(2, true, false, false, m_hostImpl->resourceProvider()));
823
824     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
825     m_hostImpl->drawLayers(frame);
826     m_hostImpl->didDrawAllLayers(frame);
827
828     // When a texture is missing and we're animating, we don't want to draw anything.
829     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(1));
830     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
831     root->addChild(MissingTextureAnimatingLayer::create(2, true, false, true, m_hostImpl->resourceProvider()));
832
833     EXPECT_FALSE(m_hostImpl->prepareToDraw(frame));
834     m_hostImpl->drawLayers(frame);
835     m_hostImpl->didDrawAllLayers(frame);
836
837     // When the layer skips draw and we're animating, we still draw the frame.
838     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(1));
839     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
840     root->addChild(MissingTextureAnimatingLayer::create(2, false, true, true, m_hostImpl->resourceProvider()));
841
842     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
843     m_hostImpl->drawLayers(frame);
844     m_hostImpl->didDrawAllLayers(frame);
845 }
846
847 TEST_F(CCLayerTreeHostImplTest, scrollRootIgnored)
848 {
849     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
850     root->setScrollable(false);
851     m_hostImpl->setRootLayer(root.release());
852     initializeLayerRendererAndDrawFrame();
853
854     // Scroll event is ignored because layer is not scrollable.
855     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollIgnored);
856     EXPECT_FALSE(m_didRequestRedraw);
857     EXPECT_FALSE(m_didRequestCommit);
858 }
859
860 TEST_F(CCLayerTreeHostImplTest, scrollNonCompositedRoot)
861 {
862     // Test the configuration where a non-composited root layer is embedded in a
863     // scrollable outer layer.
864     IntSize surfaceSize(10, 10);
865
866     OwnPtr<CCLayerImpl> contentLayer = CCLayerImpl::create(1);
867     contentLayer->setUseLCDText(true);
868     contentLayer->setDrawsContent(true);
869     contentLayer->setPosition(FloatPoint(0, 0));
870     contentLayer->setAnchorPoint(FloatPoint(0, 0));
871     contentLayer->setBounds(surfaceSize);
872     contentLayer->setContentBounds(IntSize(surfaceSize.width() * 2, surfaceSize.height() * 2));
873
874     OwnPtr<CCLayerImpl> scrollLayer = CCLayerImpl::create(2);
875     scrollLayer->setScrollable(true);
876     scrollLayer->setMaxScrollPosition(surfaceSize);
877     scrollLayer->setBounds(surfaceSize);
878     scrollLayer->setContentBounds(surfaceSize);
879     scrollLayer->setPosition(FloatPoint(0, 0));
880     scrollLayer->setAnchorPoint(FloatPoint(0, 0));
881     scrollLayer->addChild(contentLayer.release());
882
883     m_hostImpl->setRootLayer(scrollLayer.release());
884     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
885     initializeLayerRendererAndDrawFrame();
886
887     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
888     m_hostImpl->scrollBy(IntPoint(), IntSize(0, 10));
889     m_hostImpl->scrollEnd();
890     EXPECT_TRUE(m_didRequestRedraw);
891     EXPECT_TRUE(m_didRequestCommit);
892 }
893
894 TEST_F(CCLayerTreeHostImplTest, scrollChildCallsCommitAndRedraw)
895 {
896     IntSize surfaceSize(10, 10);
897     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
898     root->setBounds(surfaceSize);
899     root->setContentBounds(surfaceSize);
900     root->addChild(createScrollableLayer(2, surfaceSize));
901     m_hostImpl->setRootLayer(root.release());
902     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
903     initializeLayerRendererAndDrawFrame();
904
905     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
906     m_hostImpl->scrollBy(IntPoint(), IntSize(0, 10));
907     m_hostImpl->scrollEnd();
908     EXPECT_TRUE(m_didRequestRedraw);
909     EXPECT_TRUE(m_didRequestCommit);
910 }
911
912 TEST_F(CCLayerTreeHostImplTest, scrollMissesChild)
913 {
914     IntSize surfaceSize(10, 10);
915     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
916     root->addChild(createScrollableLayer(2, surfaceSize));
917     m_hostImpl->setRootLayer(root.release());
918     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
919     initializeLayerRendererAndDrawFrame();
920
921     // Scroll event is ignored because the input coordinate is outside the layer boundaries.
922     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(15, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollIgnored);
923     EXPECT_FALSE(m_didRequestRedraw);
924     EXPECT_FALSE(m_didRequestCommit);
925 }
926
927 TEST_F(CCLayerTreeHostImplTest, scrollMissesBackfacingChild)
928 {
929     IntSize surfaceSize(10, 10);
930     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
931     OwnPtr<CCLayerImpl> child = createScrollableLayer(2, surfaceSize);
932     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
933
934     WebTransformationMatrix matrix;
935     matrix.rotate3d(180, 0, 0);
936     child->setTransform(matrix);
937     child->setDoubleSided(false);
938
939     root->addChild(child.release());
940     m_hostImpl->setRootLayer(root.release());
941     initializeLayerRendererAndDrawFrame();
942
943     // Scroll event is ignored because the scrollable layer is not facing the viewer and there is
944     // nothing scrollable behind it.
945     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollIgnored);
946     EXPECT_FALSE(m_didRequestRedraw);
947     EXPECT_FALSE(m_didRequestCommit);
948 }
949
950 TEST_F(CCLayerTreeHostImplTest, scrollBlockedByContentLayer)
951 {
952     IntSize surfaceSize(10, 10);
953     OwnPtr<CCLayerImpl> contentLayer = createScrollableLayer(1, surfaceSize);
954     contentLayer->setShouldScrollOnMainThread(true);
955     contentLayer->setScrollable(false);
956
957     OwnPtr<CCLayerImpl> scrollLayer = createScrollableLayer(2, surfaceSize);
958     scrollLayer->addChild(contentLayer.release());
959
960     m_hostImpl->setRootLayer(scrollLayer.release());
961     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
962     initializeLayerRendererAndDrawFrame();
963
964     // Scrolling fails because the content layer is asking to be scrolled on the main thread.
965     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollOnMainThread);
966 }
967
968 TEST_F(CCLayerTreeHostImplTest, scrollRootAndChangePageScaleOnMainThread)
969 {
970     IntSize surfaceSize(10, 10);
971     float pageScale = 2;
972     OwnPtr<CCLayerImpl> root = createScrollableLayer(1, surfaceSize);
973     m_hostImpl->setRootLayer(root.release());
974     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
975     initializeLayerRendererAndDrawFrame();
976
977     IntSize scrollDelta(0, 10);
978     IntSize expectedScrollDelta(scrollDelta);
979     IntSize expectedMaxScroll(m_hostImpl->rootLayer()->maxScrollPosition());
980     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
981     m_hostImpl->scrollBy(IntPoint(), scrollDelta);
982     m_hostImpl->scrollEnd();
983
984     // Set new page scale from main thread.
985     m_hostImpl->setPageScaleFactorAndLimits(pageScale, pageScale, pageScale);
986
987     // The scale should apply to the scroll delta.
988     expectedScrollDelta.scale(pageScale);
989     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
990     expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedScrollDelta);
991
992     // The scroll range should also have been updated.
993     EXPECT_EQ(m_hostImpl->rootLayer()->maxScrollPosition(), expectedMaxScroll);
994
995     // The page scale delta remains constant because the impl thread did not scale.
996     EXPECT_EQ(m_hostImpl->rootLayer()->pageScaleDelta(), 1);
997 }
998
999 TEST_F(CCLayerTreeHostImplTest, scrollRootAndChangePageScaleOnImplThread)
1000 {
1001     IntSize surfaceSize(10, 10);
1002     float pageScale = 2;
1003     OwnPtr<CCLayerImpl> root = createScrollableLayer(1, surfaceSize);
1004     m_hostImpl->setRootLayer(root.release());
1005     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
1006     m_hostImpl->setPageScaleFactorAndLimits(1, 1, pageScale);
1007     initializeLayerRendererAndDrawFrame();
1008
1009     IntSize scrollDelta(0, 10);
1010     IntSize expectedScrollDelta(scrollDelta);
1011     IntSize expectedMaxScroll(m_hostImpl->rootLayer()->maxScrollPosition());
1012     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
1013     m_hostImpl->scrollBy(IntPoint(), scrollDelta);
1014     m_hostImpl->scrollEnd();
1015
1016     // Set new page scale on impl thread by pinching.
1017     m_hostImpl->pinchGestureBegin();
1018     m_hostImpl->pinchGestureUpdate(pageScale, IntPoint());
1019     m_hostImpl->pinchGestureEnd();
1020
1021     // The scroll delta is not scaled because the main thread did not scale.
1022     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
1023     expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedScrollDelta);
1024
1025     // The scroll range should also have been updated.
1026     EXPECT_EQ(m_hostImpl->rootLayer()->maxScrollPosition(), expectedMaxScroll);
1027
1028     // The page scale delta should match the new scale on the impl side.
1029     EXPECT_EQ(m_hostImpl->rootLayer()->pageScaleDelta(), pageScale);
1030 }
1031
1032 TEST_F(CCLayerTreeHostImplTest, pageScaleDeltaAppliedToRootScrollLayerOnly)
1033 {
1034     IntSize surfaceSize(10, 10);
1035     float defaultPageScale = 1;
1036     float newPageScale = 2;
1037
1038     // Create a normal scrollable root layer and another scrollable child layer.
1039     setupScrollAndContentsLayers(surfaceSize);
1040     CCLayerImpl* root = m_hostImpl->rootLayer();
1041     CCLayerImpl* child = root->children()[0].get();
1042
1043     OwnPtr<CCLayerImpl> scrollableChild = createScrollableLayer(3, surfaceSize);
1044     child->addChild(scrollableChild.release());
1045     CCLayerImpl* grandChild = child->children()[0].get();
1046
1047     // Set new page scale on impl thread by pinching.
1048     m_hostImpl->pinchGestureBegin();
1049     m_hostImpl->pinchGestureUpdate(newPageScale, IntPoint());
1050     m_hostImpl->pinchGestureEnd();
1051
1052     // The page scale delta should only be applied to the scrollable root layer.
1053     EXPECT_EQ(root->pageScaleDelta(), newPageScale);
1054     EXPECT_EQ(child->pageScaleDelta(), defaultPageScale);
1055     EXPECT_EQ(grandChild->pageScaleDelta(), defaultPageScale);
1056
1057     // Make sure all the layers are drawn with the page scale delta applied, i.e., the page scale
1058     // delta on the root layer is applied hierarchically.
1059     CCLayerTreeHostImpl::FrameData frame;
1060     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1061     m_hostImpl->drawLayers(frame);
1062     m_hostImpl->didDrawAllLayers(frame);
1063
1064     EXPECT_EQ(root->drawTransform().m11(), newPageScale);
1065     EXPECT_EQ(root->drawTransform().m22(), newPageScale);
1066     EXPECT_EQ(child->drawTransform().m11(), newPageScale);
1067     EXPECT_EQ(child->drawTransform().m22(), newPageScale);
1068     EXPECT_EQ(grandChild->drawTransform().m11(), newPageScale);
1069     EXPECT_EQ(grandChild->drawTransform().m22(), newPageScale);
1070 }
1071
1072 TEST_F(CCLayerTreeHostImplTest, scrollChildAndChangePageScaleOnMainThread)
1073 {
1074     IntSize surfaceSize(10, 10);
1075     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
1076     root->setBounds(surfaceSize);
1077     root->setContentBounds(surfaceSize);
1078     // Also mark the root scrollable so it becomes the root scroll layer.
1079     root->setScrollable(true);
1080     int scrollLayerId = 2;
1081     root->addChild(createScrollableLayer(scrollLayerId, surfaceSize));
1082     m_hostImpl->setRootLayer(root.release());
1083     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
1084     initializeLayerRendererAndDrawFrame();
1085
1086     CCLayerImpl* child = m_hostImpl->rootLayer()->children()[0].get();
1087
1088     IntSize scrollDelta(0, 10);
1089     IntSize expectedScrollDelta(scrollDelta);
1090     IntSize expectedMaxScroll(child->maxScrollPosition());
1091     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
1092     m_hostImpl->scrollBy(IntPoint(), scrollDelta);
1093     m_hostImpl->scrollEnd();
1094
1095     float pageScale = 2;
1096     m_hostImpl->setPageScaleFactorAndLimits(pageScale, 1, pageScale);
1097
1098     // The scale should apply to the scroll delta.
1099     expectedScrollDelta.scale(pageScale);
1100     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
1101     expectContains(*scrollInfo.get(), scrollLayerId, expectedScrollDelta);
1102
1103     // The scroll range should not have changed.
1104     EXPECT_EQ(child->maxScrollPosition(), expectedMaxScroll);
1105
1106     // The page scale delta remains constant because the impl thread did not scale.
1107     EXPECT_EQ(child->pageScaleDelta(), 1);
1108 }
1109
1110 TEST_F(CCLayerTreeHostImplTest, scrollChildBeyondLimit)
1111 {
1112     // Scroll a child layer beyond its maximum scroll range and make sure the
1113     // parent layer is scrolled on the axis on which the child was unable to
1114     // scroll.
1115     IntSize surfaceSize(10, 10);
1116     OwnPtr<CCLayerImpl> root = createScrollableLayer(1, surfaceSize);
1117
1118     OwnPtr<CCLayerImpl> grandChild = createScrollableLayer(3, surfaceSize);
1119     grandChild->setScrollPosition(IntPoint(0, 5));
1120
1121     OwnPtr<CCLayerImpl> child = createScrollableLayer(2, surfaceSize);
1122     child->setScrollPosition(IntPoint(3, 0));
1123     child->addChild(grandChild.release());
1124
1125     root->addChild(child.release());
1126     m_hostImpl->setRootLayer(root.release());
1127     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
1128     initializeLayerRendererAndDrawFrame();
1129     {
1130         IntSize scrollDelta(-8, -7);
1131         EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
1132         m_hostImpl->scrollBy(IntPoint(), scrollDelta);
1133         m_hostImpl->scrollEnd();
1134
1135         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
1136
1137         // The grand child should have scrolled up to its limit.
1138         CCLayerImpl* child = m_hostImpl->rootLayer()->children()[0].get();
1139         CCLayerImpl* grandChild = child->children()[0].get();
1140         expectContains(*scrollInfo.get(), grandChild->id(), IntSize(0, -5));
1141
1142         // The child should have only scrolled on the other axis.
1143         expectContains(*scrollInfo.get(), child->id(), IntSize(-3, 0));
1144     }
1145 }
1146
1147 TEST_F(CCLayerTreeHostImplTest, scrollEventBubbling)
1148 {
1149     // When we try to scroll a non-scrollable child layer, the scroll delta
1150     // should be applied to one of its ancestors if possible.
1151     IntSize surfaceSize(10, 10);
1152     OwnPtr<CCLayerImpl> root = createScrollableLayer(1, surfaceSize);
1153     OwnPtr<CCLayerImpl> child = createScrollableLayer(2, surfaceSize);
1154
1155     child->setScrollable(false);
1156     root->addChild(child.release());
1157
1158     m_hostImpl->setRootLayer(root.release());
1159     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
1160     initializeLayerRendererAndDrawFrame();
1161     {
1162         IntSize scrollDelta(0, 4);
1163         EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
1164         m_hostImpl->scrollBy(IntPoint(), scrollDelta);
1165         m_hostImpl->scrollEnd();
1166
1167         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
1168
1169         // Only the root should have scrolled.
1170         ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
1171         expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), scrollDelta);
1172     }
1173 }
1174
1175 TEST_F(CCLayerTreeHostImplTest, scrollBeforeRedraw)
1176 {
1177     IntSize surfaceSize(10, 10);
1178     m_hostImpl->setRootLayer(createScrollableLayer(1, surfaceSize));
1179     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
1180
1181     // Draw one frame and then immediately rebuild the layer tree to mimic a tree synchronization.
1182     initializeLayerRendererAndDrawFrame();
1183     m_hostImpl->detachLayerTree();
1184     m_hostImpl->setRootLayer(createScrollableLayer(2, surfaceSize));
1185
1186     // Scrolling should still work even though we did not draw yet.
1187     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(5, 5), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
1188 }
1189
1190 TEST_F(CCLayerTreeHostImplTest, scrollAxisAlignedRotatedLayer)
1191 {
1192     setupScrollAndContentsLayers(IntSize(100, 100));
1193
1194     // Rotate the root layer 90 degrees counter-clockwise about its center.
1195     WebTransformationMatrix rotateTransform;
1196     rotateTransform.rotate(-90);
1197     m_hostImpl->rootLayer()->setTransform(rotateTransform);
1198
1199     IntSize surfaceSize(50, 50);
1200     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
1201     initializeLayerRendererAndDrawFrame();
1202
1203     // Scroll to the right in screen coordinates with a gesture.
1204     IntSize gestureScrollDelta(10, 0);
1205     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
1206     m_hostImpl->scrollBy(IntPoint(), gestureScrollDelta);
1207     m_hostImpl->scrollEnd();
1208
1209     // The layer should have scrolled down in its local coordinates.
1210     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
1211     expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), IntSize(0, gestureScrollDelta.width()));
1212
1213     // Reset and scroll down with the wheel.
1214     m_hostImpl->rootLayer()->setScrollDelta(FloatSize());
1215     IntSize wheelScrollDelta(0, 10);
1216     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
1217     m_hostImpl->scrollBy(IntPoint(), wheelScrollDelta);
1218     m_hostImpl->scrollEnd();
1219
1220     // The layer should have scrolled down in its local coordinates.
1221     scrollInfo = m_hostImpl->processScrollDeltas();
1222     expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), wheelScrollDelta);
1223 }
1224
1225 TEST_F(CCLayerTreeHostImplTest, scrollNonAxisAlignedRotatedLayer)
1226 {
1227     setupScrollAndContentsLayers(IntSize(100, 100));
1228     int childLayerId = 3;
1229     float childLayerAngle = -20;
1230
1231     // Create a child layer that is rotated to a non-axis-aligned angle.
1232     OwnPtr<CCLayerImpl> child = createScrollableLayer(childLayerId, m_hostImpl->rootLayer()->contentBounds());
1233     WebTransformationMatrix rotateTransform;
1234     rotateTransform.translate(-50, -50);
1235     rotateTransform.rotate(childLayerAngle);
1236     rotateTransform.translate(50, 50);
1237     child->setTransform(rotateTransform);
1238
1239     // Only allow vertical scrolling.
1240     child->setMaxScrollPosition(IntSize(0, child->contentBounds().height()));
1241     m_hostImpl->rootLayer()->addChild(child.release());
1242
1243     IntSize surfaceSize(50, 50);
1244     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
1245     initializeLayerRendererAndDrawFrame();
1246
1247     {
1248         // Scroll down in screen coordinates with a gesture.
1249         IntSize gestureScrollDelta(0, 10);
1250         EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
1251         m_hostImpl->scrollBy(IntPoint(), gestureScrollDelta);
1252         m_hostImpl->scrollEnd();
1253
1254         // The child layer should have scrolled down in its local coordinates an amount proportional to
1255         // the angle between it and the input scroll delta.
1256         IntSize expectedScrollDelta(0, gestureScrollDelta.height() * cosf(deg2rad(childLayerAngle)));
1257         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
1258         expectContains(*scrollInfo.get(), childLayerId, expectedScrollDelta);
1259
1260         // The root layer should not have scrolled, because the input delta was close to the layer's
1261         // axis of movement.
1262         EXPECT_EQ(scrollInfo->scrolls.size(), 1u);
1263     }
1264
1265     {
1266         // Now reset and scroll the same amount horizontally.
1267         m_hostImpl->rootLayer()->children()[1]->setScrollDelta(FloatSize());
1268         IntSize gestureScrollDelta(10, 0);
1269         EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
1270         m_hostImpl->scrollBy(IntPoint(), gestureScrollDelta);
1271         m_hostImpl->scrollEnd();
1272
1273         // The child layer should have scrolled down in its local coordinates an amount proportional to
1274         // the angle between it and the input scroll delta.
1275         IntSize expectedScrollDelta(0, -gestureScrollDelta.width() * sinf(deg2rad(childLayerAngle)));
1276         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
1277         expectContains(*scrollInfo.get(), childLayerId, expectedScrollDelta);
1278
1279         // The root layer should have scrolled more, since the input scroll delta was mostly
1280         // orthogonal to the child layer's vertical scroll axis.
1281         IntSize expectedRootScrollDelta(gestureScrollDelta.width() * pow(cosf(deg2rad(childLayerAngle)), 2), 0);
1282         expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedRootScrollDelta);
1283     }
1284 }
1285
1286 TEST_F(CCLayerTreeHostImplTest, scrollScaledLayer)
1287 {
1288     setupScrollAndContentsLayers(IntSize(100, 100));
1289
1290     // Scale the layer to twice its normal size.
1291     int scale = 2;
1292     WebTransformationMatrix scaleTransform;
1293     scaleTransform.scale(scale);
1294     m_hostImpl->rootLayer()->setTransform(scaleTransform);
1295
1296     IntSize surfaceSize(50, 50);
1297     m_hostImpl->setViewportSize(surfaceSize, surfaceSize);
1298     initializeLayerRendererAndDrawFrame();
1299
1300     // Scroll down in screen coordinates with a gesture.
1301     IntSize scrollDelta(0, 10);
1302     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
1303     m_hostImpl->scrollBy(IntPoint(), scrollDelta);
1304     m_hostImpl->scrollEnd();
1305
1306     // The layer should have scrolled down in its local coordinates, but half he amount.
1307     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
1308     expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), IntSize(0, scrollDelta.height() / scale));
1309
1310     // Reset and scroll down with the wheel.
1311     m_hostImpl->rootLayer()->setScrollDelta(FloatSize());
1312     IntSize wheelScrollDelta(0, 10);
1313     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
1314     m_hostImpl->scrollBy(IntPoint(), wheelScrollDelta);
1315     m_hostImpl->scrollEnd();
1316
1317     // The scale should not have been applied to the scroll delta.
1318     scrollInfo = m_hostImpl->processScrollDeltas();
1319     expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), wheelScrollDelta);
1320 }
1321
1322 class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
1323 public:
1324     BlendStateTrackerContext() : m_blend(false) { }
1325
1326     virtual void enable(WGC3Denum cap)
1327     {
1328         if (cap == GraphicsContext3D::BLEND)
1329             m_blend = true;
1330     }
1331
1332     virtual void disable(WGC3Denum cap)
1333     {
1334         if (cap == GraphicsContext3D::BLEND)
1335             m_blend = false;
1336     }
1337
1338     bool blend() const { return m_blend; }
1339
1340 private:
1341     bool m_blend;
1342 };
1343
1344 class BlendStateCheckLayer : public CCLayerImpl {
1345 public:
1346     static PassOwnPtr<BlendStateCheckLayer> create(int id, CCResourceProvider* resourceProvider) { return adoptPtr(new BlendStateCheckLayer(id, resourceProvider)); }
1347
1348     virtual void appendQuads(CCQuadSink& quadList, const CCSharedQuadState* sharedQuadState, bool&) OVERRIDE
1349     {
1350         m_quadsAppended = true;
1351
1352         IntRect opaqueRect;
1353         if (opaque() || m_opaqueContents)
1354             opaqueRect = m_quadRect;
1355         else
1356             opaqueRect = m_opaqueContentRect;
1357         OwnPtr<CCDrawQuad> testBlendingDrawQuad = CCTileDrawQuad::create(sharedQuadState, m_quadRect, opaqueRect, m_resourceId, IntPoint(), IntSize(1, 1), 0, false, false, false, false, false);
1358         testBlendingDrawQuad->setQuadVisibleRect(m_quadVisibleRect);
1359         EXPECT_EQ(m_blend, testBlendingDrawQuad->needsBlending());
1360         EXPECT_EQ(m_hasRenderSurface, !!renderSurface());
1361         quadList.append(testBlendingDrawQuad.release());
1362     }
1363
1364     void setExpectation(bool blend, bool hasRenderSurface)
1365     {
1366         m_blend = blend;
1367         m_hasRenderSurface = hasRenderSurface;
1368         m_quadsAppended = false;
1369     }
1370
1371     bool quadsAppended() const { return m_quadsAppended; }
1372
1373     void setQuadRect(const IntRect& rect) { m_quadRect = rect; }
1374     void setQuadVisibleRect(const IntRect& rect) { m_quadVisibleRect = rect; }
1375     void setOpaqueContents(bool opaque) { m_opaqueContents = opaque; }
1376     void setOpaqueContentRect(const IntRect& rect) { m_opaqueContentRect = rect; }
1377
1378 private:
1379     explicit BlendStateCheckLayer(int id, CCResourceProvider* resourceProvider)
1380         : CCLayerImpl(id)
1381         , m_blend(false)
1382         , m_hasRenderSurface(false)
1383         , m_quadsAppended(false)
1384         , m_opaqueContents(false)
1385         , m_quadRect(5, 5, 5, 5)
1386         , m_quadVisibleRect(5, 5, 5, 5)
1387         , m_resourceId(resourceProvider->createResource(CCRenderer::ContentPool, IntSize(1, 1), GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageAny))
1388     {
1389         setAnchorPoint(FloatPoint(0, 0));
1390         setBounds(IntSize(10, 10));
1391         setContentBounds(IntSize(10, 10));
1392         setDrawsContent(true);
1393     }
1394
1395     bool m_blend;
1396     bool m_hasRenderSurface;
1397     bool m_quadsAppended;
1398     bool m_opaqueContents;
1399     IntRect m_quadRect;
1400     IntRect m_opaqueContentRect;
1401     IntRect m_quadVisibleRect;
1402     CCResourceProvider::ResourceId m_resourceId;
1403 };
1404
1405 TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
1406 {
1407     {
1408         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
1409         root->setAnchorPoint(FloatPoint(0, 0));
1410         root->setBounds(IntSize(10, 10));
1411         root->setContentBounds(root->bounds());
1412         root->setDrawsContent(false);
1413         m_hostImpl->setRootLayer(root.release());
1414     }
1415     CCLayerImpl* root = m_hostImpl->rootLayer();
1416
1417     root->addChild(BlendStateCheckLayer::create(2, m_hostImpl->resourceProvider()));
1418     BlendStateCheckLayer* layer1 = static_cast<BlendStateCheckLayer*>(root->children()[0].get());
1419     layer1->setPosition(FloatPoint(2, 2));
1420
1421     CCLayerTreeHostImpl::FrameData frame;
1422
1423     // Opaque layer, drawn without blending.
1424     layer1->setOpaque(true);
1425     layer1->setOpaqueContents(true);
1426     layer1->setExpectation(false, false);
1427     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1428     m_hostImpl->drawLayers(frame);
1429     EXPECT_TRUE(layer1->quadsAppended());
1430     m_hostImpl->didDrawAllLayers(frame);
1431
1432     // Layer with translucent content, but opaque content, so drawn without blending.
1433     layer1->setOpaque(false);
1434     layer1->setOpaqueContents(true);
1435     layer1->setExpectation(false, false);
1436     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1437     m_hostImpl->drawLayers(frame);
1438     EXPECT_TRUE(layer1->quadsAppended());
1439     m_hostImpl->didDrawAllLayers(frame);
1440
1441     // Layer with translucent content and painting, so drawn with blending.
1442     layer1->setOpaque(false);
1443     layer1->setOpaqueContents(false);
1444     layer1->setExpectation(true, false);
1445     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1446     m_hostImpl->drawLayers(frame);
1447     EXPECT_TRUE(layer1->quadsAppended());
1448     m_hostImpl->didDrawAllLayers(frame);
1449
1450     // Layer with translucent opacity, drawn with blending.
1451     layer1->setOpaque(true);
1452     layer1->setOpaqueContents(true);
1453     layer1->setOpacity(0.5);
1454     layer1->setExpectation(true, false);
1455     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1456     m_hostImpl->drawLayers(frame);
1457     EXPECT_TRUE(layer1->quadsAppended());
1458     m_hostImpl->didDrawAllLayers(frame);
1459
1460     // Layer with translucent opacity and painting, drawn with blending.
1461     layer1->setOpaque(true);
1462     layer1->setOpaqueContents(false);
1463     layer1->setOpacity(0.5);
1464     layer1->setExpectation(true, false);
1465     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1466     m_hostImpl->drawLayers(frame);
1467     EXPECT_TRUE(layer1->quadsAppended());
1468     m_hostImpl->didDrawAllLayers(frame);
1469
1470     layer1->addChild(BlendStateCheckLayer::create(3, m_hostImpl->resourceProvider()));
1471     BlendStateCheckLayer* layer2 = static_cast<BlendStateCheckLayer*>(layer1->children()[0].get());
1472     layer2->setPosition(FloatPoint(4, 4));
1473
1474     // 2 opaque layers, drawn without blending.
1475     layer1->setOpaque(true);
1476     layer1->setOpaqueContents(true);
1477     layer1->setOpacity(1);
1478     layer1->setExpectation(false, false);
1479     layer2->setOpaque(true);
1480     layer2->setOpaqueContents(true);
1481     layer2->setOpacity(1);
1482     layer2->setExpectation(false, false);
1483     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1484     m_hostImpl->drawLayers(frame);
1485     EXPECT_TRUE(layer1->quadsAppended());
1486     EXPECT_TRUE(layer2->quadsAppended());
1487     m_hostImpl->didDrawAllLayers(frame);
1488
1489     // Parent layer with translucent content, drawn with blending.
1490     // Child layer with opaque content, drawn without blending.
1491     layer1->setOpaque(false);
1492     layer1->setOpaqueContents(false);
1493     layer1->setExpectation(true, false);
1494     layer2->setExpectation(false, false);
1495     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1496     m_hostImpl->drawLayers(frame);
1497     EXPECT_TRUE(layer1->quadsAppended());
1498     EXPECT_TRUE(layer2->quadsAppended());
1499     m_hostImpl->didDrawAllLayers(frame);
1500
1501     // Parent layer with translucent content but opaque painting, drawn without blending.
1502     // Child layer with opaque content, drawn without blending.
1503     layer1->setOpaque(false);
1504     layer1->setOpaqueContents(true);
1505     layer1->setExpectation(false, false);
1506     layer2->setExpectation(false, false);
1507     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1508     m_hostImpl->drawLayers(frame);
1509     EXPECT_TRUE(layer1->quadsAppended());
1510     EXPECT_TRUE(layer2->quadsAppended());
1511     m_hostImpl->didDrawAllLayers(frame);
1512
1513     // Parent layer with translucent opacity and opaque content. Since it has a
1514     // drawing child, it's drawn to a render surface which carries the opacity,
1515     // so it's itself drawn without blending.
1516     // Child layer with opaque content, drawn without blending (parent surface
1517     // carries the inherited opacity).
1518     layer1->setOpaque(true);
1519     layer1->setOpaqueContents(true);
1520     layer1->setOpacity(0.5);
1521     layer1->setExpectation(false, true);
1522     layer2->setExpectation(false, false);
1523     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1524     m_hostImpl->drawLayers(frame);
1525     EXPECT_TRUE(layer1->quadsAppended());
1526     EXPECT_TRUE(layer2->quadsAppended());
1527     m_hostImpl->didDrawAllLayers(frame);
1528
1529     // Draw again, but with child non-opaque, to make sure
1530     // layer1 not culled.
1531     layer1->setOpaque(true);
1532     layer1->setOpaqueContents(true);
1533     layer1->setOpacity(1);
1534     layer1->setExpectation(false, false);
1535     layer2->setOpaque(true);
1536     layer2->setOpaqueContents(true);
1537     layer2->setOpacity(0.5);
1538     layer2->setExpectation(true, false);
1539     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1540     m_hostImpl->drawLayers(frame);
1541     EXPECT_TRUE(layer1->quadsAppended());
1542     EXPECT_TRUE(layer2->quadsAppended());
1543     m_hostImpl->didDrawAllLayers(frame);
1544
1545     // A second way of making the child non-opaque.
1546     layer1->setOpaque(true);
1547     layer1->setOpacity(1);
1548     layer1->setExpectation(false, false);
1549     layer2->setOpaque(false);
1550     layer2->setOpaqueContents(false);
1551     layer2->setOpacity(1);
1552     layer2->setExpectation(true, false);
1553     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1554     m_hostImpl->drawLayers(frame);
1555     EXPECT_TRUE(layer1->quadsAppended());
1556     EXPECT_TRUE(layer2->quadsAppended());
1557     m_hostImpl->didDrawAllLayers(frame);
1558
1559     // And when the layer says its not opaque but is painted opaque, it is not blended.
1560     layer1->setOpaque(true);
1561     layer1->setOpacity(1);
1562     layer1->setExpectation(false, false);
1563     layer2->setOpaque(false);
1564     layer2->setOpaqueContents(true);
1565     layer2->setOpacity(1);
1566     layer2->setExpectation(false, false);
1567     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1568     m_hostImpl->drawLayers(frame);
1569     EXPECT_TRUE(layer1->quadsAppended());
1570     EXPECT_TRUE(layer2->quadsAppended());
1571     m_hostImpl->didDrawAllLayers(frame);
1572
1573     // Layer with partially opaque contents, drawn with blending.
1574     layer1->setOpaque(false);
1575     layer1->setQuadRect(IntRect(5, 5, 5, 5));
1576     layer1->setQuadVisibleRect(IntRect(5, 5, 5, 5));
1577     layer1->setOpaqueContents(false);
1578     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
1579     layer1->setExpectation(true, false);
1580     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1581     m_hostImpl->drawLayers(frame);
1582     EXPECT_TRUE(layer1->quadsAppended());
1583     m_hostImpl->didDrawAllLayers(frame);
1584
1585     // Layer with partially opaque contents partially culled, drawn with blending.
1586     layer1->setOpaque(false);
1587     layer1->setQuadRect(IntRect(5, 5, 5, 5));
1588     layer1->setQuadVisibleRect(IntRect(5, 5, 5, 2));
1589     layer1->setOpaqueContents(false);
1590     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
1591     layer1->setExpectation(true, false);
1592     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1593     m_hostImpl->drawLayers(frame);
1594     EXPECT_TRUE(layer1->quadsAppended());
1595     m_hostImpl->didDrawAllLayers(frame);
1596
1597     // Layer with partially opaque contents culled, drawn with blending.
1598     layer1->setOpaque(false);
1599     layer1->setQuadRect(IntRect(5, 5, 5, 5));
1600     layer1->setQuadVisibleRect(IntRect(7, 5, 3, 5));
1601     layer1->setOpaqueContents(false);
1602     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
1603     layer1->setExpectation(true, false);
1604     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1605     m_hostImpl->drawLayers(frame);
1606     EXPECT_TRUE(layer1->quadsAppended());
1607     m_hostImpl->didDrawAllLayers(frame);
1608
1609     // Layer with partially opaque contents and translucent contents culled, drawn without blending.
1610     layer1->setOpaque(false);
1611     layer1->setQuadRect(IntRect(5, 5, 5, 5));
1612     layer1->setQuadVisibleRect(IntRect(5, 5, 2, 5));
1613     layer1->setOpaqueContents(false);
1614     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
1615     layer1->setExpectation(false, false);
1616     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1617     m_hostImpl->drawLayers(frame);
1618     EXPECT_TRUE(layer1->quadsAppended());
1619     m_hostImpl->didDrawAllLayers(frame);
1620
1621 }
1622
1623 TEST_F(CCLayerTreeHostImplTest, viewportCovered)
1624 {
1625     m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
1626     m_hostImpl->setBackgroundColor(SK_ColorGRAY);
1627
1628     IntSize viewportSize(1000, 1000);
1629     m_hostImpl->setViewportSize(viewportSize, viewportSize);
1630
1631     m_hostImpl->setRootLayer(BlendStateCheckLayer::create(1, m_hostImpl->resourceProvider()));
1632     BlendStateCheckLayer* root = static_cast<BlendStateCheckLayer*>(m_hostImpl->rootLayer());
1633     root->setExpectation(false, true);
1634     root->setOpaque(true);
1635
1636     // No gutter rects
1637     {
1638         IntRect layerRect(0, 0, 1000, 1000);
1639         root->setPosition(layerRect.location());
1640         root->setBounds(layerRect.size());
1641         root->setContentBounds(layerRect.size());
1642         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
1643         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
1644
1645         CCLayerTreeHostImpl::FrameData frame;
1646         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1647         ASSERT_EQ(1u, frame.renderPasses.size());
1648
1649         size_t numGutterQuads = 0;
1650         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
1651             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
1652         EXPECT_EQ(0u, numGutterQuads);
1653         EXPECT_EQ(1u, frame.renderPasses[0]->quadList().size());
1654
1655         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
1656         m_hostImpl->didDrawAllLayers(frame);
1657     }
1658
1659     // Empty visible content area (fullscreen gutter rect)
1660     {
1661         IntRect layerRect(0, 0, 0, 0);
1662         root->setPosition(layerRect.location());
1663         root->setBounds(layerRect.size());
1664         root->setContentBounds(layerRect.size());
1665         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
1666         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
1667
1668         CCLayerTreeHostImpl::FrameData frame;
1669         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1670         ASSERT_EQ(1u, frame.renderPasses.size());
1671         m_hostImpl->didDrawAllLayers(frame);
1672
1673         size_t numGutterQuads = 0;
1674         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
1675             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
1676         EXPECT_EQ(1u, numGutterQuads);
1677         EXPECT_EQ(1u, frame.renderPasses[0]->quadList().size());
1678
1679         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
1680         m_hostImpl->didDrawAllLayers(frame);
1681     }
1682
1683     // Content area in middle of clip rect (four surrounding gutter rects)
1684     {
1685         IntRect layerRect(500, 500, 200, 200);
1686         root->setPosition(layerRect.location());
1687         root->setBounds(layerRect.size());
1688         root->setContentBounds(layerRect.size());
1689         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
1690         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
1691
1692         CCLayerTreeHostImpl::FrameData frame;
1693         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1694         ASSERT_EQ(1u, frame.renderPasses.size());
1695
1696         size_t numGutterQuads = 0;
1697         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
1698             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
1699         EXPECT_EQ(4u, numGutterQuads);
1700         EXPECT_EQ(5u, frame.renderPasses[0]->quadList().size());
1701
1702         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
1703         m_hostImpl->didDrawAllLayers(frame);
1704     }
1705
1706 }
1707
1708
1709 class ReshapeTrackerContext: public FakeWebGraphicsContext3D {
1710 public:
1711     ReshapeTrackerContext() : m_reshapeCalled(false) { }
1712
1713     virtual void reshape(int width, int height)
1714     {
1715         m_reshapeCalled = true;
1716     }
1717
1718     bool reshapeCalled() const { return m_reshapeCalled; }
1719
1720 private:
1721     bool m_reshapeCalled;
1722 };
1723
1724 class FakeDrawableCCLayerImpl: public CCLayerImpl {
1725 public:
1726     explicit FakeDrawableCCLayerImpl(int id) : CCLayerImpl(id) { }
1727 };
1728
1729 // Only reshape when we know we are going to draw. Otherwise, the reshape
1730 // can leave the window at the wrong size if we never draw and the proper
1731 // viewport size is never set.
1732 TEST_F(CCLayerTreeHostImplTest, reshapeNotCalledUntilDraw)
1733 {
1734     OwnPtr<CCGraphicsContext> ccContext = FakeWebCompositorOutputSurface::create(adoptPtr(new ReshapeTrackerContext));
1735     ReshapeTrackerContext* reshapeTracker = static_cast<ReshapeTrackerContext*>(ccContext->context3D());
1736     m_hostImpl->initializeLayerRenderer(ccContext.release(), UnthrottledUploader);
1737
1738     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
1739     root->setAnchorPoint(FloatPoint(0, 0));
1740     root->setBounds(IntSize(10, 10));
1741     root->setDrawsContent(true);
1742     m_hostImpl->setRootLayer(adoptPtr(root));
1743     EXPECT_FALSE(reshapeTracker->reshapeCalled());
1744
1745     CCLayerTreeHostImpl::FrameData frame;
1746     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1747     m_hostImpl->drawLayers(frame);
1748     EXPECT_TRUE(reshapeTracker->reshapeCalled());
1749     m_hostImpl->didDrawAllLayers(frame);
1750 }
1751
1752 class PartialSwapTrackerContext : public FakeWebGraphicsContext3D {
1753 public:
1754     virtual void postSubBufferCHROMIUM(int x, int y, int width, int height)
1755     {
1756         m_partialSwapRect = IntRect(x, y, width, height);
1757     }
1758
1759     virtual WebString getString(WGC3Denum name)
1760     {
1761         if (name == GraphicsContext3D::EXTENSIONS)
1762             return WebString("GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
1763
1764         return WebString();
1765     }
1766
1767     IntRect partialSwapRect() const { return m_partialSwapRect; }
1768
1769 private:
1770     IntRect m_partialSwapRect;
1771 };
1772
1773 // Make sure damage tracking propagates all the way to the graphics context,
1774 // where it should request to swap only the subBuffer that is damaged.
1775 TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
1776 {
1777     OwnPtr<CCGraphicsContext> ccContext = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapTrackerContext));
1778     PartialSwapTrackerContext* partialSwapTracker = static_cast<PartialSwapTrackerContext*>(ccContext->context3D());
1779
1780     // This test creates its own CCLayerTreeHostImpl, so
1781     // that we can force partial swap enabled.
1782     CCLayerTreeSettings settings;
1783     CCSettings::setPartialSwapEnabled(true);
1784     OwnPtr<CCLayerTreeHostImpl> layerTreeHostImpl = CCLayerTreeHostImpl::create(settings, this);
1785     layerTreeHostImpl->initializeLayerRenderer(ccContext.release(), UnthrottledUploader);
1786     layerTreeHostImpl->setViewportSize(IntSize(500, 500), IntSize(500, 500));
1787
1788     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
1789     CCLayerImpl* child = new FakeDrawableCCLayerImpl(2);
1790     child->setPosition(FloatPoint(12, 13));
1791     child->setAnchorPoint(FloatPoint(0, 0));
1792     child->setBounds(IntSize(14, 15));
1793     child->setContentBounds(IntSize(14, 15));
1794     child->setDrawsContent(true);
1795     root->setAnchorPoint(FloatPoint(0, 0));
1796     root->setBounds(IntSize(500, 500));
1797     root->setContentBounds(IntSize(500, 500));
1798     root->setDrawsContent(true);
1799     root->addChild(adoptPtr(child));
1800     layerTreeHostImpl->setRootLayer(adoptPtr(root));
1801
1802     CCLayerTreeHostImpl::FrameData frame;
1803
1804     // First frame, the entire screen should get swapped.
1805     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1806     layerTreeHostImpl->drawLayers(frame);
1807     layerTreeHostImpl->didDrawAllLayers(frame);
1808     layerTreeHostImpl->swapBuffers();
1809     IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
1810     IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
1811     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1812     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1813     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1814     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1815
1816     // Second frame, only the damaged area should get swapped. Damage should be the union
1817     // of old and new child rects.
1818     // expected damage rect: IntRect(IntPoint::zero(), IntSize(26, 28));
1819     // expected swap rect: vertically flipped, with origin at bottom left corner.
1820     child->setPosition(FloatPoint(0, 0));
1821     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1822     layerTreeHostImpl->drawLayers(frame);
1823     m_hostImpl->didDrawAllLayers(frame);
1824     layerTreeHostImpl->swapBuffers();
1825     actualSwapRect = partialSwapTracker->partialSwapRect();
1826     expectedSwapRect = IntRect(IntPoint(0, 500-28), IntSize(26, 28));
1827     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1828     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1829     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1830     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1831
1832     // Make sure that partial swap is constrained to the viewport dimensions
1833     // expected damage rect: IntRect(IntPoint::zero(), IntSize(500, 500));
1834     // expected swap rect: flipped damage rect, but also clamped to viewport
1835     layerTreeHostImpl->setViewportSize(IntSize(10, 10), IntSize(10, 10));
1836     root->setOpacity(0.7f); // this will damage everything
1837     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1838     layerTreeHostImpl->drawLayers(frame);
1839     m_hostImpl->didDrawAllLayers(frame);
1840     layerTreeHostImpl->swapBuffers();
1841     actualSwapRect = partialSwapTracker->partialSwapRect();
1842     expectedSwapRect = IntRect(IntPoint::zero(), IntSize(10, 10));
1843     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1844     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1845     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1846     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1847 }
1848
1849 TEST_F(CCLayerTreeHostImplTest, rootLayerDoesntCreateExtraSurface)
1850 {
1851     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
1852     CCLayerImpl* child = new FakeDrawableCCLayerImpl(2);
1853     child->setAnchorPoint(FloatPoint(0, 0));
1854     child->setBounds(IntSize(10, 10));
1855     child->setContentBounds(IntSize(10, 10));
1856     child->setDrawsContent(true);
1857     root->setAnchorPoint(FloatPoint(0, 0));
1858     root->setBounds(IntSize(10, 10));
1859     root->setContentBounds(IntSize(10, 10));
1860     root->setDrawsContent(true);
1861     root->setOpacity(0.7f);
1862     root->addChild(adoptPtr(child));
1863
1864     m_hostImpl->setRootLayer(adoptPtr(root));
1865
1866     CCLayerTreeHostImpl::FrameData frame;
1867
1868     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1869     EXPECT_EQ(1u, frame.renderSurfaceLayerList->size());
1870     EXPECT_EQ(1u, frame.renderPasses.size());
1871     m_hostImpl->didDrawAllLayers(frame);
1872 }
1873
1874 } // namespace
1875
1876 class FakeLayerWithQuads : public CCLayerImpl {
1877 public:
1878     static PassOwnPtr<FakeLayerWithQuads> create(int id) { return adoptPtr(new FakeLayerWithQuads(id)); }
1879
1880     virtual void appendQuads(CCQuadSink& quadList, const CCSharedQuadState* sharedQuadState, bool&) OVERRIDE
1881     {
1882         SkColor gray = SkColorSetRGB(100, 100, 100);
1883         IntRect quadRect(IntPoint(0, 0), contentBounds());
1884         OwnPtr<CCDrawQuad> myQuad = CCSolidColorDrawQuad::create(sharedQuadState, quadRect, gray);
1885         quadList.append(myQuad.release());
1886     }
1887
1888 private:
1889     FakeLayerWithQuads(int id)
1890         : CCLayerImpl(id)
1891     {
1892     }
1893 };
1894
1895 namespace {
1896
1897 class MockContext : public FakeWebGraphicsContext3D {
1898 public:
1899     MOCK_METHOD1(useProgram, void(WebGLId program));
1900     MOCK_METHOD5(uniform4f, void(WGC3Dint location, WGC3Dfloat x, WGC3Dfloat y, WGC3Dfloat z, WGC3Dfloat w));
1901     MOCK_METHOD4(uniformMatrix4fv, void(WGC3Dint location, WGC3Dsizei count, WGC3Dboolean transpose, const WGC3Dfloat* value));
1902     MOCK_METHOD4(drawElements, void(WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset));
1903     MOCK_METHOD1(getString, WebString(WGC3Denum name));
1904     MOCK_METHOD0(getRequestableExtensionsCHROMIUM, WebString());
1905     MOCK_METHOD1(enable, void(WGC3Denum cap));
1906     MOCK_METHOD1(disable, void(WGC3Denum cap));
1907     MOCK_METHOD4(scissor, void(WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height));
1908 };
1909
1910 class MockContextHarness {
1911 private:
1912     MockContext* m_context;
1913 public:
1914     MockContextHarness(MockContext* context)
1915         : m_context(context)
1916     {
1917         // Catch "uninteresting" calls
1918         EXPECT_CALL(*m_context, useProgram(_))
1919             .Times(0);
1920
1921         EXPECT_CALL(*m_context, drawElements(_, _, _, _))
1922             .Times(0);
1923
1924         // These are not asserted
1925         EXPECT_CALL(*m_context, uniformMatrix4fv(_, _, _, _))
1926             .WillRepeatedly(Return());
1927
1928         EXPECT_CALL(*m_context, uniform4f(_, _, _, _, _))
1929             .WillRepeatedly(Return());
1930
1931         // Any other strings are empty
1932         EXPECT_CALL(*m_context, getString(_))
1933             .WillRepeatedly(Return(WebString()));
1934
1935         // Support for partial swap, if needed
1936         EXPECT_CALL(*m_context, getString(GraphicsContext3D::EXTENSIONS))
1937             .WillRepeatedly(Return(WebString("GL_CHROMIUM_post_sub_buffer")));
1938
1939         EXPECT_CALL(*m_context, getRequestableExtensionsCHROMIUM())
1940             .WillRepeatedly(Return(WebString("GL_CHROMIUM_post_sub_buffer")));
1941
1942         // Any un-sanctioned calls to enable() are OK
1943         EXPECT_CALL(*m_context, enable(_))
1944             .WillRepeatedly(Return());
1945
1946         // Any un-sanctioned calls to disable() are OK
1947         EXPECT_CALL(*m_context, disable(_))
1948             .WillRepeatedly(Return());
1949     }
1950
1951     void mustDrawSolidQuad()
1952     {
1953         EXPECT_CALL(*m_context, drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0))
1954             .WillOnce(Return())
1955             .RetiresOnSaturation();
1956
1957         // 1 is hardcoded return value of fake createProgram()
1958         EXPECT_CALL(*m_context, useProgram(1))
1959             .WillOnce(Return())
1960             .RetiresOnSaturation();
1961
1962     }
1963
1964     void mustSetScissor(int x, int y, int width, int height)
1965     {
1966         EXPECT_CALL(*m_context, enable(GraphicsContext3D::SCISSOR_TEST))
1967             .WillRepeatedly(Return());
1968
1969         EXPECT_CALL(*m_context, scissor(x, y, width, height))
1970             .Times(AtLeast(1))
1971             .WillRepeatedly(Return());
1972     }
1973
1974     void mustSetNoScissor()
1975     {
1976         EXPECT_CALL(*m_context, disable(GraphicsContext3D::SCISSOR_TEST))
1977             .WillRepeatedly(Return());
1978
1979         EXPECT_CALL(*m_context, enable(GraphicsContext3D::SCISSOR_TEST))
1980             .Times(0);
1981
1982         EXPECT_CALL(*m_context, scissor(_, _, _, _))
1983             .Times(0);
1984     }
1985 };
1986
1987 TEST_F(CCLayerTreeHostImplTest, noPartialSwap)
1988 {
1989     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new MockContext));
1990     MockContext* mockContext = static_cast<MockContext*>(context->context3D());
1991     MockContextHarness harness(mockContext);
1992
1993     harness.mustDrawSolidQuad();
1994     harness.mustSetScissor(0, 0, 10, 10);
1995
1996     // Run test case
1997     OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(false, context.release(), FakeLayerWithQuads::create(1));
1998
1999     CCLayerTreeHostImpl::FrameData frame;
2000     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2001     myHostImpl->drawLayers(frame);
2002     myHostImpl->didDrawAllLayers(frame);
2003     Mock::VerifyAndClearExpectations(&mockContext);
2004 }
2005
2006 TEST_F(CCLayerTreeHostImplTest, partialSwap)
2007 {
2008     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new MockContext));
2009     MockContext* mockContext = static_cast<MockContext*>(context->context3D());
2010     MockContextHarness harness(mockContext);
2011
2012     OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(true, context.release(), FakeLayerWithQuads::create(1));
2013
2014     // The first frame is not a partially-swapped one.
2015     harness.mustSetScissor(0, 0, 10, 10);
2016     harness.mustDrawSolidQuad();
2017     {
2018         CCLayerTreeHostImpl::FrameData frame;
2019         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2020         myHostImpl->drawLayers(frame);
2021         myHostImpl->didDrawAllLayers(frame);
2022     }
2023     Mock::VerifyAndClearExpectations(&mockContext);
2024
2025     // Damage a portion of the frame.
2026     myHostImpl->rootLayer()->setUpdateRect(IntRect(0, 0, 2, 3));
2027
2028     // The second frame will be partially-swapped (the y coordinates are flipped).
2029     harness.mustSetScissor(0, 7, 2, 3);
2030     harness.mustDrawSolidQuad();
2031     {
2032         CCLayerTreeHostImpl::FrameData frame;
2033         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2034         myHostImpl->drawLayers(frame);
2035         myHostImpl->didDrawAllLayers(frame);
2036     }
2037     Mock::VerifyAndClearExpectations(&mockContext);
2038 }
2039
2040 class PartialSwapContext : public FakeWebGraphicsContext3D {
2041 public:
2042     WebString getString(WGC3Denum name)
2043     {
2044         if (name == GraphicsContext3D::EXTENSIONS)
2045             return WebString("GL_CHROMIUM_post_sub_buffer");
2046         return WebString();
2047     }
2048
2049     WebString getRequestableExtensionsCHROMIUM()
2050     {
2051         return WebString("GL_CHROMIUM_post_sub_buffer");
2052     }
2053
2054     // Unlimited texture size.
2055     virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value)
2056     {
2057         if (pname == WebCore::GraphicsContext3D::MAX_TEXTURE_SIZE)
2058             *value = 8192;
2059     }
2060 };
2061
2062 static PassOwnPtr<CCLayerTreeHostImpl> setupLayersForOpacity(bool partialSwap, CCLayerTreeHostImplClient* client)
2063 {
2064     CCSettings::setPartialSwapEnabled(partialSwap);
2065
2066     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext));
2067
2068     CCLayerTreeSettings settings;
2069     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, client);
2070     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
2071     myHostImpl->setViewportSize(IntSize(100, 100), IntSize(100, 100));
2072
2073     /*
2074       Layers are created as follows:
2075
2076          +--------------------+
2077          |                  1 |
2078          |  +-----------+     |
2079          |  |         2 |     |
2080          |  | +-------------------+
2081          |  | |   3               |
2082          |  | +-------------------+
2083          |  |           |     |
2084          |  +-----------+     |
2085          |                    |
2086          |                    |
2087          +--------------------+
2088
2089          Layers 1, 2 have render surfaces
2090      */
2091     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
2092     OwnPtr<CCLayerImpl> child = CCLayerImpl::create(2);
2093     OwnPtr<CCLayerImpl> grandChild = FakeLayerWithQuads::create(3);
2094
2095     IntRect rootRect(0, 0, 100, 100);
2096     IntRect childRect(10, 10, 50, 50);
2097     IntRect grandChildRect(5, 5, 150, 150);
2098
2099     root->createRenderSurface();
2100     root->setAnchorPoint(FloatPoint(0, 0));
2101     root->setPosition(FloatPoint(rootRect.x(), rootRect.y()));
2102     root->setBounds(IntSize(rootRect.width(), rootRect.height()));
2103     root->setContentBounds(root->bounds());
2104     root->setVisibleContentRect(rootRect);
2105     root->setDrawsContent(false);
2106     root->renderSurface()->setContentRect(IntRect(IntPoint(), IntSize(rootRect.width(), rootRect.height())));
2107
2108     child->setAnchorPoint(FloatPoint(0, 0));
2109     child->setPosition(FloatPoint(childRect.x(), childRect.y()));
2110     child->setOpacity(0.5f);
2111     child->setBounds(IntSize(childRect.width(), childRect.height()));
2112     child->setContentBounds(child->bounds());
2113     child->setVisibleContentRect(childRect);
2114     child->setDrawsContent(false);
2115
2116     grandChild->setAnchorPoint(FloatPoint(0, 0));
2117     grandChild->setPosition(IntPoint(grandChildRect.x(), grandChildRect.y()));
2118     grandChild->setBounds(IntSize(grandChildRect.width(), grandChildRect.height()));
2119     grandChild->setContentBounds(grandChild->bounds());
2120     grandChild->setVisibleContentRect(grandChildRect);
2121     grandChild->setDrawsContent(true);
2122
2123     child->addChild(grandChild.release());
2124     root->addChild(child.release());
2125
2126     myHostImpl->setRootLayer(root.release());
2127     return myHostImpl.release();
2128 }
2129
2130 TEST_F(CCLayerTreeHostImplTest, contributingLayerEmptyScissorPartialSwap)
2131 {
2132     OwnPtr<CCLayerTreeHostImpl> myHostImpl = setupLayersForOpacity(true, this);
2133
2134     {
2135         CCLayerTreeHostImpl::FrameData frame;
2136         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2137
2138         // Just for consistency, the most interesting stuff already happened
2139         myHostImpl->drawLayers(frame);
2140         myHostImpl->didDrawAllLayers(frame);
2141
2142         // Verify all quads have been computed
2143         ASSERT_EQ(2U, frame.renderPasses.size());
2144         ASSERT_EQ(1U, frame.renderPasses[0]->quadList().size());
2145         ASSERT_EQ(1U, frame.renderPasses[1]->quadList().size());
2146         EXPECT_EQ(CCDrawQuad::SolidColor, frame.renderPasses[0]->quadList()[0]->material());
2147         EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[1]->quadList()[0]->material());
2148     }
2149 }
2150
2151 TEST_F(CCLayerTreeHostImplTest, contributingLayerEmptyScissorNoPartialSwap)
2152 {
2153     OwnPtr<CCLayerTreeHostImpl> myHostImpl = setupLayersForOpacity(false, this);
2154
2155     {
2156         CCLayerTreeHostImpl::FrameData frame;
2157         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2158
2159         // Just for consistency, the most interesting stuff already happened
2160         myHostImpl->drawLayers(frame);
2161         myHostImpl->didDrawAllLayers(frame);
2162
2163         // Verify all quads have been computed
2164         ASSERT_EQ(2U, frame.renderPasses.size());
2165         ASSERT_EQ(1U, frame.renderPasses[0]->quadList().size());
2166         ASSERT_EQ(1U, frame.renderPasses[1]->quadList().size());
2167         EXPECT_EQ(CCDrawQuad::SolidColor, frame.renderPasses[0]->quadList()[0]->material());
2168         EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[1]->quadList()[0]->material());
2169     }
2170 }
2171
2172 // Make sure that context lost notifications are propagated through the tree.
2173 class ContextLostNotificationCheckLayer : public CCLayerImpl {
2174 public:
2175     static PassOwnPtr<ContextLostNotificationCheckLayer> create(int id) { return adoptPtr(new ContextLostNotificationCheckLayer(id)); }
2176
2177     virtual void didLoseContext() OVERRIDE
2178     {
2179         m_didLoseContextCalled = true;
2180     }
2181
2182     bool didLoseContextCalled() const { return m_didLoseContextCalled; }
2183
2184 private:
2185     explicit ContextLostNotificationCheckLayer(int id)
2186         : CCLayerImpl(id)
2187         , m_didLoseContextCalled(false)
2188     {
2189     }
2190
2191     bool m_didLoseContextCalled;
2192 };
2193
2194 TEST_F(CCLayerTreeHostImplTest, contextLostAndRestoredNotificationSentToAllLayers)
2195 {
2196     m_hostImpl->setRootLayer(ContextLostNotificationCheckLayer::create(1));
2197     ContextLostNotificationCheckLayer* root = static_cast<ContextLostNotificationCheckLayer*>(m_hostImpl->rootLayer());
2198
2199     root->addChild(ContextLostNotificationCheckLayer::create(1));
2200     ContextLostNotificationCheckLayer* layer1 = static_cast<ContextLostNotificationCheckLayer*>(root->children()[0].get());
2201
2202     layer1->addChild(ContextLostNotificationCheckLayer::create(2));
2203     ContextLostNotificationCheckLayer* layer2 = static_cast<ContextLostNotificationCheckLayer*>(layer1->children()[0].get());
2204
2205     EXPECT_FALSE(root->didLoseContextCalled());
2206     EXPECT_FALSE(layer1->didLoseContextCalled());
2207     EXPECT_FALSE(layer2->didLoseContextCalled());
2208
2209     m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
2210
2211     EXPECT_TRUE(root->didLoseContextCalled());
2212     EXPECT_TRUE(layer1->didLoseContextCalled());
2213     EXPECT_TRUE(layer2->didLoseContextCalled());
2214 }
2215
2216 TEST_F(CCLayerTreeHostImplTest, finishAllRenderingAfterContextLost)
2217 {
2218     CCLayerTreeSettings settings;
2219     m_hostImpl = CCLayerTreeHostImpl::create(settings, this);
2220
2221     // The context initialization will fail, but we should still be able to call finishAllRendering() without any ill effects.
2222     m_hostImpl->initializeLayerRenderer(FakeWebCompositorOutputSurface::create(adoptPtr(new FakeWebGraphicsContext3DMakeCurrentFails)), UnthrottledUploader);
2223     m_hostImpl->finishAllRendering();
2224 }
2225
2226 // Fake WebGraphicsContext3D that will cause a failure if trying to use a
2227 // resource that wasn't created by it (resources created by
2228 // FakeWebGraphicsContext3D have an id of 1).
2229 class StrictWebGraphicsContext3D : public FakeWebGraphicsContext3D {
2230 public:
2231     StrictWebGraphicsContext3D()
2232         : FakeWebGraphicsContext3D()
2233     {
2234         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.
2235     }
2236
2237     virtual WebGLId createBuffer() { return 2; }
2238     virtual WebGLId createFramebuffer() { return 3; }
2239     virtual WebGLId createProgram() { return 4; }
2240     virtual WebGLId createRenderbuffer() { return 5; }
2241     virtual WebGLId createShader(WGC3Denum) { return 6; }
2242
2243     virtual void deleteBuffer(WebGLId id)
2244     {
2245         if (id != 2)
2246             ADD_FAILURE() << "Trying to delete buffer id " << id;
2247     }
2248
2249     virtual void deleteFramebuffer(WebGLId id)
2250     {
2251         if (id != 3)
2252             ADD_FAILURE() << "Trying to delete framebuffer id " << id;
2253     }
2254
2255     virtual void deleteProgram(WebGLId id)
2256     {
2257         if (id != 4)
2258             ADD_FAILURE() << "Trying to delete program id " << id;
2259     }
2260
2261     virtual void deleteRenderbuffer(WebGLId id)
2262     {
2263         if (id != 5)
2264             ADD_FAILURE() << "Trying to delete renderbuffer id " << id;
2265     }
2266
2267     virtual void deleteShader(WebGLId id)
2268     {
2269         if (id != 6)
2270             ADD_FAILURE() << "Trying to delete shader id " << id;
2271     }
2272
2273     virtual WebGLId createTexture()
2274     {
2275         unsigned textureId = FakeWebGraphicsContext3D::createTexture();
2276         m_allocatedTextureIds.add(textureId);
2277         return textureId;
2278     }
2279     virtual void deleteTexture(WebGLId id)
2280     {
2281         if (!m_allocatedTextureIds.contains(id))
2282             ADD_FAILURE() << "Trying to delete texture id " << id;
2283         m_allocatedTextureIds.remove(id);
2284     }
2285
2286     virtual void bindBuffer(WGC3Denum, WebGLId id)
2287     {
2288         if (id != 2 && id)
2289             ADD_FAILURE() << "Trying to bind buffer id " << id;
2290     }
2291
2292     virtual void bindFramebuffer(WGC3Denum, WebGLId id)
2293     {
2294         if (id != 3 && id)
2295             ADD_FAILURE() << "Trying to bind framebuffer id " << id;
2296     }
2297
2298     virtual void useProgram(WebGLId id)
2299     {
2300         if (id != 4)
2301             ADD_FAILURE() << "Trying to use program id " << id;
2302     }
2303
2304     virtual void bindRenderbuffer(WGC3Denum, WebGLId id)
2305     {
2306         if (id != 5 && id)
2307             ADD_FAILURE() << "Trying to bind renderbuffer id " << id;
2308     }
2309
2310     virtual void attachShader(WebGLId program, WebGLId shader)
2311     {
2312         if ((program != 4) || (shader != 6))
2313             ADD_FAILURE() << "Trying to attach shader id " << shader << " to program id " << program;
2314     }
2315
2316     virtual void bindTexture(WGC3Denum, WebGLId id)
2317     {
2318         if (id && !m_allocatedTextureIds.contains(id))
2319             ADD_FAILURE() << "Trying to bind texture id " << id;
2320     }
2321
2322 private:
2323     HashSet<unsigned> m_allocatedTextureIds;
2324 };
2325
2326 // Fake video frame that represents a 4x4 YUV video frame.
2327 class FakeVideoFrame: public WebVideoFrame {
2328 public:
2329     FakeVideoFrame() : m_textureId(0) { memset(m_data, 0x80, sizeof(m_data)); }
2330     virtual ~FakeVideoFrame() { }
2331     virtual Format format() const { return m_textureId ? FormatNativeTexture : FormatYV12; }
2332     virtual unsigned width() const { return 4; }
2333     virtual unsigned height() const { return 4; }
2334     virtual unsigned planes() const { return 3; }
2335     virtual int stride(unsigned plane) const { return 4; }
2336     virtual const void* data(unsigned plane) const { return m_data; }
2337     virtual unsigned textureId() const { return m_textureId; }
2338     virtual unsigned textureTarget() const { return m_textureId ? GraphicsContext3D::TEXTURE_2D : 0; }
2339
2340     void setTextureId(unsigned id) { m_textureId = id; }
2341
2342 private:
2343     char m_data[16];
2344     unsigned m_textureId;
2345 };
2346
2347 // Fake video frame provider that always provides the same FakeVideoFrame.
2348 class FakeVideoFrameProvider: public WebVideoFrameProvider {
2349 public:
2350     FakeVideoFrameProvider() : m_frame(0), m_client(0) { }
2351     virtual ~FakeVideoFrameProvider()
2352     {
2353         if (m_client)
2354             m_client->stopUsingProvider();
2355     }
2356
2357     virtual void setVideoFrameProviderClient(Client* client) { m_client = client; }
2358     virtual WebVideoFrame* getCurrentFrame() { return m_frame; }
2359     virtual void putCurrentFrame(WebVideoFrame*) { }
2360
2361     void setFrame(WebVideoFrame* frame) { m_frame = frame; }
2362
2363 private:
2364     WebVideoFrame* m_frame;
2365     Client* m_client;
2366 };
2367
2368 class StrictWebGraphicsContext3DWithIOSurface : public StrictWebGraphicsContext3D {
2369 public:
2370     virtual WebString getString(WGC3Denum name) OVERRIDE
2371     {
2372         if (name == WebCore::GraphicsContext3D::EXTENSIONS)
2373             return WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2374
2375         return WebString();
2376     }
2377 };
2378
2379 class FakeWebGraphicsContext3DWithIOSurface : public FakeWebGraphicsContext3D {
2380 public:
2381     virtual WebString getString(WGC3Denum name) OVERRIDE
2382     {
2383         if (name == WebCore::GraphicsContext3D::EXTENSIONS)
2384             return WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2385
2386         return WebString();
2387     }
2388 };
2389
2390 class FakeWebScrollbarThemeGeometryNonEmpty : public FakeWebScrollbarThemeGeometry {
2391     virtual WebRect trackRect(WebScrollbar*) OVERRIDE { return WebRect(0, 0, 10, 10); }
2392     virtual WebRect thumbRect(WebScrollbar*) OVERRIDE { return WebRect(0, 5, 5, 2); }
2393     virtual void splitTrack(WebScrollbar*, const WebRect& track, WebRect& startTrack, WebRect& thumb, WebRect& endTrack) OVERRIDE
2394     {
2395         thumb = WebRect(0, 5, 5, 2);
2396         startTrack = WebRect(0, 5, 0, 5);
2397         endTrack = WebRect(0, 0, 0, 5);
2398     }
2399 };
2400
2401 class FakeScrollbarLayerImpl : public CCScrollbarLayerImpl {
2402 public:
2403     static PassOwnPtr<FakeScrollbarLayerImpl> create(int id)
2404     {
2405         return adoptPtr(new FakeScrollbarLayerImpl(id));
2406     }
2407
2408     void createResources(CCResourceProvider* provider)
2409     {
2410         ASSERT(provider);
2411         int pool = 0;
2412         IntSize size(10, 10);
2413         GC3Denum format = GraphicsContext3D::RGBA;
2414         CCResourceProvider::TextureUsageHint hint = CCResourceProvider::TextureUsageAny;
2415         setScrollbarGeometry(FakeWebScrollbarThemeGeometryNonEmpty::create());
2416
2417         setBackTrackResourceId(provider->createResource(pool, size, format, hint));
2418         setForeTrackResourceId(provider->createResource(pool, size, format, hint));
2419         setThumbResourceId(provider->createResource(pool, size, format, hint));
2420     }
2421
2422 protected:
2423     explicit FakeScrollbarLayerImpl(int id)
2424         : CCScrollbarLayerImpl(id)
2425     {
2426     }
2427 };
2428
2429 TEST_F(CCLayerTreeHostImplTest, dontUseOldResourcesAfterLostContext)
2430 {
2431     OwnPtr<CCLayerImpl> rootLayer(CCLayerImpl::create(1));
2432     rootLayer->setBounds(IntSize(10, 10));
2433     rootLayer->setAnchorPoint(FloatPoint(0, 0));
2434
2435     OwnPtr<CCTiledLayerImpl> tileLayer = CCTiledLayerImpl::create(2);
2436     tileLayer->setBounds(IntSize(10, 10));
2437     tileLayer->setAnchorPoint(FloatPoint(0, 0));
2438     tileLayer->setContentBounds(IntSize(10, 10));
2439     tileLayer->setDrawsContent(true);
2440     tileLayer->setSkipsDraw(false);
2441     OwnPtr<CCLayerTilingData> tilingData(CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels));
2442     tilingData->setBounds(IntSize(10, 10));
2443     tileLayer->setTilingData(*tilingData);
2444     tileLayer->pushTileProperties(0, 0, 1, IntRect(0, 0, 10, 10));
2445     rootLayer->addChild(tileLayer.release());
2446
2447     OwnPtr<CCTextureLayerImpl> textureLayer = CCTextureLayerImpl::create(3);
2448     textureLayer->setBounds(IntSize(10, 10));
2449     textureLayer->setAnchorPoint(FloatPoint(0, 0));
2450     textureLayer->setContentBounds(IntSize(10, 10));
2451     textureLayer->setDrawsContent(true);
2452     textureLayer->setTextureId(1);
2453     rootLayer->addChild(textureLayer.release());
2454
2455     FakeVideoFrame videoFrame;
2456     FakeVideoFrameProvider provider;
2457     provider.setFrame(&videoFrame);
2458     OwnPtr<CCVideoLayerImpl> videoLayer = CCVideoLayerImpl::create(4, &provider);
2459     videoLayer->setBounds(IntSize(10, 10));
2460     videoLayer->setAnchorPoint(FloatPoint(0, 0));
2461     videoLayer->setContentBounds(IntSize(10, 10));
2462     videoLayer->setDrawsContent(true);
2463     videoLayer->setLayerTreeHostImpl(m_hostImpl.get());
2464     rootLayer->addChild(videoLayer.release());
2465
2466     FakeVideoFrame hwVideoFrame;
2467     FakeVideoFrameProvider hwProvider;
2468     hwProvider.setFrame(&hwVideoFrame);
2469     OwnPtr<CCVideoLayerImpl> hwVideoLayer = CCVideoLayerImpl::create(5, &hwProvider);
2470     hwVideoLayer->setBounds(IntSize(10, 10));
2471     hwVideoLayer->setAnchorPoint(FloatPoint(0, 0));
2472     hwVideoLayer->setContentBounds(IntSize(10, 10));
2473     hwVideoLayer->setDrawsContent(true);
2474     hwVideoLayer->setLayerTreeHostImpl(m_hostImpl.get());
2475     rootLayer->addChild(hwVideoLayer.release());
2476
2477     OwnPtr<CCIOSurfaceLayerImpl> ioSurfaceLayer = CCIOSurfaceLayerImpl::create(6);
2478     ioSurfaceLayer->setBounds(IntSize(10, 10));
2479     ioSurfaceLayer->setAnchorPoint(FloatPoint(0, 0));
2480     ioSurfaceLayer->setContentBounds(IntSize(10, 10));
2481     ioSurfaceLayer->setDrawsContent(true);
2482     ioSurfaceLayer->setIOSurfaceProperties(1, IntSize(10, 10));
2483     ioSurfaceLayer->setLayerTreeHostImpl(m_hostImpl.get());
2484     rootLayer->addChild(ioSurfaceLayer.release());
2485
2486     OwnPtr<CCHeadsUpDisplayLayerImpl> hudLayer = CCHeadsUpDisplayLayerImpl::create(7);
2487     hudLayer->setBounds(IntSize(10, 10));
2488     hudLayer->setAnchorPoint(FloatPoint(0, 0));
2489     hudLayer->setContentBounds(IntSize(10, 10));
2490     hudLayer->setDrawsContent(true);
2491     hudLayer->setLayerTreeHostImpl(m_hostImpl.get());
2492     rootLayer->addChild(hudLayer.release());
2493
2494     OwnPtr<FakeScrollbarLayerImpl> scrollbarLayer(FakeScrollbarLayerImpl::create(8));
2495     scrollbarLayer->setLayerTreeHostImpl(m_hostImpl.get());
2496     scrollbarLayer->setBounds(IntSize(10, 10));
2497     scrollbarLayer->setContentBounds(IntSize(10, 10));
2498     scrollbarLayer->setDrawsContent(true);
2499     scrollbarLayer->setLayerTreeHostImpl(m_hostImpl.get());
2500     scrollbarLayer->createResources(m_hostImpl->resourceProvider());
2501     rootLayer->addChild(scrollbarLayer.release());
2502
2503     // Use a context that supports IOSurfaces
2504     m_hostImpl->initializeLayerRenderer(FakeWebCompositorOutputSurface::create(adoptPtr(new FakeWebGraphicsContext3DWithIOSurface)), UnthrottledUploader);
2505
2506     hwVideoFrame.setTextureId(m_hostImpl->resourceProvider()->graphicsContext3D()->createTexture());
2507
2508     m_hostImpl->setRootLayer(rootLayer.release());
2509
2510     CCLayerTreeHostImpl::FrameData frame;
2511     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
2512     m_hostImpl->drawLayers(frame);
2513     m_hostImpl->didDrawAllLayers(frame);
2514     m_hostImpl->swapBuffers();
2515
2516     unsigned numResources = m_hostImpl->resourceProvider()->numResources();
2517
2518     // Lose the context, replacing it with a StrictWebGraphicsContext3DWithIOSurface,
2519     // that will warn if any resource from the previous context gets used.
2520     m_hostImpl->initializeLayerRenderer(FakeWebCompositorOutputSurface::create(adoptPtr(new StrictWebGraphicsContext3DWithIOSurface)), UnthrottledUploader);
2521
2522     // Create dummy resources so that looking up an old resource will get an
2523     // invalid texture id mapping.
2524     for (unsigned i = 0; i < numResources; ++i)
2525         m_hostImpl->resourceProvider()->createResourceFromExternalTexture(1);
2526
2527     // The WebVideoFrameProvider is expected to recreate its textures after a
2528     // lost context (or not serve a frame).
2529     hwProvider.setFrame(0);
2530
2531     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
2532     m_hostImpl->drawLayers(frame);
2533     m_hostImpl->didDrawAllLayers(frame);
2534     m_hostImpl->swapBuffers();
2535
2536     hwVideoFrame.setTextureId(m_hostImpl->resourceProvider()->graphicsContext3D()->createTexture());
2537     hwProvider.setFrame(&hwVideoFrame);
2538
2539     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
2540     m_hostImpl->drawLayers(frame);
2541     m_hostImpl->didDrawAllLayers(frame);
2542     m_hostImpl->swapBuffers();
2543 }
2544
2545 // Fake WebGraphicsContext3D that tracks the number of textures in use.
2546 class TrackingWebGraphicsContext3D : public FakeWebGraphicsContext3D {
2547 public:
2548     TrackingWebGraphicsContext3D()
2549         : FakeWebGraphicsContext3D()
2550         , m_numTextures(0)
2551     { }
2552
2553     virtual WebGLId createTexture() OVERRIDE
2554     {
2555         WebGLId id = FakeWebGraphicsContext3D::createTexture();
2556
2557         m_textures.set(id, true);
2558         ++m_numTextures;
2559         return id;
2560     }
2561
2562     virtual void deleteTexture(WebGLId id) OVERRIDE
2563     {
2564         if (!m_textures.get(id))
2565             return;
2566
2567         m_textures.set(id, false);
2568         --m_numTextures;
2569     }
2570
2571     virtual WebString getString(WGC3Denum name) OVERRIDE
2572     {
2573         if (name == WebCore::GraphicsContext3D::EXTENSIONS)
2574             return WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2575
2576         return WebString();
2577     }
2578
2579     unsigned numTextures() const { return m_numTextures; }
2580
2581 private:
2582     HashMap<WebGLId, bool> m_textures;
2583     unsigned m_numTextures;
2584 };
2585
2586 TEST_F(CCLayerTreeHostImplTest, layersFreeTextures)
2587 {
2588     OwnPtr<CCLayerImpl> rootLayer(CCLayerImpl::create(1));
2589     rootLayer->setBounds(IntSize(10, 10));
2590     rootLayer->setAnchorPoint(FloatPoint(0, 0));
2591
2592     OwnPtr<CCTiledLayerImpl> tileLayer = CCTiledLayerImpl::create(2);
2593     tileLayer->setBounds(IntSize(10, 10));
2594     tileLayer->setAnchorPoint(FloatPoint(0, 0));
2595     tileLayer->setContentBounds(IntSize(10, 10));
2596     tileLayer->setDrawsContent(true);
2597     tileLayer->setSkipsDraw(false);
2598     OwnPtr<CCLayerTilingData> tilingData(CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels));
2599     tilingData->setBounds(IntSize(10, 10));
2600     tileLayer->setTilingData(*tilingData);
2601     tileLayer->pushTileProperties(0, 0, 1, IntRect(0, 0, 10, 10));
2602     rootLayer->addChild(tileLayer.release());
2603
2604     OwnPtr<CCTextureLayerImpl> textureLayer = CCTextureLayerImpl::create(3);
2605     textureLayer->setBounds(IntSize(10, 10));
2606     textureLayer->setAnchorPoint(FloatPoint(0, 0));
2607     textureLayer->setContentBounds(IntSize(10, 10));
2608     textureLayer->setDrawsContent(true);
2609     textureLayer->setTextureId(1);
2610     rootLayer->addChild(textureLayer.release());
2611
2612     FakeVideoFrameProvider provider;
2613     OwnPtr<CCVideoLayerImpl> videoLayer = CCVideoLayerImpl::create(4, &provider);
2614     videoLayer->setBounds(IntSize(10, 10));
2615     videoLayer->setAnchorPoint(FloatPoint(0, 0));
2616     videoLayer->setContentBounds(IntSize(10, 10));
2617     videoLayer->setDrawsContent(true);
2618     videoLayer->setLayerTreeHostImpl(m_hostImpl.get());
2619     rootLayer->addChild(videoLayer.release());
2620
2621     OwnPtr<CCIOSurfaceLayerImpl> ioSurfaceLayer = CCIOSurfaceLayerImpl::create(5);
2622     ioSurfaceLayer->setBounds(IntSize(10, 10));
2623     ioSurfaceLayer->setAnchorPoint(FloatPoint(0, 0));
2624     ioSurfaceLayer->setContentBounds(IntSize(10, 10));
2625     ioSurfaceLayer->setDrawsContent(true);
2626     ioSurfaceLayer->setIOSurfaceProperties(1, IntSize(10, 10));
2627     ioSurfaceLayer->setLayerTreeHostImpl(m_hostImpl.get());
2628     rootLayer->addChild(ioSurfaceLayer.release());
2629
2630     // Lose the context, replacing it with a TrackingWebGraphicsContext3D (which the CCLayerTreeHostImpl takes ownership of).
2631     OwnPtr<CCGraphicsContext> ccContext(FakeWebCompositorOutputSurface::create(adoptPtr(new TrackingWebGraphicsContext3D)));
2632     TrackingWebGraphicsContext3D* trackingWebGraphicsContext = static_cast<TrackingWebGraphicsContext3D*>(ccContext->context3D());
2633     m_hostImpl->initializeLayerRenderer(ccContext.release(), UnthrottledUploader);
2634
2635     m_hostImpl->setRootLayer(rootLayer.release());
2636
2637     CCLayerTreeHostImpl::FrameData frame;
2638     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
2639     m_hostImpl->drawLayers(frame);
2640     m_hostImpl->didDrawAllLayers(frame);
2641     m_hostImpl->swapBuffers();
2642
2643     EXPECT_GT(trackingWebGraphicsContext->numTextures(), 0u);
2644
2645     // Kill the layer tree.
2646     m_hostImpl->setRootLayer(CCLayerImpl::create(100));
2647     // There should be no textures left in use after.
2648     EXPECT_EQ(0u, trackingWebGraphicsContext->numTextures());
2649 }
2650
2651 class MockDrawQuadsToFillScreenContext : public FakeWebGraphicsContext3D {
2652 public:
2653     MOCK_METHOD1(useProgram, void(WebGLId program));
2654     MOCK_METHOD4(drawElements, void(WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset));
2655 };
2656
2657 TEST_F(CCLayerTreeHostImplTest, hasTransparentBackground)
2658 {
2659     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new MockDrawQuadsToFillScreenContext));
2660     MockDrawQuadsToFillScreenContext* mockContext = static_cast<MockDrawQuadsToFillScreenContext*>(context->context3D());
2661
2662     // Run test case
2663     OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(false, context.release(), CCLayerImpl::create(1));
2664     myHostImpl->setBackgroundColor(SK_ColorWHITE);
2665
2666     // Verify one quad is drawn when transparent background set is not set.
2667     myHostImpl->setHasTransparentBackground(false);
2668     EXPECT_CALL(*mockContext, useProgram(_))
2669         .Times(1);
2670     EXPECT_CALL(*mockContext, drawElements(_, _, _, _))
2671         .Times(1);
2672     CCLayerTreeHostImpl::FrameData frame;
2673     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2674     myHostImpl->drawLayers(frame);
2675     myHostImpl->didDrawAllLayers(frame);
2676     Mock::VerifyAndClearExpectations(&mockContext);
2677
2678     // Verify no quads are drawn when transparent background is set.
2679     myHostImpl->setHasTransparentBackground(true);
2680     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2681     myHostImpl->drawLayers(frame);
2682     myHostImpl->didDrawAllLayers(frame);
2683     Mock::VerifyAndClearExpectations(&mockContext);
2684 }
2685
2686 static void addDrawingLayerTo(CCLayerImpl* parent, int id, const IntRect& layerRect, CCLayerImpl** result)
2687 {
2688     OwnPtr<CCLayerImpl> layer = FakeLayerWithQuads::create(id);
2689     CCLayerImpl* layerPtr = layer.get();
2690     layerPtr->setAnchorPoint(FloatPoint(0, 0));
2691     layerPtr->setPosition(FloatPoint(layerRect.location()));
2692     layerPtr->setBounds(layerRect.size());
2693     layerPtr->setContentBounds(layerRect.size());
2694     layerPtr->setDrawsContent(true); // only children draw content
2695     layerPtr->setOpaque(true);
2696     parent->addChild(layer.release());
2697     if (result)
2698         *result = layerPtr;
2699 }
2700
2701 static void setupLayersForTextureCaching(CCLayerTreeHostImpl* layerTreeHostImpl, CCLayerImpl*& rootPtr, CCLayerImpl*& intermediateLayerPtr, CCLayerImpl*& surfaceLayerPtr, CCLayerImpl*& childPtr, const IntSize& rootSize)
2702 {
2703     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext));
2704
2705     layerTreeHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
2706     layerTreeHostImpl->setViewportSize(rootSize, rootSize);
2707
2708     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
2709     rootPtr = root.get();
2710
2711     root->setAnchorPoint(FloatPoint(0, 0));
2712     root->setPosition(FloatPoint(0, 0));
2713     root->setBounds(rootSize);
2714     root->setContentBounds(rootSize);
2715     root->setDrawsContent(true);
2716     layerTreeHostImpl->setRootLayer(root.release());
2717
2718     addDrawingLayerTo(rootPtr, 2, IntRect(10, 10, rootSize.width(), rootSize.height()), &intermediateLayerPtr);
2719     intermediateLayerPtr->setDrawsContent(false); // only children draw content
2720
2721     // Surface layer is the layer that changes its opacity
2722     // It will contain other layers that draw content.
2723     addDrawingLayerTo(intermediateLayerPtr, 3, IntRect(10, 10, rootSize.width(), rootSize.height()), &surfaceLayerPtr);
2724     surfaceLayerPtr->setDrawsContent(false); // only children draw content
2725     surfaceLayerPtr->setOpacity(0.5f); // This will cause it to have a surface
2726
2727     // Child of the surface layer will produce some quads
2728     addDrawingLayerTo(surfaceLayerPtr, 4, IntRect(5, 5, rootSize.width() - 25, rootSize.height() - 25), &childPtr);
2729 }
2730
2731 class LayerRendererChromiumWithReleaseTextures : public LayerRendererChromium {
2732 public:
2733     using LayerRendererChromium::releaseRenderPassTextures;
2734 };
2735
2736 TEST_F(CCLayerTreeHostImplTest, textureCachingWithClipping)
2737 {
2738     CCSettings::setPartialSwapEnabled(true);
2739
2740     CCLayerTreeSettings settings;
2741     settings.minimumOcclusionTrackingSize = IntSize();
2742     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
2743
2744     CCLayerImpl* rootPtr;
2745     CCLayerImpl* surfaceLayerPtr;
2746
2747     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext));
2748
2749     IntSize rootSize(100, 100);
2750
2751     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
2752     myHostImpl->setViewportSize(IntSize(rootSize.width(), rootSize.height()), IntSize(rootSize.width(), rootSize.height()));
2753
2754     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
2755     rootPtr = root.get();
2756
2757     root->setAnchorPoint(FloatPoint(0, 0));
2758     root->setPosition(FloatPoint(0, 0));
2759     root->setBounds(rootSize);
2760     root->setContentBounds(rootSize);
2761     root->setDrawsContent(true);
2762     root->setMasksToBounds(true);
2763     myHostImpl->setRootLayer(root.release());
2764
2765     addDrawingLayerTo(rootPtr, 3, IntRect(0, 0, rootSize.width(), rootSize.height()), &surfaceLayerPtr);
2766     surfaceLayerPtr->setDrawsContent(false);
2767
2768     // Surface layer is the layer that changes its opacity
2769     // It will contain other layers that draw content.
2770     surfaceLayerPtr->setOpacity(0.5f); // This will cause it to have a surface
2771
2772     addDrawingLayerTo(surfaceLayerPtr, 4, IntRect(0, 0, 100, 3), 0);
2773     addDrawingLayerTo(surfaceLayerPtr, 5, IntRect(0, 97, 100, 3), 0);
2774
2775     // Rotation will put part of the child ouside the bounds of the root layer.
2776     // Nevertheless, the child layers should be drawn.
2777     WebTransformationMatrix transform = surfaceLayerPtr->transform();
2778     transform.translate(50, 50);
2779     transform.rotate(35);
2780     transform.translate(-50, -50);
2781     surfaceLayerPtr->setTransform(transform);
2782
2783     {
2784         CCLayerTreeHostImpl::FrameData frame;
2785         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2786
2787         // Must receive two render passes, each with one quad
2788         ASSERT_EQ(2U, frame.renderPasses.size());
2789         EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
2790         ASSERT_EQ(1U, frame.renderPasses[1]->quadList().size());
2791
2792         // Verify that the child layers are being clipped.
2793         IntRect quadVisibleRect = frame.renderPasses[0]->quadList()[0]->quadVisibleRect();
2794         EXPECT_LT(quadVisibleRect.width(), 100);
2795
2796         quadVisibleRect = frame.renderPasses[0]->quadList()[1]->quadVisibleRect();
2797         EXPECT_LT(quadVisibleRect.width(), 100);
2798
2799         // Verify that the render surface texture is *not* clipped.
2800         EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), frame.renderPasses[0]->outputRect());
2801
2802         EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[1]->quadList()[0]->material());
2803         CCRenderPassDrawQuad* quad = static_cast<CCRenderPassDrawQuad*>(frame.renderPasses[1]->quadList()[0].get());
2804         EXPECT_FALSE(quad->contentsChangedSinceLastFrame().isEmpty());
2805
2806         myHostImpl->drawLayers(frame);
2807         myHostImpl->didDrawAllLayers(frame);
2808     }
2809
2810     transform = surfaceLayerPtr->transform();
2811     transform.translate(50, 50);
2812     transform.rotate(-35);
2813     transform.translate(-50, -50);
2814     surfaceLayerPtr->setTransform(transform);
2815
2816     // The surface is now aligned again, and the clipped parts are exposed.
2817     // Since the layers were clipped, even though the render surface size
2818     // was not changed, the texture should not be saved.
2819     {
2820         CCLayerTreeHostImpl::FrameData frame;
2821         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2822
2823         // Must receive two render passes, each with one quad
2824         ASSERT_EQ(2U, frame.renderPasses.size());
2825         EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
2826         ASSERT_EQ(1U, frame.renderPasses[1]->quadList().size());
2827
2828         myHostImpl->drawLayers(frame);
2829         myHostImpl->didDrawAllLayers(frame);
2830     }
2831 }
2832
2833 TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusion)
2834 {
2835     CCSettings::setPartialSwapEnabled(false);
2836
2837     CCLayerTreeSettings settings;
2838     settings.minimumOcclusionTrackingSize = IntSize();
2839     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
2840
2841     // Layers are structure as follows:
2842     //
2843     //  R +-- S1 +- L10 (owning)
2844     //    |      +- L11
2845     //    |      +- L12
2846     //    |
2847     //    +-- S2 +- L20 (owning)
2848     //           +- L21
2849     //
2850     // Occlusion:
2851     // L12 occludes L11 (internal)
2852     // L20 occludes L10 (external)
2853     // L21 occludes L20 (internal)
2854
2855     CCLayerImpl* rootPtr;
2856     CCLayerImpl* layerS1Ptr;
2857     CCLayerImpl* layerS2Ptr;
2858
2859     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext));
2860
2861     IntSize rootSize(1000, 1000);
2862
2863     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
2864     myHostImpl->setViewportSize(IntSize(rootSize.width(), rootSize.height()), IntSize(rootSize.width(), rootSize.height()));
2865
2866     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
2867     rootPtr = root.get();
2868
2869     root->setAnchorPoint(FloatPoint(0, 0));
2870     root->setPosition(FloatPoint(0, 0));
2871     root->setBounds(rootSize);
2872     root->setContentBounds(rootSize);
2873     root->setDrawsContent(true);
2874     root->setMasksToBounds(true);
2875     myHostImpl->setRootLayer(root.release());
2876
2877     addDrawingLayerTo(rootPtr, 2, IntRect(300, 300, 300, 300), &layerS1Ptr);
2878     layerS1Ptr->setForceRenderSurface(true);
2879
2880     addDrawingLayerTo(layerS1Ptr, 3, IntRect(10, 10, 10, 10), 0); // L11
2881     addDrawingLayerTo(layerS1Ptr, 4, IntRect(0, 0, 30, 30), 0); // L12
2882
2883     addDrawingLayerTo(rootPtr, 5, IntRect(550, 250, 300, 400), &layerS2Ptr);
2884     layerS2Ptr->setForceRenderSurface(true);
2885
2886     addDrawingLayerTo(layerS2Ptr, 6, IntRect(20, 20, 5, 5), 0); // L21
2887
2888     // Initial draw - must receive all quads
2889     {
2890         CCLayerTreeHostImpl::FrameData frame;
2891         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2892
2893         // Must receive 3 render passes.
2894         // For Root, there are 2 quads; for S1, there are 2 quads (1 is occluded); for S2, there is 2 quads.
2895         ASSERT_EQ(3U, frame.renderPasses.size());
2896
2897         EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
2898         EXPECT_EQ(2U, frame.renderPasses[1]->quadList().size());
2899         EXPECT_EQ(2U, frame.renderPasses[2]->quadList().size());
2900
2901         myHostImpl->drawLayers(frame);
2902         myHostImpl->didDrawAllLayers(frame);
2903     }
2904
2905     // "Unocclude" surface S1 and repeat draw.
2906     // Must remove S2's render pass since it's cached;
2907     // Must keep S1 quads because texture contained external occlusion.
2908     WebTransformationMatrix transform = layerS2Ptr->transform();
2909     transform.translate(150, 150);
2910     layerS2Ptr->setTransform(transform);
2911     {
2912         CCLayerTreeHostImpl::FrameData frame;
2913         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2914
2915         // Must receive 2 render passes.
2916         // For Root, there are 2 quads
2917         // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
2918         // For S2, there is no render pass
2919         ASSERT_EQ(2U, frame.renderPasses.size());
2920
2921         EXPECT_GT(frame.renderPasses[0]->quadList().size(), 0U);
2922         EXPECT_EQ(2U, frame.renderPasses[1]->quadList().size());
2923
2924         myHostImpl->drawLayers(frame);
2925         myHostImpl->didDrawAllLayers(frame);
2926     }
2927
2928     // "Re-occlude" surface S1 and repeat draw.
2929     // Must remove S1's render pass since it is now available in full.
2930     // S2 has no change so must also be removed.
2931     transform = layerS2Ptr->transform();
2932     transform.translate(-15, -15);
2933     layerS2Ptr->setTransform(transform);
2934     {
2935         CCLayerTreeHostImpl::FrameData frame;
2936         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
2937
2938         // Must receive 1 render pass - for the root.
2939         ASSERT_EQ(1U, frame.renderPasses.size());
2940
2941         EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
2942
2943         myHostImpl->drawLayers(frame);
2944         myHostImpl->didDrawAllLayers(frame);
2945     }
2946
2947 }
2948
2949 TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusionEarlyOut)
2950 {
2951     CCSettings::setPartialSwapEnabled(false);
2952
2953     CCLayerTreeSettings settings;
2954     settings.minimumOcclusionTrackingSize = IntSize();
2955     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
2956
2957     // Layers are structure as follows:
2958     //
2959     //  R +-- S1 +- L10 (owning, non drawing)
2960     //    |      +- L11 (corner, unoccluded)
2961     //    |      +- L12 (corner, unoccluded)
2962     //    |      +- L13 (corner, unoccluded)
2963     //    |      +- L14 (corner, entirely occluded)
2964     //    |
2965     //    +-- S2 +- L20 (owning, drawing)
2966     //
2967
2968     CCLayerImpl* rootPtr;
2969     CCLayerImpl* layerS1Ptr;
2970     CCLayerImpl* layerS2Ptr;
2971
2972     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext));
2973
2974     IntSize rootSize(1000, 1000);
2975
2976     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
2977     myHostImpl->setViewportSize(IntSize(rootSize.width(), rootSize.height()), IntSize(rootSize.width(), rootSize.height()));
2978
2979     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
2980     rootPtr = root.get();
2981
2982     root->setAnchorPoint(FloatPoint(0, 0));
2983     root->setPosition(FloatPoint(0, 0));
2984     root->setBounds(rootSize);
2985     root->setContentBounds(rootSize);
2986     root->setDrawsContent(true);
2987     root->setMasksToBounds(true);
2988     myHostImpl->setRootLayer(root.release());
2989
2990     addDrawingLayerTo(rootPtr, 2, IntRect(0, 0, 800, 800), &layerS1Ptr);
2991     layerS1Ptr->setForceRenderSurface(true);
2992     layerS1Ptr->setDrawsContent(false);
2993
2994     addDrawingLayerTo(layerS1Ptr, 3, IntRect(0, 0, 300, 300), 0); // L11
2995     addDrawingLayerTo(layerS1Ptr, 4, IntRect(0, 500, 300, 300), 0); // L12
2996     addDrawingLayerTo(layerS1Ptr, 5, IntRect(500, 0, 300, 300), 0); // L13
2997     addDrawingLayerTo(layerS1Ptr, 6, IntRect(500, 500, 300, 300), 0); // L14
2998     addDrawingLayerTo(layerS1Ptr, 9, IntRect(500, 500, 300, 300), 0); // L14
2999
3000     addDrawingLayerTo(rootPtr, 7, IntRect(450, 450, 450, 450), &layerS2Ptr);
3001     layerS2Ptr->setForceRenderSurface(true);
3002
3003     // Initial draw - must receive all quads
3004     {
3005         CCLayerTreeHostImpl::FrameData frame;
3006         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
3007
3008         // Must receive 3 render passes.
3009         // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is 1 quad.
3010         ASSERT_EQ(3U, frame.renderPasses.size());
3011
3012         EXPECT_EQ(1U, frame.renderPasses[0]->quadList().size());
3013
3014         // L14 is culled, so only 3 quads.
3015         EXPECT_EQ(3U, frame.renderPasses[1]->quadList().size());
3016         EXPECT_EQ(2U, frame.renderPasses[2]->quadList().size());
3017
3018         myHostImpl->drawLayers(frame);
3019         myHostImpl->didDrawAllLayers(frame);
3020     }
3021
3022     // "Unocclude" surface S1 and repeat draw.
3023     // Must remove S2's render pass since it's cached;
3024     // Must keep S1 quads because texture contained external occlusion.
3025     WebTransformationMatrix transform = layerS2Ptr->transform();
3026     transform.translate(100, 100);
3027     layerS2Ptr->setTransform(transform);
3028     {
3029         CCLayerTreeHostImpl::FrameData frame;
3030         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
3031
3032         // Must receive 2 render passes.
3033         // For Root, there are 2 quads
3034         // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
3035         // For S2, there is no render pass
3036         ASSERT_EQ(2U, frame.renderPasses.size());
3037
3038         EXPECT_GT(frame.renderPasses[0]->quadList().size(), 0U);
3039         EXPECT_EQ(2U, frame.renderPasses[1]->quadList().size());
3040
3041         myHostImpl->drawLayers(frame);
3042         myHostImpl->didDrawAllLayers(frame);
3043     }
3044
3045     // "Re-occlude" surface S1 and repeat draw.
3046     // Must remove S1's render pass since it is now available in full.
3047     // S2 has no change so must also be removed.
3048     transform = layerS2Ptr->transform();
3049     transform.translate(-15, -15);
3050     layerS2Ptr->setTransform(transform);
3051     {
3052         CCLayerTreeHostImpl::FrameData frame;
3053         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
3054
3055         // Must receive 1 render pass - for the root.
3056         ASSERT_EQ(1U, frame.renderPasses.size());
3057
3058         EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
3059
3060         myHostImpl->drawLayers(frame);
3061         myHostImpl->didDrawAllLayers(frame);
3062     }
3063 }
3064
3065 TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusionExternalOverInternal)
3066 {
3067     CCSettings::setPartialSwapEnabled(false);
3068
3069     CCLayerTreeSettings settings;
3070     settings.minimumOcclusionTrackingSize = IntSize();
3071     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
3072
3073     // Layers are structured as follows:
3074     //
3075     //  R +-- S1 +- L10 (owning, drawing)
3076     //    |      +- L11 (corner, occluded by L12)
3077     //    |      +- L12 (opposite corner)
3078     //    |
3079     //    +-- S2 +- L20 (owning, drawing)
3080     //
3081
3082     CCLayerImpl* rootPtr;
3083     CCLayerImpl* layerS1Ptr;
3084     CCLayerImpl* layerS2Ptr;
3085
3086     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext));
3087
3088     IntSize rootSize(1000, 1000);
3089
3090     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
3091     myHostImpl->setViewportSize(IntSize(rootSize.width(), rootSize.height()), IntSize(rootSize.width(), rootSize.height()));
3092
3093     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
3094     rootPtr = root.get();
3095
3096     root->setAnchorPoint(FloatPoint(0, 0));
3097     root->setPosition(FloatPoint(0, 0));
3098     root->setBounds(rootSize);
3099     root->setContentBounds(rootSize);
3100     root->setDrawsContent(true);
3101     root->setMasksToBounds(true);
3102     myHostImpl->setRootLayer(root.release());
3103
3104     addDrawingLayerTo(rootPtr, 2, IntRect(0, 0, 400, 400), &layerS1Ptr);
3105     layerS1Ptr->setForceRenderSurface(true);
3106
3107     addDrawingLayerTo(layerS1Ptr, 3, IntRect(0, 0, 300, 300), 0); // L11
3108     addDrawingLayerTo(layerS1Ptr, 4, IntRect(100, 0, 300, 300), 0); // L12
3109
3110     addDrawingLayerTo(rootPtr, 7, IntRect(200, 0, 300, 300), &layerS2Ptr);
3111     layerS2Ptr->setForceRenderSurface(true);
3112
3113     // Initial draw - must receive all quads
3114     {
3115         CCLayerTreeHostImpl::FrameData frame;
3116         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
3117
3118         // Must receive 3 render passes.
3119         // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is 1 quad.
3120         ASSERT_EQ(3U, frame.renderPasses.size());
3121
3122         EXPECT_EQ(1U, frame.renderPasses[0]->quadList().size());
3123         EXPECT_EQ(3U, frame.renderPasses[1]->quadList().size());
3124         EXPECT_EQ(2U, frame.renderPasses[2]->quadList().size());
3125
3126         myHostImpl->drawLayers(frame);
3127         myHostImpl->didDrawAllLayers(frame);
3128     }
3129
3130     // "Unocclude" surface S1 and repeat draw.
3131     // Must remove S2's render pass since it's cached;
3132     // Must keep S1 quads because texture contained external occlusion.
3133     WebTransformationMatrix transform = layerS2Ptr->transform();
3134     transform.translate(300, 0);
3135     layerS2Ptr->setTransform(transform);
3136     {
3137         CCLayerTreeHostImpl::FrameData frame;
3138         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
3139
3140         // Must receive 2 render passes.
3141         // For Root, there are 2 quads
3142         // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
3143         // For S2, there is no render pass
3144         ASSERT_EQ(2U, frame.renderPasses.size());
3145
3146         EXPECT_GT(frame.renderPasses[0]->quadList().size(), 0U);
3147         EXPECT_EQ(2U, frame.renderPasses[1]->quadList().size());
3148
3149         myHostImpl->drawLayers(frame);
3150         myHostImpl->didDrawAllLayers(frame);
3151     }
3152 }
3153
3154 TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusionExternalNotAligned)
3155 {
3156     CCSettings::setPartialSwapEnabled(false);
3157
3158     CCLayerTreeSettings settings;
3159     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
3160
3161     // Layers are structured as follows:
3162     //
3163     //  R +-- S1 +- L10 (rotated, drawing)
3164     //           +- L11 (occupies half surface)
3165
3166     CCLayerImpl* rootPtr;
3167     CCLayerImpl* layerS1Ptr;
3168
3169     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext));
3170
3171     IntSize rootSize(1000, 1000);
3172
3173     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
3174     myHostImpl->setViewportSize(IntSize(rootSize.width(), rootSize.height()), IntSize(rootSize.width(), rootSize.height()));
3175
3176     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
3177     rootPtr = root.get();
3178
3179     root->setAnchorPoint(FloatPoint(0, 0));
3180     root->setPosition(FloatPoint(0, 0));
3181     root->setBounds(rootSize);
3182     root->setContentBounds(rootSize);
3183     root->setDrawsContent(true);
3184     root->setMasksToBounds(true);
3185     myHostImpl->setRootLayer(root.release());
3186
3187     addDrawingLayerTo(rootPtr, 2, IntRect(0, 0, 400, 400), &layerS1Ptr);
3188     layerS1Ptr->setForceRenderSurface(true);
3189     WebTransformationMatrix transform = layerS1Ptr->transform();
3190     transform.translate(200, 200);
3191     transform.rotate(45);
3192     transform.translate(-200, -200);
3193     layerS1Ptr->setTransform(transform);
3194
3195     addDrawingLayerTo(layerS1Ptr, 3, IntRect(200, 0, 200, 400), 0); // L11
3196
3197     // Initial draw - must receive all quads
3198     {
3199         CCLayerTreeHostImpl::FrameData frame;
3200         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
3201
3202         // Must receive 2 render passes.
3203         ASSERT_EQ(2U, frame.renderPasses.size());
3204
3205         EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
3206         EXPECT_EQ(1U, frame.renderPasses[1]->quadList().size());
3207
3208         myHostImpl->drawLayers(frame);
3209         myHostImpl->didDrawAllLayers(frame);
3210     }
3211
3212     // Change opacity and draw. Verify we used cached texture.
3213     layerS1Ptr->setOpacity(0.2f);
3214     {
3215         CCLayerTreeHostImpl::FrameData frame;
3216         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
3217
3218         // One render pass must be gone due to cached texture.
3219         ASSERT_EQ(1U, frame.renderPasses.size());
3220
3221         EXPECT_EQ(1U, frame.renderPasses[0]->quadList().size());
3222
3223         myHostImpl->drawLayers(frame);
3224         myHostImpl->didDrawAllLayers(frame);
3225     }
3226 }
3227
3228 TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusionPartialSwap)
3229 {
3230     CCSettings::setPartialSwapEnabled(true);
3231
3232     CCLayerTreeSettings settings;
3233     settings.minimumOcclusionTrackingSize = IntSize();
3234     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
3235
3236     // Layers are structure as follows:
3237     //
3238     //  R +-- S1 +- L10 (owning)
3239     //    |      +- L11
3240     //    |      +- L12
3241     //    |
3242     //    +-- S2 +- L20 (owning)
3243     //           +- L21
3244     //
3245     // Occlusion:
3246     // L12 occludes L11 (internal)
3247     // L20 occludes L10 (external)
3248     // L21 occludes L20 (internal)
3249
3250     CCLayerImpl* rootPtr;
3251     CCLayerImpl* layerS1Ptr;
3252     CCLayerImpl* layerS2Ptr;
3253
3254     OwnPtr<CCGraphicsContext> context = FakeWebCompositorOutputSurface::create(adoptPtr(new PartialSwapContext));
3255
3256     IntSize rootSize(1000, 1000);
3257
3258     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
3259     myHostImpl->setViewportSize(IntSize(rootSize.width(), rootSize.height()), IntSize(rootSize.width(), rootSize.height()));
3260
3261     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
3262     rootPtr = root.get();
3263
3264     root->setAnchorPoint(FloatPoint(0, 0));
3265     root->setPosition(FloatPoint(0, 0));
3266     root->setBounds(rootSize);
3267     root->setContentBounds(rootSize);
3268     root->setDrawsContent(true);
3269     root->setMasksToBounds(true);
3270     myHostImpl->setRootLayer(root.release());
3271
3272     addDrawingLayerTo(rootPtr, 2, IntRect(300, 300, 300, 300), &layerS1Ptr);
3273     layerS1Ptr->setForceRenderSurface(true);
3274
3275     addDrawingLayerTo(layerS1Ptr, 3, IntRect(10, 10, 10, 10), 0); // L11
3276     addDrawingLayerTo(layerS1Ptr, 4, IntRect(0, 0, 30, 30), 0); // L12
3277
3278     addDrawingLayerTo(rootPtr, 5, IntRect(550, 250, 300, 400), &layerS2Ptr);
3279     layerS2Ptr->setForceRenderSurface(true);
3280
3281     addDrawingLayerTo(layerS2Ptr, 6, IntRect(20, 20, 5, 5), 0); // L21
3282
3283     // Initial draw - must receive all quads
3284     {
3285         CCLayerTreeHostImpl::FrameData frame;
3286         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
3287
3288         // Must receive 3 render passes.
3289         // For Root, there are 2 quads; for S1, there are 2 quads (one is occluded); for S2, there is 2 quads.
3290         ASSERT_EQ(3U, frame.renderPasses.size());
3291
3292         EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
3293         EXPECT_EQ(2U, frame.renderPasses[1]->quadList().size());
3294         EXPECT_EQ(2U, frame.renderPasses[2]->quadList().size());
3295
3296         myHostImpl->drawLayers(frame);
3297         myHostImpl->didDrawAllLayers(frame);
3298     }