[chromium] Apply sent deltas on finishCommit
[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 "GraphicsContext3DPrivate.h"
30 #include "LayerRendererChromium.h"
31 #include "MockWebGraphicsContext3D.h"
32 #include "cc/CCLayerImpl.h"
33 #include "cc/CCSingleThreadProxy.h"
34 #include <gtest/gtest.h>
35
36 using namespace WebCore;
37 using namespace WebKit;
38
39 namespace {
40
41 class CCLayerTreeHostImplTest : public testing::Test, CCLayerTreeHostImplClient {
42 public:
43     CCLayerTreeHostImplTest()
44         : m_didRequestCommit(false)
45         , m_didRequestRedraw(false)
46     {
47         CCSettings settings;
48         m_hostImpl = CCLayerTreeHostImpl::create(settings, this);
49     }
50
51     virtual void onSwapBuffersCompleteOnImplThread() { }
52     virtual void setNeedsRedrawOnImplThread() { m_didRequestRedraw = true; }
53     virtual void setNeedsCommitOnImplThread() { m_didRequestCommit = true; }
54
55     static void expectClearedScrollDeltasRecursive(CCLayerImpl* layer)
56     {
57         ASSERT_EQ(layer->scrollDelta(), IntSize());
58         for (size_t i = 0; i < layer->children().size(); ++i)
59             expectClearedScrollDeltasRecursive(layer->children()[i].get());
60     }
61
62     static void expectContains(const CCScrollAndScaleSet& scrollInfo, int id, const IntSize& scrollDelta)
63     {
64         int timesEncountered = 0;
65
66         for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) {
67             if (scrollInfo.scrolls[i].layerId != id)
68                 continue;
69             ASSERT_EQ(scrollInfo.scrolls[i].scrollDelta, scrollDelta);
70             timesEncountered++;
71         }
72
73         ASSERT_EQ(timesEncountered, 1);
74     }
75
76 protected:
77     DebugScopedSetImplThread m_alwaysImplThread;
78     OwnPtr<CCLayerTreeHostImpl> m_hostImpl;
79     bool m_didRequestCommit;
80     bool m_didRequestRedraw;
81 };
82
83 TEST_F(CCLayerTreeHostImplTest, scrollDeltaNoLayers)
84 {
85     ASSERT_FALSE(m_hostImpl->rootLayer());
86
87     OwnPtr<CCScrollAndScaleSet> scrollInfo = m_hostImpl->processScrollDeltas();
88     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
89 }
90
91 TEST_F(CCLayerTreeHostImplTest, scrollDeltaTreeButNoChanges)
92 {
93     RefPtr<CCLayerImpl> root = CCLayerImpl::create(0);
94     root->addChild(CCLayerImpl::create(1));
95     root->addChild(CCLayerImpl::create(2));
96     root->children()[1]->addChild(CCLayerImpl::create(3));
97     root->children()[1]->addChild(CCLayerImpl::create(4));
98     root->children()[1]->children()[0]->addChild(CCLayerImpl::create(5));
99     m_hostImpl->setRootLayer(root);
100
101     expectClearedScrollDeltasRecursive(root.get());
102
103     OwnPtr<CCScrollAndScaleSet> scrollInfo;
104
105     scrollInfo = m_hostImpl->processScrollDeltas();
106     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
107     expectClearedScrollDeltasRecursive(root.get());
108
109     scrollInfo = m_hostImpl->processScrollDeltas();
110     ASSERT_EQ(scrollInfo->scrolls.size(), 0u);
111     expectClearedScrollDeltasRecursive(root.get());
112 }
113
114 TEST_F(CCLayerTreeHostImplTest, scrollDeltaRepeatedScrolls)
115 {
116     IntPoint scrollPosition(20, 30);
117     IntSize scrollDelta(11, -15);
118     RefPtr<CCLayerImpl> root = CCLayerImpl::create(10);
119     root->setScrollPosition(scrollPosition);
120     root->setScrollable(true);
121     root->setMaxScrollPosition(IntSize(100, 100));
122     root->scrollBy(scrollDelta);
123     m_hostImpl->setRootLayer(root);
124
125     OwnPtr<CCScrollAndScaleSet> scrollInfo;
126
127     scrollInfo = m_hostImpl->processScrollDeltas();
128     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
129     EXPECT_EQ(root->sentScrollDelta(), scrollDelta);
130     expectContains(*scrollInfo.get(), root->id(), scrollDelta);
131
132     IntSize scrollDelta2(-5, 27);
133     root->scrollBy(scrollDelta2);
134     scrollInfo = m_hostImpl->processScrollDeltas();
135     ASSERT_EQ(scrollInfo->scrolls.size(), 1u);
136     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
137     expectContains(*scrollInfo.get(), root->id(), scrollDelta + scrollDelta2);
138
139     root->scrollBy(IntSize());
140     scrollInfo = m_hostImpl->processScrollDeltas();
141     EXPECT_EQ(root->sentScrollDelta(), scrollDelta + scrollDelta2);
142 }
143
144 TEST_F(CCLayerTreeHostImplTest, scrollRootCallsCommitAndRedraw)
145 {
146     RefPtr<CCLayerImpl> root = CCLayerImpl::create(0);
147     root->setScrollable(true);
148     root->setScrollPosition(IntPoint(0, 0));
149     root->setMaxScrollPosition(IntSize(100, 100));
150     m_hostImpl->setRootLayer(root);
151     EXPECT_EQ(m_hostImpl->scrollBegin(IntPoint(0, 0)), CCInputHandlerClient::ScrollStarted);
152     m_hostImpl->scrollBy(IntSize(0, 10));
153     m_hostImpl->scrollEnd();
154     EXPECT_TRUE(m_didRequestRedraw);
155     EXPECT_TRUE(m_didRequestCommit);
156 }
157
158 class BlendStateTrackerContext: public MockWebGraphicsContext3D {
159 public:
160     BlendStateTrackerContext() : m_blend(false) { }
161
162     virtual bool initialize(Attributes, WebView*, bool renderDirectlyToWebView) { return true; }
163
164     virtual void enable(WGC3Denum cap)
165     {
166         if (cap == GraphicsContext3D::BLEND)
167             m_blend = true;
168     }
169
170     virtual void disable(WGC3Denum cap)
171     {
172         if (cap == GraphicsContext3D::BLEND)
173             m_blend = false;
174     }
175
176     bool blend() const { return m_blend; }
177
178 private:
179     bool m_blend;
180 };
181
182 class BlendStateCheckLayer : public CCLayerImpl {
183 public:
184     static PassRefPtr<BlendStateCheckLayer> create(int id) { return adoptRef(new BlendStateCheckLayer(id)); }
185
186     virtual void draw(LayerRendererChromium* renderer)
187     {
188         m_drawn = true;
189         BlendStateTrackerContext* context = static_cast<BlendStateTrackerContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(renderer->context()));
190         EXPECT_EQ(m_blend, context->blend());
191         EXPECT_EQ(m_hasRenderSurface, !!renderSurface());
192     }
193
194     void setExpectation(bool blend, bool hasRenderSurface)
195     {
196         m_blend = blend;
197         m_hasRenderSurface = hasRenderSurface;
198         m_drawn = false;
199     }
200
201     bool drawn() const { return m_drawn; }
202
203 private:
204     explicit BlendStateCheckLayer(int id)
205         : CCLayerImpl(id)
206         , m_blend(false)
207         , m_hasRenderSurface(false)
208         , m_drawn(false)
209     {
210         setAnchorPoint(FloatPoint(0, 0));
211         setBounds(IntSize(10, 10));
212         setDrawsContent(true);
213     }
214
215     bool m_blend;
216     bool m_hasRenderSurface;
217     bool m_drawn;
218 };
219
220 TEST_F(CCLayerTreeHostImplTest, blendingOffWhenDrawingOpaqueLayers)
221 {
222     GraphicsContext3D::Attributes attrs;
223     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new BlendStateTrackerContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
224     m_hostImpl->initializeLayerRenderer(context);
225     m_hostImpl->setViewport(IntSize(10, 10));
226
227     RefPtr<CCLayerImpl> root = CCLayerImpl::create(0);
228     root->setAnchorPoint(FloatPoint(0, 0));
229     root->setBounds(IntSize(10, 10));
230     root->setDrawsContent(false);
231     m_hostImpl->setRootLayer(root);
232
233     RefPtr<BlendStateCheckLayer> layer1 = BlendStateCheckLayer::create(1);
234     root->addChild(layer1);
235
236     // Opaque layer, drawn without blending.
237     layer1->setOpaque(true);
238     layer1->setExpectation(false, false);
239     m_hostImpl->drawLayers();
240     EXPECT_TRUE(layer1->drawn());
241
242     // Layer with translucent content, drawn with blending.
243     layer1->setOpaque(false);
244     layer1->setExpectation(true, false);
245     m_hostImpl->drawLayers();
246     EXPECT_TRUE(layer1->drawn());
247
248     // Layer with translucent opacity, drawn with blending.
249     layer1->setOpaque(true);
250     layer1->setOpacity(0.5);
251     layer1->setExpectation(true, false);
252     m_hostImpl->drawLayers();
253     EXPECT_TRUE(layer1->drawn());
254
255     RefPtr<BlendStateCheckLayer> layer2 = BlendStateCheckLayer::create(2);
256     layer1->addChild(layer2);
257
258     // 2 opaque layers, drawn without blending.
259     layer1->setOpaque(true);
260     layer1->setOpacity(1);
261     layer1->setExpectation(false, false);
262     layer2->setOpaque(true);
263     layer2->setOpacity(1);
264     layer2->setExpectation(false, false);
265     m_hostImpl->drawLayers();
266     EXPECT_TRUE(layer1->drawn());
267     EXPECT_TRUE(layer2->drawn());
268
269     // Parent layer with translucent content, drawn with blending.
270     // Child layer with opaque content, drawn without blending.
271     layer1->setOpaque(false);
272     layer1->setExpectation(true, false);
273     layer2->setExpectation(false, false);
274     m_hostImpl->drawLayers();
275     EXPECT_TRUE(layer1->drawn());
276     EXPECT_TRUE(layer2->drawn());
277
278     // Parent layer with translucent opacity and opaque content. Since it has a
279     // drawing child, it's drawn to a render surface which carries the opacity,
280     // so it's itself drawn without blending.
281     // Child layer with opaque content, drawn without blending (parent surface
282     // carries the inherited opacity).
283     layer1->setOpaque(true);
284     layer1->setOpacity(0.5);
285     layer1->setExpectation(false, true);
286     layer2->setExpectation(false, false);
287     m_hostImpl->drawLayers();
288     EXPECT_TRUE(layer1->drawn());
289     EXPECT_TRUE(layer2->drawn());
290 }
291
292 class ReshapeTrackerContext: public MockWebGraphicsContext3D {
293 public:
294     ReshapeTrackerContext() : m_reshapeCalled(false) { }
295
296     virtual bool initialize(Attributes, WebView*, bool renderDirectlyToWebView) { return true; }
297
298     virtual void reshape(int width, int height)
299     {
300         m_reshapeCalled = true;
301     }
302
303     bool reshapeCalled() const { return m_reshapeCalled; }
304
305 private:
306     bool m_reshapeCalled;
307 };
308
309 class FakeDrawableCCLayerImpl: public CCLayerImpl {
310 public:
311     FakeDrawableCCLayerImpl() : CCLayerImpl(0) { }
312     virtual void draw(LayerRendererChromium* renderer) { }
313 };
314
315 // Only reshape when we know we are going to draw. Otherwise, the reshape
316 // can leave the window at the wrong size if we never draw and the proper
317 // viewport size is never set.
318 TEST_F(CCLayerTreeHostImplTest, reshapeNotCalledUntilDraw)
319 {
320     GraphicsContext3D::Attributes attrs;
321     ReshapeTrackerContext* reshapeTracker = new ReshapeTrackerContext();
322     RefPtr<GraphicsContext3D> context = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(reshapeTracker), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
323     m_hostImpl->initializeLayerRenderer(context);
324     m_hostImpl->setViewport(IntSize(10, 10));
325
326     RefPtr<CCLayerImpl> root = adoptRef(new FakeDrawableCCLayerImpl());
327     root->setAnchorPoint(FloatPoint(0, 0));
328     root->setBounds(IntSize(10, 10));
329     root->setDrawsContent(true);
330     m_hostImpl->setRootLayer(root);
331     EXPECT_FALSE(reshapeTracker->reshapeCalled());
332
333     m_hostImpl->drawLayers();
334     EXPECT_TRUE(reshapeTracker->reshapeCalled());
335 }
336
337
338 } // namespace