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