c7df1915ccd76defb87d290aa8a5b24aa462fe24
[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/CCTextureLayerImpl.h"
40 #include "cc/CCTileDrawQuad.h"
41 #include "cc/CCTiledLayerImpl.h"
42 #include "cc/CCVideoLayerImpl.h"
43 #include <gtest/gtest.h>
44 #include <public/WebVideoFrame.h>
45 #include <public/WebVideoFrameProvider.h>
46
47 using namespace CCLayerTestCommon;
48 using namespace WebCore;
49 using namespace WebKit;
50 using namespace WebKitTests;
51
52 namespace {
53
54 class CCLayerTreeHostImplTest : public testing::Test, public CCLayerTreeHostImplClient {
55 public:
56     CCLayerTreeHostImplTest()
57         : m_didRequestCommit(false)
58         , m_didRequestRedraw(false)
59     {
60         CCSettings settings;
61         m_hostImpl = CCLayerTreeHostImpl::create(settings, this);
62         m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
63         m_hostImpl->setViewportSize(IntSize(10, 10));
64     }
65
66     virtual void didLoseContextOnImplThread() OVERRIDE { }
67     virtual void onSwapBuffersCompleteOnImplThread() OVERRIDE { }
68     virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_didRequestRedraw = true; }
69     virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; }
70     virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE { }
71     virtual void postSetContentsMemoryAllocationLimitBytesToMainThreadOnImplThread(size_t) OVERRIDE { }
72
73     static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer)
74     {
75         ASSERT_EQ(layer->scrollDelta(), IntSize());
76         for (size_t i = 0; i < layer->children().size(); ++i)
77             expectClearedScrollDeltasRecursive(layer->children()[i].get());
78     }
79
80     static void expectContains(const CCScrollAndScaleSet& scrollInfo, int id, const IntSize& scrollDelta)
81     {
82         int timesEncountered = 0;
83
84         for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) {
85             if (scrollInfo.scrolls[i].layerId != id)
86                 continue;
87             EXPECT_EQ(scrollDelta.width(), scrollInfo.scrolls[i].scrollDelta.width());
88             EXPECT_EQ(scrollDelta.height(), scrollInfo.scrolls[i].scrollDelta.height());
89             timesEncountered++;
90         }
91
92         ASSERT_EQ(timesEncountered, 1);
93     }
94
95     void setupScrollAndContentsLayers(const IntSize& contentSize)
96     {
97         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
98         root->setScrollable(true);
99         root->setScrollPosition(IntPoint(0, 0));
100         root->setMaxScrollPosition(contentSize);
101         OwnPtr<CCLayerImpl> contents = CCLayerImpl::create(1);
102         contents->setDrawsContent(true);
103         contents->setBounds(contentSize);
104         contents->setContentBounds(contentSize);
105         root->addChild(contents.release());
106         m_hostImpl->setRootLayer(root.release());
107     }
108
109 protected:
110     PassRefPtr<CCGraphicsContext> createContext()
111     {
112         return CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3D()), GraphicsContext3D::RenderDirectlyToHostWindow));
113     }
114
115     DebugScopedSetImplThread m_alwaysImplThread;
116     DebugScopedSetMainThreadBlocked m_alwaysMainThreadBlocked;
117
118     OwnPtr<CCLayerTreeHostImpl> m_hostImpl;
119     bool m_didRequestCommit;
120     bool m_didRequestRedraw;
121 };
122
123 TEST_F(CCLayerTreeHostImplTest, scrollDeltaNoLayers)
124 {
125     ASSERT_FALSE(m_hostImpl->rootLayer());
126
127     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
128     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
129 }
130
131 TEST_F(CCLayerTreeHostImplTest, scrollDeltaTreeButNoChanges)
132 {
133     {
134         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
135         root->addChild(CCLayerImpl::create(1));
136         root->addChild(CCLayerImpl::create(2));
137         root->children()[1]->addChild(CCLayerImpl::create(3));
138         root->children()[1]->addChild(CCLayerImpl::create(4));
139         root->children()[1]->children()[0]->addChild(CCLayerImpl::create(5));
140         m_hostImpl->setRootLayer(root.release());
141     }
142     CCLayerImpl* root = m_hostImpl->rootLayer();
143
144     expectClearedScrollDeltasRecursive(root);
145
146     OwnPtr<CCScrollAndScaleSet> scrollInfo;
147
148     scrollInfo = m_hostImpl->processScrollDeltas();
149     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
150     expectClearedScrollDeltasRecursive(root);
151
152     scrollInfo = m_hostImpl->processScrollDeltas();
153     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
154     expectClearedScrollDeltasRecursive(root);
155 }
156
157 TEST_F(CCLayerTreeHostImplTest, scrollDeltaRepeatedScrolls)
158 {
159     IntPoint scrollPosition(20, 30);
160     IntSize scrollDelta(11, -15);
161     {
162         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(10);
163         root->setScrollPosition(scrollPosition);
164         root->setScrollable(true);
165         root->setMaxScrollPosition(IntSize(100, 100));
166         root->scrollBy(scrollDelta);
167         m_hostImpl->setRootLayer(root.release());
168     }
169     CCLayerImpl* root = m_hostImpl->rootLayer();
170
171     OwnPtr<CCScrollAndScaleSet> scrollInfo;
172
173     scrollInfo = m_hostImpl->processScrollDeltas();
174     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
175     EXPECT_EQ(root->sentScrollDelta(), scrollDelta);
176     expectContains(*scrollInfo, root->id(), scrollDelta);
177
178     IntSize scrollDelta2(-5, 27);
179     root->scrollBy(scrollDelta2);
180     scrollInfo = m_hostImpl->processScrollDeltas();
181     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
182     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
183     expectContains(*scrollInfo, root->id(), scrollDelta + scrollDelta2);
184
185     root->scrollBy(IntSize());
186     scrollInfo = m_hostImpl->processScrollDeltas();
187     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
188 }
189
190 TEST_F(CCLayerTreeHostImplTest, scrollRootCallsCommitAndRedraw)
191 {
192     {
193         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
194         root->setScrollable(true);
195         root->setScrollPosition(IntPoint(0, 0));
196         root->setMaxScrollPosition(IntSize(100, 100));
197         m_hostImpl->setRootLayer(root.release());
198     }
199
200     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
201     m_hostImpl->scrollBy(IntSize(0, 10));
202     m_hostImpl->scrollEnd();
203     EXPECT_TRUE(m_didRequestRedraw);
204     EXPECT_TRUE(m_didRequestCommit);
205 }
206
207 TEST_F(CCLayerTreeHostImplTest, wheelEventHandlers)
208 {
209     {
210         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
211         root->setScrollable(true);
212         root->setScrollPosition(IntPoint(0, 0));
213         root->setMaxScrollPosition(IntSize(100, 100));
214         m_hostImpl->setRootLayer(root.release());
215     }
216     CCLayerImpl* root = m_hostImpl->rootLayer();
217
218     root->setHaveWheelEventHandlers(true);
219     // With registered event handlers, wheel scrolls have to go to the main thread.
220     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
221
222     // But gesture scrolls can still be handled.
223     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
224 }
225
226 TEST_F(CCLayerTreeHostImplTest, shouldScrollOnMainThread)
227 {
228     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
229     root->setScrollable(true);
230     root->setScrollPosition(IntPoint(0, 0));
231     root->setMaxScrollPosition(IntSize(100, 100));
232     root->setShouldScrollOnMainThread(true);
233     m_hostImpl->setRootLayer(root.release());
234     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
235     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollFailed);
236 }
237
238 TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionBasic)
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     root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
245     m_hostImpl->setRootLayer(root.release());
246     // All scroll types inside the non-fast scrollable region should fail.
247     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
248     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollFailed);
249
250     // All scroll types outside this region should succeed.
251     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
252     m_hostImpl->scrollBy(IntSize(0, 10));
253     m_hostImpl->scrollEnd();
254     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
255     m_hostImpl->scrollBy(IntSize(0, 10));
256     m_hostImpl->scrollEnd();
257 }
258
259 TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionWithOffset)
260 {
261     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
262     root->setScrollable(true);
263     root->setScrollPosition(IntPoint(0, 0));
264     root->setMaxScrollPosition(IntSize(100, 100));
265     root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
266     root->setPosition(FloatPoint(-25, 0));
267     m_hostImpl->setRootLayer(root.release());
268     CCLayerTreeHostImpl::FrameData frame;
269     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
270     m_hostImpl->drawLayers(frame); // Update draw transforms so we can correctly map points into layer space.
271
272     // This point would fall into the non-fast scrollable region except that we've moved the layer down by 25 pixels.
273     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(40, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
274     m_hostImpl->scrollBy(IntSize(0, 1));
275     m_hostImpl->scrollEnd();
276
277     // This point is still inside the non-fast region.
278     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(10, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
279 }
280
281 TEST_F(CCLayerTreeHostImplTest, pinchGesture)
282 {
283     setupScrollAndContentsLayers(IntSize(100, 100));
284     m_hostImpl->setViewportSize(IntSize(50, 50));
285
286     CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
287     ASSERT(scrollLayer);
288
289     const float minPageScale = 0.5, maxPageScale = 4;
290
291     // Basic pinch zoom in gesture
292     {
293         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
294         scrollLayer->setPageScaleDelta(1);
295         scrollLayer->setScrollDelta(IntSize());
296
297         float pageScaleDelta = 2;
298         m_hostImpl->pinchGestureBegin();
299         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
300         m_hostImpl->pinchGestureEnd();
301         EXPECT_TRUE(m_didRequestRedraw);
302         EXPECT_TRUE(m_didRequestCommit);
303
304         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
305         EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
306     }
307
308     // Zoom-in clamping
309     {
310         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
311         scrollLayer->setPageScaleDelta(1);
312         scrollLayer->setScrollDelta(IntSize());
313         float pageScaleDelta = 10;
314
315         m_hostImpl->pinchGestureBegin();
316         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
317         m_hostImpl->pinchGestureEnd();
318
319         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
320         EXPECT_EQ(scrollInfo->pageScaleDelta, maxPageScale);
321     }
322
323     // Zoom-out clamping
324     {
325         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
326         scrollLayer->setPageScaleDelta(1);
327         scrollLayer->setScrollDelta(IntSize());
328         scrollLayer->setScrollPosition(IntPoint(50, 50));
329
330         float pageScaleDelta = 0.1f;
331         m_hostImpl->pinchGestureBegin();
332         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(0, 0));
333         m_hostImpl->pinchGestureEnd();
334
335         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
336         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
337
338         // Pushed to (0,0) via clamping against contents layer size.
339         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
340     }
341
342     // Two-finger panning
343     {
344         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
345         scrollLayer->setPageScaleDelta(1);
346         scrollLayer->setScrollDelta(IntSize());
347         scrollLayer->setScrollPosition(IntPoint(20, 20));
348
349         float pageScaleDelta = 1;
350         m_hostImpl->pinchGestureBegin();
351         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(10, 10));
352         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(20, 20));
353         m_hostImpl->pinchGestureEnd();
354
355         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
356         EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
357         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-10, -10));
358     }
359 }
360
361 TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation)
362 {
363     setupScrollAndContentsLayers(IntSize(100, 100));
364     m_hostImpl->setViewportSize(IntSize(50, 50));
365
366     CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
367     ASSERT(scrollLayer);
368
369     const float minPageScale = 0.5, maxPageScale = 4;
370     const double startTime = 1;
371     const double duration = 0.1;
372     const double halfwayThroughAnimation = startTime + duration / 2;
373     const double endTime = startTime + duration;
374
375     // Non-anchor zoom-in
376     {
377         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
378         scrollLayer->setPageScaleDelta(1);
379         scrollLayer->setScrollPosition(IntPoint(50, 50));
380
381         m_hostImpl->startPageScaleAnimation(IntSize(0, 0), false, 2, startTime, duration);
382         m_hostImpl->animate(halfwayThroughAnimation, halfwayThroughAnimation);
383         EXPECT_TRUE(m_didRequestRedraw);
384         m_hostImpl->animate(endTime, endTime);
385         EXPECT_TRUE(m_didRequestCommit);
386
387         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
388         EXPECT_EQ(scrollInfo->pageScaleDelta, 2);
389         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
390     }
391
392     // Anchor zoom-out
393     {
394         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
395         scrollLayer->setPageScaleDelta(1);
396         scrollLayer->setScrollPosition(IntPoint(50, 50));
397
398         m_hostImpl->startPageScaleAnimation(IntSize(25, 25), true, minPageScale, startTime, duration);
399         m_hostImpl->animate(endTime, endTime);
400         EXPECT_TRUE(m_didRequestRedraw);
401         EXPECT_TRUE(m_didRequestCommit);
402
403         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
404         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
405         // Pushed to (0,0) via clamping against contents layer size.
406         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
407     }
408 }
409
410 class DidDrawCheckLayer : public CCTiledLayerImpl {
411 public:
412     static PassOwnPtr<DidDrawCheckLayer> create(int id) { return adoptPtr(new DidDrawCheckLayer(id)); }
413
414     virtual void didDraw()
415     {
416         m_didDrawCalled = true;
417     }
418
419     virtual void willDraw(CCRenderer*, CCGraphicsContext*)
420     {
421         m_willDrawCalled = true;
422     }
423
424     bool didDrawCalled() const { return m_didDrawCalled; }
425     bool willDrawCalled() const { return m_willDrawCalled; }
426
427 protected:
428     explicit DidDrawCheckLayer(int id)
429         : CCTiledLayerImpl(id)
430         , m_didDrawCalled(false)
431         , m_willDrawCalled(false)
432     {
433         setAnchorPoint(FloatPoint(0, 0));
434         setBounds(IntSize(10, 10));
435         setDrawsContent(true);
436     }
437
438 private:
439     bool m_didDrawCalled;
440     bool m_willDrawCalled;
441 };
442
443 TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer)
444 {
445     // The root layer is always drawn, so run this test on a child layer that
446     // will be masked out by the root layer's bounds.
447     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
448     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
449     root->setMasksToBounds(true);
450
451     root->addChild(DidDrawCheckLayer::create(1));
452     DidDrawCheckLayer* layer = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
453     // Ensure visibleLayerRect for layer is empty
454     layer->setPosition(FloatPoint(100, 100));
455     layer->setBounds(IntSize(10, 10));
456     layer->setContentBounds(IntSize(10, 10));
457
458     CCLayerTreeHostImpl::FrameData frame;
459
460     EXPECT_FALSE(layer->willDrawCalled());
461     EXPECT_FALSE(layer->didDrawCalled());
462
463     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
464     m_hostImpl->drawLayers(frame);
465     m_hostImpl->didDrawAllLayers(frame);
466
467     EXPECT_FALSE(layer->willDrawCalled());
468     EXPECT_FALSE(layer->didDrawCalled());
469
470     EXPECT_TRUE(layer->visibleLayerRect().isEmpty());
471
472     // Ensure visibleLayerRect for layer layer is not empty
473     layer->setPosition(FloatPoint(0, 0));
474
475     EXPECT_FALSE(layer->willDrawCalled());
476     EXPECT_FALSE(layer->didDrawCalled());
477
478     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
479     m_hostImpl->drawLayers(frame);
480     m_hostImpl->didDrawAllLayers(frame);
481
482     EXPECT_TRUE(layer->willDrawCalled());
483     EXPECT_TRUE(layer->didDrawCalled());
484
485     EXPECT_FALSE(layer->visibleLayerRect().isEmpty());
486 }
487
488 TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
489 {
490     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
491     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
492
493     root->addChild(DidDrawCheckLayer::create(1));
494     DidDrawCheckLayer* layer1 = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
495
496     layer1->addChild(DidDrawCheckLayer::create(2));
497     DidDrawCheckLayer* layer2 = static_cast<DidDrawCheckLayer*>(layer1->children()[0].get());
498
499     layer1->setOpacity(0.3f);
500     layer1->setPreserves3D(false);
501
502     EXPECT_FALSE(root->didDrawCalled());
503     EXPECT_FALSE(layer1->didDrawCalled());
504     EXPECT_FALSE(layer2->didDrawCalled());
505
506     CCLayerTreeHostImpl::FrameData frame;
507     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
508     m_hostImpl->drawLayers(frame);
509     m_hostImpl->didDrawAllLayers(frame);
510
511     EXPECT_TRUE(root->didDrawCalled());
512     EXPECT_TRUE(layer1->didDrawCalled());
513     EXPECT_TRUE(layer2->didDrawCalled());
514
515     EXPECT_NE(root->renderSurface(), layer1->renderSurface());
516     EXPECT_TRUE(!!layer1->renderSurface());
517 }
518
519 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
520 public:
521     static PassOwnPtr<MissingTextureAnimatingLayer> create(int id, bool tileMissing, bool skipsDraw, bool animating) { return adoptPtr(new MissingTextureAnimatingLayer(id, tileMissing, skipsDraw, animating)); }
522
523 private:
524     explicit MissingTextureAnimatingLayer(int id, bool tileMissing, bool skipsDraw, bool animating)
525         : DidDrawCheckLayer(id)
526     {
527         OwnPtr<CCLayerTilingData> tilingData = CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels);
528         tilingData->setBounds(bounds());
529         setTilingData(*tilingData.get());
530         setSkipsDraw(skipsDraw);
531         if (!tileMissing)
532             pushTileProperties(0, 0, 1, IntRect());
533         if (animating)
534             addAnimatedTransformToLayer(*this, 10, 3, 0);
535     }
536 };
537
538 TEST_F(CCLayerTreeHostImplTest, prepareToDrawFailsWhenAnimationUsesCheckerboard)
539 {
540     // When the texture is not missing, we draw as usual.
541     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
542     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
543     root->addChild(MissingTextureAnimatingLayer::create(1, false, false, true));
544
545     CCLayerTreeHostImpl::FrameData frame;
546
547     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
548     m_hostImpl->drawLayers(frame);
549     m_hostImpl->didDrawAllLayers(frame);
550
551     // When a texture is missing and we're not animating, we draw as usual with checkerboarding.
552     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
553     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
554     root->addChild(MissingTextureAnimatingLayer::create(1, true, false, false));
555
556     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
557     m_hostImpl->drawLayers(frame);
558     m_hostImpl->didDrawAllLayers(frame);
559
560     // When a texture is missing and we're animating, we don't want to draw anything.
561     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
562     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
563     root->addChild(MissingTextureAnimatingLayer::create(1, true, false, true));
564
565     m_didRequestCommit = false;
566     EXPECT_FALSE(m_hostImpl->prepareToDraw(frame));
567     EXPECT_TRUE(m_didRequestCommit);
568     m_hostImpl->drawLayers(frame);
569     m_hostImpl->didDrawAllLayers(frame);
570
571     // When the layer skips draw and we're animating, we still draw the frame.
572     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
573     root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
574     root->addChild(MissingTextureAnimatingLayer::create(1, false, true, true));
575
576     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
577     m_hostImpl->drawLayers(frame);
578     m_hostImpl->didDrawAllLayers(frame);
579 }
580
581 class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
582 public:
583     BlendStateTrackerContext() : m_blend(false) { }
584
585     virtual void enable(WGC3Denum cap)
586     {
587         if (cap == GraphicsContext3D::BLEND)
588             m_blend = true;
589     }
590
591     virtual void disable(WGC3Denum cap)
592     {
593         if (cap == GraphicsContext3D::BLEND)
594             m_blend = false;
595     }
596
597     bool blend() const { return m_blend; }
598
599 private:
600     bool m_blend;
601 };
602
603 class BlendStateCheckLayer : public CCLayerImpl {
604 public:
605     static PassOwnPtr<BlendStateCheckLayer> create(int id) { return adoptPtr(new BlendStateCheckLayer(id)); }
606
607     virtual void appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState, bool&) OVERRIDE
608     {
609         m_quadsAppended = true;
610
611         IntRect opaqueRect;
612         if (opaque() || m_opaqueContents)
613             opaqueRect = m_quadRect;
614         else
615             opaqueRect = m_opaqueContentRect;
616         OwnPtr<CCDrawQuad> testBlendingDrawQuad = CCTileDrawQuad::create(sharedQuadState, m_quadRect, opaqueRect, 0, IntPoint(), IntSize(1, 1), 0, false, false, false, false, false);
617         testBlendingDrawQuad->setQuadVisibleRect(m_quadVisibleRect);
618         EXPECT_EQ(m_blend, testBlendingDrawQuad->needsBlending());
619         EXPECT_EQ(m_hasRenderSurface, !!renderSurface());
620         quadList.append(testBlendingDrawQuad.release());
621     }
622
623     void setExpectation(bool blend, bool hasRenderSurface)
624     {
625         m_blend = blend;
626         m_hasRenderSurface = hasRenderSurface;
627         m_quadsAppended = false;
628     }
629
630     bool quadsAppended() const { return m_quadsAppended; }
631
632     void setQuadRect(const IntRect& rect) { m_quadRect = rect; }
633     void setQuadVisibleRect(const IntRect& rect) { m_quadVisibleRect = rect; }
634     void setOpaqueContents(bool opaque) { m_opaqueContents = opaque; }
635     void setOpaqueContentRect(const IntRect& rect) { m_opaqueContentRect = rect; }
636
637 private:
638     explicit BlendStateCheckLayer(int id)
639         : CCLayerImpl(id)
640         , m_blend(false)
641         , m_hasRenderSurface(false)
642         , m_quadsAppended(false)
643         , m_opaqueContents(false)
644         , m_quadRect(5, 5, 5, 5)
645         , m_quadVisibleRect(5, 5, 5, 5)
646     {
647         setAnchorPoint(FloatPoint(0, 0));
648         setBounds(IntSize(10, 10));
649         setDrawsContent(true);
650     }
651
652     bool m_blend;
653     bool m_hasRenderSurface;
654     bool m_quadsAppended;
655     bool m_opaqueContents;
656     IntRect m_quadRect;
657     IntRect m_opaqueContentRect;
658     IntRect m_quadVisibleRect;
659 };
660
661 // https://bugs.webkit.org/show_bug.cgi?id=75783
662 TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
663 {
664
665     {
666         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
667         root->setAnchorPoint(FloatPoint(0, 0));
668         root->setBounds(IntSize(10, 10));
669         root->setDrawsContent(false);
670         m_hostImpl->setRootLayer(root.release());
671     }
672     CCLayerImpl* root = m_hostImpl->rootLayer();
673
674     root->addChild(BlendStateCheckLayer::create(1));
675     BlendStateCheckLayer* layer1 = static_cast<BlendStateCheckLayer*>(root->children()[0].get());
676
677     CCLayerTreeHostImpl::FrameData frame;
678
679     // Opaque layer, drawn without blending.
680     layer1->setOpaque(true);
681     layer1->setOpaqueContents(true);
682     layer1->setExpectation(false, false);
683     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
684     m_hostImpl->drawLayers(frame);
685     EXPECT_TRUE(layer1->quadsAppended());
686     m_hostImpl->didDrawAllLayers(frame);
687
688     // Layer with translucent content, but opaque content, so drawn without blending.
689     layer1->setOpaque(false);
690     layer1->setOpaqueContents(true);
691     layer1->setExpectation(false, false);
692     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
693     m_hostImpl->drawLayers(frame);
694     EXPECT_TRUE(layer1->quadsAppended());
695     m_hostImpl->didDrawAllLayers(frame);
696
697     // Layer with translucent content and painting, so drawn with blending.
698     layer1->setOpaque(false);
699     layer1->setOpaqueContents(false);
700     layer1->setExpectation(true, false);
701     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
702     m_hostImpl->drawLayers(frame);
703     EXPECT_TRUE(layer1->quadsAppended());
704     m_hostImpl->didDrawAllLayers(frame);
705
706     // Layer with translucent opacity, drawn with blending.
707     layer1->setOpaque(true);
708     layer1->setOpaqueContents(true);
709     layer1->setOpacity(0.5);
710     layer1->setExpectation(true, false);
711     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
712     m_hostImpl->drawLayers(frame);
713     EXPECT_TRUE(layer1->quadsAppended());
714     m_hostImpl->didDrawAllLayers(frame);
715
716     // Layer with translucent opacity and painting, drawn with blending.
717     layer1->setOpaque(true);
718     layer1->setOpaqueContents(false);
719     layer1->setOpacity(0.5);
720     layer1->setExpectation(true, false);
721     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
722     m_hostImpl->drawLayers(frame);
723     EXPECT_TRUE(layer1->quadsAppended());
724     m_hostImpl->didDrawAllLayers(frame);
725
726     layer1->addChild(BlendStateCheckLayer::create(2));
727     BlendStateCheckLayer* layer2 = static_cast<BlendStateCheckLayer*>(layer1->children()[0].get());
728
729     // 2 opaque layers, drawn without blending.
730     layer1->setOpaque(true);
731     layer1->setOpaqueContents(true);
732     layer1->setOpacity(1);
733     layer1->setExpectation(false, false);
734     layer2->setOpaque(true);
735     layer2->setOpaqueContents(true);
736     layer2->setOpacity(1);
737     layer2->setExpectation(false, false);
738     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
739     m_hostImpl->drawLayers(frame);
740     EXPECT_TRUE(layer1->quadsAppended());
741     EXPECT_TRUE(layer2->quadsAppended());
742     m_hostImpl->didDrawAllLayers(frame);
743
744     // Parent layer with translucent content, drawn with blending.
745     // Child layer with opaque content, drawn without blending.
746     layer1->setOpaque(false);
747     layer1->setOpaqueContents(false);
748     layer1->setExpectation(true, false);
749     layer2->setExpectation(false, false);
750     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
751     m_hostImpl->drawLayers(frame);
752     EXPECT_TRUE(layer1->quadsAppended());
753     EXPECT_TRUE(layer2->quadsAppended());
754     m_hostImpl->didDrawAllLayers(frame);
755
756     // Parent layer with translucent content but opaque painting, drawn without blending.
757     // Child layer with opaque content, drawn without blending.
758     layer1->setOpaque(false);
759     layer1->setOpaqueContents(true);
760     layer1->setExpectation(false, false);
761     layer2->setExpectation(false, false);
762     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
763     m_hostImpl->drawLayers(frame);
764     EXPECT_TRUE(layer1->quadsAppended());
765     EXPECT_TRUE(layer2->quadsAppended());
766     m_hostImpl->didDrawAllLayers(frame);
767
768     // Parent layer with translucent opacity and opaque content. Since it has a
769     // drawing child, it's drawn to a render surface which carries the opacity,
770     // so it's itself drawn without blending.
771     // Child layer with opaque content, drawn without blending (parent surface
772     // carries the inherited opacity).
773     layer1->setOpaque(true);
774     layer1->setOpaqueContents(true);
775     layer1->setOpacity(0.5);
776     layer1->setExpectation(false, true);
777     layer2->setExpectation(false, false);
778     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
779     m_hostImpl->drawLayers(frame);
780     EXPECT_TRUE(layer1->quadsAppended());
781     EXPECT_TRUE(layer2->quadsAppended());
782     m_hostImpl->didDrawAllLayers(frame);
783
784     // Draw again, but with child non-opaque, to make sure
785     // layer1 not culled.
786     layer1->setOpaque(true);
787     layer1->setOpaqueContents(true);
788     layer1->setOpacity(1);
789     layer1->setExpectation(false, false);
790     layer2->setOpaque(true);
791     layer2->setOpaqueContents(true);
792     layer2->setOpacity(0.5);
793     layer2->setExpectation(true, false);
794     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
795     m_hostImpl->drawLayers(frame);
796     EXPECT_TRUE(layer1->quadsAppended());
797     EXPECT_TRUE(layer2->quadsAppended());
798     m_hostImpl->didDrawAllLayers(frame);
799
800     // A second way of making the child non-opaque.
801     layer1->setOpaque(true);
802     layer1->setOpacity(1);
803     layer1->setExpectation(false, false);
804     layer2->setOpaque(false);
805     layer2->setOpaqueContents(false);
806     layer2->setOpacity(1);
807     layer2->setExpectation(true, false);
808     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
809     m_hostImpl->drawLayers(frame);
810     EXPECT_TRUE(layer1->quadsAppended());
811     EXPECT_TRUE(layer2->quadsAppended());
812     m_hostImpl->didDrawAllLayers(frame);
813
814     // And when the layer says its not opaque but is painted opaque, it is not blended.
815     layer1->setOpaque(true);
816     layer1->setOpacity(1);
817     layer1->setExpectation(false, false);
818     layer2->setOpaque(false);
819     layer2->setOpaqueContents(true);
820     layer2->setOpacity(1);
821     layer2->setExpectation(false, false);
822     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
823     m_hostImpl->drawLayers(frame);
824     EXPECT_TRUE(layer1->quadsAppended());
825     EXPECT_TRUE(layer2->quadsAppended());
826     m_hostImpl->didDrawAllLayers(frame);
827
828     // Layer with partially opaque contents, drawn with blending.
829     layer1->setOpaque(false);
830     layer1->setQuadRect(IntRect(5, 5, 5, 5));
831     layer1->setQuadVisibleRect(IntRect(5, 5, 5, 5));
832     layer1->setOpaqueContents(false);
833     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
834     layer1->setExpectation(true, false);
835     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
836     m_hostImpl->drawLayers(frame);
837     EXPECT_TRUE(layer1->quadsAppended());
838     m_hostImpl->didDrawAllLayers(frame);
839
840     // Layer with partially opaque contents partially culled, drawn with blending.
841     layer1->setOpaque(false);
842     layer1->setQuadRect(IntRect(5, 5, 5, 5));
843     layer1->setQuadVisibleRect(IntRect(5, 5, 5, 2));
844     layer1->setOpaqueContents(false);
845     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
846     layer1->setExpectation(true, false);
847     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
848     m_hostImpl->drawLayers(frame);
849     EXPECT_TRUE(layer1->quadsAppended());
850     m_hostImpl->didDrawAllLayers(frame);
851
852     // Layer with partially opaque contents culled, drawn with blending.
853     layer1->setOpaque(false);
854     layer1->setQuadRect(IntRect(5, 5, 5, 5));
855     layer1->setQuadVisibleRect(IntRect(7, 5, 3, 5));
856     layer1->setOpaqueContents(false);
857     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
858     layer1->setExpectation(true, false);
859     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
860     m_hostImpl->drawLayers(frame);
861     EXPECT_TRUE(layer1->quadsAppended());
862     m_hostImpl->didDrawAllLayers(frame);
863
864     // Layer with partially opaque contents and translucent contents culled, drawn without blending.
865     layer1->setOpaque(false);
866     layer1->setQuadRect(IntRect(5, 5, 5, 5));
867     layer1->setQuadVisibleRect(IntRect(5, 5, 2, 5));
868     layer1->setOpaqueContents(false);
869     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
870     layer1->setExpectation(false, false);
871     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
872     m_hostImpl->drawLayers(frame);
873     EXPECT_TRUE(layer1->quadsAppended());
874     m_hostImpl->didDrawAllLayers(frame);
875
876 }
877
878 TEST_F(CCLayerTreeHostImplTest, viewportCovered)
879 {
880     m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
881     m_hostImpl->setBackgroundColor(Color::gray);
882
883     IntSize viewportSize(1000, 1000);
884     m_hostImpl->setViewportSize(viewportSize);
885
886     m_hostImpl->setRootLayer(BlendStateCheckLayer::create(0));
887     BlendStateCheckLayer* root = static_cast<BlendStateCheckLayer*>(m_hostImpl->rootLayer());
888     root->setExpectation(false, true);
889     root->setOpaque(true);
890
891     // No gutter rects
892     {
893         IntRect layerRect(0, 0, 1000, 1000);
894         root->setPosition(layerRect.location());
895         root->setBounds(layerRect.size());
896         root->setContentBounds(layerRect.size());
897         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
898         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
899
900         CCLayerTreeHostImpl::FrameData frame;
901         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
902         ASSERT_EQ(1u, frame.renderPasses.size());
903
904         size_t numGutterQuads = 0;
905         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
906             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
907         EXPECT_EQ(0u, numGutterQuads);
908         EXPECT_EQ(1u, frame.renderPasses[0]->quadList().size());
909
910         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
911         m_hostImpl->didDrawAllLayers(frame);
912     }
913
914     // Empty visible content area (fullscreen gutter rect)
915     {
916         IntRect layerRect(0, 0, 0, 0);
917         root->setPosition(layerRect.location());
918         root->setBounds(layerRect.size());
919         root->setContentBounds(layerRect.size());
920         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
921         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
922
923         CCLayerTreeHostImpl::FrameData frame;
924         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
925         ASSERT_EQ(1u, frame.renderPasses.size());
926         m_hostImpl->didDrawAllLayers(frame);
927
928         size_t numGutterQuads = 0;
929         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
930             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
931         EXPECT_EQ(1u, numGutterQuads);
932         EXPECT_EQ(1u, frame.renderPasses[0]->quadList().size());
933
934         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
935         m_hostImpl->didDrawAllLayers(frame);
936     }
937
938     // Content area in middle of clip rect (four surrounding gutter rects)
939     {
940         IntRect layerRect(500, 500, 200, 200);
941         root->setPosition(layerRect.location());
942         root->setBounds(layerRect.size());
943         root->setContentBounds(layerRect.size());
944         root->setQuadRect(IntRect(IntPoint(), layerRect.size()));
945         root->setQuadVisibleRect(IntRect(IntPoint(), layerRect.size()));
946
947         CCLayerTreeHostImpl::FrameData frame;
948         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
949         ASSERT_EQ(1u, frame.renderPasses.size());
950
951         size_t numGutterQuads = 0;
952         for (size_t i = 0; i < frame.renderPasses[0]->quadList().size(); ++i)
953             numGutterQuads += (frame.renderPasses[0]->quadList()[i]->material() == CCDrawQuad::SolidColor) ? 1 : 0;
954         EXPECT_EQ(4u, numGutterQuads);
955         EXPECT_EQ(5u, frame.renderPasses[0]->quadList().size());
956
957         verifyQuadsExactlyCoverRect(frame.renderPasses[0]->quadList(), IntRect(-layerRect.location(), viewportSize));
958         m_hostImpl->didDrawAllLayers(frame);
959     }
960
961 }
962
963
964 class ReshapeTrackerContext: public FakeWebGraphicsContext3D {
965 public:
966     ReshapeTrackerContext() : m_reshapeCalled(false) { }
967
968     virtual void reshape(int width, int height)
969     {
970         m_reshapeCalled = true;
971     }
972
973     bool reshapeCalled() const { return m_reshapeCalled; }
974
975 private:
976     bool m_reshapeCalled;
977 };
978
979 class FakeDrawableCCLayerImpl: public CCLayerImpl {
980 public:
981     explicit FakeDrawableCCLayerImpl(int id) : CCLayerImpl(id) { }
982 };
983
984 // Only reshape when we know we are going to draw. Otherwise, the reshape
985 // can leave the window at the wrong size if we never draw and the proper
986 // viewport size is never set.
987 TEST_F(CCLayerTreeHostImplTest, reshapeNotCalledUntilDraw)
988 {
989     ReshapeTrackerContext* reshapeTracker = new ReshapeTrackerContext();
990     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(reshapeTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
991     RefPtr<CCGraphicsContext> ccContext = CCGraphicsContext::create3D(context);
992     m_hostImpl->initializeLayerRenderer(ccContext, UnthrottledUploader);
993
994     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
995     root->setAnchorPoint(FloatPoint(0, 0));
996     root->setBounds(IntSize(10, 10));
997     root->setDrawsContent(true);
998     m_hostImpl->setRootLayer(adoptPtr(root));
999     EXPECT_FALSE(reshapeTracker->reshapeCalled());
1000
1001     CCLayerTreeHostImpl::FrameData frame;
1002     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1003     m_hostImpl->drawLayers(frame);
1004     EXPECT_TRUE(reshapeTracker->reshapeCalled());
1005     m_hostImpl->didDrawAllLayers(frame);
1006 }
1007
1008 class PartialSwapTrackerContext : public FakeWebGraphicsContext3D {
1009 public:
1010     virtual void postSubBufferCHROMIUM(int x, int y, int width, int height)
1011     {
1012         m_partialSwapRect = IntRect(x, y, width, height);
1013     }
1014
1015     virtual WebString getString(WGC3Denum name)
1016     {
1017         if (name == GraphicsContext3D::EXTENSIONS)
1018             return WebString("GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
1019
1020         return WebString();
1021     }
1022
1023     IntRect partialSwapRect() const { return m_partialSwapRect; }
1024
1025 private:
1026     IntRect m_partialSwapRect;
1027 };
1028
1029 // Make sure damage tracking propagates all the way to the graphics context,
1030 // where it should request to swap only the subBuffer that is damaged.
1031 TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
1032 {
1033     PartialSwapTrackerContext* partialSwapTracker = new PartialSwapTrackerContext();
1034     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
1035     RefPtr<CCGraphicsContext> ccContext = CCGraphicsContext::create3D(context);
1036
1037     // This test creates its own CCLayerTreeHostImpl, so
1038     // that we can force partial swap enabled.
1039     CCSettings settings;
1040     settings.partialSwapEnabled = true;
1041     OwnPtr<CCLayerTreeHostImpl> layerTreeHostImpl = CCLayerTreeHostImpl::create(settings, this);
1042     layerTreeHostImpl->initializeLayerRenderer(ccContext, UnthrottledUploader);
1043     layerTreeHostImpl->setViewportSize(IntSize(500, 500));
1044
1045     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
1046     CCLayerImpl* child = new FakeDrawableCCLayerImpl(2);
1047     child->setPosition(FloatPoint(12, 13));
1048     child->setAnchorPoint(FloatPoint(0, 0));
1049     child->setBounds(IntSize(14, 15));
1050     child->setDrawsContent(true);
1051     root->setAnchorPoint(FloatPoint(0, 0));
1052     root->setBounds(IntSize(500, 500));
1053     root->setDrawsContent(true);
1054     root->addChild(adoptPtr(child));
1055     layerTreeHostImpl->setRootLayer(adoptPtr(root));
1056
1057     CCLayerTreeHostImpl::FrameData frame;
1058
1059     // First frame, the entire screen should get swapped.
1060     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1061     layerTreeHostImpl->drawLayers(frame);
1062     layerTreeHostImpl->didDrawAllLayers(frame);
1063     layerTreeHostImpl->swapBuffers();
1064     IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
1065     IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
1066     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1067     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1068     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1069     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1070
1071     // Second frame, only the damaged area should get swapped. Damage should be the union
1072     // of old and new child rects.
1073     // expected damage rect: IntRect(IntPoint::zero(), IntSize(26, 28));
1074     // expected swap rect: vertically flipped, with origin at bottom left corner.
1075     child->setPosition(FloatPoint(0, 0));
1076     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1077     layerTreeHostImpl->drawLayers(frame);
1078     m_hostImpl->didDrawAllLayers(frame);
1079     layerTreeHostImpl->swapBuffers();
1080     actualSwapRect = partialSwapTracker->partialSwapRect();
1081     expectedSwapRect = IntRect(IntPoint(0, 500-28), IntSize(26, 28));
1082     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1083     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1084     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1085     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1086
1087     // Make sure that partial swap is constrained to the viewport dimensions
1088     // expected damage rect: IntRect(IntPoint::zero(), IntSize(500, 500));
1089     // expected swap rect: flipped damage rect, but also clamped to viewport
1090     layerTreeHostImpl->setViewportSize(IntSize(10, 10));
1091     root->setOpacity(0.7f); // this will damage everything
1092     EXPECT_TRUE(layerTreeHostImpl->prepareToDraw(frame));
1093     layerTreeHostImpl->drawLayers(frame);
1094     m_hostImpl->didDrawAllLayers(frame);
1095     layerTreeHostImpl->swapBuffers();
1096     actualSwapRect = partialSwapTracker->partialSwapRect();
1097     expectedSwapRect = IntRect(IntPoint::zero(), IntSize(10, 10));
1098     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
1099     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
1100     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
1101     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
1102 }
1103
1104 // Make sure that context lost notifications are propagated through the tree.
1105 class ContextLostNotificationCheckLayer : public CCLayerImpl {
1106 public:
1107     static PassOwnPtr<ContextLostNotificationCheckLayer> create(int id) { return adoptPtr(new ContextLostNotificationCheckLayer(id)); }
1108
1109     virtual void didLoseContext() OVERRIDE
1110     {
1111         m_didLoseContextCalled = true;
1112     }
1113
1114     bool didLoseContextCalled() const { return m_didLoseContextCalled; }
1115
1116 private:
1117     explicit ContextLostNotificationCheckLayer(int id)
1118         : CCLayerImpl(id)
1119         , m_didLoseContextCalled(false)
1120     {
1121     }
1122
1123     bool m_didLoseContextCalled;
1124 };
1125
1126 TEST_F(CCLayerTreeHostImplTest, contextLostAndRestoredNotificationSentToAllLayers)
1127 {
1128     m_hostImpl->setRootLayer(ContextLostNotificationCheckLayer::create(0));
1129     ContextLostNotificationCheckLayer* root = static_cast<ContextLostNotificationCheckLayer*>(m_hostImpl->rootLayer());
1130
1131     root->addChild(ContextLostNotificationCheckLayer::create(1));
1132     ContextLostNotificationCheckLayer* layer1 = static_cast<ContextLostNotificationCheckLayer*>(root->children()[0].get());
1133
1134     layer1->addChild(ContextLostNotificationCheckLayer::create(2));
1135     ContextLostNotificationCheckLayer* layer2 = static_cast<ContextLostNotificationCheckLayer*>(layer1->children()[0].get());
1136
1137     EXPECT_FALSE(root->didLoseContextCalled());
1138     EXPECT_FALSE(layer1->didLoseContextCalled());
1139     EXPECT_FALSE(layer2->didLoseContextCalled());
1140
1141     m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
1142
1143     EXPECT_TRUE(root->didLoseContextCalled());
1144     EXPECT_TRUE(layer1->didLoseContextCalled());
1145     EXPECT_TRUE(layer2->didLoseContextCalled());
1146 }
1147
1148 class FakeWebGraphicsContext3DMakeCurrentFails : public FakeWebGraphicsContext3D {
1149 public:
1150     virtual bool makeContextCurrent() { return false; }
1151 };
1152
1153 TEST_F(CCLayerTreeHostImplTest, finishAllRenderingAfterContextLost)
1154 {
1155     // The context initialization will fail, but we should still be able to call finishAllRendering() without any ill effects.
1156     m_hostImpl->initializeLayerRenderer(CCGraphicsContext::create3D(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3DMakeCurrentFails), GraphicsContext3D::RenderDirectlyToHostWindow)), UnthrottledUploader);
1157     m_hostImpl->finishAllRendering();
1158 }
1159
1160 class ScrollbarLayerFakePaint : public CCScrollbarLayerImpl {
1161 public:
1162     static PassOwnPtr<ScrollbarLayerFakePaint> create(int id) { return adoptPtr(new ScrollbarLayerFakePaint(id)); }
1163
1164     virtual void paint(GraphicsContext*) { }
1165
1166 private:
1167     ScrollbarLayerFakePaint(int id) : CCScrollbarLayerImpl(id) { }
1168 };
1169
1170 TEST_F(CCLayerTreeHostImplTest, scrollbarLayerLostContext)
1171 {
1172     m_hostImpl->setRootLayer(ScrollbarLayerFakePaint::create(0));
1173     ScrollbarLayerFakePaint* scrollbar = static_cast<ScrollbarLayerFakePaint*>(m_hostImpl->rootLayer());
1174     scrollbar->setBounds(IntSize(1, 1));
1175     scrollbar->setContentBounds(IntSize(1, 1));
1176     scrollbar->setDrawsContent(true);
1177
1178     for (int i = 0; i < 2; ++i) {
1179         CCLayerTreeHostImpl::FrameData frame;
1180         EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1181         ASSERT(frame.renderPasses.size() == 1);
1182         CCRenderPass* renderPass = frame.renderPasses[0].get();
1183         // Scrollbar layer should always generate quads, even after lost context
1184         EXPECT_GT(renderPass->quadList().size(), 0u);
1185         m_hostImpl->didDrawAllLayers(frame);
1186         m_hostImpl->initializeLayerRenderer(createContext(), UnthrottledUploader);
1187     }
1188 }
1189
1190 // Fake WebGraphicsContext3D that will cause a failure if trying to use a
1191 // resource that wasn't created by it (resources created by
1192 // FakeWebGraphicsContext3D have an id of 1).
1193 class StrictWebGraphicsContext3D : public FakeWebGraphicsContext3D {
1194 public:
1195     virtual WebGLId createBuffer() { return 2; }
1196     virtual WebGLId createFramebuffer() { return 3; }
1197     virtual WebGLId createProgram() { return 4; }
1198     virtual WebGLId createRenderbuffer() { return 5; }
1199     virtual WebGLId createShader(WGC3Denum) { return 6; }
1200     virtual WebGLId createTexture() { return 7; }
1201
1202     virtual void deleteBuffer(WebGLId id)
1203     {
1204         if (id != 2)
1205             ADD_FAILURE() << "Trying to delete buffer id " << id;
1206     }
1207
1208     virtual void deleteFramebuffer(WebGLId id)
1209     {
1210         if (id != 3)
1211             ADD_FAILURE() << "Trying to delete framebuffer id " << id;
1212     }
1213
1214     virtual void deleteProgram(WebGLId id)
1215     {
1216         if (id != 4)
1217             ADD_FAILURE() << "Trying to delete program id " << id;
1218     }
1219
1220     virtual void deleteRenderbuffer(WebGLId id)
1221     {
1222         if (id != 5)
1223             ADD_FAILURE() << "Trying to delete renderbuffer id " << id;
1224     }
1225
1226     virtual void deleteShader(WebGLId id)
1227     {
1228         if (id != 6)
1229             ADD_FAILURE() << "Trying to delete shader id " << id;
1230     }
1231
1232     virtual void deleteTexture(WebGLId id)
1233     {
1234         if (id != 7)
1235             ADD_FAILURE() << "Trying to delete texture id " << id;
1236     }
1237
1238     virtual void bindBuffer(WGC3Denum, WebGLId id)
1239     {
1240         if (id != 2 && id)
1241             ADD_FAILURE() << "Trying to bind buffer id " << id;
1242     }
1243
1244     virtual void bindFramebuffer(WGC3Denum, WebGLId id)
1245     {
1246         if (id != 3 && id)
1247             ADD_FAILURE() << "Trying to bind framebuffer id " << id;
1248     }
1249
1250     virtual void useProgram(WebGLId id)
1251     {
1252         if (id != 4)
1253             ADD_FAILURE() << "Trying to use program id " << id;
1254     }
1255
1256     virtual void bindRenderbuffer(WGC3Denum, WebGLId id)
1257     {
1258         if (id != 5 && id)
1259             ADD_FAILURE() << "Trying to bind renderbuffer id " << id;
1260     }
1261
1262     virtual void attachShader(WebGLId program, WebGLId shader)
1263     {
1264         if ((program != 4) || (shader != 6))
1265             ADD_FAILURE() << "Trying to attach shader id " << shader << " to program id " << program;
1266     }
1267
1268     virtual void bindTexture(WGC3Denum, WebGLId id)
1269     {
1270         if (id != 7 && id)
1271             ADD_FAILURE() << "Trying to bind texture id " << id;
1272     }
1273
1274     static PassRefPtr<GraphicsContext3D> createGraphicsContext()
1275     {
1276         return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new StrictWebGraphicsContext3D()), GraphicsContext3D::RenderDirectlyToHostWindow);
1277     }
1278 };
1279
1280 // Fake video frame that represents a 4x4 YUV video frame.
1281 class FakeVideoFrame: public WebVideoFrame {
1282 public:
1283     FakeVideoFrame() { memset(m_data, 0x80, sizeof(m_data)); }
1284     virtual ~FakeVideoFrame() { }
1285     virtual Format format() const { return FormatYV12; }
1286     virtual unsigned width() const { return 4; }
1287     virtual unsigned height() const { return 4; }
1288     virtual unsigned planes() const { return 3; }
1289     virtual int stride(unsigned plane) const { return 4; }
1290     virtual const void* data(unsigned plane) const { return m_data; }
1291     virtual unsigned textureId() const { return 0; }
1292     virtual unsigned textureTarget() const { return 0; }
1293
1294 private:
1295     char m_data[16];
1296 };
1297
1298 // Fake video frame provider that always provides the same FakeVideoFrame.
1299 class FakeVideoFrameProvider: public WebVideoFrameProvider {
1300 public:
1301     FakeVideoFrameProvider() : m_client(0) { }
1302     virtual ~FakeVideoFrameProvider()
1303     {
1304         if (m_client)
1305             m_client->stopUsingProvider();
1306     }
1307
1308     virtual void setVideoFrameProviderClient(Client* client) { m_client = client; }
1309     virtual WebVideoFrame* getCurrentFrame() { return &m_frame; }
1310     virtual void putCurrentFrame(WebVideoFrame*) { }
1311
1312 private:
1313     FakeVideoFrame m_frame;
1314     Client* m_client;
1315 };
1316
1317 TEST_F(CCLayerTreeHostImplTest, dontUseOldResourcesAfterLostContext)
1318 {
1319     OwnPtr<CCLayerImpl> rootLayer(CCLayerImpl::create(0));
1320     rootLayer->setBounds(IntSize(10, 10));
1321     rootLayer->setAnchorPoint(FloatPoint(0, 0));
1322
1323     OwnPtr<CCTiledLayerImpl> tileLayer = CCTiledLayerImpl::create(1);
1324     tileLayer->setBounds(IntSize(10, 10));
1325     tileLayer->setAnchorPoint(FloatPoint(0, 0));
1326     tileLayer->setContentBounds(IntSize(10, 10));
1327     tileLayer->setDrawsContent(true);
1328     tileLayer->setSkipsDraw(false);
1329     OwnPtr<CCLayerTilingData> tilingData(CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::NoBorderTexels));
1330     tilingData->setBounds(IntSize(10, 10));
1331     tileLayer->setTilingData(*tilingData);
1332     tileLayer->pushTileProperties(0, 0, 1, IntRect(0, 0, 10, 10));
1333     rootLayer->addChild(tileLayer.release());
1334
1335     OwnPtr<CCTextureLayerImpl> textureLayer = CCTextureLayerImpl::create(2);
1336     textureLayer->setBounds(IntSize(10, 10));
1337     textureLayer->setAnchorPoint(FloatPoint(0, 0));
1338     textureLayer->setContentBounds(IntSize(10, 10));
1339     textureLayer->setDrawsContent(true);
1340     textureLayer->setTextureId(1);
1341     rootLayer->addChild(textureLayer.release());
1342
1343     FakeVideoFrameProvider provider;
1344     OwnPtr<CCVideoLayerImpl> videoLayer = CCVideoLayerImpl::create(3, &provider);
1345     videoLayer->setBounds(IntSize(10, 10));
1346     videoLayer->setAnchorPoint(FloatPoint(0, 0));
1347     videoLayer->setContentBounds(IntSize(10, 10));
1348     videoLayer->setDrawsContent(true);
1349     rootLayer->addChild(videoLayer.release());
1350
1351     m_hostImpl->setRootLayer(rootLayer.release());
1352
1353     CCLayerTreeHostImpl::FrameData frame;
1354     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1355     m_hostImpl->drawLayers(frame);
1356     m_hostImpl->didDrawAllLayers(frame);
1357     m_hostImpl->swapBuffers();
1358
1359     // Lose the context, replacing it with a StrictWebGraphicsContext3D, that
1360     // will warn if any resource from the previous context gets used.
1361     m_hostImpl->initializeLayerRenderer(CCGraphicsContext::create3D(StrictWebGraphicsContext3D::createGraphicsContext()), UnthrottledUploader);
1362     EXPECT_TRUE(m_hostImpl->prepareToDraw(frame));
1363     m_hostImpl->drawLayers(frame);
1364     m_hostImpl->didDrawAllLayers(frame);
1365     m_hostImpl->swapBuffers();
1366 }
1367
1368 } // namespace