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/output/gl_renderer.h"
7 #include "cc/output/compositor_frame_metadata.h"
8 #include "cc/resources/prioritized_resource_manager.h"
9 #include "cc/resources/resource_provider.h"
10 #include "cc/test/fake_impl_proxy.h"
11 #include "cc/test/fake_layer_tree_host_impl.h"
12 #include "cc/test/fake_output_surface.h"
13 #include "cc/test/mock_quad_culler.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 "third_party/skia/include/core/SkImageFilter.h"
22 #include "third_party/skia/include/core/SkMatrix.h"
23 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
24 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
25 #include "ui/gfx/transform.h"
28 using testing::AnyNumber
;
29 using testing::AtLeast
;
30 using testing::Expectation
;
31 using testing::InSequence
;
33 using testing::Return
;
34 using testing::StrictMock
;
35 using WebKit::WebGraphicsMemoryAllocation
;
36 using WebKit::WebGLId
;
37 using WebKit::WebString
;
38 using WebKit::WGC3Dbitfield
;
39 using WebKit::WGC3Dboolean
;
40 using WebKit::WGC3Dchar
;
41 using WebKit::WGC3Denum
;
42 using WebKit::WGC3Dfloat
;
43 using WebKit::WGC3Dint
;
44 using WebKit::WGC3Dintptr
;
45 using WebKit::WGC3Dsizei
;
46 using WebKit::WGC3Dsizeiptr
;
47 using WebKit::WGC3Duint
;
51 #define EXPECT_PROGRAM_VALID(program_binding) \
53 EXPECT_TRUE(program_binding->program()); \
54 EXPECT_TRUE(program_binding->initialized()); \
57 // Explicitly named to be a friend in GLRenderer for shader access.
58 class GLRendererShaderPixelTest
: public PixelTest
{
61 ASSERT_FALSE(renderer_
->IsContextLost());
62 EXPECT_PROGRAM_VALID(renderer_
->GetTileProgram());
63 EXPECT_PROGRAM_VALID(renderer_
->GetTileProgramOpaque());
64 EXPECT_PROGRAM_VALID(renderer_
->GetTileProgramAA());
65 EXPECT_PROGRAM_VALID(renderer_
->GetTileProgramSwizzle());
66 EXPECT_PROGRAM_VALID(renderer_
->GetTileProgramSwizzleOpaque());
67 EXPECT_PROGRAM_VALID(renderer_
->GetTileProgramSwizzleAA());
68 EXPECT_PROGRAM_VALID(renderer_
->GetTileCheckerboardProgram());
69 EXPECT_PROGRAM_VALID(renderer_
->GetDebugBorderProgram());
70 EXPECT_PROGRAM_VALID(renderer_
->GetSolidColorProgram());
71 EXPECT_PROGRAM_VALID(renderer_
->GetSolidColorProgramAA());
72 //TestShadersWithTexCoordPrecision(TexCoordPrecisionMedium);
73 TestShadersWithTexCoordPrecision(TexCoordPrecisionHigh
);
74 ASSERT_FALSE(renderer_
->IsContextLost());
77 void TestShadersWithTexCoordPrecision(TexCoordPrecision precision
) {
78 EXPECT_PROGRAM_VALID(renderer_
->GetRenderPassProgram(precision
));
79 EXPECT_PROGRAM_VALID(renderer_
->GetRenderPassProgramAA(precision
));
80 EXPECT_PROGRAM_VALID(renderer_
->GetRenderPassMaskProgram(precision
));
81 EXPECT_PROGRAM_VALID(renderer_
->GetRenderPassMaskProgramAA(precision
));
83 renderer_
->GetRenderPassColorMatrixProgram(precision
));
85 renderer_
->GetRenderPassMaskColorMatrixProgramAA(precision
));
87 renderer_
->GetRenderPassColorMatrixProgramAA(precision
));
89 renderer_
->GetRenderPassMaskColorMatrixProgram(precision
));
90 EXPECT_PROGRAM_VALID(renderer_
->GetTextureProgram(precision
));
91 EXPECT_PROGRAM_VALID(renderer_
->GetTextureProgramFlip(precision
));
92 EXPECT_PROGRAM_VALID(renderer_
->GetTextureIOSurfaceProgram(precision
));
93 EXPECT_PROGRAM_VALID(renderer_
->GetVideoYUVProgram(precision
));
94 // This is unlikely to be ever true in tests due to usage of osmesa.
95 if (renderer_
->Capabilities().using_egl_image
)
96 EXPECT_PROGRAM_VALID(renderer_
->GetVideoStreamTextureProgram(precision
));
98 EXPECT_FALSE(renderer_
->GetVideoStreamTextureProgram(precision
));
104 #if !defined(OS_ANDROID)
105 TEST_F(GLRendererShaderPixelTest
, AllShadersCompile
) { TestShaders(); }
108 class FrameCountingMemoryAllocationSettingContext
109 : public TestWebGraphicsContext3D
{
111 FrameCountingMemoryAllocationSettingContext() : frame_(0) {}
113 // WebGraphicsContext3D methods.
115 // This method would normally do a glSwapBuffers under the hood.
116 virtual void prepareTexture() { frame_
++; }
117 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
118 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM
* callback
) {
119 memory_allocation_changed_callback_
= callback
;
121 virtual WebString
getString(WebKit::WGC3Denum name
) {
122 if (name
== GL_EXTENSIONS
)
124 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
125 "GL_CHROMIUM_discard_backbuffer");
129 // Methods added for test.
130 int frame_count() { return frame_
; }
131 void SetMemoryAllocation(WebGraphicsMemoryAllocation allocation
) {
132 memory_allocation_changed_callback_
->onMemoryAllocationChanged(allocation
);
137 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM
*
138 memory_allocation_changed_callback_
;
141 class FakeRendererClient
: public RendererClient
{
144 : host_impl_(&proxy_
),
145 set_full_root_layer_damage_count_(0),
146 last_call_was_set_visibility_(0),
147 root_layer_(LayerImpl::Create(host_impl_
.active_tree(), 1)),
148 memory_allocation_limit_bytes_(
149 PrioritizedResourceManager::DefaultMemoryAllocationLimit()) {
150 root_layer_
->CreateRenderSurface();
151 RenderPass::Id render_pass_id
=
152 root_layer_
->render_surface()->RenderPassId();
153 scoped_ptr
<RenderPass
> root_render_pass
= RenderPass::Create();
154 root_render_pass
->SetNew(
155 render_pass_id
, gfx::Rect(), gfx::Rect(), gfx::Transform());
156 render_passes_in_draw_order_
.push_back(root_render_pass
.Pass());
159 // RendererClient methods.
160 virtual gfx::Size
DeviceViewportSize() const OVERRIDE
{
161 static gfx::Size
fake_size(1, 1);
164 virtual const LayerTreeSettings
& Settings() const OVERRIDE
{
165 static LayerTreeSettings fake_settings
;
166 return fake_settings
;
168 virtual void DidLoseOutputSurface() OVERRIDE
{}
169 virtual void OnSwapBuffersComplete() OVERRIDE
{}
170 virtual void SetFullRootLayerDamage() OVERRIDE
{
171 set_full_root_layer_damage_count_
++;
173 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
175 memory_allocation_limit_bytes_
= policy
.bytes_limit_when_visible
;
177 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
179 if (last_call_was_set_visibility_
)
180 *last_call_was_set_visibility_
= false;
182 virtual bool HasImplThread() const OVERRIDE
{ return false; }
183 virtual bool ShouldClearRootRenderPass() const OVERRIDE
{ return true; }
184 virtual CompositorFrameMetadata
MakeCompositorFrameMetadata() const OVERRIDE
{
185 return CompositorFrameMetadata();
187 virtual bool AllowPartialSwap() const OVERRIDE
{
191 // Methods added for test.
192 int set_full_root_layer_damage_count() const {
193 return set_full_root_layer_damage_count_
;
195 void set_last_call_was_set_visibility_pointer(
196 bool* last_call_was_set_visibility
) {
197 last_call_was_set_visibility_
= last_call_was_set_visibility
;
200 RenderPass
* root_render_pass() { return render_passes_in_draw_order_
.back(); }
201 RenderPassList
* render_passes_in_draw_order() {
202 return &render_passes_in_draw_order_
;
205 size_t memory_allocation_limit_bytes() const {
206 return memory_allocation_limit_bytes_
;
210 FakeImplProxy proxy_
;
211 FakeLayerTreeHostImpl host_impl_
;
212 int set_full_root_layer_damage_count_
;
213 bool* last_call_was_set_visibility_
;
214 scoped_ptr
<LayerImpl
> root_layer_
;
215 RenderPassList render_passes_in_draw_order_
;
216 size_t memory_allocation_limit_bytes_
;
219 class FakeRendererGL
: public GLRenderer
{
221 FakeRendererGL(RendererClient
* client
,
222 OutputSurface
* output_surface
,
223 ResourceProvider
* resource_provider
)
224 : GLRenderer(client
, output_surface
, resource_provider
, 0) {}
226 // GLRenderer methods.
228 // Changing visibility to public.
229 using GLRenderer::Initialize
;
230 using GLRenderer::IsBackbufferDiscarded
;
231 using GLRenderer::DoDrawQuad
;
232 using GLRenderer::BeginDrawingFrame
;
233 using GLRenderer::FinishDrawingQuadList
;
236 class GLRendererTest
: public testing::Test
{
239 : suggest_have_backbuffer_yes_(1, true),
240 suggest_have_backbuffer_no_(1, false),
241 output_surface_(FakeOutputSurface::Create3d(
242 scoped_ptr
<WebKit::WebGraphicsContext3D
>(
243 new FrameCountingMemoryAllocationSettingContext()))),
244 resource_provider_(ResourceProvider::Create(output_surface_
.get(), 0)),
245 renderer_(&mock_client_
,
246 output_surface_
.get(),
247 resource_provider_
.get()) {}
249 virtual void SetUp() { renderer_
.Initialize(); }
251 void SwapBuffers() { renderer_
.SwapBuffers(); }
253 FrameCountingMemoryAllocationSettingContext
* context() {
254 return static_cast<FrameCountingMemoryAllocationSettingContext
*>(
255 output_surface_
->context3d());
258 WebGraphicsMemoryAllocation suggest_have_backbuffer_yes_
;
259 WebGraphicsMemoryAllocation suggest_have_backbuffer_no_
;
261 scoped_ptr
<OutputSurface
> output_surface_
;
262 FakeRendererClient mock_client_
;
263 scoped_ptr
<ResourceProvider
> resource_provider_
;
264 FakeRendererGL renderer_
;
267 // Closing the namespace here so that GLRendererShaderTest can take advantage
268 // of the friend relationship with GLRenderer and all of the mock classes
269 // declared above it.
272 class GLRendererShaderTest
: public testing::Test
{
274 GLRendererShaderTest()
275 : output_surface_(FakeOutputSurface::Create3d()),
276 resource_provider_(ResourceProvider::Create(output_surface_
.get(), 0)),
277 renderer_(GLRenderer::Create(&mock_client_
, output_surface_
.get(),
278 resource_provider_
.get(), 0)) {
281 void TestRenderPassProgram() {
282 EXPECT_PROGRAM_VALID(renderer_
->render_pass_program_
);
283 EXPECT_TRUE(renderer_
->program_shadow_
==
284 renderer_
->render_pass_program_
->program());
287 void TestRenderPassColorMatrixProgram() {
288 EXPECT_PROGRAM_VALID(renderer_
->render_pass_color_matrix_program_
);
289 EXPECT_TRUE(renderer_
->program_shadow_
==
290 renderer_
->render_pass_color_matrix_program_
->program());
293 void TestRenderPassMaskProgram() {
294 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_program_
);
295 EXPECT_TRUE(renderer_
->program_shadow_
==
296 renderer_
->render_pass_mask_program_
->program());
299 void TestRenderPassMaskColorMatrixProgram() {
300 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_color_matrix_program_
);
301 EXPECT_TRUE(renderer_
->program_shadow_
==
302 renderer_
->render_pass_mask_color_matrix_program_
->program());
305 void TestRenderPassProgramAA() {
306 EXPECT_PROGRAM_VALID(renderer_
->render_pass_program_aa_
);
307 EXPECT_TRUE(renderer_
->program_shadow_
==
308 renderer_
->render_pass_program_aa_
->program());
311 void TestRenderPassColorMatrixProgramAA() {
312 EXPECT_PROGRAM_VALID(renderer_
->render_pass_color_matrix_program_aa_
);
313 EXPECT_TRUE(renderer_
->program_shadow_
==
314 renderer_
->render_pass_color_matrix_program_aa_
->program());
317 void TestRenderPassMaskProgramAA() {
318 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_program_
);
319 EXPECT_TRUE(renderer_
->program_shadow_
==
320 renderer_
->render_pass_program_aa_
->program());
323 void TestRenderPassMaskColorMatrixProgramAA() {
324 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_color_matrix_program_aa_
);
325 EXPECT_TRUE(renderer_
->program_shadow_
==
326 renderer_
->render_pass_color_matrix_program_aa_
->program());
329 scoped_ptr
<OutputSurface
> output_surface_
;
330 FakeRendererClient mock_client_
;
331 scoped_ptr
<ResourceProvider
> resource_provider_
;
332 scoped_ptr
<GLRenderer
> renderer_
;
337 // Test GLRenderer discardBackbuffer functionality:
338 // Suggest recreating framebuffer when one already exists.
339 // Expected: it does nothing.
340 TEST_F(GLRendererTest
, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing
) {
341 context()->SetMemoryAllocation(suggest_have_backbuffer_yes_
);
342 EXPECT_EQ(0, mock_client_
.set_full_root_layer_damage_count());
343 EXPECT_FALSE(renderer_
.IsBackbufferDiscarded());
346 EXPECT_EQ(1, context()->frame_count());
349 // Test GLRenderer DiscardBackbuffer functionality:
350 // Suggest discarding framebuffer when one exists and the renderer is not
352 // Expected: it is discarded and damage tracker is reset.
355 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible
) {
356 renderer_
.SetVisible(false);
357 context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
358 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
359 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
362 // Test GLRenderer DiscardBackbuffer functionality:
363 // Suggest discarding framebuffer when one exists and the renderer is visible.
364 // Expected: the allocation is ignored.
365 TEST_F(GLRendererTest
, SuggestBackbufferNoDoNothingWhenVisible
) {
366 renderer_
.SetVisible(true);
367 context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
368 EXPECT_EQ(0, mock_client_
.set_full_root_layer_damage_count());
369 EXPECT_FALSE(renderer_
.IsBackbufferDiscarded());
372 // Test GLRenderer DiscardBackbuffer functionality:
373 // Suggest discarding framebuffer when one does not exist.
374 // Expected: it does nothing.
375 TEST_F(GLRendererTest
, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing
) {
376 renderer_
.SetVisible(false);
377 context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
378 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
379 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
381 context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
382 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
383 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
386 // Test GLRenderer DiscardBackbuffer functionality:
387 // Begin drawing a frame while a framebuffer is discarded.
388 // Expected: will recreate framebuffer.
389 TEST_F(GLRendererTest
, DiscardedBackbufferIsRecreatedForScopeDuration
) {
390 renderer_
.SetVisible(false);
391 context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
392 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
393 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
395 renderer_
.SetVisible(true);
396 renderer_
.DrawFrame(mock_client_
.render_passes_in_draw_order());
397 EXPECT_FALSE(renderer_
.IsBackbufferDiscarded());
400 EXPECT_EQ(1, context()->frame_count());
403 TEST_F(GLRendererTest
, FramebufferDiscardedAfterReadbackWhenNotVisible
) {
404 renderer_
.SetVisible(false);
405 context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
406 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
407 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
410 renderer_
.DrawFrame(mock_client_
.render_passes_in_draw_order());
411 EXPECT_FALSE(renderer_
.IsBackbufferDiscarded());
413 renderer_
.GetFramebufferPixels(pixels
, gfx::Rect(0, 0, 1, 1));
414 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
415 EXPECT_EQ(2, mock_client_
.set_full_root_layer_damage_count());
418 class ForbidSynchronousCallContext
: public TestWebGraphicsContext3D
{
420 ForbidSynchronousCallContext() {}
422 virtual bool getActiveAttrib(WebGLId program
,
428 virtual bool getActiveUniform(WebGLId program
,
434 virtual void getAttachedShaders(WebGLId program
,
435 WGC3Dsizei max_count
,
440 virtual WGC3Dint
getAttribLocation(WebGLId program
, const WGC3Dchar
* name
) {
444 virtual void getBooleanv(WGC3Denum pname
, WGC3Dboolean
* value
) {
447 virtual void getBufferParameteriv(WGC3Denum target
,
452 virtual Attributes
getContextAttributes() {
456 virtual WGC3Denum
getError() {
460 virtual void getFloatv(WGC3Denum pname
, WGC3Dfloat
* value
) { ADD_FAILURE(); }
461 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target
,
462 WGC3Denum attachment
,
467 virtual void getIntegerv(WGC3Denum pname
, WGC3Dint
* value
) {
468 if (pname
== GL_MAX_TEXTURE_SIZE
) {
469 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
476 // We allow querying the shader compilation and program link status in debug
477 // mode, but not release.
478 virtual void getProgramiv(WebGLId program
, WGC3Denum pname
, WGC3Dint
* value
) {
486 virtual void getShaderiv(WebGLId shader
, WGC3Denum pname
, WGC3Dint
* value
) {
494 virtual WebString
getString(WGC3Denum name
) {
495 // We allow querying the extension string.
496 // FIXME: It'd be better to check that we only do this before starting any
497 // other expensive work (like starting a compilation)
498 if (name
!= GL_EXTENSIONS
)
503 virtual WebString
getProgramInfoLog(WebGLId program
) {
507 virtual void getRenderbufferParameteriv(WGC3Denum target
,
513 virtual WebString
getShaderInfoLog(WebGLId shader
) {
517 virtual void getShaderPrecisionFormat(WGC3Denum shadertype
,
518 WGC3Denum precisiontype
,
520 WGC3Dint
* precision
) {
523 virtual WebString
getShaderSource(WebGLId shader
) {
527 virtual void getTexParameterfv(WGC3Denum target
,
532 virtual void getTexParameteriv(WGC3Denum target
,
537 virtual void getUniformfv(WebGLId program
,
542 virtual void getUniformiv(WebGLId program
,
547 virtual WGC3Dint
getUniformLocation(WebGLId program
, const WGC3Dchar
* name
) {
551 virtual void getVertexAttribfv(WGC3Duint index
,
556 virtual void getVertexAttribiv(WGC3Duint index
,
561 virtual WGC3Dsizeiptr
getVertexAttribOffset(WGC3Duint index
,
568 // This test isn't using the same fixture as GLRendererTest, and you can't mix
569 // TEST() and TEST_F() with the same name, Hence LRC2.
570 TEST(GLRendererTest2
, InitializationDoesNotMakeSynchronousCalls
) {
571 FakeRendererClient mock_client
;
572 scoped_ptr
<OutputSurface
> output_surface(
573 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
574 new ForbidSynchronousCallContext
)));
575 scoped_ptr
<ResourceProvider
> resource_provider(
576 ResourceProvider::Create(output_surface
.get(), 0));
577 FakeRendererGL
renderer(
578 &mock_client
, output_surface
.get(), resource_provider
.get());
580 EXPECT_TRUE(renderer
.Initialize());
583 class LoseContextOnFirstGetContext
: public TestWebGraphicsContext3D
{
585 LoseContextOnFirstGetContext() : context_lost_(false) {}
587 virtual bool makeContextCurrent() OVERRIDE
{ return !context_lost_
; }
589 virtual void getProgramiv(WebGLId program
, WGC3Denum pname
, WGC3Dint
* value
)
591 context_lost_
= true;
595 virtual void getShaderiv(WebGLId shader
, WGC3Denum pname
, WGC3Dint
* value
)
597 context_lost_
= true;
601 virtual WGC3Denum
getGraphicsResetStatusARB() OVERRIDE
{
602 return context_lost_
? 1 : 0;
609 TEST(GLRendererTest2
, InitializationWithQuicklyLostContextDoesNotAssert
) {
610 FakeRendererClient mock_client
;
611 scoped_ptr
<OutputSurface
> output_surface(
612 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
613 new LoseContextOnFirstGetContext
)));
614 scoped_ptr
<ResourceProvider
> resource_provider(
615 ResourceProvider::Create(output_surface
.get(), 0));
616 FakeRendererGL
renderer(
617 &mock_client
, output_surface
.get(), resource_provider
.get());
619 renderer
.Initialize();
622 class ContextThatDoesNotSupportMemoryManagmentExtensions
623 : public TestWebGraphicsContext3D
{
625 ContextThatDoesNotSupportMemoryManagmentExtensions() {}
627 // WebGraphicsContext3D methods.
629 // This method would normally do a glSwapBuffers under the hood.
630 virtual void prepareTexture() {}
631 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
632 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM
* callback
) {}
633 virtual WebString
getString(WebKit::WGC3Denum name
) { return WebString(); }
638 InitWithoutGpuMemManagerExtensionSupportShouldDefaultToNonZeroAllocation
) {
639 FakeRendererClient mock_client
;
640 scoped_ptr
<OutputSurface
> output_surface(
641 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
642 new ContextThatDoesNotSupportMemoryManagmentExtensions
)));
643 scoped_ptr
<ResourceProvider
> resource_provider(
644 ResourceProvider::Create(output_surface
.get(), 0));
645 FakeRendererGL
renderer(
646 &mock_client
, output_surface
.get(), resource_provider
.get());
648 renderer
.Initialize();
650 EXPECT_GT(mock_client
.memory_allocation_limit_bytes(), 0ul);
653 class ClearCountingContext
: public TestWebGraphicsContext3D
{
655 ClearCountingContext() : clear_(0) {}
657 virtual void clear(WGC3Dbitfield
) { clear_
++; }
659 int clear_count() const { return clear_
; }
665 TEST(GLRendererTest2
, OpaqueBackground
) {
666 FakeRendererClient mock_client
;
667 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
668 scoped_ptr
<WebKit::WebGraphicsContext3D
>(new ClearCountingContext
)));
669 ClearCountingContext
* context
=
670 static_cast<ClearCountingContext
*>(output_surface
->context3d());
671 scoped_ptr
<ResourceProvider
> resource_provider(
672 ResourceProvider::Create(output_surface
.get(), 0));
673 FakeRendererGL
renderer(
674 &mock_client
, output_surface
.get(), resource_provider
.get());
676 mock_client
.root_render_pass()->has_transparent_background
= false;
678 EXPECT_TRUE(renderer
.Initialize());
680 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
682 // On DEBUG builds, render passes with opaque background clear to blue to
683 // easily see regions that were not drawn on the screen.
685 EXPECT_EQ(0, context
->clear_count());
687 EXPECT_EQ(1, context
->clear_count());
691 TEST(GLRendererTest2
, TransparentBackground
) {
692 FakeRendererClient mock_client
;
693 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
694 scoped_ptr
<WebKit::WebGraphicsContext3D
>(new ClearCountingContext
)));
695 ClearCountingContext
* context
=
696 static_cast<ClearCountingContext
*>(output_surface
->context3d());
697 scoped_ptr
<ResourceProvider
> resource_provider(
698 ResourceProvider::Create(output_surface
.get(), 0));
699 FakeRendererGL
renderer(
700 &mock_client
, output_surface
.get(), resource_provider
.get());
702 mock_client
.root_render_pass()->has_transparent_background
= true;
704 EXPECT_TRUE(renderer
.Initialize());
706 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
708 EXPECT_EQ(1, context
->clear_count());
711 class VisibilityChangeIsLastCallTrackingContext
712 : public TestWebGraphicsContext3D
{
714 VisibilityChangeIsLastCallTrackingContext()
715 : last_call_was_set_visibility_(0) {}
717 // WebGraphicsContext3D methods.
718 virtual void setVisibilityCHROMIUM(bool visible
) {
719 if (!last_call_was_set_visibility_
)
721 DCHECK(*last_call_was_set_visibility_
== false);
722 *last_call_was_set_visibility_
= true;
724 virtual void flush() {
725 if (last_call_was_set_visibility_
)
726 *last_call_was_set_visibility_
= false;
728 virtual void deleteTexture(WebGLId
) {
729 if (last_call_was_set_visibility_
)
730 *last_call_was_set_visibility_
= false;
732 virtual void deleteFramebuffer(WebGLId
) {
733 if (last_call_was_set_visibility_
)
734 *last_call_was_set_visibility_
= false;
736 virtual void deleteRenderbuffer(WebGLId
) {
737 if (last_call_was_set_visibility_
)
738 *last_call_was_set_visibility_
= false;
741 // This method would normally do a glSwapBuffers under the hood.
742 virtual WebString
getString(WebKit::WGC3Denum name
) {
743 if (name
== GL_EXTENSIONS
)
745 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
746 "GL_CHROMIUM_discard_backbuffer");
750 // Methods added for test.
751 void set_last_call_was_set_visibility_pointer(
752 bool* last_call_was_set_visibility
) {
753 last_call_was_set_visibility_
= last_call_was_set_visibility
;
757 bool* last_call_was_set_visibility_
;
760 TEST(GLRendererTest2
, VisibilityChangeIsLastCall
) {
761 FakeRendererClient mock_client
;
762 scoped_ptr
<OutputSurface
> output_surface(
763 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
764 new VisibilityChangeIsLastCallTrackingContext
)));
765 VisibilityChangeIsLastCallTrackingContext
* context
=
766 static_cast<VisibilityChangeIsLastCallTrackingContext
*>(
767 output_surface
->context3d());
768 scoped_ptr
<ResourceProvider
> resource_provider(
769 ResourceProvider::Create(output_surface
.get(), 0));
770 FakeRendererGL
renderer(
771 &mock_client
, output_surface
.get(), resource_provider
.get());
773 EXPECT_TRUE(renderer
.Initialize());
775 bool last_call_was_set_visiblity
= false;
776 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the
777 // GPU process, after glFlush is called, and after the RendererClient's
778 // EnforceManagedMemoryPolicy is called. Plumb this tracking between both the
779 // RenderClient and the Context by giving them both a pointer to a variable on
781 context
->set_last_call_was_set_visibility_pointer(
782 &last_call_was_set_visiblity
);
783 mock_client
.set_last_call_was_set_visibility_pointer(
784 &last_call_was_set_visiblity
);
785 renderer
.SetVisible(true);
786 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
787 renderer
.SetVisible(false);
788 EXPECT_TRUE(last_call_was_set_visiblity
);
791 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
793 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM
) {}
795 virtual WebString
getString(WGC3Denum name
) {
796 if (name
== GL_EXTENSIONS
)
797 return WebString("GL_OES_EGL_image_external");
801 MOCK_METHOD3(texParameteri
,
802 void(WGC3Denum target
, WGC3Denum pname
, WGC3Dint param
));
803 MOCK_METHOD4(drawElements
,
807 WGC3Dintptr offset
));
809 virtual void activeTexture(WGC3Denum texture
) {
810 EXPECT_NE(texture
, active_texture_
);
811 active_texture_
= texture
;
814 WGC3Denum
active_texture() const { return active_texture_
; }
817 WGC3Denum active_texture_
;
820 TEST(GLRendererTest2
, ActiveTextureState
) {
821 FakeRendererClient fake_client
;
822 scoped_ptr
<OutputSurface
> output_surface(
823 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
824 new TextureStateTrackingContext
)));
825 TextureStateTrackingContext
* context
=
826 static_cast<TextureStateTrackingContext
*>(output_surface
->context3d());
827 scoped_ptr
<ResourceProvider
> resource_provider(
828 ResourceProvider::Create(output_surface
.get(), 0));
829 FakeRendererGL
renderer(
830 &fake_client
, output_surface
.get(), resource_provider
.get());
832 // During initialization we are allowed to set any texture parameters.
833 EXPECT_CALL(*context
, texParameteri(_
, _
, _
)).Times(AnyNumber());
834 EXPECT_TRUE(renderer
.Initialize());
836 cc::RenderPass::Id
id(1, 1);
837 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
839 gfx::Rect(0, 0, 100, 100),
840 gfx::Rect(0, 0, 100, 100),
842 pass
->AppendOneOfEveryQuadType(resource_provider
.get(), RenderPass::Id(2, 1));
844 // Set up expected texture filter state transitions that match the quads
845 // created in AppendOneOfEveryQuadType().
846 Mock::VerifyAndClearExpectations(context
);
850 // yuv_quad is drawn with the default linear filter.
851 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
853 // tile_quad is drawn with GL_NEAREST because it is not transformed or
857 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
860 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
861 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
863 // transformed_tile_quad uses GL_LINEAR.
864 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
866 // scaled_tile_quad also uses GL_LINEAR.
867 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
869 // The remaining quads also use GL_LINEAR because nearest neighbor
870 // filtering is currently only used with tile quads.
871 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
)).Times(6);
874 cc::DirectRenderer::DrawingFrame drawing_frame
;
875 renderer
.BeginDrawingFrame(&drawing_frame
);
876 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0
), context
->active_texture());
878 for (cc::QuadList::BackToFrontIterator
879 it
= pass
->quad_list
.BackToFrontBegin();
880 it
!= pass
->quad_list
.BackToFrontEnd();
882 renderer
.DoDrawQuad(&drawing_frame
, *it
);
884 renderer
.FinishDrawingQuadList();
885 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0
), context
->active_texture());
886 Mock::VerifyAndClearExpectations(context
);
889 class NoClearRootRenderPassFakeClient
: public FakeRendererClient
{
891 virtual bool ShouldClearRootRenderPass() const OVERRIDE
{ return false; }
894 class NoClearRootRenderPassMockContext
: public TestWebGraphicsContext3D
{
896 MOCK_METHOD1(clear
, void(WGC3Dbitfield mask
));
897 MOCK_METHOD4(drawElements
,
901 WGC3Dintptr offset
));
904 TEST(GLRendererTest2
, ShouldClearRootRenderPass
) {
905 NoClearRootRenderPassFakeClient mock_client
;
906 scoped_ptr
<OutputSurface
> output_surface(
907 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
908 new NoClearRootRenderPassMockContext
)));
909 NoClearRootRenderPassMockContext
* mock_context
=
910 static_cast<NoClearRootRenderPassMockContext
*>(
911 output_surface
->context3d());
912 scoped_ptr
<ResourceProvider
> resource_provider(
913 ResourceProvider::Create(output_surface
.get(), 0));
914 FakeRendererGL
renderer(
915 &mock_client
, output_surface
.get(), resource_provider
.get());
916 EXPECT_TRUE(renderer
.Initialize());
918 gfx::Rect
viewport_rect(mock_client
.DeviceViewportSize());
919 ScopedPtrVector
<RenderPass
>& render_passes
=
920 *mock_client
.render_passes_in_draw_order();
921 render_passes
.clear();
923 RenderPass::Id
root_pass_id(1, 0);
924 TestRenderPass
* root_pass
= AddRenderPass(
925 &render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
926 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
928 RenderPass::Id
child_pass_id(2, 0);
929 TestRenderPass
* child_pass
= AddRenderPass(
930 &render_passes
, child_pass_id
, viewport_rect
, gfx::Transform());
931 AddQuad(child_pass
, viewport_rect
, SK_ColorBLUE
);
933 AddRenderPassQuad(root_pass
, child_pass
);
935 // First render pass is not the root one, clearing should happen.
936 EXPECT_CALL(*mock_context
, clear(GL_COLOR_BUFFER_BIT
)).Times(AtLeast(1));
938 Expectation first_render_pass
=
939 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
)).Times(1);
941 // The second render pass is the root one, clearing should be prevented.
942 EXPECT_CALL(*mock_context
, clear(GL_COLOR_BUFFER_BIT
)).Times(0)
943 .After(first_render_pass
);
945 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
)).Times(AnyNumber())
946 .After(first_render_pass
);
948 renderer
.DecideRenderPassAllocationsForFrame(
949 *mock_client
.render_passes_in_draw_order());
950 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
952 // In multiple render passes all but the root pass should clear the
954 Mock::VerifyAndClearExpectations(&mock_context
);
957 class ScissorTestOnClearCheckingContext
: public TestWebGraphicsContext3D
{
959 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
961 virtual void clear(WGC3Dbitfield
) { EXPECT_FALSE(scissor_enabled_
); }
963 virtual void enable(WGC3Denum cap
) {
964 if (cap
== GL_SCISSOR_TEST
)
965 scissor_enabled_
= true;
968 virtual void disable(WGC3Denum cap
) {
969 if (cap
== GL_SCISSOR_TEST
)
970 scissor_enabled_
= false;
974 bool scissor_enabled_
;
977 TEST(GLRendererTest2
, ScissorTestWhenClearing
) {
978 FakeRendererClient mock_client
;
979 scoped_ptr
<OutputSurface
> output_surface(
980 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
981 new ScissorTestOnClearCheckingContext
)));
982 scoped_ptr
<ResourceProvider
> resource_provider(
983 ResourceProvider::Create(output_surface
.get(), 0));
984 FakeRendererGL
renderer(
985 &mock_client
, output_surface
.get(), resource_provider
.get());
986 EXPECT_TRUE(renderer
.Initialize());
987 EXPECT_FALSE(renderer
.Capabilities().using_partial_swap
);
989 gfx::Rect
viewport_rect(mock_client
.DeviceViewportSize());
990 ScopedPtrVector
<RenderPass
>& render_passes
=
991 *mock_client
.render_passes_in_draw_order();
992 render_passes
.clear();
994 gfx::Rect
grand_child_rect(25, 25);
995 RenderPass::Id
grand_child_pass_id(3, 0);
996 TestRenderPass
* grand_child_pass
= AddRenderPass(
997 &render_passes
, grand_child_pass_id
, grand_child_rect
, gfx::Transform());
998 AddClippedQuad(grand_child_pass
, grand_child_rect
, SK_ColorYELLOW
);
1000 gfx::Rect
child_rect(50, 50);
1001 RenderPass::Id
child_pass_id(2, 0);
1002 TestRenderPass
* child_pass
= AddRenderPass(
1003 &render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1004 AddQuad(child_pass
, child_rect
, SK_ColorBLUE
);
1006 RenderPass::Id
root_pass_id(1, 0);
1007 TestRenderPass
* root_pass
= AddRenderPass(
1008 &render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1009 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1011 AddRenderPassQuad(root_pass
, child_pass
);
1012 AddRenderPassQuad(child_pass
, grand_child_pass
);
1014 renderer
.DecideRenderPassAllocationsForFrame(
1015 *mock_client
.render_passes_in_draw_order());
1016 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
1019 TEST_F(GLRendererShaderTest
, DrawRenderPassQuadShaderPermutations
) {
1020 gfx::Rect
viewportRect(mock_client_
.DeviceViewportSize());
1021 ScopedPtrVector
<RenderPass
>* renderPasses
=
1022 mock_client_
.render_passes_in_draw_order();
1024 gfx::Rect
grandChildRect(25, 25);
1025 RenderPass::Id
grandChildPassId(3, 0);
1026 TestRenderPass
* grandChildPass
;
1028 gfx::Rect
childRect(50, 50);
1029 RenderPass::Id
childPassId(2, 0);
1030 TestRenderPass
* childPass
;
1032 RenderPass::Id
rootPassId(1, 0);
1033 TestRenderPass
* rootPass
;
1035 cc::ResourceProvider::ResourceId mask
=
1036 resource_provider_
->CreateResource(gfx::Size(20, 12),
1037 resource_provider_
->best_texture_format(),
1038 ResourceProvider::TextureUsageAny
);
1039 resource_provider_
->AllocateForTesting(mask
);
1041 SkScalar matrix
[20];
1042 float amount
= 0.5f
;
1043 matrix
[0] = 0.213f
+ 0.787f
* amount
;
1044 matrix
[1] = 0.715f
- 0.715f
* amount
;
1045 matrix
[2] = 1.f
- (matrix
[0] + matrix
[1]);
1046 matrix
[3] = matrix
[4] = 0;
1047 matrix
[5] = 0.213f
- 0.213f
* amount
;
1048 matrix
[6] = 0.715f
+ 0.285f
* amount
;
1049 matrix
[7] = 1.f
- (matrix
[5] + matrix
[6]);
1050 matrix
[8] = matrix
[9] = 0;
1051 matrix
[10] = 0.213f
- 0.213f
* amount
;
1052 matrix
[11] = 0.715f
- 0.715f
* amount
;
1053 matrix
[12] = 1.f
- (matrix
[10] + matrix
[11]);
1054 matrix
[13] = matrix
[14] = 0;
1055 matrix
[15] = matrix
[16] = matrix
[17] = matrix
[19] = 0;
1057 skia::RefPtr
<SkColorFilter
> colorFilter(skia::AdoptRef(
1058 new SkColorMatrixFilter(matrix
)));
1059 skia::RefPtr
<SkImageFilter
> filter
=
1060 skia::AdoptRef(SkColorFilterImageFilter::Create(colorFilter
.get(), NULL
));
1062 gfx::Transform transform_causing_aa
;
1063 transform_causing_aa
.Rotate(20.0);
1065 // RenderPassProgram
1066 renderPasses
->clear();
1068 grandChildPass
= AddRenderPass(renderPasses
, grandChildPassId
, grandChildRect
,
1070 AddClippedQuad(grandChildPass
, grandChildRect
, SK_ColorYELLOW
);
1072 childPass
= AddRenderPass(renderPasses
, childPassId
, childRect
,
1074 AddQuad(childPass
, childRect
, SK_ColorBLUE
);
1076 rootPass
= AddRenderPass(renderPasses
, rootPassId
, viewportRect
,
1078 AddQuad(rootPass
, viewportRect
, SK_ColorGREEN
);
1080 AddRenderPassQuad(rootPass
, childPass
, 0, skia::RefPtr
<SkImageFilter
>(),
1082 AddRenderPassQuad(childPass
, grandChildPass
);
1084 renderer_
->DecideRenderPassAllocationsForFrame(
1085 *mock_client_
.render_passes_in_draw_order());
1086 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1087 TestRenderPassProgram();
1089 // RenderPassColorMatrixProgram
1090 renderPasses
->clear();
1092 grandChildPass
= AddRenderPass(renderPasses
, grandChildPassId
, grandChildRect
,
1093 transform_causing_aa
);
1094 AddClippedQuad(grandChildPass
, grandChildRect
, SK_ColorYELLOW
);
1096 childPass
= AddRenderPass(renderPasses
, childPassId
, childRect
,
1097 transform_causing_aa
);
1098 AddQuad(childPass
, childRect
, SK_ColorBLUE
);
1100 rootPass
= AddRenderPass(renderPasses
, rootPassId
, viewportRect
,
1102 AddQuad(rootPass
, viewportRect
, SK_ColorGREEN
);
1104 AddRenderPassQuad(rootPass
, childPass
, 0, filter
, gfx::Transform());
1105 AddRenderPassQuad(childPass
, grandChildPass
);
1107 renderer_
->DecideRenderPassAllocationsForFrame(
1108 *mock_client_
.render_passes_in_draw_order());
1109 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1110 TestRenderPassColorMatrixProgram();
1112 // RenderPassMaskProgram
1113 renderPasses
->clear();
1115 grandChildPass
= AddRenderPass(renderPasses
, grandChildPassId
, grandChildRect
,
1117 AddClippedQuad(grandChildPass
, grandChildRect
, SK_ColorYELLOW
);
1119 childPass
= AddRenderPass(renderPasses
, childPassId
, childRect
,
1121 AddQuad(childPass
, childRect
, SK_ColorBLUE
);
1123 rootPass
= AddRenderPass(renderPasses
, rootPassId
, viewportRect
,
1125 AddQuad(rootPass
, viewportRect
, SK_ColorGREEN
);
1127 AddRenderPassQuad(rootPass
, childPass
, mask
, skia::RefPtr
<SkImageFilter
>(),
1129 AddRenderPassQuad(childPass
, grandChildPass
);
1131 renderer_
->DecideRenderPassAllocationsForFrame(
1132 *mock_client_
.render_passes_in_draw_order());
1133 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1134 TestRenderPassMaskProgram();
1136 // RenderPassMaskColorMatrixProgram
1137 renderPasses
->clear();
1139 grandChildPass
= AddRenderPass(renderPasses
, grandChildPassId
, grandChildRect
,
1141 AddClippedQuad(grandChildPass
, grandChildRect
, SK_ColorYELLOW
);
1143 childPass
= AddRenderPass(renderPasses
, childPassId
, childRect
,
1145 AddQuad(childPass
, childRect
, SK_ColorBLUE
);
1147 rootPass
= AddRenderPass(renderPasses
, rootPassId
, viewportRect
,
1149 AddQuad(rootPass
, viewportRect
, SK_ColorGREEN
);
1151 AddRenderPassQuad(rootPass
, childPass
, mask
, filter
, gfx::Transform());
1152 AddRenderPassQuad(childPass
, grandChildPass
);
1154 renderer_
->DecideRenderPassAllocationsForFrame(
1155 *mock_client_
.render_passes_in_draw_order());
1156 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1157 TestRenderPassMaskColorMatrixProgram();
1159 // RenderPassProgramAA
1160 renderPasses
->clear();
1162 grandChildPass
= AddRenderPass(renderPasses
, grandChildPassId
, grandChildRect
,
1163 transform_causing_aa
);
1164 AddClippedQuad(grandChildPass
, grandChildRect
, SK_ColorYELLOW
);
1166 childPass
= AddRenderPass(renderPasses
, childPassId
, childRect
,
1167 transform_causing_aa
);
1168 AddQuad(childPass
, childRect
, SK_ColorBLUE
);
1170 rootPass
= AddRenderPass(renderPasses
, rootPassId
, viewportRect
,
1172 AddQuad(rootPass
, viewportRect
, SK_ColorGREEN
);
1174 AddRenderPassQuad(rootPass
, childPass
, 0, skia::RefPtr
<SkImageFilter
>(),
1175 transform_causing_aa
);
1176 AddRenderPassQuad(childPass
, grandChildPass
);
1178 renderer_
->DecideRenderPassAllocationsForFrame(
1179 *mock_client_
.render_passes_in_draw_order());
1180 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1181 TestRenderPassProgramAA();
1183 // RenderPassColorMatrixProgramAA
1184 renderPasses
->clear();
1186 grandChildPass
= AddRenderPass(renderPasses
, grandChildPassId
, grandChildRect
,
1187 transform_causing_aa
);
1188 AddClippedQuad(grandChildPass
, grandChildRect
, SK_ColorYELLOW
);
1190 childPass
= AddRenderPass(renderPasses
, childPassId
, childRect
,
1191 transform_causing_aa
);
1192 AddQuad(childPass
, childRect
, SK_ColorBLUE
);
1194 rootPass
= AddRenderPass(renderPasses
, rootPassId
, viewportRect
,
1196 AddQuad(rootPass
, viewportRect
, SK_ColorGREEN
);
1198 AddRenderPassQuad(rootPass
, childPass
, 0, filter
, transform_causing_aa
);
1199 AddRenderPassQuad(childPass
, grandChildPass
);
1201 renderer_
->DecideRenderPassAllocationsForFrame(
1202 *mock_client_
.render_passes_in_draw_order());
1203 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1204 TestRenderPassColorMatrixProgramAA();
1206 // RenderPassMaskProgramAA
1207 renderPasses
->clear();
1209 grandChildPass
= AddRenderPass(renderPasses
, grandChildPassId
, grandChildRect
,
1210 transform_causing_aa
);
1211 AddClippedQuad(grandChildPass
, grandChildRect
, SK_ColorYELLOW
);
1213 childPass
= AddRenderPass(renderPasses
, childPassId
, childRect
,
1214 transform_causing_aa
);
1215 AddQuad(childPass
, childRect
, SK_ColorBLUE
);
1217 rootPass
= AddRenderPass(renderPasses
, rootPassId
, viewportRect
,
1219 AddQuad(rootPass
, viewportRect
, SK_ColorGREEN
);
1221 AddRenderPassQuad(rootPass
, childPass
, mask
, skia::RefPtr
<SkImageFilter
>(),
1222 transform_causing_aa
);
1223 AddRenderPassQuad(childPass
, grandChildPass
);
1225 renderer_
->DecideRenderPassAllocationsForFrame(
1226 *mock_client_
.render_passes_in_draw_order());
1227 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1228 TestRenderPassMaskProgramAA();
1230 // RenderPassMaskColorMatrixProgramAA
1231 renderPasses
->clear();
1233 grandChildPass
= AddRenderPass(renderPasses
, grandChildPassId
, grandChildRect
,
1234 transform_causing_aa
);
1235 AddClippedQuad(grandChildPass
, grandChildRect
, SK_ColorYELLOW
);
1237 childPass
= AddRenderPass(renderPasses
, childPassId
, childRect
,
1238 transform_causing_aa
);
1239 AddQuad(childPass
, childRect
, SK_ColorBLUE
);
1241 rootPass
= AddRenderPass(renderPasses
, rootPassId
, viewportRect
,
1242 transform_causing_aa
);
1243 AddQuad(rootPass
, viewportRect
, SK_ColorGREEN
);
1245 AddRenderPassQuad(rootPass
, childPass
, mask
, filter
, transform_causing_aa
);
1246 AddRenderPassQuad(childPass
, grandChildPass
);
1248 renderer_
->DecideRenderPassAllocationsForFrame(
1249 *mock_client_
.render_passes_in_draw_order());
1250 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1251 TestRenderPassMaskColorMatrixProgramAA();
1254 class OutputSurfaceMockContext
: public TestWebGraphicsContext3D
{
1256 // Specifically override methods even if they are unused (used in conjunction
1257 // with StrictMock). We need to make sure that GLRenderer does not issue
1258 // framebuffer-related GL calls directly. Instead these are supposed to go
1259 // through the OutputSurface abstraction.
1260 MOCK_METHOD0(ensureBackbufferCHROMIUM
, void());
1261 MOCK_METHOD0(discardBackbufferCHROMIUM
, void());
1262 MOCK_METHOD2(bindFramebuffer
, void(WGC3Denum target
, WebGLId framebuffer
));
1263 MOCK_METHOD0(prepareTexture
, void());
1264 MOCK_METHOD2(reshape
, void(int width
, int height
));
1265 MOCK_METHOD4(drawElements
,
1266 void(WGC3Denum mode
,
1269 WGC3Dintptr offset
));
1271 virtual WebString
getString(WebKit::WGC3Denum name
) {
1272 if (name
== GL_EXTENSIONS
)
1274 "GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_discard_backbuffer");
1279 class MockOutputSurface
: public OutputSurface
{
1282 : OutputSurface(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
1283 new StrictMock
<OutputSurfaceMockContext
>)) {}
1284 virtual ~MockOutputSurface() {}
1286 MOCK_METHOD1(SendFrameToParentCompositor
, void(CompositorFrame
* frame
));
1287 MOCK_METHOD0(EnsureBackbuffer
, void());
1288 MOCK_METHOD0(DiscardBackbuffer
, void());
1289 MOCK_METHOD1(Reshape
, void(gfx::Size size
));
1290 MOCK_METHOD0(BindFramebuffer
, void());
1291 MOCK_METHOD1(PostSubBuffer
, void(gfx::Rect rect
));
1292 MOCK_METHOD0(SwapBuffers
, void());
1295 class MockOutputSurfaceTest
: public testing::Test
, public FakeRendererClient
{
1297 MockOutputSurfaceTest()
1298 : resource_provider_(ResourceProvider::Create(&output_surface_
, 0)),
1299 renderer_(this, &output_surface_
, resource_provider_
.get()) {}
1301 virtual void SetUp() { EXPECT_TRUE(renderer_
.Initialize()); }
1303 void SwapBuffers() { renderer_
.SwapBuffers(); }
1306 gfx::Rect
viewport_rect(DeviceViewportSize());
1307 ScopedPtrVector
<RenderPass
>* render_passes
= render_passes_in_draw_order();
1308 render_passes
->clear();
1310 RenderPass::Id
render_pass_id(1, 0);
1311 TestRenderPass
* render_pass
= AddRenderPass(
1312 render_passes
, render_pass_id
, viewport_rect
, gfx::Transform());
1313 AddQuad(render_pass
, viewport_rect
, SK_ColorGREEN
);
1315 EXPECT_CALL(output_surface_
, EnsureBackbuffer()).WillRepeatedly(Return());
1317 EXPECT_CALL(output_surface_
, Reshape(_
)).Times(1);
1319 EXPECT_CALL(output_surface_
, BindFramebuffer()).Times(1);
1321 EXPECT_CALL(*context(), drawElements(_
, _
, _
, _
)).Times(1);
1323 renderer_
.DecideRenderPassAllocationsForFrame(
1324 *render_passes_in_draw_order());
1325 renderer_
.DrawFrame(render_passes_in_draw_order());
1328 OutputSurfaceMockContext
* context() {
1329 return static_cast<OutputSurfaceMockContext
*>(output_surface_
.context3d());
1332 StrictMock
<MockOutputSurface
> output_surface_
;
1333 scoped_ptr
<ResourceProvider
> resource_provider_
;
1334 FakeRendererGL renderer_
;
1337 TEST_F(MockOutputSurfaceTest
, DrawFrameAndSwap
) {
1340 EXPECT_CALL(output_surface_
, SwapBuffers()).Times(1);
1341 renderer_
.SwapBuffers();
1344 class MockOutputSurfaceTestWithPartialSwap
: public MockOutputSurfaceTest
{
1346 virtual const LayerTreeSettings
& Settings() const OVERRIDE
{
1347 static LayerTreeSettings fake_settings
;
1348 fake_settings
.partial_swap_enabled
= true;
1349 return fake_settings
;
1353 TEST_F(MockOutputSurfaceTestWithPartialSwap
, DrawFrameAndSwap
) {
1356 EXPECT_CALL(output_surface_
, PostSubBuffer(_
)).Times(1);
1357 renderer_
.SwapBuffers();
1360 class MockOutputSurfaceTestWithSendCompositorFrame
1361 : public MockOutputSurfaceTest
{
1363 virtual const LayerTreeSettings
& Settings() const OVERRIDE
{
1364 static LayerTreeSettings fake_settings
;
1365 fake_settings
.compositor_frame_message
= true;
1366 return fake_settings
;
1370 TEST_F(MockOutputSurfaceTestWithSendCompositorFrame
, DrawFrame
) {
1371 EXPECT_CALL(output_surface_
, SendFrameToParentCompositor(_
)).Times(1);