[chromium] Skip willDraw() and didDraw() on fully occluded layers
[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 "FakeWebGraphicsContext3D.h"
32 #include "GraphicsContext3DPrivate.h"
33 #include "LayerRendererChromium.h"
34 #include "cc/CCLayerImpl.h"
35 #include "cc/CCLayerTilingData.h"
36 #include "cc/CCQuadCuller.h"
37 #include "cc/CCScrollbarLayerImpl.h"
38 #include "cc/CCSingleThreadProxy.h"
39 #include "cc/CCSolidColorDrawQuad.h"
40 #include "cc/CCTextureLayerImpl.h"
41 #include "cc/CCTileDrawQuad.h"
42 #include "cc/CCTiledLayerImpl.h"
43 #include "cc/CCVideoLayerImpl.h"
44 #include <gmock/gmock.h>
45 #include <gtest/gtest.h>
46 #include <public/WebVideoFrame.h>
47 #include <public/WebVideoFrameProvider.h>
48
49 using namespace CCLayerTestCommon;
50 using namespace WebCore;
51 using namespace WebKit;
52 using namespace WebKitTests;
53
54 using ::testing::Mock;
55 using ::testing::Return;
56 using ::testing::AnyNumber;
57 using ::testing::AtLeast;
58 using ::testing::_;
59
60 namespace {
61
62 class CCLayerTreeHostImplTest : public testing::Test, public CCLayerTreeHostImplClient {
63 public:
64     CCLayerTreeHostImplTest()
65         : m_didRequestCommit(false)
66         , m_didRequestRedraw(false)
67     {
68         CCSettings settings;
69         m_hostImpl = CCLayerTreeHostImpl::create(settings, this);
70         m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
71         m_hostImpl->setViewportSize(IntSize(10, 10));
72     }
73
74     virtual void didLoseContextOnImplThread() OVERRIDE { }
75     virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE { }
76     virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_didRequestRedraw = true; }
77     virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; }
78     virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE { }
79     virtual void postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t) OVERRIDE { }
80
81     PassOwnPtr<CCLayerTreeHostImpl> createLayerTreeHost(bool partialSwap, PassRefPtr<CCGraphicsContext> graphicsContext, PassOwnPtr<CCLayerImpl> rootPtr)
82     {
83         CCSettings settings;
84
85         settings.partialSwapEnabled = partialSwap;
86
87         OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
88
89         myHostImpl->initializeLayerRenderer(graphicsContext, UnthrottledUploader);
90         myHostImpl->setViewportSize(IntSize(10, 10));
91
92         OwnPtr<CCLayerImpl> root = rootPtr;
93
94         root->setAnchorPoint(FloatPoint(0, 0));
95         root->setPosition(FloatPoint(0, 0));
96         root->setBounds(IntSize(10, 10));
97         root->setVisibleLayerRect(IntRect(0, 0, 10, 10));
98         root->setDrawsContent(true);
99         myHostImpl->setRootLayer(root.release());
100         return myHostImpl.release();
101     }
102
103     static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer)
104     {
105         ASSERT_EQ(layer->scrollDelta(), IntSize());
106         for (size_t i = 0; i < layer->children().size(); ++i)
107             expectClearedScrollDeltasRecursive(layer->children()[i].get());
108     }
109
110     static void expectContains(const CCScrollAndScaleSet& scrollInfo, int id, const IntSize& scrollDelta)
111     {
112         int timesEncountered = 0;
113
114         for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) {
115             if (scrollInfo.scrolls[i].layerId != id)
116                 continue;
117             EXPECT_EQ(scrollDelta.width(), scrollInfo.scrolls[i].scrollDelta.width());
118             EXPECT_EQ(scrollDelta.height(), scrollInfo.scrolls[i].scrollDelta.height());
119             timesEncountered++;
120         }
121
122         ASSERT_EQ(timesEncountered, 1);
123     }
124
125     void setupScrollAndContentsLayers(const IntSize& contentSize)
126     {
127         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
128         root->setScrollable(true);
129         root->setScrollPosition(IntPoint(0, 0));
130         root->setMaxScrollPosition(contentSize);
131         OwnPtr<CCLayerImpl> contents = CCLayerImpl::create(1);
132         contents->setDrawsContent(true);
133         contents->setBounds(contentSize);
134         contents->setContentBounds(contentSize);
135         root->addChild(contents.release());
136         m_hostImpl->setRootLayer(root.release());
137     }
138
139 protected:
140     PassRefPtr<CCGraphicsContext> createContext()
141     {
142         return CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3D()), GraphicsContext3D::RenderDirectlyToHostWindow));
143     }
144
145     DebugScopedSetImplThread m_alwaysImplThread;
146     DebugScopedSetMainThreadBlocked m_alwaysMainThreadBlocked;
147
148     OwnPtr<CCLayerTreeHostImpl> m_hostImpl;
149     bool m_didRequestCommit;
150     bool m_didRequestRedraw;
151 };
152
153 TEST_F(CCLayerTreeHostImplTest, scrollDeltaNoLayers)
154 {
155     ASSERT_FALSE(m_hostImpl->rootLayer());
156
157     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
158     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
159 }
160
161 TEST_F(CCLayerTreeHostImplTest, scrollDeltaTreeButNoChanges)
162 {
163     {
164         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
165         root->addChild(CCLayerImpl::create(1));
166         root->addChild(CCLayerImpl::create(2));
167         root->children()[1]->addChild(CCLayerImpl::create(3));
168         root->children()[1]->addChild(CCLayerImpl::create(4));
169         root->children()[1]->children()[0]->addChild(CCLayerImpl::create(5));
170         m_hostImpl->setRootLayer(root.release());
171     }
172     CCLayerImpl* root = m_hostImpl->rootLayer();
173
174     expectClearedScrollDeltasRecursive(root);
175
176     OwnPtr<CCScrollAndScaleSet> scrollInfo;
177
178     scrollInfo = m_hostImpl->processScrollDeltas();
179     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
180     expectClearedScrollDeltasRecursive(root);
181
182     scrollInfo = m_hostImpl->processScrollDeltas();
183     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
184     expectClearedScrollDeltasRecursive(root);
185 }
186
187 TEST_F(CCLayerTreeHostImplTest, scrollDeltaRepeatedScrolls)
188 {
189     IntPoint scrollPosition(20, 30);
190     IntSize scrollDelta(11, -15);
191     {
192         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(10);
193         root->setScrollPosition(scrollPosition);
194         root->setScrollable(true);
195         root->setMaxScrollPosition(IntSize(100, 100));
196         root->scrollBy(scrollDelta);
197         m_hostImpl->setRootLayer(root.release());
198     }
199     CCLayerImpl* root = m_hostImpl->rootLayer();
200
201     OwnPtr<CCScrollAndScaleSet> scrollInfo;
202
203     scrollInfo = m_hostImpl->processScrollDeltas();
204     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
205     EXPECT_EQ(root->sentScrollDelta(), scrollDelta);
206     expectContains(*scrollInfo, root->id(), scrollDelta);
207
208     IntSize scrollDelta2(-5, 27);
209     root->scrollBy(scrollDelta2);
210     scrollInfo = m_hostImpl->processScrollDeltas();
211     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
212     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
213     expectContains(*scrollInfo, root->id(), scrollDelta + scrollDelta2);
214
215     root->scrollBy(IntSize());
216     scrollInfo = m_hostImpl->processScrollDeltas();
217     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
218 }
219
220 TEST_F(CCLayerTreeHostImplTest, scrollRootCallsCommitAndRedraw)
221 {
222     {
223         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
224         root->setScrollable(true);
225         root->setScrollPosition(IntPoint(0, 0));
226         root->setMaxScrollPosition(IntSize(100, 100));
227         m_hostImpl->setRootLayer(root.release());
228     }
229
230     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
231     m_hostImpl->scrollBy(IntSize(0, 10));
232     m_hostImpl->scrollEnd();
233     EXPECT_TRUE(m_didRequestRedraw);
234     EXPECT_TRUE(m_didRequestCommit);
235 }
236
237 TEST_F(CCLayerTreeHostImplTest, wheelEventHandlers)
238 {
239     {
240         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
241         root->setScrollable(true);
242         root->setScrollPosition(IntPoint(0, 0));
243         root->setMaxScrollPosition(IntSize(100, 100));
244         m_hostImpl->setRootLayer(root.release());
245     }
246     CCLayerImpl* root = m_hostImpl->rootLayer();
247
248     root->setHaveWheelEventHandlers(true);
249     // With registered event handlers, wheel scrolls have to go to the main thread.
250     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
251
252     // But gesture scrolls can still be handled.
253     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
254 }
255
256 TEST_F(CCLayerTreeHostImplTest, shouldScrollOnMainThread)
257 {
258     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
259     root->setScrollable(true);
260     root->setScrollPosition(IntPoint(0, 0));
261     root->setMaxScrollPosition(IntSize(100, 100));
262     root->setShouldScrollOnMainThread(true);
263     m_hostImpl->setRootLayer(root.release());
264     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
265     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollFailed);
266 }
267
268 TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionBasic)
269 {
270     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
271     root->setScrollable(true);
272     root->setScrollPosition(IntPoint(0, 0));
273     root->setMaxScrollPosition(IntSize(100, 100));
274     root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
275     m_hostImpl->setRootLayer(root.release());
276     // All scroll types inside the non-fast scrollable region should fail.
277     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
278     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollFailed);
279
280     // All scroll types outside this region should succeed.
281     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
282     m_hostImpl->scrollBy(IntSize(0, 10));
283     m_hostImpl->scrollEnd();
284     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
285     m_hostImpl->scrollBy(IntSize(0, 10));
286     m_hostImpl->scrollEnd();
287 }
288
289 TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionWithOffset)
290 {
291     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
292     root->setScrollable(true);
293     root->setScrollPosition(IntPoint(0, 0));
294     root->setMaxScrollPosition(IntSize(100, 100));
295     root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
296     root->setPosition(FloatPoint(-25, 0));
297     m_hostImpl->setRootLayer(root.release());
298     CCLayerTreeHostImpl::FrameData frame;
299     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
300     m_hostImpl->drawLayers(frame); // Update draw transforms so we can correctly map points into layer space.
301
302     // This point would fall into the non-fast scrollable region except that we've moved the layer down by 25 pixels.
303     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(40, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
304     m_hostImpl->scrollBy(IntSize(0, 1));
305     m_hostImpl->scrollEnd();
306
307     // This point is still inside the non-fast region.
308     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(10, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
309 }
310
311 TEST_F(CCLayerTreeHostImplTest, pinchGesture)
312 {
313     setupScrollAndContentsLayers(IntSize(100, 100));
314     m_hostImpl->setViewportSize(IntSize(50, 50));
315
316     CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
317     ASSERT(scrollLayer);
318
319     const float minPageScale = 0.5, maxPageScale = 4;
320
321     // Basic pinch zoom in gesture
322     {
323         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
324         scrollLayer->setPageScaleDelta(1);
325         scrollLayer->setScrollDelta(IntSize());
326
327         float pageScaleDelta = 2;
328         m_hostImpl->pinchGestureBegin();
329         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
330         m_hostImpl->pinchGestureEnd();
331         EXPECT_TRUE(m_didRequestRedraw);
332         EXPECT_TRUE(m_didRequestCommit);
333
334         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
335         EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
336     }
337
338     // Zoom-in clamping
339     {
340         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
341         scrollLayer->setPageScaleDelta(1);
342         scrollLayer->setScrollDelta(IntSize());
343         float pageScaleDelta = 10;
344
345         m_hostImpl->pinchGestureBegin();
346         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
347         m_hostImpl->pinchGestureEnd();
348
349         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
350         EXPECT_EQ(scrollInfo->pageScaleDelta, maxPageScale);
351     }
352
353     // Zoom-out clamping
354     {
355         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
356         scrollLayer->setPageScaleDelta(1);
357         scrollLayer->setScrollDelta(IntSize());
358         scrollLayer->setScrollPosition(IntPoint(50, 50));
359
360         float pageScaleDelta = 0.1f;
361         m_hostImpl->pinchGestureBegin();
362         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(0, 0));
363         m_hostImpl->pinchGestureEnd();
364
365         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
366         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
367
368         // Pushed to (0,0) via clamping against contents layer size.
369         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
370     }
371
372     // Two-finger panning
373     {
374         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
375         scrollLayer->setPageScaleDelta(1);
376         scrollLayer->setScrollDelta(IntSize());
377         scrollLayer->setScrollPosition(IntPoint(20, 20));
378
379         float pageScaleDelta = 1;
380         m_hostImpl->pinchGestureBegin();
381         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(10, 10));
382         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(20, 20));
383         m_hostImpl->pinchGestureEnd();
384
385         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
386         EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
387         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-10, -10));
388     }
389 }
390
391 TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation)
392 {
393     setupScrollAndContentsLayers(IntSize(100, 100));
394     m_hostImpl->setViewportSize(IntSize(50, 50));
395
396     CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
397     ASSERT(scrollLayer);
398
399     const float minPageScale = 0.5, maxPageScale = 4;
400     const double startTime = 1;
401     const double duration = 0.1;
402     const double halfwayThroughAnimation = startTime + duration / 2;
403     const double endTime = startTime + duration;
404
405     // Non-anchor zoom-in
406     {
407         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
408         scrollLayer->setPageScaleDelta(1);
409         scrollLayer->setScrollPosition(IntPoint(50, 50));
410
411         m_hostImpl->startPageScaleAnimation(IntSize(0, 0), false, 2, startTime, duration);
412         m_hostImpl->animate(halfwayThroughAnimation, halfwayThroughAnimation);
413         EXPECT_TRUE(m_didRequestRedraw);
414         m_hostImpl->animate(endTime, endTime);
415         EXPECT_TRUE(m_didRequestCommit);
416
417         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
418         EXPECT_EQ(scrollInfo->pageScaleDelta, 2);
419         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
420     }
421
422     // Anchor zoom-out
423     {
424         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
425         scrollLayer->setPageScaleDelta(1);
426         scrollLayer->setScrollPosition(IntPoint(50, 50));
427
428         m_hostImpl->startPageScaleAnimation(IntSize(25, 25), true, minPageScale, startTime, duration);
429         m_hostImpl->animate(endTime, endTime);
430         EXPECT_TRUE(m_didRequestRedraw);
431         EXPECT_TRUE(m_didRequestCommit);
432
433         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
434         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
435         // Pushed to (0,0) via clamping against contents layer size.
436         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
437     }
438 }
439
440 class DidDrawCheckLayer : public CCTiledLayerImpl {
441 public:
442     static PassOwnPtr<DidDrawCheckLayer> create(int id) { return adoptPtr(new DidDrawCheckLayer(id)); }
443
444     virtual void didDraw()
445     {
446         m_didDrawCalled = true;
447     }
448
449     virtual void willDraw(CCRenderer*, CCGraphicsContext*)
450     {
451         m_willDrawCalled = true;
452     }
453
454     bool didDrawCalled() const { return m_didDrawCalled; }
455     bool willDrawCalled() const { return m_willDrawCalled; }
456
457     void clearDidDrawCheck()
458     {
459         m_didDrawCalled = false;
460         m_willDrawCalled = false;
461     }
462
463 protected:
464     explicit DidDrawCheckLayer(int id)
465         : CCTiledLayerImpl(id)
466         , m_didDrawCalled(false)
467         , m_willDrawCalled(false)
468     {
469         setAnchorPoint(FloatPoint(0, 0));
470         setBounds(IntSize(10, 10));
471         setContentBounds(IntSize(10, 10));
472         setDrawsContent(true);
473         setSkipsDraw(false);
474
475         OwnPtr<CCLayerTilingData> tiler = CCLayerTilingData::create(IntSize(100, 100), CCLayerTilingData::HasBorderTexels);
476         setTilingData(*tiler.get());
477     }
478
479 private:
480     bool m_didDrawCalled;
481     bool m_willDrawCalled;
482 };
483
484 TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer)
485 {
486     // The root layer is always drawn, so run this test on a child layer that
487     // will be masked out by the root layer's bounds.
488     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
489     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
490     root->setMasksToBounds(true);
491
492     root->addChild(DidDrawCheckLayer::create(1));
493     DidDrawCheckLayer* layer = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
494     // Ensure visibleLayerRect for layer is empty
495     layer->setPosition(FloatPoint(100, 100));
496     layer->setBounds(IntSize(10, 10));
497     layer->setContentBounds(IntSize(10, 10));
498
499     CCLayerTreeHostImpl::FrameData frame;
500
501     EXPECT_FALSE(layer->willDrawCalled());
502     EXPECT_FALSE(layer->didDrawCalled());
503
504     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
505     m_hostImpl->drawLayers(frame);
506     m_hostImpl->didDrawAllLayers(frame);
507
508     EXPECT_FALSE(layer->willDrawCalled());
509     EXPECT_FALSE(layer->didDrawCalled());
510
511     EXPECT_TRUE(layer->visibleLayerRect().isEmpty());
512
513     // Ensure visibleLayerRect for layer layer is not empty
514     layer->setPosition(FloatPoint(0, 0));
515
516     EXPECT_FALSE(layer->willDrawCalled());
517     EXPECT_FALSE(layer->didDrawCalled());
518
519     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
520     m_hostImpl->drawLayers(frame);
521     m_hostImpl->didDrawAllLayers(frame);
522
523     EXPECT_TRUE(layer->willDrawCalled());
524     EXPECT_TRUE(layer->didDrawCalled());
525
526     EXPECT_FALSE(layer->visibleLayerRect().isEmpty());
527 }
528
529 TEST_F(CCLayerTreeHostImplTest, willDrawNotCalledOnOccludedLayer)
530 {
531     // Make the viewport large so that we can have large layers that get considered for occlusion (small layers do not).
532     IntSize bigSize(1000, 1000);
533     m_hostImpl->setViewportSize(bigSize);
534
535     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
536     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
537
538     root->addChild(DidDrawCheckLayer::create(1));
539     DidDrawCheckLayer* occludedLayer = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
540
541     root->addChild(DidDrawCheckLayer::create(2));
542     DidDrawCheckLayer* topLayer = static_cast<DidDrawCheckLayer*>(root->children()[1].get());
543     // This layer covers the occludedLayer above. Make this layer large so it can occlude.
544     topLayer->setBounds(bigSize);
545     topLayer->setContentBounds(bigSize);
546     topLayer->setOpaque(true);
547
548     CCLayerTreeHostImpl::FrameData frame;
549
550     EXPECT_FALSE(occludedLayer->willDrawCalled());
551     EXPECT_FALSE(occludedLayer->didDrawCalled());
552     EXPECT_FALSE(topLayer->willDrawCalled());
553     EXPECT_FALSE(topLayer->didDrawCalled());
554
555     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
556     m_hostImpl->drawLayers(frame);
557     m_hostImpl->didDrawAllLayers(frame);
558
559     EXPECT_FALSE(occludedLayer->willDrawCalled());
560     EXPECT_FALSE(occludedLayer->didDrawCalled());
561     EXPECT_TRUE(topLayer->willDrawCalled());
562     EXPECT_TRUE(topLayer->didDrawCalled());
563 }
564
565 TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
566 {
567     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
568     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
569
570     root->addChild(DidDrawCheckLayer::create(1));
571     DidDrawCheckLayer* layer1 = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
572
573     layer1->addChild(DidDrawCheckLayer::create(2));
574     DidDrawCheckLayer* layer2 = static_cast<DidDrawCheckLayer*>(layer1->children()[0].get());
575
576     layer1->setOpacity(0.3f);
577     layer1->setPreserves3D(false);
578
579     EXPECT_FALSE(root->didDrawCalled());
580     EXPECT_FALSE(layer1->didDrawCalled());
581     EXPECT_FALSE(layer2->didDrawCalled());
582
583     CCLayerTreeHostImpl::FrameData frame;
584     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
585     m_hostImpl->drawLayers(frame);
586     m_hostImpl->didDrawAllLayers(frame);
587
588     EXPECT_TRUE(root->didDrawCalled());
589     EXPECT_TRUE(layer1->didDrawCalled());
590     EXPECT_TRUE(layer2->didDrawCalled());
591
592     EXPECT_NE(root->renderSurface(), layer1->renderSurface());
593     EXPECT_TRUE(!!layer1->renderSurface());
594 }
595
596 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
597 public:
598     static PassOwnPtr<MissingTextureAnimatingLayer> create(int id, bool tileMissing, bool skipsDraw, bool animating) { return adoptPtr(new MissingTextureAnimatingLayer(id, tileMissing, skipsDraw, animating)); }
599
600 private:
601     explicit MissingTextureAnimatingLayer(int id, bool tileMissing, bool skipsDraw, bool animating)
602         : DidDrawCheckLayer(id)
603     {
604         OwnPtr<CCLayerTilingData> tilingData = CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels);
605         tilingData->setBounds(bounds());
606         setTilingData(*tilingData.get());
607         setSkipsDraw(skipsDraw);
608         if (!tileMissing)
609             pushTileProperties(0, 0, 1, IntRect());
610         if (animating)
611             addAnimatedTransformToLayer(*this, 10, 3, 0);
612     }
613 };
614
615 TEST_F(CCLayerTreeHostImplTest, prepareToDrawFailsWhenAnimationUsesCheckerboard)
616 {
617     // When the texture is not missing, we draw as usual.
618     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
619     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
620     root->addChild(MissingTextureAnimatingLayer::create(1, false, false, true));
621
622     CCLayerTreeHostImpl::FrameData frame;
623
624     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
625     m_hostImpl->drawLayers(frame);
626     m_hostImpl->didDrawAllLayers(frame);
627
628     // When a texture is missing and we're not animating, we draw as usual with checkerboarding.
629     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
630     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
631     root->addChild(MissingTextureAnimatingLayer::create(1, true, false, false));
632
633     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
634     m_hostImpl->drawLayers(frame);
635     m_hostImpl->didDrawAllLayers(frame);
636
637     // When a texture is missing and we're animating, we don't want to draw anything.
638     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
639     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
640     root->addChild(MissingTextureAnimatingLayer::create(1, true, false, true));
641
642     EXPECT_FALSE(m_hostImpl->prepareToDraw(frame));
643     m_hostImpl->drawLayers(frame);
644     m_hostImpl->didDrawAllLayers(frame);
645
646     // When the layer skips draw and we're animating, we still draw the frame.
647     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
648     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
649     root->addChild(MissingTextureAnimatingLayer::create(1, false, true, true));
650
651     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
652     m_hostImpl->drawLayers(frame);
653     m_hostImpl->didDrawAllLayers(frame);
654 }
655
656 class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
657 public:
658     BlendStateTrackerContext() : m_blend(false) { }
659
660     virtual void enable(WGC3Denum cap)
661     {
662         if (cap == GraphicsContext3D::BLEND)
663             m_blend = true;
664     }
665
666     virtual void disable(WGC3Denum cap)
667     {
668         if (cap == GraphicsContext3D::BLEND)
669             m_blend = false;
670     }
671
672     bool blend() const { return m_blend; }
673
674 private:
675     bool m_blend;
676 };
677
678 class BlendStateCheckLayer : public CCLayerImpl {
679 public:
680     static PassOwnPtr<BlendStateCheckLayer> create(int id) { return adoptPtr(new BlendStateCheckLayer(id)); }
681
682     virtual void appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&) OVERRIDE
683     {
684         m_quadsAppended = true;
685
686         IntRect opaqueRect;
687         if (opaque() || m_opaqueContents)
688             opaqueRect = m_quadRect;
689         else
690             opaqueRect = m_opaqueContentRect;
691         OwnPtr<CCDrawQuad> testBlendingDrawQuad = CCTileDrawQuad::create(sharedQuadState, m_quadRect, opaqueRect, 0, IntPoint(), IntSize(1, 1), 0, false, false, false, false, false);
692         testBlendingDrawQuad->setQuadVisibleRect(m_quadVisibleRect);
693         EXPECT_EQ(m_blend, testBlendingDrawQuad->needsBlending());
694         EXPECT_EQ(m_hasRenderSurface, !!renderSurface());
695         quadList.append(testBlendingDrawQuad.release());
696     }
697
698     void setExpectation(bool blend, bool hasRenderSurface)
699     {
700         m_blend = blend;
701         m_hasRenderSurface = hasRenderSurface;
702         m_quadsAppended = false;
703     }
704
705     bool quadsAppended() const { return m_quadsAppended; }
706
707     void setQuadRect(const IntRect& rect) { m_quadRect = rect; }
708     void setQuadVisibleRect(const IntRect& rect) { m_quadVisibleRect = rect; }
709     void setOpaqueContents(bool opaque) { m_opaqueContents = opaque; }
710     void setOpaqueContentRect(const IntRect& rect) { m_opaqueContentRect = rect; }
711
712 private:
713     explicit BlendStateCheckLayer(int id)
714         : CCLayerImpl(id)
715         , m_blend(false)
716         , m_hasRenderSurface(false)
717         , m_quadsAppended(false)
718         , m_opaqueContents(false)
719         , m_quadRect(5, 5, 5, 5)
720         , m_quadVisibleRect(5, 5, 5, 5)
721     {
722         setAnchorPoint(FloatPoint(0, 0));
723         setBounds(IntSize(10, 10));
724         setDrawsContent(true);
725     }
726
727     bool m_blend;
728     bool m_hasRenderSurface;
729     bool m_quadsAppended;
730     bool m_opaqueContents;
731     IntRect m_quadRect;
732     IntRect m_opaqueContentRect;
733     IntRect m_quadVisibleRect;
734 };
735
736 // https://bugs.webkit.org/show_bug.cgi?id=75783
737 TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
738 {
739
740     {
741         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
742         root->setAnchorPoint(FloatPoint(0, 0));
743         root->setBounds(IntSize(10, 10));
744         root->setDrawsContent(false);
745         m_hostImpl->setRootLayer(root.release());
746     }
747     CCLayerImpl* root = m_hostImpl->rootLayer();
748
749     root->addChild(BlendStateCheckLayer::create(1));
750     BlendStateCheckLayer* layer1 = static_cast<BlendStateCheckLayer*>(root->children()[0].get());
751
752     CCLayerTreeHostImpl::FrameData frame;
753
754     // Opaque layer, drawn without blending.
755     layer1->setOpaque(true);
756     layer1->setOpaqueContents(true);
757     layer1->setExpectation(false, false);
758     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
759     m_hostImpl->drawLayers(frame);
760     EXPECT_TRUE(layer1->quadsAppended());
761     m_hostImpl->didDrawAllLayers(frame);
762
763     // Layer with translucent content, but opaque content, so drawn without blending.
764     layer1->setOpaque(false);
765     layer1->setOpaqueContents(true);
766     layer1->setExpectation(false, false);
767     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
768     m_hostImpl->drawLayers(frame);
769     EXPECT_TRUE(layer1->quadsAppended());
770     m_hostImpl->didDrawAllLayers(frame);
771
772     // Layer with translucent content and painting, so drawn with blending.
773     layer1->setOpaque(false);
774     layer1->setOpaqueContents(false);
775     layer1->setExpectation(true, false);
776     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
777     m_hostImpl->drawLayers(frame);
778     EXPECT_TRUE(layer1->quadsAppended());
779     m_hostImpl->didDrawAllLayers(frame);
780
781     // Layer with translucent opacity, drawn with blending.
782     layer1->setOpaque(true);
783     layer1->setOpaqueContents(true);
784     layer1->setOpacity(0.5);
785     layer1->setExpectation(true, false);
786     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
787     m_hostImpl->drawLayers(frame);
788     EXPECT_TRUE(layer1->quadsAppended());
789     m_hostImpl->didDrawAllLayers(frame);
790
791     // Layer with translucent opacity and painting, drawn with blending.
792     layer1->setOpaque(true);
793     layer1->setOpaqueContents(false);
794     layer1->setOpacity(0.5);
795     layer1->setExpectation(true, false);
796     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
797     m_hostImpl->drawLayers(frame);
798     EXPECT_TRUE(layer1->quadsAppended());
799     m_hostImpl->didDrawAllLayers(frame);
800
801     layer1->addChild(BlendStateCheckLayer::create(2));
802     BlendStateCheckLayer* layer2 = static_cast<BlendStateCheckLayer*>(layer1->children()[0].get());
803
804     // 2 opaque layers, drawn without blending.
805     layer1->setOpaque(true);
806     layer1->setOpaqueContents(true);
807     layer1->setOpacity(1);
808     layer1->setExpectation(false, false);
809     layer2->setOpaque(true);
810     layer2->setOpaqueContents(true);
811     layer2->setOpacity(1);
812     layer2->setExpectation(false, false);
813     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
814     m_hostImpl->drawLayers(frame);
815     EXPECT_TRUE(layer1->quadsAppended());
816     EXPECT_TRUE(layer2->quadsAppended());
817     m_hostImpl->didDrawAllLayers(frame);
818
819     // Parent layer with translucent content, drawn with blending.
820     // Child layer with opaque content, drawn without blending.
821     layer1->setOpaque(false);
822     layer1->setOpaqueContents(false);
823     layer1->setExpectation(true, false);
824     layer2->setExpectation(false, false);
825     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
826     m_hostImpl->drawLayers(frame);
827     EXPECT_TRUE(layer1->quadsAppended());
828     EXPECT_TRUE(layer2->quadsAppended());
829     m_hostImpl->didDrawAllLayers(frame);
830
831     // Parent layer with translucent content but opaque painting, drawn without blending.
832     // Child layer with opaque content, drawn without blending.
833     layer1->setOpaque(false);
834     layer1->setOpaqueContents(true);
835     layer1->setExpectation(false, false);
836     layer2->setExpectation(false, false);
837     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
838     m_hostImpl->drawLayers(frame);
839     EXPECT_TRUE(layer1->quadsAppended());
840     EXPECT_TRUE(layer2->quadsAppended());
841     m_hostImpl->didDrawAllLayers(frame);
842
843     // Parent layer with translucent opacity and opaque content. Since it has a
844     // drawing child, it's drawn to a render surface which carries the opacity,
845     // so it's itself drawn without blending.
846     // Child layer with opaque content, drawn without blending (parent surface
847     // carries the inherited opacity).
848     layer1->setOpaque(true);
849     layer1->setOpaqueContents(true);
850     layer1->setOpacity(0.5);
851     layer1->setExpectation(false, true);
852     layer2->setExpectation(false, false);
853     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
854     m_hostImpl->drawLayers(frame);
855     EXPECT_TRUE(layer1->quadsAppended());
856     EXPECT_TRUE(layer2->quadsAppended());
857     m_hostImpl->didDrawAllLayers(frame);
858
859     // Draw again, but with child non-opaque, to make sure
860     // layer1 not culled.
861     layer1->setOpaque(true);
862     layer1->setOpaqueContents(true);
863     layer1->setOpacity(1);
864     layer1->setExpectation(false, false);
865     layer2->setOpaque(true);
866     layer2->setOpaqueContents(true);
867     layer2->setOpacity(0.5);
868     layer2->setExpectation(true, false);
869     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
870     m_hostImpl->drawLayers(frame);
871     EXPECT_TRUE(layer1->quadsAppended());
872     EXPECT_TRUE(layer2->quadsAppended());
873     m_hostImpl->didDrawAllLayers(frame);
874
875     // A second way of making the child non-opaque.
876     layer1->setOpaque(true);
877     layer1->setOpacity(1);
878     layer1->setExpectation(false, false);
879     layer2->setOpaque(false);
880     layer2->setOpaqueContents(false);
881     layer2->setOpacity(1);
882     layer2->setExpectation(true, false);
883     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
884     m_hostImpl->drawLayers(frame);
885     EXPECT_TRUE(layer1->quadsAppended());
886     EXPECT_TRUE(layer2->quadsAppended());
887     m_hostImpl->didDrawAllLayers(frame);
888
889     // And when the layer says its not opaque but is painted opaque, it is not blended.
890     layer1->setOpaque(true);
891     layer1->setOpacity(1);
892     layer1->setExpectation(false, false);
893     layer2->setOpaque(false);
894     layer2->setOpaqueContents(true);
895     layer2->setOpacity(1);
896     layer2->setExpectation(false, false);
897     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
898     m_hostImpl->drawLayers(frame);
899     EXPECT_TRUE(layer1->quadsAppended());
900     EXPECT_TRUE(layer2->quadsAppended());
901     m_hostImpl->didDrawAllLayers(frame);
902
903     // Layer with partially opaque contents, drawn with blending.
904     layer1->setOpaque(false);
905     layer1->setQuadRect(IntRect(5, 5, 5, 5));
906     layer1->setQuadVisibleRect(IntRect(5, 5, 5, 5));
907     layer1->setOpaqueContents(false);
908     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
909     layer1->setExpectation(true, false);
910     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
911     m_hostImpl->drawLayers(frame);
912     EXPECT_TRUE(layer1->quadsAppended());
913     m_hostImpl->didDrawAllLayers(frame);
914
915     // Layer with partially opaque contents partially culled, drawn with blending.
916     layer1->setOpaque(false);
917     layer1->setQuadRect(IntRect(5, 5, 5, 5));
918     layer1->setQuadVisibleRect(IntRect(5, 5, 5, 2));
919     layer1->setOpaqueContents(false);
920     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
921     layer1->setExpectation(true, false);
922     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
923     m_hostImpl->drawLayers(frame);
924     EXPECT_TRUE(layer1->quadsAppended());
925     m_hostImpl->didDrawAllLayers(frame);
926
927     // Layer with partially opaque contents culled, drawn with blending.
928     layer1->setOpaque(false);
929     layer1->setQuadRect(IntRect(5, 5, 5, 5));
930     layer1->setQuadVisibleRect(IntRect(7, 5, 3, 5));
931     layer1->setOpaqueContents(false);
932     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
933     layer1->setExpectation(true, false);
934     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
935     m_hostImpl->drawLayers(frame);
936     EXPECT_TRUE(layer1->quadsAppended());
937     m_hostImpl->didDrawAllLayers(frame);
938
939     // Layer with partially opaque contents and translucent contents culled, drawn without blending.
940     layer1->setOpaque(false);
941     layer1->setQuadRect(IntRect(5, 5, 5, 5));
942     layer1->setQuadVisibleRect(IntRect(5, 5, 2, 5));
943     layer1->setOpaqueContents(false);
944     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
945     layer1->setExpectation(false, false);
946     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
947     m_hostImpl->drawLayers(frame);
948     EXPECT_TRUE(layer1->quadsAppended());
949     m_hostImpl->didDrawAllLayers(frame);
950
951 }
952
953 TEST_F(CCLayerTreeHostImplTest, viewportCovered)
954 {
955     m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
956     m_hostImpl->setBackgroundColor(Color::gray);
957
958     IntSize viewportSize(1000, 1000);
959     m_hostImpl->setViewportSize(viewportSize);
960
961     m_hostImpl->setRootLayer(BlendStateCheckLayer::create(0));
962     BlendStateCheckLayer* root = static_cast<BlendStateCheckLayer*>(m_hostImpl->rootLayer());
963     root->setExpectation(false, true);
964     root->setOpaque(true);
965
966     // No gutter rects
967     {
968         IntRect layerRect(0, 0, 1000, 1000);
969         root->setPosition(layerRect.location());
970         root->setBounds(layerRect.size());
971         root->setContentBounds(layerRect.size());
972         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
973         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
974
975         CCLayerTreeHostImpl::FrameData frame;
976         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
977         ASSERT_EQ(1u, frame.renderPasses.size());
978
979         size_t numGutterQuads = 0;
980         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
981             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
982         EXPECT_EQ(0u, numGutterQuads);
983         EXPECT_EQ(1u, frame.renderPasses[0]->quadList().size());
984
985         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
986         m_hostImpl->didDrawAllLayers(frame);
987     }
988
989     // Empty visible content area (fullscreen gutter rect)
990     {
991         IntRect layerRect(0, 0, 0, 0);
992         root->setPosition(layerRect.location());
993         root->setBounds(layerRect.size());
994         root->setContentBounds(layerRect.size());
995         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
996         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
997
998         CCLayerTreeHostImpl::FrameData frame;
999         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1000         ASSERT_EQ(1u, frame.renderPasses.size());
1001         m_hostImpl->didDrawAllLayers(frame);
1002
1003         size_t numGutterQuads = 0;
1004         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
1005             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
1006         EXPECT_EQ(1u, numGutterQuads);
1007         EXPECT_EQ(1u, frame.renderPasses[0]->quadList().size());
1008
1009         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
1010         m_hostImpl->didDrawAllLayers(frame);
1011     }
1012
1013     // Content area in middle of clip rect (four surrounding gutter rects)
1014     {
1015         IntRect layerRect(500, 500, 200, 200);
1016         root->setPosition(layerRect.location());
1017         root->setBounds(layerRect.size());
1018         root->setContentBounds(layerRect.size());
1019         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
1020         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
1021
1022         CCLayerTreeHostImpl::FrameData frame;
1023         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1024         ASSERT_EQ(1u, frame.renderPasses.size());
1025
1026         size_t numGutterQuads = 0;
1027         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
1028             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
1029         EXPECT_EQ(4u, numGutterQuads);
1030         EXPECT_EQ(5u, frame.renderPasses[0]->quadList().size());
1031
1032         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
1033         m_hostImpl->didDrawAllLayers(frame);
1034     }
1035
1036 }
1037
1038
1039 class ReshapeTrackerContext: public FakeWebGraphicsContext3D {
1040 public:
1041     ReshapeTrackerContext() : m_reshapeCalled(false) { }
1042
1043     virtual void reshape(int width, int height)
1044     {
1045         m_reshapeCalled = true;
1046     }
1047
1048     bool reshapeCalled() const { return m_reshapeCalled; }
1049
1050 private:
1051     bool m_reshapeCalled;
1052 };
1053
1054 class FakeDrawableCCLayerImpl: public CCLayerImpl {
1055 public:
1056     explicit FakeDrawableCCLayerImpl(int id) : CCLayerImpl(id) { }
1057 };
1058
1059 // Only reshape when we know we are going to draw. Otherwise, the reshape
1060 // can leave the window at the wrong size if we never draw and the proper
1061 // viewport size is never set.
1062 TEST_F(CCLayerTreeHostImplTest, reshapeNotCalledUntilDraw)
1063 {
1064     ReshapeTrackerContext* reshapeTracker = new ReshapeTrackerContext();
1065     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(reshapeTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
1066     RefPtr<CCGraphicsContext> ccContext = CCGraphicsContext::create3D(context);
1067     m_hostImpl->initializeLayerRenderer(ccContext, UnthrottledUploader);
1068
1069     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
1070     root->setAnchorPoint(FloatPoint(0, 0));
1071     root->setBounds(IntSize(10, 10));
1072     root->setDrawsContent(true);
1073     m_hostImpl->setRootLayer(adoptPtr(root));
1074     EXPECT_FALSE(reshapeTracker->reshapeCalled());
1075
1076     CCLayerTreeHostImpl::FrameData frame;
1077     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1078     m_hostImpl->drawLayers(frame);
1079     EXPECT_TRUE(reshapeTracker->reshapeCalled());
1080     m_hostImpl->didDrawAllLayers(frame);
1081 }
1082
1083 class PartialSwapTrackerContext : public FakeWebGraphicsContext3D {
1084 public:
1085     virtual void postSubBufferCHROMIUM(int x, int y, int width, int height)
1086     {
1087         m_partialSwapRect = IntRect(x, y, width, height);
1088     }
1089
1090     virtual WebString getString(WGC3Denum name)
1091     {
1092         if (name == GraphicsContext3D::EXTENSIONS)
1093             return WebString("GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
1094
1095         return WebString();
1096     }
1097
1098     IntRect partialSwapRect() const { return m_partialSwapRect; }
1099
1100 private:
1101     IntRect m_partialSwapRect;
1102 };
1103
1104 // Make sure damage tracking propagates all the way to the graphics context,
1105 // where it should request to swap only the subBuffer that is damaged.
1106 TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
1107 {
1108     PartialSwapTrackerContext* partialSwapTracker = new PartialSwapTrackerContext();
1109     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
1110     RefPtr<CCGraphicsContext> ccContext = CCGraphicsContext::create3D(context);
1111
1112     // This test creates its own CCLayerTreeHostImpl, so
1113     // that we can force partial swap enabled.
1114     CCSettings settings;
1115     settings.partialSwapEnabled = true;
1116     OwnPtr<CCLayerTreeHostImpl> layerTreeHostImpl = CCLayerTreeHostImpl::create(settings, this);
1117     layerTreeHostImpl->initializeLayerRenderer(ccContext, UnthrottledUploader);
1118     layerTreeHostImpl->setViewportSize(IntSize(500, 500));
1119
1120     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
1121     CCLayerImpl* child = new FakeDrawableCCLayerImpl(2);
1122     child->setPosition(FloatPoint(12, 13));
1123     child->setAnchorPoint(FloatPoint(0, 0));
1124     child->setBounds(IntSize(14, 15));
1125     child->setDrawsContent(true);
1126     root->setAnchorPoint(FloatPoint(0, 0));
1127     root->setBounds(IntSize(500, 500));
1128     root->setDrawsContent(true);
1129     root->addChild(adoptPtr(child));
1130     layerTreeHostImpl->setRootLayer(adoptPtr(root));
1131
1132     CCLayerTreeHostImpl::FrameData frame;
1133
1134     // First frame, the entire screen should get swapped.
1135     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1136     layerTreeHostImpl->drawLayers(frame);
1137     layerTreeHostImpl->didDrawAllLayers(frame);
1138     layerTreeHostImpl->swapBuffers();
1139     IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
1140     IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
1141     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1142     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1143     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1144     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1145
1146     // Second frame, only the damaged area should get swapped. Damage should be the union
1147     // of old and new child rects.
1148     // expected damage rect: IntRect(IntPoint::zero(), IntSize(26, 28));
1149     // expected swap rect: vertically flipped, with origin at bottom left corner.
1150     child->setPosition(FloatPoint(0, 0));
1151     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1152     layerTreeHostImpl->drawLayers(frame);
1153     m_hostImpl->didDrawAllLayers(frame);
1154     layerTreeHostImpl->swapBuffers();
1155     actualSwapRect = partialSwapTracker->partialSwapRect();
1156     expectedSwapRect = IntRect(IntPoint(0, 500-28), IntSize(26, 28));
1157     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1158     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1159     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1160     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1161
1162     // Make sure that partial swap is constrained to the viewport dimensions
1163     // expected damage rect: IntRect(IntPoint::zero(), IntSize(500, 500));
1164     // expected swap rect: flipped damage rect, but also clamped to viewport
1165     layerTreeHostImpl->setViewportSize(IntSize(10, 10));
1166     root->setOpacity(0.7f); // this will damage everything
1167     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1168     layerTreeHostImpl->drawLayers(frame);
1169     m_hostImpl->didDrawAllLayers(frame);
1170     layerTreeHostImpl->swapBuffers();
1171     actualSwapRect = partialSwapTracker->partialSwapRect();
1172     expectedSwapRect = IntRect(IntPoint::zero(), IntSize(10, 10));
1173     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1174     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1175     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1176     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1177 }
1178
1179 class FakeLayerWithQuads : public CCLayerImpl {
1180 public:
1181     static PassOwnPtr<FakeLayerWithQuads> create(int id) { return adoptPtr(new FakeLayerWithQuads(id)); }
1182
1183     virtual void appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&) OVERRIDE
1184     {
1185         const Color gray(100, 100, 100);
1186         IntRect quadRect(0, 0, 5, 5);
1187         OwnPtr<CCDrawQuad> myQuad = CCSolidColorDrawQuad::create(sharedQuadState, quadRect, gray);
1188         quadList.append(myQuad.release());
1189     }
1190
1191 private:
1192     FakeLayerWithQuads(int id)
1193         : CCLayerImpl(id)
1194     {
1195     }
1196 };
1197
1198 class MockContext : public FakeWebGraphicsContext3D {
1199 public:
1200     MOCK_METHOD1(useProgram, void(WebGLId program));
1201     MOCK_METHOD5(uniform4f, void(WGC3Dint location, WGC3Dfloat x, WGC3Dfloat y, WGC3Dfloat z, WGC3Dfloat w));
1202     MOCK_METHOD4(uniformMatrix4fv, void(WGC3Dint location, WGC3Dsizei count, WGC3Dboolean transpose, const WGC3Dfloat* value));
1203     MOCK_METHOD4(drawElements, void(WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset));
1204     MOCK_METHOD1(getString, WebString(WGC3Denum name));
1205     MOCK_METHOD0(getRequestableExtensionsCHROMIUM, WebString());
1206     MOCK_METHOD1(enable, void(WGC3Denum cap));
1207     MOCK_METHOD4(scissor, void(WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height));
1208 };
1209
1210 class MockContextHarness {
1211 private:
1212     MockContext* m_context;
1213 public:
1214     MockContextHarness(MockContext* context)
1215         : m_context(context)
1216     {
1217         // Catch "uninteresting" calls
1218         EXPECT_CALL(*m_context, useProgram(_))
1219             .Times(0);
1220
1221         EXPECT_CALL(*m_context, drawElements(_, _, _, _))
1222             .Times(0);
1223
1224         // These are not asserted
1225         EXPECT_CALL(*m_context, uniformMatrix4fv(_, _, _, _))
1226             .WillRepeatedly(Return());
1227
1228         EXPECT_CALL(*m_context, uniform4f(_, _, _, _, _))
1229             .WillRepeatedly(Return());
1230
1231         // Any other strings are empty
1232         EXPECT_CALL(*m_context, getString(_))
1233             .WillRepeatedly(Return(WebString()));
1234
1235         // Support for partial swap, if needed
1236         EXPECT_CALL(*m_context, getString(GraphicsContext3D::EXTENSIONS))
1237             .WillRepeatedly(Return(WebString("GL_CHROMIUM_post_sub_buffer")));
1238
1239         EXPECT_CALL(*m_context, getRequestableExtensionsCHROMIUM())
1240             .WillRepeatedly(Return(WebString("GL_CHROMIUM_post_sub_buffer")));
1241
1242         // Any un-sanctioned calls to enable() are OK
1243         EXPECT_CALL(*m_context, enable(_))
1244             .WillRepeatedly(Return());
1245     }
1246
1247     void mustDrawSolidQuad()
1248     {
1249         EXPECT_CALL(*m_context, drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0))
1250             .WillOnce(Return())
1251             .RetiresOnSaturation();
1252
1253         // 1 is hardcoded return value of fake createProgram()
1254         EXPECT_CALL(*m_context, useProgram(1))
1255             .WillOnce(Return())
1256             .RetiresOnSaturation();
1257
1258     }
1259
1260     void mustSetScissor(int x, int y, int width, int height)
1261     {
1262         EXPECT_CALL(*m_context, enable(GraphicsContext3D::SCISSOR_TEST))
1263             .WillRepeatedly(Return());
1264
1265         EXPECT_CALL(*m_context, scissor(x, y, width, height))
1266             .Times(AtLeast(1))
1267             .WillRepeatedly(Return());
1268     }
1269
1270 };
1271
1272 TEST_F(CCLayerTreeHostImplTest, noPartialSwap)
1273 {
1274     MockContext* mockContext = new MockContext();
1275     RefPtr<CCGraphicsContext> context = CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(mockContext), GraphicsContext3D::RenderDirectlyToHostWindow));
1276     MockContextHarness harness(mockContext);
1277
1278     harness.mustDrawSolidQuad();
1279     harness.mustSetScissor(0, 0, 10, 10);
1280
1281     // Run test case
1282     OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(false, context, FakeLayerWithQuads::create(1));
1283
1284     CCLayerTreeHostImpl::FrameData frame;
1285     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
1286     myHostImpl->drawLayers(frame);
1287     myHostImpl->didDrawAllLayers(frame);
1288     Mock::VerifyAndClearExpectations(&mockContext);
1289 }
1290
1291 TEST_F(CCLayerTreeHostImplTest, partialSwap)
1292 {
1293     MockContext* mockContext = new MockContext();
1294     RefPtr<CCGraphicsContext> context = CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(mockContext), GraphicsContext3D::RenderDirectlyToHostWindow));
1295     MockContextHarness harness(mockContext);
1296
1297     harness.mustDrawSolidQuad();
1298     harness.mustSetScissor(0, 0, 10, 10);
1299
1300     OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(true, context, FakeLayerWithQuads::create(1));
1301
1302     CCLayerTreeHostImpl::FrameData frame;
1303     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
1304     myHostImpl->drawLayers(frame);
1305     myHostImpl->didDrawAllLayers(frame);
1306     Mock::VerifyAndClearExpectations(&mockContext);
1307 }
1308
1309 TEST_F(CCLayerTreeHostImplTest, partialSwapNoUpdate)
1310 {
1311     MockContext* mockContext = new MockContext();
1312     RefPtr<CCGraphicsContext> context = CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(mockContext), GraphicsContext3D::RenderDirectlyToHostWindow));
1313     MockContextHarness harness(mockContext);
1314
1315     harness.mustDrawSolidQuad();
1316     harness.mustSetScissor(0, 8, 2, 2);
1317     harness.mustDrawSolidQuad();
1318     harness.mustSetScissor(0, 0, 10, 10);
1319
1320     OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(true, context, FakeLayerWithQuads::create(1));
1321     
1322     // Draw once to make sure layer is not new
1323     CCLayerTreeHostImpl::FrameData frame;
1324     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
1325     myHostImpl->drawLayers(frame);
1326     myHostImpl->didDrawAllLayers(frame);
1327
1328     // Generate update in layer
1329     CCLayerImpl* root = myHostImpl->rootLayer();
1330     root->setUpdateRect(FloatRect(0, 0, 2, 2));
1331
1332     // This draw should generate no new udpates
1333     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
1334     myHostImpl->drawLayers(frame);
1335     myHostImpl->didDrawAllLayers(frame);
1336
1337     Mock::VerifyAndClearExpectations(&mockContext);
1338 }
1339
1340 class PartialSwapContext: public FakeWebGraphicsContext3D {
1341 public:
1342     WebString getString(WGC3Denum name)
1343     {
1344         if (name == GraphicsContext3D::EXTENSIONS)
1345             return WebString("GL_CHROMIUM_post_sub_buffer");
1346         return WebString();
1347     }
1348     
1349     WebString getRequestableExtensionsCHROMIUM()
1350     {
1351         return WebString("GL_CHROMIUM_post_sub_buffer");
1352     }
1353 };
1354
1355 static PassOwnPtr<CCLayerTreeHostImpl> setupLayersForOpacity(bool partialSwap, CCLayerTreeHostImplClient* client)
1356 {
1357     CCSettings settings;
1358     settings.partialSwapEnabled = partialSwap;
1359
1360     RefPtr<CCGraphicsContext> context = CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new PartialSwapContext()), GraphicsContext3D::RenderDirectlyToHostWindow));
1361     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, client);
1362     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
1363     myHostImpl->setViewportSize(IntSize(100, 100));
1364
1365     /*
1366       Layers are created as follows:
1367
1368          +--------------------+
1369          |                  1 |
1370          |  +-----------+     |
1371          |  |         2 |     |
1372          |  | +-------------------+
1373          |  | |   3               |
1374          |  | +-------------------+
1375          |  |           |     |
1376          |  +-----------+     |
1377          |                    |
1378          |                    |
1379          +--------------------+
1380
1381          Layers 1, 2 have render surfaces
1382      */
1383     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
1384     OwnPtr<CCLayerImpl> child = CCLayerImpl::create(2);
1385     OwnPtr<CCLayerImpl> grandChild = FakeLayerWithQuads::create(3);
1386
1387     IntRect rootRect(0, 0, 100, 100);
1388     IntRect childRect(10, 10, 50, 50);
1389     IntRect grandChildRect(5, 5, 150, 150);
1390
1391     root->createRenderSurface();
1392     root->setAnchorPoint(FloatPoint(0, 0));
1393     root->setPosition(FloatPoint(rootRect.x(), rootRect.y()));
1394     root->setBounds(IntSize(rootRect.width(), rootRect.height()));
1395     root->setVisibleLayerRect(rootRect);
1396     root->setDrawsContent(false);
1397     root->renderSurface()->setContentRect(IntRect(IntPoint(), IntSize(rootRect.width(), rootRect.height())));
1398
1399     child->setAnchorPoint(FloatPoint(0, 0));
1400     child->setPosition(FloatPoint(childRect.x(), childRect.y()));
1401     child->setOpacity(0.5f);
1402     child->setBounds(IntSize(childRect.width(), childRect.height()));
1403     child->setVisibleLayerRect(childRect);
1404     child->setDrawsContent(false);
1405
1406     grandChild->setAnchorPoint(FloatPoint(0, 0));
1407     grandChild->setPosition(IntPoint(grandChildRect.x(), grandChildRect.y()));
1408     grandChild->setBounds(IntSize(grandChildRect.width(), grandChildRect.height()));
1409     grandChild->setVisibleLayerRect(grandChildRect);
1410     grandChild->setDrawsContent(true);
1411
1412     child->addChild(grandChild.release());
1413     root->addChild(child.release());
1414
1415     myHostImpl->setRootLayer(root.release());
1416     return myHostImpl.release();
1417 }
1418
1419 TEST_F(CCLayerTreeHostImplTest, contributingLayerEmptyScissorPartialSwap)
1420 {
1421     OwnPtr<CCLayerTreeHostImpl> myHostImpl = setupLayersForOpacity(true, this);
1422
1423     {
1424         CCLayerTreeHostImpl::FrameData frame;
1425         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
1426
1427         // Just for consistency, the most interesting stuff already happened
1428         myHostImpl->drawLayers(frame);
1429         myHostImpl->didDrawAllLayers(frame);
1430
1431         // Verify all quads have been computed
1432         ASSERT_EQ(2U, frame.renderPasses.size());
1433         ASSERT_EQ(1U, frame.renderPasses[0]->quadList().size());
1434         ASSERT_EQ(1U, frame.renderPasses[1]->quadList().size());
1435         EXPECT_EQ(CCDrawQuad::SolidColor, frame.renderPasses[0]->quadList()[0]->material());
1436         EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[1]->quadList()[0]->material());
1437     }
1438 }
1439
1440 TEST_F(CCLayerTreeHostImplTest, contributingLayerEmptyScissorNoPartialSwap)
1441 {
1442     OwnPtr<CCLayerTreeHostImpl> myHostImpl = setupLayersForOpacity(false, this);
1443
1444     {
1445         CCLayerTreeHostImpl::FrameData frame;
1446         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
1447
1448         // Just for consistency, the most interesting stuff already happened
1449         myHostImpl->drawLayers(frame);
1450         myHostImpl->didDrawAllLayers(frame);
1451
1452         // Verify all quads have been computed
1453         ASSERT_EQ(2U, frame.renderPasses.size());
1454         ASSERT_EQ(1U, frame.renderPasses[0]->quadList().size());
1455         ASSERT_EQ(1U, frame.renderPasses[1]->quadList().size());
1456         EXPECT_EQ(CCDrawQuad::SolidColor, frame.renderPasses[0]->quadList()[0]->material());
1457         EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[1]->quadList()[0]->material());
1458     }
1459 }
1460
1461 TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnScissoredLayer)
1462 {
1463     CCSettings settings;
1464     settings.partialSwapEnabled = true;
1465
1466     RefPtr<CCGraphicsContext> context = CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new PartialSwapContext()), GraphicsContext3D::RenderDirectlyToHostWindow));
1467     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
1468     myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
1469     myHostImpl->setViewportSize(IntSize(10, 10));
1470
1471     myHostImpl->setRootLayer(DidDrawCheckLayer::create(1));
1472     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(myHostImpl->rootLayer());
1473     root->setMasksToBounds(true);
1474
1475     root->addChild(DidDrawCheckLayer::create(2));
1476     DidDrawCheckLayer* layer = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
1477
1478     CCLayerTreeHostImpl::FrameData frame;
1479
1480     EXPECT_FALSE(root->willDrawCalled());
1481     EXPECT_FALSE(root->didDrawCalled());
1482     EXPECT_FALSE(layer->willDrawCalled());
1483     EXPECT_FALSE(layer->didDrawCalled());
1484
1485     // We should draw everything the first frame.
1486     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
1487     myHostImpl->drawLayers(frame);
1488     myHostImpl->didDrawAllLayers(frame);
1489
1490     EXPECT_TRUE(root->willDrawCalled());
1491     EXPECT_TRUE(root->didDrawCalled());
1492     EXPECT_TRUE(layer->willDrawCalled());
1493     EXPECT_TRUE(layer->didDrawCalled());
1494
1495     root->clearDidDrawCheck();
1496     layer->clearDidDrawCheck();
1497
1498     EXPECT_FALSE(root->willDrawCalled());
1499     EXPECT_FALSE(root->didDrawCalled());
1500     EXPECT_FALSE(layer->willDrawCalled());
1501     EXPECT_FALSE(layer->didDrawCalled());
1502
1503     // Drawing again, we should scissor out everything since there is no damage.
1504     EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
1505     myHostImpl->drawLayers(frame);
1506     myHostImpl->didDrawAllLayers(frame);
1507
1508     EXPECT_FALSE(root->willDrawCalled());
1509     EXPECT_FALSE(root->didDrawCalled());
1510     EXPECT_FALSE(layer->willDrawCalled());
1511     EXPECT_FALSE(layer->didDrawCalled());
1512 }
1513
1514 // Make sure that context lost notifications are propagated through the tree.
1515 class ContextLostNotificationCheckLayer : public CCLayerImpl {
1516 public:
1517     static PassOwnPtr<ContextLostNotificationCheckLayer> create(int id) { return adoptPtr(new ContextLostNotificationCheckLayer(id)); }
1518
1519     virtual void didLoseContext() OVERRIDE
1520     {
1521         m_didLoseContextCalled = true;
1522     }
1523
1524     bool didLoseContextCalled() const { return m_didLoseContextCalled; }
1525
1526 private:
1527     explicit ContextLostNotificationCheckLayer(int id)
1528         : CCLayerImpl(id)
1529         , m_didLoseContextCalled(false)
1530     {
1531     }
1532
1533     bool m_didLoseContextCalled;
1534 };
1535
1536 TEST_F(CCLayerTreeHostImplTest, contextLostAndRestoredNotificationSentToAllLayers)
1537 {
1538     m_hostImpl->setRootLayer(ContextLostNotificationCheckLayer::create(0));
1539     ContextLostNotificationCheckLayer* root = static_cast<ContextLostNotificationCheckLayer*>(m_hostImpl->rootLayer());
1540
1541     root->addChild(ContextLostNotificationCheckLayer::create(1));
1542     ContextLostNotificationCheckLayer* layer1 = static_cast<ContextLostNotificationCheckLayer*>(root->children()[0].get());
1543
1544     layer1->addChild(ContextLostNotificationCheckLayer::create(2));
1545     ContextLostNotificationCheckLayer* layer2 = static_cast<ContextLostNotificationCheckLayer*>(layer1->children()[0].get());
1546
1547     EXPECT_FALSE(root->didLoseContextCalled());
1548     EXPECT_FALSE(layer1->didLoseContextCalled());
1549     EXPECT_FALSE(layer2->didLoseContextCalled());
1550
1551     m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
1552
1553     EXPECT_TRUE(root->didLoseContextCalled());
1554     EXPECT_TRUE(layer1->didLoseContextCalled());
1555     EXPECT_TRUE(layer2->didLoseContextCalled());
1556 }
1557
1558 class FakeWebGraphicsContext3DMakeCurrentFails : public FakeWebGraphicsContext3D {
1559 public:
1560     virtual bool makeContextCurrent() { return false; }
1561 };
1562
1563 TEST_F(CCLayerTreeHostImplTest, finishAllRenderingAfterContextLost)
1564 {
1565     // The context initialization will fail, but we should still be able to call finishAllRendering() without any ill effects.
1566     m_hostImpl->initializeLayerRenderer(CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3DMakeCurrentFails), GraphicsContext3D::RenderDirectlyToHostWindow)), UnthrottledUploader);
1567     m_hostImpl->finishAllRendering();
1568 }
1569
1570 class ScrollbarLayerFakePaint : public CCScrollbarLayerImpl {
1571 public:
1572     static PassOwnPtr<ScrollbarLayerFakePaint> create(int id) { return adoptPtr(new ScrollbarLayerFakePaint(id)); }
1573
1574     virtual void paint(GraphicsContext*) { }
1575
1576 private:
1577     ScrollbarLayerFakePaint(int id) : CCScrollbarLayerImpl(id) { }
1578 };
1579
1580 TEST_F(CCLayerTreeHostImplTest, scrollbarLayerLostContext)
1581 {
1582     m_hostImpl->setRootLayer(ScrollbarLayerFakePaint::create(0));
1583     ScrollbarLayerFakePaint* scrollbar = static_cast<ScrollbarLayerFakePaint*>(m_hostImpl->rootLayer());
1584     scrollbar->setBounds(IntSize(1, 1));
1585     scrollbar->setContentBounds(IntSize(1, 1));
1586     scrollbar->setDrawsContent(true);
1587
1588     for (int i = 0; i < 2; ++i) {
1589         CCLayerTreeHostImpl::FrameData frame;
1590         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1591         ASSERT(frame.renderPasses.size() == 1);
1592         CCRenderPass* renderPass = frame.renderPasses[0].get();
1593         // Scrollbar layer should always generate quads, even after lost context
1594         EXPECT_GT(renderPass->quadList().size(), 0u);
1595         m_hostImpl->didDrawAllLayers(frame);
1596         m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
1597     }
1598 }
1599
1600 // Fake WebGraphicsContext3D that will cause a failure if trying to use a
1601 // resource that wasn't created by it (resources created by
1602 // FakeWebGraphicsContext3D have an id of 1).
1603 class StrictWebGraphicsContext3D : public FakeWebGraphicsContext3D {
1604 public:
1605     virtual WebGLId createBuffer() { return 2; }
1606     virtual WebGLId createFramebuffer() { return 3; }
1607     virtual WebGLId createProgram() { return 4; }
1608     virtual WebGLId createRenderbuffer() { return 5; }
1609     virtual WebGLId createShader(WGC3Denum) { return 6; }
1610     virtual WebGLId createTexture() { return 7; }
1611
1612     virtual void deleteBuffer(WebGLId id)
1613     {
1614         if (id != 2)
1615             ADD_FAILURE() << "Trying to delete buffer id " << id;
1616     }
1617
1618     virtual void deleteFramebuffer(WebGLId id)
1619     {
1620         if (id != 3)
1621             ADD_FAILURE() << "Trying to delete framebuffer id " << id;
1622     }
1623
1624     virtual void deleteProgram(WebGLId id)
1625     {
1626         if (id != 4)
1627             ADD_FAILURE() << "Trying to delete program id " << id;
1628     }
1629
1630     virtual void deleteRenderbuffer(WebGLId id)
1631     {
1632         if (id != 5)
1633             ADD_FAILURE() << "Trying to delete renderbuffer id " << id;
1634     }
1635
1636     virtual void deleteShader(WebGLId id)
1637     {
1638         if (id != 6)
1639             ADD_FAILURE() << "Trying to delete shader id " << id;
1640     }
1641
1642     virtual void deleteTexture(WebGLId id)
1643     {
1644         if (id != 7)
1645             ADD_FAILURE() << "Trying to delete texture id " << id;
1646     }
1647
1648     virtual void bindBuffer(WGC3Denum, WebGLId id)
1649     {
1650         if (id != 2 && id)
1651             ADD_FAILURE() << "Trying to bind buffer id " << id;
1652     }
1653
1654     virtual void bindFramebuffer(WGC3Denum, WebGLId id)
1655     {
1656         if (id != 3 && id)
1657             ADD_FAILURE() << "Trying to bind framebuffer id " << id;
1658     }
1659
1660     virtual void useProgram(WebGLId id)
1661     {
1662         if (id != 4)
1663             ADD_FAILURE() << "Trying to use program id " << id;
1664     }
1665
1666     virtual void bindRenderbuffer(WGC3Denum, WebGLId id)
1667     {
1668         if (id != 5 && id)
1669             ADD_FAILURE() << "Trying to bind renderbuffer id " << id;
1670     }
1671
1672     virtual void attachShader(WebGLId program, WebGLId shader)
1673     {
1674         if ((program != 4) || (shader != 6))
1675             ADD_FAILURE() << "Trying to attach shader id " << shader << " to program id " << program;
1676     }
1677
1678     virtual void bindTexture(WGC3Denum, WebGLId id)
1679     {
1680         if (id != 7 && id)
1681             ADD_FAILURE() << "Trying to bind texture id " << id;
1682     }
1683
1684     static PassRefPtr<GraphicsContext3D> createGraphicsContext()
1685     {
1686         return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new StrictWebGraphicsContext3D()), GraphicsContext3D::RenderDirectlyToHostWindow);
1687     }
1688 };
1689
1690 // Fake video frame that represents a 4x4 YUV video frame.
1691 class FakeVideoFrame: public WebVideoFrame {
1692 public:
1693     FakeVideoFrame() { memset(m_data, 0x80, sizeof(m_data)); }
1694     virtual ~FakeVideoFrame() { }
1695     virtual Format format() const { return FormatYV12; }
1696     virtual unsigned width() const { return 4; }
1697     virtual unsigned height() const { return 4; }
1698     virtual unsigned planes() const { return 3; }
1699     virtual int stride(unsigned plane) const { return 4; }
1700     virtual const void* data(unsigned plane) const { return m_data; }
1701     virtual unsigned textureId() const { return 0; }
1702     virtual unsigned textureTarget() const { return 0; }
1703
1704 private:
1705     char m_data[16];
1706 };
1707
1708 // Fake video frame provider that always provides the same FakeVideoFrame.
1709 class FakeVideoFrameProvider: public WebVideoFrameProvider {
1710 public:
1711     FakeVideoFrameProvider() : m_client(0) { }
1712     virtual ~FakeVideoFrameProvider()
1713     {
1714         if (m_client)
1715             m_client->stopUsingProvider();
1716     }
1717
1718     virtual void setVideoFrameProviderClient(Client* client) { m_client = client; }
1719     virtual WebVideoFrame* getCurrentFrame() { return &m_frame; }
1720     virtual void putCurrentFrame(WebVideoFrame*) { }
1721
1722 private:
1723     FakeVideoFrame m_frame;
1724     Client* m_client;
1725 };
1726
1727 TEST_F(CCLayerTreeHostImplTest, dontUseOldResourcesAfterLostContext)
1728 {
1729     OwnPtr<CCLayerImpl> rootLayer(CCLayerImpl::create(0));
1730     rootLayer->setBounds(IntSize(10, 10));
1731     rootLayer->setAnchorPoint(FloatPoint(0, 0));
1732
1733     OwnPtr<CCTiledLayerImpl> tileLayer = CCTiledLayerImpl::create(1);
1734     tileLayer->setBounds(IntSize(10, 10));
1735     tileLayer->setAnchorPoint(FloatPoint(0, 0));
1736     tileLayer->setContentBounds(IntSize(10, 10));
1737     tileLayer->setDrawsContent(true);
1738     tileLayer->setSkipsDraw(false);
1739     OwnPtr<CCLayerTilingData> tilingData(CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels));
1740     tilingData->setBounds(IntSize(10, 10));
1741     tileLayer->setTilingData(*tilingData);
1742     tileLayer->pushTileProperties(0, 0, 1, IntRect(0, 0, 10, 10));
1743     rootLayer->addChild(tileLayer.release());
1744
1745     OwnPtr<CCTextureLayerImpl> textureLayer = CCTextureLayerImpl::create(2);
1746     textureLayer->setBounds(IntSize(10, 10));
1747     textureLayer->setAnchorPoint(FloatPoint(0, 0));
1748     textureLayer->setContentBounds(IntSize(10, 10));
1749     textureLayer->setDrawsContent(true);
1750     textureLayer->setTextureId(1);
1751     rootLayer->addChild(textureLayer.release());
1752
1753     FakeVideoFrameProvider provider;
1754     OwnPtr<CCVideoLayerImpl> videoLayer = CCVideoLayerImpl::create(3, &provider);
1755     videoLayer->setBounds(IntSize(10, 10));
1756     videoLayer->setAnchorPoint(FloatPoint(0, 0));
1757     videoLayer->setContentBounds(IntSize(10, 10));
1758     videoLayer->setDrawsContent(true);
1759     rootLayer->addChild(videoLayer.release());
1760
1761     m_hostImpl->setRootLayer(rootLayer.release());
1762
1763     CCLayerTreeHostImpl::FrameData frame;
1764     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1765     m_hostImpl->drawLayers(frame);
1766     m_hostImpl->didDrawAllLayers(frame);
1767     m_hostImpl->swapBuffers();
1768
1769     // Lose the context, replacing it with a StrictWebGraphicsContext3D, that
1770     // will warn if any resource from the previous context gets used.
1771     m_hostImpl->initializeLayerRenderer(CCGraphicsContext::create3D(StrictWebGraphicsContext3D::createGraphicsContext()), UnthrottledUploader);
1772     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1773     m_hostImpl->drawLayers(frame);
1774     m_hostImpl->didDrawAllLayers(frame);
1775     m_hostImpl->swapBuffers();
1776 }
1777
1778 } // namespace