[chromium] Clean up includes in compositor unit tests
[WebKit-https.git] / Source / WebKit / chromium / tests / LayerRendererChromiumTest.cpp
1 /*
2  * Copyright (C) 2012 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 #include "LayerRendererChromium.h"
27
28 #include "CCTestCommon.h"
29 #include "FakeWebGraphicsContext3D.h"
30 #include "GraphicsContext3D.h"
31 #include "cc/CCDrawQuad.h"
32 #include "cc/CCPrioritizedTextureManager.h"
33 #include "cc/CCSettings.h"
34 #include "cc/CCSingleThreadProxy.h"
35 #include <public/WebCompositor.h>
36
37 #include <gmock/gmock.h>
38 #include <gtest/gtest.h>
39
40 using namespace WebCore;
41 using namespace WebKit;
42 using namespace WebKitTests;
43
44 class FrameCountingMemoryAllocationSettingContext : public FakeWebGraphicsContext3D {
45 public:
46     FrameCountingMemoryAllocationSettingContext() : m_frame(0) { }
47
48     // WebGraphicsContext3D methods.
49
50     // This method would normally do a glSwapBuffers under the hood.
51     virtual void prepareTexture() { m_frame++; }
52     virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { m_memoryAllocationChangedCallback = callback; }
53     virtual WebString getString(WebKit::WGC3Denum name)
54     {
55         if (name == GraphicsContext3D::EXTENSIONS)
56             return WebString("GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager GL_CHROMIUM_discard_framebuffer");
57         return WebString();
58     }
59
60     // Methods added for test.
61     int frameCount() { return m_frame; }
62     void setMemoryAllocation(WebGraphicsMemoryAllocation allocation)
63     {
64         ASSERT(CCProxy::isImplThread());
65         // In single threaded mode we expect this callback on main thread.
66         DebugScopedSetMainThread main;
67         m_memoryAllocationChangedCallback->onMemoryAllocationChanged(allocation);
68     }
69
70 private:
71     int m_frame;
72     WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* m_memoryAllocationChangedCallback;
73 };
74
75 class FakeCCRendererClient : public CCRendererClient {
76 public:
77     FakeCCRendererClient()
78         : m_setFullRootLayerDamageCount(0)
79         , m_rootLayer(CCLayerImpl::create(1))
80         , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit())
81     {
82         m_rootLayer->createRenderSurface();
83         OwnPtr<CCRenderPass> rootRenderPass = CCRenderPass::create(m_rootLayer->renderSurface(), m_rootLayer->id());
84         m_renderPassesInDrawOrder.append(rootRenderPass.get());
85         m_renderPasses.set(m_rootLayer->id(), rootRenderPass.release());
86     }
87
88     // CCRendererClient methods.
89     virtual const IntSize& deviceViewportSize() const OVERRIDE { static IntSize fakeSize(1, 1); return fakeSize; }
90     virtual const CCLayerTreeSettings& settings() const OVERRIDE { static CCLayerTreeSettings fakeSettings; return fakeSettings; }
91     virtual void didLoseContext() OVERRIDE { }
92     virtual void onSwapBuffersComplete() OVERRIDE { }
93     virtual void setFullRootLayerDamage() OVERRIDE { m_setFullRootLayerDamageCount++; }
94     virtual void releaseContentsTextures() OVERRIDE { }
95     virtual void setMemoryAllocationLimitBytes(size_t bytes) OVERRIDE { m_memoryAllocationLimitBytes = bytes; }
96
97     // Methods added for test.
98     int setFullRootLayerDamageCount() const { return m_setFullRootLayerDamageCount; }
99
100     CCRenderPass* rootRenderPass() { return m_renderPassesInDrawOrder.last(); }
101     const CCRenderPassList& renderPassesInDrawOrder() const { return m_renderPassesInDrawOrder; }
102     const CCRenderPassIdHashMap& renderPasses() const { return m_renderPasses; }
103
104     size_t memoryAllocationLimitBytes() const { return m_memoryAllocationLimitBytes; }
105
106 private:
107     int m_setFullRootLayerDamageCount;
108     DebugScopedSetImplThread m_implThread;
109     OwnPtr<CCLayerImpl> m_rootLayer;
110     CCRenderPassList m_renderPassesInDrawOrder;
111     CCRenderPassIdHashMap m_renderPasses;
112     size_t m_memoryAllocationLimitBytes;
113 };
114
115 class FakeLayerRendererChromium : public LayerRendererChromium {
116 public:
117     FakeLayerRendererChromium(CCRendererClient* client, CCResourceProvider* resourceProvider) : LayerRendererChromium(client, resourceProvider, UnthrottledUploader) { }
118
119     // LayerRendererChromium methods.
120
121     // Changing visibility to public.
122     using LayerRendererChromium::initialize;
123     using LayerRendererChromium::isFramebufferDiscarded;
124 };
125
126 class LayerRendererChromiumTest : public testing::Test {
127 protected:
128     LayerRendererChromiumTest()
129         : m_suggestHaveBackbufferYes(1, true)
130         , m_suggestHaveBackbufferNo(1, false)
131         , m_context(CCGraphicsContext::create3D(adoptPtr(new FrameCountingMemoryAllocationSettingContext())))
132         , m_resourceProvider(CCResourceProvider::create(m_context.get()))
133         , m_layerRendererChromium(&m_mockClient, m_resourceProvider.get())
134     {
135     }
136
137     virtual void SetUp()
138     {
139         WebKit::WebCompositor::initialize(0);
140         m_layerRendererChromium.initialize();
141     }
142
143     virtual void TearDown()
144     {
145         WebKit::WebCompositor::shutdown();
146     }
147
148     void swapBuffers()
149     {
150         m_layerRendererChromium.swapBuffers(IntRect());
151     }
152
153     FrameCountingMemoryAllocationSettingContext* context() { return static_cast<FrameCountingMemoryAllocationSettingContext*>(m_context->context3D()); }
154
155     WebGraphicsMemoryAllocation m_suggestHaveBackbufferYes;
156     WebGraphicsMemoryAllocation m_suggestHaveBackbufferNo;
157
158     OwnPtr<CCGraphicsContext> m_context;
159     FakeCCRendererClient m_mockClient;
160     OwnPtr<CCResourceProvider> m_resourceProvider;
161     FakeLayerRendererChromium m_layerRendererChromium;
162     CCScopedSettings m_scopedSettings;
163 };
164
165 // Test LayerRendererChromium discardFramebuffer functionality:
166 // Suggest recreating framebuffer when one already exists.
167 // Expected: it does nothing.
168 TEST_F(LayerRendererChromiumTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing)
169 {
170     context()->setMemoryAllocation(m_suggestHaveBackbufferYes);
171     EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
172     EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
173
174     swapBuffers();
175     EXPECT_EQ(1, context()->frameCount());
176 }
177
178 // Test LayerRendererChromium discardFramebuffer functionality:
179 // Suggest discarding framebuffer when one exists and the renderer is not visible.
180 // Expected: it is discarded and damage tracker is reset.
181 TEST_F(LayerRendererChromiumTest, SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerWhileNotVisible)
182 {
183     m_layerRendererChromium.setVisible(false);
184     context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
185     EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
186     EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
187 }
188
189 // Test LayerRendererChromium discardFramebuffer functionality:
190 // Suggest discarding framebuffer when one exists and the renderer is visible.
191 // Expected: the allocation is ignored.
192 TEST_F(LayerRendererChromiumTest, SuggestBackbufferNoDoNothingWhenVisible)
193 {
194     m_layerRendererChromium.setVisible(true);
195     context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
196     EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
197     EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
198 }
199
200
201 // Test LayerRendererChromium discardFramebuffer functionality:
202 // Suggest discarding framebuffer when one does not exist.
203 // Expected: it does nothing.
204 TEST_F(LayerRendererChromiumTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing)
205 {
206     m_layerRendererChromium.setVisible(false);
207     context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
208     EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
209     EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
210
211     context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
212     EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
213     EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
214 }
215
216 // Test LayerRendererChromium discardFramebuffer functionality:
217 // Begin drawing a frame while a framebuffer is discarded.
218 // Expected: will recreate framebuffer.
219 TEST_F(LayerRendererChromiumTest, DiscardedBackbufferIsRecreatedForScopeDuration)
220 {
221     m_layerRendererChromium.setVisible(false);
222     context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
223     EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
224     EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
225
226     m_layerRendererChromium.setVisible(true);
227     m_layerRendererChromium.drawFrame(m_mockClient.renderPassesInDrawOrder(), m_mockClient.renderPasses(), FloatRect());
228     EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
229
230     swapBuffers();
231     EXPECT_EQ(1, context()->frameCount());
232 }
233
234 TEST_F(LayerRendererChromiumTest, FramebufferDiscardedAfterReadbackWhenNotVisible)
235 {
236     m_layerRendererChromium.setVisible(false);
237     context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
238     EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
239     EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
240
241     char pixels[4];
242     m_layerRendererChromium.drawFrame(m_mockClient.renderPassesInDrawOrder(), m_mockClient.renderPasses(), FloatRect());
243     EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
244
245     m_layerRendererChromium.getFramebufferPixels(pixels, IntRect(0, 0, 1, 1));
246     EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
247     EXPECT_EQ(2, m_mockClient.setFullRootLayerDamageCount());
248 }
249
250 class ForbidSynchronousCallContext : public FakeWebGraphicsContext3D {
251 public:
252     ForbidSynchronousCallContext() { }
253
254     virtual bool getActiveAttrib(WebGLId program, WGC3Duint index, ActiveInfo&) { ADD_FAILURE(); return false; }
255     virtual bool getActiveUniform(WebGLId program, WGC3Duint index, ActiveInfo&) { ADD_FAILURE(); return false; }
256     virtual void getAttachedShaders(WebGLId program, WGC3Dsizei maxCount, WGC3Dsizei* count, WebGLId* shaders) { ADD_FAILURE(); }
257     virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) { ADD_FAILURE(); return 0; }
258     virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) { ADD_FAILURE(); }
259     virtual void getBufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
260     virtual Attributes getContextAttributes() { ADD_FAILURE(); return m_attrs; }
261     virtual WGC3Denum getError() { ADD_FAILURE(); return 0; }
262     virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
263     virtual void getFramebufferAttachmentParameteriv(WGC3Denum target, WGC3Denum attachment, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
264     virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value)
265     {
266         if (pname == WebCore::GraphicsContext3D::MAX_TEXTURE_SIZE)
267             *value = 1024; // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
268         else
269             ADD_FAILURE();
270     }
271
272     // We allow querying the shader compilation and program link status in debug mode, but not release.
273     virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
274     {
275 #ifndef NDEBUG
276         *value = 1;
277 #else
278         ADD_FAILURE();
279 #endif
280     }
281
282     virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
283     {
284 #ifndef NDEBUG
285         *value = 1;
286 #else
287         ADD_FAILURE();
288 #endif
289     }
290
291     virtual WebString getString(WGC3Denum name)
292     {
293         // We allow querying the extension string.
294         // FIXME: It'd be better to check that we only do this before starting any other expensive work (like starting a compilation)
295         if (name != WebCore::GraphicsContext3D::EXTENSIONS)
296             ADD_FAILURE();
297         return WebString();
298     }
299
300     virtual WebString getProgramInfoLog(WebGLId program) { ADD_FAILURE(); return WebString(); }
301     virtual void getRenderbufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
302
303     virtual WebString getShaderInfoLog(WebGLId shader) { ADD_FAILURE(); return WebString(); }
304     virtual void getShaderPrecisionFormat(WGC3Denum shadertype, WGC3Denum precisiontype, WGC3Dint* range, WGC3Dint* precision) { ADD_FAILURE(); }
305     virtual WebString getShaderSource(WebGLId shader) { ADD_FAILURE(); return WebString(); }
306     virtual void getTexParameterfv(WGC3Denum target, WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
307     virtual void getTexParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
308     virtual void getUniformfv(WebGLId program, WGC3Dint location, WGC3Dfloat* value) { ADD_FAILURE(); }
309     virtual void getUniformiv(WebGLId program, WGC3Dint location, WGC3Dint* value) { ADD_FAILURE(); }
310     virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name) { ADD_FAILURE(); return 0; }
311     virtual void getVertexAttribfv(WGC3Duint index, WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
312     virtual void getVertexAttribiv(WGC3Duint index, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
313     virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index, WGC3Denum pname) { ADD_FAILURE(); return 0; }
314 };
315
316 // This test isn't using the same fixture as LayerRendererChromiumTest, and you can't mix TEST() and TEST_F() with the same name, hence LRC2.
317 TEST(LayerRendererChromiumTest2, initializationDoesNotMakeSynchronousCalls)
318 {
319     CCScopedSettings scopedSettings;
320     FakeCCRendererClient mockClient;
321     OwnPtr<CCGraphicsContext> context(CCGraphicsContext::create3D(adoptPtr(new ForbidSynchronousCallContext)));
322     OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(context.get()));
323     FakeLayerRendererChromium layerRendererChromium(&mockClient, resourceProvider.get());
324
325     EXPECT_TRUE(layerRendererChromium.initialize());
326 }
327
328 class LoseContextOnFirstGetContext : public FakeWebGraphicsContext3D {
329 public:
330     LoseContextOnFirstGetContext()
331         : m_contextLost(false)
332     {
333     }
334
335     virtual bool makeContextCurrent() OVERRIDE
336     {
337         return !m_contextLost;
338     }
339
340     virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) OVERRIDE
341     {
342         m_contextLost = true;
343         *value = 0;
344     }
345
346     virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) OVERRIDE
347     {
348         m_contextLost = true;
349         *value = 0;
350     }
351
352     virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE
353     {
354         return m_contextLost ? 1 : 0;
355     }
356
357 private:
358     bool m_contextLost;
359 };
360
361 TEST(LayerRendererChromiumTest2, initializationWithQuicklyLostContextDoesNotAssert)
362 {
363     CCScopedSettings scopedSettings;
364     FakeCCRendererClient mockClient;
365     OwnPtr<CCGraphicsContext> context(CCGraphicsContext::create3D(adoptPtr(new LoseContextOnFirstGetContext)));
366     OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(context.get()));
367     FakeLayerRendererChromium layerRendererChromium(&mockClient, resourceProvider.get());
368
369     layerRendererChromium.initialize();
370 }
371
372 class ContextThatDoesNotSupportMemoryManagmentExtensions : public FakeWebGraphicsContext3D {
373 public:
374     ContextThatDoesNotSupportMemoryManagmentExtensions() { }
375
376     // WebGraphicsContext3D methods.
377
378     // This method would normally do a glSwapBuffers under the hood.
379     virtual void prepareTexture() { }
380     virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { }
381     virtual WebString getString(WebKit::WGC3Denum name) { return WebString(); }
382 };
383
384 TEST(LayerRendererChromiumTest2, initializationWithoutGpuMemoryManagerExtensionSupportShouldDefaultToNonZeroAllocation)
385 {
386     FakeCCRendererClient mockClient;
387     OwnPtr<CCGraphicsContext> context(CCGraphicsContext::create3D(adoptPtr(new ContextThatDoesNotSupportMemoryManagmentExtensions)));
388     OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(context.get()));
389     FakeLayerRendererChromium layerRendererChromium(&mockClient, resourceProvider.get());
390
391     layerRendererChromium.initialize();
392
393     EXPECT_GT(mockClient.memoryAllocationLimitBytes(), 0ul);
394 }
395
396 class ClearCountingContext : public FakeWebGraphicsContext3D {
397 public:
398     ClearCountingContext() : m_clear(0) { }
399
400     virtual void clear(WGC3Dbitfield)
401     {
402         m_clear++;
403     }
404
405     int clearCount() const { return m_clear; }
406
407 private:
408     int m_clear;
409 };
410
411 TEST(LayerRendererChromiumTest2, opaqueBackground)
412 {
413     FakeCCRendererClient mockClient;
414     OwnPtr<CCGraphicsContext> ccContext(CCGraphicsContext::create3D(adoptPtr(new ClearCountingContext)));
415     ClearCountingContext* context = static_cast<ClearCountingContext*>(ccContext->context3D());
416     OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(ccContext.get()));
417     FakeLayerRendererChromium layerRendererChromium(&mockClient, resourceProvider.get());
418
419     mockClient.rootRenderPass()->setHasTransparentBackground(false);
420
421     EXPECT_TRUE(layerRendererChromium.initialize());
422
423     layerRendererChromium.drawFrame(mockClient.renderPassesInDrawOrder(), mockClient.renderPasses(), FloatRect());
424
425     // On DEBUG builds, render passes with opaque background clear to blue to
426     // easily see regions that were not drawn on the screen.
427 #if defined(NDEBUG)
428     EXPECT_EQ(0, context->clearCount());
429 #else
430     EXPECT_EQ(1, context->clearCount());
431 #endif
432 }
433
434 TEST(LayerRendererChromiumTest2, transparentBackground)
435 {
436     FakeCCRendererClient mockClient;
437     OwnPtr<CCGraphicsContext> ccContext(CCGraphicsContext::create3D(adoptPtr(new ClearCountingContext)));
438     ClearCountingContext* context = static_cast<ClearCountingContext*>(ccContext->context3D());
439     OwnPtr<CCResourceProvider> resourceProvider(CCResourceProvider::create(ccContext.get()));
440     FakeLayerRendererChromium layerRendererChromium(&mockClient, resourceProvider.get());
441
442     mockClient.rootRenderPass()->setHasTransparentBackground(true);
443
444     EXPECT_TRUE(layerRendererChromium.initialize());
445
446     layerRendererChromium.drawFrame(mockClient.renderPassesInDrawOrder(), mockClient.renderPasses(), FloatRect());
447
448     EXPECT_EQ(1, context->clearCount());
449 }