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