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