14c92ae9f7c92e9c7aa9634438dbd927ce0cad86
[WebKit-https.git] / Source / WebKit / chromium / tests / Canvas2DLayerChromiumTest.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 "Canvas2DLayerChromium.h"
28
29 #include "CCSchedulerTestCommon.h"
30 #include "FakeCCLayerTreeHostClient.h"
31 #include "FakeWebGraphicsContext3D.h"
32 #include "GraphicsContext3DPrivate.h"
33 #include "Region.h"
34 #include "TextureManager.h"
35 #include "WebCompositor.h"
36 #include "WebKit.h"
37 #include "cc/CCSingleThreadProxy.h"
38 #include "cc/CCTextureLayerImpl.h"
39 #include "cc/CCTextureUpdater.h"
40 #include "platform/WebKitPlatformSupport.h"
41 #include "platform/WebThread.h"
42
43 #include <gmock/gmock.h>
44 #include <gtest/gtest.h>
45 #include <wtf/RefPtr.h>
46
47 using namespace WebCore;
48 using namespace WebKit;
49 using namespace WebKitTests;
50 using testing::InSequence;
51 using testing::Return;
52 using testing::Test;
53
54 namespace {
55
56 class FakeCCLayerTreeHost : public CCLayerTreeHost {
57 public:
58     static PassRefPtr<FakeCCLayerTreeHost> create()
59     {
60         RefPtr<FakeCCLayerTreeHost> host = adoptRef(new FakeCCLayerTreeHost);
61         host->initialize();
62         return host.release();
63     }
64
65 private:
66     FakeCCLayerTreeHost()
67         : CCLayerTreeHost(&m_client, CCSettings())
68     {
69     }
70
71     FakeCCLayerTreeHostClient m_client;
72 };
73
74 class MockCanvasContext : public FakeWebGraphicsContext3D {
75 public:
76     MOCK_METHOD0(createFramebuffer, WebGLId());
77     MOCK_METHOD0(createTexture, WebGLId());
78
79     MOCK_METHOD2(bindFramebuffer, void(WGC3Denum, WebGLId));
80     MOCK_METHOD5(framebufferTexture2D, void(WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint));
81
82     MOCK_METHOD2(bindTexture, void(WGC3Denum, WebGLId));
83     MOCK_METHOD8(copyTexSubImage2D, void(WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei));
84
85     MOCK_METHOD1(deleteFramebuffer, void(WebGLId));
86     MOCK_METHOD1(deleteTexture, void(WebGLId));
87 };
88
89 class MockTextureAllocator : public TextureAllocator {
90 public:
91     MOCK_METHOD2(createTexture, unsigned(const IntSize&, GC3Denum));
92     MOCK_METHOD3(deleteTexture, void(unsigned, const IntSize&, GC3Denum));
93 };
94
95 class Canvas2DLayerChromiumTest : public Test {
96 protected:
97     void fullLifecycleTest(bool threaded)
98     {
99         GraphicsContext3D::Attributes attrs;
100
101         RefPtr<GraphicsContext3D> mainContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), GraphicsContext3D::RenderDirectlyToHostWindow);
102         RefPtr<GraphicsContext3D> implContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), GraphicsContext3D::RenderDirectlyToHostWindow);
103
104         MockCanvasContext& mainMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(mainContext.get()));
105         MockCanvasContext& implMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(implContext.get()));
106
107         MockTextureAllocator allocatorMock;
108         CCTextureUpdater updater(&allocatorMock);
109
110         const IntSize size(300, 150);
111
112         OwnPtr<WebThread> thread;
113         if (threaded)
114            thread = adoptPtr(webKitPlatformSupport()->createThread("Canvas2DLayerChromiumTest"));
115         WebCompositor::initialize(thread.get());
116
117         RefPtr<FakeCCLayerTreeHost> layerTreeHost = FakeCCLayerTreeHost::create();
118         // Force an update, so that we get a valid TextureManager.
119         layerTreeHost->updateLayers();
120
121         const WebGLId backTextureId = 1;
122         const WebGLId frontTextureId = 2;
123         const WebGLId fboId = 3;
124         {
125             InSequence sequence;
126
127             // Note that the canvas backing texture is doublebuffered only when using the threaded
128             // compositor.
129             if (threaded) {
130                 // Setup Canvas2DLayerChromium (on the main thread).
131                 EXPECT_CALL(mainMock, createFramebuffer())
132                     .WillOnce(Return(fboId));
133
134                 // Create texture and do the copy (on the impl thread).
135                 EXPECT_CALL(allocatorMock, createTexture(size, GraphicsContext3D::RGBA))
136                     .WillOnce(Return(frontTextureId));
137                 EXPECT_CALL(implMock, bindTexture(GraphicsContext3D::TEXTURE_2D, frontTextureId));
138                 EXPECT_CALL(implMock, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, fboId));
139                 EXPECT_CALL(implMock, framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, backTextureId, 0));
140                 EXPECT_CALL(implMock, copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, 300, 150));
141                 EXPECT_CALL(implMock, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
142
143                 // Teardown Canvas2DLayerChromium.
144                 EXPECT_CALL(mainMock, deleteFramebuffer(fboId));
145
146                 // Teardown TextureManager.
147                 EXPECT_CALL(allocatorMock, deleteTexture(frontTextureId, size, GraphicsContext3D::RGBA));
148             }
149         }
150
151         RefPtr<Canvas2DLayerChromium> canvas = Canvas2DLayerChromium::create(mainContext.get(), size);
152         canvas->setIsDrawable(true);
153         canvas->setLayerTreeHost(layerTreeHost.get());
154         canvas->setBounds(IntSize(600, 300));
155         canvas->setTextureId(backTextureId);
156
157         canvas->setNeedsDisplay();
158         EXPECT_TRUE(canvas->needsDisplay());
159         canvas->paintContentsIfDirty(0);
160         EXPECT_FALSE(canvas->needsDisplay());
161         {
162             DebugScopedSetImplThread scopedImplThread;
163
164             OwnPtr<CCLayerImpl> layerImpl = canvas->createCCLayerImpl();
165             EXPECT_EQ(0u, static_cast<CCTextureLayerImpl*>(layerImpl.get())->textureId());
166
167             canvas->updateCompositorResources(implContext.get(), updater);
168             canvas->pushPropertiesTo(layerImpl.get());
169
170             if (threaded)
171                 EXPECT_EQ(frontTextureId, static_cast<CCTextureLayerImpl*>(layerImpl.get())->textureId());
172             else
173                 EXPECT_EQ(backTextureId, static_cast<CCTextureLayerImpl*>(layerImpl.get())->textureId());
174         }
175         canvas.clear();
176         layerTreeHost->contentsTextureManager()->reduceMemoryToLimit(0);
177         layerTreeHost->contentsTextureManager()->deleteEvictedTextures(&allocatorMock);
178         layerTreeHost.clear();
179         WebCompositor::shutdown();
180     }
181 };
182
183 TEST_F(Canvas2DLayerChromiumTest, testFullLifecycleSingleThread)
184 {
185     fullLifecycleTest(false);
186 }
187
188 TEST_F(Canvas2DLayerChromiumTest, testFullLifecycleThreaded)
189 {
190     fullLifecycleTest(true);
191 }
192
193 } // namespace