Fake PO2TS GetRequestContext should return NULL.
[chromium-blink-merge.git] / cc / output / gl_renderer_unittest.cc
blob476f7a85bd67e48d6f90273f8d6c85c247f42b33
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/output/gl_renderer.h"
7 #include <set>
9 #include "cc/base/math_util.h"
10 #include "cc/output/compositor_frame_metadata.h"
11 #include "cc/resources/prioritized_resource_manager.h"
12 #include "cc/resources/resource_provider.h"
13 #include "cc/test/fake_impl_proxy.h"
14 #include "cc/test/fake_layer_tree_host_impl.h"
15 #include "cc/test/fake_output_surface.h"
16 #include "cc/test/fake_output_surface_client.h"
17 #include "cc/test/mock_quad_culler.h"
18 #include "cc/test/pixel_test.h"
19 #include "cc/test/render_pass_test_common.h"
20 #include "cc/test/render_pass_test_utils.h"
21 #include "cc/test/test_web_graphics_context_3d.h"
22 #include "gpu/GLES2/gl2extchromium.h"
23 #include "gpu/command_buffer/client/context_support.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/khronos/GLES2/gl2.h"
27 #include "third_party/skia/include/core/SkImageFilter.h"
28 #include "third_party/skia/include/core/SkMatrix.h"
29 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
30 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
31 #include "ui/gfx/transform.h"
33 using testing::_;
34 using testing::AnyNumber;
35 using testing::Args;
36 using testing::AtLeast;
37 using testing::ElementsAre;
38 using testing::Expectation;
39 using testing::InSequence;
40 using testing::Mock;
41 using testing::Return;
42 using testing::StrictMock;
44 namespace cc {
46 class GLRendererTest : public testing::Test {
47 protected:
48 RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
50 RenderPassList render_passes_in_draw_order_;
53 #define EXPECT_PROGRAM_VALID(program_binding) \
54 do { \
55 EXPECT_TRUE((program_binding)->program()); \
56 EXPECT_TRUE((program_binding)->initialized()); \
57 } while (false)
59 // Explicitly named to be a friend in GLRenderer for shader access.
60 class GLRendererShaderPixelTest : public GLRendererPixelTest {
61 public:
62 void TestShaders() {
63 ASSERT_FALSE(renderer()->IsContextLost());
64 EXPECT_PROGRAM_VALID(renderer()->GetTileCheckerboardProgram());
65 EXPECT_PROGRAM_VALID(renderer()->GetDebugBorderProgram());
66 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgram());
67 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgramAA());
68 TestShadersWithTexCoordPrecision(TexCoordPrecisionMedium);
69 TestShadersWithTexCoordPrecision(TexCoordPrecisionHigh);
70 ASSERT_FALSE(renderer()->IsContextLost());
73 void TestShadersWithTexCoordPrecision(TexCoordPrecision precision) {
74 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgram(precision));
75 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassProgramAA(precision));
76 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgram(precision));
77 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA(precision));
78 EXPECT_PROGRAM_VALID(
79 renderer()->GetRenderPassColorMatrixProgram(precision));
80 EXPECT_PROGRAM_VALID(
81 renderer()->GetRenderPassMaskColorMatrixProgramAA(precision));
82 EXPECT_PROGRAM_VALID(
83 renderer()->GetRenderPassColorMatrixProgramAA(precision));
84 EXPECT_PROGRAM_VALID(
85 renderer()->GetRenderPassMaskColorMatrixProgram(precision));
86 EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision));
87 EXPECT_PROGRAM_VALID(
88 renderer()->GetNonPremultipliedTextureProgram(precision));
89 EXPECT_PROGRAM_VALID(renderer()->GetTextureBackgroundProgram(precision));
90 EXPECT_PROGRAM_VALID(
91 renderer()->GetNonPremultipliedTextureBackgroundProgram(precision));
92 EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision));
93 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision));
94 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision));
95 // This is unlikely to be ever true in tests due to usage of osmesa.
96 if (renderer()->Capabilities().using_egl_image)
97 EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision));
98 else
99 EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision));
100 TestShadersWithSamplerType(precision, SamplerType2D);
101 TestShadersWithSamplerType(precision, SamplerType2DRect);
102 // This is unlikely to be ever true in tests due to usage of osmesa.
103 if (renderer()->Capabilities().using_egl_image)
104 TestShadersWithSamplerType(precision, SamplerTypeExternalOES);
107 void TestShadersWithSamplerType(TexCoordPrecision precision,
108 SamplerType sampler) {
109 EXPECT_PROGRAM_VALID(renderer()->GetTileProgram(precision, sampler));
110 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramOpaque(precision, sampler));
111 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramAA(precision, sampler));
112 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzle(precision, sampler));
113 EXPECT_PROGRAM_VALID(
114 renderer()->GetTileProgramSwizzleOpaque(precision, sampler));
115 EXPECT_PROGRAM_VALID(
116 renderer()->GetTileProgramSwizzleAA(precision, sampler));
120 namespace {
122 #if !defined(OS_ANDROID)
123 TEST_F(GLRendererShaderPixelTest, AllShadersCompile) { TestShaders(); }
124 #endif
126 class FakeRendererClient : public RendererClient {
127 public:
128 FakeRendererClient() : set_full_root_layer_damage_count_(0) {}
130 // RendererClient methods.
131 virtual void SetFullRootLayerDamage() OVERRIDE {
132 set_full_root_layer_damage_count_++;
135 // Methods added for test.
136 int set_full_root_layer_damage_count() const {
137 return set_full_root_layer_damage_count_;
140 private:
141 int set_full_root_layer_damage_count_;
144 class FakeRendererGL : public GLRenderer {
145 public:
146 FakeRendererGL(RendererClient* client,
147 const LayerTreeSettings* settings,
148 OutputSurface* output_surface,
149 ResourceProvider* resource_provider)
150 : GLRenderer(client,
151 settings,
152 output_surface,
153 resource_provider,
154 NULL,
155 0) {}
157 // GLRenderer methods.
159 // Changing visibility to public.
160 using GLRenderer::IsBackbufferDiscarded;
161 using GLRenderer::DoDrawQuad;
162 using GLRenderer::BeginDrawingFrame;
163 using GLRenderer::FinishDrawingQuadList;
164 using GLRenderer::stencil_enabled;
167 class GLRendererWithDefaultHarnessTest : public GLRendererTest {
168 protected:
169 GLRendererWithDefaultHarnessTest() {
170 output_surface_ =
171 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()).Pass();
172 CHECK(output_surface_->BindToClient(&output_surface_client_));
174 resource_provider_ = ResourceProvider::Create(
175 output_surface_.get(), NULL, 0, false, 1).Pass();
176 renderer_ = make_scoped_ptr(new FakeRendererGL(&renderer_client_,
177 &settings_,
178 output_surface_.get(),
179 resource_provider_.get()));
182 void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
184 LayerTreeSettings settings_;
185 FakeOutputSurfaceClient output_surface_client_;
186 scoped_ptr<FakeOutputSurface> output_surface_;
187 FakeRendererClient renderer_client_;
188 scoped_ptr<ResourceProvider> resource_provider_;
189 scoped_ptr<FakeRendererGL> renderer_;
192 // Closing the namespace here so that GLRendererShaderTest can take advantage
193 // of the friend relationship with GLRenderer and all of the mock classes
194 // declared above it.
195 } // namespace
197 class GLRendererShaderTest : public GLRendererTest {
198 protected:
199 GLRendererShaderTest() {
200 output_surface_ = FakeOutputSurface::Create3d().Pass();
201 CHECK(output_surface_->BindToClient(&output_surface_client_));
203 resource_provider_ = ResourceProvider::Create(
204 output_surface_.get(), NULL, 0, false, 1).Pass();
205 renderer_.reset(new FakeRendererGL(&renderer_client_,
206 &settings_,
207 output_surface_.get(),
208 resource_provider_.get()));
211 void TestRenderPassProgram(TexCoordPrecision precision) {
212 EXPECT_PROGRAM_VALID(&renderer_->render_pass_program_[precision]);
213 EXPECT_EQ(renderer_->render_pass_program_[precision].program(),
214 renderer_->program_shadow_);
217 void TestRenderPassColorMatrixProgram(TexCoordPrecision precision) {
218 EXPECT_PROGRAM_VALID(
219 &renderer_->render_pass_color_matrix_program_[precision]);
220 EXPECT_EQ(renderer_->render_pass_color_matrix_program_[precision].program(),
221 renderer_->program_shadow_);
224 void TestRenderPassMaskProgram(TexCoordPrecision precision) {
225 EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_program_[precision]);
226 EXPECT_EQ(renderer_->render_pass_mask_program_[precision].program(),
227 renderer_->program_shadow_);
230 void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision) {
231 EXPECT_PROGRAM_VALID(
232 &renderer_->render_pass_mask_color_matrix_program_[precision]);
233 EXPECT_EQ(
234 renderer_->render_pass_mask_color_matrix_program_[precision].program(),
235 renderer_->program_shadow_);
238 void TestRenderPassProgramAA(TexCoordPrecision precision) {
239 EXPECT_PROGRAM_VALID(&renderer_->render_pass_program_aa_[precision]);
240 EXPECT_EQ(renderer_->render_pass_program_aa_[precision].program(),
241 renderer_->program_shadow_);
244 void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision) {
245 EXPECT_PROGRAM_VALID(
246 &renderer_->render_pass_color_matrix_program_aa_[precision]);
247 EXPECT_EQ(
248 renderer_->render_pass_color_matrix_program_aa_[precision].program(),
249 renderer_->program_shadow_);
252 void TestRenderPassMaskProgramAA(TexCoordPrecision precision) {
253 EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_program_aa_[precision]);
254 EXPECT_EQ(renderer_->render_pass_mask_program_aa_[precision].program(),
255 renderer_->program_shadow_);
258 void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision) {
259 EXPECT_PROGRAM_VALID(
260 &renderer_->render_pass_mask_color_matrix_program_aa_[precision]);
261 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_[precision]
262 .program(),
263 renderer_->program_shadow_);
266 void TestSolidColorProgramAA() {
267 EXPECT_PROGRAM_VALID(&renderer_->solid_color_program_aa_);
268 EXPECT_EQ(renderer_->solid_color_program_aa_.program(),
269 renderer_->program_shadow_);
272 LayerTreeSettings settings_;
273 FakeOutputSurfaceClient output_surface_client_;
274 scoped_ptr<FakeOutputSurface> output_surface_;
275 FakeRendererClient renderer_client_;
276 scoped_ptr<ResourceProvider> resource_provider_;
277 scoped_ptr<FakeRendererGL> renderer_;
280 namespace {
282 // Test GLRenderer DiscardBackbuffer functionality:
283 // Suggest discarding framebuffer when one exists and the renderer is not
284 // visible.
285 // Expected: it is discarded and damage tracker is reset.
286 TEST_F(
287 GLRendererWithDefaultHarnessTest,
288 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible) {
289 renderer_->SetVisible(false);
290 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
291 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
294 // Test GLRenderer DiscardBackbuffer functionality:
295 // Suggest discarding framebuffer when one exists and the renderer is visible.
296 // Expected: the allocation is ignored.
297 TEST_F(GLRendererWithDefaultHarnessTest,
298 SuggestBackbufferNoDoNothingWhenVisible) {
299 renderer_->SetVisible(true);
300 EXPECT_EQ(0, renderer_client_.set_full_root_layer_damage_count());
301 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
304 // Test GLRenderer DiscardBackbuffer functionality:
305 // Suggest discarding framebuffer when one does not exist.
306 // Expected: it does nothing.
307 TEST_F(GLRendererWithDefaultHarnessTest,
308 SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
309 renderer_->SetVisible(false);
310 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
311 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
313 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
314 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
317 // Test GLRenderer DiscardBackbuffer functionality:
318 // Begin drawing a frame while a framebuffer is discarded.
319 // Expected: will recreate framebuffer.
320 TEST_F(GLRendererWithDefaultHarnessTest,
321 DiscardedBackbufferIsRecreatedForScopeDuration) {
322 gfx::Rect viewport_rect(1, 1);
323 renderer_->SetVisible(false);
324 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
325 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
327 AddRenderPass(&render_passes_in_draw_order_,
328 RenderPass::Id(1, 0),
329 viewport_rect,
330 gfx::Transform());
332 renderer_->SetVisible(true);
333 renderer_->DrawFrame(&render_passes_in_draw_order_,
334 NULL,
335 1.f,
336 viewport_rect,
337 viewport_rect,
338 true,
339 false);
340 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
342 SwapBuffers();
343 EXPECT_EQ(1u, output_surface_->num_sent_frames());
346 TEST_F(GLRendererWithDefaultHarnessTest,
347 FramebufferDiscardedAfterReadbackWhenNotVisible) {
348 gfx::Rect viewport_rect(1, 1);
349 renderer_->SetVisible(false);
350 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
351 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
353 AddRenderPass(&render_passes_in_draw_order_,
354 RenderPass::Id(1, 0),
355 viewport_rect,
356 gfx::Transform());
358 char pixels[4];
359 renderer_->DrawFrame(&render_passes_in_draw_order_,
360 NULL,
361 1.f,
362 viewport_rect,
363 viewport_rect,
364 true,
365 false);
366 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
368 renderer_->GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
369 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
370 EXPECT_EQ(2, renderer_client_.set_full_root_layer_damage_count());
373 TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) {
374 gfx::Rect viewport_rect(1, 1);
375 EXPECT_FALSE(renderer_->stencil_enabled());
377 output_surface_->set_has_external_stencil_test(true);
379 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
380 RenderPass::Id(1, 0),
381 viewport_rect,
382 gfx::Transform());
383 root_pass->has_transparent_background = false;
385 renderer_->DrawFrame(&render_passes_in_draw_order_,
386 NULL,
387 1.f,
388 viewport_rect,
389 viewport_rect,
390 true,
391 false);
392 EXPECT_TRUE(renderer_->stencil_enabled());
395 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
396 public:
397 ForbidSynchronousCallContext() {}
399 virtual void getAttachedShaders(GLuint program,
400 GLsizei max_count,
401 GLsizei* count,
402 GLuint* shaders) OVERRIDE {
403 ADD_FAILURE();
405 virtual GLint getAttribLocation(GLuint program, const GLchar* name) OVERRIDE {
406 ADD_FAILURE();
407 return 0;
409 virtual void getBooleanv(GLenum pname, GLboolean* value) OVERRIDE {
410 ADD_FAILURE();
412 virtual void getBufferParameteriv(GLenum target,
413 GLenum pname,
414 GLint* value) OVERRIDE {
415 ADD_FAILURE();
417 virtual GLenum getError() OVERRIDE {
418 ADD_FAILURE();
419 return GL_NO_ERROR;
421 virtual void getFloatv(GLenum pname, GLfloat* value) OVERRIDE {
422 ADD_FAILURE();
424 virtual void getFramebufferAttachmentParameteriv(GLenum target,
425 GLenum attachment,
426 GLenum pname,
427 GLint* value) OVERRIDE {
428 ADD_FAILURE();
430 virtual void getIntegerv(GLenum pname, GLint* value) OVERRIDE {
431 if (pname == GL_MAX_TEXTURE_SIZE) {
432 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
433 *value = 1024;
434 } else {
435 ADD_FAILURE();
439 // We allow querying the shader compilation and program link status in debug
440 // mode, but not release.
441 virtual void getProgramiv(GLuint program,
442 GLenum pname,
443 GLint* value) OVERRIDE {
444 #ifndef NDEBUG
445 *value = 1;
446 #else
447 ADD_FAILURE();
448 #endif
451 virtual void getShaderiv(GLuint shader, GLenum pname, GLint* value) OVERRIDE {
452 #ifndef NDEBUG
453 *value = 1;
454 #else
455 ADD_FAILURE();
456 #endif
459 virtual void getRenderbufferParameteriv(GLenum target,
460 GLenum pname,
461 GLint* value) OVERRIDE {
462 ADD_FAILURE();
465 virtual void getShaderPrecisionFormat(GLenum shadertype,
466 GLenum precisiontype,
467 GLint* range,
468 GLint* precision) OVERRIDE {
469 ADD_FAILURE();
471 virtual void getTexParameterfv(GLenum target,
472 GLenum pname,
473 GLfloat* value) OVERRIDE {
474 ADD_FAILURE();
476 virtual void getTexParameteriv(GLenum target,
477 GLenum pname,
478 GLint* value) OVERRIDE {
479 ADD_FAILURE();
481 virtual void getUniformfv(GLuint program,
482 GLint location,
483 GLfloat* value) OVERRIDE {
484 ADD_FAILURE();
486 virtual void getUniformiv(GLuint program,
487 GLint location,
488 GLint* value) OVERRIDE {
489 ADD_FAILURE();
491 virtual GLint getUniformLocation(GLuint program,
492 const GLchar* name) OVERRIDE {
493 ADD_FAILURE();
494 return 0;
496 virtual void getVertexAttribfv(GLuint index,
497 GLenum pname,
498 GLfloat* value) OVERRIDE {
499 ADD_FAILURE();
501 virtual void getVertexAttribiv(GLuint index,
502 GLenum pname,
503 GLint* value) OVERRIDE {
504 ADD_FAILURE();
506 virtual GLsizeiptr getVertexAttribOffset(GLuint index,
507 GLenum pname) OVERRIDE {
508 ADD_FAILURE();
509 return 0;
512 TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
513 FakeOutputSurfaceClient output_surface_client;
514 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
515 scoped_ptr<TestWebGraphicsContext3D>(new ForbidSynchronousCallContext)));
516 CHECK(output_surface->BindToClient(&output_surface_client));
518 scoped_ptr<ResourceProvider> resource_provider(
519 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
521 LayerTreeSettings settings;
522 FakeRendererClient renderer_client;
523 FakeRendererGL renderer(&renderer_client,
524 &settings,
525 output_surface.get(),
526 resource_provider.get());
529 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
530 public:
531 LoseContextOnFirstGetContext() {}
533 virtual void getProgramiv(GLuint program,
534 GLenum pname,
535 GLint* value) OVERRIDE {
536 context_lost_ = true;
537 *value = 0;
540 virtual void getShaderiv(GLuint shader, GLenum pname, GLint* value) OVERRIDE {
541 context_lost_ = true;
542 *value = 0;
546 TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
547 FakeOutputSurfaceClient output_surface_client;
548 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
549 scoped_ptr<TestWebGraphicsContext3D>(new LoseContextOnFirstGetContext)));
550 CHECK(output_surface->BindToClient(&output_surface_client));
552 scoped_ptr<ResourceProvider> resource_provider(
553 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
555 LayerTreeSettings settings;
556 FakeRendererClient renderer_client;
557 FakeRendererGL renderer(&renderer_client,
558 &settings,
559 output_surface.get(),
560 resource_provider.get());
563 class ClearCountingContext : public TestWebGraphicsContext3D {
564 public:
565 ClearCountingContext() { test_capabilities_.gpu.discard_framebuffer = true; }
567 MOCK_METHOD3(discardFramebufferEXT,
568 void(GLenum target,
569 GLsizei numAttachments,
570 const GLenum* attachments));
571 MOCK_METHOD1(clear, void(GLbitfield mask));
574 TEST_F(GLRendererTest, OpaqueBackground) {
575 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
576 ClearCountingContext* context = context_owned.get();
578 FakeOutputSurfaceClient output_surface_client;
579 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
580 context_owned.PassAs<TestWebGraphicsContext3D>()));
581 CHECK(output_surface->BindToClient(&output_surface_client));
583 scoped_ptr<ResourceProvider> resource_provider(
584 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
586 LayerTreeSettings settings;
587 FakeRendererClient renderer_client;
588 FakeRendererGL renderer(&renderer_client,
589 &settings,
590 output_surface.get(),
591 resource_provider.get());
593 gfx::Rect viewport_rect(1, 1);
594 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
595 RenderPass::Id(1, 0),
596 viewport_rect,
597 gfx::Transform());
598 root_pass->has_transparent_background = false;
600 // On DEBUG builds, render passes with opaque background clear to blue to
601 // easily see regions that were not drawn on the screen.
602 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
603 .With(Args<2, 1>(ElementsAre(GL_COLOR_EXT)))
604 .Times(1);
605 #ifdef NDEBUG
606 EXPECT_CALL(*context, clear(_)).Times(0);
607 #else
608 EXPECT_CALL(*context, clear(_)).Times(1);
609 #endif
610 renderer.DrawFrame(&render_passes_in_draw_order_,
611 NULL,
612 1.f,
613 viewport_rect,
614 viewport_rect,
615 true,
616 false);
617 Mock::VerifyAndClearExpectations(context);
620 TEST_F(GLRendererTest, TransparentBackground) {
621 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
622 ClearCountingContext* context = context_owned.get();
624 FakeOutputSurfaceClient output_surface_client;
625 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
626 context_owned.PassAs<TestWebGraphicsContext3D>()));
627 CHECK(output_surface->BindToClient(&output_surface_client));
629 scoped_ptr<ResourceProvider> resource_provider(
630 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
632 LayerTreeSettings settings;
633 FakeRendererClient renderer_client;
634 FakeRendererGL renderer(&renderer_client,
635 &settings,
636 output_surface.get(),
637 resource_provider.get());
639 gfx::Rect viewport_rect(1, 1);
640 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
641 RenderPass::Id(1, 0),
642 viewport_rect,
643 gfx::Transform());
644 root_pass->has_transparent_background = true;
646 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1);
647 EXPECT_CALL(*context, clear(_)).Times(1);
648 renderer.DrawFrame(&render_passes_in_draw_order_,
649 NULL,
650 1.f,
651 viewport_rect,
652 viewport_rect,
653 true,
654 false);
656 Mock::VerifyAndClearExpectations(context);
659 TEST_F(GLRendererTest, OffscreenOutputSurface) {
660 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
661 ClearCountingContext* context = context_owned.get();
663 FakeOutputSurfaceClient output_surface_client;
664 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::CreateOffscreen(
665 context_owned.PassAs<TestWebGraphicsContext3D>()));
666 CHECK(output_surface->BindToClient(&output_surface_client));
668 scoped_ptr<ResourceProvider> resource_provider(
669 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
671 LayerTreeSettings settings;
672 FakeRendererClient renderer_client;
673 FakeRendererGL renderer(&renderer_client,
674 &settings,
675 output_surface.get(),
676 resource_provider.get());
678 gfx::Rect viewport_rect(1, 1);
679 AddRenderPass(&render_passes_in_draw_order_,
680 RenderPass::Id(1, 0),
681 viewport_rect,
682 gfx::Transform());
684 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
685 .With(Args<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0)))
686 .Times(1);
687 EXPECT_CALL(*context, clear(_)).Times(AnyNumber());
688 renderer.DrawFrame(&render_passes_in_draw_order_,
689 NULL,
690 1.f,
691 viewport_rect,
692 viewport_rect,
693 true,
694 false);
695 Mock::VerifyAndClearExpectations(context);
698 class VisibilityChangeIsLastCallTrackingContext
699 : public TestWebGraphicsContext3D {
700 public:
701 VisibilityChangeIsLastCallTrackingContext()
702 : last_call_was_set_visibility_(false) {}
704 // TestWebGraphicsContext3D methods.
705 virtual void flush() OVERRIDE { last_call_was_set_visibility_ = false; }
706 virtual void deleteTexture(GLuint) OVERRIDE {
707 last_call_was_set_visibility_ = false;
709 virtual void deleteFramebuffer(GLuint) OVERRIDE {
710 last_call_was_set_visibility_ = false;
712 virtual void deleteQueryEXT(GLuint) OVERRIDE {
713 last_call_was_set_visibility_ = false;
715 virtual void deleteRenderbuffer(GLuint) OVERRIDE {
716 last_call_was_set_visibility_ = false;
719 // Methods added for test.
720 void set_last_call_was_visibility(bool visible) {
721 DCHECK(last_call_was_set_visibility_ == false);
722 last_call_was_set_visibility_ = true;
724 bool last_call_was_set_visibility() const {
725 return last_call_was_set_visibility_;
728 private:
729 bool last_call_was_set_visibility_;
732 TEST_F(GLRendererTest, VisibilityChangeIsLastCall) {
733 scoped_ptr<VisibilityChangeIsLastCallTrackingContext> context_owned(
734 new VisibilityChangeIsLastCallTrackingContext);
735 VisibilityChangeIsLastCallTrackingContext* context = context_owned.get();
737 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create(
738 context_owned.PassAs<TestWebGraphicsContext3D>());
740 provider->support()->SetSurfaceVisibleCallback(base::Bind(
741 &VisibilityChangeIsLastCallTrackingContext::set_last_call_was_visibility,
742 base::Unretained(context)));
744 FakeOutputSurfaceClient output_surface_client;
745 scoped_ptr<OutputSurface> output_surface(
746 FakeOutputSurface::Create3d(provider));
747 CHECK(output_surface->BindToClient(&output_surface_client));
749 scoped_ptr<ResourceProvider> resource_provider(
750 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
752 LayerTreeSettings settings;
753 FakeRendererClient renderer_client;
754 FakeRendererGL renderer(&renderer_client,
755 &settings,
756 output_surface.get(),
757 resource_provider.get());
759 gfx::Rect viewport_rect(1, 1);
760 AddRenderPass(&render_passes_in_draw_order_,
761 RenderPass::Id(1, 0),
762 viewport_rect,
763 gfx::Transform());
765 // Ensure that the call to SetSurfaceVisible is the last call issue to the
766 // GPU process, after glFlush is called, and after the RendererClient's
767 // SetManagedMemoryPolicy is called. Plumb this tracking between both the
768 // RenderClient and the Context by giving them both a pointer to a variable on
769 // the stack.
770 renderer.SetVisible(true);
771 renderer.DrawFrame(&render_passes_in_draw_order_,
772 NULL,
773 1.f,
774 viewport_rect,
775 viewport_rect,
776 true,
777 false);
778 renderer.SetVisible(false);
779 EXPECT_TRUE(context->last_call_was_set_visibility());
782 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
783 public:
784 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {
785 test_capabilities_.gpu.egl_image_external = true;
788 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
789 MOCK_METHOD4(drawElements,
790 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
792 virtual void activeTexture(GLenum texture) {
793 EXPECT_NE(texture, active_texture_);
794 active_texture_ = texture;
797 GLenum active_texture() const { return active_texture_; }
799 private:
800 GLenum active_texture_;
803 TEST_F(GLRendererTest, ActiveTextureState) {
804 scoped_ptr<TextureStateTrackingContext> context_owned(
805 new TextureStateTrackingContext);
806 TextureStateTrackingContext* context = context_owned.get();
808 FakeOutputSurfaceClient output_surface_client;
809 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
810 context_owned.PassAs<TestWebGraphicsContext3D>()));
811 CHECK(output_surface->BindToClient(&output_surface_client));
813 scoped_ptr<ResourceProvider> resource_provider(
814 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
816 LayerTreeSettings settings;
817 FakeRendererClient renderer_client;
818 FakeRendererGL renderer(&renderer_client,
819 &settings,
820 output_surface.get(),
821 resource_provider.get());
823 // During initialization we are allowed to set any texture parameters.
824 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
826 RenderPass::Id id(1, 1);
827 TestRenderPass* root_pass = AddRenderPass(
828 &render_passes_in_draw_order_, id, gfx::Rect(100, 100), gfx::Transform());
829 root_pass->AppendOneOfEveryQuadType(resource_provider.get(),
830 RenderPass::Id(2, 1));
832 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
834 // Set up expected texture filter state transitions that match the quads
835 // created in AppendOneOfEveryQuadType().
836 Mock::VerifyAndClearExpectations(context);
838 InSequence sequence;
840 // yuv_quad is drawn with the default linear filter.
841 EXPECT_CALL(*context, drawElements(_, _, _, _));
843 // tile_quad is drawn with GL_NEAREST because it is not transformed or
844 // scaled.
845 EXPECT_CALL(
846 *context,
847 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
848 EXPECT_CALL(
849 *context,
850 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
851 EXPECT_CALL(*context, drawElements(_, _, _, _));
853 // transformed_tile_quad uses GL_LINEAR.
854 EXPECT_CALL(*context, drawElements(_, _, _, _));
856 // scaled_tile_quad also uses GL_LINEAR.
857 EXPECT_CALL(*context, drawElements(_, _, _, _));
859 // The remaining quads also use GL_LINEAR because nearest neighbor
860 // filtering is currently only used with tile quads.
861 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
864 gfx::Rect viewport_rect(100, 100);
865 renderer.DrawFrame(&render_passes_in_draw_order_,
866 NULL,
867 1.f,
868 viewport_rect,
869 viewport_rect,
870 true,
871 false);
872 Mock::VerifyAndClearExpectations(context);
875 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
876 public:
877 MOCK_METHOD1(clear, void(GLbitfield mask));
878 MOCK_METHOD4(drawElements,
879 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
882 TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
883 scoped_ptr<NoClearRootRenderPassMockContext> mock_context_owned(
884 new NoClearRootRenderPassMockContext);
885 NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get();
887 FakeOutputSurfaceClient output_surface_client;
888 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
889 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
890 CHECK(output_surface->BindToClient(&output_surface_client));
892 scoped_ptr<ResourceProvider> resource_provider(
893 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
895 LayerTreeSettings settings;
896 settings.should_clear_root_render_pass = false;
898 FakeRendererClient renderer_client;
899 FakeRendererGL renderer(&renderer_client,
900 &settings,
901 output_surface.get(),
902 resource_provider.get());
904 gfx::Rect viewport_rect(10, 10);
906 RenderPass::Id root_pass_id(1, 0);
907 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
908 root_pass_id,
909 viewport_rect,
910 gfx::Transform());
911 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
913 RenderPass::Id child_pass_id(2, 0);
914 TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_,
915 child_pass_id,
916 viewport_rect,
917 gfx::Transform());
918 AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
920 AddRenderPassQuad(root_pass, child_pass);
922 #ifdef NDEBUG
923 GLint clear_bits = GL_COLOR_BUFFER_BIT;
924 #else
925 GLint clear_bits = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
926 #endif
928 // First render pass is not the root one, clearing should happen.
929 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(AtLeast(1));
931 Expectation first_render_pass =
932 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
934 // The second render pass is the root one, clearing should be prevented.
935 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(0).After(
936 first_render_pass);
938 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber()).After(
939 first_render_pass);
941 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
942 renderer.DrawFrame(&render_passes_in_draw_order_,
943 NULL,
944 1.f,
945 viewport_rect,
946 viewport_rect,
947 true,
948 false);
950 // In multiple render passes all but the root pass should clear the
951 // framebuffer.
952 Mock::VerifyAndClearExpectations(&mock_context);
955 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
956 public:
957 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
959 virtual void clear(GLbitfield) OVERRIDE { EXPECT_FALSE(scissor_enabled_); }
961 virtual void enable(GLenum cap) OVERRIDE {
962 if (cap == GL_SCISSOR_TEST)
963 scissor_enabled_ = true;
966 virtual void disable(GLenum cap) OVERRIDE {
967 if (cap == GL_SCISSOR_TEST)
968 scissor_enabled_ = false;
971 private:
972 bool scissor_enabled_;
975 TEST_F(GLRendererTest, ScissorTestWhenClearing) {
976 scoped_ptr<ScissorTestOnClearCheckingContext> context_owned(
977 new ScissorTestOnClearCheckingContext);
979 FakeOutputSurfaceClient output_surface_client;
980 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
981 context_owned.PassAs<TestWebGraphicsContext3D>()));
982 CHECK(output_surface->BindToClient(&output_surface_client));
984 scoped_ptr<ResourceProvider> resource_provider(
985 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
987 LayerTreeSettings settings;
988 FakeRendererClient renderer_client;
989 FakeRendererGL renderer(&renderer_client,
990 &settings,
991 output_surface.get(),
992 resource_provider.get());
993 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
995 gfx::Rect viewport_rect(1, 1);
997 gfx::Rect grand_child_rect(25, 25);
998 RenderPass::Id grand_child_pass_id(3, 0);
999 TestRenderPass* grand_child_pass =
1000 AddRenderPass(&render_passes_in_draw_order_,
1001 grand_child_pass_id,
1002 grand_child_rect,
1003 gfx::Transform());
1004 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1006 gfx::Rect child_rect(50, 50);
1007 RenderPass::Id child_pass_id(2, 0);
1008 TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_,
1009 child_pass_id,
1010 child_rect,
1011 gfx::Transform());
1012 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1014 RenderPass::Id root_pass_id(1, 0);
1015 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1016 root_pass_id,
1017 viewport_rect,
1018 gfx::Transform());
1019 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1021 AddRenderPassQuad(root_pass, child_pass);
1022 AddRenderPassQuad(child_pass, grand_child_pass);
1024 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1025 renderer.DrawFrame(&render_passes_in_draw_order_,
1026 NULL,
1027 1.f,
1028 viewport_rect,
1029 viewport_rect,
1030 true,
1031 false);
1034 class DiscardCheckingContext : public TestWebGraphicsContext3D {
1035 public:
1036 DiscardCheckingContext() : discarded_(0) {
1037 set_have_post_sub_buffer(true);
1038 set_have_discard_framebuffer(true);
1041 virtual void discardFramebufferEXT(GLenum target,
1042 GLsizei numAttachments,
1043 const GLenum* attachments) OVERRIDE {
1044 ++discarded_;
1047 int discarded() const { return discarded_; }
1048 void reset() { discarded_ = 0; }
1050 private:
1051 int discarded_;
1054 class NonReshapableOutputSurface : public FakeOutputSurface {
1055 public:
1056 explicit NonReshapableOutputSurface(
1057 scoped_ptr<TestWebGraphicsContext3D> context3d)
1058 : FakeOutputSurface(TestContextProvider::Create(context3d.Pass()),
1059 false) {
1060 surface_size_ = gfx::Size(500, 500);
1062 virtual void Reshape(const gfx::Size& size, float scale_factor) OVERRIDE {}
1063 void set_fixed_size(const gfx::Size& size) { surface_size_ = size; }
1066 TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
1067 scoped_ptr<DiscardCheckingContext> context_owned(new DiscardCheckingContext);
1068 DiscardCheckingContext* context = context_owned.get();
1070 FakeOutputSurfaceClient output_surface_client;
1071 scoped_ptr<NonReshapableOutputSurface> output_surface(
1072 new NonReshapableOutputSurface(
1073 context_owned.PassAs<TestWebGraphicsContext3D>()));
1074 CHECK(output_surface->BindToClient(&output_surface_client));
1075 output_surface->set_fixed_size(gfx::Size(100, 100));
1077 scoped_ptr<ResourceProvider> resource_provider(
1078 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
1080 LayerTreeSettings settings;
1081 settings.partial_swap_enabled = true;
1082 FakeRendererClient renderer_client;
1083 FakeRendererGL renderer(&renderer_client,
1084 &settings,
1085 output_surface.get(),
1086 resource_provider.get());
1087 EXPECT_TRUE(renderer.Capabilities().using_partial_swap);
1089 gfx::Rect viewport_rect(100, 100);
1090 gfx::Rect clip_rect(100, 100);
1093 // Partial frame, should not discard.
1094 RenderPass::Id root_pass_id(1, 0);
1095 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1096 root_pass_id,
1097 viewport_rect,
1098 gfx::Transform());
1099 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1100 root_pass->damage_rect = gfx::RectF(2.f, 2.f, 3.f, 3.f);
1102 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1103 renderer.DrawFrame(&render_passes_in_draw_order_,
1104 NULL,
1105 1.f,
1106 viewport_rect,
1107 clip_rect,
1108 true,
1109 false);
1110 EXPECT_EQ(0, context->discarded());
1111 context->reset();
1114 // Full frame, should discard.
1115 RenderPass::Id root_pass_id(1, 0);
1116 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1117 root_pass_id,
1118 viewport_rect,
1119 gfx::Transform());
1120 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1121 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1123 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1124 renderer.DrawFrame(&render_passes_in_draw_order_,
1125 NULL,
1126 1.f,
1127 viewport_rect,
1128 clip_rect,
1129 true,
1130 false);
1131 EXPECT_EQ(1, context->discarded());
1132 context->reset();
1135 // Partial frame, disallow partial swap, should discard.
1136 RenderPass::Id root_pass_id(1, 0);
1137 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1138 root_pass_id,
1139 viewport_rect,
1140 gfx::Transform());
1141 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1142 root_pass->damage_rect = gfx::RectF(2.f, 2.f, 3.f, 3.f);
1144 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1145 renderer.DrawFrame(&render_passes_in_draw_order_,
1146 NULL,
1147 1.f,
1148 viewport_rect,
1149 clip_rect,
1150 false,
1151 false);
1152 EXPECT_EQ(1, context->discarded());
1153 context->reset();
1156 // Full frame, external scissor is set, should not discard.
1157 output_surface->set_has_external_stencil_test(true);
1158 RenderPass::Id root_pass_id(1, 0);
1159 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1160 root_pass_id,
1161 viewport_rect,
1162 gfx::Transform());
1163 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1164 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1165 root_pass->has_transparent_background = false;
1167 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1168 renderer.DrawFrame(&render_passes_in_draw_order_,
1169 NULL,
1170 1.f,
1171 viewport_rect,
1172 clip_rect,
1173 true,
1174 false);
1175 EXPECT_EQ(0, context->discarded());
1176 context->reset();
1177 output_surface->set_has_external_stencil_test(false);
1180 // Full frame, clipped, should not discard.
1181 clip_rect = gfx::Rect(10, 10, 10, 10);
1182 RenderPass::Id root_pass_id(1, 0);
1183 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1184 root_pass_id,
1185 viewport_rect,
1186 gfx::Transform());
1187 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1188 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1190 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1191 renderer.DrawFrame(&render_passes_in_draw_order_,
1192 NULL,
1193 1.f,
1194 viewport_rect,
1195 clip_rect,
1196 true,
1197 false);
1198 EXPECT_EQ(0, context->discarded());
1199 context->reset();
1202 // Full frame, doesn't cover the surface, should not discard.
1203 viewport_rect = gfx::Rect(10, 10, 10, 10);
1204 RenderPass::Id root_pass_id(1, 0);
1205 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1206 root_pass_id,
1207 viewport_rect,
1208 gfx::Transform());
1209 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1210 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1212 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1213 renderer.DrawFrame(&render_passes_in_draw_order_,
1214 NULL,
1215 1.f,
1216 viewport_rect,
1217 clip_rect,
1218 true,
1219 false);
1220 EXPECT_EQ(0, context->discarded());
1221 context->reset();
1224 // Full frame, doesn't cover the surface (no offset), should not discard.
1225 clip_rect = gfx::Rect(100, 100);
1226 viewport_rect = gfx::Rect(50, 50);
1227 RenderPass::Id root_pass_id(1, 0);
1228 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1229 root_pass_id,
1230 viewport_rect,
1231 gfx::Transform());
1232 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1233 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1235 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1236 renderer.DrawFrame(&render_passes_in_draw_order_,
1237 NULL,
1238 1.f,
1239 viewport_rect,
1240 clip_rect,
1241 true,
1242 false);
1243 EXPECT_EQ(0, context->discarded());
1244 context->reset();
1248 class FlippedScissorAndViewportContext : public TestWebGraphicsContext3D {
1249 public:
1250 FlippedScissorAndViewportContext()
1251 : did_call_viewport_(false), did_call_scissor_(false) {}
1252 virtual ~FlippedScissorAndViewportContext() {
1253 EXPECT_TRUE(did_call_viewport_);
1254 EXPECT_TRUE(did_call_scissor_);
1257 virtual void viewport(GLint x, GLint y, GLsizei width, GLsizei height)
1258 OVERRIDE {
1259 EXPECT_EQ(10, x);
1260 EXPECT_EQ(390, y);
1261 EXPECT_EQ(100, width);
1262 EXPECT_EQ(100, height);
1263 did_call_viewport_ = true;
1266 virtual void scissor(GLint x, GLint y, GLsizei width, GLsizei height)
1267 OVERRIDE {
1268 EXPECT_EQ(30, x);
1269 EXPECT_EQ(450, y);
1270 EXPECT_EQ(20, width);
1271 EXPECT_EQ(20, height);
1272 did_call_scissor_ = true;
1275 private:
1276 bool did_call_viewport_;
1277 bool did_call_scissor_;
1280 TEST_F(GLRendererTest, ScissorAndViewportWithinNonreshapableSurface) {
1281 // In Android WebView, the OutputSurface is unable to respect reshape() calls
1282 // and maintains a fixed size. This test verifies that glViewport and
1283 // glScissor's Y coordinate is flipped correctly in this environment, and that
1284 // the glViewport can be at a nonzero origin within the surface.
1285 scoped_ptr<FlippedScissorAndViewportContext> context_owned(
1286 new FlippedScissorAndViewportContext);
1288 FakeOutputSurfaceClient output_surface_client;
1289 scoped_ptr<OutputSurface> output_surface(new NonReshapableOutputSurface(
1290 context_owned.PassAs<TestWebGraphicsContext3D>()));
1291 CHECK(output_surface->BindToClient(&output_surface_client));
1293 scoped_ptr<ResourceProvider> resource_provider(
1294 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
1296 LayerTreeSettings settings;
1297 FakeRendererClient renderer_client;
1298 FakeRendererGL renderer(&renderer_client,
1299 &settings,
1300 output_surface.get(),
1301 resource_provider.get());
1302 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1304 gfx::Rect device_viewport_rect(10, 10, 100, 100);
1305 gfx::Rect viewport_rect(device_viewport_rect.size());
1306 gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
1308 RenderPass::Id root_pass_id(1, 0);
1309 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1310 root_pass_id,
1311 viewport_rect,
1312 gfx::Transform());
1313 AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
1315 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1316 renderer.DrawFrame(&render_passes_in_draw_order_,
1317 NULL,
1318 1.f,
1319 device_viewport_rect,
1320 device_viewport_rect,
1321 true,
1322 false);
1325 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
1326 gfx::Rect viewport_rect(1, 1);
1328 gfx::Rect child_rect(50, 50);
1329 RenderPass::Id child_pass_id(2, 0);
1330 TestRenderPass* child_pass;
1332 RenderPass::Id root_pass_id(1, 0);
1333 TestRenderPass* root_pass;
1335 ResourceProvider::ResourceId mask = resource_provider_->CreateResource(
1336 gfx::Size(20, 12),
1337 GL_CLAMP_TO_EDGE,
1338 ResourceProvider::TextureUsageAny,
1339 resource_provider_->best_texture_format());
1340 resource_provider_->AllocateForTesting(mask);
1342 SkScalar matrix[20];
1343 float amount = 0.5f;
1344 matrix[0] = 0.213f + 0.787f * amount;
1345 matrix[1] = 0.715f - 0.715f * amount;
1346 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1347 matrix[3] = matrix[4] = 0;
1348 matrix[5] = 0.213f - 0.213f * amount;
1349 matrix[6] = 0.715f + 0.285f * amount;
1350 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1351 matrix[8] = matrix[9] = 0;
1352 matrix[10] = 0.213f - 0.213f * amount;
1353 matrix[11] = 0.715f - 0.715f * amount;
1354 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1355 matrix[13] = matrix[14] = 0;
1356 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1357 matrix[18] = 1;
1358 skia::RefPtr<SkColorFilter> color_filter(
1359 skia::AdoptRef(new SkColorMatrixFilter(matrix)));
1360 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
1361 SkColorFilterImageFilter::Create(color_filter.get(), NULL));
1362 FilterOperations filters;
1363 filters.Append(FilterOperation::CreateReferenceFilter(filter));
1365 gfx::Transform transform_causing_aa;
1366 transform_causing_aa.Rotate(20.0);
1368 // RenderPassProgram
1369 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1370 child_pass_id,
1371 child_rect,
1372 gfx::Transform());
1374 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1375 root_pass_id,
1376 viewport_rect,
1377 gfx::Transform());
1379 AddRenderPassQuad(
1380 root_pass, child_pass, 0, FilterOperations(), gfx::Transform());
1382 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1383 renderer_->DrawFrame(&render_passes_in_draw_order_,
1384 NULL,
1385 1.f,
1386 viewport_rect,
1387 viewport_rect,
1388 true,
1389 false);
1390 TestRenderPassProgram(TexCoordPrecisionMedium);
1392 // RenderPassColorMatrixProgram
1393 render_passes_in_draw_order_.clear();
1395 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1396 child_pass_id,
1397 child_rect,
1398 transform_causing_aa);
1400 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1401 root_pass_id,
1402 viewport_rect,
1403 gfx::Transform());
1405 AddRenderPassQuad(root_pass, child_pass, 0, filters, gfx::Transform());
1407 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1408 renderer_->DrawFrame(&render_passes_in_draw_order_,
1409 NULL,
1410 1.f,
1411 viewport_rect,
1412 viewport_rect,
1413 true,
1414 false);
1415 TestRenderPassColorMatrixProgram(TexCoordPrecisionMedium);
1417 // RenderPassMaskProgram
1418 render_passes_in_draw_order_.clear();
1420 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1421 child_pass_id,
1422 child_rect,
1423 gfx::Transform());
1425 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1426 root_pass_id,
1427 viewport_rect,
1428 gfx::Transform());
1430 AddRenderPassQuad(
1431 root_pass, child_pass, mask, FilterOperations(), gfx::Transform());
1433 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1434 renderer_->DrawFrame(&render_passes_in_draw_order_,
1435 NULL,
1436 1.f,
1437 viewport_rect,
1438 viewport_rect,
1439 true,
1440 false);
1441 TestRenderPassMaskProgram(TexCoordPrecisionMedium);
1443 // RenderPassMaskColorMatrixProgram
1444 render_passes_in_draw_order_.clear();
1446 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1447 child_pass_id,
1448 child_rect,
1449 gfx::Transform());
1451 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1452 root_pass_id,
1453 viewport_rect,
1454 gfx::Transform());
1456 AddRenderPassQuad(root_pass, child_pass, mask, filters, gfx::Transform());
1458 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1459 renderer_->DrawFrame(&render_passes_in_draw_order_,
1460 NULL,
1461 1.f,
1462 viewport_rect,
1463 viewport_rect,
1464 true,
1465 false);
1466 TestRenderPassMaskColorMatrixProgram(TexCoordPrecisionMedium);
1468 // RenderPassProgramAA
1469 render_passes_in_draw_order_.clear();
1471 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1472 child_pass_id,
1473 child_rect,
1474 transform_causing_aa);
1476 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1477 root_pass_id,
1478 viewport_rect,
1479 gfx::Transform());
1481 AddRenderPassQuad(
1482 root_pass, child_pass, 0, FilterOperations(), transform_causing_aa);
1484 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1485 renderer_->DrawFrame(&render_passes_in_draw_order_,
1486 NULL,
1487 1.f,
1488 viewport_rect,
1489 viewport_rect,
1490 true,
1491 false);
1492 TestRenderPassProgramAA(TexCoordPrecisionMedium);
1494 // RenderPassColorMatrixProgramAA
1495 render_passes_in_draw_order_.clear();
1497 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1498 child_pass_id,
1499 child_rect,
1500 transform_causing_aa);
1502 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1503 root_pass_id,
1504 viewport_rect,
1505 gfx::Transform());
1507 AddRenderPassQuad(root_pass, child_pass, 0, filters, transform_causing_aa);
1509 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1510 renderer_->DrawFrame(&render_passes_in_draw_order_,
1511 NULL,
1512 1.f,
1513 viewport_rect,
1514 viewport_rect,
1515 true,
1516 false);
1517 TestRenderPassColorMatrixProgramAA(TexCoordPrecisionMedium);
1519 // RenderPassMaskProgramAA
1520 render_passes_in_draw_order_.clear();
1522 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1523 child_pass_id,
1524 child_rect,
1525 transform_causing_aa);
1527 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1528 root_pass_id,
1529 viewport_rect,
1530 gfx::Transform());
1532 AddRenderPassQuad(
1533 root_pass, child_pass, mask, FilterOperations(), transform_causing_aa);
1535 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1536 renderer_->DrawFrame(&render_passes_in_draw_order_,
1537 NULL,
1538 1.f,
1539 viewport_rect,
1540 viewport_rect,
1541 true,
1542 false);
1543 TestRenderPassMaskProgramAA(TexCoordPrecisionMedium);
1545 // RenderPassMaskColorMatrixProgramAA
1546 render_passes_in_draw_order_.clear();
1548 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1549 child_pass_id,
1550 child_rect,
1551 transform_causing_aa);
1553 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1554 root_pass_id,
1555 viewport_rect,
1556 transform_causing_aa);
1558 AddRenderPassQuad(root_pass, child_pass, mask, filters, transform_causing_aa);
1560 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1561 renderer_->DrawFrame(&render_passes_in_draw_order_,
1562 NULL,
1563 1.f,
1564 viewport_rect,
1565 viewport_rect,
1566 true,
1567 false);
1568 TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecisionMedium);
1571 // At this time, the AA code path cannot be taken if the surface's rect would
1572 // project incorrectly by the given transform, because of w<0 clipping.
1573 TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
1574 gfx::Rect child_rect(50, 50);
1575 RenderPass::Id child_pass_id(2, 0);
1576 TestRenderPass* child_pass;
1578 gfx::Rect viewport_rect(1, 1);
1579 RenderPass::Id root_pass_id(1, 0);
1580 TestRenderPass* root_pass;
1582 gfx::Transform transform_preventing_aa;
1583 transform_preventing_aa.ApplyPerspectiveDepth(40.0);
1584 transform_preventing_aa.RotateAboutYAxis(-20.0);
1585 transform_preventing_aa.Scale(30.0, 1.0);
1587 // Verify that the test transform and test rect actually do cause the clipped
1588 // flag to trigger. Otherwise we are not testing the intended scenario.
1589 bool clipped = false;
1590 MathUtil::MapQuad(transform_preventing_aa, gfx::QuadF(child_rect), &clipped);
1591 ASSERT_TRUE(clipped);
1593 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1594 child_pass_id,
1595 child_rect,
1596 transform_preventing_aa);
1598 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1599 root_pass_id,
1600 viewport_rect,
1601 gfx::Transform());
1603 AddRenderPassQuad(
1604 root_pass, child_pass, 0, FilterOperations(), transform_preventing_aa);
1606 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1607 renderer_->DrawFrame(&render_passes_in_draw_order_,
1608 NULL,
1609 1.f,
1610 viewport_rect,
1611 viewport_rect,
1612 true,
1613 false);
1615 // If use_aa incorrectly ignores clipping, it will use the
1616 // RenderPassProgramAA shader instead of the RenderPassProgram.
1617 TestRenderPassProgram(TexCoordPrecisionMedium);
1620 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
1621 gfx::Rect viewport_rect(1, 1);
1622 RenderPass::Id root_pass_id(1, 0);
1623 TestRenderPass* root_pass;
1625 gfx::Transform pixel_aligned_transform_causing_aa;
1626 pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
1627 pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f);
1629 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1630 root_pass_id,
1631 viewport_rect,
1632 gfx::Transform());
1633 AddTransformedQuad(root_pass,
1634 viewport_rect,
1635 SK_ColorYELLOW,
1636 pixel_aligned_transform_causing_aa);
1638 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1639 renderer_->DrawFrame(&render_passes_in_draw_order_,
1640 NULL,
1641 1.f,
1642 viewport_rect,
1643 viewport_rect,
1644 true,
1645 false);
1647 TestSolidColorProgramAA();
1650 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
1651 public:
1652 OutputSurfaceMockContext() { test_capabilities_.gpu.post_sub_buffer = true; }
1654 // Specifically override methods even if they are unused (used in conjunction
1655 // with StrictMock). We need to make sure that GLRenderer does not issue
1656 // framebuffer-related GLuint calls directly. Instead these are supposed to go
1657 // through the OutputSurface abstraction.
1658 MOCK_METHOD2(bindFramebuffer, void(GLenum target, GLuint framebuffer));
1659 MOCK_METHOD3(reshapeWithScaleFactor,
1660 void(int width, int height, float scale_factor));
1661 MOCK_METHOD4(drawElements,
1662 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
1665 class MockOutputSurface : public OutputSurface {
1666 public:
1667 MockOutputSurface()
1668 : OutputSurface(
1669 TestContextProvider::Create(scoped_ptr<TestWebGraphicsContext3D>(
1670 new StrictMock<OutputSurfaceMockContext>))) {
1671 surface_size_ = gfx::Size(100, 100);
1673 virtual ~MockOutputSurface() {}
1675 MOCK_METHOD0(EnsureBackbuffer, void());
1676 MOCK_METHOD0(DiscardBackbuffer, void());
1677 MOCK_METHOD2(Reshape, void(const gfx::Size& size, float scale_factor));
1678 MOCK_METHOD0(BindFramebuffer, void());
1679 MOCK_METHOD1(SwapBuffers, void(CompositorFrame* frame));
1682 class MockOutputSurfaceTest : public GLRendererTest {
1683 protected:
1684 virtual void SetUp() {
1685 FakeOutputSurfaceClient output_surface_client_;
1686 CHECK(output_surface_.BindToClient(&output_surface_client_));
1688 resource_provider_ =
1689 ResourceProvider::Create(&output_surface_, NULL, 0, false, 1).Pass();
1691 renderer_.reset(new FakeRendererGL(&renderer_client_,
1692 &settings_,
1693 &output_surface_,
1694 resource_provider_.get()));
1697 void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
1699 void DrawFrame(float device_scale_factor,
1700 const gfx::Rect& device_viewport_rect) {
1701 RenderPass::Id render_pass_id(1, 0);
1702 TestRenderPass* render_pass = AddRenderPass(&render_passes_in_draw_order_,
1703 render_pass_id,
1704 device_viewport_rect,
1705 gfx::Transform());
1706 AddQuad(render_pass, device_viewport_rect, SK_ColorGREEN);
1708 EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
1710 EXPECT_CALL(output_surface_,
1711 Reshape(device_viewport_rect.size(), device_scale_factor))
1712 .Times(1);
1714 EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
1716 EXPECT_CALL(*Context(), drawElements(_, _, _, _)).Times(1);
1718 renderer_->DecideRenderPassAllocationsForFrame(
1719 render_passes_in_draw_order_);
1720 renderer_->DrawFrame(&render_passes_in_draw_order_,
1721 NULL,
1722 device_scale_factor,
1723 device_viewport_rect,
1724 device_viewport_rect,
1725 true,
1726 false);
1729 OutputSurfaceMockContext* Context() {
1730 return static_cast<OutputSurfaceMockContext*>(
1731 static_cast<TestContextProvider*>(
1732 output_surface_.context_provider().get())->TestContext3d());
1735 LayerTreeSettings settings_;
1736 FakeOutputSurfaceClient output_surface_client_;
1737 StrictMock<MockOutputSurface> output_surface_;
1738 scoped_ptr<ResourceProvider> resource_provider_;
1739 FakeRendererClient renderer_client_;
1740 scoped_ptr<FakeRendererGL> renderer_;
1743 TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap) {
1744 gfx::Rect device_viewport_rect(1, 1);
1745 DrawFrame(1.f, device_viewport_rect);
1747 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1748 renderer_->SwapBuffers(CompositorFrameMetadata());
1751 TEST_F(MockOutputSurfaceTest, DrawFrameAndResizeAndSwap) {
1752 gfx::Rect device_viewport_rect(1, 1);
1754 DrawFrame(1.f, device_viewport_rect);
1755 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1756 renderer_->SwapBuffers(CompositorFrameMetadata());
1758 device_viewport_rect = gfx::Rect(2, 2);
1760 DrawFrame(2.f, device_viewport_rect);
1761 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1762 renderer_->SwapBuffers(CompositorFrameMetadata());
1764 DrawFrame(2.f, device_viewport_rect);
1765 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1766 renderer_->SwapBuffers(CompositorFrameMetadata());
1768 device_viewport_rect = gfx::Rect(1, 1);
1770 DrawFrame(1.f, device_viewport_rect);
1771 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1772 renderer_->SwapBuffers(CompositorFrameMetadata());
1775 class GLRendererTestSyncPoint : public GLRendererPixelTest {
1776 protected:
1777 static void SyncPointCallback(int* callback_count) {
1778 ++(*callback_count);
1779 base::MessageLoop::current()->QuitWhenIdle();
1782 static void OtherCallback(int* callback_count) {
1783 ++(*callback_count);
1784 base::MessageLoop::current()->QuitWhenIdle();
1788 #if !defined(OS_ANDROID)
1789 TEST_F(GLRendererTestSyncPoint, SignalSyncPointOnLostContext) {
1790 int sync_point_callback_count = 0;
1791 int other_callback_count = 0;
1792 gpu::gles2::GLES2Interface* gl =
1793 output_surface_->context_provider()->ContextGL();
1794 gpu::ContextSupport* context_support =
1795 output_surface_->context_provider()->ContextSupport();
1797 uint32 sync_point = gl->InsertSyncPointCHROMIUM();
1799 gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
1800 GL_INNOCENT_CONTEXT_RESET_ARB);
1802 context_support->SignalSyncPoint(
1803 sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count));
1804 EXPECT_EQ(0, sync_point_callback_count);
1805 EXPECT_EQ(0, other_callback_count);
1807 // Make the sync point happen.
1808 gl->Finish();
1809 // Post a task after the sync point.
1810 base::MessageLoop::current()->PostTask(
1811 FROM_HERE, base::Bind(&OtherCallback, &other_callback_count));
1813 base::MessageLoop::current()->Run();
1815 // The sync point shouldn't have happened since the context was lost.
1816 EXPECT_EQ(0, sync_point_callback_count);
1817 EXPECT_EQ(1, other_callback_count);
1820 TEST_F(GLRendererTestSyncPoint, SignalSyncPoint) {
1821 int sync_point_callback_count = 0;
1822 int other_callback_count = 0;
1824 gpu::gles2::GLES2Interface* gl =
1825 output_surface_->context_provider()->ContextGL();
1826 gpu::ContextSupport* context_support =
1827 output_surface_->context_provider()->ContextSupport();
1829 uint32 sync_point = gl->InsertSyncPointCHROMIUM();
1831 context_support->SignalSyncPoint(
1832 sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count));
1833 EXPECT_EQ(0, sync_point_callback_count);
1834 EXPECT_EQ(0, other_callback_count);
1836 // Make the sync point happen.
1837 gl->Finish();
1838 // Post a task after the sync point.
1839 base::MessageLoop::current()->PostTask(
1840 FROM_HERE, base::Bind(&OtherCallback, &other_callback_count));
1842 base::MessageLoop::current()->Run();
1844 // The sync point should have happened.
1845 EXPECT_EQ(1, sync_point_callback_count);
1846 EXPECT_EQ(1, other_callback_count);
1848 #endif // OS_ANDROID
1850 } // namespace
1851 } // namespace cc