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"
9 #include "cc/base/math_util.h"
10 #include "cc/output/compositor_frame_metadata.h"
11 #include "cc/resources/prioritized_resource_manager.h"
12 #include "cc/resources/resource_provider.h"
13 #include "cc/test/fake_impl_proxy.h"
14 #include "cc/test/fake_layer_tree_host_impl.h"
15 #include "cc/test/fake_output_surface.h"
16 #include "cc/test/fake_output_surface_client.h"
17 #include "cc/test/mock_quad_culler.h"
18 #include "cc/test/pixel_test.h"
19 #include "cc/test/render_pass_test_common.h"
20 #include "cc/test/render_pass_test_utils.h"
21 #include "cc/test/test_web_graphics_context_3d.h"
22 #include "gpu/GLES2/gl2extchromium.h"
23 #include "gpu/command_buffer/client/context_support.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/khronos/GLES2/gl2.h"
27 #include "third_party/skia/include/core/SkImageFilter.h"
28 #include "third_party/skia/include/core/SkMatrix.h"
29 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
30 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
31 #include "ui/gfx/transform.h"
34 using testing::AnyNumber
;
36 using testing::AtLeast
;
37 using testing::ElementsAre
;
38 using testing::Expectation
;
39 using testing::InSequence
;
41 using testing::Return
;
42 using testing::StrictMock
;
46 class GLRendererTest
: public testing::Test
{
48 RenderPass
* root_render_pass() { return render_passes_in_draw_order_
.back(); }
50 RenderPassList render_passes_in_draw_order_
;
53 #define EXPECT_PROGRAM_VALID(program_binding) \
55 EXPECT_TRUE((program_binding)->program()); \
56 EXPECT_TRUE((program_binding)->initialized()); \
59 // Explicitly named to be a friend in GLRenderer for shader access.
60 class GLRendererShaderPixelTest
: public GLRendererPixelTest
{
63 ASSERT_FALSE(renderer()->IsContextLost());
64 EXPECT_PROGRAM_VALID(renderer()->GetTileCheckerboardProgram());
65 EXPECT_PROGRAM_VALID(renderer()->GetDebugBorderProgram());
66 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgram());
67 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgramAA());
68 TestShadersWithTexCoordPrecision(TexCoordPrecisionMedium
);
69 TestShadersWithTexCoordPrecision(TexCoordPrecisionHigh
);
70 ASSERT_FALSE(renderer()->IsContextLost());
73 void TestShadersWithTexCoordPrecision(TexCoordPrecision precision
) {
74 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgram(precision
));
75 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgramAA(precision
));
76 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgram(precision
));
77 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA(precision
));
79 renderer()->GetRenderPassColorMatrixProgram(precision
));
81 renderer()->GetRenderPassMaskColorMatrixProgramAA(precision
));
83 renderer()->GetRenderPassColorMatrixProgramAA(precision
));
85 renderer()->GetRenderPassMaskColorMatrixProgram(precision
));
86 EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision
));
88 renderer()->GetNonPremultipliedTextureProgram(precision
));
89 EXPECT_PROGRAM_VALID(renderer()->GetTextureBackgroundProgram(precision
));
91 renderer()->GetNonPremultipliedTextureBackgroundProgram(precision
));
92 EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision
));
93 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision
));
94 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision
));
95 // This is unlikely to be ever true in tests due to usage of osmesa.
96 if (renderer()->Capabilities().using_egl_image
)
97 EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision
));
99 EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision
));
100 TestShadersWithSamplerType(precision
, SamplerType2D
);
101 TestShadersWithSamplerType(precision
, SamplerType2DRect
);
102 // This is unlikely to be ever true in tests due to usage of osmesa.
103 if (renderer()->Capabilities().using_egl_image
)
104 TestShadersWithSamplerType(precision
, SamplerTypeExternalOES
);
107 void TestShadersWithSamplerType(TexCoordPrecision precision
,
108 SamplerType sampler
) {
109 EXPECT_PROGRAM_VALID(renderer()->GetTileProgram(precision
, sampler
));
110 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramOpaque(precision
, sampler
));
111 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramAA(precision
, sampler
));
112 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzle(precision
, sampler
));
113 EXPECT_PROGRAM_VALID(
114 renderer()->GetTileProgramSwizzleOpaque(precision
, sampler
));
115 EXPECT_PROGRAM_VALID(
116 renderer()->GetTileProgramSwizzleAA(precision
, sampler
));
122 #if !defined(OS_ANDROID)
123 TEST_F(GLRendererShaderPixelTest
, AllShadersCompile
) { TestShaders(); }
126 class FakeRendererClient
: public RendererClient
{
128 FakeRendererClient() : set_full_root_layer_damage_count_(0) {}
130 // RendererClient methods.
131 virtual void SetFullRootLayerDamage() OVERRIDE
{
132 set_full_root_layer_damage_count_
++;
135 // Methods added for test.
136 int set_full_root_layer_damage_count() const {
137 return set_full_root_layer_damage_count_
;
141 int set_full_root_layer_damage_count_
;
144 class FakeRendererGL
: public GLRenderer
{
146 FakeRendererGL(RendererClient
* client
,
147 const LayerTreeSettings
* settings
,
148 OutputSurface
* output_surface
,
149 ResourceProvider
* resource_provider
)
157 // GLRenderer methods.
159 // Changing visibility to public.
160 using GLRenderer::IsBackbufferDiscarded
;
161 using GLRenderer::DoDrawQuad
;
162 using GLRenderer::BeginDrawingFrame
;
163 using GLRenderer::FinishDrawingQuadList
;
164 using GLRenderer::stencil_enabled
;
167 class GLRendererWithDefaultHarnessTest
: public GLRendererTest
{
169 GLRendererWithDefaultHarnessTest() {
171 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()).Pass();
172 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
174 resource_provider_
= ResourceProvider::Create(
175 output_surface_
.get(), NULL
, 0, false, 1).Pass();
176 renderer_
= make_scoped_ptr(new FakeRendererGL(&renderer_client_
,
178 output_surface_
.get(),
179 resource_provider_
.get()));
182 void SwapBuffers() { renderer_
->SwapBuffers(CompositorFrameMetadata()); }
184 LayerTreeSettings settings_
;
185 FakeOutputSurfaceClient output_surface_client_
;
186 scoped_ptr
<FakeOutputSurface
> output_surface_
;
187 FakeRendererClient renderer_client_
;
188 scoped_ptr
<ResourceProvider
> resource_provider_
;
189 scoped_ptr
<FakeRendererGL
> renderer_
;
192 // Closing the namespace here so that GLRendererShaderTest can take advantage
193 // of the friend relationship with GLRenderer and all of the mock classes
194 // declared above it.
197 class GLRendererShaderTest
: public GLRendererTest
{
199 GLRendererShaderTest() {
200 output_surface_
= FakeOutputSurface::Create3d().Pass();
201 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
203 resource_provider_
= ResourceProvider::Create(
204 output_surface_
.get(), NULL
, 0, false, 1).Pass();
205 renderer_
.reset(new FakeRendererGL(&renderer_client_
,
207 output_surface_
.get(),
208 resource_provider_
.get()));
211 void TestRenderPassProgram(TexCoordPrecision precision
) {
212 EXPECT_PROGRAM_VALID(&renderer_
->render_pass_program_
[precision
]);
213 EXPECT_EQ(renderer_
->render_pass_program_
[precision
].program(),
214 renderer_
->program_shadow_
);
217 void TestRenderPassColorMatrixProgram(TexCoordPrecision precision
) {
218 EXPECT_PROGRAM_VALID(
219 &renderer_
->render_pass_color_matrix_program_
[precision
]);
220 EXPECT_EQ(renderer_
->render_pass_color_matrix_program_
[precision
].program(),
221 renderer_
->program_shadow_
);
224 void TestRenderPassMaskProgram(TexCoordPrecision precision
) {
225 EXPECT_PROGRAM_VALID(&renderer_
->render_pass_mask_program_
[precision
]);
226 EXPECT_EQ(renderer_
->render_pass_mask_program_
[precision
].program(),
227 renderer_
->program_shadow_
);
230 void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision
) {
231 EXPECT_PROGRAM_VALID(
232 &renderer_
->render_pass_mask_color_matrix_program_
[precision
]);
234 renderer_
->render_pass_mask_color_matrix_program_
[precision
].program(),
235 renderer_
->program_shadow_
);
238 void TestRenderPassProgramAA(TexCoordPrecision precision
) {
239 EXPECT_PROGRAM_VALID(&renderer_
->render_pass_program_aa_
[precision
]);
240 EXPECT_EQ(renderer_
->render_pass_program_aa_
[precision
].program(),
241 renderer_
->program_shadow_
);
244 void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision
) {
245 EXPECT_PROGRAM_VALID(
246 &renderer_
->render_pass_color_matrix_program_aa_
[precision
]);
248 renderer_
->render_pass_color_matrix_program_aa_
[precision
].program(),
249 renderer_
->program_shadow_
);
252 void TestRenderPassMaskProgramAA(TexCoordPrecision precision
) {
253 EXPECT_PROGRAM_VALID(&renderer_
->render_pass_mask_program_aa_
[precision
]);
254 EXPECT_EQ(renderer_
->render_pass_mask_program_aa_
[precision
].program(),
255 renderer_
->program_shadow_
);
258 void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision
) {
259 EXPECT_PROGRAM_VALID(
260 &renderer_
->render_pass_mask_color_matrix_program_aa_
[precision
]);
261 EXPECT_EQ(renderer_
->render_pass_mask_color_matrix_program_aa_
[precision
]
263 renderer_
->program_shadow_
);
266 void TestSolidColorProgramAA() {
267 EXPECT_PROGRAM_VALID(&renderer_
->solid_color_program_aa_
);
268 EXPECT_EQ(renderer_
->solid_color_program_aa_
.program(),
269 renderer_
->program_shadow_
);
272 LayerTreeSettings settings_
;
273 FakeOutputSurfaceClient output_surface_client_
;
274 scoped_ptr
<FakeOutputSurface
> output_surface_
;
275 FakeRendererClient renderer_client_
;
276 scoped_ptr
<ResourceProvider
> resource_provider_
;
277 scoped_ptr
<FakeRendererGL
> renderer_
;
282 // Test GLRenderer DiscardBackbuffer functionality:
283 // Suggest discarding framebuffer when one exists and the renderer is not
285 // Expected: it is discarded and damage tracker is reset.
287 GLRendererWithDefaultHarnessTest
,
288 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible
) {
289 renderer_
->SetVisible(false);
290 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
291 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
294 // Test GLRenderer DiscardBackbuffer functionality:
295 // Suggest discarding framebuffer when one exists and the renderer is visible.
296 // Expected: the allocation is ignored.
297 TEST_F(GLRendererWithDefaultHarnessTest
,
298 SuggestBackbufferNoDoNothingWhenVisible
) {
299 renderer_
->SetVisible(true);
300 EXPECT_EQ(0, renderer_client_
.set_full_root_layer_damage_count());
301 EXPECT_FALSE(renderer_
->IsBackbufferDiscarded());
304 // Test GLRenderer DiscardBackbuffer functionality:
305 // Suggest discarding framebuffer when one does not exist.
306 // Expected: it does nothing.
307 TEST_F(GLRendererWithDefaultHarnessTest
,
308 SuggestBackbufferNoWhenItDoesntExistShouldDoNothing
) {
309 renderer_
->SetVisible(false);
310 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
311 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
313 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
314 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
317 // Test GLRenderer DiscardBackbuffer functionality:
318 // Begin drawing a frame while a framebuffer is discarded.
319 // Expected: will recreate framebuffer.
320 TEST_F(GLRendererWithDefaultHarnessTest
,
321 DiscardedBackbufferIsRecreatedForScopeDuration
) {
322 gfx::Rect
viewport_rect(1, 1);
323 renderer_
->SetVisible(false);
324 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
325 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
327 AddRenderPass(&render_passes_in_draw_order_
,
328 RenderPass::Id(1, 0),
332 renderer_
->SetVisible(true);
333 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
339 EXPECT_FALSE(renderer_
->IsBackbufferDiscarded());
342 EXPECT_EQ(1u, output_surface_
->num_sent_frames());
345 TEST_F(GLRendererWithDefaultHarnessTest
,
346 FramebufferDiscardedAfterReadbackWhenNotVisible
) {
347 gfx::Rect
viewport_rect(1, 1);
348 renderer_
->SetVisible(false);
349 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
350 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
352 AddRenderPass(&render_passes_in_draw_order_
,
353 RenderPass::Id(1, 0),
358 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
364 EXPECT_FALSE(renderer_
->IsBackbufferDiscarded());
366 renderer_
->GetFramebufferPixels(pixels
, gfx::Rect(0, 0, 1, 1));
367 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
368 EXPECT_EQ(2, renderer_client_
.set_full_root_layer_damage_count());
371 TEST_F(GLRendererWithDefaultHarnessTest
, ExternalStencil
) {
372 gfx::Rect
viewport_rect(1, 1);
373 EXPECT_FALSE(renderer_
->stencil_enabled());
375 output_surface_
->set_has_external_stencil_test(true);
377 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
378 RenderPass::Id(1, 0),
381 root_pass
->has_transparent_background
= false;
383 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
389 EXPECT_TRUE(renderer_
->stencil_enabled());
392 class ForbidSynchronousCallContext
: public TestWebGraphicsContext3D
{
394 ForbidSynchronousCallContext() {}
396 virtual void getAttachedShaders(GLuint program
,
399 GLuint
* shaders
) OVERRIDE
{
402 virtual GLint
getAttribLocation(GLuint program
, const GLchar
* name
) OVERRIDE
{
406 virtual void getBooleanv(GLenum pname
, GLboolean
* value
) OVERRIDE
{
409 virtual void getBufferParameteriv(GLenum target
,
411 GLint
* value
) OVERRIDE
{
414 virtual GLenum
getError() OVERRIDE
{
418 virtual void getFloatv(GLenum pname
, GLfloat
* value
) OVERRIDE
{
421 virtual void getFramebufferAttachmentParameteriv(GLenum target
,
424 GLint
* value
) OVERRIDE
{
427 virtual void getIntegerv(GLenum pname
, GLint
* value
) OVERRIDE
{
428 if (pname
== GL_MAX_TEXTURE_SIZE
) {
429 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
436 // We allow querying the shader compilation and program link status in debug
437 // mode, but not release.
438 virtual void getProgramiv(GLuint program
,
440 GLint
* value
) OVERRIDE
{
448 virtual void getShaderiv(GLuint shader
, GLenum pname
, GLint
* value
) OVERRIDE
{
456 virtual void getRenderbufferParameteriv(GLenum target
,
458 GLint
* value
) OVERRIDE
{
462 virtual void getShaderPrecisionFormat(GLenum shadertype
,
463 GLenum precisiontype
,
465 GLint
* precision
) OVERRIDE
{
468 virtual void getTexParameterfv(GLenum target
,
470 GLfloat
* value
) OVERRIDE
{
473 virtual void getTexParameteriv(GLenum target
,
475 GLint
* value
) OVERRIDE
{
478 virtual void getUniformfv(GLuint program
,
480 GLfloat
* value
) OVERRIDE
{
483 virtual void getUniformiv(GLuint program
,
485 GLint
* value
) OVERRIDE
{
488 virtual GLint
getUniformLocation(GLuint program
,
489 const GLchar
* name
) OVERRIDE
{
493 virtual void getVertexAttribfv(GLuint index
,
495 GLfloat
* value
) OVERRIDE
{
498 virtual void getVertexAttribiv(GLuint index
,
500 GLint
* value
) OVERRIDE
{
503 virtual GLsizeiptr
getVertexAttribOffset(GLuint index
,
504 GLenum pname
) OVERRIDE
{
509 TEST_F(GLRendererTest
, InitializationDoesNotMakeSynchronousCalls
) {
510 FakeOutputSurfaceClient output_surface_client
;
511 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
512 scoped_ptr
<TestWebGraphicsContext3D
>(new ForbidSynchronousCallContext
)));
513 CHECK(output_surface
->BindToClient(&output_surface_client
));
515 scoped_ptr
<ResourceProvider
> resource_provider(
516 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
518 LayerTreeSettings settings
;
519 FakeRendererClient renderer_client
;
520 FakeRendererGL
renderer(&renderer_client
,
522 output_surface
.get(),
523 resource_provider
.get());
526 class LoseContextOnFirstGetContext
: public TestWebGraphicsContext3D
{
528 LoseContextOnFirstGetContext() {}
530 virtual void getProgramiv(GLuint program
,
532 GLint
* value
) OVERRIDE
{
533 context_lost_
= true;
537 virtual void getShaderiv(GLuint shader
, GLenum pname
, GLint
* value
) OVERRIDE
{
538 context_lost_
= true;
543 TEST_F(GLRendererTest
, InitializationWithQuicklyLostContextDoesNotAssert
) {
544 FakeOutputSurfaceClient output_surface_client
;
545 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
546 scoped_ptr
<TestWebGraphicsContext3D
>(new LoseContextOnFirstGetContext
)));
547 CHECK(output_surface
->BindToClient(&output_surface_client
));
549 scoped_ptr
<ResourceProvider
> resource_provider(
550 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
552 LayerTreeSettings settings
;
553 FakeRendererClient renderer_client
;
554 FakeRendererGL
renderer(&renderer_client
,
556 output_surface
.get(),
557 resource_provider
.get());
560 class ClearCountingContext
: public TestWebGraphicsContext3D
{
562 ClearCountingContext() { test_capabilities_
.gpu
.discard_framebuffer
= true; }
564 MOCK_METHOD3(discardFramebufferEXT
,
566 GLsizei numAttachments
,
567 const GLenum
* attachments
));
568 MOCK_METHOD1(clear
, void(GLbitfield mask
));
571 TEST_F(GLRendererTest
, OpaqueBackground
) {
572 scoped_ptr
<ClearCountingContext
> context_owned(new ClearCountingContext
);
573 ClearCountingContext
* context
= context_owned
.get();
575 FakeOutputSurfaceClient output_surface_client
;
576 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
577 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
578 CHECK(output_surface
->BindToClient(&output_surface_client
));
580 scoped_ptr
<ResourceProvider
> resource_provider(
581 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
583 LayerTreeSettings settings
;
584 FakeRendererClient renderer_client
;
585 FakeRendererGL
renderer(&renderer_client
,
587 output_surface
.get(),
588 resource_provider
.get());
590 gfx::Rect
viewport_rect(1, 1);
591 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
592 RenderPass::Id(1, 0),
595 root_pass
->has_transparent_background
= false;
597 // On DEBUG builds, render passes with opaque background clear to blue to
598 // easily see regions that were not drawn on the screen.
599 EXPECT_CALL(*context
, discardFramebufferEXT(GL_FRAMEBUFFER
, _
, _
))
600 .With(Args
<2, 1>(ElementsAre(GL_COLOR_EXT
)))
603 EXPECT_CALL(*context
, clear(_
)).Times(0);
605 EXPECT_CALL(*context
, clear(_
)).Times(1);
607 renderer
.DrawFrame(&render_passes_in_draw_order_
,
613 Mock::VerifyAndClearExpectations(context
);
616 TEST_F(GLRendererTest
, TransparentBackground
) {
617 scoped_ptr
<ClearCountingContext
> context_owned(new ClearCountingContext
);
618 ClearCountingContext
* context
= context_owned
.get();
620 FakeOutputSurfaceClient output_surface_client
;
621 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
622 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
623 CHECK(output_surface
->BindToClient(&output_surface_client
));
625 scoped_ptr
<ResourceProvider
> resource_provider(
626 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
628 LayerTreeSettings settings
;
629 FakeRendererClient renderer_client
;
630 FakeRendererGL
renderer(&renderer_client
,
632 output_surface
.get(),
633 resource_provider
.get());
635 gfx::Rect
viewport_rect(1, 1);
636 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
637 RenderPass::Id(1, 0),
640 root_pass
->has_transparent_background
= true;
642 EXPECT_CALL(*context
, discardFramebufferEXT(GL_FRAMEBUFFER
, 1, _
)).Times(1);
643 EXPECT_CALL(*context
, clear(_
)).Times(1);
644 renderer
.DrawFrame(&render_passes_in_draw_order_
,
651 Mock::VerifyAndClearExpectations(context
);
654 TEST_F(GLRendererTest
, OffscreenOutputSurface
) {
655 scoped_ptr
<ClearCountingContext
> context_owned(new ClearCountingContext
);
656 ClearCountingContext
* context
= context_owned
.get();
658 FakeOutputSurfaceClient output_surface_client
;
659 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::CreateOffscreen(
660 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
661 CHECK(output_surface
->BindToClient(&output_surface_client
));
663 scoped_ptr
<ResourceProvider
> resource_provider(
664 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
666 LayerTreeSettings settings
;
667 FakeRendererClient renderer_client
;
668 FakeRendererGL
renderer(&renderer_client
,
670 output_surface
.get(),
671 resource_provider
.get());
673 gfx::Rect
viewport_rect(1, 1);
674 AddRenderPass(&render_passes_in_draw_order_
,
675 RenderPass::Id(1, 0),
679 EXPECT_CALL(*context
, discardFramebufferEXT(GL_FRAMEBUFFER
, _
, _
))
680 .With(Args
<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0
)))
682 EXPECT_CALL(*context
, clear(_
)).Times(AnyNumber());
683 renderer
.DrawFrame(&render_passes_in_draw_order_
,
689 Mock::VerifyAndClearExpectations(context
);
692 class VisibilityChangeIsLastCallTrackingContext
693 : public TestWebGraphicsContext3D
{
695 VisibilityChangeIsLastCallTrackingContext()
696 : last_call_was_set_visibility_(false) {}
698 // TestWebGraphicsContext3D methods.
699 virtual void flush() OVERRIDE
{ last_call_was_set_visibility_
= false; }
700 virtual void deleteTexture(GLuint
) OVERRIDE
{
701 last_call_was_set_visibility_
= false;
703 virtual void deleteFramebuffer(GLuint
) OVERRIDE
{
704 last_call_was_set_visibility_
= false;
706 virtual void deleteQueryEXT(GLuint
) OVERRIDE
{
707 last_call_was_set_visibility_
= false;
709 virtual void deleteRenderbuffer(GLuint
) OVERRIDE
{
710 last_call_was_set_visibility_
= false;
713 // Methods added for test.
714 void set_last_call_was_visibility(bool visible
) {
715 DCHECK(last_call_was_set_visibility_
== false);
716 last_call_was_set_visibility_
= true;
718 bool last_call_was_set_visibility() const {
719 return last_call_was_set_visibility_
;
723 bool last_call_was_set_visibility_
;
726 TEST_F(GLRendererTest
, VisibilityChangeIsLastCall
) {
727 scoped_ptr
<VisibilityChangeIsLastCallTrackingContext
> context_owned(
728 new VisibilityChangeIsLastCallTrackingContext
);
729 VisibilityChangeIsLastCallTrackingContext
* context
= context_owned
.get();
731 scoped_refptr
<TestContextProvider
> provider
= TestContextProvider::Create(
732 context_owned
.PassAs
<TestWebGraphicsContext3D
>());
734 provider
->support()->SetSurfaceVisibleCallback(base::Bind(
735 &VisibilityChangeIsLastCallTrackingContext::set_last_call_was_visibility
,
736 base::Unretained(context
)));
738 FakeOutputSurfaceClient output_surface_client
;
739 scoped_ptr
<OutputSurface
> output_surface(
740 FakeOutputSurface::Create3d(provider
));
741 CHECK(output_surface
->BindToClient(&output_surface_client
));
743 scoped_ptr
<ResourceProvider
> resource_provider(
744 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
746 LayerTreeSettings settings
;
747 FakeRendererClient renderer_client
;
748 FakeRendererGL
renderer(&renderer_client
,
750 output_surface
.get(),
751 resource_provider
.get());
753 gfx::Rect
viewport_rect(1, 1);
754 AddRenderPass(&render_passes_in_draw_order_
,
755 RenderPass::Id(1, 0),
759 // Ensure that the call to SetSurfaceVisible is the last call issue to the
760 // GPU process, after glFlush is called, and after the RendererClient's
761 // SetManagedMemoryPolicy is called. Plumb this tracking between both the
762 // RenderClient and the Context by giving them both a pointer to a variable on
764 renderer
.SetVisible(true);
765 renderer
.DrawFrame(&render_passes_in_draw_order_
,
771 renderer
.SetVisible(false);
772 EXPECT_TRUE(context
->last_call_was_set_visibility());
775 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
777 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM
) {
778 test_capabilities_
.gpu
.egl_image_external
= true;
781 MOCK_METHOD3(texParameteri
, void(GLenum target
, GLenum pname
, GLint param
));
782 MOCK_METHOD4(drawElements
,
783 void(GLenum mode
, GLsizei count
, GLenum type
, GLintptr offset
));
785 virtual void activeTexture(GLenum texture
) {
786 EXPECT_NE(texture
, active_texture_
);
787 active_texture_
= texture
;
790 GLenum
active_texture() const { return active_texture_
; }
793 GLenum active_texture_
;
796 TEST_F(GLRendererTest
, ActiveTextureState
) {
797 scoped_ptr
<TextureStateTrackingContext
> context_owned(
798 new TextureStateTrackingContext
);
799 TextureStateTrackingContext
* context
= context_owned
.get();
801 FakeOutputSurfaceClient output_surface_client
;
802 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
803 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
804 CHECK(output_surface
->BindToClient(&output_surface_client
));
806 scoped_ptr
<ResourceProvider
> resource_provider(
807 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
809 LayerTreeSettings settings
;
810 FakeRendererClient renderer_client
;
811 FakeRendererGL
renderer(&renderer_client
,
813 output_surface
.get(),
814 resource_provider
.get());
816 // During initialization we are allowed to set any texture parameters.
817 EXPECT_CALL(*context
, texParameteri(_
, _
, _
)).Times(AnyNumber());
819 RenderPass::Id
id(1, 1);
820 TestRenderPass
* root_pass
= AddRenderPass(
821 &render_passes_in_draw_order_
, id
, gfx::Rect(100, 100), gfx::Transform());
822 root_pass
->AppendOneOfEveryQuadType(resource_provider
.get(),
823 RenderPass::Id(2, 1));
825 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
827 // Set up expected texture filter state transitions that match the quads
828 // created in AppendOneOfEveryQuadType().
829 Mock::VerifyAndClearExpectations(context
);
833 // yuv_quad is drawn with the default linear filter.
834 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
836 // tile_quad is drawn with GL_NEAREST because it is not transformed or
840 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
843 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
844 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
846 // transformed_tile_quad uses GL_LINEAR.
847 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
849 // scaled_tile_quad also uses GL_LINEAR.
850 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
852 // The remaining quads also use GL_LINEAR because nearest neighbor
853 // filtering is currently only used with tile quads.
854 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
)).Times(6);
857 gfx::Rect
viewport_rect(100, 100);
858 renderer
.DrawFrame(&render_passes_in_draw_order_
,
864 Mock::VerifyAndClearExpectations(context
);
867 class NoClearRootRenderPassMockContext
: public TestWebGraphicsContext3D
{
869 MOCK_METHOD1(clear
, void(GLbitfield mask
));
870 MOCK_METHOD4(drawElements
,
871 void(GLenum mode
, GLsizei count
, GLenum type
, GLintptr offset
));
874 TEST_F(GLRendererTest
, ShouldClearRootRenderPass
) {
875 scoped_ptr
<NoClearRootRenderPassMockContext
> mock_context_owned(
876 new NoClearRootRenderPassMockContext
);
877 NoClearRootRenderPassMockContext
* mock_context
= mock_context_owned
.get();
879 FakeOutputSurfaceClient output_surface_client
;
880 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
881 mock_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
882 CHECK(output_surface
->BindToClient(&output_surface_client
));
884 scoped_ptr
<ResourceProvider
> resource_provider(
885 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
887 LayerTreeSettings settings
;
888 settings
.should_clear_root_render_pass
= false;
890 FakeRendererClient renderer_client
;
891 FakeRendererGL
renderer(&renderer_client
,
893 output_surface
.get(),
894 resource_provider
.get());
896 gfx::Rect
viewport_rect(10, 10);
898 RenderPass::Id
root_pass_id(1, 0);
899 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
903 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
905 RenderPass::Id
child_pass_id(2, 0);
906 TestRenderPass
* child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
910 AddQuad(child_pass
, viewport_rect
, SK_ColorBLUE
);
912 AddRenderPassQuad(root_pass
, child_pass
);
915 GLint clear_bits
= GL_COLOR_BUFFER_BIT
;
917 GLint clear_bits
= GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
;
920 // First render pass is not the root one, clearing should happen.
921 EXPECT_CALL(*mock_context
, clear(clear_bits
)).Times(AtLeast(1));
923 Expectation first_render_pass
=
924 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
)).Times(1);
926 // The second render pass is the root one, clearing should be prevented.
927 EXPECT_CALL(*mock_context
, clear(clear_bits
)).Times(0).After(
930 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
)).Times(AnyNumber()).After(
933 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
934 renderer
.DrawFrame(&render_passes_in_draw_order_
,
941 // In multiple render passes all but the root pass should clear the
943 Mock::VerifyAndClearExpectations(&mock_context
);
946 class ScissorTestOnClearCheckingContext
: public TestWebGraphicsContext3D
{
948 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
950 virtual void clear(GLbitfield
) OVERRIDE
{ EXPECT_FALSE(scissor_enabled_
); }
952 virtual void enable(GLenum cap
) OVERRIDE
{
953 if (cap
== GL_SCISSOR_TEST
)
954 scissor_enabled_
= true;
957 virtual void disable(GLenum cap
) OVERRIDE
{
958 if (cap
== GL_SCISSOR_TEST
)
959 scissor_enabled_
= false;
963 bool scissor_enabled_
;
966 TEST_F(GLRendererTest
, ScissorTestWhenClearing
) {
967 scoped_ptr
<ScissorTestOnClearCheckingContext
> context_owned(
968 new ScissorTestOnClearCheckingContext
);
970 FakeOutputSurfaceClient output_surface_client
;
971 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
972 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
973 CHECK(output_surface
->BindToClient(&output_surface_client
));
975 scoped_ptr
<ResourceProvider
> resource_provider(
976 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
978 LayerTreeSettings settings
;
979 FakeRendererClient renderer_client
;
980 FakeRendererGL
renderer(&renderer_client
,
982 output_surface
.get(),
983 resource_provider
.get());
984 EXPECT_FALSE(renderer
.Capabilities().using_partial_swap
);
986 gfx::Rect
viewport_rect(1, 1);
988 gfx::Rect
grand_child_rect(25, 25);
989 RenderPass::Id
grand_child_pass_id(3, 0);
990 TestRenderPass
* grand_child_pass
=
991 AddRenderPass(&render_passes_in_draw_order_
,
995 AddClippedQuad(grand_child_pass
, grand_child_rect
, SK_ColorYELLOW
);
997 gfx::Rect
child_rect(50, 50);
998 RenderPass::Id
child_pass_id(2, 0);
999 TestRenderPass
* child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1003 AddQuad(child_pass
, child_rect
, SK_ColorBLUE
);
1005 RenderPass::Id
root_pass_id(1, 0);
1006 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1010 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1012 AddRenderPassQuad(root_pass
, child_pass
);
1013 AddRenderPassQuad(child_pass
, grand_child_pass
);
1015 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1016 renderer
.DrawFrame(&render_passes_in_draw_order_
,
1024 class DiscardCheckingContext
: public TestWebGraphicsContext3D
{
1026 DiscardCheckingContext() : discarded_(0) {
1027 set_have_post_sub_buffer(true);
1028 set_have_discard_framebuffer(true);
1031 virtual void discardFramebufferEXT(GLenum target
,
1032 GLsizei numAttachments
,
1033 const GLenum
* attachments
) OVERRIDE
{
1037 int discarded() const { return discarded_
; }
1038 void reset() { discarded_
= 0; }
1044 class NonReshapableOutputSurface
: public FakeOutputSurface
{
1046 explicit NonReshapableOutputSurface(
1047 scoped_ptr
<TestWebGraphicsContext3D
> context3d
)
1048 : FakeOutputSurface(TestContextProvider::Create(context3d
.Pass()),
1050 surface_size_
= gfx::Size(500, 500);
1052 virtual void Reshape(const gfx::Size
& size
, float scale_factor
) OVERRIDE
{}
1053 void set_fixed_size(const gfx::Size
& size
) { surface_size_
= size
; }
1056 TEST_F(GLRendererTest
, NoDiscardOnPartialUpdates
) {
1057 scoped_ptr
<DiscardCheckingContext
> context_owned(new DiscardCheckingContext
);
1058 DiscardCheckingContext
* context
= context_owned
.get();
1060 FakeOutputSurfaceClient output_surface_client
;
1061 scoped_ptr
<NonReshapableOutputSurface
> output_surface(
1062 new NonReshapableOutputSurface(
1063 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1064 CHECK(output_surface
->BindToClient(&output_surface_client
));
1065 output_surface
->set_fixed_size(gfx::Size(100, 100));
1067 scoped_ptr
<ResourceProvider
> resource_provider(
1068 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
1070 LayerTreeSettings settings
;
1071 settings
.partial_swap_enabled
= true;
1072 FakeRendererClient renderer_client
;
1073 FakeRendererGL
renderer(&renderer_client
,
1075 output_surface
.get(),
1076 resource_provider
.get());
1077 EXPECT_TRUE(renderer
.Capabilities().using_partial_swap
);
1079 gfx::Rect
viewport_rect(100, 100);
1080 gfx::Rect
clip_rect(100, 100);
1083 // Partial frame, should not discard.
1084 RenderPass::Id
root_pass_id(1, 0);
1085 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1089 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1090 root_pass
->damage_rect
= gfx::RectF(2.f
, 2.f
, 3.f
, 3.f
);
1092 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1093 renderer
.DrawFrame(&render_passes_in_draw_order_
,
1099 EXPECT_EQ(0, context
->discarded());
1103 // Full frame, should discard.
1104 RenderPass::Id
root_pass_id(1, 0);
1105 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1109 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1110 root_pass
->damage_rect
= gfx::RectF(root_pass
->output_rect
);
1112 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1113 renderer
.DrawFrame(&render_passes_in_draw_order_
,
1119 EXPECT_EQ(1, context
->discarded());
1123 // Full frame, external scissor is set, should not discard.
1124 output_surface
->set_has_external_stencil_test(true);
1125 RenderPass::Id
root_pass_id(1, 0);
1126 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1130 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1131 root_pass
->damage_rect
= gfx::RectF(root_pass
->output_rect
);
1132 root_pass
->has_transparent_background
= false;
1134 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1135 renderer
.DrawFrame(&render_passes_in_draw_order_
,
1141 EXPECT_EQ(0, context
->discarded());
1143 output_surface
->set_has_external_stencil_test(false);
1146 // Full frame, clipped, should not discard.
1147 clip_rect
= gfx::Rect(10, 10, 10, 10);
1148 RenderPass::Id
root_pass_id(1, 0);
1149 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1153 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1154 root_pass
->damage_rect
= gfx::RectF(root_pass
->output_rect
);
1156 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1157 renderer
.DrawFrame(&render_passes_in_draw_order_
,
1163 EXPECT_EQ(0, context
->discarded());
1167 // Full frame, doesn't cover the surface, should not discard.
1168 viewport_rect
= gfx::Rect(10, 10, 10, 10);
1169 RenderPass::Id
root_pass_id(1, 0);
1170 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1174 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1175 root_pass
->damage_rect
= gfx::RectF(root_pass
->output_rect
);
1177 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1178 renderer
.DrawFrame(&render_passes_in_draw_order_
,
1184 EXPECT_EQ(0, context
->discarded());
1188 // Full frame, doesn't cover the surface (no offset), should not discard.
1189 clip_rect
= gfx::Rect(100, 100);
1190 viewport_rect
= gfx::Rect(50, 50);
1191 RenderPass::Id
root_pass_id(1, 0);
1192 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1196 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1197 root_pass
->damage_rect
= gfx::RectF(root_pass
->output_rect
);
1199 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1200 renderer
.DrawFrame(&render_passes_in_draw_order_
,
1206 EXPECT_EQ(0, context
->discarded());
1211 class FlippedScissorAndViewportContext
: public TestWebGraphicsContext3D
{
1213 FlippedScissorAndViewportContext()
1214 : did_call_viewport_(false), did_call_scissor_(false) {}
1215 virtual ~FlippedScissorAndViewportContext() {
1216 EXPECT_TRUE(did_call_viewport_
);
1217 EXPECT_TRUE(did_call_scissor_
);
1220 virtual void viewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1224 EXPECT_EQ(100, width
);
1225 EXPECT_EQ(100, height
);
1226 did_call_viewport_
= true;
1229 virtual void scissor(GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1233 EXPECT_EQ(20, width
);
1234 EXPECT_EQ(20, height
);
1235 did_call_scissor_
= true;
1239 bool did_call_viewport_
;
1240 bool did_call_scissor_
;
1243 TEST_F(GLRendererTest
, ScissorAndViewportWithinNonreshapableSurface
) {
1244 // In Android WebView, the OutputSurface is unable to respect reshape() calls
1245 // and maintains a fixed size. This test verifies that glViewport and
1246 // glScissor's Y coordinate is flipped correctly in this environment, and that
1247 // the glViewport can be at a nonzero origin within the surface.
1248 scoped_ptr
<FlippedScissorAndViewportContext
> context_owned(
1249 new FlippedScissorAndViewportContext
);
1251 FakeOutputSurfaceClient output_surface_client
;
1252 scoped_ptr
<OutputSurface
> output_surface(new NonReshapableOutputSurface(
1253 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1254 CHECK(output_surface
->BindToClient(&output_surface_client
));
1256 scoped_ptr
<ResourceProvider
> resource_provider(
1257 ResourceProvider::Create(output_surface
.get(), NULL
, 0, false, 1));
1259 LayerTreeSettings settings
;
1260 FakeRendererClient renderer_client
;
1261 FakeRendererGL
renderer(&renderer_client
,
1263 output_surface
.get(),
1264 resource_provider
.get());
1265 EXPECT_FALSE(renderer
.Capabilities().using_partial_swap
);
1267 gfx::Rect
device_viewport_rect(10, 10, 100, 100);
1268 gfx::Rect
viewport_rect(device_viewport_rect
.size());
1269 gfx::Rect quad_rect
= gfx::Rect(20, 20, 20, 20);
1271 RenderPass::Id
root_pass_id(1, 0);
1272 TestRenderPass
* root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1276 AddClippedQuad(root_pass
, quad_rect
, SK_ColorGREEN
);
1278 renderer
.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1279 renderer
.DrawFrame(&render_passes_in_draw_order_
,
1282 device_viewport_rect
,
1283 device_viewport_rect
,
1287 TEST_F(GLRendererShaderTest
, DrawRenderPassQuadShaderPermutations
) {
1288 gfx::Rect
viewport_rect(1, 1);
1290 gfx::Rect
child_rect(50, 50);
1291 RenderPass::Id
child_pass_id(2, 0);
1292 TestRenderPass
* child_pass
;
1294 RenderPass::Id
root_pass_id(1, 0);
1295 TestRenderPass
* root_pass
;
1297 ResourceProvider::ResourceId mask
= resource_provider_
->CreateResource(
1300 ResourceProvider::TextureUsageAny
,
1301 resource_provider_
->best_texture_format());
1302 resource_provider_
->AllocateForTesting(mask
);
1304 SkScalar matrix
[20];
1305 float amount
= 0.5f
;
1306 matrix
[0] = 0.213f
+ 0.787f
* amount
;
1307 matrix
[1] = 0.715f
- 0.715f
* amount
;
1308 matrix
[2] = 1.f
- (matrix
[0] + matrix
[1]);
1309 matrix
[3] = matrix
[4] = 0;
1310 matrix
[5] = 0.213f
- 0.213f
* amount
;
1311 matrix
[6] = 0.715f
+ 0.285f
* amount
;
1312 matrix
[7] = 1.f
- (matrix
[5] + matrix
[6]);
1313 matrix
[8] = matrix
[9] = 0;
1314 matrix
[10] = 0.213f
- 0.213f
* amount
;
1315 matrix
[11] = 0.715f
- 0.715f
* amount
;
1316 matrix
[12] = 1.f
- (matrix
[10] + matrix
[11]);
1317 matrix
[13] = matrix
[14] = 0;
1318 matrix
[15] = matrix
[16] = matrix
[17] = matrix
[19] = 0;
1320 skia::RefPtr
<SkColorFilter
> color_filter(
1321 skia::AdoptRef(new SkColorMatrixFilter(matrix
)));
1322 skia::RefPtr
<SkImageFilter
> filter
= skia::AdoptRef(
1323 SkColorFilterImageFilter::Create(color_filter
.get(), NULL
));
1324 FilterOperations filters
;
1325 filters
.Append(FilterOperation::CreateReferenceFilter(filter
));
1327 gfx::Transform transform_causing_aa
;
1328 transform_causing_aa
.Rotate(20.0);
1330 // RenderPassProgram
1331 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1336 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1342 root_pass
, child_pass
, 0, FilterOperations(), gfx::Transform());
1344 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1345 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1351 TestRenderPassProgram(TexCoordPrecisionMedium
);
1353 // RenderPassColorMatrixProgram
1354 render_passes_in_draw_order_
.clear();
1356 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1359 transform_causing_aa
);
1361 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1366 AddRenderPassQuad(root_pass
, child_pass
, 0, filters
, gfx::Transform());
1368 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1369 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1375 TestRenderPassColorMatrixProgram(TexCoordPrecisionMedium
);
1377 // RenderPassMaskProgram
1378 render_passes_in_draw_order_
.clear();
1380 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1385 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1391 root_pass
, child_pass
, mask
, FilterOperations(), gfx::Transform());
1393 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1394 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1400 TestRenderPassMaskProgram(TexCoordPrecisionMedium
);
1402 // RenderPassMaskColorMatrixProgram
1403 render_passes_in_draw_order_
.clear();
1405 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1410 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1415 AddRenderPassQuad(root_pass
, child_pass
, mask
, filters
, gfx::Transform());
1417 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1418 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1424 TestRenderPassMaskColorMatrixProgram(TexCoordPrecisionMedium
);
1426 // RenderPassProgramAA
1427 render_passes_in_draw_order_
.clear();
1429 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1432 transform_causing_aa
);
1434 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1440 root_pass
, child_pass
, 0, FilterOperations(), transform_causing_aa
);
1442 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1443 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1449 TestRenderPassProgramAA(TexCoordPrecisionMedium
);
1451 // RenderPassColorMatrixProgramAA
1452 render_passes_in_draw_order_
.clear();
1454 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1457 transform_causing_aa
);
1459 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1464 AddRenderPassQuad(root_pass
, child_pass
, 0, filters
, transform_causing_aa
);
1466 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1467 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1473 TestRenderPassColorMatrixProgramAA(TexCoordPrecisionMedium
);
1475 // RenderPassMaskProgramAA
1476 render_passes_in_draw_order_
.clear();
1478 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1481 transform_causing_aa
);
1483 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1489 root_pass
, child_pass
, mask
, FilterOperations(), transform_causing_aa
);
1491 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1492 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1498 TestRenderPassMaskProgramAA(TexCoordPrecisionMedium
);
1500 // RenderPassMaskColorMatrixProgramAA
1501 render_passes_in_draw_order_
.clear();
1503 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1506 transform_causing_aa
);
1508 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1511 transform_causing_aa
);
1513 AddRenderPassQuad(root_pass
, child_pass
, mask
, filters
, transform_causing_aa
);
1515 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1516 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1522 TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecisionMedium
);
1525 // At this time, the AA code path cannot be taken if the surface's rect would
1526 // project incorrectly by the given transform, because of w<0 clipping.
1527 TEST_F(GLRendererShaderTest
, DrawRenderPassQuadSkipsAAForClippingTransform
) {
1528 gfx::Rect
child_rect(50, 50);
1529 RenderPass::Id
child_pass_id(2, 0);
1530 TestRenderPass
* child_pass
;
1532 gfx::Rect
viewport_rect(1, 1);
1533 RenderPass::Id
root_pass_id(1, 0);
1534 TestRenderPass
* root_pass
;
1536 gfx::Transform transform_preventing_aa
;
1537 transform_preventing_aa
.ApplyPerspectiveDepth(40.0);
1538 transform_preventing_aa
.RotateAboutYAxis(-20.0);
1539 transform_preventing_aa
.Scale(30.0, 1.0);
1541 // Verify that the test transform and test rect actually do cause the clipped
1542 // flag to trigger. Otherwise we are not testing the intended scenario.
1543 bool clipped
= false;
1544 MathUtil::MapQuad(transform_preventing_aa
, gfx::QuadF(child_rect
), &clipped
);
1545 ASSERT_TRUE(clipped
);
1547 child_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1550 transform_preventing_aa
);
1552 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1558 root_pass
, child_pass
, 0, FilterOperations(), transform_preventing_aa
);
1560 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1561 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1568 // If use_aa incorrectly ignores clipping, it will use the
1569 // RenderPassProgramAA shader instead of the RenderPassProgram.
1570 TestRenderPassProgram(TexCoordPrecisionMedium
);
1573 TEST_F(GLRendererShaderTest
, DrawSolidColorShader
) {
1574 gfx::Rect
viewport_rect(1, 1);
1575 RenderPass::Id
root_pass_id(1, 0);
1576 TestRenderPass
* root_pass
;
1578 gfx::Transform pixel_aligned_transform_causing_aa
;
1579 pixel_aligned_transform_causing_aa
.Translate(25.5f
, 25.5f
);
1580 pixel_aligned_transform_causing_aa
.Scale(0.5f
, 0.5f
);
1582 root_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1586 AddTransformedQuad(root_pass
,
1589 pixel_aligned_transform_causing_aa
);
1591 renderer_
->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_
);
1592 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1599 TestSolidColorProgramAA();
1602 class OutputSurfaceMockContext
: public TestWebGraphicsContext3D
{
1604 OutputSurfaceMockContext() { test_capabilities_
.gpu
.post_sub_buffer
= true; }
1606 // Specifically override methods even if they are unused (used in conjunction
1607 // with StrictMock). We need to make sure that GLRenderer does not issue
1608 // framebuffer-related GLuint calls directly. Instead these are supposed to go
1609 // through the OutputSurface abstraction.
1610 MOCK_METHOD2(bindFramebuffer
, void(GLenum target
, GLuint framebuffer
));
1611 MOCK_METHOD3(reshapeWithScaleFactor
,
1612 void(int width
, int height
, float scale_factor
));
1613 MOCK_METHOD4(drawElements
,
1614 void(GLenum mode
, GLsizei count
, GLenum type
, GLintptr offset
));
1617 class MockOutputSurface
: public OutputSurface
{
1621 TestContextProvider::Create(scoped_ptr
<TestWebGraphicsContext3D
>(
1622 new StrictMock
<OutputSurfaceMockContext
>))) {
1623 surface_size_
= gfx::Size(100, 100);
1625 virtual ~MockOutputSurface() {}
1627 MOCK_METHOD0(EnsureBackbuffer
, void());
1628 MOCK_METHOD0(DiscardBackbuffer
, void());
1629 MOCK_METHOD2(Reshape
, void(const gfx::Size
& size
, float scale_factor
));
1630 MOCK_METHOD0(BindFramebuffer
, void());
1631 MOCK_METHOD1(SwapBuffers
, void(CompositorFrame
* frame
));
1634 class MockOutputSurfaceTest
: public GLRendererTest
{
1636 virtual void SetUp() {
1637 FakeOutputSurfaceClient output_surface_client_
;
1638 CHECK(output_surface_
.BindToClient(&output_surface_client_
));
1640 resource_provider_
=
1641 ResourceProvider::Create(&output_surface_
, NULL
, 0, false, 1).Pass();
1643 renderer_
.reset(new FakeRendererGL(&renderer_client_
,
1646 resource_provider_
.get()));
1649 void SwapBuffers() { renderer_
->SwapBuffers(CompositorFrameMetadata()); }
1651 void DrawFrame(float device_scale_factor
,
1652 const gfx::Rect
& device_viewport_rect
) {
1653 RenderPass::Id
render_pass_id(1, 0);
1654 TestRenderPass
* render_pass
= AddRenderPass(&render_passes_in_draw_order_
,
1656 device_viewport_rect
,
1658 AddQuad(render_pass
, device_viewport_rect
, SK_ColorGREEN
);
1660 EXPECT_CALL(output_surface_
, EnsureBackbuffer()).WillRepeatedly(Return());
1662 EXPECT_CALL(output_surface_
,
1663 Reshape(device_viewport_rect
.size(), device_scale_factor
))
1666 EXPECT_CALL(output_surface_
, BindFramebuffer()).Times(1);
1668 EXPECT_CALL(*Context(), drawElements(_
, _
, _
, _
)).Times(1);
1670 renderer_
->DecideRenderPassAllocationsForFrame(
1671 render_passes_in_draw_order_
);
1672 renderer_
->DrawFrame(&render_passes_in_draw_order_
,
1674 device_scale_factor
,
1675 device_viewport_rect
,
1676 device_viewport_rect
,
1680 OutputSurfaceMockContext
* Context() {
1681 return static_cast<OutputSurfaceMockContext
*>(
1682 static_cast<TestContextProvider
*>(
1683 output_surface_
.context_provider().get())->TestContext3d());
1686 LayerTreeSettings settings_
;
1687 FakeOutputSurfaceClient output_surface_client_
;
1688 StrictMock
<MockOutputSurface
> output_surface_
;
1689 scoped_ptr
<ResourceProvider
> resource_provider_
;
1690 FakeRendererClient renderer_client_
;
1691 scoped_ptr
<FakeRendererGL
> renderer_
;
1694 TEST_F(MockOutputSurfaceTest
, DrawFrameAndSwap
) {
1695 gfx::Rect
device_viewport_rect(1, 1);
1696 DrawFrame(1.f
, device_viewport_rect
);
1698 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1699 renderer_
->SwapBuffers(CompositorFrameMetadata());
1702 TEST_F(MockOutputSurfaceTest
, DrawFrameAndResizeAndSwap
) {
1703 gfx::Rect
device_viewport_rect(1, 1);
1705 DrawFrame(1.f
, device_viewport_rect
);
1706 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1707 renderer_
->SwapBuffers(CompositorFrameMetadata());
1709 device_viewport_rect
= gfx::Rect(2, 2);
1711 DrawFrame(2.f
, device_viewport_rect
);
1712 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1713 renderer_
->SwapBuffers(CompositorFrameMetadata());
1715 DrawFrame(2.f
, device_viewport_rect
);
1716 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1717 renderer_
->SwapBuffers(CompositorFrameMetadata());
1719 device_viewport_rect
= gfx::Rect(1, 1);
1721 DrawFrame(1.f
, device_viewport_rect
);
1722 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1723 renderer_
->SwapBuffers(CompositorFrameMetadata());
1726 class GLRendererTestSyncPoint
: public GLRendererPixelTest
{
1728 static void SyncPointCallback(int* callback_count
) {
1729 ++(*callback_count
);
1730 base::MessageLoop::current()->QuitWhenIdle();
1733 static void OtherCallback(int* callback_count
) {
1734 ++(*callback_count
);
1735 base::MessageLoop::current()->QuitWhenIdle();
1739 #if !defined(OS_ANDROID)
1740 TEST_F(GLRendererTestSyncPoint
, SignalSyncPointOnLostContext
) {
1741 int sync_point_callback_count
= 0;
1742 int other_callback_count
= 0;
1743 gpu::gles2::GLES2Interface
* gl
=
1744 output_surface_
->context_provider()->ContextGL();
1745 gpu::ContextSupport
* context_support
=
1746 output_surface_
->context_provider()->ContextSupport();
1748 uint32 sync_point
= gl
->InsertSyncPointCHROMIUM();
1750 gl
->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
1751 GL_INNOCENT_CONTEXT_RESET_ARB
);
1753 context_support
->SignalSyncPoint(
1754 sync_point
, base::Bind(&SyncPointCallback
, &sync_point_callback_count
));
1755 EXPECT_EQ(0, sync_point_callback_count
);
1756 EXPECT_EQ(0, other_callback_count
);
1758 // Make the sync point happen.
1760 // Post a task after the sync point.
1761 base::MessageLoop::current()->PostTask(
1762 FROM_HERE
, base::Bind(&OtherCallback
, &other_callback_count
));
1764 base::MessageLoop::current()->Run();
1766 // The sync point shouldn't have happened since the context was lost.
1767 EXPECT_EQ(0, sync_point_callback_count
);
1768 EXPECT_EQ(1, other_callback_count
);
1771 TEST_F(GLRendererTestSyncPoint
, SignalSyncPoint
) {
1772 int sync_point_callback_count
= 0;
1773 int other_callback_count
= 0;
1775 gpu::gles2::GLES2Interface
* gl
=
1776 output_surface_
->context_provider()->ContextGL();
1777 gpu::ContextSupport
* context_support
=
1778 output_surface_
->context_provider()->ContextSupport();
1780 uint32 sync_point
= gl
->InsertSyncPointCHROMIUM();
1782 context_support
->SignalSyncPoint(
1783 sync_point
, base::Bind(&SyncPointCallback
, &sync_point_callback_count
));
1784 EXPECT_EQ(0, sync_point_callback_count
);
1785 EXPECT_EQ(0, other_callback_count
);
1787 // Make the sync point happen.
1789 // Post a task after the sync point.
1790 base::MessageLoop::current()->PostTask(
1791 FROM_HERE
, base::Bind(&OtherCallback
, &other_callback_count
));
1793 base::MessageLoop::current()->Run();
1795 // The sync point should have happened.
1796 EXPECT_EQ(1, sync_point_callback_count
);
1797 EXPECT_EQ(1, other_callback_count
);
1799 #endif // OS_ANDROID