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