Use TargetTransform instead of transform in ConvertPointFor/FromAncestor
[chromium-blink-merge.git] / cc / gl_renderer_unittest.cc
blob5a355ddd396a58e04263e42662ba439c58146243
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.
5 #include "cc/gl_renderer.h"
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/fake_web_graphics_context_3d.h"
15 #include "cc/test/render_pass_test_common.h"
16 #include "cc/test/render_pass_test_utils.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/khronos/GLES2/gl2.h"
20 #include "ui/gfx/transform.h"
22 using namespace WebKit;
24 using testing::_;
25 using testing::AnyNumber;
26 using testing::AtLeast;
27 using testing::Expectation;
28 using testing::InSequence;
29 using testing::Mock;
31 namespace cc {
32 namespace {
34 class FrameCountingMemoryAllocationSettingContext : public FakeWebGraphicsContext3D {
35 public:
36 FrameCountingMemoryAllocationSettingContext() : m_frame(0) { }
38 // WebGraphicsContext3D methods.
40 // This method would normally do a glSwapBuffers under the hood.
41 virtual void prepareTexture() { m_frame++; }
42 virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { m_memoryAllocationChangedCallback = callback; }
43 virtual WebString getString(WebKit::WGC3Denum name)
45 if (name == GL_EXTENSIONS)
46 return WebString("GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager GL_CHROMIUM_discard_backbuffer");
47 return WebString();
50 // Methods added for test.
51 int frameCount() { return m_frame; }
52 void setMemoryAllocation(WebGraphicsMemoryAllocation allocation)
54 m_memoryAllocationChangedCallback->onMemoryAllocationChanged(allocation);
57 private:
58 int m_frame;
59 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* m_memoryAllocationChangedCallback;
62 class FakeRendererClient : public RendererClient {
63 public:
64 FakeRendererClient()
65 : m_hostImpl(&m_proxy)
66 , m_setFullRootLayerDamageCount(0)
67 , m_lastCallWasSetVisibility(0)
68 , m_rootLayer(LayerImpl::create(m_hostImpl.activeTree(), 1))
69 , m_memoryAllocationLimitBytes(PrioritizedResourceManager::defaultMemoryAllocationLimit())
71 m_rootLayer->createRenderSurface();
72 RenderPass::Id renderPassId = m_rootLayer->renderSurface()->renderPassId();
73 scoped_ptr<RenderPass> rootRenderPass = RenderPass::Create();
74 rootRenderPass->SetNew(renderPassId, gfx::Rect(), gfx::Rect(), gfx::Transform());
75 m_renderPassesInDrawOrder.append(rootRenderPass.Pass());
78 // RendererClient methods.
79 virtual const gfx::Size& deviceViewportSize() const OVERRIDE { static gfx::Size fakeSize(1, 1); return fakeSize; }
80 virtual const LayerTreeSettings& settings() const OVERRIDE { static LayerTreeSettings fakeSettings; return fakeSettings; }
81 virtual void didLoseOutputSurface() OVERRIDE { }
82 virtual void onSwapBuffersComplete() OVERRIDE { }
83 virtual void setFullRootLayerDamage() OVERRIDE { m_setFullRootLayerDamageCount++; }
84 virtual void setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { m_memoryAllocationLimitBytes = policy.bytesLimitWhenVisible; }
85 virtual void enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { if (m_lastCallWasSetVisibility) *m_lastCallWasSetVisibility = false; }
86 virtual bool hasImplThread() const OVERRIDE { return false; }
87 virtual bool shouldClearRootRenderPass() const OVERRIDE { return true; }
88 virtual CompositorFrameMetadata makeCompositorFrameMetadata() const
89 OVERRIDE { return CompositorFrameMetadata(); }
91 // Methods added for test.
92 int setFullRootLayerDamageCount() const { return m_setFullRootLayerDamageCount; }
93 void setLastCallWasSetVisibilityPointer(bool* lastCallWasSetVisibility) { m_lastCallWasSetVisibility = lastCallWasSetVisibility; }
95 RenderPass* rootRenderPass() { return m_renderPassesInDrawOrder.last(); }
96 RenderPassList& renderPassesInDrawOrder() { return m_renderPassesInDrawOrder; }
98 size_t memoryAllocationLimitBytes() const { return m_memoryAllocationLimitBytes; }
100 private:
101 FakeImplProxy m_proxy;
102 FakeLayerTreeHostImpl m_hostImpl;
103 int m_setFullRootLayerDamageCount;
104 bool* m_lastCallWasSetVisibility;
105 scoped_ptr<LayerImpl> m_rootLayer;
106 RenderPassList m_renderPassesInDrawOrder;
107 size_t m_memoryAllocationLimitBytes;
110 class FakeRendererGL : public GLRenderer {
111 public:
112 FakeRendererGL(RendererClient* client, OutputSurface* outputSurface, ResourceProvider* resourceProvider) : GLRenderer(client, outputSurface, resourceProvider) { }
114 // GLRenderer methods.
116 // Changing visibility to public.
117 using GLRenderer::initialize;
118 using GLRenderer::isBackbufferDiscarded;
119 using GLRenderer::drawQuad;
120 using GLRenderer::beginDrawingFrame;
121 using GLRenderer::finishDrawingQuadList;
124 class GLRendererTest : public testing::Test {
125 protected:
126 GLRendererTest()
127 : m_suggestHaveBackbufferYes(1, true)
128 , m_suggestHaveBackbufferNo(1, false)
129 , m_outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new FrameCountingMemoryAllocationSettingContext())))
130 , m_resourceProvider(ResourceProvider::create(m_outputSurface.get()))
131 , m_renderer(&m_mockClient, m_outputSurface.get(), m_resourceProvider.get())
135 virtual void SetUp()
137 m_renderer.initialize();
140 void swapBuffers()
142 m_renderer.swapBuffers();
145 FrameCountingMemoryAllocationSettingContext* context() { return static_cast<FrameCountingMemoryAllocationSettingContext*>(m_outputSurface->Context3D()); }
147 WebGraphicsMemoryAllocation m_suggestHaveBackbufferYes;
148 WebGraphicsMemoryAllocation m_suggestHaveBackbufferNo;
150 scoped_ptr<OutputSurface> m_outputSurface;
151 FakeRendererClient m_mockClient;
152 scoped_ptr<ResourceProvider> m_resourceProvider;
153 FakeRendererGL m_renderer;
156 // Test GLRenderer discardBackbuffer functionality:
157 // Suggest recreating framebuffer when one already exists.
158 // Expected: it does nothing.
159 TEST_F(GLRendererTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing)
161 context()->setMemoryAllocation(m_suggestHaveBackbufferYes);
162 EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
163 EXPECT_FALSE(m_renderer.isBackbufferDiscarded());
165 swapBuffers();
166 EXPECT_EQ(1, context()->frameCount());
169 // Test GLRenderer discardBackbuffer functionality:
170 // Suggest discarding framebuffer when one exists and the renderer is not visible.
171 // Expected: it is discarded and damage tracker is reset.
172 TEST_F(GLRendererTest, SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerWhileNotVisible)
174 m_renderer.setVisible(false);
175 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
176 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
177 EXPECT_TRUE(m_renderer.isBackbufferDiscarded());
180 // Test GLRenderer discardBackbuffer functionality:
181 // Suggest discarding framebuffer when one exists and the renderer is visible.
182 // Expected: the allocation is ignored.
183 TEST_F(GLRendererTest, SuggestBackbufferNoDoNothingWhenVisible)
185 m_renderer.setVisible(true);
186 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
187 EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
188 EXPECT_FALSE(m_renderer.isBackbufferDiscarded());
192 // Test GLRenderer discardBackbuffer functionality:
193 // Suggest discarding framebuffer when one does not exist.
194 // Expected: it does nothing.
195 TEST_F(GLRendererTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing)
197 m_renderer.setVisible(false);
198 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
199 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
200 EXPECT_TRUE(m_renderer.isBackbufferDiscarded());
202 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
203 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
204 EXPECT_TRUE(m_renderer.isBackbufferDiscarded());
207 // Test GLRenderer discardBackbuffer functionality:
208 // Begin drawing a frame while a framebuffer is discarded.
209 // Expected: will recreate framebuffer.
210 TEST_F(GLRendererTest, DiscardedBackbufferIsRecreatedForScopeDuration)
212 m_renderer.setVisible(false);
213 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
214 EXPECT_TRUE(m_renderer.isBackbufferDiscarded());
215 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
217 m_renderer.setVisible(true);
218 m_renderer.drawFrame(m_mockClient.renderPassesInDrawOrder());
219 EXPECT_FALSE(m_renderer.isBackbufferDiscarded());
221 swapBuffers();
222 EXPECT_EQ(1, context()->frameCount());
225 TEST_F(GLRendererTest, FramebufferDiscardedAfterReadbackWhenNotVisible)
227 m_renderer.setVisible(false);
228 context()->setMemoryAllocation(m_suggestHaveBackbufferNo);
229 EXPECT_TRUE(m_renderer.isBackbufferDiscarded());
230 EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
232 char pixels[4];
233 m_renderer.drawFrame(m_mockClient.renderPassesInDrawOrder());
234 EXPECT_FALSE(m_renderer.isBackbufferDiscarded());
236 m_renderer.getFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
237 EXPECT_TRUE(m_renderer.isBackbufferDiscarded());
238 EXPECT_EQ(2, m_mockClient.setFullRootLayerDamageCount());
241 class ForbidSynchronousCallContext : public FakeWebGraphicsContext3D {
242 public:
243 ForbidSynchronousCallContext() { }
245 virtual bool getActiveAttrib(WebGLId program, WGC3Duint index, ActiveInfo&) { ADD_FAILURE(); return false; }
246 virtual bool getActiveUniform(WebGLId program, WGC3Duint index, ActiveInfo&) { ADD_FAILURE(); return false; }
247 virtual void getAttachedShaders(WebGLId program, WGC3Dsizei maxCount, WGC3Dsizei* count, WebGLId* shaders) { ADD_FAILURE(); }
248 virtual WGC3Dint getAttribLocation(WebGLId program, const WGC3Dchar* name) { ADD_FAILURE(); return 0; }
249 virtual void getBooleanv(WGC3Denum pname, WGC3Dboolean* value) { ADD_FAILURE(); }
250 virtual void getBufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
251 virtual Attributes getContextAttributes() { ADD_FAILURE(); return attributes_; }
252 virtual WGC3Denum getError() { ADD_FAILURE(); return 0; }
253 virtual void getFloatv(WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
254 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target, WGC3Denum attachment, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
255 virtual void getIntegerv(WGC3Denum pname, WGC3Dint* value)
257 if (pname == GL_MAX_TEXTURE_SIZE)
258 *value = 1024; // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
259 else
260 ADD_FAILURE();
263 // We allow querying the shader compilation and program link status in debug mode, but not release.
264 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value)
266 #ifndef NDEBUG
267 *value = 1;
268 #else
269 ADD_FAILURE();
270 #endif
273 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value)
275 #ifndef NDEBUG
276 *value = 1;
277 #else
278 ADD_FAILURE();
279 #endif
282 virtual WebString getString(WGC3Denum name)
284 // We allow querying the extension string.
285 // FIXME: It'd be better to check that we only do this before starting any other expensive work (like starting a compilation)
286 if (name != GL_EXTENSIONS)
287 ADD_FAILURE();
288 return WebString();
291 virtual WebString getProgramInfoLog(WebGLId program) { ADD_FAILURE(); return WebString(); }
292 virtual void getRenderbufferParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
294 virtual WebString getShaderInfoLog(WebGLId shader) { ADD_FAILURE(); return WebString(); }
295 virtual void getShaderPrecisionFormat(WGC3Denum shadertype, WGC3Denum precisiontype, WGC3Dint* range, WGC3Dint* precision) { ADD_FAILURE(); }
296 virtual WebString getShaderSource(WebGLId shader) { ADD_FAILURE(); return WebString(); }
297 virtual void getTexParameterfv(WGC3Denum target, WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
298 virtual void getTexParameteriv(WGC3Denum target, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
299 virtual void getUniformfv(WebGLId program, WGC3Dint location, WGC3Dfloat* value) { ADD_FAILURE(); }
300 virtual void getUniformiv(WebGLId program, WGC3Dint location, WGC3Dint* value) { ADD_FAILURE(); }
301 virtual WGC3Dint getUniformLocation(WebGLId program, const WGC3Dchar* name) { ADD_FAILURE(); return 0; }
302 virtual void getVertexAttribfv(WGC3Duint index, WGC3Denum pname, WGC3Dfloat* value) { ADD_FAILURE(); }
303 virtual void getVertexAttribiv(WGC3Duint index, WGC3Denum pname, WGC3Dint* value) { ADD_FAILURE(); }
304 virtual WGC3Dsizeiptr getVertexAttribOffset(WGC3Duint index, WGC3Denum pname) { ADD_FAILURE(); return 0; }
307 // This test isn't using the same fixture as GLRendererTest, and you can't mix TEST() and TEST_F() with the same name, hence LRC2.
308 TEST(GLRendererTest2, initializationDoesNotMakeSynchronousCalls)
310 FakeRendererClient mockClient;
311 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new ForbidSynchronousCallContext)));
312 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
313 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.get());
315 EXPECT_TRUE(renderer.initialize());
318 class LoseContextOnFirstGetContext : public FakeWebGraphicsContext3D {
319 public:
320 LoseContextOnFirstGetContext()
321 : m_contextLost(false)
325 virtual bool makeContextCurrent() OVERRIDE
327 return !m_contextLost;
330 virtual void getProgramiv(WebGLId program, WGC3Denum pname, WGC3Dint* value) OVERRIDE
332 m_contextLost = true;
333 *value = 0;
336 virtual void getShaderiv(WebGLId shader, WGC3Denum pname, WGC3Dint* value) OVERRIDE
338 m_contextLost = true;
339 *value = 0;
342 virtual WGC3Denum getGraphicsResetStatusARB() OVERRIDE
344 return m_contextLost ? 1 : 0;
347 private:
348 bool m_contextLost;
351 TEST(GLRendererTest2, initializationWithQuicklyLostContextDoesNotAssert)
353 FakeRendererClient mockClient;
354 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new LoseContextOnFirstGetContext)));
355 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
356 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.get());
358 renderer.initialize();
361 class ContextThatDoesNotSupportMemoryManagmentExtensions : public FakeWebGraphicsContext3D {
362 public:
363 ContextThatDoesNotSupportMemoryManagmentExtensions() { }
365 // WebGraphicsContext3D methods.
367 // This method would normally do a glSwapBuffers under the hood.
368 virtual void prepareTexture() { }
369 virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { }
370 virtual WebString getString(WebKit::WGC3Denum name) { return WebString(); }
373 TEST(GLRendererTest2, initializationWithoutGpuMemoryManagerExtensionSupportShouldDefaultToNonZeroAllocation)
375 FakeRendererClient mockClient;
376 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new ContextThatDoesNotSupportMemoryManagmentExtensions)));
377 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
378 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.get());
380 renderer.initialize();
382 EXPECT_GT(mockClient.memoryAllocationLimitBytes(), 0ul);
385 class ClearCountingContext : public FakeWebGraphicsContext3D {
386 public:
387 ClearCountingContext() : m_clear(0) { }
389 virtual void clear(WGC3Dbitfield)
391 m_clear++;
394 int clearCount() const { return m_clear; }
396 private:
397 int m_clear;
400 TEST(GLRendererTest2, opaqueBackground)
402 FakeRendererClient mockClient;
403 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
404 ClearCountingContext* context = static_cast<ClearCountingContext*>(outputSurface->Context3D());
405 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
406 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.get());
408 mockClient.rootRenderPass()->has_transparent_background = false;
410 EXPECT_TRUE(renderer.initialize());
412 renderer.drawFrame(mockClient.renderPassesInDrawOrder());
414 // On DEBUG builds, render passes with opaque background clear to blue to
415 // easily see regions that were not drawn on the screen.
416 #ifdef NDEBUG
417 EXPECT_EQ(0, context->clearCount());
418 #else
419 EXPECT_EQ(1, context->clearCount());
420 #endif
423 TEST(GLRendererTest2, transparentBackground)
425 FakeRendererClient mockClient;
426 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new ClearCountingContext)));
427 ClearCountingContext* context = static_cast<ClearCountingContext*>(outputSurface->Context3D());
428 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
429 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.get());
431 mockClient.rootRenderPass()->has_transparent_background = true;
433 EXPECT_TRUE(renderer.initialize());
435 renderer.drawFrame(mockClient.renderPassesInDrawOrder());
437 EXPECT_EQ(1, context->clearCount());
440 class VisibilityChangeIsLastCallTrackingContext : public FakeWebGraphicsContext3D {
441 public:
442 VisibilityChangeIsLastCallTrackingContext()
443 : m_lastCallWasSetVisibility(0)
447 // WebGraphicsContext3D methods.
448 virtual void setVisibilityCHROMIUM(bool visible) {
449 if (!m_lastCallWasSetVisibility)
450 return;
451 DCHECK(*m_lastCallWasSetVisibility == false);
452 *m_lastCallWasSetVisibility = true;
454 virtual void flush() { if (m_lastCallWasSetVisibility) *m_lastCallWasSetVisibility = false; }
455 virtual void deleteTexture(WebGLId) { if (m_lastCallWasSetVisibility) *m_lastCallWasSetVisibility = false; }
456 virtual void deleteFramebuffer(WebGLId) { if (m_lastCallWasSetVisibility) *m_lastCallWasSetVisibility = false; }
457 virtual void deleteRenderbuffer(WebGLId) { if (m_lastCallWasSetVisibility) *m_lastCallWasSetVisibility = false; }
459 // This method would normally do a glSwapBuffers under the hood.
460 virtual WebString getString(WebKit::WGC3Denum name)
462 if (name == GL_EXTENSIONS)
463 return WebString("GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager GL_CHROMIUM_discard_backbuffer");
464 return WebString();
467 // Methods added for test.
468 void setLastCallWasSetVisibilityPointer(bool* lastCallWasSetVisibility) { m_lastCallWasSetVisibility = lastCallWasSetVisibility; }
470 private:
471 bool* m_lastCallWasSetVisibility;
474 TEST(GLRendererTest2, visibilityChangeIsLastCall)
476 FakeRendererClient mockClient;
477 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new VisibilityChangeIsLastCallTrackingContext)));
478 VisibilityChangeIsLastCallTrackingContext* context = static_cast<VisibilityChangeIsLastCallTrackingContext*>(outputSurface->Context3D());
479 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
480 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.get());
482 EXPECT_TRUE(renderer.initialize());
484 bool lastCallWasSetVisiblity = false;
485 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the GPU
486 // process, after glFlush is called, and after the RendererClient's enforceManagedMemoryPolicy
487 // is called. Plumb this tracking between both the RenderClient and the Context by giving
488 // them both a pointer to a variable on the stack.
489 context->setLastCallWasSetVisibilityPointer(&lastCallWasSetVisiblity);
490 mockClient.setLastCallWasSetVisibilityPointer(&lastCallWasSetVisiblity);
491 renderer.setVisible(true);
492 renderer.drawFrame(mockClient.renderPassesInDrawOrder());
493 renderer.setVisible(false);
494 EXPECT_TRUE(lastCallWasSetVisiblity);
497 class TextureStateTrackingContext : public FakeWebGraphicsContext3D {
498 public:
499 TextureStateTrackingContext()
500 : m_activeTexture(GL_INVALID_ENUM)
504 virtual WebString getString(WGC3Denum name)
506 if (name == GL_EXTENSIONS)
507 return WebString("GL_OES_EGL_image_external");
508 return WebString();
511 MOCK_METHOD3(texParameteri, void(WGC3Denum target, WGC3Denum pname, WGC3Dint param));
512 MOCK_METHOD4(drawElements, void(WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset));
514 virtual void activeTexture(WGC3Denum texture)
516 EXPECT_NE(texture, m_activeTexture);
517 m_activeTexture = texture;
520 WGC3Denum activeTexture() const { return m_activeTexture; }
522 private:
523 WGC3Denum m_activeTexture;
526 TEST(GLRendererTest2, activeTextureState)
528 FakeRendererClient fakeClient;
529 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new TextureStateTrackingContext)));
530 TextureStateTrackingContext* context = static_cast<TextureStateTrackingContext*>(outputSurface->Context3D());
531 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
532 FakeRendererGL renderer(&fakeClient, outputSurface.get(), resourceProvider.get());
534 // During initialization we are allowed to set any texture parameters.
535 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
536 EXPECT_TRUE(renderer.initialize());
538 cc::RenderPass::Id id(1, 1);
539 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
540 pass->SetNew(id, gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 0, 100, 100), gfx::Transform());
541 pass->AppendOneOfEveryQuadType(resourceProvider.get());
543 // Set up expected texture filter state transitions that match the quads
544 // created in AppendOneOfEveryQuadType().
545 Mock::VerifyAndClearExpectations(context);
547 InSequence sequence;
549 // yuv_quad is drawn with the default filter.
550 EXPECT_CALL(*context, drawElements(_, _, _, _));
552 // tile_quad is drawn with GL_NEAREST because it is not transformed or
553 // scaled.
554 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
555 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
556 EXPECT_CALL(*context, drawElements(_, _, _, _));
558 // transformed_tile_quad uses GL_LINEAR.
559 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
560 EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
561 EXPECT_CALL(*context, drawElements(_, _, _, _));
563 // scaled_tile_quad also uses GL_LINEAR.
564 EXPECT_CALL(*context, drawElements(_, _, _, _));
566 // The remaining quads also use GL_LINEAR because nearest neighbor
567 // filtering is currently only used with tile quads.
568 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
571 cc::DirectRenderer::DrawingFrame drawingFrame;
572 renderer.beginDrawingFrame(drawingFrame);
573 EXPECT_EQ(context->activeTexture(), GL_TEXTURE0);
575 for (cc::QuadList::backToFrontIterator it = pass->quad_list.backToFrontBegin();
576 it != pass->quad_list.backToFrontEnd(); ++it) {
577 renderer.drawQuad(drawingFrame, *it);
579 renderer.finishDrawingQuadList();
580 EXPECT_EQ(context->activeTexture(), GL_TEXTURE0);
581 Mock::VerifyAndClearExpectations(context);
584 class NoClearRootRenderPassFakeClient : public FakeRendererClient {
585 public:
586 virtual bool shouldClearRootRenderPass() const { return false; }
589 class NoClearRootRenderPassMockContext : public FakeWebGraphicsContext3D {
590 public:
591 MOCK_METHOD1(clear, void(WGC3Dbitfield mask));
592 MOCK_METHOD4(drawElements, void(WGC3Denum mode, WGC3Dsizei count, WGC3Denum type, WGC3Dintptr offset));
595 TEST(GLRendererTest2, shouldClearRootRenderPass)
597 NoClearRootRenderPassFakeClient mockClient;
598 scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new NoClearRootRenderPassMockContext)));
599 NoClearRootRenderPassMockContext* mockContext = static_cast<NoClearRootRenderPassMockContext*>(outputSurface->Context3D());
600 scoped_ptr<ResourceProvider> resourceProvider(ResourceProvider::create(outputSurface.get()));
601 FakeRendererGL renderer(&mockClient, outputSurface.get(), resourceProvider.get());
602 EXPECT_TRUE(renderer.initialize());
604 gfx::Rect viewportRect(mockClient.deviceViewportSize());
605 ScopedPtrVector<RenderPass>& renderPasses = mockClient.renderPassesInDrawOrder();
606 renderPasses.clear();
608 RenderPass::Id rootPassId(1, 0);
609 TestRenderPass* rootPass = addRenderPass(renderPasses, rootPassId, viewportRect, gfx::Transform());
610 addQuad(rootPass, viewportRect, SK_ColorGREEN);
612 RenderPass::Id childPassId(2, 0);
613 TestRenderPass* childPass = addRenderPass(renderPasses, childPassId, viewportRect, gfx::Transform());
614 addQuad(childPass, viewportRect, SK_ColorBLUE);
616 addRenderPassQuad(rootPass, childPass);
618 // First render pass is not the root one, clearing should happen.
619 EXPECT_CALL(*mockContext, clear(GL_COLOR_BUFFER_BIT))
620 .Times(AtLeast(1));
622 Expectation firstRenderPass = EXPECT_CALL(*mockContext, drawElements(_, _, _, _))
623 .Times(1);
625 // The second render pass is the root one, clearing should be prevented.
626 EXPECT_CALL(*mockContext, clear(GL_COLOR_BUFFER_BIT))
627 .Times(0)
628 .After(firstRenderPass);
630 EXPECT_CALL(*mockContext, drawElements(_, _, _, _))
631 .Times(AnyNumber())
632 .After(firstRenderPass);
634 renderer.decideRenderPassAllocationsForFrame(mockClient.renderPassesInDrawOrder());
635 renderer.drawFrame(mockClient.renderPassesInDrawOrder());
637 // In multiple render passes all but the root pass should clear the framebuffer.
638 Mock::VerifyAndClearExpectations(&mockContext);
641 } // namespace
642 } // namespace cc