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/debug/test_web_graphics_context_3d.h"
11 #include "cc/output/compositor_frame_metadata.h"
12 #include "cc/resources/prioritized_resource_manager.h"
13 #include "cc/resources/resource_provider.h"
14 #include "cc/resources/sync_point_helper.h"
15 #include "cc/test/fake_impl_proxy.h"
16 #include "cc/test/fake_layer_tree_host_impl.h"
17 #include "cc/test/fake_output_surface.h"
18 #include "cc/test/fake_output_surface_client.h"
19 #include "cc/test/mock_quad_culler.h"
20 #include "cc/test/pixel_test.h"
21 #include "cc/test/render_pass_test_common.h"
22 #include "cc/test/render_pass_test_utils.h"
23 #include "gpu/GLES2/gl2extchromium.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
;
35 using testing::AtLeast
;
36 using testing::Expectation
;
37 using testing::InSequence
;
39 using testing::Return
;
40 using testing::StrictMock
;
41 using WebKit::WebGLId
;
42 using WebKit::WebString
;
43 using WebKit::WGC3Dbitfield
;
44 using WebKit::WGC3Dboolean
;
45 using WebKit::WGC3Dchar
;
46 using WebKit::WGC3Denum
;
47 using WebKit::WGC3Dfloat
;
48 using WebKit::WGC3Dint
;
49 using WebKit::WGC3Dintptr
;
50 using WebKit::WGC3Dsizei
;
51 using WebKit::WGC3Dsizeiptr
;
52 using WebKit::WGC3Duint
;
56 #define EXPECT_PROGRAM_VALID(program_binding) \
58 EXPECT_TRUE(program_binding->program()); \
59 EXPECT_TRUE(program_binding->initialized()); \
62 // Explicitly named to be a friend in GLRenderer for shader access.
63 class GLRendererShaderPixelTest
: public GLRendererPixelTest
{
66 ASSERT_FALSE(renderer()->IsContextLost());
67 EXPECT_PROGRAM_VALID(renderer()->GetTileCheckerboardProgram());
68 EXPECT_PROGRAM_VALID(renderer()->GetDebugBorderProgram());
69 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgram());
70 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgramAA());
71 TestShadersWithTexCoordPrecision(TexCoordPrecisionMedium
);
72 TestShadersWithTexCoordPrecision(TexCoordPrecisionHigh
);
73 ASSERT_FALSE(renderer()->IsContextLost());
76 void TestShadersWithTexCoordPrecision(TexCoordPrecision precision
) {
77 EXPECT_PROGRAM_VALID(renderer()->GetTileProgram(precision
));
78 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramOpaque(precision
));
79 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramAA(precision
));
80 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzle(precision
));
81 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzleOpaque(precision
));
82 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzleAA(precision
));
83 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgram(precision
));
84 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgramAA(precision
));
85 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgram(precision
));
86 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA(precision
));
88 renderer()->GetRenderPassColorMatrixProgram(precision
));
90 renderer()->GetRenderPassMaskColorMatrixProgramAA(precision
));
92 renderer()->GetRenderPassColorMatrixProgramAA(precision
));
94 renderer()->GetRenderPassMaskColorMatrixProgram(precision
));
95 EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision
));
97 renderer()->GetNonPremultipliedTextureProgram(precision
));
98 EXPECT_PROGRAM_VALID(renderer()->GetTextureBackgroundProgram(precision
));
100 renderer()->GetNonPremultipliedTextureBackgroundProgram(precision
));
101 EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision
));
102 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision
));
103 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision
));
104 // This is unlikely to be ever true in tests due to usage of osmesa.
105 if (renderer()->Capabilities().using_egl_image
)
106 EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision
));
108 EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision
));
114 #if !defined(OS_ANDROID)
115 TEST_F(GLRendererShaderPixelTest
, AllShadersCompile
) { TestShaders(); }
118 class FrameCountingContext
: public TestWebGraphicsContext3D
{
120 FrameCountingContext()
122 test_capabilities_
.set_visibility
= true;
123 test_capabilities_
.discard_backbuffer
= true;
126 // WebGraphicsContext3D methods.
128 // This method would normally do a glSwapBuffers under the hood.
129 virtual void prepareTexture() { frame_
++; }
131 // Methods added for test.
132 int frame_count() { return frame_
; }
138 class FakeRendererClient
: public RendererClient
{
141 : host_impl_(&proxy_
),
142 set_full_root_layer_damage_count_(0),
143 root_layer_(LayerImpl::Create(host_impl_
.active_tree(), 1)),
144 viewport_size_(gfx::Size(1, 1)),
146 external_stencil_test_enabled_(false) {
147 root_layer_
->CreateRenderSurface();
148 RenderPass::Id render_pass_id
=
149 root_layer_
->render_surface()->RenderPassId();
150 scoped_ptr
<RenderPass
> root_render_pass
= RenderPass::Create();
151 root_render_pass
->SetNew(
152 render_pass_id
, gfx::Rect(), gfx::Rect(), gfx::Transform());
153 render_passes_in_draw_order_
.push_back(root_render_pass
.Pass());
156 // RendererClient methods.
157 virtual gfx::Rect
DeviceViewport() const OVERRIDE
{
158 static gfx::Size
fake_size(1, 1);
159 return gfx::Rect(fake_size
);
161 virtual float DeviceScaleFactor() const OVERRIDE
{
162 return scale_factor_
;
164 virtual const LayerTreeSettings
& Settings() const OVERRIDE
{
165 static LayerTreeSettings fake_settings
;
166 return fake_settings
;
168 virtual void SetFullRootLayerDamage() OVERRIDE
{
169 set_full_root_layer_damage_count_
++;
171 virtual bool HasImplThread() const OVERRIDE
{ return false; }
172 virtual bool ShouldClearRootRenderPass() const OVERRIDE
{ return true; }
173 virtual CompositorFrameMetadata
MakeCompositorFrameMetadata() const OVERRIDE
{
174 return CompositorFrameMetadata();
176 virtual bool AllowPartialSwap() const OVERRIDE
{
179 virtual bool ExternalStencilTestEnabled() const OVERRIDE
{
180 return external_stencil_test_enabled_
;
183 void EnableExternalStencilTest() {
184 external_stencil_test_enabled_
= true;
187 // Methods added for test.
188 int set_full_root_layer_damage_count() const {
189 return set_full_root_layer_damage_count_
;
191 void set_viewport_and_scale(
192 gfx::Size viewport_size
, float scale_factor
) {
193 viewport_size_
= viewport_size
;
194 scale_factor_
= scale_factor
;
197 RenderPass
* root_render_pass() { return render_passes_in_draw_order_
.back(); }
198 RenderPassList
* render_passes_in_draw_order() {
199 return &render_passes_in_draw_order_
;
203 FakeImplProxy proxy_
;
204 FakeLayerTreeHostImpl host_impl_
;
205 int set_full_root_layer_damage_count_
;
206 scoped_ptr
<LayerImpl
> root_layer_
;
207 RenderPassList render_passes_in_draw_order_
;
208 gfx::Size viewport_size_
;
210 bool external_stencil_test_enabled_
;
213 class FakeRendererGL
: public GLRenderer
{
215 FakeRendererGL(RendererClient
* client
,
216 OutputSurface
* output_surface
,
217 ResourceProvider
* resource_provider
)
218 : GLRenderer(client
, output_surface
, resource_provider
, 0) {}
220 // GLRenderer methods.
222 // Changing visibility to public.
223 using GLRenderer::Initialize
;
224 using GLRenderer::IsBackbufferDiscarded
;
225 using GLRenderer::DoDrawQuad
;
226 using GLRenderer::BeginDrawingFrame
;
227 using GLRenderer::FinishDrawingQuadList
;
228 using GLRenderer::stencil_enabled
;
231 class GLRendererTest
: public testing::Test
{
234 scoped_ptr
<FrameCountingContext
> context3d(new FrameCountingContext
);
235 context3d_
= context3d
.get();
237 output_surface_
= FakeOutputSurface::Create3d(
238 context3d
.PassAs
<TestWebGraphicsContext3D
>()).Pass();
239 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
242 ResourceProvider::Create(output_surface_
.get(), 0).Pass();
243 renderer_
= make_scoped_ptr(new FakeRendererGL(
245 output_surface_
.get(),
246 resource_provider_
.get()));
249 virtual void SetUp() { renderer_
->Initialize(); }
251 void SwapBuffers() { renderer_
->SwapBuffers(); }
253 FrameCountingContext
* context3d_
;
254 FakeOutputSurfaceClient output_surface_client_
;
255 scoped_ptr
<FakeOutputSurface
> output_surface_
;
256 FakeRendererClient renderer_client_
;
257 scoped_ptr
<ResourceProvider
> resource_provider_
;
258 scoped_ptr
<FakeRendererGL
> renderer_
;
261 // Closing the namespace here so that GLRendererShaderTest can take advantage
262 // of the friend relationship with GLRenderer and all of the mock classes
263 // declared above it.
267 // Gives unique shader ids and unique program ids for tests that need them.
268 class ShaderCreatorMockGraphicsContext
: public TestWebGraphicsContext3D
{
270 ShaderCreatorMockGraphicsContext()
271 : next_program_id_number_(10000),
272 next_shader_id_number_(1) {}
274 bool hasShader(WebGLId shader
) {
275 return shader_set_
.find(shader
) != shader_set_
.end();
278 bool hasProgram(WebGLId program
) {
279 return program_set_
.find(program
) != program_set_
.end();
282 virtual WebGLId
createProgram() {
283 unsigned program
= next_program_id_number_
;
284 program_set_
.insert(program
);
285 next_program_id_number_
++;
289 virtual void deleteProgram(WebGLId program
) {
290 ASSERT_TRUE(hasProgram(program
));
291 program_set_
.erase(program
);
294 virtual void useProgram(WebGLId program
) {
297 ASSERT_TRUE(hasProgram(program
));
300 virtual WebKit::WebGLId
createShader(WebKit::WGC3Denum
) {
301 unsigned shader
= next_shader_id_number_
;
302 shader_set_
.insert(shader
);
303 next_shader_id_number_
++;
307 virtual void deleteShader(WebKit::WebGLId shader
) {
308 ASSERT_TRUE(hasShader(shader
));
309 shader_set_
.erase(shader
);
312 virtual void attachShader(WebGLId program
, WebGLId shader
) {
313 ASSERT_TRUE(hasProgram(program
));
314 ASSERT_TRUE(hasShader(shader
));
318 unsigned next_program_id_number_
;
319 unsigned next_shader_id_number_
;
320 std::set
<unsigned> program_set_
;
321 std::set
<unsigned> shader_set_
;
324 class GLRendererShaderTest
: public testing::Test
{
326 GLRendererShaderTest() {
327 output_surface_
= FakeOutputSurface::Create3d(
328 scoped_ptr
<TestWebGraphicsContext3D
>(
329 new ShaderCreatorMockGraphicsContext())).Pass();
330 CHECK(output_surface_
->BindToClient(&output_surface_client_
));
332 resource_provider_
= ResourceProvider::Create(output_surface_
.get(),
334 renderer_
.reset(new FakeRendererGL(&renderer_client_
,
335 output_surface_
.get(),
336 resource_provider_
.get()));
337 renderer_
->Initialize();
340 void TestRenderPassProgram() {
341 EXPECT_PROGRAM_VALID(renderer_
->render_pass_program_
);
342 EXPECT_EQ(renderer_
->render_pass_program_
->program(),
343 renderer_
->program_shadow_
);
346 void TestRenderPassColorMatrixProgram() {
347 EXPECT_PROGRAM_VALID(renderer_
->render_pass_color_matrix_program_
);
348 EXPECT_EQ(renderer_
->render_pass_color_matrix_program_
->program(),
349 renderer_
->program_shadow_
);
352 void TestRenderPassMaskProgram() {
353 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_program_
);
354 EXPECT_EQ(renderer_
->render_pass_mask_program_
->program(),
355 renderer_
->program_shadow_
);
358 void TestRenderPassMaskColorMatrixProgram() {
359 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_color_matrix_program_
);
360 EXPECT_EQ(renderer_
->render_pass_mask_color_matrix_program_
->program(),
361 renderer_
->program_shadow_
);
364 void TestRenderPassProgramAA() {
365 EXPECT_PROGRAM_VALID(renderer_
->render_pass_program_aa_
);
366 EXPECT_EQ(renderer_
->render_pass_program_aa_
->program(),
367 renderer_
->program_shadow_
);
370 void TestRenderPassColorMatrixProgramAA() {
371 EXPECT_PROGRAM_VALID(renderer_
->render_pass_color_matrix_program_aa_
);
372 EXPECT_EQ(renderer_
->render_pass_color_matrix_program_aa_
->program(),
373 renderer_
->program_shadow_
);
376 void TestRenderPassMaskProgramAA() {
377 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_program_aa_
);
378 EXPECT_EQ(renderer_
->render_pass_mask_program_aa_
->program(),
379 renderer_
->program_shadow_
);
382 void TestRenderPassMaskColorMatrixProgramAA() {
383 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_color_matrix_program_aa_
);
384 EXPECT_EQ(renderer_
->render_pass_mask_color_matrix_program_aa_
->program(),
385 renderer_
->program_shadow_
);
388 void TestSolidColorProgramAA() {
389 EXPECT_PROGRAM_VALID(renderer_
->solid_color_program_aa_
);
390 EXPECT_EQ(renderer_
->solid_color_program_aa_
->program(),
391 renderer_
->program_shadow_
);
394 FakeOutputSurfaceClient output_surface_client_
;
395 scoped_ptr
<FakeOutputSurface
> output_surface_
;
396 FakeRendererClient renderer_client_
;
397 scoped_ptr
<ResourceProvider
> resource_provider_
;
398 scoped_ptr
<FakeRendererGL
> renderer_
;
403 // Test GLRenderer discardBackbuffer functionality:
404 // Suggest recreating framebuffer when one already exists.
405 // Expected: it does nothing.
406 TEST_F(GLRendererTest
, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing
) {
407 renderer_
->SetDiscardBackBufferWhenNotVisible(false);
408 EXPECT_EQ(0, renderer_client_
.set_full_root_layer_damage_count());
409 EXPECT_FALSE(renderer_
->IsBackbufferDiscarded());
412 EXPECT_EQ(1, context3d_
->frame_count());
415 // Test GLRenderer DiscardBackbuffer functionality:
416 // Suggest discarding framebuffer when one exists and the renderer is not
418 // Expected: it is discarded and damage tracker is reset.
421 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible
) {
422 renderer_
->SetVisible(false);
423 renderer_
->SetDiscardBackBufferWhenNotVisible(true);
424 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
425 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
428 // Test GLRenderer DiscardBackbuffer functionality:
429 // Suggest discarding framebuffer when one exists and the renderer is visible.
430 // Expected: the allocation is ignored.
431 TEST_F(GLRendererTest
, SuggestBackbufferNoDoNothingWhenVisible
) {
432 renderer_
->SetVisible(true);
433 renderer_
->SetDiscardBackBufferWhenNotVisible(true);
434 EXPECT_EQ(0, renderer_client_
.set_full_root_layer_damage_count());
435 EXPECT_FALSE(renderer_
->IsBackbufferDiscarded());
438 // Test GLRenderer DiscardBackbuffer functionality:
439 // Suggest discarding framebuffer when one does not exist.
440 // Expected: it does nothing.
441 TEST_F(GLRendererTest
, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing
) {
442 renderer_
->SetVisible(false);
443 renderer_
->SetDiscardBackBufferWhenNotVisible(true);
444 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
445 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
447 renderer_
->SetDiscardBackBufferWhenNotVisible(true);
448 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
449 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
452 // Test GLRenderer DiscardBackbuffer functionality:
453 // Begin drawing a frame while a framebuffer is discarded.
454 // Expected: will recreate framebuffer.
455 TEST_F(GLRendererTest
, DiscardedBackbufferIsRecreatedForScopeDuration
) {
456 renderer_
->SetVisible(false);
457 renderer_
->SetDiscardBackBufferWhenNotVisible(true);
458 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
459 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
461 renderer_
->SetVisible(true);
462 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
463 EXPECT_FALSE(renderer_
->IsBackbufferDiscarded());
466 EXPECT_EQ(1, context3d_
->frame_count());
469 TEST_F(GLRendererTest
, FramebufferDiscardedAfterReadbackWhenNotVisible
) {
470 renderer_
->SetVisible(false);
471 renderer_
->SetDiscardBackBufferWhenNotVisible(true);
472 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
473 EXPECT_EQ(1, renderer_client_
.set_full_root_layer_damage_count());
476 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
477 EXPECT_FALSE(renderer_
->IsBackbufferDiscarded());
479 renderer_
->GetFramebufferPixels(pixels
, gfx::Rect(0, 0, 1, 1));
480 EXPECT_TRUE(renderer_
->IsBackbufferDiscarded());
481 EXPECT_EQ(2, renderer_client_
.set_full_root_layer_damage_count());
484 TEST_F(GLRendererTest
, ExternalStencil
) {
485 EXPECT_FALSE(renderer_
->stencil_enabled());
487 renderer_client_
.EnableExternalStencilTest();
488 renderer_client_
.root_render_pass()->has_transparent_background
= false;
490 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
491 EXPECT_TRUE(renderer_
->stencil_enabled());
494 class ForbidSynchronousCallContext
: public TestWebGraphicsContext3D
{
496 ForbidSynchronousCallContext() {}
498 virtual bool getActiveAttrib(WebGLId program
,
504 virtual bool getActiveUniform(WebGLId program
,
510 virtual void getAttachedShaders(WebGLId program
,
511 WGC3Dsizei max_count
,
516 virtual WGC3Dint
getAttribLocation(WebGLId program
, const WGC3Dchar
* name
) {
520 virtual void getBooleanv(WGC3Denum pname
, WGC3Dboolean
* value
) {
523 virtual void getBufferParameteriv(WGC3Denum target
,
528 virtual Attributes
getContextAttributes() {
532 virtual WGC3Denum
getError() {
536 virtual void getFloatv(WGC3Denum pname
, WGC3Dfloat
* value
) { ADD_FAILURE(); }
537 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target
,
538 WGC3Denum attachment
,
543 virtual void getIntegerv(WGC3Denum pname
, WGC3Dint
* value
) {
544 if (pname
== GL_MAX_TEXTURE_SIZE
) {
545 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
552 // We allow querying the shader compilation and program link status in debug
553 // mode, but not release.
554 virtual void getProgramiv(WebGLId program
, WGC3Denum pname
, WGC3Dint
* value
) {
562 virtual void getShaderiv(WebGLId shader
, WGC3Denum pname
, WGC3Dint
* value
) {
570 virtual WebString
getString(WGC3Denum name
) {
571 ADD_FAILURE() << name
;
575 virtual WebString
getProgramInfoLog(WebGLId program
) {
579 virtual void getRenderbufferParameteriv(WGC3Denum target
,
585 virtual WebString
getShaderInfoLog(WebGLId shader
) {
589 virtual void getShaderPrecisionFormat(WGC3Denum shadertype
,
590 WGC3Denum precisiontype
,
592 WGC3Dint
* precision
) {
595 virtual WebString
getShaderSource(WebGLId shader
) {
599 virtual void getTexParameterfv(WGC3Denum target
,
604 virtual void getTexParameteriv(WGC3Denum target
,
609 virtual void getUniformfv(WebGLId program
,
614 virtual void getUniformiv(WebGLId program
,
619 virtual WGC3Dint
getUniformLocation(WebGLId program
, const WGC3Dchar
* name
) {
623 virtual void getVertexAttribfv(WGC3Duint index
,
628 virtual void getVertexAttribiv(WGC3Duint index
,
633 virtual WGC3Dsizeiptr
getVertexAttribOffset(WGC3Duint index
,
640 // This test isn't using the same fixture as GLRendererTest, and you can't mix
641 // TEST() and TEST_F() with the same name, Hence LRC2.
642 TEST(GLRendererTest2
, InitializationDoesNotMakeSynchronousCalls
) {
643 FakeOutputSurfaceClient output_surface_client
;
644 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
645 scoped_ptr
<TestWebGraphicsContext3D
>(new ForbidSynchronousCallContext
)));
646 CHECK(output_surface
->BindToClient(&output_surface_client
));
648 scoped_ptr
<ResourceProvider
> resource_provider(
649 ResourceProvider::Create(output_surface
.get(), 0));
651 FakeRendererClient renderer_client
;
652 FakeRendererGL
renderer(
653 &renderer_client
, output_surface
.get(), resource_provider
.get());
655 EXPECT_TRUE(renderer
.Initialize());
658 class LoseContextOnFirstGetContext
: public TestWebGraphicsContext3D
{
660 LoseContextOnFirstGetContext() : context_lost_(false) {}
662 virtual bool makeContextCurrent() OVERRIDE
{ return !context_lost_
; }
664 virtual void getProgramiv(WebGLId program
, WGC3Denum pname
, WGC3Dint
* value
)
666 context_lost_
= true;
670 virtual void getShaderiv(WebGLId shader
, WGC3Denum pname
, WGC3Dint
* value
)
672 context_lost_
= true;
676 virtual WGC3Denum
getGraphicsResetStatusARB() OVERRIDE
{
677 return context_lost_
? 1 : 0;
684 TEST(GLRendererTest2
, InitializationWithQuicklyLostContextDoesNotAssert
) {
685 FakeOutputSurfaceClient output_surface_client
;
686 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
687 scoped_ptr
<TestWebGraphicsContext3D
>(new LoseContextOnFirstGetContext
)));
688 CHECK(output_surface
->BindToClient(&output_surface_client
));
690 scoped_ptr
<ResourceProvider
> resource_provider(
691 ResourceProvider::Create(output_surface
.get(), 0));
693 FakeRendererClient renderer_client
;
694 FakeRendererGL
renderer(
695 &renderer_client
, output_surface
.get(), resource_provider
.get());
697 renderer
.Initialize();
700 class ClearCountingContext
: public TestWebGraphicsContext3D
{
702 ClearCountingContext() : clear_(0) {}
704 virtual void clear(WGC3Dbitfield
) { clear_
++; }
706 int clear_count() const { return clear_
; }
712 TEST(GLRendererTest2
, OpaqueBackground
) {
713 scoped_ptr
<ClearCountingContext
> context_owned(new ClearCountingContext
);
714 ClearCountingContext
* context
= context_owned
.get();
716 FakeOutputSurfaceClient output_surface_client
;
717 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
718 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
719 CHECK(output_surface
->BindToClient(&output_surface_client
));
721 scoped_ptr
<ResourceProvider
> resource_provider(
722 ResourceProvider::Create(output_surface
.get(), 0));
724 FakeRendererClient renderer_client
;
725 FakeRendererGL
renderer(
726 &renderer_client
, output_surface
.get(), resource_provider
.get());
728 renderer_client
.root_render_pass()->has_transparent_background
= false;
730 EXPECT_TRUE(renderer
.Initialize());
732 renderer
.DrawFrame(renderer_client
.render_passes_in_draw_order(), NULL
);
734 // On DEBUG builds, render passes with opaque background clear to blue to
735 // easily see regions that were not drawn on the screen.
737 EXPECT_EQ(0, context
->clear_count());
739 EXPECT_EQ(1, context
->clear_count());
743 TEST(GLRendererTest2
, TransparentBackground
) {
744 scoped_ptr
<ClearCountingContext
> context_owned(new ClearCountingContext
);
745 ClearCountingContext
* context
= context_owned
.get();
747 FakeOutputSurfaceClient output_surface_client
;
748 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
749 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
750 CHECK(output_surface
->BindToClient(&output_surface_client
));
752 scoped_ptr
<ResourceProvider
> resource_provider(
753 ResourceProvider::Create(output_surface
.get(), 0));
755 FakeRendererClient renderer_client
;
756 FakeRendererGL
renderer(
757 &renderer_client
, output_surface
.get(), resource_provider
.get());
759 renderer_client
.root_render_pass()->has_transparent_background
= true;
761 EXPECT_TRUE(renderer
.Initialize());
763 renderer
.DrawFrame(renderer_client
.render_passes_in_draw_order(), NULL
);
765 EXPECT_EQ(1, context
->clear_count());
768 class VisibilityChangeIsLastCallTrackingContext
769 : public TestWebGraphicsContext3D
{
771 VisibilityChangeIsLastCallTrackingContext()
772 : last_call_was_set_visibility_(false) {
773 test_capabilities_
.set_visibility
= true;
774 test_capabilities_
.discard_backbuffer
= true;
777 // WebGraphicsContext3D methods.
778 virtual void setVisibilityCHROMIUM(bool visible
) {
779 DCHECK(last_call_was_set_visibility_
== false);
780 last_call_was_set_visibility_
= true;
782 virtual void flush() {
783 last_call_was_set_visibility_
= false;
785 virtual void deleteTexture(WebGLId
) {
786 last_call_was_set_visibility_
= false;
788 virtual void deleteFramebuffer(WebGLId
) {
789 last_call_was_set_visibility_
= false;
791 virtual void deleteQueryEXT(WebGLId
) {
792 last_call_was_set_visibility_
= false;
794 virtual void deleteRenderbuffer(WebGLId
) {
795 last_call_was_set_visibility_
= false;
797 virtual void discardBackbufferCHROMIUM() {
798 last_call_was_set_visibility_
= false;
800 virtual void ensureBackbufferCHROMIUM() {
801 last_call_was_set_visibility_
= false;
804 // Methods added for test.
805 bool last_call_was_set_visibility() const {
806 return last_call_was_set_visibility_
;
810 bool last_call_was_set_visibility_
;
813 TEST(GLRendererTest2
, VisibilityChangeIsLastCall
) {
814 scoped_ptr
<VisibilityChangeIsLastCallTrackingContext
> context_owned(
815 new VisibilityChangeIsLastCallTrackingContext
);
816 VisibilityChangeIsLastCallTrackingContext
* context
= context_owned
.get();
818 FakeOutputSurfaceClient output_surface_client
;
819 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
820 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
821 CHECK(output_surface
->BindToClient(&output_surface_client
));
823 scoped_ptr
<ResourceProvider
> resource_provider(
824 ResourceProvider::Create(output_surface
.get(), 0));
826 FakeRendererClient renderer_client
;
827 FakeRendererGL
renderer(
828 &renderer_client
, output_surface
.get(), resource_provider
.get());
830 EXPECT_TRUE(renderer
.Initialize());
832 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the
833 // GPU process, after glFlush is called, and after the RendererClient's
834 // SetManagedMemoryPolicy is called. Plumb this tracking between both the
835 // RenderClient and the Context by giving them both a pointer to a variable on
837 renderer
.SetVisible(true);
838 renderer
.DrawFrame(renderer_client
.render_passes_in_draw_order(), NULL
);
839 renderer
.SetVisible(false);
840 EXPECT_TRUE(context
->last_call_was_set_visibility());
843 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
845 TextureStateTrackingContext()
846 : active_texture_(GL_INVALID_ENUM
) {
847 test_capabilities_
.egl_image_external
= true;
850 MOCK_METHOD3(texParameteri
,
851 void(WGC3Denum target
, WGC3Denum pname
, WGC3Dint param
));
852 MOCK_METHOD4(drawElements
,
856 WGC3Dintptr offset
));
858 virtual void activeTexture(WGC3Denum texture
) {
859 EXPECT_NE(texture
, active_texture_
);
860 active_texture_
= texture
;
863 WGC3Denum
active_texture() const { return active_texture_
; }
866 WGC3Denum active_texture_
;
869 TEST(GLRendererTest2
, ActiveTextureState
) {
870 scoped_ptr
<TextureStateTrackingContext
> context_owned(
871 new TextureStateTrackingContext
);
872 TextureStateTrackingContext
* context
= context_owned
.get();
874 FakeOutputSurfaceClient output_surface_client
;
875 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
876 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
877 CHECK(output_surface
->BindToClient(&output_surface_client
));
879 scoped_ptr
<ResourceProvider
> resource_provider(
880 ResourceProvider::Create(output_surface
.get(), 0));
882 FakeRendererClient renderer_client
;
883 FakeRendererGL
renderer(
884 &renderer_client
, output_surface
.get(), resource_provider
.get());
886 // During initialization we are allowed to set any texture parameters.
887 EXPECT_CALL(*context
, texParameteri(_
, _
, _
)).Times(AnyNumber());
888 EXPECT_TRUE(renderer
.Initialize());
890 cc::RenderPass::Id
id(1, 1);
891 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
893 gfx::Rect(0, 0, 100, 100),
894 gfx::Rect(0, 0, 100, 100),
896 pass
->AppendOneOfEveryQuadType(resource_provider
.get(), RenderPass::Id(2, 1));
898 // Set up expected texture filter state transitions that match the quads
899 // created in AppendOneOfEveryQuadType().
900 Mock::VerifyAndClearExpectations(context
);
904 // yuv_quad is drawn with the default linear filter.
905 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
907 // tile_quad is drawn with GL_NEAREST because it is not transformed or
911 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
914 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
915 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
917 // transformed_tile_quad uses GL_LINEAR.
918 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
920 // scaled_tile_quad also uses GL_LINEAR.
921 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
923 // The remaining quads also use GL_LINEAR because nearest neighbor
924 // filtering is currently only used with tile quads.
925 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
)).Times(6);
928 cc::DirectRenderer::DrawingFrame drawing_frame
;
929 renderer
.BeginDrawingFrame(&drawing_frame
);
930 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0
), context
->active_texture());
932 for (cc::QuadList::BackToFrontIterator
933 it
= pass
->quad_list
.BackToFrontBegin();
934 it
!= pass
->quad_list
.BackToFrontEnd();
936 renderer
.DoDrawQuad(&drawing_frame
, *it
);
938 renderer
.FinishDrawingQuadList();
939 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0
), context
->active_texture());
940 Mock::VerifyAndClearExpectations(context
);
943 class NoClearRootRenderPassFakeClient
: public FakeRendererClient
{
945 virtual bool ShouldClearRootRenderPass() const OVERRIDE
{ return false; }
948 class NoClearRootRenderPassMockContext
: public TestWebGraphicsContext3D
{
950 MOCK_METHOD1(clear
, void(WGC3Dbitfield mask
));
951 MOCK_METHOD4(drawElements
,
955 WGC3Dintptr offset
));
958 TEST(GLRendererTest2
, ShouldClearRootRenderPass
) {
959 scoped_ptr
<NoClearRootRenderPassMockContext
> mock_context_owned(
960 new NoClearRootRenderPassMockContext
);
961 NoClearRootRenderPassMockContext
* mock_context
= mock_context_owned
.get();
963 FakeOutputSurfaceClient output_surface_client
;
964 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
965 mock_context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
966 CHECK(output_surface
->BindToClient(&output_surface_client
));
968 scoped_ptr
<ResourceProvider
> resource_provider(
969 ResourceProvider::Create(output_surface
.get(), 0));
971 NoClearRootRenderPassFakeClient renderer_client
;
972 FakeRendererGL
renderer(
973 &renderer_client
, output_surface
.get(), resource_provider
.get());
974 EXPECT_TRUE(renderer
.Initialize());
976 gfx::Rect
viewport_rect(renderer_client
.DeviceViewport());
977 ScopedPtrVector
<RenderPass
>& render_passes
=
978 *renderer_client
.render_passes_in_draw_order();
979 render_passes
.clear();
981 RenderPass::Id
root_pass_id(1, 0);
982 TestRenderPass
* root_pass
= AddRenderPass(
983 &render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
984 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
986 RenderPass::Id
child_pass_id(2, 0);
987 TestRenderPass
* child_pass
= AddRenderPass(
988 &render_passes
, child_pass_id
, viewport_rect
, gfx::Transform());
989 AddQuad(child_pass
, viewport_rect
, SK_ColorBLUE
);
991 AddRenderPassQuad(root_pass
, child_pass
);
994 GLint clear_bits
= GL_COLOR_BUFFER_BIT
;
996 GLint clear_bits
= GL_COLOR_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
;
999 // First render pass is not the root one, clearing should happen.
1000 EXPECT_CALL(*mock_context
, clear(clear_bits
)).Times(AtLeast(1));
1002 Expectation first_render_pass
=
1003 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
)).Times(1);
1005 // The second render pass is the root one, clearing should be prevented.
1006 EXPECT_CALL(*mock_context
, clear(clear_bits
)).Times(0)
1007 .After(first_render_pass
);
1009 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
)).Times(AnyNumber())
1010 .After(first_render_pass
);
1012 renderer
.DecideRenderPassAllocationsForFrame(
1013 *renderer_client
.render_passes_in_draw_order());
1014 renderer
.DrawFrame(renderer_client
.render_passes_in_draw_order(), NULL
);
1016 // In multiple render passes all but the root pass should clear the
1018 Mock::VerifyAndClearExpectations(&mock_context
);
1021 class ScissorTestOnClearCheckingContext
: public TestWebGraphicsContext3D
{
1023 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
1025 virtual void clear(WGC3Dbitfield
) { EXPECT_FALSE(scissor_enabled_
); }
1027 virtual void enable(WGC3Denum cap
) {
1028 if (cap
== GL_SCISSOR_TEST
)
1029 scissor_enabled_
= true;
1032 virtual void disable(WGC3Denum cap
) {
1033 if (cap
== GL_SCISSOR_TEST
)
1034 scissor_enabled_
= false;
1038 bool scissor_enabled_
;
1041 TEST(GLRendererTest2
, ScissorTestWhenClearing
) {
1042 scoped_ptr
<ScissorTestOnClearCheckingContext
> context_owned(
1043 new ScissorTestOnClearCheckingContext
);
1045 FakeOutputSurfaceClient output_surface_client
;
1046 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
1047 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1048 CHECK(output_surface
->BindToClient(&output_surface_client
));
1050 scoped_ptr
<ResourceProvider
> resource_provider(
1051 ResourceProvider::Create(output_surface
.get(), 0));
1053 FakeRendererClient renderer_client
;
1054 FakeRendererGL
renderer(
1055 &renderer_client
, output_surface
.get(), resource_provider
.get());
1056 EXPECT_TRUE(renderer
.Initialize());
1057 EXPECT_FALSE(renderer
.Capabilities().using_partial_swap
);
1059 gfx::Rect
viewport_rect(renderer_client
.DeviceViewport());
1060 ScopedPtrVector
<RenderPass
>& render_passes
=
1061 *renderer_client
.render_passes_in_draw_order();
1062 render_passes
.clear();
1064 gfx::Rect
grand_child_rect(25, 25);
1065 RenderPass::Id
grand_child_pass_id(3, 0);
1066 TestRenderPass
* grand_child_pass
= AddRenderPass(
1067 &render_passes
, grand_child_pass_id
, grand_child_rect
, gfx::Transform());
1068 AddClippedQuad(grand_child_pass
, grand_child_rect
, SK_ColorYELLOW
);
1070 gfx::Rect
child_rect(50, 50);
1071 RenderPass::Id
child_pass_id(2, 0);
1072 TestRenderPass
* child_pass
= AddRenderPass(
1073 &render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1074 AddQuad(child_pass
, child_rect
, SK_ColorBLUE
);
1076 RenderPass::Id
root_pass_id(1, 0);
1077 TestRenderPass
* root_pass
= AddRenderPass(
1078 &render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1079 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1081 AddRenderPassQuad(root_pass
, child_pass
);
1082 AddRenderPassQuad(child_pass
, grand_child_pass
);
1084 renderer
.DecideRenderPassAllocationsForFrame(
1085 *renderer_client
.render_passes_in_draw_order());
1086 renderer
.DrawFrame(renderer_client
.render_passes_in_draw_order(), NULL
);
1089 class NonReshapableOutputSurface
: public FakeOutputSurface
{
1091 explicit NonReshapableOutputSurface(
1092 scoped_ptr
<TestWebGraphicsContext3D
> context3d
)
1093 : FakeOutputSurface(
1094 TestContextProvider::Create(context3d
.Pass()),
1096 virtual gfx::Size
SurfaceSize() const OVERRIDE
{ return gfx::Size(500, 500); }
1099 class OffsetViewportRendererClient
: public FakeRendererClient
{
1101 virtual gfx::Rect
DeviceViewport() const OVERRIDE
{
1102 return gfx::Rect(10, 10, 100, 100);
1106 class FlippedScissorAndViewportContext
: public TestWebGraphicsContext3D
{
1108 FlippedScissorAndViewportContext()
1109 : did_call_viewport_(false), did_call_scissor_(false) {}
1110 virtual ~FlippedScissorAndViewportContext() {
1111 EXPECT_TRUE(did_call_viewport_
);
1112 EXPECT_TRUE(did_call_scissor_
);
1115 virtual void viewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
) {
1118 EXPECT_EQ(100, width
);
1119 EXPECT_EQ(100, height
);
1120 did_call_viewport_
= true;
1123 virtual void scissor(GLint x
, GLint y
, GLsizei width
, GLsizei height
) {
1126 EXPECT_EQ(20, width
);
1127 EXPECT_EQ(20, height
);
1128 did_call_scissor_
= true;
1132 bool did_call_viewport_
;
1133 bool did_call_scissor_
;
1136 TEST(GLRendererTest2
, ScissorAndViewportWithinNonreshapableSurface
) {
1137 // In Android WebView, the OutputSurface is unable to respect reshape() calls
1138 // and maintains a fixed size. This test verifies that glViewport and
1139 // glScissor's Y coordinate is flipped correctly in this environment, and that
1140 // the glViewport can be at a nonzero origin within the surface.
1141 scoped_ptr
<FlippedScissorAndViewportContext
> context_owned(
1142 new FlippedScissorAndViewportContext
);
1144 FakeOutputSurfaceClient output_surface_client
;
1145 scoped_ptr
<OutputSurface
> output_surface(new NonReshapableOutputSurface(
1146 context_owned
.PassAs
<TestWebGraphicsContext3D
>()));
1147 CHECK(output_surface
->BindToClient(&output_surface_client
));
1149 scoped_ptr
<ResourceProvider
> resource_provider(
1150 ResourceProvider::Create(output_surface
.get(), 0));
1152 OffsetViewportRendererClient renderer_client
;
1153 FakeRendererGL
renderer(
1154 &renderer_client
, output_surface
.get(), resource_provider
.get());
1155 EXPECT_TRUE(renderer
.Initialize());
1156 EXPECT_FALSE(renderer
.Capabilities().using_partial_swap
);
1158 gfx::Rect
viewport_rect(renderer_client
.DeviceViewport().size());
1159 gfx::Rect quad_rect
= gfx::Rect(20, 20, 20, 20);
1160 ScopedPtrVector
<RenderPass
>& render_passes
=
1161 *renderer_client
.render_passes_in_draw_order();
1162 render_passes
.clear();
1164 RenderPass::Id
root_pass_id(1, 0);
1165 TestRenderPass
* root_pass
= AddRenderPass(
1166 &render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1167 AddClippedQuad(root_pass
, quad_rect
, SK_ColorGREEN
);
1169 renderer
.DecideRenderPassAllocationsForFrame(
1170 *renderer_client
.render_passes_in_draw_order());
1171 renderer
.DrawFrame(renderer_client
.render_passes_in_draw_order(), NULL
);
1174 TEST_F(GLRendererShaderTest
, DrawRenderPassQuadShaderPermutations
) {
1175 gfx::Rect
viewport_rect(renderer_client_
.DeviceViewport());
1176 ScopedPtrVector
<RenderPass
>* render_passes
=
1177 renderer_client_
.render_passes_in_draw_order();
1179 gfx::Rect
child_rect(50, 50);
1180 RenderPass::Id
child_pass_id(2, 0);
1181 TestRenderPass
* child_pass
;
1183 RenderPass::Id
root_pass_id(1, 0);
1184 TestRenderPass
* root_pass
;
1186 cc::ResourceProvider::ResourceId mask
=
1187 resource_provider_
->CreateResource(gfx::Size(20, 12),
1188 resource_provider_
->best_texture_format(),
1189 ResourceProvider::TextureUsageAny
);
1190 resource_provider_
->AllocateForTesting(mask
);
1192 SkScalar matrix
[20];
1193 float amount
= 0.5f
;
1194 matrix
[0] = 0.213f
+ 0.787f
* amount
;
1195 matrix
[1] = 0.715f
- 0.715f
* amount
;
1196 matrix
[2] = 1.f
- (matrix
[0] + matrix
[1]);
1197 matrix
[3] = matrix
[4] = 0;
1198 matrix
[5] = 0.213f
- 0.213f
* amount
;
1199 matrix
[6] = 0.715f
+ 0.285f
* amount
;
1200 matrix
[7] = 1.f
- (matrix
[5] + matrix
[6]);
1201 matrix
[8] = matrix
[9] = 0;
1202 matrix
[10] = 0.213f
- 0.213f
* amount
;
1203 matrix
[11] = 0.715f
- 0.715f
* amount
;
1204 matrix
[12] = 1.f
- (matrix
[10] + matrix
[11]);
1205 matrix
[13] = matrix
[14] = 0;
1206 matrix
[15] = matrix
[16] = matrix
[17] = matrix
[19] = 0;
1208 skia::RefPtr
<SkColorFilter
> color_filter(
1209 skia::AdoptRef(new SkColorMatrixFilter(matrix
)));
1210 skia::RefPtr
<SkImageFilter
> filter
= skia::AdoptRef(
1211 SkColorFilterImageFilter::Create(color_filter
.get(), NULL
));
1213 gfx::Transform transform_causing_aa
;
1214 transform_causing_aa
.Rotate(20.0);
1216 // RenderPassProgram
1217 render_passes
->clear();
1219 child_pass
= AddRenderPass(
1220 render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1222 root_pass
= AddRenderPass(
1223 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1225 AddRenderPassQuad(root_pass
,
1228 skia::RefPtr
<SkImageFilter
>(),
1231 renderer_
->DecideRenderPassAllocationsForFrame(
1232 *renderer_client_
.render_passes_in_draw_order());
1233 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1234 TestRenderPassProgram();
1236 // RenderPassColorMatrixProgram
1237 render_passes
->clear();
1239 child_pass
= AddRenderPass(
1240 render_passes
, child_pass_id
, child_rect
, transform_causing_aa
);
1242 root_pass
= AddRenderPass(
1243 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1245 AddRenderPassQuad(root_pass
, child_pass
, 0, filter
, gfx::Transform());
1247 renderer_
->DecideRenderPassAllocationsForFrame(
1248 *renderer_client_
.render_passes_in_draw_order());
1249 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1250 TestRenderPassColorMatrixProgram();
1252 // RenderPassMaskProgram
1253 render_passes
->clear();
1255 child_pass
= AddRenderPass(
1256 render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1258 root_pass
= AddRenderPass(
1259 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1261 AddRenderPassQuad(root_pass
,
1264 skia::RefPtr
<SkImageFilter
>(),
1267 renderer_
->DecideRenderPassAllocationsForFrame(
1268 *renderer_client_
.render_passes_in_draw_order());
1269 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1270 TestRenderPassMaskProgram();
1272 // RenderPassMaskColorMatrixProgram
1273 render_passes
->clear();
1275 child_pass
= AddRenderPass(
1276 render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1278 root_pass
= AddRenderPass(
1279 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1281 AddRenderPassQuad(root_pass
, child_pass
, mask
, filter
, gfx::Transform());
1283 renderer_
->DecideRenderPassAllocationsForFrame(
1284 *renderer_client_
.render_passes_in_draw_order());
1285 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1286 TestRenderPassMaskColorMatrixProgram();
1288 // RenderPassProgramAA
1289 render_passes
->clear();
1291 child_pass
= AddRenderPass(
1292 render_passes
, child_pass_id
, child_rect
, transform_causing_aa
);
1294 root_pass
= AddRenderPass(
1295 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1297 AddRenderPassQuad(root_pass
,
1300 skia::RefPtr
<SkImageFilter
>(),
1301 transform_causing_aa
);
1303 renderer_
->DecideRenderPassAllocationsForFrame(
1304 *renderer_client_
.render_passes_in_draw_order());
1305 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1306 TestRenderPassProgramAA();
1308 // RenderPassColorMatrixProgramAA
1309 render_passes
->clear();
1311 child_pass
= AddRenderPass(
1312 render_passes
, child_pass_id
, child_rect
, transform_causing_aa
);
1314 root_pass
= AddRenderPass(
1315 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1317 AddRenderPassQuad(root_pass
, child_pass
, 0, filter
, transform_causing_aa
);
1319 renderer_
->DecideRenderPassAllocationsForFrame(
1320 *renderer_client_
.render_passes_in_draw_order());
1321 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1322 TestRenderPassColorMatrixProgramAA();
1324 // RenderPassMaskProgramAA
1325 render_passes
->clear();
1327 child_pass
= AddRenderPass(render_passes
, child_pass_id
, child_rect
,
1328 transform_causing_aa
);
1330 root_pass
= AddRenderPass(render_passes
, root_pass_id
, viewport_rect
,
1333 AddRenderPassQuad(root_pass
, child_pass
, mask
, skia::RefPtr
<SkImageFilter
>(),
1334 transform_causing_aa
);
1336 renderer_
->DecideRenderPassAllocationsForFrame(
1337 *renderer_client_
.render_passes_in_draw_order());
1338 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1339 TestRenderPassMaskProgramAA();
1341 // RenderPassMaskColorMatrixProgramAA
1342 render_passes
->clear();
1344 child_pass
= AddRenderPass(render_passes
, child_pass_id
, child_rect
,
1345 transform_causing_aa
);
1347 root_pass
= AddRenderPass(render_passes
, root_pass_id
, viewport_rect
,
1348 transform_causing_aa
);
1350 AddRenderPassQuad(root_pass
, child_pass
, mask
, filter
, transform_causing_aa
);
1352 renderer_
->DecideRenderPassAllocationsForFrame(
1353 *renderer_client_
.render_passes_in_draw_order());
1354 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1355 TestRenderPassMaskColorMatrixProgramAA();
1358 // At this time, the AA code path cannot be taken if the surface's rect would
1359 // project incorrectly by the given transform, because of w<0 clipping.
1360 TEST_F(GLRendererShaderTest
, DrawRenderPassQuadSkipsAAForClippingTransform
) {
1361 gfx::Rect
child_rect(50, 50);
1362 RenderPass::Id
child_pass_id(2, 0);
1363 TestRenderPass
* child_pass
;
1365 gfx::Rect
viewport_rect(renderer_client_
.DeviceViewport());
1366 RenderPass::Id
root_pass_id(1, 0);
1367 TestRenderPass
* root_pass
;
1369 gfx::Transform transform_preventing_aa
;
1370 transform_preventing_aa
.ApplyPerspectiveDepth(40.0);
1371 transform_preventing_aa
.RotateAboutYAxis(-20.0);
1372 transform_preventing_aa
.Scale(30.0, 1.0);
1374 // Verify that the test transform and test rect actually do cause the clipped
1375 // flag to trigger. Otherwise we are not testing the intended scenario.
1376 bool clipped
= false;
1377 MathUtil::MapQuad(transform_preventing_aa
,
1378 gfx::QuadF(child_rect
),
1380 ASSERT_TRUE(clipped
);
1382 // Set up the render pass quad to be drawn
1383 ScopedPtrVector
<RenderPass
>* render_passes
=
1384 renderer_client_
.render_passes_in_draw_order();
1386 render_passes
->clear();
1388 child_pass
= AddRenderPass(
1389 render_passes
, child_pass_id
, child_rect
, transform_preventing_aa
);
1391 root_pass
= AddRenderPass(
1392 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1394 AddRenderPassQuad(root_pass
,
1397 skia::RefPtr
<SkImageFilter
>(),
1398 transform_preventing_aa
);
1400 renderer_
->DecideRenderPassAllocationsForFrame(
1401 *renderer_client_
.render_passes_in_draw_order());
1402 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1404 // If use_aa incorrectly ignores clipping, it will use the
1405 // RenderPassProgramAA shader instead of the RenderPassProgram.
1406 TestRenderPassProgram();
1409 TEST_F(GLRendererShaderTest
, DrawSolidColorShader
) {
1410 gfx::Rect
viewport_rect(renderer_client_
.DeviceViewport());
1411 ScopedPtrVector
<RenderPass
>* render_passes
=
1412 renderer_client_
.render_passes_in_draw_order();
1414 RenderPass::Id
root_pass_id(1, 0);
1415 TestRenderPass
* root_pass
;
1417 gfx::Transform pixel_aligned_transform_causing_aa
;
1418 pixel_aligned_transform_causing_aa
.Translate(25.5f
, 25.5f
);
1419 pixel_aligned_transform_causing_aa
.Scale(0.5f
, 0.5f
);
1421 render_passes
->clear();
1423 root_pass
= AddRenderPass(
1424 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1425 AddTransformedQuad(root_pass
,
1428 pixel_aligned_transform_causing_aa
);
1430 renderer_
->DecideRenderPassAllocationsForFrame(
1431 *renderer_client_
.render_passes_in_draw_order());
1432 renderer_
->DrawFrame(renderer_client_
.render_passes_in_draw_order(), NULL
);
1434 TestSolidColorProgramAA();
1437 class OutputSurfaceMockContext
: public TestWebGraphicsContext3D
{
1439 OutputSurfaceMockContext() {
1440 test_capabilities_
.discard_backbuffer
= true;
1441 test_capabilities_
.post_sub_buffer
= true;
1444 // Specifically override methods even if they are unused (used in conjunction
1445 // with StrictMock). We need to make sure that GLRenderer does not issue
1446 // framebuffer-related GL calls directly. Instead these are supposed to go
1447 // through the OutputSurface abstraction.
1448 MOCK_METHOD0(ensureBackbufferCHROMIUM
, void());
1449 MOCK_METHOD0(discardBackbufferCHROMIUM
, void());
1450 MOCK_METHOD2(bindFramebuffer
, void(WGC3Denum target
, WebGLId framebuffer
));
1451 MOCK_METHOD0(prepareTexture
, void());
1452 MOCK_METHOD3(reshapeWithScaleFactor
,
1453 void(int width
, int height
, float scale_factor
));
1454 MOCK_METHOD4(drawElements
,
1455 void(WGC3Denum mode
,
1458 WGC3Dintptr offset
));
1461 class MockOutputSurface
: public OutputSurface
{
1464 : OutputSurface(TestContextProvider::Create(
1465 scoped_ptr
<TestWebGraphicsContext3D
>(
1466 new StrictMock
<OutputSurfaceMockContext
>))) {
1467 surface_size_
= gfx::Size(100, 100);
1469 virtual ~MockOutputSurface() {}
1471 MOCK_METHOD0(EnsureBackbuffer
, void());
1472 MOCK_METHOD0(DiscardBackbuffer
, void());
1473 MOCK_METHOD2(Reshape
, void(gfx::Size size
, float scale_factor
));
1474 MOCK_METHOD0(BindFramebuffer
, void());
1475 MOCK_METHOD1(SwapBuffers
, void(CompositorFrame
* frame
));
1478 class MockOutputSurfaceTest
: public testing::Test
, public FakeRendererClient
{
1480 virtual void SetUp() {
1481 FakeOutputSurfaceClient output_surface_client_
;
1482 CHECK(output_surface_
.BindToClient(&output_surface_client_
));
1484 resource_provider_
= ResourceProvider::Create(&output_surface_
, 0).Pass();
1486 renderer_
.reset(new FakeRendererGL(this,
1488 resource_provider_
.get()));
1489 EXPECT_TRUE(renderer_
->Initialize());
1492 void SwapBuffers() { renderer_
->SwapBuffers(); }
1495 gfx::Rect
viewport_rect(DeviceViewport());
1496 ScopedPtrVector
<RenderPass
>* render_passes
= render_passes_in_draw_order();
1497 render_passes
->clear();
1499 RenderPass::Id
render_pass_id(1, 0);
1500 TestRenderPass
* render_pass
= AddRenderPass(
1501 render_passes
, render_pass_id
, viewport_rect
, gfx::Transform());
1502 AddQuad(render_pass
, viewport_rect
, SK_ColorGREEN
);
1504 EXPECT_CALL(output_surface_
, EnsureBackbuffer()).WillRepeatedly(Return());
1506 EXPECT_CALL(output_surface_
,
1507 Reshape(DeviceViewport().size(), DeviceScaleFactor())).Times(1);
1509 EXPECT_CALL(output_surface_
, BindFramebuffer()).Times(1);
1511 EXPECT_CALL(*Context(), drawElements(_
, _
, _
, _
)).Times(1);
1513 renderer_
->DecideRenderPassAllocationsForFrame(
1514 *render_passes_in_draw_order());
1515 renderer_
->DrawFrame(render_passes_in_draw_order(), NULL
);
1518 OutputSurfaceMockContext
* Context() {
1519 return static_cast<OutputSurfaceMockContext
*>(
1520 output_surface_
.context_provider()->Context3d());
1523 FakeOutputSurfaceClient output_surface_client_
;
1524 StrictMock
<MockOutputSurface
> output_surface_
;
1525 scoped_ptr
<ResourceProvider
> resource_provider_
;
1526 scoped_ptr
<FakeRendererGL
> renderer_
;
1529 TEST_F(MockOutputSurfaceTest
, DrawFrameAndSwap
) {
1532 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1533 renderer_
->SwapBuffers();
1536 TEST_F(MockOutputSurfaceTest
, DrawFrameAndResizeAndSwap
) {
1538 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1539 renderer_
->SwapBuffers();
1541 set_viewport_and_scale(gfx::Size(2, 2), 2.f
);
1542 renderer_
->ViewportChanged();
1545 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1546 renderer_
->SwapBuffers();
1549 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1550 renderer_
->SwapBuffers();
1552 set_viewport_and_scale(gfx::Size(1, 1), 1.f
);
1553 renderer_
->ViewportChanged();
1556 EXPECT_CALL(output_surface_
, SwapBuffers(_
)).Times(1);
1557 renderer_
->SwapBuffers();
1560 class GLRendererTestSyncPoint
: public GLRendererPixelTest
{
1562 static void SyncPointCallback(int* callback_count
) {
1563 ++(*callback_count
);
1564 base::MessageLoop::current()->QuitWhenIdle();
1567 static void OtherCallback(int* callback_count
) {
1568 ++(*callback_count
);
1569 base::MessageLoop::current()->QuitWhenIdle();
1573 #if !defined(OS_ANDROID)
1574 TEST_F(GLRendererTestSyncPoint
, SignalSyncPointOnLostContext
) {
1575 int sync_point_callback_count
= 0;
1576 int other_callback_count
= 0;
1577 unsigned sync_point
=
1578 output_surface_
->context_provider()->Context3d()->insertSyncPoint();
1580 output_surface_
->context_provider()->Context3d()->loseContextCHROMIUM(
1581 GL_GUILTY_CONTEXT_RESET_ARB
, GL_INNOCENT_CONTEXT_RESET_ARB
);
1583 SyncPointHelper::SignalSyncPoint(
1584 output_surface_
->context_provider()->Context3d(),
1586 base::Bind(&SyncPointCallback
, &sync_point_callback_count
));
1587 EXPECT_EQ(0, sync_point_callback_count
);
1588 EXPECT_EQ(0, other_callback_count
);
1590 // Make the sync point happen.
1591 output_surface_
->context_provider()->Context3d()->finish();
1592 // Post a task after the sync point.
1593 base::MessageLoop::current()->PostTask(
1595 base::Bind(&OtherCallback
, &other_callback_count
));
1597 base::MessageLoop::current()->Run();
1599 // The sync point shouldn't have happened since the context was lost.
1600 EXPECT_EQ(0, sync_point_callback_count
);
1601 EXPECT_EQ(1, other_callback_count
);
1604 TEST_F(GLRendererTestSyncPoint
, SignalSyncPoint
) {
1605 int sync_point_callback_count
= 0;
1606 int other_callback_count
= 0;
1607 unsigned sync_point
=
1608 output_surface_
->context_provider()->Context3d()->insertSyncPoint();
1610 SyncPointHelper::SignalSyncPoint(
1611 output_surface_
->context_provider()->Context3d(),
1613 base::Bind(&SyncPointCallback
, &sync_point_callback_count
));
1614 EXPECT_EQ(0, sync_point_callback_count
);
1615 EXPECT_EQ(0, other_callback_count
);
1617 // Make the sync point happen.
1618 output_surface_
->context_provider()->Context3d()->finish();
1619 // Post a task after the sync point.
1620 base::MessageLoop::current()->PostTask(
1622 base::Bind(&OtherCallback
, &other_callback_count
));
1624 base::MessageLoop::current()->Run();
1626 // The sync point should have happened.
1627 EXPECT_EQ(1, sync_point_callback_count
);
1628 EXPECT_EQ(1, other_callback_count
);
1630 #endif // OS_ANDROID