NativeViewHost should query its native view for the current cursor
[chromium-blink-merge.git] / cc / output / gl_renderer_unittest.cc
blobd5f848cd2039e3a24c2726a68c8ae19c1f218f36
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 false);
339 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
341 SwapBuffers();
342 EXPECT_EQ(1u, output_surface_->num_sent_frames());
345 TEST_F(GLRendererWithDefaultHarnessTest,
346 FramebufferDiscardedAfterReadbackWhenNotVisible) {
347 gfx::Rect viewport_rect(1, 1);
348 renderer_->SetVisible(false);
349 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
350 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
352 AddRenderPass(&render_passes_in_draw_order_,
353 RenderPass::Id(1, 0),
354 viewport_rect,
355 gfx::Transform());
357 char pixels[4];
358 renderer_->DrawFrame(&render_passes_in_draw_order_,
359 NULL,
360 1.f,
361 viewport_rect,
362 viewport_rect,
363 false);
364 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
366 renderer_->GetFramebufferPixels(pixels, gfx::Rect(0, 0, 1, 1));
367 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
368 EXPECT_EQ(2, renderer_client_.set_full_root_layer_damage_count());
371 TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) {
372 gfx::Rect viewport_rect(1, 1);
373 EXPECT_FALSE(renderer_->stencil_enabled());
375 output_surface_->set_has_external_stencil_test(true);
377 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
378 RenderPass::Id(1, 0),
379 viewport_rect,
380 gfx::Transform());
381 root_pass->has_transparent_background = false;
383 renderer_->DrawFrame(&render_passes_in_draw_order_,
384 NULL,
385 1.f,
386 viewport_rect,
387 viewport_rect,
388 false);
389 EXPECT_TRUE(renderer_->stencil_enabled());
392 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
393 public:
394 ForbidSynchronousCallContext() {}
396 virtual void getAttachedShaders(GLuint program,
397 GLsizei max_count,
398 GLsizei* count,
399 GLuint* shaders) OVERRIDE {
400 ADD_FAILURE();
402 virtual GLint getAttribLocation(GLuint program, const GLchar* name) OVERRIDE {
403 ADD_FAILURE();
404 return 0;
406 virtual void getBooleanv(GLenum pname, GLboolean* value) OVERRIDE {
407 ADD_FAILURE();
409 virtual void getBufferParameteriv(GLenum target,
410 GLenum pname,
411 GLint* value) OVERRIDE {
412 ADD_FAILURE();
414 virtual GLenum getError() OVERRIDE {
415 ADD_FAILURE();
416 return GL_NO_ERROR;
418 virtual void getFloatv(GLenum pname, GLfloat* value) OVERRIDE {
419 ADD_FAILURE();
421 virtual void getFramebufferAttachmentParameteriv(GLenum target,
422 GLenum attachment,
423 GLenum pname,
424 GLint* value) OVERRIDE {
425 ADD_FAILURE();
427 virtual void getIntegerv(GLenum pname, GLint* value) OVERRIDE {
428 if (pname == GL_MAX_TEXTURE_SIZE) {
429 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
430 *value = 1024;
431 } else {
432 ADD_FAILURE();
436 // We allow querying the shader compilation and program link status in debug
437 // mode, but not release.
438 virtual void getProgramiv(GLuint program,
439 GLenum pname,
440 GLint* value) OVERRIDE {
441 #ifndef NDEBUG
442 *value = 1;
443 #else
444 ADD_FAILURE();
445 #endif
448 virtual void getShaderiv(GLuint shader, GLenum pname, GLint* value) OVERRIDE {
449 #ifndef NDEBUG
450 *value = 1;
451 #else
452 ADD_FAILURE();
453 #endif
456 virtual void getRenderbufferParameteriv(GLenum target,
457 GLenum pname,
458 GLint* value) OVERRIDE {
459 ADD_FAILURE();
462 virtual void getShaderPrecisionFormat(GLenum shadertype,
463 GLenum precisiontype,
464 GLint* range,
465 GLint* precision) OVERRIDE {
466 ADD_FAILURE();
468 virtual void getTexParameterfv(GLenum target,
469 GLenum pname,
470 GLfloat* value) OVERRIDE {
471 ADD_FAILURE();
473 virtual void getTexParameteriv(GLenum target,
474 GLenum pname,
475 GLint* value) OVERRIDE {
476 ADD_FAILURE();
478 virtual void getUniformfv(GLuint program,
479 GLint location,
480 GLfloat* value) OVERRIDE {
481 ADD_FAILURE();
483 virtual void getUniformiv(GLuint program,
484 GLint location,
485 GLint* value) OVERRIDE {
486 ADD_FAILURE();
488 virtual GLint getUniformLocation(GLuint program,
489 const GLchar* name) OVERRIDE {
490 ADD_FAILURE();
491 return 0;
493 virtual void getVertexAttribfv(GLuint index,
494 GLenum pname,
495 GLfloat* value) OVERRIDE {
496 ADD_FAILURE();
498 virtual void getVertexAttribiv(GLuint index,
499 GLenum pname,
500 GLint* value) OVERRIDE {
501 ADD_FAILURE();
503 virtual GLsizeiptr getVertexAttribOffset(GLuint index,
504 GLenum pname) OVERRIDE {
505 ADD_FAILURE();
506 return 0;
509 TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
510 FakeOutputSurfaceClient output_surface_client;
511 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
512 scoped_ptr<TestWebGraphicsContext3D>(new ForbidSynchronousCallContext)));
513 CHECK(output_surface->BindToClient(&output_surface_client));
515 scoped_ptr<ResourceProvider> resource_provider(
516 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
518 LayerTreeSettings settings;
519 FakeRendererClient renderer_client;
520 FakeRendererGL renderer(&renderer_client,
521 &settings,
522 output_surface.get(),
523 resource_provider.get());
526 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
527 public:
528 LoseContextOnFirstGetContext() {}
530 virtual void getProgramiv(GLuint program,
531 GLenum pname,
532 GLint* value) OVERRIDE {
533 context_lost_ = true;
534 *value = 0;
537 virtual void getShaderiv(GLuint shader, GLenum pname, GLint* value) OVERRIDE {
538 context_lost_ = true;
539 *value = 0;
543 TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
544 FakeOutputSurfaceClient output_surface_client;
545 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
546 scoped_ptr<TestWebGraphicsContext3D>(new LoseContextOnFirstGetContext)));
547 CHECK(output_surface->BindToClient(&output_surface_client));
549 scoped_ptr<ResourceProvider> resource_provider(
550 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
552 LayerTreeSettings settings;
553 FakeRendererClient renderer_client;
554 FakeRendererGL renderer(&renderer_client,
555 &settings,
556 output_surface.get(),
557 resource_provider.get());
560 class ClearCountingContext : public TestWebGraphicsContext3D {
561 public:
562 ClearCountingContext() { test_capabilities_.gpu.discard_framebuffer = true; }
564 MOCK_METHOD3(discardFramebufferEXT,
565 void(GLenum target,
566 GLsizei numAttachments,
567 const GLenum* attachments));
568 MOCK_METHOD1(clear, void(GLbitfield mask));
571 TEST_F(GLRendererTest, OpaqueBackground) {
572 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
573 ClearCountingContext* context = context_owned.get();
575 FakeOutputSurfaceClient output_surface_client;
576 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
577 context_owned.PassAs<TestWebGraphicsContext3D>()));
578 CHECK(output_surface->BindToClient(&output_surface_client));
580 scoped_ptr<ResourceProvider> resource_provider(
581 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
583 LayerTreeSettings settings;
584 FakeRendererClient renderer_client;
585 FakeRendererGL renderer(&renderer_client,
586 &settings,
587 output_surface.get(),
588 resource_provider.get());
590 gfx::Rect viewport_rect(1, 1);
591 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
592 RenderPass::Id(1, 0),
593 viewport_rect,
594 gfx::Transform());
595 root_pass->has_transparent_background = false;
597 // On DEBUG builds, render passes with opaque background clear to blue to
598 // easily see regions that were not drawn on the screen.
599 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
600 .With(Args<2, 1>(ElementsAre(GL_COLOR_EXT)))
601 .Times(1);
602 #ifdef NDEBUG
603 EXPECT_CALL(*context, clear(_)).Times(0);
604 #else
605 EXPECT_CALL(*context, clear(_)).Times(1);
606 #endif
607 renderer.DrawFrame(&render_passes_in_draw_order_,
608 NULL,
609 1.f,
610 viewport_rect,
611 viewport_rect,
612 false);
613 Mock::VerifyAndClearExpectations(context);
616 TEST_F(GLRendererTest, TransparentBackground) {
617 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
618 ClearCountingContext* context = context_owned.get();
620 FakeOutputSurfaceClient output_surface_client;
621 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
622 context_owned.PassAs<TestWebGraphicsContext3D>()));
623 CHECK(output_surface->BindToClient(&output_surface_client));
625 scoped_ptr<ResourceProvider> resource_provider(
626 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
628 LayerTreeSettings settings;
629 FakeRendererClient renderer_client;
630 FakeRendererGL renderer(&renderer_client,
631 &settings,
632 output_surface.get(),
633 resource_provider.get());
635 gfx::Rect viewport_rect(1, 1);
636 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
637 RenderPass::Id(1, 0),
638 viewport_rect,
639 gfx::Transform());
640 root_pass->has_transparent_background = true;
642 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1);
643 EXPECT_CALL(*context, clear(_)).Times(1);
644 renderer.DrawFrame(&render_passes_in_draw_order_,
645 NULL,
646 1.f,
647 viewport_rect,
648 viewport_rect,
649 false);
651 Mock::VerifyAndClearExpectations(context);
654 TEST_F(GLRendererTest, OffscreenOutputSurface) {
655 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
656 ClearCountingContext* context = context_owned.get();
658 FakeOutputSurfaceClient output_surface_client;
659 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::CreateOffscreen(
660 context_owned.PassAs<TestWebGraphicsContext3D>()));
661 CHECK(output_surface->BindToClient(&output_surface_client));
663 scoped_ptr<ResourceProvider> resource_provider(
664 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
666 LayerTreeSettings settings;
667 FakeRendererClient renderer_client;
668 FakeRendererGL renderer(&renderer_client,
669 &settings,
670 output_surface.get(),
671 resource_provider.get());
673 gfx::Rect viewport_rect(1, 1);
674 AddRenderPass(&render_passes_in_draw_order_,
675 RenderPass::Id(1, 0),
676 viewport_rect,
677 gfx::Transform());
679 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
680 .With(Args<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0)))
681 .Times(1);
682 EXPECT_CALL(*context, clear(_)).Times(AnyNumber());
683 renderer.DrawFrame(&render_passes_in_draw_order_,
684 NULL,
685 1.f,
686 viewport_rect,
687 viewport_rect,
688 false);
689 Mock::VerifyAndClearExpectations(context);
692 class VisibilityChangeIsLastCallTrackingContext
693 : public TestWebGraphicsContext3D {
694 public:
695 VisibilityChangeIsLastCallTrackingContext()
696 : last_call_was_set_visibility_(false) {}
698 // TestWebGraphicsContext3D methods.
699 virtual void flush() OVERRIDE { last_call_was_set_visibility_ = false; }
700 virtual void deleteTexture(GLuint) OVERRIDE {
701 last_call_was_set_visibility_ = false;
703 virtual void deleteFramebuffer(GLuint) OVERRIDE {
704 last_call_was_set_visibility_ = false;
706 virtual void deleteQueryEXT(GLuint) OVERRIDE {
707 last_call_was_set_visibility_ = false;
709 virtual void deleteRenderbuffer(GLuint) OVERRIDE {
710 last_call_was_set_visibility_ = false;
713 // Methods added for test.
714 void set_last_call_was_visibility(bool visible) {
715 DCHECK(last_call_was_set_visibility_ == false);
716 last_call_was_set_visibility_ = true;
718 bool last_call_was_set_visibility() const {
719 return last_call_was_set_visibility_;
722 private:
723 bool last_call_was_set_visibility_;
726 TEST_F(GLRendererTest, VisibilityChangeIsLastCall) {
727 scoped_ptr<VisibilityChangeIsLastCallTrackingContext> context_owned(
728 new VisibilityChangeIsLastCallTrackingContext);
729 VisibilityChangeIsLastCallTrackingContext* context = context_owned.get();
731 scoped_refptr<TestContextProvider> provider = TestContextProvider::Create(
732 context_owned.PassAs<TestWebGraphicsContext3D>());
734 provider->support()->SetSurfaceVisibleCallback(base::Bind(
735 &VisibilityChangeIsLastCallTrackingContext::set_last_call_was_visibility,
736 base::Unretained(context)));
738 FakeOutputSurfaceClient output_surface_client;
739 scoped_ptr<OutputSurface> output_surface(
740 FakeOutputSurface::Create3d(provider));
741 CHECK(output_surface->BindToClient(&output_surface_client));
743 scoped_ptr<ResourceProvider> resource_provider(
744 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
746 LayerTreeSettings settings;
747 FakeRendererClient renderer_client;
748 FakeRendererGL renderer(&renderer_client,
749 &settings,
750 output_surface.get(),
751 resource_provider.get());
753 gfx::Rect viewport_rect(1, 1);
754 AddRenderPass(&render_passes_in_draw_order_,
755 RenderPass::Id(1, 0),
756 viewport_rect,
757 gfx::Transform());
759 // Ensure that the call to SetSurfaceVisible is the last call issue to the
760 // GPU process, after glFlush is called, and after the RendererClient's
761 // SetManagedMemoryPolicy is called. Plumb this tracking between both the
762 // RenderClient and the Context by giving them both a pointer to a variable on
763 // the stack.
764 renderer.SetVisible(true);
765 renderer.DrawFrame(&render_passes_in_draw_order_,
766 NULL,
767 1.f,
768 viewport_rect,
769 viewport_rect,
770 false);
771 renderer.SetVisible(false);
772 EXPECT_TRUE(context->last_call_was_set_visibility());
775 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
776 public:
777 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {
778 test_capabilities_.gpu.egl_image_external = true;
781 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
782 MOCK_METHOD4(drawElements,
783 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
785 virtual void activeTexture(GLenum texture) {
786 EXPECT_NE(texture, active_texture_);
787 active_texture_ = texture;
790 GLenum active_texture() const { return active_texture_; }
792 private:
793 GLenum active_texture_;
796 TEST_F(GLRendererTest, ActiveTextureState) {
797 scoped_ptr<TextureStateTrackingContext> context_owned(
798 new TextureStateTrackingContext);
799 TextureStateTrackingContext* context = context_owned.get();
801 FakeOutputSurfaceClient output_surface_client;
802 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
803 context_owned.PassAs<TestWebGraphicsContext3D>()));
804 CHECK(output_surface->BindToClient(&output_surface_client));
806 scoped_ptr<ResourceProvider> resource_provider(
807 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
809 LayerTreeSettings settings;
810 FakeRendererClient renderer_client;
811 FakeRendererGL renderer(&renderer_client,
812 &settings,
813 output_surface.get(),
814 resource_provider.get());
816 // During initialization we are allowed to set any texture parameters.
817 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
819 RenderPass::Id id(1, 1);
820 TestRenderPass* root_pass = AddRenderPass(
821 &render_passes_in_draw_order_, id, gfx::Rect(100, 100), gfx::Transform());
822 root_pass->AppendOneOfEveryQuadType(resource_provider.get(),
823 RenderPass::Id(2, 1));
825 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
827 // Set up expected texture filter state transitions that match the quads
828 // created in AppendOneOfEveryQuadType().
829 Mock::VerifyAndClearExpectations(context);
831 InSequence sequence;
833 // yuv_quad is drawn with the default linear filter.
834 EXPECT_CALL(*context, drawElements(_, _, _, _));
836 // tile_quad is drawn with GL_NEAREST because it is not transformed or
837 // scaled.
838 EXPECT_CALL(
839 *context,
840 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
841 EXPECT_CALL(
842 *context,
843 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
844 EXPECT_CALL(*context, drawElements(_, _, _, _));
846 // transformed_tile_quad uses GL_LINEAR.
847 EXPECT_CALL(*context, drawElements(_, _, _, _));
849 // scaled_tile_quad also uses GL_LINEAR.
850 EXPECT_CALL(*context, drawElements(_, _, _, _));
852 // The remaining quads also use GL_LINEAR because nearest neighbor
853 // filtering is currently only used with tile quads.
854 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(6);
857 gfx::Rect viewport_rect(100, 100);
858 renderer.DrawFrame(&render_passes_in_draw_order_,
859 NULL,
860 1.f,
861 viewport_rect,
862 viewport_rect,
863 false);
864 Mock::VerifyAndClearExpectations(context);
867 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
868 public:
869 MOCK_METHOD1(clear, void(GLbitfield mask));
870 MOCK_METHOD4(drawElements,
871 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
874 TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
875 scoped_ptr<NoClearRootRenderPassMockContext> mock_context_owned(
876 new NoClearRootRenderPassMockContext);
877 NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get();
879 FakeOutputSurfaceClient output_surface_client;
880 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
881 mock_context_owned.PassAs<TestWebGraphicsContext3D>()));
882 CHECK(output_surface->BindToClient(&output_surface_client));
884 scoped_ptr<ResourceProvider> resource_provider(
885 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
887 LayerTreeSettings settings;
888 settings.should_clear_root_render_pass = false;
890 FakeRendererClient renderer_client;
891 FakeRendererGL renderer(&renderer_client,
892 &settings,
893 output_surface.get(),
894 resource_provider.get());
896 gfx::Rect viewport_rect(10, 10);
898 RenderPass::Id root_pass_id(1, 0);
899 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
900 root_pass_id,
901 viewport_rect,
902 gfx::Transform());
903 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
905 RenderPass::Id child_pass_id(2, 0);
906 TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_,
907 child_pass_id,
908 viewport_rect,
909 gfx::Transform());
910 AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
912 AddRenderPassQuad(root_pass, child_pass);
914 #ifdef NDEBUG
915 GLint clear_bits = GL_COLOR_BUFFER_BIT;
916 #else
917 GLint clear_bits = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
918 #endif
920 // First render pass is not the root one, clearing should happen.
921 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(AtLeast(1));
923 Expectation first_render_pass =
924 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
926 // The second render pass is the root one, clearing should be prevented.
927 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(0).After(
928 first_render_pass);
930 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber()).After(
931 first_render_pass);
933 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
934 renderer.DrawFrame(&render_passes_in_draw_order_,
935 NULL,
936 1.f,
937 viewport_rect,
938 viewport_rect,
939 false);
941 // In multiple render passes all but the root pass should clear the
942 // framebuffer.
943 Mock::VerifyAndClearExpectations(&mock_context);
946 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
947 public:
948 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
950 virtual void clear(GLbitfield) OVERRIDE { EXPECT_FALSE(scissor_enabled_); }
952 virtual void enable(GLenum cap) OVERRIDE {
953 if (cap == GL_SCISSOR_TEST)
954 scissor_enabled_ = true;
957 virtual void disable(GLenum cap) OVERRIDE {
958 if (cap == GL_SCISSOR_TEST)
959 scissor_enabled_ = false;
962 private:
963 bool scissor_enabled_;
966 TEST_F(GLRendererTest, ScissorTestWhenClearing) {
967 scoped_ptr<ScissorTestOnClearCheckingContext> context_owned(
968 new ScissorTestOnClearCheckingContext);
970 FakeOutputSurfaceClient output_surface_client;
971 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
972 context_owned.PassAs<TestWebGraphicsContext3D>()));
973 CHECK(output_surface->BindToClient(&output_surface_client));
975 scoped_ptr<ResourceProvider> resource_provider(
976 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
978 LayerTreeSettings settings;
979 FakeRendererClient renderer_client;
980 FakeRendererGL renderer(&renderer_client,
981 &settings,
982 output_surface.get(),
983 resource_provider.get());
984 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
986 gfx::Rect viewport_rect(1, 1);
988 gfx::Rect grand_child_rect(25, 25);
989 RenderPass::Id grand_child_pass_id(3, 0);
990 TestRenderPass* grand_child_pass =
991 AddRenderPass(&render_passes_in_draw_order_,
992 grand_child_pass_id,
993 grand_child_rect,
994 gfx::Transform());
995 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
997 gfx::Rect child_rect(50, 50);
998 RenderPass::Id child_pass_id(2, 0);
999 TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_,
1000 child_pass_id,
1001 child_rect,
1002 gfx::Transform());
1003 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1005 RenderPass::Id root_pass_id(1, 0);
1006 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1007 root_pass_id,
1008 viewport_rect,
1009 gfx::Transform());
1010 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1012 AddRenderPassQuad(root_pass, child_pass);
1013 AddRenderPassQuad(child_pass, grand_child_pass);
1015 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1016 renderer.DrawFrame(&render_passes_in_draw_order_,
1017 NULL,
1018 1.f,
1019 viewport_rect,
1020 viewport_rect,
1021 false);
1024 class DiscardCheckingContext : public TestWebGraphicsContext3D {
1025 public:
1026 DiscardCheckingContext() : discarded_(0) {
1027 set_have_post_sub_buffer(true);
1028 set_have_discard_framebuffer(true);
1031 virtual void discardFramebufferEXT(GLenum target,
1032 GLsizei numAttachments,
1033 const GLenum* attachments) OVERRIDE {
1034 ++discarded_;
1037 int discarded() const { return discarded_; }
1038 void reset() { discarded_ = 0; }
1040 private:
1041 int discarded_;
1044 class NonReshapableOutputSurface : public FakeOutputSurface {
1045 public:
1046 explicit NonReshapableOutputSurface(
1047 scoped_ptr<TestWebGraphicsContext3D> context3d)
1048 : FakeOutputSurface(TestContextProvider::Create(context3d.Pass()),
1049 false) {
1050 surface_size_ = gfx::Size(500, 500);
1052 virtual void Reshape(const gfx::Size& size, float scale_factor) OVERRIDE {}
1053 void set_fixed_size(const gfx::Size& size) { surface_size_ = size; }
1056 TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
1057 scoped_ptr<DiscardCheckingContext> context_owned(new DiscardCheckingContext);
1058 DiscardCheckingContext* context = context_owned.get();
1060 FakeOutputSurfaceClient output_surface_client;
1061 scoped_ptr<NonReshapableOutputSurface> output_surface(
1062 new NonReshapableOutputSurface(
1063 context_owned.PassAs<TestWebGraphicsContext3D>()));
1064 CHECK(output_surface->BindToClient(&output_surface_client));
1065 output_surface->set_fixed_size(gfx::Size(100, 100));
1067 scoped_ptr<ResourceProvider> resource_provider(
1068 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
1070 LayerTreeSettings settings;
1071 settings.partial_swap_enabled = true;
1072 FakeRendererClient renderer_client;
1073 FakeRendererGL renderer(&renderer_client,
1074 &settings,
1075 output_surface.get(),
1076 resource_provider.get());
1077 EXPECT_TRUE(renderer.Capabilities().using_partial_swap);
1079 gfx::Rect viewport_rect(100, 100);
1080 gfx::Rect clip_rect(100, 100);
1083 // Partial frame, should not discard.
1084 RenderPass::Id root_pass_id(1, 0);
1085 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1086 root_pass_id,
1087 viewport_rect,
1088 gfx::Transform());
1089 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1090 root_pass->damage_rect = gfx::RectF(2.f, 2.f, 3.f, 3.f);
1092 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1093 renderer.DrawFrame(&render_passes_in_draw_order_,
1094 NULL,
1095 1.f,
1096 viewport_rect,
1097 clip_rect,
1098 false);
1099 EXPECT_EQ(0, context->discarded());
1100 context->reset();
1103 // Full frame, should discard.
1104 RenderPass::Id root_pass_id(1, 0);
1105 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1106 root_pass_id,
1107 viewport_rect,
1108 gfx::Transform());
1109 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1110 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1112 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1113 renderer.DrawFrame(&render_passes_in_draw_order_,
1114 NULL,
1115 1.f,
1116 viewport_rect,
1117 clip_rect,
1118 false);
1119 EXPECT_EQ(1, context->discarded());
1120 context->reset();
1123 // Full frame, external scissor is set, should not discard.
1124 output_surface->set_has_external_stencil_test(true);
1125 RenderPass::Id root_pass_id(1, 0);
1126 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1127 root_pass_id,
1128 viewport_rect,
1129 gfx::Transform());
1130 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1131 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1132 root_pass->has_transparent_background = false;
1134 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1135 renderer.DrawFrame(&render_passes_in_draw_order_,
1136 NULL,
1137 1.f,
1138 viewport_rect,
1139 clip_rect,
1140 false);
1141 EXPECT_EQ(0, context->discarded());
1142 context->reset();
1143 output_surface->set_has_external_stencil_test(false);
1146 // Full frame, clipped, should not discard.
1147 clip_rect = gfx::Rect(10, 10, 10, 10);
1148 RenderPass::Id root_pass_id(1, 0);
1149 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1150 root_pass_id,
1151 viewport_rect,
1152 gfx::Transform());
1153 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1154 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1156 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1157 renderer.DrawFrame(&render_passes_in_draw_order_,
1158 NULL,
1159 1.f,
1160 viewport_rect,
1161 clip_rect,
1162 false);
1163 EXPECT_EQ(0, context->discarded());
1164 context->reset();
1167 // Full frame, doesn't cover the surface, should not discard.
1168 viewport_rect = gfx::Rect(10, 10, 10, 10);
1169 RenderPass::Id root_pass_id(1, 0);
1170 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1171 root_pass_id,
1172 viewport_rect,
1173 gfx::Transform());
1174 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1175 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1177 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1178 renderer.DrawFrame(&render_passes_in_draw_order_,
1179 NULL,
1180 1.f,
1181 viewport_rect,
1182 clip_rect,
1183 false);
1184 EXPECT_EQ(0, context->discarded());
1185 context->reset();
1188 // Full frame, doesn't cover the surface (no offset), should not discard.
1189 clip_rect = gfx::Rect(100, 100);
1190 viewport_rect = gfx::Rect(50, 50);
1191 RenderPass::Id root_pass_id(1, 0);
1192 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1193 root_pass_id,
1194 viewport_rect,
1195 gfx::Transform());
1196 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1197 root_pass->damage_rect = gfx::RectF(root_pass->output_rect);
1199 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1200 renderer.DrawFrame(&render_passes_in_draw_order_,
1201 NULL,
1202 1.f,
1203 viewport_rect,
1204 clip_rect,
1205 false);
1206 EXPECT_EQ(0, context->discarded());
1207 context->reset();
1211 class FlippedScissorAndViewportContext : public TestWebGraphicsContext3D {
1212 public:
1213 FlippedScissorAndViewportContext()
1214 : did_call_viewport_(false), did_call_scissor_(false) {}
1215 virtual ~FlippedScissorAndViewportContext() {
1216 EXPECT_TRUE(did_call_viewport_);
1217 EXPECT_TRUE(did_call_scissor_);
1220 virtual void viewport(GLint x, GLint y, GLsizei width, GLsizei height)
1221 OVERRIDE {
1222 EXPECT_EQ(10, x);
1223 EXPECT_EQ(390, y);
1224 EXPECT_EQ(100, width);
1225 EXPECT_EQ(100, height);
1226 did_call_viewport_ = true;
1229 virtual void scissor(GLint x, GLint y, GLsizei width, GLsizei height)
1230 OVERRIDE {
1231 EXPECT_EQ(30, x);
1232 EXPECT_EQ(450, y);
1233 EXPECT_EQ(20, width);
1234 EXPECT_EQ(20, height);
1235 did_call_scissor_ = true;
1238 private:
1239 bool did_call_viewport_;
1240 bool did_call_scissor_;
1243 TEST_F(GLRendererTest, ScissorAndViewportWithinNonreshapableSurface) {
1244 // In Android WebView, the OutputSurface is unable to respect reshape() calls
1245 // and maintains a fixed size. This test verifies that glViewport and
1246 // glScissor's Y coordinate is flipped correctly in this environment, and that
1247 // the glViewport can be at a nonzero origin within the surface.
1248 scoped_ptr<FlippedScissorAndViewportContext> context_owned(
1249 new FlippedScissorAndViewportContext);
1251 FakeOutputSurfaceClient output_surface_client;
1252 scoped_ptr<OutputSurface> output_surface(new NonReshapableOutputSurface(
1253 context_owned.PassAs<TestWebGraphicsContext3D>()));
1254 CHECK(output_surface->BindToClient(&output_surface_client));
1256 scoped_ptr<ResourceProvider> resource_provider(
1257 ResourceProvider::Create(output_surface.get(), NULL, 0, false, 1));
1259 LayerTreeSettings settings;
1260 FakeRendererClient renderer_client;
1261 FakeRendererGL renderer(&renderer_client,
1262 &settings,
1263 output_surface.get(),
1264 resource_provider.get());
1265 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1267 gfx::Rect device_viewport_rect(10, 10, 100, 100);
1268 gfx::Rect viewport_rect(device_viewport_rect.size());
1269 gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
1271 RenderPass::Id root_pass_id(1, 0);
1272 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1273 root_pass_id,
1274 viewport_rect,
1275 gfx::Transform());
1276 AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
1278 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1279 renderer.DrawFrame(&render_passes_in_draw_order_,
1280 NULL,
1281 1.f,
1282 device_viewport_rect,
1283 device_viewport_rect,
1284 false);
1287 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
1288 gfx::Rect viewport_rect(1, 1);
1290 gfx::Rect child_rect(50, 50);
1291 RenderPass::Id child_pass_id(2, 0);
1292 TestRenderPass* child_pass;
1294 RenderPass::Id root_pass_id(1, 0);
1295 TestRenderPass* root_pass;
1297 ResourceProvider::ResourceId mask = resource_provider_->CreateResource(
1298 gfx::Size(20, 12),
1299 GL_CLAMP_TO_EDGE,
1300 ResourceProvider::TextureUsageAny,
1301 resource_provider_->best_texture_format());
1302 resource_provider_->AllocateForTesting(mask);
1304 SkScalar matrix[20];
1305 float amount = 0.5f;
1306 matrix[0] = 0.213f + 0.787f * amount;
1307 matrix[1] = 0.715f - 0.715f * amount;
1308 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1309 matrix[3] = matrix[4] = 0;
1310 matrix[5] = 0.213f - 0.213f * amount;
1311 matrix[6] = 0.715f + 0.285f * amount;
1312 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1313 matrix[8] = matrix[9] = 0;
1314 matrix[10] = 0.213f - 0.213f * amount;
1315 matrix[11] = 0.715f - 0.715f * amount;
1316 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1317 matrix[13] = matrix[14] = 0;
1318 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1319 matrix[18] = 1;
1320 skia::RefPtr<SkColorFilter> color_filter(
1321 skia::AdoptRef(new SkColorMatrixFilter(matrix)));
1322 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
1323 SkColorFilterImageFilter::Create(color_filter.get(), NULL));
1324 FilterOperations filters;
1325 filters.Append(FilterOperation::CreateReferenceFilter(filter));
1327 gfx::Transform transform_causing_aa;
1328 transform_causing_aa.Rotate(20.0);
1330 // RenderPassProgram
1331 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1332 child_pass_id,
1333 child_rect,
1334 gfx::Transform());
1336 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1337 root_pass_id,
1338 viewport_rect,
1339 gfx::Transform());
1341 AddRenderPassQuad(
1342 root_pass, child_pass, 0, FilterOperations(), gfx::Transform());
1344 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1345 renderer_->DrawFrame(&render_passes_in_draw_order_,
1346 NULL,
1347 1.f,
1348 viewport_rect,
1349 viewport_rect,
1350 false);
1351 TestRenderPassProgram(TexCoordPrecisionMedium);
1353 // RenderPassColorMatrixProgram
1354 render_passes_in_draw_order_.clear();
1356 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1357 child_pass_id,
1358 child_rect,
1359 transform_causing_aa);
1361 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1362 root_pass_id,
1363 viewport_rect,
1364 gfx::Transform());
1366 AddRenderPassQuad(root_pass, child_pass, 0, filters, gfx::Transform());
1368 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1369 renderer_->DrawFrame(&render_passes_in_draw_order_,
1370 NULL,
1371 1.f,
1372 viewport_rect,
1373 viewport_rect,
1374 false);
1375 TestRenderPassColorMatrixProgram(TexCoordPrecisionMedium);
1377 // RenderPassMaskProgram
1378 render_passes_in_draw_order_.clear();
1380 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1381 child_pass_id,
1382 child_rect,
1383 gfx::Transform());
1385 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1386 root_pass_id,
1387 viewport_rect,
1388 gfx::Transform());
1390 AddRenderPassQuad(
1391 root_pass, child_pass, mask, FilterOperations(), gfx::Transform());
1393 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1394 renderer_->DrawFrame(&render_passes_in_draw_order_,
1395 NULL,
1396 1.f,
1397 viewport_rect,
1398 viewport_rect,
1399 false);
1400 TestRenderPassMaskProgram(TexCoordPrecisionMedium);
1402 // RenderPassMaskColorMatrixProgram
1403 render_passes_in_draw_order_.clear();
1405 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1406 child_pass_id,
1407 child_rect,
1408 gfx::Transform());
1410 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1411 root_pass_id,
1412 viewport_rect,
1413 gfx::Transform());
1415 AddRenderPassQuad(root_pass, child_pass, mask, filters, gfx::Transform());
1417 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1418 renderer_->DrawFrame(&render_passes_in_draw_order_,
1419 NULL,
1420 1.f,
1421 viewport_rect,
1422 viewport_rect,
1423 false);
1424 TestRenderPassMaskColorMatrixProgram(TexCoordPrecisionMedium);
1426 // RenderPassProgramAA
1427 render_passes_in_draw_order_.clear();
1429 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1430 child_pass_id,
1431 child_rect,
1432 transform_causing_aa);
1434 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1435 root_pass_id,
1436 viewport_rect,
1437 gfx::Transform());
1439 AddRenderPassQuad(
1440 root_pass, child_pass, 0, FilterOperations(), transform_causing_aa);
1442 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1443 renderer_->DrawFrame(&render_passes_in_draw_order_,
1444 NULL,
1445 1.f,
1446 viewport_rect,
1447 viewport_rect,
1448 false);
1449 TestRenderPassProgramAA(TexCoordPrecisionMedium);
1451 // RenderPassColorMatrixProgramAA
1452 render_passes_in_draw_order_.clear();
1454 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1455 child_pass_id,
1456 child_rect,
1457 transform_causing_aa);
1459 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1460 root_pass_id,
1461 viewport_rect,
1462 gfx::Transform());
1464 AddRenderPassQuad(root_pass, child_pass, 0, filters, transform_causing_aa);
1466 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1467 renderer_->DrawFrame(&render_passes_in_draw_order_,
1468 NULL,
1469 1.f,
1470 viewport_rect,
1471 viewport_rect,
1472 false);
1473 TestRenderPassColorMatrixProgramAA(TexCoordPrecisionMedium);
1475 // RenderPassMaskProgramAA
1476 render_passes_in_draw_order_.clear();
1478 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1479 child_pass_id,
1480 child_rect,
1481 transform_causing_aa);
1483 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1484 root_pass_id,
1485 viewport_rect,
1486 gfx::Transform());
1488 AddRenderPassQuad(
1489 root_pass, child_pass, mask, FilterOperations(), transform_causing_aa);
1491 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1492 renderer_->DrawFrame(&render_passes_in_draw_order_,
1493 NULL,
1494 1.f,
1495 viewport_rect,
1496 viewport_rect,
1497 false);
1498 TestRenderPassMaskProgramAA(TexCoordPrecisionMedium);
1500 // RenderPassMaskColorMatrixProgramAA
1501 render_passes_in_draw_order_.clear();
1503 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1504 child_pass_id,
1505 child_rect,
1506 transform_causing_aa);
1508 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1509 root_pass_id,
1510 viewport_rect,
1511 transform_causing_aa);
1513 AddRenderPassQuad(root_pass, child_pass, mask, filters, transform_causing_aa);
1515 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1516 renderer_->DrawFrame(&render_passes_in_draw_order_,
1517 NULL,
1518 1.f,
1519 viewport_rect,
1520 viewport_rect,
1521 false);
1522 TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecisionMedium);
1525 // At this time, the AA code path cannot be taken if the surface's rect would
1526 // project incorrectly by the given transform, because of w<0 clipping.
1527 TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
1528 gfx::Rect child_rect(50, 50);
1529 RenderPass::Id child_pass_id(2, 0);
1530 TestRenderPass* child_pass;
1532 gfx::Rect viewport_rect(1, 1);
1533 RenderPass::Id root_pass_id(1, 0);
1534 TestRenderPass* root_pass;
1536 gfx::Transform transform_preventing_aa;
1537 transform_preventing_aa.ApplyPerspectiveDepth(40.0);
1538 transform_preventing_aa.RotateAboutYAxis(-20.0);
1539 transform_preventing_aa.Scale(30.0, 1.0);
1541 // Verify that the test transform and test rect actually do cause the clipped
1542 // flag to trigger. Otherwise we are not testing the intended scenario.
1543 bool clipped = false;
1544 MathUtil::MapQuad(transform_preventing_aa, gfx::QuadF(child_rect), &clipped);
1545 ASSERT_TRUE(clipped);
1547 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1548 child_pass_id,
1549 child_rect,
1550 transform_preventing_aa);
1552 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1553 root_pass_id,
1554 viewport_rect,
1555 gfx::Transform());
1557 AddRenderPassQuad(
1558 root_pass, child_pass, 0, FilterOperations(), transform_preventing_aa);
1560 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1561 renderer_->DrawFrame(&render_passes_in_draw_order_,
1562 NULL,
1563 1.f,
1564 viewport_rect,
1565 viewport_rect,
1566 false);
1568 // If use_aa incorrectly ignores clipping, it will use the
1569 // RenderPassProgramAA shader instead of the RenderPassProgram.
1570 TestRenderPassProgram(TexCoordPrecisionMedium);
1573 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
1574 gfx::Rect viewport_rect(1, 1);
1575 RenderPass::Id root_pass_id(1, 0);
1576 TestRenderPass* root_pass;
1578 gfx::Transform pixel_aligned_transform_causing_aa;
1579 pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
1580 pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f);
1582 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1583 root_pass_id,
1584 viewport_rect,
1585 gfx::Transform());
1586 AddTransformedQuad(root_pass,
1587 viewport_rect,
1588 SK_ColorYELLOW,
1589 pixel_aligned_transform_causing_aa);
1591 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1592 renderer_->DrawFrame(&render_passes_in_draw_order_,
1593 NULL,
1594 1.f,
1595 viewport_rect,
1596 viewport_rect,
1597 false);
1599 TestSolidColorProgramAA();
1602 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
1603 public:
1604 OutputSurfaceMockContext() { test_capabilities_.gpu.post_sub_buffer = true; }
1606 // Specifically override methods even if they are unused (used in conjunction
1607 // with StrictMock). We need to make sure that GLRenderer does not issue
1608 // framebuffer-related GLuint calls directly. Instead these are supposed to go
1609 // through the OutputSurface abstraction.
1610 MOCK_METHOD2(bindFramebuffer, void(GLenum target, GLuint framebuffer));
1611 MOCK_METHOD3(reshapeWithScaleFactor,
1612 void(int width, int height, float scale_factor));
1613 MOCK_METHOD4(drawElements,
1614 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
1617 class MockOutputSurface : public OutputSurface {
1618 public:
1619 MockOutputSurface()
1620 : OutputSurface(
1621 TestContextProvider::Create(scoped_ptr<TestWebGraphicsContext3D>(
1622 new StrictMock<OutputSurfaceMockContext>))) {
1623 surface_size_ = gfx::Size(100, 100);
1625 virtual ~MockOutputSurface() {}
1627 MOCK_METHOD0(EnsureBackbuffer, void());
1628 MOCK_METHOD0(DiscardBackbuffer, void());
1629 MOCK_METHOD2(Reshape, void(const gfx::Size& size, float scale_factor));
1630 MOCK_METHOD0(BindFramebuffer, void());
1631 MOCK_METHOD1(SwapBuffers, void(CompositorFrame* frame));
1634 class MockOutputSurfaceTest : public GLRendererTest {
1635 protected:
1636 virtual void SetUp() {
1637 FakeOutputSurfaceClient output_surface_client_;
1638 CHECK(output_surface_.BindToClient(&output_surface_client_));
1640 resource_provider_ =
1641 ResourceProvider::Create(&output_surface_, NULL, 0, false, 1).Pass();
1643 renderer_.reset(new FakeRendererGL(&renderer_client_,
1644 &settings_,
1645 &output_surface_,
1646 resource_provider_.get()));
1649 void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
1651 void DrawFrame(float device_scale_factor,
1652 const gfx::Rect& device_viewport_rect) {
1653 RenderPass::Id render_pass_id(1, 0);
1654 TestRenderPass* render_pass = AddRenderPass(&render_passes_in_draw_order_,
1655 render_pass_id,
1656 device_viewport_rect,
1657 gfx::Transform());
1658 AddQuad(render_pass, device_viewport_rect, SK_ColorGREEN);
1660 EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
1662 EXPECT_CALL(output_surface_,
1663 Reshape(device_viewport_rect.size(), device_scale_factor))
1664 .Times(1);
1666 EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
1668 EXPECT_CALL(*Context(), drawElements(_, _, _, _)).Times(1);
1670 renderer_->DecideRenderPassAllocationsForFrame(
1671 render_passes_in_draw_order_);
1672 renderer_->DrawFrame(&render_passes_in_draw_order_,
1673 NULL,
1674 device_scale_factor,
1675 device_viewport_rect,
1676 device_viewport_rect,
1677 false);
1680 OutputSurfaceMockContext* Context() {
1681 return static_cast<OutputSurfaceMockContext*>(
1682 static_cast<TestContextProvider*>(
1683 output_surface_.context_provider().get())->TestContext3d());
1686 LayerTreeSettings settings_;
1687 FakeOutputSurfaceClient output_surface_client_;
1688 StrictMock<MockOutputSurface> output_surface_;
1689 scoped_ptr<ResourceProvider> resource_provider_;
1690 FakeRendererClient renderer_client_;
1691 scoped_ptr<FakeRendererGL> renderer_;
1694 TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap) {
1695 gfx::Rect device_viewport_rect(1, 1);
1696 DrawFrame(1.f, device_viewport_rect);
1698 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1699 renderer_->SwapBuffers(CompositorFrameMetadata());
1702 TEST_F(MockOutputSurfaceTest, DrawFrameAndResizeAndSwap) {
1703 gfx::Rect device_viewport_rect(1, 1);
1705 DrawFrame(1.f, device_viewport_rect);
1706 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1707 renderer_->SwapBuffers(CompositorFrameMetadata());
1709 device_viewport_rect = gfx::Rect(2, 2);
1711 DrawFrame(2.f, device_viewport_rect);
1712 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1713 renderer_->SwapBuffers(CompositorFrameMetadata());
1715 DrawFrame(2.f, device_viewport_rect);
1716 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1717 renderer_->SwapBuffers(CompositorFrameMetadata());
1719 device_viewport_rect = gfx::Rect(1, 1);
1721 DrawFrame(1.f, device_viewport_rect);
1722 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1723 renderer_->SwapBuffers(CompositorFrameMetadata());
1726 class GLRendererTestSyncPoint : public GLRendererPixelTest {
1727 protected:
1728 static void SyncPointCallback(int* callback_count) {
1729 ++(*callback_count);
1730 base::MessageLoop::current()->QuitWhenIdle();
1733 static void OtherCallback(int* callback_count) {
1734 ++(*callback_count);
1735 base::MessageLoop::current()->QuitWhenIdle();
1739 #if !defined(OS_ANDROID)
1740 TEST_F(GLRendererTestSyncPoint, SignalSyncPointOnLostContext) {
1741 int sync_point_callback_count = 0;
1742 int other_callback_count = 0;
1743 gpu::gles2::GLES2Interface* gl =
1744 output_surface_->context_provider()->ContextGL();
1745 gpu::ContextSupport* context_support =
1746 output_surface_->context_provider()->ContextSupport();
1748 uint32 sync_point = gl->InsertSyncPointCHROMIUM();
1750 gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
1751 GL_INNOCENT_CONTEXT_RESET_ARB);
1753 context_support->SignalSyncPoint(
1754 sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count));
1755 EXPECT_EQ(0, sync_point_callback_count);
1756 EXPECT_EQ(0, other_callback_count);
1758 // Make the sync point happen.
1759 gl->Finish();
1760 // Post a task after the sync point.
1761 base::MessageLoop::current()->PostTask(
1762 FROM_HERE, base::Bind(&OtherCallback, &other_callback_count));
1764 base::MessageLoop::current()->Run();
1766 // The sync point shouldn't have happened since the context was lost.
1767 EXPECT_EQ(0, sync_point_callback_count);
1768 EXPECT_EQ(1, other_callback_count);
1771 TEST_F(GLRendererTestSyncPoint, SignalSyncPoint) {
1772 int sync_point_callback_count = 0;
1773 int other_callback_count = 0;
1775 gpu::gles2::GLES2Interface* gl =
1776 output_surface_->context_provider()->ContextGL();
1777 gpu::ContextSupport* context_support =
1778 output_surface_->context_provider()->ContextSupport();
1780 uint32 sync_point = gl->InsertSyncPointCHROMIUM();
1782 context_support->SignalSyncPoint(
1783 sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count));
1784 EXPECT_EQ(0, sync_point_callback_count);
1785 EXPECT_EQ(0, other_callback_count);
1787 // Make the sync point happen.
1788 gl->Finish();
1789 // Post a task after the sync point.
1790 base::MessageLoop::current()->PostTask(
1791 FROM_HERE, base::Bind(&OtherCallback, &other_callback_count));
1793 base::MessageLoop::current()->Run();
1795 // The sync point should have happened.
1796 EXPECT_EQ(1, sync_point_callback_count);
1797 EXPECT_EQ(1, other_callback_count);
1799 #endif // OS_ANDROID
1801 } // namespace
1802 } // namespace cc