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