Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: cc/gl_renderer_unittest.cc

Issue 12912006: Part 4 of cc/ directory shuffles: output (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/gl_renderer.h"
6
7 #include "cc/compositor_frame_metadata.h"
8 #include "cc/draw_quad.h"
9 #include "cc/prioritized_resource_manager.h"
10 #include "cc/resource_provider.h"
11 #include "cc/test/fake_impl_proxy.h"
12 #include "cc/test/fake_layer_tree_host_impl.h"
13 #include "cc/test/fake_output_surface.h"
14 #include "cc/test/pixel_test.h"
15 #include "cc/test/render_pass_test_common.h"
16 #include "cc/test/render_pass_test_utils.h"
17 #include "cc/test/test_web_graphics_context_3d.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/khronos/GLES2/gl2.h"
21 #include "ui/gfx/transform.h"
22
23 using namespace WebKit;
24
25 using testing::_;
26 using testing::AnyNumber;
27 using testing::AtLeast;
28 using testing::Expectation;
29 using testing::InSequence;
30 using testing::Mock;
31 using testing::Return;
32 using testing::StrictMock;
33
34 namespace cc {
35
36 #define EXPECT_PROGRAM_VALID(program_binding) \
37 do { \
38 EXPECT_TRUE(program_binding->program()); \
39 EXPECT_TRUE(program_binding->initialized()); \
40 } while (false)
41
42 // Explicitly named to be a friend in GLRenderer for shader access.
43 class GLRendererShaderTest : public PixelTest {
44 public:
45 void TestShaders() {
46 ASSERT_FALSE(renderer_->IsContextLost());
47 EXPECT_PROGRAM_VALID(renderer_->GetTileProgram());
48 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramOpaque());
49 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramAA());
50 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzle());
51 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzleOpaque());
52 EXPECT_PROGRAM_VALID(renderer_->GetTileProgramSwizzleAA());
53 EXPECT_PROGRAM_VALID(renderer_->GetTileCheckerboardProgram());
54 EXPECT_PROGRAM_VALID(renderer_->GetRenderPassProgram());
55 EXPECT_PROGRAM_VALID(renderer_->GetRenderPassProgramAA());
56 EXPECT_PROGRAM_VALID(renderer_->GetRenderPassMaskProgram());
57 EXPECT_PROGRAM_VALID(renderer_->GetRenderPassMaskProgramAA());
58 EXPECT_PROGRAM_VALID(renderer_->GetTextureProgram());
59 EXPECT_PROGRAM_VALID(renderer_->GetTextureProgramFlip());
60 EXPECT_PROGRAM_VALID(renderer_->GetTextureIOSurfaceProgram());
61 EXPECT_PROGRAM_VALID(renderer_->GetVideoYUVProgram());
62 // This is unlikely to be ever true in tests due to usage of osmesa.
63 if (renderer_->Capabilities().using_egl_image)
64 EXPECT_PROGRAM_VALID(renderer_->GetVideoStreamTextureProgram());
65 else
66 EXPECT_FALSE(renderer_->GetVideoStreamTextureProgram());
67 EXPECT_PROGRAM_VALID(renderer_->GetDebugBorderProgram());
68 EXPECT_PROGRAM_VALID(renderer_->GetSolidColorProgram());
69 EXPECT_PROGRAM_VALID(renderer_->GetSolidColorProgramAA());
70 ASSERT_FALSE(renderer_->IsContextLost());
71 }
72 };
73
74 namespace {
75
76 #if !defined(OS_ANDROID)
77 TEST_F(GLRendererShaderTest, AllShadersCompile) {
78 TestShaders();
79 }
80 #endif
81
82 class FrameCountingMemoryAllocationSettingContext : public TestWebGraphicsContex t3D {
83 public:
84 FrameCountingMemoryAllocationSettingContext() : m_frame(0) { }
85
86 // WebGraphicsContext3D methods.
87
88 // This method would normally do a glSwapBuffers under the hood.
89 virtual void prepareTexture() { m_frame++; }
90 virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAll ocationChangedCallbackCHROMIUM* callback) { m_memoryAllocationChangedCallback = callback; }
91 virtual WebString getString(WebKit::WGC3Denum name)
92 {
93 if (name == GL_EXTENSIONS)
94 return WebString("GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_ manager GL_CHROMIUM_discard_backbuffer");
95 return WebString();
96 }
97
98 // Methods added for test.
99 int frameCount() { return m_frame; }
100 void setMemoryAllocation(WebGraphicsMemoryAllocation allocation)
101 {
102 m_memoryAllocationChangedCallback->onMemoryAllocationChanged(allocation) ;
103 }
104
105 private:
106 int m_frame;
107 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* m_memoryAllocationChange dCallback;
108 };
109
110 class FakeRendererClient : public RendererClient {
111 public:
112 FakeRendererClient()
113 : m_hostImpl(&m_proxy)
114 , m_setFullRootLayerDamageCount(0)
115 , m_lastCallWasSetVisibility(0)
116 , m_rootLayer(LayerImpl::Create(m_hostImpl.active_tree(), 1))
117 , m_memoryAllocationLimitBytes(PrioritizedResourceManager::defaultMemory AllocationLimit())
118 {
119 m_rootLayer->CreateRenderSurface();
120 RenderPass::Id renderPassId = m_rootLayer->render_surface()->RenderPassI d();
121 scoped_ptr<RenderPass> root_render_pass = RenderPass::Create();
122 root_render_pass->SetNew(renderPassId, gfx::Rect(), gfx::Rect(), gfx::Tr ansform());
123 m_renderPassesInDrawOrder.push_back(root_render_pass.Pass());
124 }
125
126 // RendererClient methods.
127 virtual gfx::Size DeviceViewportSize() const OVERRIDE { static gfx::Size fak eSize(1, 1); return fakeSize; }
128 virtual const LayerTreeSettings& Settings() const OVERRIDE { static LayerTre eSettings fakeSettings; return fakeSettings; }
129 virtual void DidLoseOutputSurface() OVERRIDE { }
130 virtual void OnSwapBuffersComplete() OVERRIDE { }
131 virtual void SetFullRootLayerDamage() OVERRIDE { m_setFullRootLayerDamageCou nt++; }
132 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERR IDE { m_memoryAllocationLimitBytes = policy.bytesLimitWhenVisible; }
133 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) O VERRIDE { if (m_lastCallWasSetVisibility) *m_lastCallWasSetVisibility = false; }
134 virtual bool HasImplThread() const OVERRIDE { return false; }
135 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return true; }
136 virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const
137 OVERRIDE { return CompositorFrameMetadata(); }
138
139 // Methods added for test.
140 int setFullRootLayerDamageCount() const { return m_setFullRootLayerDamageCou nt; }
141 void setLastCallWasSetVisibilityPointer(bool* lastCallWasSetVisibility) { m_ lastCallWasSetVisibility = lastCallWasSetVisibility; }
142
143 RenderPass* root_render_pass() { return m_renderPassesInDrawOrder.back(); }
144 RenderPassList& renderPassesInDrawOrder() { return m_renderPassesInDrawOrder ; }
145
146 size_t memoryAllocationLimitBytes() const { return m_memoryAllocationLimitBy tes; }
147
148 private:
149 FakeImplProxy m_proxy;
150 FakeLayerTreeHostImpl m_hostImpl;
151 int m_setFullRootLayerDamageCount;
152 bool* m_lastCallWasSetVisibility;
153 scoped_ptr<LayerImpl> m_rootLayer;
154 RenderPassList m_renderPassesInDrawOrder;
155 size_t m_memoryAllocationLimitBytes;
156 };
157
158 class FakeRendererGL : public GLRenderer {
159 public:
160 FakeRendererGL(RendererClient* client, OutputSurface* outputSurface, Resourc eProvider* resourceProvider) : GLRenderer(client, outputSurface, resourceProvide r) { }
161
162 // GLRenderer methods.
163
164 // Changing visibility to public.
165 using GLRenderer::Initialize;
166 using GLRenderer::IsBackbufferDiscarded;
167 using GLRenderer::DoDrawQuad;
168 using GLRenderer::BeginDrawingFrame;
169 using GLRenderer::FinishDrawingQuadList;
170 };
171
172 class GLRendererTest : public testing::Test {
173 protected:
174 GLRendererTest()
175 : m_suggestHaveBackbufferYes(1, true)
176 , m_suggestHaveBackbufferNo(1, false)
177 , m_outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGrap hicsContext3D>(new FrameCountingMemoryAllocationSettingContext())))
178 , resource_provider_(ResourceProvider::Create(m_outputSurface.get()))
179 , m_renderer(&m_mockClient, m_outputSurface.get(), resource_provider_.ge t())
180 {
181 }
182
183 virtual void SetUp()
184 {
185 m_renderer.Initialize();
186 }
187
188 void SwapBuffers()
189 {
190 m_renderer.SwapBuffers();
191 }
192
193 FrameCountingMemoryAllocationSettingContext* context() { return static_cast< FrameCountingMemoryAllocationSettingContext*>(m_outputSurface->context3d()); }
194
195 WebGraphicsMemoryAllocation m_suggestHaveBackbufferYes;
196 WebGraphicsMemoryAllocation m_suggestHaveBackbufferNo;
197
198 scoped_ptr<OutputSurface> m_outputSurface;
199 FakeRendererClient m_mockClient;
200 scoped_ptr<ResourceProvider> resource_provider_;
201 FakeRendererGL m_renderer;
202 };
203
204 // Test GLRenderer discardBackbuffer functionality:
205 // Suggest recreating framebuffer when one already exists.
206 // Expected: it does nothing.
207 TEST_F(GLRendererTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing)
208 {
209 context()->setMemoryAllocation(m_suggestHaveBackbufferYes);
210 EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
211 EXPECT_FALSE(m_renderer.IsBackbufferDiscarded());
212
213 SwapBuffers();
214 EXPECT_EQ(1, context()->frameCount());
215 }
216
217 // Test GLRenderer discardBackbuffer functionality:
218 // Suggest discarding framebuffer when one exists and the renderer is not visibl e.
219 // Expected: it is discarded and damage tracker is reset.
220 TEST_F(GLRendererTest, SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLa yerWhileNotVisible)
221 {
222 m_renderer.SetVisible(false);
223 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
224 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
225 EXPECT_TRUE(m_renderer.IsBackbufferDiscarded());
226 }
227
228 // Test GLRenderer discardBackbuffer functionality:
229 // Suggest discarding framebuffer when one exists and the renderer is visible.
230 // Expected: the allocation is ignored.
231 TEST_F(GLRendererTest, SuggestBackbufferNoDoNothingWhenVisible)
232 {
233 m_renderer.SetVisible(true);
234 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
235 EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
236 EXPECT_FALSE(m_renderer.IsBackbufferDiscarded());
237 }
238
239
240 // Test GLRenderer discardBackbuffer functionality:
241 // Suggest discarding framebuffer when one does not exist.
242 // Expected: it does nothing.
243 TEST_F(GLRendererTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing)
244 {
245 m_renderer.SetVisible(false);
246 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
247 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
248 EXPECT_TRUE(m_renderer.IsBackbufferDiscarded());
249
250 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
251 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
252 EXPECT_TRUE(m_renderer.IsBackbufferDiscarded());
253 }
254
255 // Test GLRenderer discardBackbuffer functionality:
256 // Begin drawing a frame while a framebuffer is discarded.
257 // Expected: will recreate framebuffer.
258 TEST_F(GLRendererTest, DiscardedBackbufferIsRecreatedForScopeDuration)
259 {
260 m_renderer.SetVisible(false);
261 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
262 EXPECT_TRUE(m_renderer.IsBackbufferDiscarded());
263 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
264
265 m_renderer.SetVisible(true);
266 m_renderer.DrawFrame(m_mockClient.renderPassesInDrawOrder());
267 EXPECT_FALSE(m_renderer.IsBackbufferDiscarded());
268
269 SwapBuffers();
270 EXPECT_EQ(1, context()->frameCount());
271 }
272
273 TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible)
274 {
275 m_renderer.SetVisible(false);
276 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
277 EXPECT_TRUE(m_renderer.IsBackbufferDiscarded());
278 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
279
280 char pixels[4];
281 m_renderer.DrawFrame(m_mockClient.renderPassesInDrawOrder());
282 EXPECT_FALSE(m_renderer.IsBackbufferDiscarded());
283
284 m_renderer.GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
285 EXPECT_TRUE(m_renderer.IsBackbufferDiscarded());
286 EXPECT_EQ(2, m_mockClient.setFullRootLayerDamageCount());
287 }
288
289 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
290 public:
291 ForbidSynchronousCallContext() { }
292
293 virtual bool getActiveAttrib(WebGLId program, WGC3Duint index, ActiveInfo&) { ADD_FAILURE(); return false; }
294 virtual bool getActiveUniform(WebGLId program, WGC3Duint index, ActiveInfo&) { ADD_FAILURE(); return false; }
295 virtual void getAttachedShaders(WebGLId program, WGC3Dsizei maxCount, WGC3Ds izei* count, WebGLId* shaders) { ADD_FAILURE(); }
296 virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) { ADD_FAILURE(); return 0; }
297 virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) { ADD_FAILURE (); }
298 virtual void getBufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Din t* value) { ADD_FAILURE(); }
299 virtual Attributes getContextAttributes() { ADD_FAILURE(); return attributes _; }
300 virtual WGC3Denum getError() { ADD_FAILURE(); return 0; }
301 virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
302 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target, WGC3Denum attachment, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
303 virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value)
304 {
305 if (pname == GL_MAX_TEXTURE_SIZE)
306 *value = 1024; // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
307 else
308 ADD_FAILURE();
309 }
310
311 // We allow querying the shader compilation and program link status in debug mode, but not release.
312 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
313 {
314 #ifndef NDEBUG
315 *value = 1;
316 #else
317 ADD_FAILURE();
318 #endif
319 }
320
321 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
322 {
323 #ifndef NDEBUG
324 *value = 1;
325 #else
326 ADD_FAILURE();
327 #endif
328 }
329
330 virtual WebString getString(WGC3Denum name)
331 {
332 // We allow querying the extension string.
333 // FIXME: It'd be better to check that we only do this before starting a ny other expensive work (like starting a compilation)
334 if (name != GL_EXTENSIONS)
335 ADD_FAILURE();
336 return WebString();
337 }
338
339 virtual WebString getProgramInfoLog(WebGLId program) { ADD_FAILURE(); return WebString(); }
340 virtual void getRenderbufferParameteriv(WGC3Denum target, WGC3Denum pname, W GC3Dint* value) { ADD_FAILURE(); }
341
342 virtual WebString getShaderInfoLog(WebGLId shader) { ADD_FAILURE(); return W ebString(); }
343 virtual void getShaderPrecisionFormat(WGC3Denum shadertype, WGC3Denum precis iontype, WGC3Dint* range, WGC3Dint* precision) { ADD_FAILURE(); }
344 virtual WebString getShaderSource(WebGLId shader) { ADD_FAILURE(); return We bString(); }
345 virtual void getTexParameterfv(WGC3Denum target, WGC3Denum pname, WGC3Dfloat * value) { ADD_FAILURE(); }
346 virtual void getTexParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
347 virtual void getUniformfv(WebGLId program, WGC3Dint location, WGC3Dfloat* va lue) { ADD_FAILURE(); }
348 virtual void getUniformiv(WebGLId program, WGC3Dint location, WGC3Dint* valu e) { ADD_FAILURE(); }
349 virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name) { ADD_FAILURE(); return 0; }
350 virtual void getVertexAttribfv(WGC3Duint index, WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
351 virtual void getVertexAttribiv(WGC3Duint index, WGC3Denum pname, WGC3Dint* v alue) { ADD_FAILURE(); }
352 virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index, WGC3Denum pname ) { ADD_FAILURE(); return 0; }
353 };
354
355 // This test isn't using the same fixture as GLRendererTest, and you can't mix T EST() and TEST_F() with the same name, hence LRC2.
356 TEST(GLRendererTest2, initializationDoesNotMakeSynchronousCalls)
357 {
358 FakeRendererClient mockClient;
359 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new ForbidSynchronousCallContext)));
360 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
361 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.g et());
362
363 EXPECT_TRUE(renderer.Initialize());
364 }
365
366 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
367 public:
368 LoseContextOnFirstGetContext()
369 : m_contextLost(false)
370 {
371 }
372
373 virtual bool makeContextCurrent() OVERRIDE
374 {
375 return !m_contextLost;
376 }
377
378 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) OVERRIDE
379 {
380 m_contextLost = true;
381 *value = 0;
382 }
383
384 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) O VERRIDE
385 {
386 m_contextLost = true;
387 *value = 0;
388 }
389
390 virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE
391 {
392 return m_contextLost ? 1 : 0;
393 }
394
395 private:
396 bool m_contextLost;
397 };
398
399 TEST(GLRendererTest2, initializationWithQuicklyLostContextDoesNotAssert)
400 {
401 FakeRendererClient mockClient;
402 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new LoseContextOnFirstGetContext)));
403 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
404 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.g et());
405
406 renderer.Initialize();
407 }
408
409 class ContextThatDoesNotSupportMemoryManagmentExtensions : public TestWebGraphic sContext3D {
410 public:
411 ContextThatDoesNotSupportMemoryManagmentExtensions() { }
412
413 // WebGraphicsContext3D methods.
414
415 // This method would normally do a glSwapBuffers under the hood.
416 virtual void prepareTexture() { }
417 virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAll ocationChangedCallbackCHROMIUM* callback) { }
418 virtual WebString getString(WebKit::WGC3Denum name) { return WebString(); }
419 };
420
421 TEST(GLRendererTest2, initializationWithoutGpuMemoryManagerExtensionSupportShoul dDefaultToNonZeroAllocation)
422 {
423 FakeRendererClient mockClient;
424 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new ContextThatDoesNotSupportMemoryManagmentExt ensions)));
425 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
426 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.g et());
427
428 renderer.Initialize();
429
430 EXPECT_GT(mockClient.memoryAllocationLimitBytes(), 0ul);
431 }
432
433 class ClearCountingContext : public TestWebGraphicsContext3D {
434 public:
435 ClearCountingContext() : m_clear(0) { }
436
437 virtual void clear(WGC3Dbitfield)
438 {
439 m_clear++;
440 }
441
442 int clearCount() const { return m_clear; }
443
444 private:
445 int m_clear;
446 };
447
448 TEST(GLRendererTest2, opaqueBackground)
449 {
450 FakeRendererClient mockClient;
451 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
452 ClearCountingContext* context = static_cast<ClearCountingContext*>(outputSur face->context3d());
453 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
454 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.g et());
455
456 mockClient.root_render_pass()->has_transparent_background = false;
457
458 EXPECT_TRUE(renderer.Initialize());
459
460 renderer.DrawFrame(mockClient.renderPassesInDrawOrder());
461
462 // On DEBUG builds, render passes with opaque background clear to blue to
463 // easily see regions that were not drawn on the screen.
464 #ifdef NDEBUG
465 EXPECT_EQ(0, context->clearCount());
466 #else
467 EXPECT_EQ(1, context->clearCount());
468 #endif
469 }
470
471 TEST(GLRendererTest2, transparentBackground)
472 {
473 FakeRendererClient mockClient;
474 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
475 ClearCountingContext* context = static_cast<ClearCountingContext*>(outputSur face->context3d());
476 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
477 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.g et());
478
479 mockClient.root_render_pass()->has_transparent_background = true;
480
481 EXPECT_TRUE(renderer.Initialize());
482
483 renderer.DrawFrame(mockClient.renderPassesInDrawOrder());
484
485 EXPECT_EQ(1, context->clearCount());
486 }
487
488 class VisibilityChangeIsLastCallTrackingContext : public TestWebGraphicsContext3 D {
489 public:
490 VisibilityChangeIsLastCallTrackingContext()
491 : m_lastCallWasSetVisibility(0)
492 {
493 }
494
495 // WebGraphicsContext3D methods.
496 virtual void setVisibilityCHROMIUM(bool visible) {
497 if (!m_lastCallWasSetVisibility)
498 return;
499 DCHECK(*m_lastCallWasSetVisibility == false);
500 *m_lastCallWasSetVisibility = true;
501 }
502 virtual void flush() { if (m_lastCallWasSetVisibility) *m_lastCallWasSetVisi bility = false; }
503 virtual void deleteTexture(WebGLId) { if (m_lastCallWasSetVisibility) *m_las tCallWasSetVisibility = false; }
504 virtual void deleteFramebuffer(WebGLId) { if (m_lastCallWasSetVisibility) *m _lastCallWasSetVisibility = false; }
505 virtual void deleteRenderbuffer(WebGLId) { if (m_lastCallWasSetVisibility) * m_lastCallWasSetVisibility = false; }
506
507 // This method would normally do a glSwapBuffers under the hood.
508 virtual WebString getString(WebKit::WGC3Denum name)
509 {
510 if (name == GL_EXTENSIONS)
511 return WebString("GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_ manager GL_CHROMIUM_discard_backbuffer");
512 return WebString();
513 }
514
515 // Methods added for test.
516 void setLastCallWasSetVisibilityPointer(bool* lastCallWasSetVisibility) { m_ lastCallWasSetVisibility = lastCallWasSetVisibility; }
517
518 private:
519 bool* m_lastCallWasSetVisibility;
520 };
521
522 TEST(GLRendererTest2, visibilityChangeIsLastCall)
523 {
524 FakeRendererClient mockClient;
525 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new VisibilityChangeIsLastCallTrackingContext)) );
526 VisibilityChangeIsLastCallTrackingContext* context = static_cast<VisibilityC hangeIsLastCallTrackingContext*>(outputSurface->context3d());
527 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
528 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.g et());
529
530 EXPECT_TRUE(renderer.Initialize());
531
532 bool lastCallWasSetVisiblity = false;
533 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to t he GPU
534 // process, after glFlush is called, and after the RendererClient's enforceM anagedMemoryPolicy
535 // is called. Plumb this tracking between both the RenderClient and the Cont ext by giving
536 // them both a pointer to a variable on the stack.
537 context->setLastCallWasSetVisibilityPointer(&lastCallWasSetVisiblity);
538 mockClient.setLastCallWasSetVisibilityPointer(&lastCallWasSetVisiblity);
539 renderer.SetVisible(true);
540 renderer.DrawFrame(mockClient.renderPassesInDrawOrder());
541 renderer.SetVisible(false);
542 EXPECT_TRUE(lastCallWasSetVisiblity);
543 }
544
545 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
546 public:
547 TextureStateTrackingContext()
548 : m_activeTexture(GL_INVALID_ENUM)
549 {
550 }
551
552 virtual WebString getString(WGC3Denum name)
553 {
554 if (name == GL_EXTENSIONS)
555 return WebString("GL_OES_EGL_image_external");
556 return WebString();
557 }
558
559 MOCK_METHOD3(texParameteri, void(WGC3Denum target, WGC3Denum pname, WGC3Dint param));
560 MOCK_METHOD4(drawElements, void(WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset));
561
562 virtual void activeTexture(WGC3Denum texture)
563 {
564 EXPECT_NE(texture, m_activeTexture);
565 m_activeTexture = texture;
566 }
567
568 WGC3Denum activeTexture() const { return m_activeTexture; }
569
570 private:
571 WGC3Denum m_activeTexture;
572 };
573
574 TEST(GLRendererTest2, activeTextureState)
575 {
576 FakeRendererClient fakeClient;
577 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new TextureStateTrackingContext)));
578 TextureStateTrackingContext* context = static_cast<TextureStateTrackingConte xt*>(outputSurface->context3d());
579 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
580 FakeRendererGL renderer(&fakeClient, outputSurface.get(), resourceProvider.g et());
581
582 // During initialization we are allowed to set any texture parameters.
583 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
584 EXPECT_TRUE(renderer.Initialize());
585
586 cc::RenderPass::Id id(1, 1);
587 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
588 pass->SetNew(id, gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 100, 100), gfx:: Transform());
589 pass->AppendOneOfEveryQuadType(resourceProvider.get(), RenderPass::Id(2, 1)) ;
590
591 // Set up expected texture filter state transitions that match the quads
592 // created in AppendOneOfEveryQuadType().
593 Mock::VerifyAndClearExpectations(context);
594 {
595 InSequence sequence;
596
597 // yuv_quad is drawn with the default linear filter.
598 EXPECT_CALL(*context, drawElements(_, _, _, _));
599
600 // tile_quad is drawn with GL_NEAREST because it is not transformed or
601 // scaled.
602 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_NEAREST));
603 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_NEAREST));
604 EXPECT_CALL(*context, drawElements(_, _, _, _));
605
606 // transformed_tile_quad uses GL_LINEAR.
607 EXPECT_CALL(*context, drawElements(_, _, _, _));
608
609 // scaled_tile_quad also uses GL_LINEAR.
610 EXPECT_CALL(*context, drawElements(_, _, _, _));
611
612 // The remaining quads also use GL_LINEAR because nearest neighbor
613 // filtering is currently only used with tile quads.
614 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
615 }
616
617 cc::DirectRenderer::DrawingFrame drawingFrame;
618 renderer.BeginDrawingFrame(drawingFrame);
619 EXPECT_EQ(context->activeTexture(), GL_TEXTURE0);
620
621 for (cc::QuadList::backToFrontIterator it = pass->quad_list.backToFrontBegin ();
622 it != pass->quad_list.backToFrontEnd(); ++it) {
623 renderer.DoDrawQuad(drawingFrame, *it);
624 }
625 renderer.FinishDrawingQuadList();
626 EXPECT_EQ(context->activeTexture(), GL_TEXTURE0);
627 Mock::VerifyAndClearExpectations(context);
628 }
629
630 class NoClearRootRenderPassFakeClient : public FakeRendererClient {
631 public:
632 virtual bool ShouldClearRootRenderPass() const OVERRIDE { return false; }
633 };
634
635 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
636 public:
637 MOCK_METHOD1(clear, void(WGC3Dbitfield mask));
638 MOCK_METHOD4(drawElements, void(WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset));
639 };
640
641 TEST(GLRendererTest2, shouldClearRootRenderPass)
642 {
643 NoClearRootRenderPassFakeClient mockClient;
644 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new NoClearRootRenderPassMockContext)));
645 NoClearRootRenderPassMockContext* mockContext = static_cast<NoClearRootRende rPassMockContext*>(outputSurface->context3d());
646 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
647 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.g et());
648 EXPECT_TRUE(renderer.Initialize());
649
650 gfx::Rect viewportRect(mockClient.DeviceViewportSize());
651 ScopedPtrVector<RenderPass>& renderPasses = mockClient.renderPassesInDrawOrd er();
652 renderPasses.clear();
653
654 RenderPass::Id rootPassId(1, 0);
655 TestRenderPass* rootPass = addRenderPass(renderPasses, rootPassId, viewportR ect, gfx::Transform());
656 addQuad(rootPass, viewportRect, SK_ColorGREEN);
657
658 RenderPass::Id childPassId(2, 0);
659 TestRenderPass* childPass = addRenderPass(renderPasses, childPassId, viewpor tRect, gfx::Transform());
660 addQuad(childPass, viewportRect, SK_ColorBLUE);
661
662 addRenderPassQuad(rootPass, childPass);
663
664 // First render pass is not the root one, clearing should happen.
665 EXPECT_CALL(*mockContext, clear(GL_COLOR_BUFFER_BIT))
666 .Times(AtLeast(1));
667
668 Expectation firstRenderPass = EXPECT_CALL(*mockContext, drawElements(_, _, _ , _))
669 .Times(1);
670
671 // The second render pass is the root one, clearing should be prevented.
672 EXPECT_CALL(*mockContext, clear(GL_COLOR_BUFFER_BIT))
673 .Times(0)
674 .After(firstRenderPass);
675
676 EXPECT_CALL(*mockContext, drawElements(_, _, _, _))
677 .Times(AnyNumber())
678 .After(firstRenderPass);
679
680 renderer.DecideRenderPassAllocationsForFrame(mockClient.renderPassesInDrawOr der());
681 renderer.DrawFrame(mockClient.renderPassesInDrawOrder());
682
683 // In multiple render passes all but the root pass should clear the framebuf fer.
684 Mock::VerifyAndClearExpectations(&mockContext);
685 }
686
687 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
688 public:
689 ScissorTestOnClearCheckingContext() : m_scissorEnabled(false) { }
690
691 virtual void clear(WGC3Dbitfield)
692 {
693 EXPECT_FALSE(m_scissorEnabled);
694 }
695
696 virtual void enable(WGC3Denum cap)
697 {
698 if (cap == GL_SCISSOR_TEST)
699 m_scissorEnabled = true;
700 }
701
702 virtual void disable(WGC3Denum cap)
703 {
704 if (cap == GL_SCISSOR_TEST)
705 m_scissorEnabled = false;
706 }
707
708 private:
709 bool m_scissorEnabled;
710 };
711
712 TEST(GLRendererTest2, scissorTestWhenClearing) {
713 FakeRendererClient mockClient;
714 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_p tr<WebKit::WebGraphicsContext3D>(new ScissorTestOnClearCheckingContext)));
715 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::Create(outpu tSurface.get()));
716 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.g et());
717 EXPECT_TRUE(renderer.Initialize());
718 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
719
720 gfx::Rect viewportRect(mockClient.DeviceViewportSize());
721 ScopedPtrVector<RenderPass>& renderPasses = mockClient.renderPassesInDrawOrd er();
722 renderPasses.clear();
723
724 gfx::Rect grandChildRect(25, 25);
725 RenderPass::Id grandChildPassId(3, 0);
726 TestRenderPass* grandChildPass = addRenderPass(renderPasses, grandChildPassI d, grandChildRect, gfx::Transform());
727 addClippedQuad(grandChildPass, grandChildRect, SK_ColorYELLOW);
728
729 gfx::Rect childRect(50, 50);
730 RenderPass::Id childPassId(2, 0);
731 TestRenderPass* childPass = addRenderPass(renderPasses, childPassId, childRe ct, gfx::Transform());
732 addQuad(childPass, childRect, SK_ColorBLUE);
733
734 RenderPass::Id rootPassId(1, 0);
735 TestRenderPass* rootPass = addRenderPass(renderPasses, rootPassId, viewportR ect, gfx::Transform());
736 addQuad(rootPass, viewportRect, SK_ColorGREEN);
737
738 addRenderPassQuad(rootPass, childPass);
739 addRenderPassQuad(childPass, grandChildPass);
740
741 renderer.DecideRenderPassAllocationsForFrame(mockClient.renderPassesInDrawOr der());
742 renderer.DrawFrame(mockClient.renderPassesInDrawOrder());
743 }
744
745 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
746 public:
747 // Specifically override methods even if they are unused (used in conjunctio n with StrictMock).
748 // We need to make sure that GLRenderer does not issue framebuffer-related G L calls directly. Instead these
749 // are supposed to go through the OutputSurface abstraction.
750 MOCK_METHOD0(ensureBackbufferCHROMIUM, void());
751 MOCK_METHOD0(discardBackbufferCHROMIUM, void());
752 MOCK_METHOD2(bindFramebuffer, void(WGC3Denum target, WebGLId framebuffer));
753 MOCK_METHOD0(prepareTexture, void());
754 MOCK_METHOD2(reshape, void(int width, int height));
755 MOCK_METHOD4(drawElements, void(WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset));
756
757 virtual WebString getString(WebKit::WGC3Denum name)
758 {
759 if (name == GL_EXTENSIONS)
760 return WebString("GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_discard_ba ckbuffer");
761 return WebString();
762 }
763 };
764
765 class MockOutputSurface : public OutputSurface {
766 public:
767 MockOutputSurface()
768 : OutputSurface(scoped_ptr<WebKit::WebGraphicsContext3D>(new StrictMock< OutputSurfaceMockContext>)) { }
769 virtual ~MockOutputSurface() { }
770
771 MOCK_METHOD1(SendFrameToParentCompositor, void(CompositorFrame* frame));
772 MOCK_METHOD0(EnsureBackbuffer, void());
773 MOCK_METHOD0(DiscardBackbuffer, void());
774 MOCK_METHOD1(Reshape, void(gfx::Size size));
775 MOCK_METHOD0(BindFramebuffer, void());
776 MOCK_METHOD1(PostSubBuffer, void(gfx::Rect rect));
777 MOCK_METHOD0(SwapBuffers, void());
778 };
779
780 class MockOutputSurfaceTest : public testing::Test,
781 public FakeRendererClient {
782 protected:
783 MockOutputSurfaceTest()
784 : resource_provider_(ResourceProvider::Create(&m_outputSurface))
785 , m_renderer(this, &m_outputSurface, resource_provider_.get())
786 {
787 }
788
789 virtual void SetUp()
790 {
791 EXPECT_TRUE(m_renderer.Initialize());
792 }
793
794 void SwapBuffers()
795 {
796 m_renderer.SwapBuffers();
797 }
798
799 void DrawFrame()
800 {
801 gfx::Rect viewportRect(DeviceViewportSize());
802 ScopedPtrVector<RenderPass>& renderPasses = renderPassesInDrawOrder();
803 renderPasses.clear();
804
805 RenderPass::Id renderPassId(1, 0);
806 TestRenderPass* renderPass = addRenderPass(renderPasses, renderPassId, v iewportRect, gfx::Transform());
807 addQuad(renderPass, viewportRect, SK_ColorGREEN);
808
809 EXPECT_CALL(m_outputSurface, EnsureBackbuffer())
810 .WillRepeatedly(Return());
811
812 EXPECT_CALL(m_outputSurface, Reshape(_))
813 .Times(1);
814
815 EXPECT_CALL(m_outputSurface, BindFramebuffer())
816 .Times(1);
817
818 EXPECT_CALL(*context(), drawElements(_, _, _, _))
819 .Times(1);
820
821 m_renderer.DecideRenderPassAllocationsForFrame(renderPassesInDrawOrder() );
822 m_renderer.DrawFrame(renderPassesInDrawOrder());
823 }
824
825 OutputSurfaceMockContext* context() { return static_cast<OutputSurfaceMockCo ntext*>(m_outputSurface.context3d()); }
826
827 StrictMock<MockOutputSurface> m_outputSurface;
828 scoped_ptr<ResourceProvider> resource_provider_;
829 FakeRendererGL m_renderer;
830 };
831
832 TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap)
833 {
834 DrawFrame();
835
836 EXPECT_CALL(m_outputSurface, SwapBuffers())
837 .Times(1);
838 m_renderer.SwapBuffers();
839 }
840
841 class MockOutputSurfaceTestWithPartialSwap : public MockOutputSurfaceTest {
842 public:
843 virtual const LayerTreeSettings& Settings() const OVERRIDE
844 {
845 static LayerTreeSettings fakeSettings;
846 fakeSettings.partialSwapEnabled = true;
847 return fakeSettings;
848 }
849 };
850
851 TEST_F(MockOutputSurfaceTestWithPartialSwap, DrawFrameAndSwap)
852 {
853 DrawFrame();
854
855 EXPECT_CALL(m_outputSurface, PostSubBuffer(_))
856 .Times(1);
857 m_renderer.SwapBuffers();
858 }
859
860 class MockOutputSurfaceTestWithSendCompositorFrame : public MockOutputSurfaceTes t {
861 public:
862 virtual const LayerTreeSettings& Settings() const OVERRIDE
863 {
864 static LayerTreeSettings fakeSettings;
865 fakeSettings.compositorFrameMessage = true;
866 return fakeSettings;
867 }
868 };
869
870 TEST_F(MockOutputSurfaceTestWithSendCompositorFrame, DrawFrame)
871 {
872 EXPECT_CALL(m_outputSurface, SendFrameToParentCompositor(_))
873 .Times(1);
874 DrawFrame();
875 }
876
877 } // namespace
878 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698