a192ba557bf0ea16c21e4c04242cb25d090a1763
[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 "FakeWebGraphicsContext3D.h"
30 #include "GraphicsContext3DPrivate.h"
31 #include "LayerRendererChromium.h"
32 #include "cc/CCLayerImpl.h"
33 #include "cc/CCSingleThreadProxy.h"
34 #include "cc/CCTileDrawQuad.h"
35 #include <gtest/gtest.h>
36
37 using namespace WebCore;
38 using namespace WebKit;
39
40 namespace {
41
42 class CCLayerTreeHostImplTest : public testing::Test, public CCLayerTreeHostImplClient {
43 public:
44     CCLayerTreeHostImplTest()
45         : m_didRequestCommit(false)
46         , m_didRequestRedraw(false)
47     {
48         CCSettings settings;
49         m_hostImpl = CCLayerTreeHostImpl::create(settings, this);
50     }
51
52     virtual void didLoseContextOnImplThread() { }
53     virtual void onSwapBuffersCompleteOnImplThread() { }
54     virtual void setNeedsRedrawOnImplThread() { m_didRequestRedraw = true; }
55     virtual void setNeedsCommitOnImplThread() { m_didRequestCommit = true; }
56     virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) { }
57
58     static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer)
59     {
60         ASSERT_EQ(layer->scrollDelta(), IntSize());
61         for (size_t i = 0; i < layer->children().size(); ++i)
62             expectClearedScrollDeltasRecursive(layer->children()[i].get());
63     }
64
65     static void expectContains(const CCScrollAndScaleSet& scrollInfo, int id, const IntSize& scrollDelta)
66     {
67         int timesEncountered = 0;
68
69         for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) {
70             if (scrollInfo.scrolls[i].layerId != id)
71                 continue;
72             EXPECT_EQ(scrollDelta.width(), scrollInfo.scrolls[i].scrollDelta.width());
73             EXPECT_EQ(scrollDelta.height(), scrollInfo.scrolls[i].scrollDelta.height());
74             timesEncountered++;
75         }
76
77         ASSERT_EQ(timesEncountered, 1);
78     }
79
80     void setupScrollAndContentsLayers(const IntSize& contentSize)
81     {
82         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
83         root->setScrollable(true);
84         root->setScrollPosition(IntPoint(0, 0));
85         root->setMaxScrollPosition(contentSize);
86         OwnPtr<CCLayerImpl> contents = CCLayerImpl::create(1);
87         contents->setDrawsContent(true);
88         contents->setBounds(contentSize);
89         contents->setContentBounds(contentSize);
90         root->addChild(contents.release());
91         m_hostImpl->setRootLayer(root.release());
92     }
93
94 protected:
95     PassRefPtr<GraphicsContext3D> createContext()
96     {
97         return GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3D()), GraphicsContext3D::RenderDirectlyToHostWindow);
98     }
99
100     DebugScopedSetImplThread m_alwaysImplThread;
101     OwnPtr<CCLayerTreeHostImpl> m_hostImpl;
102     bool m_didRequestCommit;
103     bool m_didRequestRedraw;
104 };
105
106 TEST_F(CCLayerTreeHostImplTest, scrollDeltaNoLayers)
107 {
108     ASSERT_FALSE(m_hostImpl->rootLayer());
109
110     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
111     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
112 }
113
114 TEST_F(CCLayerTreeHostImplTest, scrollDeltaTreeButNoChanges)
115 {
116     {
117         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
118         root->addChild(CCLayerImpl::create(1));
119         root->addChild(CCLayerImpl::create(2));
120         root->children()[1]->addChild(CCLayerImpl::create(3));
121         root->children()[1]->addChild(CCLayerImpl::create(4));
122         root->children()[1]->children()[0]->addChild(CCLayerImpl::create(5));
123         m_hostImpl->setRootLayer(root.release());
124     }
125     CCLayerImpl* root = m_hostImpl->rootLayer();
126
127     expectClearedScrollDeltasRecursive(root);
128
129     OwnPtr<CCScrollAndScaleSet> scrollInfo;
130
131     scrollInfo = m_hostImpl->processScrollDeltas();
132     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
133     expectClearedScrollDeltasRecursive(root);
134
135     scrollInfo = m_hostImpl->processScrollDeltas();
136     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
137     expectClearedScrollDeltasRecursive(root);
138 }
139
140 TEST_F(CCLayerTreeHostImplTest, scrollDeltaRepeatedScrolls)
141 {
142     IntPoint scrollPosition(20, 30);
143     IntSize scrollDelta(11, -15);
144     {
145         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(10);
146         root->setScrollPosition(scrollPosition);
147         root->setScrollable(true);
148         root->setMaxScrollPosition(IntSize(100, 100));
149         root->scrollBy(scrollDelta);
150         m_hostImpl->setRootLayer(root.release());
151     }
152     CCLayerImpl* root = m_hostImpl->rootLayer();
153
154     OwnPtr<CCScrollAndScaleSet> scrollInfo;
155
156     scrollInfo = m_hostImpl->processScrollDeltas();
157     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
158     EXPECT_EQ(root->sentScrollDelta(), scrollDelta);
159     expectContains(*scrollInfo, root->id(), scrollDelta);
160
161     IntSize scrollDelta2(-5, 27);
162     root->scrollBy(scrollDelta2);
163     scrollInfo = m_hostImpl->processScrollDeltas();
164     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
165     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
166     expectContains(*scrollInfo, root->id(), scrollDelta + scrollDelta2);
167
168     root->scrollBy(IntSize());
169     scrollInfo = m_hostImpl->processScrollDeltas();
170     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
171 }
172
173 TEST_F(CCLayerTreeHostImplTest, scrollRootCallsCommitAndRedraw)
174 {
175     {
176         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
177         root->setScrollable(true);
178         root->setScrollPosition(IntPoint(0, 0));
179         root->setMaxScrollPosition(IntSize(100, 100));
180         m_hostImpl->setRootLayer(root.release());
181     }
182
183     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
184     m_hostImpl->scrollBy(IntSize(0, 10));
185     m_hostImpl->scrollEnd();
186     EXPECT_TRUE(m_didRequestRedraw);
187     EXPECT_TRUE(m_didRequestCommit);
188 }
189
190 TEST_F(CCLayerTreeHostImplTest, wheelEventHandlers)
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     CCLayerImpl* root = m_hostImpl->rootLayer();
200
201     root->setHaveWheelEventHandlers(true);
202     // With registered event handlers, wheel scrolls have to go to the main thread.
203     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
204
205     // But gesture scrolls can still be handled.
206     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
207 }
208
209 TEST_F(CCLayerTreeHostImplTest, shouldScrollOnMainThread)
210 {
211     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
212     root->setScrollable(true);
213     root->setScrollPosition(IntPoint(0, 0));
214     root->setMaxScrollPosition(IntSize(100, 100));
215     root->setShouldScrollOnMainThread(true);
216     m_hostImpl->setRootLayer(root.release());
217     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
218     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollFailed);
219 }
220
221 TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionBasic)
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     root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
228     m_hostImpl->setRootLayer(root.release());
229     // All scroll types inside the non-fast scrollable region should fail.
230     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
231     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(25, 25), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollFailed);
232
233     // All scroll types outside this region should succeed.
234     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
235     m_hostImpl->scrollBy(IntSize(0, 10));
236     m_hostImpl->scrollEnd();
237     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(75, 75), CCInputHandlerClient::Gesture), CCInputHandlerClient::ScrollStarted);
238     m_hostImpl->scrollBy(IntSize(0, 10));
239     m_hostImpl->scrollEnd();
240 }
241
242 TEST_F(CCLayerTreeHostImplTest, nonFastScrollableRegionWithOffset)
243 {
244     m_hostImpl->initializeLayerRenderer(createContext());
245
246     OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
247     root->setScrollable(true);
248     root->setScrollPosition(IntPoint(0, 0));
249     root->setMaxScrollPosition(IntSize(100, 100));
250     root->setNonFastScrollableRegion(IntRect(0, 0, 50, 50));
251     root->setPosition(FloatPoint(-25, 0));
252     m_hostImpl->setRootLayer(root.release());
253     m_hostImpl->drawLayers(); // Update draw transforms so we can correctly map points into layer space.
254
255     // This point would fall into the non-fast scrollable region except that we've moved the layer down by 25 pixels.
256     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(40, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollStarted);
257     m_hostImpl->scrollBy(IntSize(0, 1));
258     m_hostImpl->scrollEnd();
259
260     // This point is still inside the non-fast region.
261     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(10, 10), CCInputHandlerClient::Wheel), CCInputHandlerClient::ScrollFailed);
262 }
263
264 TEST_F(CCLayerTreeHostImplTest, pinchGesture)
265 {
266     setupScrollAndContentsLayers(IntSize(100, 100));
267     m_hostImpl->setViewportSize(IntSize(50, 50));
268
269     CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
270     ASSERT(scrollLayer);
271
272     const float minPageScale = 0.5, maxPageScale = 4;
273
274     // Basic pinch zoom in gesture
275     {
276         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
277         scrollLayer->setPageScaleDelta(1);
278         scrollLayer->setScrollDelta(IntSize());
279
280         float pageScaleDelta = 2;
281         m_hostImpl->pinchGestureBegin();
282         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
283         m_hostImpl->pinchGestureEnd();
284         EXPECT_TRUE(m_didRequestRedraw);
285         EXPECT_TRUE(m_didRequestCommit);
286
287         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
288         EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
289     }
290
291     // Zoom-in clamping
292     {
293         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
294         scrollLayer->setPageScaleDelta(1);
295         scrollLayer->setScrollDelta(IntSize());
296         float pageScaleDelta = 10;
297
298         m_hostImpl->pinchGestureBegin();
299         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(50, 50));
300         m_hostImpl->pinchGestureEnd();
301
302         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
303         EXPECT_EQ(scrollInfo->pageScaleDelta, maxPageScale);
304     }
305
306     // Zoom-out clamping
307     {
308         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
309         scrollLayer->setPageScaleDelta(1);
310         scrollLayer->setScrollDelta(IntSize());
311         scrollLayer->setScrollPosition(IntPoint(50, 50));
312
313         float pageScaleDelta = 0.1;
314         m_hostImpl->pinchGestureBegin();
315         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(0, 0));
316         m_hostImpl->pinchGestureEnd();
317
318         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
319         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
320
321         // Pushed to (0,0) via clamping against contents layer size.
322         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
323     }
324
325     // Two-finger panning
326     {
327         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
328         scrollLayer->setPageScaleDelta(1);
329         scrollLayer->setScrollDelta(IntSize());
330         scrollLayer->setScrollPosition(IntPoint(20, 20));
331
332         float pageScaleDelta = 1;
333         m_hostImpl->pinchGestureBegin();
334         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(10, 10));
335         m_hostImpl->pinchGestureUpdate(pageScaleDelta, IntPoint(20, 20));
336         m_hostImpl->pinchGestureEnd();
337
338         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
339         EXPECT_EQ(scrollInfo->pageScaleDelta, pageScaleDelta);
340         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-10, -10));
341     }
342 }
343
344 TEST_F(CCLayerTreeHostImplTest, pageScaleAnimation)
345 {
346     setupScrollAndContentsLayers(IntSize(100, 100));
347     m_hostImpl->setViewportSize(IntSize(50, 50));
348
349     CCLayerImpl* scrollLayer = m_hostImpl->scrollLayer();
350     ASSERT(scrollLayer);
351
352     const float minPageScale = 0.5, maxPageScale = 4;
353     const double startTime = 1;
354     const double duration = 0.1;
355     const double halfwayThroughAnimation = startTime + duration / 2;
356     const double endTime = startTime + duration;
357
358     // Non-anchor zoom-in
359     {
360         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
361         scrollLayer->setPageScaleDelta(1);
362         scrollLayer->setScrollPosition(IntPoint(50, 50));
363
364         m_hostImpl->startPageScaleAnimation(IntSize(0, 0), false, 2, startTime, duration);
365         m_hostImpl->animate(halfwayThroughAnimation, halfwayThroughAnimation);
366         EXPECT_TRUE(m_didRequestRedraw);
367         m_hostImpl->animate(endTime, endTime);
368         EXPECT_TRUE(m_didRequestCommit);
369
370         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
371         EXPECT_EQ(scrollInfo->pageScaleDelta, 2);
372         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
373     }
374
375     // Anchor zoom-out
376     {
377         m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale);
378         scrollLayer->setPageScaleDelta(1);
379         scrollLayer->setScrollPosition(IntPoint(50, 50));
380
381         m_hostImpl->startPageScaleAnimation(IntSize(25, 25), true, minPageScale, startTime, duration);
382         m_hostImpl->animate(endTime, endTime);
383         EXPECT_TRUE(m_didRequestRedraw);
384         EXPECT_TRUE(m_didRequestCommit);
385
386         OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
387         EXPECT_EQ(scrollInfo->pageScaleDelta, minPageScale);
388         // Pushed to (0,0) via clamping against contents layer size.
389         expectContains(*scrollInfo, scrollLayer->id(), IntSize(-50, -50));
390     }
391 }
392
393 class DidDrawCheckLayer : public CCLayerImpl {
394 public:
395     static PassOwnPtr<DidDrawCheckLayer> create(int id) { return adoptPtr(new DidDrawCheckLayer(id)); }
396
397     virtual void didDraw()
398     {
399         m_didDrawCalled = true;
400     }
401
402     virtual void willDraw(LayerRendererChromium*)
403     {
404         m_willDrawCalled = true;
405     }
406
407     bool didDrawCalled() const { return m_didDrawCalled; }
408     bool willDrawCalled() const { return m_willDrawCalled; }
409
410 private:
411     explicit DidDrawCheckLayer(int id)
412         : CCLayerImpl(id)
413         , m_didDrawCalled(false)
414         , m_willDrawCalled(false)
415     {
416         setAnchorPoint(FloatPoint(0, 0));
417         setBounds(IntSize(10, 10));
418         setDrawsContent(true);
419     }
420
421     bool m_didDrawCalled;
422     bool m_willDrawCalled;
423 };
424
425 TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnHiddenLayer)
426 {
427     m_hostImpl->initializeLayerRenderer(createContext());
428
429     // Ensure visibleLayerRect for root layer is empty
430     m_hostImpl->setViewportSize(IntSize(0, 0));
431
432     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
433     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
434
435     EXPECT_FALSE(root->willDrawCalled());
436     EXPECT_FALSE(root->didDrawCalled());
437
438     m_hostImpl->drawLayers();
439
440     EXPECT_FALSE(root->willDrawCalled());
441     EXPECT_FALSE(root->didDrawCalled());
442
443     EXPECT_TRUE(root->visibleLayerRect().isEmpty());
444
445     // Ensure visibleLayerRect for root layer is not empty
446     m_hostImpl->setViewportSize(IntSize(10, 10));
447
448     EXPECT_FALSE(root->willDrawCalled());
449     EXPECT_FALSE(root->didDrawCalled());
450
451     m_hostImpl->drawLayers();
452
453     EXPECT_TRUE(root->willDrawCalled());
454     EXPECT_TRUE(root->didDrawCalled());
455
456     EXPECT_FALSE(root->visibleLayerRect().isEmpty());
457 }
458
459 TEST_F(CCLayerTreeHostImplTest, didDrawCalledOnAllLayers)
460 {
461     m_hostImpl->initializeLayerRenderer(createContext());
462     m_hostImpl->setViewportSize(IntSize(10, 10));
463
464     m_hostImpl->setRootLayer(DidDrawCheckLayer::create(0));
465     DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(m_hostImpl->rootLayer());
466
467     root->addChild(DidDrawCheckLayer::create(1));
468     DidDrawCheckLayer* layer1 = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
469
470     layer1->addChild(DidDrawCheckLayer::create(2));
471     DidDrawCheckLayer* layer2 = static_cast<DidDrawCheckLayer*>(layer1->children()[0].get());
472
473     layer1->setOpacity(0.3);
474     layer1->setPreserves3D(false);
475
476     EXPECT_FALSE(root->didDrawCalled());
477     EXPECT_FALSE(layer1->didDrawCalled());
478     EXPECT_FALSE(layer2->didDrawCalled());
479
480     m_hostImpl->drawLayers();
481
482     EXPECT_TRUE(root->didDrawCalled());
483     EXPECT_TRUE(layer1->didDrawCalled());
484     EXPECT_TRUE(layer2->didDrawCalled());
485
486     EXPECT_NE(root->renderSurface(), layer1->renderSurface());
487     EXPECT_TRUE(!!layer1->renderSurface());
488 }
489
490 class BlendStateTrackerContext: public FakeWebGraphicsContext3D {
491 public:
492     BlendStateTrackerContext() : m_blend(false) { }
493
494     virtual void enable(WGC3Denum cap)
495     {
496         if (cap == GraphicsContext3D::BLEND)
497             m_blend = true;
498     }
499
500     virtual void disable(WGC3Denum cap)
501     {
502         if (cap == GraphicsContext3D::BLEND)
503             m_blend = false;
504     }
505
506     bool blend() const { return m_blend; }
507
508 private:
509     bool m_blend;
510 };
511
512 class BlendStateCheckLayer : public CCLayerImpl {
513 public:
514     static PassOwnPtr<BlendStateCheckLayer> create(int id) { return adoptPtr(new BlendStateCheckLayer(id)); }
515
516     virtual void appendQuads(CCQuadCuller& quadList, const CCSharedQuadState* sharedQuadState)
517     {
518         m_quadsAppended = true;
519
520         IntRect opaqueRect;
521         if (opaque() || m_opaqueContents)
522             opaqueRect = m_quadRect;
523         else
524             opaqueRect = m_opaqueContentRect;
525         OwnPtr<CCDrawQuad> testBlendingDrawQuad = CCTileDrawQuad::create(sharedQuadState, m_quadRect, opaqueRect, 0, IntPoint(), IntSize(1, 1), 0, false, false, false, false, false);
526         testBlendingDrawQuad->setQuadVisibleRect(m_quadVisibleRect);
527         EXPECT_EQ(m_blend, testBlendingDrawQuad->needsBlending());
528         EXPECT_EQ(m_hasRenderSurface, !!renderSurface());
529     }
530
531     void setExpectation(bool blend, bool hasRenderSurface)
532     {
533         m_blend = blend;
534         m_hasRenderSurface = hasRenderSurface;
535         m_quadsAppended = false;
536     }
537
538     bool quadsAppended() const { return m_quadsAppended; }
539
540     void setQuadRect(const IntRect& rect) { m_quadRect = rect; }
541     void setQuadVisibleRect(const IntRect& rect) { m_quadVisibleRect = rect; }
542     void setOpaqueContents(bool opaque) { m_opaqueContents = opaque; }
543     void setOpaqueContentRect(const IntRect& rect) { m_opaqueContentRect = rect; }
544
545 private:
546     explicit BlendStateCheckLayer(int id)
547         : CCLayerImpl(id)
548         , m_blend(false)
549         , m_hasRenderSurface(false)
550         , m_quadsAppended(false)
551         , m_opaqueContents(false)
552         , m_quadRect(5, 5, 5, 5)
553         , m_quadVisibleRect(5, 5, 5, 5)
554     {
555         setAnchorPoint(FloatPoint(0, 0));
556         setBounds(IntSize(10, 10));
557         setDrawsContent(true);
558     }
559
560     bool m_blend;
561     bool m_hasRenderSurface;
562     bool m_quadsAppended;
563     bool m_opaqueContents;
564     IntRect m_quadRect;
565     IntRect m_opaqueContentRect;
566     IntRect m_quadVisibleRect;
567 };
568
569 // https://bugs.webkit.org/show_bug.cgi?id=75783
570 TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
571 {
572     m_hostImpl->initializeLayerRenderer(createContext());
573     m_hostImpl->setViewportSize(IntSize(10, 10));
574
575     {
576         OwnPtr<CCLayerImpl> root = CCLayerImpl::create(0);
577         root->setAnchorPoint(FloatPoint(0, 0));
578         root->setBounds(IntSize(10, 10));
579         root->setDrawsContent(false);
580         m_hostImpl->setRootLayer(root.release());
581     }
582     CCLayerImpl* root = m_hostImpl->rootLayer();
583
584     root->addChild(BlendStateCheckLayer::create(1));
585     BlendStateCheckLayer* layer1 = static_cast<BlendStateCheckLayer*>(root->children()[0].get());
586
587     // Opaque layer, drawn without blending.
588     layer1->setOpaque(true);
589     layer1->setOpaqueContents(true);
590     layer1->setExpectation(false, false);
591     m_hostImpl->drawLayers();
592     EXPECT_TRUE(layer1->quadsAppended());
593
594     // Layer with translucent content, but opaque content, so drawn without blending.
595     layer1->setOpaque(false);
596     layer1->setOpaqueContents(true);
597     layer1->setExpectation(false, false);
598     m_hostImpl->drawLayers();
599     EXPECT_TRUE(layer1->quadsAppended());
600
601     // Layer with translucent content and painting, so drawn with blending.
602     layer1->setOpaque(false);
603     layer1->setOpaqueContents(false);
604     layer1->setExpectation(true, false);
605     m_hostImpl->drawLayers();
606     EXPECT_TRUE(layer1->quadsAppended());
607
608     // Layer with translucent opacity, drawn with blending.
609     layer1->setOpaque(true);
610     layer1->setOpaqueContents(true);
611     layer1->setOpacity(0.5);
612     layer1->setExpectation(true, false);
613     m_hostImpl->drawLayers();
614     EXPECT_TRUE(layer1->quadsAppended());
615
616     // Layer with translucent opacity and painting, drawn with blending.
617     layer1->setOpaque(true);
618     layer1->setOpaqueContents(false);
619     layer1->setOpacity(0.5);
620     layer1->setExpectation(true, false);
621     m_hostImpl->drawLayers();
622     EXPECT_TRUE(layer1->quadsAppended());
623
624     layer1->addChild(BlendStateCheckLayer::create(2));
625     BlendStateCheckLayer* layer2 = static_cast<BlendStateCheckLayer*>(layer1->children()[0].get());
626
627     // 2 opaque layers, drawn without blending.
628     layer1->setOpaque(true);
629     layer1->setOpaqueContents(true);
630     layer1->setOpacity(1);
631     layer1->setExpectation(false, false);
632     layer2->setOpaque(true);
633     layer2->setOpaqueContents(true);
634     layer2->setOpacity(1);
635     layer2->setExpectation(false, false);
636     m_hostImpl->drawLayers();
637     EXPECT_TRUE(layer1->quadsAppended());
638     EXPECT_TRUE(layer2->quadsAppended());
639
640     // Parent layer with translucent content, drawn with blending.
641     // Child layer with opaque content, drawn without blending.
642     layer1->setOpaque(false);
643     layer1->setOpaqueContents(false);
644     layer1->setExpectation(true, false);
645     layer2->setExpectation(false, false);
646     m_hostImpl->drawLayers();
647     EXPECT_TRUE(layer1->quadsAppended());
648     EXPECT_TRUE(layer2->quadsAppended());
649
650     // Parent layer with translucent content but opaque painting, drawn without blending.
651     // Child layer with opaque content, drawn without blending.
652     layer1->setOpaque(false);
653     layer1->setOpaqueContents(true);
654     layer1->setExpectation(false, false);
655     layer2->setExpectation(false, false);
656     m_hostImpl->drawLayers();
657     EXPECT_TRUE(layer1->quadsAppended());
658     EXPECT_TRUE(layer2->quadsAppended());
659
660     // Parent layer with translucent opacity and opaque content. Since it has a
661     // drawing child, it's drawn to a render surface which carries the opacity,
662     // so it's itself drawn without blending.
663     // Child layer with opaque content, drawn without blending (parent surface
664     // carries the inherited opacity).
665     layer1->setOpaque(true);
666     layer1->setOpaqueContents(true);
667     layer1->setOpacity(0.5);
668     layer1->setExpectation(false, true);
669     layer2->setExpectation(false, false);
670     m_hostImpl->drawLayers();
671     EXPECT_TRUE(layer1->quadsAppended());
672     EXPECT_TRUE(layer2->quadsAppended());
673
674     // Draw again, but with child non-opaque, to make sure
675     // layer1 not culled.
676     layer1->setOpaque(true);
677     layer1->setOpaqueContents(true);
678     layer1->setOpacity(1);
679     layer1->setExpectation(false, false);
680     layer2->setOpaque(true);
681     layer2->setOpaqueContents(true);
682     layer2->setOpacity(0.5);
683     layer2->setExpectation(true, false);
684     m_hostImpl->drawLayers();
685     EXPECT_TRUE(layer1->quadsAppended());
686     EXPECT_TRUE(layer2->quadsAppended());
687
688     // A second way of making the child non-opaque.
689     layer1->setOpaque(true);
690     layer1->setOpacity(1);
691     layer1->setExpectation(false, false);
692     layer2->setOpaque(false);
693     layer2->setOpaqueContents(false);
694     layer2->setOpacity(1);
695     layer2->setExpectation(true, false);
696     m_hostImpl->drawLayers();
697     EXPECT_TRUE(layer1->quadsAppended());
698     EXPECT_TRUE(layer2->quadsAppended());
699
700     // And when the layer says its not opaque but is painted opaque, it is not blended.
701     layer1->setOpaque(true);
702     layer1->setOpacity(1);
703     layer1->setExpectation(false, false);
704     layer2->setOpaque(false);
705     layer2->setOpaqueContents(true);
706     layer2->setOpacity(1);
707     layer2->setExpectation(false, false);
708     m_hostImpl->drawLayers();
709     EXPECT_TRUE(layer1->quadsAppended());
710     EXPECT_TRUE(layer2->quadsAppended());
711
712     // Layer with partially opaque contents, drawn with blending.
713     layer1->setOpaque(false);
714     layer1->setQuadRect(IntRect(5, 5, 5, 5));
715     layer1->setQuadVisibleRect(IntRect(5, 5, 5, 5));
716     layer1->setOpaqueContents(false);
717     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
718     layer1->setExpectation(true, false);
719     m_hostImpl->drawLayers();
720     EXPECT_TRUE(layer1->quadsAppended());
721
722     // Layer with partially opaque contents partially culled, drawn with blending.
723     layer1->setOpaque(false);
724     layer1->setQuadRect(IntRect(5, 5, 5, 5));
725     layer1->setQuadVisibleRect(IntRect(5, 5, 5, 2));
726     layer1->setOpaqueContents(false);
727     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
728     layer1->setExpectation(true, false);
729     m_hostImpl->drawLayers();
730     EXPECT_TRUE(layer1->quadsAppended());
731
732     // Layer with partially opaque contents culled, drawn with blending.
733     layer1->setOpaque(false);
734     layer1->setQuadRect(IntRect(5, 5, 5, 5));
735     layer1->setQuadVisibleRect(IntRect(7, 5, 3, 5));
736     layer1->setOpaqueContents(false);
737     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
738     layer1->setExpectation(true, false);
739     m_hostImpl->drawLayers();
740     EXPECT_TRUE(layer1->quadsAppended());
741
742     // Layer with partially opaque contents and translucent contents culled, drawn without blending.
743     layer1->setOpaque(false);
744     layer1->setQuadRect(IntRect(5, 5, 5, 5));
745     layer1->setQuadVisibleRect(IntRect(5, 5, 2, 5));
746     layer1->setOpaqueContents(false);
747     layer1->setOpaqueContentRect(IntRect(5, 5, 2, 5));
748     layer1->setExpectation(false, false);
749     m_hostImpl->drawLayers();
750     EXPECT_TRUE(layer1->quadsAppended());
751
752 }
753
754 class ReshapeTrackerContext: public FakeWebGraphicsContext3D {
755 public:
756     ReshapeTrackerContext() : m_reshapeCalled(false) { }
757
758     virtual void reshape(int width, int height)
759     {
760         m_reshapeCalled = true;
761     }
762
763     bool reshapeCalled() const { return m_reshapeCalled; }
764
765 private:
766     bool m_reshapeCalled;
767 };
768
769 class FakeDrawableCCLayerImpl: public CCLayerImpl {
770 public:
771     explicit FakeDrawableCCLayerImpl(int id) : CCLayerImpl(id) { }
772 };
773
774 // Only reshape when we know we are going to draw. Otherwise, the reshape
775 // can leave the window at the wrong size if we never draw and the proper
776 // viewport size is never set.
777 TEST_F(CCLayerTreeHostImplTest, reshapeNotCalledUntilDraw)
778 {
779     ReshapeTrackerContext* reshapeTracker = new ReshapeTrackerContext();
780     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(reshapeTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
781     m_hostImpl->initializeLayerRenderer(context);
782     m_hostImpl->setViewportSize(IntSize(10, 10));
783
784     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
785     root->setAnchorPoint(FloatPoint(0, 0));
786     root->setBounds(IntSize(10, 10));
787     root->setDrawsContent(true);
788     m_hostImpl->setRootLayer(adoptPtr(root));
789     EXPECT_FALSE(reshapeTracker->reshapeCalled());
790
791     m_hostImpl->drawLayers();
792     EXPECT_TRUE(reshapeTracker->reshapeCalled());
793 }
794
795 class PartialSwapTrackerContext : public FakeWebGraphicsContext3D {
796 public:
797     virtual void postSubBufferCHROMIUM(int x, int y, int width, int height)
798     {
799         m_partialSwapRect = IntRect(x, y, width, height);
800     }
801
802     virtual WebString getString(WGC3Denum name)
803     {
804         if (name == GraphicsContext3D::EXTENSIONS)
805             return WebString("GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
806
807         return WebString();
808     }
809
810     IntRect partialSwapRect() const { return m_partialSwapRect; }
811
812 private:
813     IntRect m_partialSwapRect;
814 };
815
816 // Make sure damage tracking propagates all the way to the graphics context,
817 // where it should request to swap only the subBuffer that is damaged.
818 TEST_F(CCLayerTreeHostImplTest, partialSwapReceivesDamageRect)
819 {
820     PartialSwapTrackerContext* partialSwapTracker = new PartialSwapTrackerContext();
821     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
822
823     // This test creates its own CCLayerTreeHostImpl, so
824     // that we can force partial swap enabled.
825     CCSettings settings;
826     settings.partialSwapEnabled = true;
827     OwnPtr<CCLayerTreeHostImpl> layerTreeHostImpl = CCLayerTreeHostImpl::create(settings, this);
828     layerTreeHostImpl->initializeLayerRenderer(context);
829     layerTreeHostImpl->setViewportSize(IntSize(500, 500));
830
831     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
832     CCLayerImpl* child = new FakeDrawableCCLayerImpl(2);
833     child->setPosition(FloatPoint(12, 13));
834     child->setAnchorPoint(FloatPoint(0, 0));
835     child->setBounds(IntSize(14, 15));
836     child->setDrawsContent(true);
837     root->setAnchorPoint(FloatPoint(0, 0));
838     root->setBounds(IntSize(500, 500));
839     root->setDrawsContent(true);
840     root->addChild(adoptPtr(child));
841     layerTreeHostImpl->setRootLayer(adoptPtr(root));
842
843     // First frame, the entire screen should get swapped.
844     layerTreeHostImpl->drawLayers();
845     layerTreeHostImpl->swapBuffers();
846     IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
847     IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
848     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
849     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
850     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
851     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
852
853     // Second frame, only the damaged area should get swapped. Damage should be the union
854     // of old and new child rects.
855     // expected damage rect: IntRect(IntPoint::zero(), IntSize(26, 28));
856     // expected swap rect: vertically flipped, with origin at bottom left corner.
857     child->setPosition(FloatPoint(0, 0));
858     layerTreeHostImpl->drawLayers();
859     layerTreeHostImpl->swapBuffers();
860     actualSwapRect = partialSwapTracker->partialSwapRect();
861     expectedSwapRect = IntRect(IntPoint(0, 500-28), IntSize(26, 28));
862     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
863     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
864     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
865     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
866
867     // Make sure that partial swap is constrained to the viewport dimensions
868     // expected damage rect: IntRect(IntPoint::zero(), IntSize(500, 500));
869     // expected swap rect: flipped damage rect, but also clamped to viewport
870     layerTreeHostImpl->setViewportSize(IntSize(10, 10));
871     root->setOpacity(0.7); // this will damage everything
872     layerTreeHostImpl->drawLayers();
873     layerTreeHostImpl->swapBuffers();
874     actualSwapRect = partialSwapTracker->partialSwapRect();
875     expectedSwapRect = IntRect(IntPoint::zero(), IntSize(10, 10));
876     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
877     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
878     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
879     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
880 }
881
882 // Make sure that we reset damage tracking on visibility change because the
883 // state of the front buffer that we push to with PostSubBuffer is undefined.
884 TEST_F(CCLayerTreeHostImplTest, visibilityChangeResetsDamage)
885 {
886     PartialSwapTrackerContext* partialSwapTracker = new PartialSwapTrackerContext();
887     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(partialSwapTracker), GraphicsContext3D::RenderDirectlyToHostWindow);
888
889     // This test creates its own CCLayerTreeHostImpl, so
890     // that we can force partial swap enabled.
891     CCSettings settings;
892     settings.partialSwapEnabled = true;
893     OwnPtr<CCLayerTreeHostImpl> layerTreeHostImpl = CCLayerTreeHostImpl::create(settings, this);
894     layerTreeHostImpl->initializeLayerRenderer(context);
895     layerTreeHostImpl->setViewportSize(IntSize(500, 500));
896
897     CCLayerImpl* root = new FakeDrawableCCLayerImpl(1);
898     root->setAnchorPoint(FloatPoint(0, 0));
899     root->setBounds(IntSize(500, 500));
900     root->setDrawsContent(true);
901     layerTreeHostImpl->setRootLayer(adoptPtr(root));
902
903     // First frame: ignore.
904     layerTreeHostImpl->drawLayers();
905     layerTreeHostImpl->swapBuffers();
906
907     // Second frame: nothing has changed --- so we souldn't push anything with partial swap.
908     layerTreeHostImpl->drawLayers();
909     layerTreeHostImpl->swapBuffers();
910     EXPECT_TRUE(partialSwapTracker->partialSwapRect().isEmpty());
911
912     // Third frame: visibility change --- so we should push a full frame with partial swap.
913     layerTreeHostImpl->setVisible(false);
914     layerTreeHostImpl->setVisible(true);
915     layerTreeHostImpl->drawLayers();
916     layerTreeHostImpl->swapBuffers();
917     IntRect actualSwapRect = partialSwapTracker->partialSwapRect();
918     IntRect expectedSwapRect = IntRect(IntPoint::zero(), IntSize(500, 500));
919     EXPECT_EQ(expectedSwapRect.x(), actualSwapRect.x());
920     EXPECT_EQ(expectedSwapRect.y(), actualSwapRect.y());
921     EXPECT_EQ(expectedSwapRect.width(), actualSwapRect.width());
922     EXPECT_EQ(expectedSwapRect.height(), actualSwapRect.height());
923 }
924
925 // Make sure that context lost notifications are propagated through the tree.
926 class ContextLostNotificationCheckLayer : public CCLayerImpl {
927 public:
928     static PassOwnPtr<ContextLostNotificationCheckLayer> create(int id) { return adoptPtr(new ContextLostNotificationCheckLayer(id)); }
929
930     virtual void didLoseContext()
931     {
932         m_didLoseContextCalled = true;
933     }
934
935     bool didLoseContextCalled() const { return m_didLoseContextCalled; }
936
937 private:
938     explicit ContextLostNotificationCheckLayer(int id)
939         : CCLayerImpl(id)
940         , m_didLoseContextCalled(false)
941     {
942     }
943
944     bool m_didLoseContextCalled;
945 };
946
947 TEST_F(CCLayerTreeHostImplTest, contextLostAndRestoredNotificationSentToAllLayers)
948 {
949     m_hostImpl->initializeLayerRenderer(createContext());
950     m_hostImpl->setViewportSize(IntSize(10, 10));
951
952     m_hostImpl->setRootLayer(ContextLostNotificationCheckLayer::create(0));
953     ContextLostNotificationCheckLayer* root = static_cast<ContextLostNotificationCheckLayer*>(m_hostImpl->rootLayer());
954
955     root->addChild(ContextLostNotificationCheckLayer::create(1));
956     ContextLostNotificationCheckLayer* layer1 = static_cast<ContextLostNotificationCheckLayer*>(root->children()[0].get());
957
958     layer1->addChild(ContextLostNotificationCheckLayer::create(2));
959     ContextLostNotificationCheckLayer* layer2 = static_cast<ContextLostNotificationCheckLayer*>(layer1->children()[0].get());
960
961     EXPECT_FALSE(root->didLoseContextCalled());
962     EXPECT_FALSE(layer1->didLoseContextCalled());
963     EXPECT_FALSE(layer2->didLoseContextCalled());
964
965     m_hostImpl->initializeLayerRenderer(createContext());
966
967     EXPECT_TRUE(root->didLoseContextCalled());
968     EXPECT_TRUE(layer1->didLoseContextCalled());
969     EXPECT_TRUE(layer2->didLoseContextCalled());
970 }
971
972 class FakeWebGraphicsContext3DMakeCurrentFails : public FakeWebGraphicsContext3D {
973 public:
974     virtual bool makeContextCurrent() { return false; }
975 };
976
977 TEST_F(CCLayerTreeHostImplTest, finishAllRenderingAfterContextLost)
978 {
979     // The context initialization will fail, but we should still be able to call finishAllRendering() without any ill effects.
980     m_hostImpl->initializeLayerRenderer(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FakeWebGraphicsContext3DMakeCurrentFails), GraphicsContext3D::RenderDirectlyToHostWindow));
981     m_hostImpl->finishAllRendering();
982 }
983
984 } // namespace