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