IndexedDB: Protect against use-after-free in ChainedBlobWriter.
[chromium-blink-merge.git] / cc / output / gl_renderer_unittest.cc
blob918877fcd72b6ec45a32ba01b3c50c7f8dc22de3
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 "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "cc/base/math_util.h"
13 #include "cc/output/compositor_frame_metadata.h"
14 #include "cc/output/copy_output_request.h"
15 #include "cc/output/copy_output_result.h"
16 #include "cc/quads/texture_draw_quad.h"
17 #include "cc/resources/resource_provider.h"
18 #include "cc/resources/texture_mailbox_deleter.h"
19 #include "cc/test/fake_impl_proxy.h"
20 #include "cc/test/fake_layer_tree_host_impl.h"
21 #include "cc/test/fake_output_surface.h"
22 #include "cc/test/fake_output_surface_client.h"
23 #include "cc/test/fake_renderer_client.h"
24 #include "cc/test/pixel_test.h"
25 #include "cc/test/render_pass_test_common.h"
26 #include "cc/test/render_pass_test_utils.h"
27 #include "cc/test/test_shared_bitmap_manager.h"
28 #include "cc/test/test_web_graphics_context_3d.h"
29 #include "gpu/GLES2/gl2extchromium.h"
30 #include "gpu/command_buffer/client/context_support.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/skia/include/core/SkImageFilter.h"
34 #include "third_party/skia/include/core/SkMatrix.h"
35 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
36 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
37 #include "ui/gfx/transform.h"
39 using testing::_;
40 using testing::AnyNumber;
41 using testing::Args;
42 using testing::AtLeast;
43 using testing::ElementsAre;
44 using testing::Expectation;
45 using testing::InSequence;
46 using testing::Mock;
47 using testing::Return;
48 using testing::StrictMock;
50 namespace cc {
52 class GLRendererTest : public testing::Test {
53 protected:
54 RenderPass* root_render_pass() { return render_passes_in_draw_order_.back(); }
56 RenderPassList render_passes_in_draw_order_;
59 #define EXPECT_PROGRAM_VALID(program_binding) \
60 do { \
61 EXPECT_TRUE((program_binding)->program()); \
62 EXPECT_TRUE((program_binding)->initialized()); \
63 } while (false)
65 static inline SkXfermode::Mode BlendModeToSkXfermode(BlendMode blend_mode) {
66 switch (blend_mode) {
67 case BLEND_MODE_NONE:
68 case BLEND_MODE_NORMAL:
69 return SkXfermode::kSrcOver_Mode;
70 case BLEND_MODE_SCREEN:
71 return SkXfermode::kScreen_Mode;
72 case BLEND_MODE_OVERLAY:
73 return SkXfermode::kOverlay_Mode;
74 case BLEND_MODE_DARKEN:
75 return SkXfermode::kDarken_Mode;
76 case BLEND_MODE_LIGHTEN:
77 return SkXfermode::kLighten_Mode;
78 case BLEND_MODE_COLOR_DODGE:
79 return SkXfermode::kColorDodge_Mode;
80 case BLEND_MODE_COLOR_BURN:
81 return SkXfermode::kColorBurn_Mode;
82 case BLEND_MODE_HARD_LIGHT:
83 return SkXfermode::kHardLight_Mode;
84 case BLEND_MODE_SOFT_LIGHT:
85 return SkXfermode::kSoftLight_Mode;
86 case BLEND_MODE_DIFFERENCE:
87 return SkXfermode::kDifference_Mode;
88 case BLEND_MODE_EXCLUSION:
89 return SkXfermode::kExclusion_Mode;
90 case BLEND_MODE_MULTIPLY:
91 return SkXfermode::kMultiply_Mode;
92 case BLEND_MODE_HUE:
93 return SkXfermode::kHue_Mode;
94 case BLEND_MODE_SATURATION:
95 return SkXfermode::kSaturation_Mode;
96 case BLEND_MODE_COLOR:
97 return SkXfermode::kColor_Mode;
98 case BLEND_MODE_LUMINOSITY:
99 return SkXfermode::kLuminosity_Mode;
101 return SkXfermode::kSrcOver_Mode;
104 // Explicitly named to be a friend in GLRenderer for shader access.
105 class GLRendererShaderPixelTest : public GLRendererPixelTest {
106 public:
107 void SetUp() override {
108 GLRendererPixelTest::SetUp();
109 ASSERT_FALSE(renderer()->IsContextLost());
112 void TearDown() override {
113 GLRendererPixelTest::TearDown();
114 ASSERT_FALSE(renderer()->IsContextLost());
117 void TestBasicShaders() {
118 EXPECT_PROGRAM_VALID(renderer()->GetTileCheckerboardProgram());
119 EXPECT_PROGRAM_VALID(renderer()->GetDebugBorderProgram());
120 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgram());
121 EXPECT_PROGRAM_VALID(renderer()->GetSolidColorProgramAA());
124 void TestShadersWithPrecision(TexCoordPrecision precision) {
125 EXPECT_PROGRAM_VALID(renderer()->GetTextureProgram(precision));
126 EXPECT_PROGRAM_VALID(
127 renderer()->GetNonPremultipliedTextureProgram(precision));
128 EXPECT_PROGRAM_VALID(renderer()->GetTextureBackgroundProgram(precision));
129 EXPECT_PROGRAM_VALID(
130 renderer()->GetNonPremultipliedTextureBackgroundProgram(precision));
131 EXPECT_PROGRAM_VALID(renderer()->GetTextureIOSurfaceProgram(precision));
132 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVProgram(precision));
133 EXPECT_PROGRAM_VALID(renderer()->GetVideoYUVAProgram(precision));
134 if (renderer()->Capabilities().using_egl_image)
135 EXPECT_PROGRAM_VALID(renderer()->GetVideoStreamTextureProgram(precision));
136 else
137 EXPECT_FALSE(renderer()->GetVideoStreamTextureProgram(precision));
140 void TestShadersWithPrecisionAndBlend(TexCoordPrecision precision,
141 BlendMode blend_mode) {
142 EXPECT_PROGRAM_VALID(
143 renderer()->GetRenderPassProgram(precision, blend_mode));
144 EXPECT_PROGRAM_VALID(
145 renderer()->GetRenderPassProgramAA(precision, blend_mode));
148 void TestShadersWithPrecisionAndSampler(TexCoordPrecision precision,
149 SamplerType sampler) {
150 if (!renderer()->Capabilities().using_egl_image &&
151 sampler == SAMPLER_TYPE_EXTERNAL_OES) {
152 // This will likely be hit in tests due to usage of osmesa.
153 return;
156 EXPECT_PROGRAM_VALID(renderer()->GetTileProgram(precision, sampler));
157 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramOpaque(precision, sampler));
158 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramAA(precision, sampler));
159 EXPECT_PROGRAM_VALID(renderer()->GetTileProgramSwizzle(precision, sampler));
160 EXPECT_PROGRAM_VALID(
161 renderer()->GetTileProgramSwizzleOpaque(precision, sampler));
162 EXPECT_PROGRAM_VALID(
163 renderer()->GetTileProgramSwizzleAA(precision, sampler));
166 void TestShadersWithMasks(TexCoordPrecision precision,
167 SamplerType sampler,
168 BlendMode blend_mode,
169 bool mask_for_background) {
170 if (!renderer()->Capabilities().using_egl_image &&
171 sampler == SAMPLER_TYPE_EXTERNAL_OES) {
172 // This will likely be hit in tests due to usage of osmesa.
173 return;
176 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgram(
177 precision, sampler, blend_mode, mask_for_background));
178 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskProgramAA(
179 precision, sampler, blend_mode, mask_for_background));
180 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgramAA(
181 precision, sampler, blend_mode, mask_for_background));
182 EXPECT_PROGRAM_VALID(renderer()->GetRenderPassMaskColorMatrixProgram(
183 precision, sampler, blend_mode, mask_for_background));
187 namespace {
189 #if !defined(OS_ANDROID) && !defined(OS_WIN)
190 static const TexCoordPrecision kPrecisionList[] = {TEX_COORD_PRECISION_MEDIUM,
191 TEX_COORD_PRECISION_HIGH};
193 static const BlendMode kBlendModeList[LAST_BLEND_MODE + 1] = {
194 BLEND_MODE_NONE,
195 BLEND_MODE_NORMAL,
196 BLEND_MODE_SCREEN,
197 BLEND_MODE_OVERLAY,
198 BLEND_MODE_DARKEN,
199 BLEND_MODE_LIGHTEN,
200 BLEND_MODE_COLOR_DODGE,
201 BLEND_MODE_COLOR_BURN,
202 BLEND_MODE_HARD_LIGHT,
203 BLEND_MODE_SOFT_LIGHT,
204 BLEND_MODE_DIFFERENCE,
205 BLEND_MODE_EXCLUSION,
206 BLEND_MODE_MULTIPLY,
207 BLEND_MODE_HUE,
208 BLEND_MODE_SATURATION,
209 BLEND_MODE_COLOR,
210 BLEND_MODE_LUMINOSITY,
213 static const SamplerType kSamplerList[] = {
214 SAMPLER_TYPE_2D,
215 SAMPLER_TYPE_2D_RECT,
216 SAMPLER_TYPE_EXTERNAL_OES,
219 TEST_F(GLRendererShaderPixelTest, BasicShadersCompile) {
220 TestBasicShaders();
223 class PrecisionShaderPixelTest
224 : public GLRendererShaderPixelTest,
225 public ::testing::WithParamInterface<TexCoordPrecision> {};
227 TEST_P(PrecisionShaderPixelTest, ShadersCompile) {
228 TestShadersWithPrecision(GetParam());
231 INSTANTIATE_TEST_CASE_P(PrecisionShadersCompile,
232 PrecisionShaderPixelTest,
233 ::testing::ValuesIn(kPrecisionList));
235 class PrecisionBlendShaderPixelTest
236 : public GLRendererShaderPixelTest,
237 public ::testing::WithParamInterface<
238 std::tr1::tuple<TexCoordPrecision, BlendMode>> {};
240 TEST_P(PrecisionBlendShaderPixelTest, ShadersCompile) {
241 TestShadersWithPrecisionAndBlend(std::tr1::get<0>(GetParam()),
242 std::tr1::get<1>(GetParam()));
245 INSTANTIATE_TEST_CASE_P(
246 PrecisionBlendShadersCompile,
247 PrecisionBlendShaderPixelTest,
248 ::testing::Combine(::testing::ValuesIn(kPrecisionList),
249 ::testing::ValuesIn(kBlendModeList)));
251 class PrecisionSamplerShaderPixelTest
252 : public GLRendererShaderPixelTest,
253 public ::testing::WithParamInterface<
254 std::tr1::tuple<TexCoordPrecision, SamplerType>> {};
256 TEST_P(PrecisionSamplerShaderPixelTest, ShadersCompile) {
257 TestShadersWithPrecisionAndSampler(std::tr1::get<0>(GetParam()),
258 std::tr1::get<1>(GetParam()));
261 INSTANTIATE_TEST_CASE_P(PrecisionSamplerShadersCompile,
262 PrecisionSamplerShaderPixelTest,
263 ::testing::Combine(::testing::ValuesIn(kPrecisionList),
264 ::testing::ValuesIn(kSamplerList)));
266 class MaskShaderPixelTest
267 : public GLRendererShaderPixelTest,
268 public ::testing::WithParamInterface<
269 std::tr1::tuple<TexCoordPrecision, SamplerType, BlendMode, bool>> {};
271 TEST_P(MaskShaderPixelTest, ShadersCompile) {
272 TestShadersWithMasks(
273 std::tr1::get<0>(GetParam()), std::tr1::get<1>(GetParam()),
274 std::tr1::get<2>(GetParam()), std::tr1::get<3>(GetParam()));
277 INSTANTIATE_TEST_CASE_P(MaskShadersCompile,
278 MaskShaderPixelTest,
279 ::testing::Combine(::testing::ValuesIn(kPrecisionList),
280 ::testing::ValuesIn(kSamplerList),
281 ::testing::ValuesIn(kBlendModeList),
282 ::testing::Bool()));
284 #endif
286 class FakeRendererGL : public GLRenderer {
287 public:
288 FakeRendererGL(RendererClient* client,
289 const RendererSettings* settings,
290 OutputSurface* output_surface,
291 ResourceProvider* resource_provider)
292 : GLRenderer(client,
293 settings,
294 output_surface,
295 resource_provider,
296 NULL,
297 0) {}
299 FakeRendererGL(RendererClient* client,
300 const RendererSettings* settings,
301 OutputSurface* output_surface,
302 ResourceProvider* resource_provider,
303 TextureMailboxDeleter* texture_mailbox_deleter)
304 : GLRenderer(client,
305 settings,
306 output_surface,
307 resource_provider,
308 texture_mailbox_deleter,
309 0) {}
311 void SetOverlayProcessor(OverlayProcessor* processor) {
312 overlay_processor_.reset(processor);
315 // GLRenderer methods.
317 // Changing visibility to public.
318 using GLRenderer::IsBackbufferDiscarded;
319 using GLRenderer::DoDrawQuad;
320 using GLRenderer::BeginDrawingFrame;
321 using GLRenderer::FinishDrawingQuadList;
322 using GLRenderer::stencil_enabled;
325 class GLRendererWithDefaultHarnessTest : public GLRendererTest {
326 protected:
327 GLRendererWithDefaultHarnessTest() {
328 output_surface_ =
329 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()).Pass();
330 CHECK(output_surface_->BindToClient(&output_surface_client_));
332 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
333 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
334 shared_bitmap_manager_.get(),
335 NULL,
336 NULL,
338 false,
339 1).Pass();
340 renderer_ = make_scoped_ptr(new FakeRendererGL(&renderer_client_,
341 &settings_,
342 output_surface_.get(),
343 resource_provider_.get()));
346 void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
348 RendererSettings settings_;
349 FakeOutputSurfaceClient output_surface_client_;
350 scoped_ptr<FakeOutputSurface> output_surface_;
351 FakeRendererClient renderer_client_;
352 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
353 scoped_ptr<ResourceProvider> resource_provider_;
354 scoped_ptr<FakeRendererGL> renderer_;
357 // Closing the namespace here so that GLRendererShaderTest can take advantage
358 // of the friend relationship with GLRenderer and all of the mock classes
359 // declared above it.
360 } // namespace
362 class GLRendererShaderTest : public GLRendererTest {
363 protected:
364 GLRendererShaderTest() {
365 output_surface_ = FakeOutputSurface::Create3d().Pass();
366 CHECK(output_surface_->BindToClient(&output_surface_client_));
368 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
369 resource_provider_ = ResourceProvider::Create(output_surface_.get(),
370 shared_bitmap_manager_.get(),
371 NULL,
372 NULL,
374 false,
375 1).Pass();
376 renderer_.reset(new FakeRendererGL(&renderer_client_,
377 &settings_,
378 output_surface_.get(),
379 resource_provider_.get()));
382 void TestRenderPassProgram(TexCoordPrecision precision,
383 BlendMode blend_mode) {
384 EXPECT_PROGRAM_VALID(
385 &renderer_->render_pass_program_[precision][blend_mode]);
386 EXPECT_EQ(renderer_->render_pass_program_[precision][blend_mode].program(),
387 renderer_->program_shadow_);
390 void TestRenderPassColorMatrixProgram(TexCoordPrecision precision,
391 BlendMode blend_mode) {
392 EXPECT_PROGRAM_VALID(
393 &renderer_->render_pass_color_matrix_program_[precision][blend_mode]);
394 EXPECT_EQ(
395 renderer_->render_pass_color_matrix_program_[precision][blend_mode]
396 .program(),
397 renderer_->program_shadow_);
400 void TestRenderPassMaskProgram(TexCoordPrecision precision,
401 SamplerType sampler,
402 BlendMode blend_mode) {
403 EXPECT_PROGRAM_VALID(
404 &renderer_->render_pass_mask_program_[precision]
405 [sampler]
406 [blend_mode]
407 [NO_MASK]);
408 EXPECT_EQ(
409 renderer_->render_pass_mask_program_[precision]
410 [sampler]
411 [blend_mode]
412 [NO_MASK].program(),
413 renderer_->program_shadow_);
416 void TestRenderPassMaskColorMatrixProgram(TexCoordPrecision precision,
417 SamplerType sampler,
418 BlendMode blend_mode) {
419 EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_color_matrix_program_
420 [precision][sampler][blend_mode][NO_MASK]);
421 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_
422 [precision][sampler][blend_mode][NO_MASK].program(),
423 renderer_->program_shadow_);
426 void TestRenderPassProgramAA(TexCoordPrecision precision,
427 BlendMode blend_mode) {
428 EXPECT_PROGRAM_VALID(
429 &renderer_->render_pass_program_aa_[precision][blend_mode]);
430 EXPECT_EQ(
431 renderer_->render_pass_program_aa_[precision][blend_mode].program(),
432 renderer_->program_shadow_);
435 void TestRenderPassColorMatrixProgramAA(TexCoordPrecision precision,
436 BlendMode blend_mode) {
437 EXPECT_PROGRAM_VALID(
438 &renderer_
439 ->render_pass_color_matrix_program_aa_[precision][blend_mode]);
440 EXPECT_EQ(
441 renderer_->render_pass_color_matrix_program_aa_[precision][blend_mode]
442 .program(),
443 renderer_->program_shadow_);
446 void TestRenderPassMaskProgramAA(TexCoordPrecision precision,
447 SamplerType sampler,
448 BlendMode blend_mode) {
449 EXPECT_PROGRAM_VALID(
450 &renderer_
451 ->render_pass_mask_program_aa_
452 [precision][sampler][blend_mode][NO_MASK]);
453 EXPECT_EQ(
454 renderer_->render_pass_mask_program_aa_[precision][sampler][blend_mode]
455 [NO_MASK].program(),
456 renderer_->program_shadow_);
459 void TestRenderPassMaskColorMatrixProgramAA(TexCoordPrecision precision,
460 SamplerType sampler,
461 BlendMode blend_mode) {
462 EXPECT_PROGRAM_VALID(&renderer_->render_pass_mask_color_matrix_program_aa_
463 [precision][sampler][blend_mode][NO_MASK]);
464 EXPECT_EQ(renderer_->render_pass_mask_color_matrix_program_aa_
465 [precision][sampler][blend_mode][NO_MASK].program(),
466 renderer_->program_shadow_);
469 void TestSolidColorProgramAA() {
470 EXPECT_PROGRAM_VALID(&renderer_->solid_color_program_aa_);
471 EXPECT_EQ(renderer_->solid_color_program_aa_.program(),
472 renderer_->program_shadow_);
475 RendererSettings settings_;
476 FakeOutputSurfaceClient output_surface_client_;
477 scoped_ptr<FakeOutputSurface> output_surface_;
478 FakeRendererClient renderer_client_;
479 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
480 scoped_ptr<ResourceProvider> resource_provider_;
481 scoped_ptr<FakeRendererGL> renderer_;
484 namespace {
486 // Test GLRenderer DiscardBackbuffer functionality:
487 // Suggest discarding framebuffer when one exists and the renderer is not
488 // visible.
489 // Expected: it is discarded and damage tracker is reset.
490 TEST_F(
491 GLRendererWithDefaultHarnessTest,
492 SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayerIfNotVisible) {
493 renderer_->SetVisible(false);
494 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
495 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
498 // Test GLRenderer DiscardBackbuffer functionality:
499 // Suggest discarding framebuffer when one exists and the renderer is visible.
500 // Expected: the allocation is ignored.
501 TEST_F(GLRendererWithDefaultHarnessTest,
502 SuggestBackbufferNoDoNothingWhenVisible) {
503 renderer_->SetVisible(true);
504 EXPECT_EQ(0, renderer_client_.set_full_root_layer_damage_count());
505 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
508 // Test GLRenderer DiscardBackbuffer functionality:
509 // Suggest discarding framebuffer when one does not exist.
510 // Expected: it does nothing.
511 TEST_F(GLRendererWithDefaultHarnessTest,
512 SuggestBackbufferNoWhenItDoesntExistShouldDoNothing) {
513 renderer_->SetVisible(false);
514 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
515 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
517 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
518 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
521 // Test GLRenderer DiscardBackbuffer functionality:
522 // Begin drawing a frame while a framebuffer is discarded.
523 // Expected: will recreate framebuffer.
524 TEST_F(GLRendererWithDefaultHarnessTest,
525 DiscardedBackbufferIsRecreatedForScopeDuration) {
526 gfx::Rect viewport_rect(1, 1);
527 renderer_->SetVisible(false);
528 EXPECT_TRUE(renderer_->IsBackbufferDiscarded());
529 EXPECT_EQ(1, renderer_client_.set_full_root_layer_damage_count());
531 AddRenderPass(&render_passes_in_draw_order_,
532 RenderPassId(1, 0),
533 viewport_rect,
534 gfx::Transform());
536 renderer_->SetVisible(true);
537 renderer_->DrawFrame(&render_passes_in_draw_order_,
538 1.f,
539 viewport_rect,
540 viewport_rect,
541 false);
542 EXPECT_FALSE(renderer_->IsBackbufferDiscarded());
544 SwapBuffers();
545 EXPECT_EQ(1u, output_surface_->num_sent_frames());
548 TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) {
549 gfx::Rect viewport_rect(1, 1);
550 EXPECT_FALSE(renderer_->stencil_enabled());
552 output_surface_->set_has_external_stencil_test(true);
554 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
555 RenderPassId(1, 0),
556 viewport_rect,
557 gfx::Transform());
558 root_pass->has_transparent_background = false;
560 renderer_->DrawFrame(&render_passes_in_draw_order_,
561 1.f,
562 viewport_rect,
563 viewport_rect,
564 false);
565 EXPECT_TRUE(renderer_->stencil_enabled());
568 class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
569 public:
570 ForbidSynchronousCallContext() {}
572 void getAttachedShaders(GLuint program,
573 GLsizei max_count,
574 GLsizei* count,
575 GLuint* shaders) override {
576 ADD_FAILURE();
578 GLint getAttribLocation(GLuint program, const GLchar* name) override {
579 ADD_FAILURE();
580 return 0;
582 void getBooleanv(GLenum pname, GLboolean* value) override { ADD_FAILURE(); }
583 void getBufferParameteriv(GLenum target,
584 GLenum pname,
585 GLint* value) override {
586 ADD_FAILURE();
588 GLenum getError() override {
589 ADD_FAILURE();
590 return GL_NO_ERROR;
592 void getFloatv(GLenum pname, GLfloat* value) override { ADD_FAILURE(); }
593 void getFramebufferAttachmentParameteriv(GLenum target,
594 GLenum attachment,
595 GLenum pname,
596 GLint* value) override {
597 ADD_FAILURE();
599 void getIntegerv(GLenum pname, GLint* value) override {
600 if (pname == GL_MAX_TEXTURE_SIZE) {
601 // MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
602 *value = 1024;
603 } else {
604 ADD_FAILURE();
608 // We allow querying the shader compilation and program link status in debug
609 // mode, but not release.
610 void getProgramiv(GLuint program, GLenum pname, GLint* value) override {
611 #ifndef NDEBUG
612 *value = 1;
613 #else
614 ADD_FAILURE();
615 #endif
618 void getShaderiv(GLuint shader, GLenum pname, GLint* value) override {
619 #ifndef NDEBUG
620 *value = 1;
621 #else
622 ADD_FAILURE();
623 #endif
626 void getRenderbufferParameteriv(GLenum target,
627 GLenum pname,
628 GLint* value) override {
629 ADD_FAILURE();
632 void getShaderPrecisionFormat(GLenum shadertype,
633 GLenum precisiontype,
634 GLint* range,
635 GLint* precision) override {
636 ADD_FAILURE();
638 void getTexParameterfv(GLenum target, GLenum pname, GLfloat* value) override {
639 ADD_FAILURE();
641 void getTexParameteriv(GLenum target, GLenum pname, GLint* value) override {
642 ADD_FAILURE();
644 void getUniformfv(GLuint program, GLint location, GLfloat* value) override {
645 ADD_FAILURE();
647 void getUniformiv(GLuint program, GLint location, GLint* value) override {
648 ADD_FAILURE();
650 GLint getUniformLocation(GLuint program, const GLchar* name) override {
651 ADD_FAILURE();
652 return 0;
654 void getVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) override {
655 ADD_FAILURE();
657 void getVertexAttribiv(GLuint index, GLenum pname, GLint* value) override {
658 ADD_FAILURE();
660 GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname) override {
661 ADD_FAILURE();
662 return 0;
665 TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
666 FakeOutputSurfaceClient output_surface_client;
667 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
668 scoped_ptr<TestWebGraphicsContext3D>(new ForbidSynchronousCallContext)));
669 CHECK(output_surface->BindToClient(&output_surface_client));
671 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
672 new TestSharedBitmapManager());
673 scoped_ptr<ResourceProvider> resource_provider(
674 ResourceProvider::Create(output_surface.get(),
675 shared_bitmap_manager.get(),
676 NULL,
677 NULL,
679 false,
680 1));
682 RendererSettings settings;
683 FakeRendererClient renderer_client;
684 FakeRendererGL renderer(&renderer_client,
685 &settings,
686 output_surface.get(),
687 resource_provider.get());
690 class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
691 public:
692 LoseContextOnFirstGetContext() {}
694 void getProgramiv(GLuint program, GLenum pname, GLint* value) override {
695 context_lost_ = true;
696 *value = 0;
699 void getShaderiv(GLuint shader, GLenum pname, GLint* value) override {
700 context_lost_ = true;
701 *value = 0;
705 TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
706 FakeOutputSurfaceClient output_surface_client;
707 scoped_ptr<OutputSurface> output_surface(FakeOutputSurface::Create3d(
708 scoped_ptr<TestWebGraphicsContext3D>(new LoseContextOnFirstGetContext)));
709 CHECK(output_surface->BindToClient(&output_surface_client));
711 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
712 new TestSharedBitmapManager());
713 scoped_ptr<ResourceProvider> resource_provider(
714 ResourceProvider::Create(output_surface.get(),
715 shared_bitmap_manager.get(),
716 NULL,
717 NULL,
719 false,
720 1));
722 RendererSettings settings;
723 FakeRendererClient renderer_client;
724 FakeRendererGL renderer(&renderer_client,
725 &settings,
726 output_surface.get(),
727 resource_provider.get());
730 class ClearCountingContext : public TestWebGraphicsContext3D {
731 public:
732 ClearCountingContext() { test_capabilities_.gpu.discard_framebuffer = true; }
734 MOCK_METHOD3(discardFramebufferEXT,
735 void(GLenum target,
736 GLsizei numAttachments,
737 const GLenum* attachments));
738 MOCK_METHOD1(clear, void(GLbitfield mask));
741 TEST_F(GLRendererTest, OpaqueBackground) {
742 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
743 ClearCountingContext* context = context_owned.get();
745 FakeOutputSurfaceClient output_surface_client;
746 scoped_ptr<OutputSurface> output_surface(
747 FakeOutputSurface::Create3d(context_owned.Pass()));
748 CHECK(output_surface->BindToClient(&output_surface_client));
750 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
751 new TestSharedBitmapManager());
752 scoped_ptr<ResourceProvider> resource_provider(
753 ResourceProvider::Create(output_surface.get(),
754 shared_bitmap_manager.get(),
755 NULL,
756 NULL,
758 false,
759 1));
761 RendererSettings settings;
762 FakeRendererClient renderer_client;
763 FakeRendererGL renderer(&renderer_client,
764 &settings,
765 output_surface.get(),
766 resource_provider.get());
768 gfx::Rect viewport_rect(1, 1);
769 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
770 RenderPassId(1, 0),
771 viewport_rect,
772 gfx::Transform());
773 root_pass->has_transparent_background = false;
775 // On DEBUG builds, render passes with opaque background clear to blue to
776 // easily see regions that were not drawn on the screen.
777 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
778 .With(Args<2, 1>(ElementsAre(GL_COLOR_EXT)))
779 .Times(1);
780 #ifdef NDEBUG
781 EXPECT_CALL(*context, clear(_)).Times(0);
782 #else
783 EXPECT_CALL(*context, clear(_)).Times(1);
784 #endif
785 renderer.DrawFrame(&render_passes_in_draw_order_,
786 1.f,
787 viewport_rect,
788 viewport_rect,
789 false);
790 Mock::VerifyAndClearExpectations(context);
793 TEST_F(GLRendererTest, TransparentBackground) {
794 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
795 ClearCountingContext* context = context_owned.get();
797 FakeOutputSurfaceClient output_surface_client;
798 scoped_ptr<OutputSurface> output_surface(
799 FakeOutputSurface::Create3d(context_owned.Pass()));
800 CHECK(output_surface->BindToClient(&output_surface_client));
802 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
803 new TestSharedBitmapManager());
804 scoped_ptr<ResourceProvider> resource_provider(
805 ResourceProvider::Create(output_surface.get(),
806 shared_bitmap_manager.get(),
807 NULL,
808 NULL,
810 false,
811 1));
813 RendererSettings settings;
814 FakeRendererClient renderer_client;
815 FakeRendererGL renderer(&renderer_client,
816 &settings,
817 output_surface.get(),
818 resource_provider.get());
820 gfx::Rect viewport_rect(1, 1);
821 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
822 RenderPassId(1, 0),
823 viewport_rect,
824 gfx::Transform());
825 root_pass->has_transparent_background = true;
827 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1);
828 EXPECT_CALL(*context, clear(_)).Times(1);
829 renderer.DrawFrame(&render_passes_in_draw_order_,
830 1.f,
831 viewport_rect,
832 viewport_rect,
833 false);
835 Mock::VerifyAndClearExpectations(context);
838 TEST_F(GLRendererTest, OffscreenOutputSurface) {
839 scoped_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
840 ClearCountingContext* context = context_owned.get();
842 FakeOutputSurfaceClient output_surface_client;
843 scoped_ptr<OutputSurface> output_surface(
844 FakeOutputSurface::CreateOffscreen(context_owned.Pass()));
845 CHECK(output_surface->BindToClient(&output_surface_client));
847 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
848 new TestSharedBitmapManager());
849 scoped_ptr<ResourceProvider> resource_provider(
850 ResourceProvider::Create(output_surface.get(),
851 shared_bitmap_manager.get(),
852 NULL,
853 NULL,
855 false,
856 1));
858 RendererSettings settings;
859 FakeRendererClient renderer_client;
860 FakeRendererGL renderer(&renderer_client,
861 &settings,
862 output_surface.get(),
863 resource_provider.get());
865 gfx::Rect viewport_rect(1, 1);
866 AddRenderPass(&render_passes_in_draw_order_,
867 RenderPassId(1, 0),
868 viewport_rect,
869 gfx::Transform());
871 EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
872 .With(Args<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0)))
873 .Times(1);
874 EXPECT_CALL(*context, clear(_)).Times(AnyNumber());
875 renderer.DrawFrame(&render_passes_in_draw_order_,
876 1.f,
877 viewport_rect,
878 viewport_rect,
879 false);
880 Mock::VerifyAndClearExpectations(context);
883 class VisibilityChangeIsLastCallTrackingContext
884 : public TestWebGraphicsContext3D {
885 public:
886 VisibilityChangeIsLastCallTrackingContext()
887 : last_call_was_set_visibility_(false) {}
889 // TestWebGraphicsContext3D methods.
890 void flush() override { last_call_was_set_visibility_ = false; }
891 void deleteTexture(GLuint) override { last_call_was_set_visibility_ = false; }
892 void deleteFramebuffer(GLuint) override {
893 last_call_was_set_visibility_ = false;
895 void deleteQueryEXT(GLuint) override {
896 last_call_was_set_visibility_ = false;
898 void deleteRenderbuffer(GLuint) override {
899 last_call_was_set_visibility_ = false;
902 // Methods added for test.
903 void set_last_call_was_visibility(bool visible) {
904 DCHECK(last_call_was_set_visibility_ == false);
905 last_call_was_set_visibility_ = true;
907 bool last_call_was_set_visibility() const {
908 return last_call_was_set_visibility_;
911 private:
912 bool last_call_was_set_visibility_;
915 TEST_F(GLRendererTest, VisibilityChangeIsLastCall) {
916 scoped_ptr<VisibilityChangeIsLastCallTrackingContext> context_owned(
917 new VisibilityChangeIsLastCallTrackingContext);
918 VisibilityChangeIsLastCallTrackingContext* context = context_owned.get();
920 scoped_refptr<TestContextProvider> provider =
921 TestContextProvider::Create(context_owned.Pass());
923 provider->support()->SetSurfaceVisibleCallback(base::Bind(
924 &VisibilityChangeIsLastCallTrackingContext::set_last_call_was_visibility,
925 base::Unretained(context)));
927 FakeOutputSurfaceClient output_surface_client;
928 scoped_ptr<OutputSurface> output_surface(
929 FakeOutputSurface::Create3d(provider));
930 CHECK(output_surface->BindToClient(&output_surface_client));
932 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
933 new TestSharedBitmapManager());
934 scoped_ptr<ResourceProvider> resource_provider(
935 ResourceProvider::Create(output_surface.get(),
936 shared_bitmap_manager.get(),
937 NULL,
938 NULL,
940 false,
941 1));
943 RendererSettings settings;
944 FakeRendererClient renderer_client;
945 FakeRendererGL renderer(&renderer_client,
946 &settings,
947 output_surface.get(),
948 resource_provider.get());
950 gfx::Rect viewport_rect(1, 1);
951 AddRenderPass(&render_passes_in_draw_order_,
952 RenderPassId(1, 0),
953 viewport_rect,
954 gfx::Transform());
956 // Ensure that the call to SetSurfaceVisible is the last call issue to the
957 // GPU process, after glFlush is called, and after the RendererClient's
958 // SetManagedMemoryPolicy is called. Plumb this tracking between both the
959 // RenderClient and the Context by giving them both a pointer to a variable on
960 // the stack.
961 renderer.SetVisible(true);
962 renderer.DrawFrame(&render_passes_in_draw_order_,
963 1.f,
964 viewport_rect,
965 viewport_rect,
966 false);
967 renderer.SetVisible(false);
968 EXPECT_TRUE(context->last_call_was_set_visibility());
971 class TextureStateTrackingContext : public TestWebGraphicsContext3D {
972 public:
973 TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {
974 test_capabilities_.gpu.egl_image_external = true;
977 MOCK_METHOD1(waitSyncPoint, void(unsigned sync_point));
978 MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
979 MOCK_METHOD4(drawElements,
980 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
982 virtual void activeTexture(GLenum texture) {
983 EXPECT_NE(texture, active_texture_);
984 active_texture_ = texture;
987 GLenum active_texture() const { return active_texture_; }
989 private:
990 GLenum active_texture_;
993 TEST_F(GLRendererTest, ActiveTextureState) {
994 scoped_ptr<TextureStateTrackingContext> context_owned(
995 new TextureStateTrackingContext);
996 TextureStateTrackingContext* context = context_owned.get();
998 FakeOutputSurfaceClient output_surface_client;
999 scoped_ptr<OutputSurface> output_surface(
1000 FakeOutputSurface::Create3d(context_owned.Pass()));
1001 CHECK(output_surface->BindToClient(&output_surface_client));
1003 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1004 new TestSharedBitmapManager());
1005 scoped_ptr<ResourceProvider> resource_provider(
1006 ResourceProvider::Create(output_surface.get(),
1007 shared_bitmap_manager.get(),
1008 NULL,
1009 NULL,
1011 false,
1012 1));
1014 RendererSettings settings;
1015 FakeRendererClient renderer_client;
1016 FakeRendererGL renderer(&renderer_client,
1017 &settings,
1018 output_surface.get(),
1019 resource_provider.get());
1021 // During initialization we are allowed to set any texture parameters.
1022 EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
1024 TestRenderPass* root_pass =
1025 AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 1),
1026 gfx::Rect(100, 100), gfx::Transform());
1027 root_pass->AppendOneOfEveryQuadType(resource_provider.get(),
1028 RenderPassId(0, 0));
1030 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1032 // Set up expected texture filter state transitions that match the quads
1033 // created in AppendOneOfEveryQuadType().
1034 Mock::VerifyAndClearExpectations(context);
1036 InSequence sequence;
1038 // The sync points for all quads are waited on first. This sync point is
1039 // for a texture quad drawn later in the frame.
1040 EXPECT_CALL(*context,
1041 waitSyncPoint(TestRenderPass::kSyncPointForMailboxTextureQuad))
1042 .Times(1);
1044 // yuv_quad is drawn with the default linear filter.
1045 EXPECT_CALL(*context, drawElements(_, _, _, _));
1047 // tile_quad is drawn with GL_NEAREST because it is not transformed or
1048 // scaled.
1049 EXPECT_CALL(
1050 *context,
1051 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
1052 EXPECT_CALL(
1053 *context,
1054 texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
1055 EXPECT_CALL(*context, drawElements(_, _, _, _));
1057 // transformed_tile_quad uses GL_LINEAR.
1058 EXPECT_CALL(*context, drawElements(_, _, _, _));
1060 // scaled_tile_quad also uses GL_LINEAR.
1061 EXPECT_CALL(*context, drawElements(_, _, _, _));
1063 // The remaining quads also use GL_LINEAR because nearest neighbor
1064 // filtering is currently only used with tile quads.
1065 EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(7);
1068 gfx::Rect viewport_rect(100, 100);
1069 renderer.DrawFrame(&render_passes_in_draw_order_,
1070 1.f,
1071 viewport_rect,
1072 viewport_rect,
1073 false);
1074 Mock::VerifyAndClearExpectations(context);
1077 class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
1078 public:
1079 MOCK_METHOD1(clear, void(GLbitfield mask));
1080 MOCK_METHOD4(drawElements,
1081 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
1084 TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
1085 scoped_ptr<NoClearRootRenderPassMockContext> mock_context_owned(
1086 new NoClearRootRenderPassMockContext);
1087 NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get();
1089 FakeOutputSurfaceClient output_surface_client;
1090 scoped_ptr<OutputSurface> output_surface(
1091 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
1092 CHECK(output_surface->BindToClient(&output_surface_client));
1094 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1095 new TestSharedBitmapManager());
1096 scoped_ptr<ResourceProvider> resource_provider(
1097 ResourceProvider::Create(output_surface.get(),
1098 shared_bitmap_manager.get(),
1099 NULL,
1100 NULL,
1102 false,
1103 1));
1105 RendererSettings settings;
1106 settings.should_clear_root_render_pass = false;
1108 FakeRendererClient renderer_client;
1109 FakeRendererGL renderer(&renderer_client,
1110 &settings,
1111 output_surface.get(),
1112 resource_provider.get());
1114 gfx::Rect viewport_rect(10, 10);
1116 RenderPassId child_pass_id(2, 0);
1117 TestRenderPass* child_pass =
1118 AddRenderPass(&render_passes_in_draw_order_, child_pass_id, viewport_rect,
1119 gfx::Transform());
1120 AddQuad(child_pass, viewport_rect, SK_ColorBLUE);
1122 RenderPassId root_pass_id(1, 0);
1123 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1124 root_pass_id,
1125 viewport_rect,
1126 gfx::Transform());
1127 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1130 AddRenderPassQuad(root_pass, child_pass);
1132 #ifdef NDEBUG
1133 GLint clear_bits = GL_COLOR_BUFFER_BIT;
1134 #else
1135 GLint clear_bits = GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
1136 #endif
1138 // First render pass is not the root one, clearing should happen.
1139 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(AtLeast(1));
1141 Expectation first_render_pass =
1142 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
1144 // The second render pass is the root one, clearing should be prevented.
1145 EXPECT_CALL(*mock_context, clear(clear_bits)).Times(0).After(
1146 first_render_pass);
1148 EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(AnyNumber()).After(
1149 first_render_pass);
1151 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1152 renderer.DrawFrame(&render_passes_in_draw_order_,
1153 1.f,
1154 viewport_rect,
1155 viewport_rect,
1156 false);
1158 // In multiple render passes all but the root pass should clear the
1159 // framebuffer.
1160 Mock::VerifyAndClearExpectations(&mock_context);
1163 class ScissorTestOnClearCheckingContext : public TestWebGraphicsContext3D {
1164 public:
1165 ScissorTestOnClearCheckingContext() : scissor_enabled_(false) {}
1167 void clear(GLbitfield) override { EXPECT_FALSE(scissor_enabled_); }
1169 void enable(GLenum cap) override {
1170 if (cap == GL_SCISSOR_TEST)
1171 scissor_enabled_ = true;
1174 void disable(GLenum cap) override {
1175 if (cap == GL_SCISSOR_TEST)
1176 scissor_enabled_ = false;
1179 private:
1180 bool scissor_enabled_;
1183 TEST_F(GLRendererTest, ScissorTestWhenClearing) {
1184 scoped_ptr<ScissorTestOnClearCheckingContext> context_owned(
1185 new ScissorTestOnClearCheckingContext);
1187 FakeOutputSurfaceClient output_surface_client;
1188 scoped_ptr<OutputSurface> output_surface(
1189 FakeOutputSurface::Create3d(context_owned.Pass()));
1190 CHECK(output_surface->BindToClient(&output_surface_client));
1192 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1193 new TestSharedBitmapManager());
1194 scoped_ptr<ResourceProvider> resource_provider(
1195 ResourceProvider::Create(output_surface.get(),
1196 shared_bitmap_manager.get(),
1197 NULL,
1198 NULL,
1200 false,
1201 1));
1203 RendererSettings settings;
1204 FakeRendererClient renderer_client;
1205 FakeRendererGL renderer(&renderer_client,
1206 &settings,
1207 output_surface.get(),
1208 resource_provider.get());
1209 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1211 gfx::Rect viewport_rect(1, 1);
1213 gfx::Rect grand_child_rect(25, 25);
1214 RenderPassId grand_child_pass_id(3, 0);
1215 TestRenderPass* grand_child_pass =
1216 AddRenderPass(&render_passes_in_draw_order_,
1217 grand_child_pass_id,
1218 grand_child_rect,
1219 gfx::Transform());
1220 AddClippedQuad(grand_child_pass, grand_child_rect, SK_ColorYELLOW);
1222 gfx::Rect child_rect(50, 50);
1223 RenderPassId child_pass_id(2, 0);
1224 TestRenderPass* child_pass = AddRenderPass(&render_passes_in_draw_order_,
1225 child_pass_id,
1226 child_rect,
1227 gfx::Transform());
1228 AddQuad(child_pass, child_rect, SK_ColorBLUE);
1230 RenderPassId root_pass_id(1, 0);
1231 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1232 root_pass_id,
1233 viewport_rect,
1234 gfx::Transform());
1235 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1237 AddRenderPassQuad(root_pass, child_pass);
1238 AddRenderPassQuad(child_pass, grand_child_pass);
1240 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1241 renderer.DrawFrame(&render_passes_in_draw_order_,
1242 1.f,
1243 viewport_rect,
1244 viewport_rect,
1245 false);
1248 class DiscardCheckingContext : public TestWebGraphicsContext3D {
1249 public:
1250 DiscardCheckingContext() : discarded_(0) {
1251 set_have_post_sub_buffer(true);
1252 set_have_discard_framebuffer(true);
1255 void discardFramebufferEXT(GLenum target,
1256 GLsizei numAttachments,
1257 const GLenum* attachments) override {
1258 ++discarded_;
1261 int discarded() const { return discarded_; }
1262 void reset() { discarded_ = 0; }
1264 private:
1265 int discarded_;
1268 class NonReshapableOutputSurface : public FakeOutputSurface {
1269 public:
1270 explicit NonReshapableOutputSurface(
1271 scoped_ptr<TestWebGraphicsContext3D> context3d)
1272 : FakeOutputSurface(TestContextProvider::Create(context3d.Pass()),
1273 false) {
1274 surface_size_ = gfx::Size(500, 500);
1276 void Reshape(const gfx::Size& size, float scale_factor) override {}
1277 void set_fixed_size(const gfx::Size& size) { surface_size_ = size; }
1280 TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
1281 scoped_ptr<DiscardCheckingContext> context_owned(new DiscardCheckingContext);
1282 DiscardCheckingContext* context = context_owned.get();
1284 FakeOutputSurfaceClient output_surface_client;
1285 scoped_ptr<NonReshapableOutputSurface> output_surface(
1286 new NonReshapableOutputSurface(context_owned.Pass()));
1287 CHECK(output_surface->BindToClient(&output_surface_client));
1288 output_surface->set_fixed_size(gfx::Size(100, 100));
1290 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1291 new TestSharedBitmapManager());
1292 scoped_ptr<ResourceProvider> resource_provider(
1293 ResourceProvider::Create(output_surface.get(),
1294 shared_bitmap_manager.get(),
1295 NULL,
1296 NULL,
1298 false,
1299 1));
1301 RendererSettings settings;
1302 settings.partial_swap_enabled = true;
1303 FakeRendererClient renderer_client;
1304 FakeRendererGL renderer(&renderer_client,
1305 &settings,
1306 output_surface.get(),
1307 resource_provider.get());
1308 EXPECT_TRUE(renderer.Capabilities().using_partial_swap);
1310 gfx::Rect viewport_rect(100, 100);
1311 gfx::Rect clip_rect(100, 100);
1314 // Partial frame, should not discard.
1315 RenderPassId root_pass_id(1, 0);
1316 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1317 root_pass_id,
1318 viewport_rect,
1319 gfx::Transform());
1320 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1321 root_pass->damage_rect = gfx::Rect(2, 2, 3, 3);
1323 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1324 renderer.DrawFrame(&render_passes_in_draw_order_,
1325 1.f,
1326 viewport_rect,
1327 clip_rect,
1328 false);
1329 EXPECT_EQ(0, context->discarded());
1330 context->reset();
1333 // Full frame, should discard.
1334 RenderPassId root_pass_id(1, 0);
1335 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1336 root_pass_id,
1337 viewport_rect,
1338 gfx::Transform());
1339 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1340 root_pass->damage_rect = root_pass->output_rect;
1342 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1343 renderer.DrawFrame(&render_passes_in_draw_order_,
1344 1.f,
1345 viewport_rect,
1346 clip_rect,
1347 false);
1348 EXPECT_EQ(1, context->discarded());
1349 context->reset();
1352 // Full frame, external scissor is set, should not discard.
1353 output_surface->set_has_external_stencil_test(true);
1354 RenderPassId root_pass_id(1, 0);
1355 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1356 root_pass_id,
1357 viewport_rect,
1358 gfx::Transform());
1359 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1360 root_pass->damage_rect = root_pass->output_rect;
1361 root_pass->has_transparent_background = false;
1363 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1364 renderer.DrawFrame(&render_passes_in_draw_order_,
1365 1.f,
1366 viewport_rect,
1367 clip_rect,
1368 false);
1369 EXPECT_EQ(0, context->discarded());
1370 context->reset();
1371 output_surface->set_has_external_stencil_test(false);
1374 // Full frame, clipped, should not discard.
1375 clip_rect = gfx::Rect(10, 10, 10, 10);
1376 RenderPassId root_pass_id(1, 0);
1377 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1378 root_pass_id,
1379 viewport_rect,
1380 gfx::Transform());
1381 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1382 root_pass->damage_rect = root_pass->output_rect;
1384 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1385 renderer.DrawFrame(&render_passes_in_draw_order_,
1386 1.f,
1387 viewport_rect,
1388 clip_rect,
1389 false);
1390 EXPECT_EQ(0, context->discarded());
1391 context->reset();
1394 // Full frame, doesn't cover the surface, should not discard.
1395 viewport_rect = gfx::Rect(10, 10, 10, 10);
1396 RenderPassId root_pass_id(1, 0);
1397 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1398 root_pass_id,
1399 viewport_rect,
1400 gfx::Transform());
1401 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1402 root_pass->damage_rect = root_pass->output_rect;
1404 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1405 renderer.DrawFrame(&render_passes_in_draw_order_,
1406 1.f,
1407 viewport_rect,
1408 clip_rect,
1409 false);
1410 EXPECT_EQ(0, context->discarded());
1411 context->reset();
1414 // Full frame, doesn't cover the surface (no offset), should not discard.
1415 clip_rect = gfx::Rect(100, 100);
1416 viewport_rect = gfx::Rect(50, 50);
1417 RenderPassId root_pass_id(1, 0);
1418 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1419 root_pass_id,
1420 viewport_rect,
1421 gfx::Transform());
1422 AddQuad(root_pass, viewport_rect, SK_ColorGREEN);
1423 root_pass->damage_rect = root_pass->output_rect;
1425 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1426 renderer.DrawFrame(&render_passes_in_draw_order_,
1427 1.f,
1428 viewport_rect,
1429 clip_rect,
1430 false);
1431 EXPECT_EQ(0, context->discarded());
1432 context->reset();
1436 class FlippedScissorAndViewportContext : public TestWebGraphicsContext3D {
1437 public:
1438 MOCK_METHOD4(viewport, void(GLint x, GLint y, GLsizei width, GLsizei height));
1439 MOCK_METHOD4(scissor, void(GLint x, GLint y, GLsizei width, GLsizei height));
1442 TEST_F(GLRendererTest, ScissorAndViewportWithinNonreshapableSurface) {
1443 // In Android WebView, the OutputSurface is unable to respect reshape() calls
1444 // and maintains a fixed size. This test verifies that glViewport and
1445 // glScissor's Y coordinate is flipped correctly in this environment, and that
1446 // the glViewport can be at a nonzero origin within the surface.
1447 scoped_ptr<FlippedScissorAndViewportContext> context_owned(
1448 new FlippedScissorAndViewportContext);
1450 // We expect exactly one call to viewport on this context and exactly two
1451 // to scissor (one to scissor the clear, one to scissor the quad draw).
1452 EXPECT_CALL(*context_owned, viewport(10, 390, 100, 100));
1453 EXPECT_CALL(*context_owned, scissor(10, 390, 100, 100));
1454 EXPECT_CALL(*context_owned, scissor(30, 450, 20, 20));
1456 FakeOutputSurfaceClient output_surface_client;
1457 scoped_ptr<OutputSurface> output_surface(
1458 new NonReshapableOutputSurface(context_owned.Pass()));
1459 CHECK(output_surface->BindToClient(&output_surface_client));
1461 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1462 new TestSharedBitmapManager());
1463 scoped_ptr<ResourceProvider> resource_provider(
1464 ResourceProvider::Create(output_surface.get(),
1465 shared_bitmap_manager.get(),
1466 NULL,
1467 NULL,
1469 false,
1470 1));
1472 RendererSettings settings;
1473 FakeRendererClient renderer_client;
1474 FakeRendererGL renderer(&renderer_client,
1475 &settings,
1476 output_surface.get(),
1477 resource_provider.get());
1478 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1480 gfx::Rect device_viewport_rect(10, 10, 100, 100);
1481 gfx::Rect viewport_rect(device_viewport_rect.size());
1482 gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
1484 RenderPassId root_pass_id(1, 0);
1485 TestRenderPass* root_pass = AddRenderPass(&render_passes_in_draw_order_,
1486 root_pass_id,
1487 viewport_rect,
1488 gfx::Transform());
1489 AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
1491 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1492 renderer.DrawFrame(&render_passes_in_draw_order_,
1493 1.f,
1494 device_viewport_rect,
1495 device_viewport_rect,
1496 false);
1499 TEST_F(GLRendererTest, DrawFramePreservesFramebuffer) {
1500 // When using render-to-FBO to display the surface, all rendering is done
1501 // to a non-zero FBO. Make sure that the framebuffer is always restored to
1502 // the correct framebuffer during rendering, if changed.
1503 // Note: there is one path that will set it to 0, but that is after the render
1504 // has finished.
1505 FakeOutputSurfaceClient output_surface_client;
1506 scoped_ptr<FakeOutputSurface> output_surface(
1507 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create().Pass()));
1508 CHECK(output_surface->BindToClient(&output_surface_client));
1510 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
1511 new TestSharedBitmapManager());
1512 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
1513 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
1514 1));
1516 RendererSettings settings;
1517 FakeRendererClient renderer_client;
1518 FakeRendererGL renderer(&renderer_client, &settings, output_surface.get(),
1519 resource_provider.get());
1520 EXPECT_FALSE(renderer.Capabilities().using_partial_swap);
1522 gfx::Rect device_viewport_rect(0, 0, 100, 100);
1523 gfx::Rect viewport_rect(device_viewport_rect.size());
1524 gfx::Rect quad_rect = gfx::Rect(20, 20, 20, 20);
1526 RenderPassId root_pass_id(1, 0);
1527 TestRenderPass* root_pass =
1528 AddRenderPass(&render_passes_in_draw_order_, root_pass_id, viewport_rect,
1529 gfx::Transform());
1530 AddClippedQuad(root_pass, quad_rect, SK_ColorGREEN);
1532 unsigned fbo;
1533 gpu::gles2::GLES2Interface* gl =
1534 output_surface->context_provider()->ContextGL();
1535 gl->GenFramebuffers(1, &fbo);
1536 output_surface->set_framebuffer(fbo);
1538 renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1539 renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, device_viewport_rect,
1540 device_viewport_rect, false);
1542 int bound_fbo;
1543 gl->GetIntegerv(GL_FRAMEBUFFER_BINDING, &bound_fbo);
1544 EXPECT_EQ(static_cast<int>(fbo), bound_fbo);
1547 TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
1548 gfx::Rect viewport_rect(1, 1);
1550 gfx::Rect child_rect(50, 50);
1551 RenderPassId child_pass_id(2, 0);
1552 TestRenderPass* child_pass;
1554 RenderPassId root_pass_id(1, 0);
1555 TestRenderPass* root_pass;
1557 ResourceProvider::ResourceId mask = resource_provider_->CreateResource(
1558 gfx::Size(20, 12), GL_CLAMP_TO_EDGE,
1559 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
1560 resource_provider_->best_texture_format());
1561 resource_provider_->AllocateForTesting(mask);
1563 SkScalar matrix[20];
1564 float amount = 0.5f;
1565 matrix[0] = 0.213f + 0.787f * amount;
1566 matrix[1] = 0.715f - 0.715f * amount;
1567 matrix[2] = 1.f - (matrix[0] + matrix[1]);
1568 matrix[3] = matrix[4] = 0;
1569 matrix[5] = 0.213f - 0.213f * amount;
1570 matrix[6] = 0.715f + 0.285f * amount;
1571 matrix[7] = 1.f - (matrix[5] + matrix[6]);
1572 matrix[8] = matrix[9] = 0;
1573 matrix[10] = 0.213f - 0.213f * amount;
1574 matrix[11] = 0.715f - 0.715f * amount;
1575 matrix[12] = 1.f - (matrix[10] + matrix[11]);
1576 matrix[13] = matrix[14] = 0;
1577 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0;
1578 matrix[18] = 1;
1579 skia::RefPtr<SkColorFilter> color_filter(
1580 skia::AdoptRef(SkColorMatrixFilter::Create(matrix)));
1581 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(
1582 SkColorFilterImageFilter::Create(color_filter.get(), NULL));
1583 FilterOperations filters;
1584 filters.Append(FilterOperation::CreateReferenceFilter(filter));
1586 gfx::Transform transform_causing_aa;
1587 transform_causing_aa.Rotate(20.0);
1589 for (int i = 0; i <= LAST_BLEND_MODE; ++i) {
1590 BlendMode blend_mode = static_cast<BlendMode>(i);
1591 SkXfermode::Mode xfer_mode = BlendModeToSkXfermode(blend_mode);
1592 settings_.force_blending_with_shaders = (blend_mode != BLEND_MODE_NONE);
1593 // RenderPassProgram
1594 render_passes_in_draw_order_.clear();
1595 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1596 child_pass_id,
1597 child_rect,
1598 gfx::Transform());
1600 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1601 root_pass_id,
1602 viewport_rect,
1603 gfx::Transform());
1605 AddRenderPassQuad(root_pass,
1606 child_pass,
1608 FilterOperations(),
1609 gfx::Transform(),
1610 xfer_mode);
1612 renderer_->DecideRenderPassAllocationsForFrame(
1613 render_passes_in_draw_order_);
1614 renderer_->DrawFrame(&render_passes_in_draw_order_,
1615 1.f,
1616 viewport_rect,
1617 viewport_rect,
1618 false);
1619 TestRenderPassProgram(TEX_COORD_PRECISION_MEDIUM, blend_mode);
1621 // RenderPassColorMatrixProgram
1622 render_passes_in_draw_order_.clear();
1624 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1625 child_pass_id,
1626 child_rect,
1627 transform_causing_aa);
1629 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1630 root_pass_id,
1631 viewport_rect,
1632 gfx::Transform());
1634 AddRenderPassQuad(
1635 root_pass, child_pass, 0, filters, gfx::Transform(), xfer_mode);
1637 renderer_->DecideRenderPassAllocationsForFrame(
1638 render_passes_in_draw_order_);
1639 renderer_->DrawFrame(&render_passes_in_draw_order_,
1640 1.f,
1641 viewport_rect,
1642 viewport_rect,
1643 false);
1644 TestRenderPassColorMatrixProgram(TEX_COORD_PRECISION_MEDIUM, blend_mode);
1646 // RenderPassMaskProgram
1647 render_passes_in_draw_order_.clear();
1649 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1650 child_pass_id,
1651 child_rect,
1652 gfx::Transform());
1654 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1655 root_pass_id,
1656 viewport_rect,
1657 gfx::Transform());
1659 AddRenderPassQuad(root_pass,
1660 child_pass,
1661 mask,
1662 FilterOperations(),
1663 gfx::Transform(),
1664 xfer_mode);
1666 renderer_->DecideRenderPassAllocationsForFrame(
1667 render_passes_in_draw_order_);
1668 renderer_->DrawFrame(&render_passes_in_draw_order_,
1669 1.f,
1670 viewport_rect,
1671 viewport_rect,
1672 false);
1673 TestRenderPassMaskProgram(TEX_COORD_PRECISION_MEDIUM, SAMPLER_TYPE_2D,
1674 blend_mode);
1676 // RenderPassMaskColorMatrixProgram
1677 render_passes_in_draw_order_.clear();
1679 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1680 child_pass_id,
1681 child_rect,
1682 gfx::Transform());
1684 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1685 root_pass_id,
1686 viewport_rect,
1687 gfx::Transform());
1689 AddRenderPassQuad(
1690 root_pass, child_pass, mask, filters, gfx::Transform(), xfer_mode);
1692 renderer_->DecideRenderPassAllocationsForFrame(
1693 render_passes_in_draw_order_);
1694 renderer_->DrawFrame(&render_passes_in_draw_order_,
1695 1.f,
1696 viewport_rect,
1697 viewport_rect,
1698 false);
1699 TestRenderPassMaskColorMatrixProgram(TEX_COORD_PRECISION_MEDIUM,
1700 SAMPLER_TYPE_2D, blend_mode);
1702 // RenderPassProgramAA
1703 render_passes_in_draw_order_.clear();
1705 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1706 child_pass_id,
1707 child_rect,
1708 transform_causing_aa);
1710 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1711 root_pass_id,
1712 viewport_rect,
1713 gfx::Transform());
1715 AddRenderPassQuad(root_pass,
1716 child_pass,
1718 FilterOperations(),
1719 transform_causing_aa,
1720 xfer_mode);
1722 renderer_->DecideRenderPassAllocationsForFrame(
1723 render_passes_in_draw_order_);
1724 renderer_->DrawFrame(&render_passes_in_draw_order_,
1725 1.f,
1726 viewport_rect,
1727 viewport_rect,
1728 false);
1729 TestRenderPassProgramAA(TEX_COORD_PRECISION_MEDIUM, blend_mode);
1731 // RenderPassColorMatrixProgramAA
1732 render_passes_in_draw_order_.clear();
1734 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1735 child_pass_id,
1736 child_rect,
1737 transform_causing_aa);
1739 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1740 root_pass_id,
1741 viewport_rect,
1742 gfx::Transform());
1744 AddRenderPassQuad(
1745 root_pass, child_pass, 0, filters, transform_causing_aa, xfer_mode);
1747 renderer_->DecideRenderPassAllocationsForFrame(
1748 render_passes_in_draw_order_);
1749 renderer_->DrawFrame(&render_passes_in_draw_order_,
1750 1.f,
1751 viewport_rect,
1752 viewport_rect,
1753 false);
1754 TestRenderPassColorMatrixProgramAA(TEX_COORD_PRECISION_MEDIUM, blend_mode);
1756 // RenderPassMaskProgramAA
1757 render_passes_in_draw_order_.clear();
1759 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1760 child_pass_id,
1761 child_rect,
1762 transform_causing_aa);
1764 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1765 root_pass_id,
1766 viewport_rect,
1767 gfx::Transform());
1769 AddRenderPassQuad(root_pass,
1770 child_pass,
1771 mask,
1772 FilterOperations(),
1773 transform_causing_aa,
1774 xfer_mode);
1776 renderer_->DecideRenderPassAllocationsForFrame(
1777 render_passes_in_draw_order_);
1778 renderer_->DrawFrame(&render_passes_in_draw_order_,
1779 1.f,
1780 viewport_rect,
1781 viewport_rect,
1782 false);
1783 TestRenderPassMaskProgramAA(TEX_COORD_PRECISION_MEDIUM, SAMPLER_TYPE_2D,
1784 blend_mode);
1786 // RenderPassMaskColorMatrixProgramAA
1787 render_passes_in_draw_order_.clear();
1789 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1790 child_pass_id,
1791 child_rect,
1792 transform_causing_aa);
1794 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1795 root_pass_id,
1796 viewport_rect,
1797 transform_causing_aa);
1799 AddRenderPassQuad(
1800 root_pass, child_pass, mask, filters, transform_causing_aa, xfer_mode);
1802 renderer_->DecideRenderPassAllocationsForFrame(
1803 render_passes_in_draw_order_);
1804 renderer_->DrawFrame(&render_passes_in_draw_order_,
1805 1.f,
1806 viewport_rect,
1807 viewport_rect,
1808 false);
1809 TestRenderPassMaskColorMatrixProgramAA(TEX_COORD_PRECISION_MEDIUM,
1810 SAMPLER_TYPE_2D, blend_mode);
1814 // At this time, the AA code path cannot be taken if the surface's rect would
1815 // project incorrectly by the given transform, because of w<0 clipping.
1816 TEST_F(GLRendererShaderTest, DrawRenderPassQuadSkipsAAForClippingTransform) {
1817 gfx::Rect child_rect(50, 50);
1818 RenderPassId child_pass_id(2, 0);
1819 TestRenderPass* child_pass;
1821 gfx::Rect viewport_rect(1, 1);
1822 RenderPassId root_pass_id(1, 0);
1823 TestRenderPass* root_pass;
1825 gfx::Transform transform_preventing_aa;
1826 transform_preventing_aa.ApplyPerspectiveDepth(40.0);
1827 transform_preventing_aa.RotateAboutYAxis(-20.0);
1828 transform_preventing_aa.Scale(30.0, 1.0);
1830 // Verify that the test transform and test rect actually do cause the clipped
1831 // flag to trigger. Otherwise we are not testing the intended scenario.
1832 bool clipped = false;
1833 MathUtil::MapQuad(transform_preventing_aa, gfx::QuadF(child_rect), &clipped);
1834 ASSERT_TRUE(clipped);
1836 child_pass = AddRenderPass(&render_passes_in_draw_order_,
1837 child_pass_id,
1838 child_rect,
1839 transform_preventing_aa);
1841 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1842 root_pass_id,
1843 viewport_rect,
1844 gfx::Transform());
1846 AddRenderPassQuad(root_pass,
1847 child_pass,
1849 FilterOperations(),
1850 transform_preventing_aa,
1851 SkXfermode::kSrcOver_Mode);
1853 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1854 renderer_->DrawFrame(&render_passes_in_draw_order_,
1855 1.f,
1856 viewport_rect,
1857 viewport_rect,
1858 false);
1860 // If use_aa incorrectly ignores clipping, it will use the
1861 // RenderPassProgramAA shader instead of the RenderPassProgram.
1862 TestRenderPassProgram(TEX_COORD_PRECISION_MEDIUM, BLEND_MODE_NONE);
1865 TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
1866 gfx::Rect viewport_rect(1, 1);
1867 RenderPassId root_pass_id(1, 0);
1868 TestRenderPass* root_pass;
1870 gfx::Transform pixel_aligned_transform_causing_aa;
1871 pixel_aligned_transform_causing_aa.Translate(25.5f, 25.5f);
1872 pixel_aligned_transform_causing_aa.Scale(0.5f, 0.5f);
1874 root_pass = AddRenderPass(&render_passes_in_draw_order_,
1875 root_pass_id,
1876 viewport_rect,
1877 gfx::Transform());
1878 AddTransformedQuad(root_pass,
1879 viewport_rect,
1880 SK_ColorYELLOW,
1881 pixel_aligned_transform_causing_aa);
1883 renderer_->DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
1884 renderer_->DrawFrame(&render_passes_in_draw_order_,
1885 1.f,
1886 viewport_rect,
1887 viewport_rect,
1888 false);
1890 TestSolidColorProgramAA();
1893 class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
1894 public:
1895 OutputSurfaceMockContext() { test_capabilities_.gpu.post_sub_buffer = true; }
1897 // Specifically override methods even if they are unused (used in conjunction
1898 // with StrictMock). We need to make sure that GLRenderer does not issue
1899 // framebuffer-related GLuint calls directly. Instead these are supposed to go
1900 // through the OutputSurface abstraction.
1901 MOCK_METHOD2(bindFramebuffer, void(GLenum target, GLuint framebuffer));
1902 MOCK_METHOD3(reshapeWithScaleFactor,
1903 void(int width, int height, float scale_factor));
1904 MOCK_METHOD4(drawElements,
1905 void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
1908 class MockOutputSurface : public OutputSurface {
1909 public:
1910 MockOutputSurface()
1911 : OutputSurface(
1912 TestContextProvider::Create(scoped_ptr<TestWebGraphicsContext3D>(
1913 new StrictMock<OutputSurfaceMockContext>))) {
1914 surface_size_ = gfx::Size(100, 100);
1916 virtual ~MockOutputSurface() {}
1918 MOCK_METHOD0(EnsureBackbuffer, void());
1919 MOCK_METHOD0(DiscardBackbuffer, void());
1920 MOCK_METHOD2(Reshape, void(const gfx::Size& size, float scale_factor));
1921 MOCK_METHOD0(BindFramebuffer, void());
1922 MOCK_METHOD1(SwapBuffers, void(CompositorFrame* frame));
1925 class MockOutputSurfaceTest : public GLRendererTest {
1926 protected:
1927 virtual void SetUp() {
1928 FakeOutputSurfaceClient output_surface_client_;
1929 CHECK(output_surface_.BindToClient(&output_surface_client_));
1931 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
1932 resource_provider_ = ResourceProvider::Create(&output_surface_,
1933 shared_bitmap_manager_.get(),
1934 NULL,
1935 NULL,
1937 false,
1938 1).Pass();
1940 renderer_.reset(new FakeRendererGL(&renderer_client_,
1941 &settings_,
1942 &output_surface_,
1943 resource_provider_.get()));
1946 void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
1948 void DrawFrame(float device_scale_factor,
1949 const gfx::Rect& device_viewport_rect) {
1950 RenderPassId render_pass_id(1, 0);
1951 TestRenderPass* render_pass = AddRenderPass(&render_passes_in_draw_order_,
1952 render_pass_id,
1953 device_viewport_rect,
1954 gfx::Transform());
1955 AddQuad(render_pass, device_viewport_rect, SK_ColorGREEN);
1957 EXPECT_CALL(output_surface_, EnsureBackbuffer()).WillRepeatedly(Return());
1959 EXPECT_CALL(output_surface_,
1960 Reshape(device_viewport_rect.size(), device_scale_factor))
1961 .Times(1);
1963 EXPECT_CALL(output_surface_, BindFramebuffer()).Times(1);
1965 EXPECT_CALL(*Context(), drawElements(_, _, _, _)).Times(1);
1967 renderer_->DecideRenderPassAllocationsForFrame(
1968 render_passes_in_draw_order_);
1969 renderer_->DrawFrame(&render_passes_in_draw_order_,
1970 device_scale_factor,
1971 device_viewport_rect,
1972 device_viewport_rect,
1973 false);
1976 OutputSurfaceMockContext* Context() {
1977 return static_cast<OutputSurfaceMockContext*>(
1978 static_cast<TestContextProvider*>(output_surface_.context_provider())
1979 ->TestContext3d());
1982 RendererSettings settings_;
1983 FakeOutputSurfaceClient output_surface_client_;
1984 StrictMock<MockOutputSurface> output_surface_;
1985 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
1986 scoped_ptr<ResourceProvider> resource_provider_;
1987 FakeRendererClient renderer_client_;
1988 scoped_ptr<FakeRendererGL> renderer_;
1991 TEST_F(MockOutputSurfaceTest, DrawFrameAndSwap) {
1992 gfx::Rect device_viewport_rect(1, 1);
1993 DrawFrame(1.f, device_viewport_rect);
1995 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
1996 renderer_->SwapBuffers(CompositorFrameMetadata());
1999 TEST_F(MockOutputSurfaceTest, DrawFrameAndResizeAndSwap) {
2000 gfx::Rect device_viewport_rect(1, 1);
2002 DrawFrame(1.f, device_viewport_rect);
2003 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
2004 renderer_->SwapBuffers(CompositorFrameMetadata());
2006 device_viewport_rect = gfx::Rect(2, 2);
2008 DrawFrame(2.f, device_viewport_rect);
2009 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
2010 renderer_->SwapBuffers(CompositorFrameMetadata());
2012 DrawFrame(2.f, device_viewport_rect);
2013 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
2014 renderer_->SwapBuffers(CompositorFrameMetadata());
2016 device_viewport_rect = gfx::Rect(1, 1);
2018 DrawFrame(1.f, device_viewport_rect);
2019 EXPECT_CALL(output_surface_, SwapBuffers(_)).Times(1);
2020 renderer_->SwapBuffers(CompositorFrameMetadata());
2023 class GLRendererTestSyncPoint : public GLRendererPixelTest {
2024 protected:
2025 static void SyncPointCallback(int* callback_count) {
2026 ++(*callback_count);
2027 base::MessageLoop::current()->QuitWhenIdle();
2030 static void OtherCallback(int* callback_count) {
2031 ++(*callback_count);
2032 base::MessageLoop::current()->QuitWhenIdle();
2036 #if !defined(OS_ANDROID)
2037 TEST_F(GLRendererTestSyncPoint, SignalSyncPointOnLostContext) {
2038 int sync_point_callback_count = 0;
2039 int other_callback_count = 0;
2040 gpu::gles2::GLES2Interface* gl =
2041 output_surface_->context_provider()->ContextGL();
2042 gpu::ContextSupport* context_support =
2043 output_surface_->context_provider()->ContextSupport();
2045 uint32 sync_point = gl->InsertSyncPointCHROMIUM();
2047 gl->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
2048 GL_INNOCENT_CONTEXT_RESET_ARB);
2050 context_support->SignalSyncPoint(
2051 sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count));
2052 EXPECT_EQ(0, sync_point_callback_count);
2053 EXPECT_EQ(0, other_callback_count);
2055 // Make the sync point happen.
2056 gl->Finish();
2057 // Post a task after the sync point.
2058 base::ThreadTaskRunnerHandle::Get()->PostTask(
2059 FROM_HERE, base::Bind(&OtherCallback, &other_callback_count));
2061 base::MessageLoop::current()->Run();
2063 // The sync point shouldn't have happened since the context was lost.
2064 EXPECT_EQ(0, sync_point_callback_count);
2065 EXPECT_EQ(1, other_callback_count);
2068 TEST_F(GLRendererTestSyncPoint, SignalSyncPoint) {
2069 int sync_point_callback_count = 0;
2070 int other_callback_count = 0;
2072 gpu::gles2::GLES2Interface* gl =
2073 output_surface_->context_provider()->ContextGL();
2074 gpu::ContextSupport* context_support =
2075 output_surface_->context_provider()->ContextSupport();
2077 uint32 sync_point = gl->InsertSyncPointCHROMIUM();
2079 context_support->SignalSyncPoint(
2080 sync_point, base::Bind(&SyncPointCallback, &sync_point_callback_count));
2081 EXPECT_EQ(0, sync_point_callback_count);
2082 EXPECT_EQ(0, other_callback_count);
2084 // Make the sync point happen.
2085 gl->Finish();
2086 // Post a task after the sync point.
2087 base::ThreadTaskRunnerHandle::Get()->PostTask(
2088 FROM_HERE, base::Bind(&OtherCallback, &other_callback_count));
2090 base::MessageLoop::current()->Run();
2092 // The sync point should have happened.
2093 EXPECT_EQ(1, sync_point_callback_count);
2094 EXPECT_EQ(1, other_callback_count);
2096 #endif // OS_ANDROID
2098 class TestOverlayProcessor : public OverlayProcessor {
2099 public:
2100 class Strategy : public OverlayProcessor::Strategy {
2101 public:
2102 Strategy() {}
2103 ~Strategy() override {}
2104 MOCK_METHOD2(Attempt,
2105 bool(RenderPassList* render_passes_in_draw_order,
2106 OverlayCandidateList* candidates));
2109 TestOverlayProcessor(OutputSurface* surface,
2110 ResourceProvider* resource_provider)
2111 : OverlayProcessor(surface, resource_provider) {}
2112 ~TestOverlayProcessor() override {}
2113 void Initialize() override {
2114 strategy_ = new Strategy();
2115 strategies_.push_back(scoped_ptr<OverlayProcessor::Strategy>(strategy_));
2118 Strategy* strategy_;
2121 void MailboxReleased(unsigned sync_point,
2122 bool lost_resource,
2123 BlockingTaskRunner* main_thread_task_runner) {
2126 void IgnoreCopyResult(scoped_ptr<CopyOutputResult> result) {
2129 TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
2130 scoped_ptr<DiscardCheckingContext> context_owned(new DiscardCheckingContext);
2131 FakeOutputSurfaceClient output_surface_client;
2132 scoped_ptr<OutputSurface> output_surface(
2133 FakeOutputSurface::Create3d(context_owned.Pass()));
2134 CHECK(output_surface->BindToClient(&output_surface_client));
2136 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
2137 new TestSharedBitmapManager());
2138 scoped_ptr<ResourceProvider> resource_provider(ResourceProvider::Create(
2139 output_surface.get(), shared_bitmap_manager.get(), NULL, NULL, 0, false,
2140 1));
2141 scoped_ptr<TextureMailboxDeleter> mailbox_deleter(
2142 new TextureMailboxDeleter(base::ThreadTaskRunnerHandle::Get()));
2144 RendererSettings settings;
2145 FakeRendererClient renderer_client;
2146 FakeRendererGL renderer(&renderer_client, &settings, output_surface.get(),
2147 resource_provider.get(), mailbox_deleter.get());
2149 TestOverlayProcessor* processor =
2150 new TestOverlayProcessor(output_surface.get(), resource_provider.get());
2151 processor->Initialize();
2152 renderer.SetOverlayProcessor(processor);
2154 gfx::Rect viewport_rect(1, 1);
2155 TestRenderPass* root_pass =
2156 AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 0),
2157 viewport_rect, gfx::Transform());
2158 root_pass->has_transparent_background = false;
2159 root_pass->copy_requests.push_back(
2160 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreCopyResult)));
2162 unsigned sync_point = 0;
2163 TextureMailbox mailbox =
2164 TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
2165 mailbox.set_allow_overlay(true);
2166 scoped_ptr<SingleReleaseCallbackImpl> release_callback =
2167 SingleReleaseCallbackImpl::Create(base::Bind(&MailboxReleased));
2168 ResourceProvider::ResourceId resource_id =
2169 resource_provider->CreateResourceFromTextureMailbox(
2170 mailbox, release_callback.Pass());
2171 bool premultiplied_alpha = false;
2172 bool flipped = false;
2173 bool nearest_neighbor = false;
2174 float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
2176 TextureDrawQuad* overlay_quad =
2177 root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
2178 overlay_quad->SetNew(root_pass->CreateAndAppendSharedQuadState(),
2179 viewport_rect, viewport_rect, viewport_rect, resource_id,
2180 premultiplied_alpha, gfx::PointF(0, 0),
2181 gfx::PointF(1, 1), SK_ColorTRANSPARENT, vertex_opacity,
2182 flipped, nearest_neighbor);
2184 // DirectRenderer::DrawFrame calls into OverlayProcessor::ProcessForOverlays.
2185 // Attempt will be called for each strategy in OverlayProcessor. We have
2186 // added a fake strategy, so checking for Attempt calls checks if there was
2187 // any attempt to overlay, which there shouldn't be. We can't use the quad
2188 // list because the render pass is cleaned up by DrawFrame.
2189 EXPECT_CALL(*processor->strategy_, Attempt(_, _)).Times(0);
2190 renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_rect,
2191 viewport_rect, false);
2192 Mock::VerifyAndClearExpectations(processor->strategy_);
2194 // Without a copy request Attempt() should be called once.
2195 root_pass = AddRenderPass(&render_passes_in_draw_order_, RenderPassId(1, 0),
2196 viewport_rect, gfx::Transform());
2197 root_pass->has_transparent_background = false;
2199 overlay_quad = root_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
2200 overlay_quad->SetNew(root_pass->CreateAndAppendSharedQuadState(),
2201 viewport_rect, viewport_rect, viewport_rect, resource_id,
2202 premultiplied_alpha, gfx::PointF(0, 0),
2203 gfx::PointF(1, 1), SK_ColorTRANSPARENT, vertex_opacity,
2204 flipped, nearest_neighbor);
2206 EXPECT_CALL(*processor->strategy_, Attempt(_, _)).Times(1);
2207 renderer.DrawFrame(&render_passes_in_draw_order_, 1.f, viewport_rect,
2208 viewport_rect, false);
2211 } // namespace
2212 } // namespace cc