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