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/resources/sync_point_helper.h"
14 #include "cc/test/fake_impl_proxy.h"
15 #include "cc/test/fake_layer_tree_host_impl.h"
16 #include "cc/test/fake_output_surface.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 "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "third_party/khronos/GLES2/gl2.h"
26 #include "third_party/skia/include/core/SkImageFilter.h"
27 #include "third_party/skia/include/core/SkMatrix.h"
28 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
29 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
30 #include "ui/gfx/transform.h"
33 using testing::AnyNumber
;
34 using testing::AtLeast
;
35 using testing::Expectation
;
36 using testing::InSequence
;
38 using testing::Return
;
39 using testing::StrictMock
;
40 using WebKit::WebGraphicsMemoryAllocation
;
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
));
96 EXPECT_PROGRAM_VALID(renderer()->GetTextureProgramFlip(precision
));
97 EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision
));
98 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision
));
99 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision
));
100 // This is unlikely to be ever true in tests due to usage of osmesa.
101 if (renderer()->Capabilities().using_egl_image
)
102 EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision
));
104 EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision
));
110 #if !defined(OS_ANDROID)
111 TEST_F(GLRendererShaderPixelTest
, AllShadersCompile
) { TestShaders(); }
114 class FrameCountingMemoryAllocationSettingContext
115 : public TestWebGraphicsContext3D
{
117 FrameCountingMemoryAllocationSettingContext() : frame_(0) {}
119 // WebGraphicsContext3D methods.
121 // This method would normally do a glSwapBuffers under the hood.
122 virtual void prepareTexture() { frame_
++; }
123 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
124 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM
* callback
) {
125 memory_allocation_changed_callback_
= callback
;
127 virtual WebString
getString(WebKit::WGC3Denum name
) {
128 if (name
== GL_EXTENSIONS
)
130 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
131 "GL_CHROMIUM_discard_backbuffer");
135 // Methods added for test.
136 int frame_count() { return frame_
; }
137 void SetMemoryAllocation(WebGraphicsMemoryAllocation allocation
) {
138 memory_allocation_changed_callback_
->onMemoryAllocationChanged(allocation
);
143 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM
*
144 memory_allocation_changed_callback_
;
147 class FakeRendererClient
: public RendererClient
{
150 : host_impl_(&proxy_
),
151 set_full_root_layer_damage_count_(0),
152 last_call_was_set_visibility_(0),
153 root_layer_(LayerImpl::Create(host_impl_
.active_tree(), 1)),
154 memory_allocation_limit_bytes_(
155 PrioritizedResourceManager::DefaultMemoryAllocationLimit()),
156 viewport_size_(gfx::Size(1, 1)),
158 root_layer_
->CreateRenderSurface();
159 RenderPass::Id render_pass_id
=
160 root_layer_
->render_surface()->RenderPassId();
161 scoped_ptr
<RenderPass
> root_render_pass
= RenderPass::Create();
162 root_render_pass
->SetNew(
163 render_pass_id
, gfx::Rect(), gfx::Rect(), gfx::Transform());
164 render_passes_in_draw_order_
.push_back(root_render_pass
.Pass());
167 // RendererClient methods.
168 virtual gfx::Rect
DeviceViewport() const OVERRIDE
{
169 static gfx::Size
fake_size(1, 1);
170 return gfx::Rect(fake_size
);
172 virtual float DeviceScaleFactor() const OVERRIDE
{
173 return scale_factor_
;
175 virtual const LayerTreeSettings
& Settings() const OVERRIDE
{
176 static LayerTreeSettings fake_settings
;
177 return fake_settings
;
179 virtual void SetFullRootLayerDamage() OVERRIDE
{
180 set_full_root_layer_damage_count_
++;
182 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
184 memory_allocation_limit_bytes_
= policy
.bytes_limit_when_visible
;
186 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
188 if (last_call_was_set_visibility_
)
189 *last_call_was_set_visibility_
= false;
191 virtual bool HasImplThread() const OVERRIDE
{ return false; }
192 virtual bool ShouldClearRootRenderPass() const OVERRIDE
{ return true; }
193 virtual CompositorFrameMetadata
MakeCompositorFrameMetadata() const OVERRIDE
{
194 return CompositorFrameMetadata();
196 virtual bool AllowPartialSwap() const OVERRIDE
{
200 // Methods added for test.
201 int set_full_root_layer_damage_count() const {
202 return set_full_root_layer_damage_count_
;
204 void set_last_call_was_set_visibility_pointer(
205 bool* last_call_was_set_visibility
) {
206 last_call_was_set_visibility_
= last_call_was_set_visibility
;
208 void set_viewport_and_scale(
209 gfx::Size viewport_size
, float scale_factor
) {
210 viewport_size_
= viewport_size
;
211 scale_factor_
= scale_factor
;
214 RenderPass
* root_render_pass() { return render_passes_in_draw_order_
.back(); }
215 RenderPassList
* render_passes_in_draw_order() {
216 return &render_passes_in_draw_order_
;
219 size_t memory_allocation_limit_bytes() const {
220 return memory_allocation_limit_bytes_
;
224 FakeImplProxy proxy_
;
225 FakeLayerTreeHostImpl host_impl_
;
226 int set_full_root_layer_damage_count_
;
227 bool* last_call_was_set_visibility_
;
228 scoped_ptr
<LayerImpl
> root_layer_
;
229 RenderPassList render_passes_in_draw_order_
;
230 size_t memory_allocation_limit_bytes_
;
231 gfx::Size viewport_size_
;
235 class FakeRendererGL
: public GLRenderer
{
237 FakeRendererGL(RendererClient
* client
,
238 OutputSurface
* output_surface
,
239 ResourceProvider
* resource_provider
)
240 : GLRenderer(client
, output_surface
, resource_provider
, 0) {}
242 // GLRenderer methods.
244 // Changing visibility to public.
245 using GLRenderer::Initialize
;
246 using GLRenderer::IsBackbufferDiscarded
;
247 using GLRenderer::DoDrawQuad
;
248 using GLRenderer::BeginDrawingFrame
;
249 using GLRenderer::FinishDrawingQuadList
;
252 class GLRendererTest
: public testing::Test
{
255 : suggest_have_backbuffer_yes_(1, true),
256 suggest_have_backbuffer_no_(1, false),
257 output_surface_(FakeOutputSurface::Create3d(
258 scoped_ptr
<WebKit::WebGraphicsContext3D
>(
259 new FrameCountingMemoryAllocationSettingContext()))),
260 resource_provider_(ResourceProvider::Create(output_surface_
.get(), 0)),
261 renderer_(&mock_client_
,
262 output_surface_
.get(),
263 resource_provider_
.get()) {}
265 virtual void SetUp() { renderer_
.Initialize(); }
267 void SwapBuffers() { renderer_
.SwapBuffers(); }
269 FrameCountingMemoryAllocationSettingContext
* Context() {
270 return static_cast<FrameCountingMemoryAllocationSettingContext
*>(
271 output_surface_
->context3d());
274 WebGraphicsMemoryAllocation suggest_have_backbuffer_yes_
;
275 WebGraphicsMemoryAllocation suggest_have_backbuffer_no_
;
277 scoped_ptr
<OutputSurface
> output_surface_
;
278 FakeRendererClient mock_client_
;
279 scoped_ptr
<ResourceProvider
> resource_provider_
;
280 FakeRendererGL renderer_
;
283 // Closing the namespace here so that GLRendererShaderTest can take advantage
284 // of the friend relationship with GLRenderer and all of the mock classes
285 // declared above it.
289 // Gives unique shader ids and unique program ids for tests that need them.
290 class ShaderCreatorMockGraphicsContext
: public TestWebGraphicsContext3D
{
292 ShaderCreatorMockGraphicsContext()
293 : next_program_id_number_(10000),
294 next_shader_id_number_(1) {}
296 bool hasShader(WebGLId shader
) {
297 return shader_set_
.find(shader
) != shader_set_
.end();
300 bool hasProgram(WebGLId program
) {
301 return program_set_
.find(program
) != program_set_
.end();
304 virtual WebGLId
createProgram() {
305 unsigned program
= next_program_id_number_
;
306 program_set_
.insert(program
);
307 next_program_id_number_
++;
311 virtual void deleteProgram(WebGLId program
) {
312 ASSERT_TRUE(hasProgram(program
));
313 program_set_
.erase(program
);
316 virtual void useProgram(WebGLId program
) {
319 ASSERT_TRUE(hasProgram(program
));
322 virtual WebKit::WebGLId
createShader(WebKit::WGC3Denum
) {
323 unsigned shader
= next_shader_id_number_
;
324 shader_set_
.insert(shader
);
325 next_shader_id_number_
++;
329 virtual void deleteShader(WebKit::WebGLId shader
) {
330 ASSERT_TRUE(hasShader(shader
));
331 shader_set_
.erase(shader
);
334 virtual void attachShader(WebGLId program
, WebGLId shader
) {
335 ASSERT_TRUE(hasProgram(program
));
336 ASSERT_TRUE(hasShader(shader
));
340 unsigned next_program_id_number_
;
341 unsigned next_shader_id_number_
;
342 std::set
<unsigned> program_set_
;
343 std::set
<unsigned> shader_set_
;
346 class GLRendererShaderTest
: public testing::Test
{
348 GLRendererShaderTest()
349 : output_surface_(FakeOutputSurface::Create3d(
350 scoped_ptr
<WebKit::WebGraphicsContext3D
>(
351 new ShaderCreatorMockGraphicsContext()))),
352 resource_provider_(ResourceProvider::Create(output_surface_
.get(), 0)),
353 renderer_(scoped_ptr
<FakeRendererGL
>(
354 new FakeRendererGL(&mock_client_
,
355 output_surface_
.get(),
356 resource_provider_
.get()))) {
357 renderer_
->Initialize();
360 void TestRenderPassProgram() {
361 EXPECT_PROGRAM_VALID(renderer_
->render_pass_program_
);
362 EXPECT_EQ(renderer_
->render_pass_program_
->program(),
363 renderer_
->program_shadow_
);
366 void TestRenderPassColorMatrixProgram() {
367 EXPECT_PROGRAM_VALID(renderer_
->render_pass_color_matrix_program_
);
368 EXPECT_EQ(renderer_
->render_pass_color_matrix_program_
->program(),
369 renderer_
->program_shadow_
);
372 void TestRenderPassMaskProgram() {
373 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_program_
);
374 EXPECT_EQ(renderer_
->render_pass_mask_program_
->program(),
375 renderer_
->program_shadow_
);
378 void TestRenderPassMaskColorMatrixProgram() {
379 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_color_matrix_program_
);
380 EXPECT_EQ(renderer_
->render_pass_mask_color_matrix_program_
->program(),
381 renderer_
->program_shadow_
);
384 void TestRenderPassProgramAA() {
385 EXPECT_PROGRAM_VALID(renderer_
->render_pass_program_aa_
);
386 EXPECT_EQ(renderer_
->render_pass_program_aa_
->program(),
387 renderer_
->program_shadow_
);
390 void TestRenderPassColorMatrixProgramAA() {
391 EXPECT_PROGRAM_VALID(renderer_
->render_pass_color_matrix_program_aa_
);
392 EXPECT_EQ(renderer_
->render_pass_color_matrix_program_aa_
->program(),
393 renderer_
->program_shadow_
);
396 void TestRenderPassMaskProgramAA() {
397 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_program_aa_
);
398 EXPECT_EQ(renderer_
->render_pass_mask_program_aa_
->program(),
399 renderer_
->program_shadow_
);
402 void TestRenderPassMaskColorMatrixProgramAA() {
403 EXPECT_PROGRAM_VALID(renderer_
->render_pass_mask_color_matrix_program_aa_
);
404 EXPECT_EQ(renderer_
->render_pass_mask_color_matrix_program_aa_
->program(),
405 renderer_
->program_shadow_
);
408 void TestSolidColorProgramAA() {
409 EXPECT_PROGRAM_VALID(renderer_
->solid_color_program_aa_
);
410 EXPECT_EQ(renderer_
->solid_color_program_aa_
->program(),
411 renderer_
->program_shadow_
);
414 scoped_ptr
<OutputSurface
> output_surface_
;
415 FakeRendererClient mock_client_
;
416 scoped_ptr
<ResourceProvider
> resource_provider_
;
417 scoped_ptr
<FakeRendererGL
> renderer_
;
422 // Test GLRenderer discardBackbuffer functionality:
423 // Suggest recreating framebuffer when one already exists.
424 // Expected: it does nothing.
425 TEST_F(GLRendererTest
, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing
) {
426 Context()->SetMemoryAllocation(suggest_have_backbuffer_yes_
);
427 EXPECT_EQ(0, mock_client_
.set_full_root_layer_damage_count());
428 EXPECT_FALSE(renderer_
.IsBackbufferDiscarded());
431 EXPECT_EQ(1, Context()->frame_count());
434 // Test GLRenderer DiscardBackbuffer functionality:
435 // Suggest discarding framebuffer when one exists and the renderer is not
437 // Expected: it is discarded and damage tracker is reset.
440 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible
) {
441 renderer_
.SetVisible(false);
442 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
443 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
444 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
447 // Test GLRenderer DiscardBackbuffer functionality:
448 // Suggest discarding framebuffer when one exists and the renderer is visible.
449 // Expected: the allocation is ignored.
450 TEST_F(GLRendererTest
, SuggestBackbufferNoDoNothingWhenVisible
) {
451 renderer_
.SetVisible(true);
452 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
453 EXPECT_EQ(0, mock_client_
.set_full_root_layer_damage_count());
454 EXPECT_FALSE(renderer_
.IsBackbufferDiscarded());
457 // Test GLRenderer DiscardBackbuffer functionality:
458 // Suggest discarding framebuffer when one does not exist.
459 // Expected: it does nothing.
460 TEST_F(GLRendererTest
, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing
) {
461 renderer_
.SetVisible(false);
462 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
463 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
464 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
466 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
467 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
468 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
471 // Test GLRenderer DiscardBackbuffer functionality:
472 // Begin drawing a frame while a framebuffer is discarded.
473 // Expected: will recreate framebuffer.
474 TEST_F(GLRendererTest
, DiscardedBackbufferIsRecreatedForScopeDuration
) {
475 renderer_
.SetVisible(false);
476 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
477 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
478 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
480 renderer_
.SetVisible(true);
481 renderer_
.DrawFrame(mock_client_
.render_passes_in_draw_order());
482 EXPECT_FALSE(renderer_
.IsBackbufferDiscarded());
485 EXPECT_EQ(1, Context()->frame_count());
488 TEST_F(GLRendererTest
, FramebufferDiscardedAfterReadbackWhenNotVisible
) {
489 renderer_
.SetVisible(false);
490 Context()->SetMemoryAllocation(suggest_have_backbuffer_no_
);
491 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
492 EXPECT_EQ(1, mock_client_
.set_full_root_layer_damage_count());
495 renderer_
.DrawFrame(mock_client_
.render_passes_in_draw_order());
496 EXPECT_FALSE(renderer_
.IsBackbufferDiscarded());
498 renderer_
.GetFramebufferPixels(pixels
, gfx::Rect(0, 0, 1, 1));
499 EXPECT_TRUE(renderer_
.IsBackbufferDiscarded());
500 EXPECT_EQ(2, mock_client_
.set_full_root_layer_damage_count());
503 class ForbidSynchronousCallContext
: public TestWebGraphicsContext3D
{
505 ForbidSynchronousCallContext() {}
507 virtual bool getActiveAttrib(WebGLId program
,
513 virtual bool getActiveUniform(WebGLId program
,
519 virtual void getAttachedShaders(WebGLId program
,
520 WGC3Dsizei max_count
,
525 virtual WGC3Dint
getAttribLocation(WebGLId program
, const WGC3Dchar
* name
) {
529 virtual void getBooleanv(WGC3Denum pname
, WGC3Dboolean
* value
) {
532 virtual void getBufferParameteriv(WGC3Denum target
,
537 virtual Attributes
getContextAttributes() {
541 virtual WGC3Denum
getError() {
545 virtual void getFloatv(WGC3Denum pname
, WGC3Dfloat
* value
) { ADD_FAILURE(); }
546 virtual void getFramebufferAttachmentParameteriv(WGC3Denum target
,
547 WGC3Denum attachment
,
552 virtual void getIntegerv(WGC3Denum pname
, WGC3Dint
* value
) {
553 if (pname
== GL_MAX_TEXTURE_SIZE
) {
554 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
561 // We allow querying the shader compilation and program link status in debug
562 // mode, but not release.
563 virtual void getProgramiv(WebGLId program
, WGC3Denum pname
, WGC3Dint
* value
) {
571 virtual void getShaderiv(WebGLId shader
, WGC3Denum pname
, WGC3Dint
* value
) {
579 virtual WebString
getString(WGC3Denum name
) {
580 // We allow querying the extension string.
581 // FIXME: It'd be better to check that we only do this before starting any
582 // other expensive work (like starting a compilation)
583 if (name
!= GL_EXTENSIONS
)
588 virtual WebString
getProgramInfoLog(WebGLId program
) {
592 virtual void getRenderbufferParameteriv(WGC3Denum target
,
598 virtual WebString
getShaderInfoLog(WebGLId shader
) {
602 virtual void getShaderPrecisionFormat(WGC3Denum shadertype
,
603 WGC3Denum precisiontype
,
605 WGC3Dint
* precision
) {
608 virtual WebString
getShaderSource(WebGLId shader
) {
612 virtual void getTexParameterfv(WGC3Denum target
,
617 virtual void getTexParameteriv(WGC3Denum target
,
622 virtual void getUniformfv(WebGLId program
,
627 virtual void getUniformiv(WebGLId program
,
632 virtual WGC3Dint
getUniformLocation(WebGLId program
, const WGC3Dchar
* name
) {
636 virtual void getVertexAttribfv(WGC3Duint index
,
641 virtual void getVertexAttribiv(WGC3Duint index
,
646 virtual WGC3Dsizeiptr
getVertexAttribOffset(WGC3Duint index
,
653 // This test isn't using the same fixture as GLRendererTest, and you can't mix
654 // TEST() and TEST_F() with the same name, Hence LRC2.
655 TEST(GLRendererTest2
, InitializationDoesNotMakeSynchronousCalls
) {
656 FakeRendererClient mock_client
;
657 scoped_ptr
<OutputSurface
> output_surface(
658 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
659 new ForbidSynchronousCallContext
)));
660 scoped_ptr
<ResourceProvider
> resource_provider(
661 ResourceProvider::Create(output_surface
.get(), 0));
662 FakeRendererGL
renderer(
663 &mock_client
, output_surface
.get(), resource_provider
.get());
665 EXPECT_TRUE(renderer
.Initialize());
668 class LoseContextOnFirstGetContext
: public TestWebGraphicsContext3D
{
670 LoseContextOnFirstGetContext() : context_lost_(false) {}
672 virtual bool makeContextCurrent() OVERRIDE
{ return !context_lost_
; }
674 virtual void getProgramiv(WebGLId program
, WGC3Denum pname
, WGC3Dint
* value
)
676 context_lost_
= true;
680 virtual void getShaderiv(WebGLId shader
, WGC3Denum pname
, WGC3Dint
* value
)
682 context_lost_
= true;
686 virtual WGC3Denum
getGraphicsResetStatusARB() OVERRIDE
{
687 return context_lost_
? 1 : 0;
694 TEST(GLRendererTest2
, InitializationWithQuicklyLostContextDoesNotAssert
) {
695 FakeRendererClient mock_client
;
696 scoped_ptr
<OutputSurface
> output_surface(
697 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
698 new LoseContextOnFirstGetContext
)));
699 scoped_ptr
<ResourceProvider
> resource_provider(
700 ResourceProvider::Create(output_surface
.get(), 0));
701 FakeRendererGL
renderer(
702 &mock_client
, output_surface
.get(), resource_provider
.get());
704 renderer
.Initialize();
707 class ContextThatDoesNotSupportMemoryManagmentExtensions
708 : public TestWebGraphicsContext3D
{
710 ContextThatDoesNotSupportMemoryManagmentExtensions() {}
712 // WebGraphicsContext3D methods.
714 // This method would normally do a glSwapBuffers under the hood.
715 virtual void prepareTexture() {}
716 virtual void setMemoryAllocationChangedCallbackCHROMIUM(
717 WebGraphicsMemoryAllocationChangedCallbackCHROMIUM
* callback
) {}
718 virtual WebString
getString(WebKit::WGC3Denum name
) { return WebString(); }
723 InitWithoutGpuMemManagerExtensionSupportShouldDefaultToNonZeroAllocation
) {
724 FakeRendererClient mock_client
;
725 scoped_ptr
<OutputSurface
> output_surface(
726 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
727 new ContextThatDoesNotSupportMemoryManagmentExtensions
)));
728 scoped_ptr
<ResourceProvider
> resource_provider(
729 ResourceProvider::Create(output_surface
.get(), 0));
730 FakeRendererGL
renderer(
731 &mock_client
, output_surface
.get(), resource_provider
.get());
733 renderer
.Initialize();
735 EXPECT_GT(mock_client
.memory_allocation_limit_bytes(), 0ul);
738 class ClearCountingContext
: public TestWebGraphicsContext3D
{
740 ClearCountingContext() : clear_(0) {}
742 virtual void clear(WGC3Dbitfield
) { clear_
++; }
744 int clear_count() const { return clear_
; }
750 TEST(GLRendererTest2
, OpaqueBackground
) {
751 FakeRendererClient mock_client
;
752 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
753 scoped_ptr
<WebKit::WebGraphicsContext3D
>(new ClearCountingContext
)));
754 ClearCountingContext
* context
=
755 static_cast<ClearCountingContext
*>(output_surface
->context3d());
756 scoped_ptr
<ResourceProvider
> resource_provider(
757 ResourceProvider::Create(output_surface
.get(), 0));
758 FakeRendererGL
renderer(
759 &mock_client
, output_surface
.get(), resource_provider
.get());
761 mock_client
.root_render_pass()->has_transparent_background
= false;
763 EXPECT_TRUE(renderer
.Initialize());
765 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
767 // On DEBUG builds, render passes with opaque background clear to blue to
768 // easily see regions that were not drawn on the screen.
770 EXPECT_EQ(0, context
->clear_count());
772 EXPECT_EQ(1, context
->clear_count());
776 TEST(GLRendererTest2
, TransparentBackground
) {
777 FakeRendererClient mock_client
;
778 scoped_ptr
<OutputSurface
> output_surface(FakeOutputSurface::Create3d(
779 scoped_ptr
<WebKit::WebGraphicsContext3D
>(new ClearCountingContext
)));
780 ClearCountingContext
* context
=
781 static_cast<ClearCountingContext
*>(output_surface
->context3d());
782 scoped_ptr
<ResourceProvider
> resource_provider(
783 ResourceProvider::Create(output_surface
.get(), 0));
784 FakeRendererGL
renderer(
785 &mock_client
, output_surface
.get(), resource_provider
.get());
787 mock_client
.root_render_pass()->has_transparent_background
= true;
789 EXPECT_TRUE(renderer
.Initialize());
791 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
793 EXPECT_EQ(1, context
->clear_count());
796 class VisibilityChangeIsLastCallTrackingContext
797 : public TestWebGraphicsContext3D
{
799 VisibilityChangeIsLastCallTrackingContext()
800 : last_call_was_set_visibility_(0) {}
802 // WebGraphicsContext3D methods.
803 virtual void setVisibilityCHROMIUM(bool visible
) {
804 if (!last_call_was_set_visibility_
)
806 DCHECK(*last_call_was_set_visibility_
== false);
807 *last_call_was_set_visibility_
= true;
809 virtual void flush() {
810 if (last_call_was_set_visibility_
)
811 *last_call_was_set_visibility_
= false;
813 virtual void deleteTexture(WebGLId
) {
814 if (last_call_was_set_visibility_
)
815 *last_call_was_set_visibility_
= false;
817 virtual void deleteFramebuffer(WebGLId
) {
818 if (last_call_was_set_visibility_
)
819 *last_call_was_set_visibility_
= false;
821 virtual void deleteRenderbuffer(WebGLId
) {
822 if (last_call_was_set_visibility_
)
823 *last_call_was_set_visibility_
= false;
826 // This method would normally do a glSwapBuffers under the hood.
827 virtual WebString
getString(WebKit::WGC3Denum name
) {
828 if (name
== GL_EXTENSIONS
)
830 "GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager "
831 "GL_CHROMIUM_discard_backbuffer");
835 // Methods added for test.
836 void set_last_call_was_set_visibility_pointer(
837 bool* last_call_was_set_visibility
) {
838 last_call_was_set_visibility_
= last_call_was_set_visibility
;
842 bool* last_call_was_set_visibility_
;
845 TEST(GLRendererTest2
, VisibilityChangeIsLastCall
) {
846 FakeRendererClient mock_client
;
847 scoped_ptr
<OutputSurface
> output_surface(
848 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
849 new VisibilityChangeIsLastCallTrackingContext
)));
850 VisibilityChangeIsLastCallTrackingContext
* context
=
851 static_cast<VisibilityChangeIsLastCallTrackingContext
*>(
852 output_surface
->context3d());
853 scoped_ptr
<ResourceProvider
> resource_provider(
854 ResourceProvider::Create(output_surface
.get(), 0));
855 FakeRendererGL
renderer(
856 &mock_client
, output_surface
.get(), resource_provider
.get());
858 EXPECT_TRUE(renderer
.Initialize());
860 bool last_call_was_set_visiblity
= false;
861 // Ensure that the call to setVisibilityCHROMIUM is the last call issue to the
862 // GPU process, after glFlush is called, and after the RendererClient's
863 // EnforceManagedMemoryPolicy is called. Plumb this tracking between both the
864 // RenderClient and the Context by giving them both a pointer to a variable on
866 context
->set_last_call_was_set_visibility_pointer(
867 &last_call_was_set_visiblity
);
868 mock_client
.set_last_call_was_set_visibility_pointer(
869 &last_call_was_set_visiblity
);
870 renderer
.SetVisible(true);
871 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
872 renderer
.SetVisible(false);
873 EXPECT_TRUE(last_call_was_set_visiblity
);
876 class TextureStateTrackingContext
: public TestWebGraphicsContext3D
{
878 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM
) {}
880 virtual WebString
getString(WGC3Denum name
) {
881 if (name
== GL_EXTENSIONS
)
882 return WebString("GL_OES_EGL_image_external");
886 MOCK_METHOD3(texParameteri
,
887 void(WGC3Denum target
, WGC3Denum pname
, WGC3Dint param
));
888 MOCK_METHOD4(drawElements
,
892 WGC3Dintptr offset
));
894 virtual void activeTexture(WGC3Denum texture
) {
895 EXPECT_NE(texture
, active_texture_
);
896 active_texture_
= texture
;
899 WGC3Denum
active_texture() const { return active_texture_
; }
902 WGC3Denum active_texture_
;
905 TEST(GLRendererTest2
, ActiveTextureState
) {
906 FakeRendererClient fake_client
;
907 scoped_ptr
<OutputSurface
> output_surface(
908 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
909 new TextureStateTrackingContext
)));
910 TextureStateTrackingContext
* context
=
911 static_cast<TextureStateTrackingContext
*>(output_surface
->context3d());
912 scoped_ptr
<ResourceProvider
> resource_provider(
913 ResourceProvider::Create(output_surface
.get(), 0));
914 FakeRendererGL
renderer(
915 &fake_client
, output_surface
.get(), resource_provider
.get());
917 // During initialization we are allowed to set any texture parameters.
918 EXPECT_CALL(*context
, texParameteri(_
, _
, _
)).Times(AnyNumber());
919 EXPECT_TRUE(renderer
.Initialize());
921 cc::RenderPass::Id
id(1, 1);
922 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
924 gfx::Rect(0, 0, 100, 100),
925 gfx::Rect(0, 0, 100, 100),
927 pass
->AppendOneOfEveryQuadType(resource_provider
.get(), RenderPass::Id(2, 1));
929 // Set up expected texture filter state transitions that match the quads
930 // created in AppendOneOfEveryQuadType().
931 Mock::VerifyAndClearExpectations(context
);
935 // yuv_quad is drawn with the default linear filter.
936 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
938 // tile_quad is drawn with GL_NEAREST because it is not transformed or
942 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
));
945 texParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
));
946 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
948 // transformed_tile_quad uses GL_LINEAR.
949 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
951 // scaled_tile_quad also uses GL_LINEAR.
952 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
));
954 // The remaining quads also use GL_LINEAR because nearest neighbor
955 // filtering is currently only used with tile quads.
956 EXPECT_CALL(*context
, drawElements(_
, _
, _
, _
)).Times(6);
959 cc::DirectRenderer::DrawingFrame drawing_frame
;
960 renderer
.BeginDrawingFrame(&drawing_frame
);
961 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0
), context
->active_texture());
963 for (cc::QuadList::BackToFrontIterator
964 it
= pass
->quad_list
.BackToFrontBegin();
965 it
!= pass
->quad_list
.BackToFrontEnd();
967 renderer
.DoDrawQuad(&drawing_frame
, *it
);
969 renderer
.FinishDrawingQuadList();
970 EXPECT_EQ(static_cast<unsigned>(GL_TEXTURE0
), context
->active_texture());
971 Mock::VerifyAndClearExpectations(context
);
974 class NoClearRootRenderPassFakeClient
: public FakeRendererClient
{
976 virtual bool ShouldClearRootRenderPass() const OVERRIDE
{ return false; }
979 class NoClearRootRenderPassMockContext
: public TestWebGraphicsContext3D
{
981 MOCK_METHOD1(clear
, void(WGC3Dbitfield mask
));
982 MOCK_METHOD4(drawElements
,
986 WGC3Dintptr offset
));
989 TEST(GLRendererTest2
, ShouldClearRootRenderPass
) {
990 NoClearRootRenderPassFakeClient mock_client
;
991 scoped_ptr
<OutputSurface
> output_surface(
992 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
993 new NoClearRootRenderPassMockContext
)));
994 NoClearRootRenderPassMockContext
* mock_context
=
995 static_cast<NoClearRootRenderPassMockContext
*>(
996 output_surface
->context3d());
997 scoped_ptr
<ResourceProvider
> resource_provider(
998 ResourceProvider::Create(output_surface
.get(), 0));
999 FakeRendererGL
renderer(
1000 &mock_client
, output_surface
.get(), resource_provider
.get());
1001 EXPECT_TRUE(renderer
.Initialize());
1003 gfx::Rect
viewport_rect(mock_client
.DeviceViewport());
1004 ScopedPtrVector
<RenderPass
>& render_passes
=
1005 *mock_client
.render_passes_in_draw_order();
1006 render_passes
.clear();
1008 RenderPass::Id
root_pass_id(1, 0);
1009 TestRenderPass
* root_pass
= AddRenderPass(
1010 &render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1011 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1013 RenderPass::Id
child_pass_id(2, 0);
1014 TestRenderPass
* child_pass
= AddRenderPass(
1015 &render_passes
, child_pass_id
, viewport_rect
, gfx::Transform());
1016 AddQuad(child_pass
, viewport_rect
, SK_ColorBLUE
);
1018 AddRenderPassQuad(root_pass
, child_pass
);
1020 // First render pass is not the root one, clearing should happen.
1021 EXPECT_CALL(*mock_context
, clear(GL_COLOR_BUFFER_BIT
)).Times(AtLeast(1));
1023 Expectation first_render_pass
=
1024 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
)).Times(1);
1026 // The second render pass is the root one, clearing should be prevented.
1027 EXPECT_CALL(*mock_context
, clear(GL_COLOR_BUFFER_BIT
)).Times(0)
1028 .After(first_render_pass
);
1030 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
)).Times(AnyNumber())
1031 .After(first_render_pass
);
1033 renderer
.DecideRenderPassAllocationsForFrame(
1034 *mock_client
.render_passes_in_draw_order());
1035 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
1037 // In multiple render passes all but the root pass should clear the
1039 Mock::VerifyAndClearExpectations(&mock_context
);
1042 class ScissorTestOnClearCheckingContext
: public TestWebGraphicsContext3D
{
1044 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
1046 virtual void clear(WGC3Dbitfield
) { EXPECT_FALSE(scissor_enabled_
); }
1048 virtual void enable(WGC3Denum cap
) {
1049 if (cap
== GL_SCISSOR_TEST
)
1050 scissor_enabled_
= true;
1053 virtual void disable(WGC3Denum cap
) {
1054 if (cap
== GL_SCISSOR_TEST
)
1055 scissor_enabled_
= false;
1059 bool scissor_enabled_
;
1062 TEST(GLRendererTest2
, ScissorTestWhenClearing
) {
1063 FakeRendererClient mock_client
;
1064 scoped_ptr
<OutputSurface
> output_surface(
1065 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
1066 new ScissorTestOnClearCheckingContext
)));
1067 scoped_ptr
<ResourceProvider
> resource_provider(
1068 ResourceProvider::Create(output_surface
.get(), 0));
1069 FakeRendererGL
renderer(
1070 &mock_client
, output_surface
.get(), resource_provider
.get());
1071 EXPECT_TRUE(renderer
.Initialize());
1072 EXPECT_FALSE(renderer
.Capabilities().using_partial_swap
);
1074 gfx::Rect
viewport_rect(mock_client
.DeviceViewport());
1075 ScopedPtrVector
<RenderPass
>& render_passes
=
1076 *mock_client
.render_passes_in_draw_order();
1077 render_passes
.clear();
1079 gfx::Rect
grand_child_rect(25, 25);
1080 RenderPass::Id
grand_child_pass_id(3, 0);
1081 TestRenderPass
* grand_child_pass
= AddRenderPass(
1082 &render_passes
, grand_child_pass_id
, grand_child_rect
, gfx::Transform());
1083 AddClippedQuad(grand_child_pass
, grand_child_rect
, SK_ColorYELLOW
);
1085 gfx::Rect
child_rect(50, 50);
1086 RenderPass::Id
child_pass_id(2, 0);
1087 TestRenderPass
* child_pass
= AddRenderPass(
1088 &render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1089 AddQuad(child_pass
, child_rect
, SK_ColorBLUE
);
1091 RenderPass::Id
root_pass_id(1, 0);
1092 TestRenderPass
* root_pass
= AddRenderPass(
1093 &render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1094 AddQuad(root_pass
, viewport_rect
, SK_ColorGREEN
);
1096 AddRenderPassQuad(root_pass
, child_pass
);
1097 AddRenderPassQuad(child_pass
, grand_child_pass
);
1099 renderer
.DecideRenderPassAllocationsForFrame(
1100 *mock_client
.render_passes_in_draw_order());
1101 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
1104 class NonReshapableOutputSurface
: public FakeOutputSurface
{
1106 explicit NonReshapableOutputSurface(
1107 scoped_ptr
<WebKit::WebGraphicsContext3D
> context3d
)
1108 : FakeOutputSurface(context3d
.Pass(), false) {}
1109 virtual gfx::Size
SurfaceSize() const OVERRIDE
{ return gfx::Size(500, 500); }
1112 class OffsetViewportRendererClient
: public FakeRendererClient
{
1114 virtual gfx::Rect
DeviceViewport() const OVERRIDE
{
1115 return gfx::Rect(10, 10, 100, 100);
1119 class FlippedScissorAndViewportContext
: public TestWebGraphicsContext3D
{
1121 FlippedScissorAndViewportContext()
1122 : did_call_viewport_(false), did_call_scissor_(false) {}
1123 virtual ~FlippedScissorAndViewportContext() {
1124 EXPECT_TRUE(did_call_viewport_
);
1125 EXPECT_TRUE(did_call_scissor_
);
1128 virtual void viewport(GLint x
, GLint y
, GLsizei width
, GLsizei height
) {
1131 EXPECT_EQ(100, width
);
1132 EXPECT_EQ(100, height
);
1133 did_call_viewport_
= true;
1136 virtual void scissor(GLint x
, GLint y
, GLsizei width
, GLsizei height
) {
1139 EXPECT_EQ(20, width
);
1140 EXPECT_EQ(20, height
);
1141 did_call_scissor_
= true;
1145 bool did_call_viewport_
;
1146 bool did_call_scissor_
;
1149 TEST(GLRendererTest2
, ScissorAndViewportWithinNonreshapableSurface
) {
1150 // In Android WebView, the OutputSurface is unable to respect reshape() calls
1151 // and maintains a fixed size. This test verifies that glViewport and
1152 // glScissor's Y coordinate is flipped correctly in this environment, and that
1153 // the glViewport can be at a nonzero origin within the surface.
1154 OffsetViewportRendererClient mock_client
;
1155 scoped_ptr
<OutputSurface
> output_surface(make_scoped_ptr(
1156 new NonReshapableOutputSurface(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
1157 new FlippedScissorAndViewportContext
))));
1158 scoped_ptr
<ResourceProvider
> resource_provider(
1159 ResourceProvider::Create(output_surface
.get(), 0));
1160 FakeRendererGL
renderer(
1161 &mock_client
, output_surface
.get(), resource_provider
.get());
1162 EXPECT_TRUE(renderer
.Initialize());
1163 EXPECT_FALSE(renderer
.Capabilities().using_partial_swap
);
1165 gfx::Rect
viewport_rect(mock_client
.DeviceViewport().size());
1166 gfx::Rect quad_rect
= gfx::Rect(20, 20, 20, 20);
1167 ScopedPtrVector
<RenderPass
>& render_passes
=
1168 *mock_client
.render_passes_in_draw_order();
1169 render_passes
.clear();
1171 RenderPass::Id
root_pass_id(1, 0);
1172 TestRenderPass
* root_pass
= AddRenderPass(
1173 &render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1174 AddClippedQuad(root_pass
, quad_rect
, SK_ColorGREEN
);
1176 renderer
.DecideRenderPassAllocationsForFrame(
1177 *mock_client
.render_passes_in_draw_order());
1178 renderer
.DrawFrame(mock_client
.render_passes_in_draw_order());
1181 TEST_F(GLRendererShaderTest
, DrawRenderPassQuadShaderPermutations
) {
1182 gfx::Rect
viewport_rect(mock_client_
.DeviceViewport());
1183 ScopedPtrVector
<RenderPass
>* render_passes
=
1184 mock_client_
.render_passes_in_draw_order();
1186 gfx::Rect
child_rect(50, 50);
1187 RenderPass::Id
child_pass_id(2, 0);
1188 TestRenderPass
* child_pass
;
1190 RenderPass::Id
root_pass_id(1, 0);
1191 TestRenderPass
* root_pass
;
1193 cc::ResourceProvider::ResourceId mask
=
1194 resource_provider_
->CreateResource(gfx::Size(20, 12),
1195 resource_provider_
->best_texture_format(),
1196 ResourceProvider::TextureUsageAny
);
1197 resource_provider_
->AllocateForTesting(mask
);
1199 SkScalar matrix
[20];
1200 float amount
= 0.5f
;
1201 matrix
[0] = 0.213f
+ 0.787f
* amount
;
1202 matrix
[1] = 0.715f
- 0.715f
* amount
;
1203 matrix
[2] = 1.f
- (matrix
[0] + matrix
[1]);
1204 matrix
[3] = matrix
[4] = 0;
1205 matrix
[5] = 0.213f
- 0.213f
* amount
;
1206 matrix
[6] = 0.715f
+ 0.285f
* amount
;
1207 matrix
[7] = 1.f
- (matrix
[5] + matrix
[6]);
1208 matrix
[8] = matrix
[9] = 0;
1209 matrix
[10] = 0.213f
- 0.213f
* amount
;
1210 matrix
[11] = 0.715f
- 0.715f
* amount
;
1211 matrix
[12] = 1.f
- (matrix
[10] + matrix
[11]);
1212 matrix
[13] = matrix
[14] = 0;
1213 matrix
[15] = matrix
[16] = matrix
[17] = matrix
[19] = 0;
1215 skia::RefPtr
<SkColorFilter
> color_filter(
1216 skia::AdoptRef(new SkColorMatrixFilter(matrix
)));
1217 skia::RefPtr
<SkImageFilter
> filter
= skia::AdoptRef(
1218 SkColorFilterImageFilter::Create(color_filter
.get(), NULL
));
1220 gfx::Transform transform_causing_aa
;
1221 transform_causing_aa
.Rotate(20.0);
1223 // RenderPassProgram
1224 render_passes
->clear();
1226 child_pass
= AddRenderPass(
1227 render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1229 root_pass
= AddRenderPass(
1230 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1232 AddRenderPassQuad(root_pass
,
1235 skia::RefPtr
<SkImageFilter
>(),
1238 renderer_
->DecideRenderPassAllocationsForFrame(
1239 *mock_client_
.render_passes_in_draw_order());
1240 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1241 TestRenderPassProgram();
1243 // RenderPassColorMatrixProgram
1244 render_passes
->clear();
1246 child_pass
= AddRenderPass(
1247 render_passes
, child_pass_id
, child_rect
, transform_causing_aa
);
1249 root_pass
= AddRenderPass(
1250 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1252 AddRenderPassQuad(root_pass
, child_pass
, 0, filter
, gfx::Transform());
1254 renderer_
->DecideRenderPassAllocationsForFrame(
1255 *mock_client_
.render_passes_in_draw_order());
1256 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1257 TestRenderPassColorMatrixProgram();
1259 // RenderPassMaskProgram
1260 render_passes
->clear();
1262 child_pass
= AddRenderPass(
1263 render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1265 root_pass
= AddRenderPass(
1266 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1268 AddRenderPassQuad(root_pass
,
1271 skia::RefPtr
<SkImageFilter
>(),
1274 renderer_
->DecideRenderPassAllocationsForFrame(
1275 *mock_client_
.render_passes_in_draw_order());
1276 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1277 TestRenderPassMaskProgram();
1279 // RenderPassMaskColorMatrixProgram
1280 render_passes
->clear();
1282 child_pass
= AddRenderPass(
1283 render_passes
, child_pass_id
, child_rect
, gfx::Transform());
1285 root_pass
= AddRenderPass(
1286 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1288 AddRenderPassQuad(root_pass
, child_pass
, mask
, filter
, gfx::Transform());
1290 renderer_
->DecideRenderPassAllocationsForFrame(
1291 *mock_client_
.render_passes_in_draw_order());
1292 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1293 TestRenderPassMaskColorMatrixProgram();
1295 // RenderPassProgramAA
1296 render_passes
->clear();
1298 child_pass
= AddRenderPass(
1299 render_passes
, child_pass_id
, child_rect
, transform_causing_aa
);
1301 root_pass
= AddRenderPass(
1302 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1304 AddRenderPassQuad(root_pass
,
1307 skia::RefPtr
<SkImageFilter
>(),
1308 transform_causing_aa
);
1310 renderer_
->DecideRenderPassAllocationsForFrame(
1311 *mock_client_
.render_passes_in_draw_order());
1312 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1313 TestRenderPassProgramAA();
1315 // RenderPassColorMatrixProgramAA
1316 render_passes
->clear();
1318 child_pass
= AddRenderPass(
1319 render_passes
, child_pass_id
, child_rect
, transform_causing_aa
);
1321 root_pass
= AddRenderPass(
1322 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1324 AddRenderPassQuad(root_pass
, child_pass
, 0, filter
, transform_causing_aa
);
1326 renderer_
->DecideRenderPassAllocationsForFrame(
1327 *mock_client_
.render_passes_in_draw_order());
1328 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1329 TestRenderPassColorMatrixProgramAA();
1331 // RenderPassMaskProgramAA
1332 render_passes
->clear();
1334 child_pass
= AddRenderPass(render_passes
, child_pass_id
, child_rect
,
1335 transform_causing_aa
);
1337 root_pass
= AddRenderPass(render_passes
, root_pass_id
, viewport_rect
,
1340 AddRenderPassQuad(root_pass
, child_pass
, mask
, skia::RefPtr
<SkImageFilter
>(),
1341 transform_causing_aa
);
1343 renderer_
->DecideRenderPassAllocationsForFrame(
1344 *mock_client_
.render_passes_in_draw_order());
1345 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1346 TestRenderPassMaskProgramAA();
1348 // RenderPassMaskColorMatrixProgramAA
1349 render_passes
->clear();
1351 child_pass
= AddRenderPass(render_passes
, child_pass_id
, child_rect
,
1352 transform_causing_aa
);
1354 root_pass
= AddRenderPass(render_passes
, root_pass_id
, viewport_rect
,
1355 transform_causing_aa
);
1357 AddRenderPassQuad(root_pass
, child_pass
, mask
, filter
, transform_causing_aa
);
1359 renderer_
->DecideRenderPassAllocationsForFrame(
1360 *mock_client_
.render_passes_in_draw_order());
1361 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1362 TestRenderPassMaskColorMatrixProgramAA();
1365 // At this time, the AA code path cannot be taken if the surface's rect would
1366 // project incorrectly by the given transform, because of w<0 clipping.
1367 TEST_F(GLRendererShaderTest
, DrawRenderPassQuadSkipsAAForClippingTransform
) {
1368 gfx::Rect
child_rect(50, 50);
1369 RenderPass::Id
child_pass_id(2, 0);
1370 TestRenderPass
* child_pass
;
1372 gfx::Rect
viewport_rect(mock_client_
.DeviceViewport());
1373 RenderPass::Id
root_pass_id(1, 0);
1374 TestRenderPass
* root_pass
;
1376 gfx::Transform transform_preventing_aa
;
1377 transform_preventing_aa
.ApplyPerspectiveDepth(40.0);
1378 transform_preventing_aa
.RotateAboutYAxis(-20.0);
1379 transform_preventing_aa
.Scale(30.0, 1.0);
1381 // Verify that the test transform and test rect actually do cause the clipped
1382 // flag to trigger. Otherwise we are not testing the intended scenario.
1383 bool clipped
= false;
1384 MathUtil::MapQuad(transform_preventing_aa
,
1385 gfx::QuadF(child_rect
),
1387 ASSERT_TRUE(clipped
);
1389 // Set up the render pass quad to be drawn
1390 ScopedPtrVector
<RenderPass
>* render_passes
=
1391 mock_client_
.render_passes_in_draw_order();
1393 render_passes
->clear();
1395 child_pass
= AddRenderPass(
1396 render_passes
, child_pass_id
, child_rect
, transform_preventing_aa
);
1398 root_pass
= AddRenderPass(
1399 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1401 AddRenderPassQuad(root_pass
,
1404 skia::RefPtr
<SkImageFilter
>(),
1405 transform_preventing_aa
);
1407 renderer_
->DecideRenderPassAllocationsForFrame(
1408 *mock_client_
.render_passes_in_draw_order());
1409 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1411 // If use_aa incorrectly ignores clipping, it will use the
1412 // RenderPassProgramAA shader instead of the RenderPassProgram.
1413 TestRenderPassProgram();
1416 TEST_F(GLRendererShaderTest
, DrawSolidColorShader
) {
1417 gfx::Rect
viewport_rect(mock_client_
.DeviceViewport());
1418 ScopedPtrVector
<RenderPass
>* render_passes
=
1419 mock_client_
.render_passes_in_draw_order();
1421 RenderPass::Id
root_pass_id(1, 0);
1422 TestRenderPass
* root_pass
;
1424 gfx::Transform pixel_aligned_transform_causing_aa
;
1425 pixel_aligned_transform_causing_aa
.Translate(25.5f
, 25.5f
);
1426 pixel_aligned_transform_causing_aa
.Scale(0.5f
, 0.5f
);
1428 render_passes
->clear();
1430 root_pass
= AddRenderPass(
1431 render_passes
, root_pass_id
, viewport_rect
, gfx::Transform());
1432 AddTransformedQuad(root_pass
,
1435 pixel_aligned_transform_causing_aa
);
1437 renderer_
->DecideRenderPassAllocationsForFrame(
1438 *mock_client_
.render_passes_in_draw_order());
1439 renderer_
->DrawFrame(mock_client_
.render_passes_in_draw_order());
1441 TestSolidColorProgramAA();
1444 class OutputSurfaceMockContext
: public TestWebGraphicsContext3D
{
1446 // Specifically override methods even if they are unused (used in conjunction
1447 // with StrictMock). We need to make sure that GLRenderer does not issue
1448 // framebuffer-related GL calls directly. Instead these are supposed to go
1449 // through the OutputSurface abstraction.
1450 MOCK_METHOD0(ensureBackbufferCHROMIUM
, void());
1451 MOCK_METHOD0(discardBackbufferCHROMIUM
, void());
1452 MOCK_METHOD2(bindFramebuffer
, void(WGC3Denum target
, WebGLId framebuffer
));
1453 MOCK_METHOD0(prepareTexture
, void());
1454 MOCK_METHOD3(reshapeWithScaleFactor
,
1455 void(int width
, int height
, float scale_factor
));
1456 MOCK_METHOD4(drawElements
,
1457 void(WGC3Denum mode
,
1460 WGC3Dintptr offset
));
1462 virtual WebString
getString(WebKit::WGC3Denum name
) {
1463 if (name
== GL_EXTENSIONS
)
1465 "GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_discard_backbuffer");
1470 class MockOutputSurface
: public OutputSurface
{
1473 : OutputSurface(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
1474 new StrictMock
<OutputSurfaceMockContext
>)) {
1475 surface_size_
= gfx::Size(100, 100);
1477 virtual ~MockOutputSurface() {}
1479 MOCK_METHOD0(EnsureBackbuffer
, void());
1480 MOCK_METHOD0(DiscardBackbuffer
, void());
1481 MOCK_METHOD2(Reshape
, void(gfx::Size size
, float scale_factor
));
1482 MOCK_METHOD0(BindFramebuffer
, void());
1483 MOCK_METHOD1(SwapBuffers
, void(CompositorFrame
* frame
));
1486 class MockOutputSurfaceTest
: public testing::Test
, public FakeRendererClient
{
1488 MockOutputSurfaceTest()
1489 : resource_provider_(ResourceProvider::Create(&output_surface_
, 0)),
1490 renderer_(this, &output_surface_
, resource_provider_
.get()) {}
1492 virtual void SetUp() { EXPECT_TRUE(renderer_
.Initialize()); }
1494 void SwapBuffers() { renderer_
.SwapBuffers(); }
1497 gfx::Rect
viewport_rect(DeviceViewport());
1498 ScopedPtrVector
<RenderPass
>* render_passes
= render_passes_in_draw_order();
1499 render_passes
->clear();
1501 RenderPass::Id
render_pass_id(1, 0);
1502 TestRenderPass
* render_pass
= AddRenderPass(
1503 render_passes
, render_pass_id
, viewport_rect
, gfx::Transform());
1504 AddQuad(render_pass
, viewport_rect
, SK_ColorGREEN
);
1506 EXPECT_CALL(output_surface_
, EnsureBackbuffer()).WillRepeatedly(Return());
1508 EXPECT_CALL(output_surface_
,
1509 Reshape(DeviceViewport().size(), DeviceScaleFactor())).Times(1);
1511 EXPECT_CALL(output_surface_
, BindFramebuffer()).Times(1);
1513 EXPECT_CALL(*Context(), drawElements(_
, _
, _
, _
)).Times(1);
1515 renderer_
.DecideRenderPassAllocationsForFrame(
1516 *render_passes_in_draw_order());
1517 renderer_
.DrawFrame(render_passes_in_draw_order());
1520 OutputSurfaceMockContext
* Context() {
1521 return static_cast<OutputSurfaceMockContext
*>(output_surface_
.context3d());
1524 StrictMock
<MockOutputSurface
> output_surface_
;
1525 scoped_ptr
<ResourceProvider
> resource_provider_
;
1526 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
= output_surface_
->context3d()->insertSyncPoint();
1579 output_surface_
->context3d()->loseContextCHROMIUM(
1580 GL_GUILTY_CONTEXT_RESET_ARB
, GL_INNOCENT_CONTEXT_RESET_ARB
);
1582 SyncPointHelper::SignalSyncPoint(
1583 output_surface_
->context3d(),
1585 base::Bind(&SyncPointCallback
, &sync_point_callback_count
));
1586 EXPECT_EQ(0, sync_point_callback_count
);
1587 EXPECT_EQ(0, other_callback_count
);
1589 // Make the sync point happen.
1590 output_surface_
->context3d()->finish();
1591 // Post a task after the sync point.
1592 base::MessageLoop::current()->PostTask(
1594 base::Bind(&OtherCallback
, &other_callback_count
));
1596 base::MessageLoop::current()->Run();
1598 // The sync point shouldn't have happened since the context was lost.
1599 EXPECT_EQ(0, sync_point_callback_count
);
1600 EXPECT_EQ(1, other_callback_count
);
1603 TEST_F(GLRendererTestSyncPoint
, SignalSyncPoint
) {
1604 int sync_point_callback_count
= 0;
1605 int other_callback_count
= 0;
1606 unsigned sync_point
= output_surface_
->context3d()->insertSyncPoint();
1608 SyncPointHelper::SignalSyncPoint(
1609 output_surface_
->context3d(),
1611 base::Bind(&SyncPointCallback
, &sync_point_callback_count
));
1612 EXPECT_EQ(0, sync_point_callback_count
);
1613 EXPECT_EQ(0, other_callback_count
);
1615 // Make the sync point happen.
1616 output_surface_
->context3d()->finish();
1617 // Post a task after the sync point.
1618 base::MessageLoop::current()->PostTask(
1620 base::Bind(&OtherCallback
, &other_callback_count
));
1622 base::MessageLoop::current()->Run();
1624 // The sync point should have happened.
1625 EXPECT_EQ(1, sync_point_callback_count
);
1626 EXPECT_EQ(1, other_callback_count
);
1628 #endif // OS_ANDROID