Home | History | Annotate | Download | only in trees
      1 // Copyright 2011 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/trees/layer_tree_host_impl.h"
      6 
      7 #include <cmath>
      8 
      9 #include "base/bind.h"
     10 #include "base/command_line.h"
     11 #include "base/containers/hash_tables.h"
     12 #include "cc/base/math_util.h"
     13 #include "cc/input/top_controls_manager.h"
     14 #include "cc/layers/delegated_renderer_layer_impl.h"
     15 #include "cc/layers/heads_up_display_layer_impl.h"
     16 #include "cc/layers/io_surface_layer_impl.h"
     17 #include "cc/layers/layer_impl.h"
     18 #include "cc/layers/quad_sink.h"
     19 #include "cc/layers/render_surface_impl.h"
     20 #include "cc/layers/scrollbar_layer_impl.h"
     21 #include "cc/layers/solid_color_layer_impl.h"
     22 #include "cc/layers/texture_layer_impl.h"
     23 #include "cc/layers/tiled_layer_impl.h"
     24 #include "cc/layers/video_layer_impl.h"
     25 #include "cc/output/begin_frame_args.h"
     26 #include "cc/output/compositor_frame_ack.h"
     27 #include "cc/output/compositor_frame_metadata.h"
     28 #include "cc/output/gl_renderer.h"
     29 #include "cc/quads/render_pass_draw_quad.h"
     30 #include "cc/quads/solid_color_draw_quad.h"
     31 #include "cc/quads/texture_draw_quad.h"
     32 #include "cc/quads/tile_draw_quad.h"
     33 #include "cc/resources/layer_tiling_data.h"
     34 #include "cc/test/animation_test_common.h"
     35 #include "cc/test/fake_output_surface.h"
     36 #include "cc/test/fake_proxy.h"
     37 #include "cc/test/fake_rendering_stats_instrumentation.h"
     38 #include "cc/test/fake_video_frame_provider.h"
     39 #include "cc/test/geometry_test_utils.h"
     40 #include "cc/test/layer_test_common.h"
     41 #include "cc/test/render_pass_test_common.h"
     42 #include "cc/test/test_web_graphics_context_3d.h"
     43 #include "cc/trees/layer_tree_impl.h"
     44 #include "cc/trees/single_thread_proxy.h"
     45 #include "media/base/media.h"
     46 #include "testing/gmock/include/gmock/gmock.h"
     47 #include "testing/gtest/include/gtest/gtest.h"
     48 #include "ui/gfx/size_conversions.h"
     49 #include "ui/gfx/vector2d_conversions.h"
     50 
     51 using ::testing::Mock;
     52 using ::testing::Return;
     53 using ::testing::AnyNumber;
     54 using ::testing::AtLeast;
     55 using ::testing::_;
     56 using media::VideoFrame;
     57 
     58 namespace cc {
     59 namespace {
     60 
     61 class LayerTreeHostImplTest : public testing::Test,
     62                               public LayerTreeHostImplClient {
     63  public:
     64   LayerTreeHostImplTest()
     65       : proxy_(),
     66         always_impl_thread_(&proxy_),
     67         always_main_thread_blocked_(&proxy_),
     68         did_try_initialize_renderer_(false),
     69         on_can_draw_state_changed_called_(false),
     70         has_pending_tree_(false),
     71         did_request_commit_(false),
     72         did_request_redraw_(false),
     73         did_upload_visible_tile_(false),
     74         reduce_memory_result_(true),
     75         current_limit_bytes_(0),
     76         current_priority_cutoff_value_(0) {
     77     media::InitializeMediaLibraryForTesting();
     78   }
     79 
     80   virtual void SetUp() OVERRIDE {
     81     LayerTreeSettings settings;
     82     settings.minimum_occlusion_tracking_size = gfx::Size();
     83     settings.impl_side_painting = true;
     84     settings.solid_color_scrollbars = true;
     85 
     86     host_impl_ = LayerTreeHostImpl::Create(settings,
     87                                            this,
     88                                            &proxy_,
     89                                            &stats_instrumentation_);
     90     host_impl_->InitializeRenderer(CreateOutputSurface());
     91     host_impl_->SetViewportSize(gfx::Size(10, 10));
     92   }
     93 
     94   virtual void TearDown() OVERRIDE {}
     95 
     96   virtual void DidTryInitializeRendererOnImplThread(
     97       bool success,
     98       scoped_refptr<ContextProvider> offscreen_context_provider) OVERRIDE {
     99     did_try_initialize_renderer_ = true;
    100   }
    101   virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE {}
    102   virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {}
    103   virtual void BeginFrameOnImplThread(const BeginFrameArgs& args)
    104       OVERRIDE {}
    105   virtual void OnCanDrawStateChanged(bool can_draw) OVERRIDE {
    106     on_can_draw_state_changed_called_ = true;
    107   }
    108   virtual void OnHasPendingTreeStateChanged(bool has_pending_tree) OVERRIDE {
    109     has_pending_tree_ = has_pending_tree;
    110   }
    111   virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
    112     did_request_redraw_ = true;
    113   }
    114   virtual void SetNeedsRedrawRectOnImplThread(gfx::Rect damage_rect) OVERRIDE {
    115     did_request_redraw_ = true;
    116   }
    117   virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
    118     did_upload_visible_tile_ = true;
    119   }
    120   virtual void SetNeedsCommitOnImplThread() OVERRIDE {
    121     did_request_commit_ = true;
    122   }
    123   virtual void PostAnimationEventsToMainThreadOnImplThread(
    124       scoped_ptr<AnimationEventsVector> events,
    125       base::Time wall_clock_time) OVERRIDE {}
    126   virtual bool ReduceContentsTextureMemoryOnImplThread(
    127       size_t limit_bytes, int priority_cutoff) OVERRIDE {
    128     current_limit_bytes_ = limit_bytes;
    129     current_priority_cutoff_value_ = priority_cutoff;
    130     return reduce_memory_result_;
    131   }
    132   virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE {}
    133   virtual void SendManagedMemoryStats() OVERRIDE {}
    134   virtual bool IsInsideDraw() OVERRIDE { return false; }
    135   virtual void RenewTreePriority() OVERRIDE {}
    136   virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay)
    137       OVERRIDE { requested_scrollbar_animation_delay_ = delay; }
    138   virtual void DidActivatePendingTree() OVERRIDE {}
    139 
    140   void set_reduce_memory_result(bool reduce_memory_result) {
    141     reduce_memory_result_ = reduce_memory_result;
    142   }
    143 
    144   void CreateLayerTreeHost(bool partial_swap,
    145                            scoped_ptr<OutputSurface> output_surface) {
    146     LayerTreeSettings settings;
    147     settings.minimum_occlusion_tracking_size = gfx::Size();
    148     settings.partial_swap_enabled = partial_swap;
    149 
    150     host_impl_ = LayerTreeHostImpl::Create(settings,
    151                                            this,
    152                                            &proxy_,
    153                                            &stats_instrumentation_);
    154 
    155     host_impl_->InitializeRenderer(output_surface.Pass());
    156     host_impl_->SetViewportSize(gfx::Size(10, 10));
    157   }
    158 
    159   void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
    160     root->SetAnchorPoint(gfx::PointF());
    161     root->SetPosition(gfx::PointF());
    162     root->SetBounds(gfx::Size(10, 10));
    163     root->SetContentBounds(gfx::Size(10, 10));
    164     root->SetDrawsContent(true);
    165     root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
    166     host_impl_->active_tree()->SetRootLayer(root.Pass());
    167   }
    168 
    169   static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
    170     ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
    171     for (size_t i = 0; i < layer->children().size(); ++i)
    172       ExpectClearedScrollDeltasRecursive(layer->children()[i]);
    173   }
    174 
    175   static void ExpectContains(const ScrollAndScaleSet& scroll_info,
    176                              int id,
    177                              gfx::Vector2d scroll_delta) {
    178     int times_encountered = 0;
    179 
    180     for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
    181       if (scroll_info.scrolls[i].layer_id != id)
    182         continue;
    183       EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
    184       times_encountered++;
    185     }
    186 
    187     ASSERT_EQ(times_encountered, 1);
    188   }
    189 
    190   static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
    191     int times_encountered = 0;
    192 
    193     for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
    194       if (scroll_info.scrolls[i].layer_id != id)
    195         continue;
    196       times_encountered++;
    197     }
    198 
    199     ASSERT_EQ(0, times_encountered);
    200   }
    201 
    202   LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
    203                                            gfx::Size content_size) {
    204     scoped_ptr<LayerImpl> root =
    205         LayerImpl::Create(layer_tree_impl, 1);
    206     root->SetBounds(content_size);
    207     root->SetContentBounds(content_size);
    208     root->SetPosition(gfx::PointF());
    209     root->SetAnchorPoint(gfx::PointF());
    210 
    211     scoped_ptr<LayerImpl> scroll =
    212         LayerImpl::Create(layer_tree_impl, 2);
    213     LayerImpl* scroll_layer = scroll.get();
    214     scroll->SetScrollable(true);
    215     scroll->SetScrollOffset(gfx::Vector2d());
    216     scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
    217                                              content_size.height()));
    218     scroll->SetBounds(content_size);
    219     scroll->SetContentBounds(content_size);
    220     scroll->SetPosition(gfx::PointF());
    221     scroll->SetAnchorPoint(gfx::PointF());
    222 
    223     scoped_ptr<LayerImpl> contents =
    224         LayerImpl::Create(layer_tree_impl, 3);
    225     contents->SetDrawsContent(true);
    226     contents->SetBounds(content_size);
    227     contents->SetContentBounds(content_size);
    228     contents->SetPosition(gfx::PointF());
    229     contents->SetAnchorPoint(gfx::PointF());
    230 
    231     scroll->AddChild(contents.Pass());
    232     root->AddChild(scroll.Pass());
    233 
    234     layer_tree_impl->SetRootLayer(root.Pass());
    235     return scroll_layer;
    236   }
    237 
    238   LayerImpl* SetupScrollAndContentsLayers(gfx::Size content_size) {
    239     LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
    240         host_impl_->active_tree(), content_size);
    241     host_impl_->active_tree()->DidBecomeActive();
    242     return scroll_layer;
    243   }
    244 
    245   scoped_ptr<LayerImpl> CreateScrollableLayer(int id, gfx::Size size) {
    246     scoped_ptr<LayerImpl> layer =
    247         LayerImpl::Create(host_impl_->active_tree(), id);
    248     layer->SetScrollable(true);
    249     layer->SetDrawsContent(true);
    250     layer->SetBounds(size);
    251     layer->SetContentBounds(size);
    252     layer->SetMaxScrollOffset(gfx::Vector2d(size.width() * 2,
    253                                             size.height() * 2));
    254     return layer.Pass();
    255   }
    256 
    257   void InitializeRendererAndDrawFrame() {
    258     host_impl_->InitializeRenderer(CreateOutputSurface());
    259     DrawFrame();
    260   }
    261 
    262   void DrawFrame() {
    263     LayerTreeHostImpl::FrameData frame;
    264     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
    265     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
    266     host_impl_->DidDrawAllLayers(frame);
    267   }
    268 
    269   void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
    270   void pinch_zoom_pan_viewport_test(float device_scale_factor);
    271   void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
    272   void pinch_zoom_pan_viewport_and_scroll_boundary_test(
    273       float device_scale_factor);
    274 
    275   void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
    276     // Note: It is not possible to disable the renderer once it has been set,
    277     // so we do not need to test that disabling the renderer notifies us
    278     // that can_draw changed.
    279     EXPECT_FALSE(host_impl_->CanDraw());
    280     on_can_draw_state_changed_called_ = false;
    281 
    282     // Set up the root layer, which allows us to draw.
    283     SetupScrollAndContentsLayers(gfx::Size(100, 100));
    284     EXPECT_TRUE(host_impl_->CanDraw());
    285     EXPECT_TRUE(on_can_draw_state_changed_called_);
    286     on_can_draw_state_changed_called_ = false;
    287 
    288     // Toggle the root layer to make sure it toggles can_draw
    289     host_impl_->active_tree()->SetRootLayer(scoped_ptr<LayerImpl>());
    290     EXPECT_FALSE(host_impl_->CanDraw());
    291     EXPECT_TRUE(on_can_draw_state_changed_called_);
    292     on_can_draw_state_changed_called_ = false;
    293 
    294     SetupScrollAndContentsLayers(gfx::Size(100, 100));
    295     EXPECT_TRUE(host_impl_->CanDraw());
    296     EXPECT_TRUE(on_can_draw_state_changed_called_);
    297     on_can_draw_state_changed_called_ = false;
    298 
    299     // Toggle the device viewport size to make sure it toggles can_draw.
    300     host_impl_->SetViewportSize(gfx::Size());
    301     if (always_draw) {
    302       EXPECT_TRUE(host_impl_->CanDraw());
    303     } else {
    304       EXPECT_FALSE(host_impl_->CanDraw());
    305     }
    306     EXPECT_TRUE(on_can_draw_state_changed_called_);
    307     on_can_draw_state_changed_called_ = false;
    308 
    309     host_impl_->SetViewportSize(gfx::Size(100, 100));
    310     EXPECT_TRUE(host_impl_->CanDraw());
    311     EXPECT_TRUE(on_can_draw_state_changed_called_);
    312     on_can_draw_state_changed_called_ = false;
    313 
    314     // Toggle contents textures purged without causing any evictions,
    315     // and make sure that it does not change can_draw.
    316     set_reduce_memory_result(false);
    317     host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
    318         host_impl_->memory_allocation_limit_bytes() - 1));
    319     host_impl_->SetDiscardBackBufferWhenNotVisible(true);
    320     EXPECT_TRUE(host_impl_->CanDraw());
    321     EXPECT_FALSE(on_can_draw_state_changed_called_);
    322     on_can_draw_state_changed_called_ = false;
    323 
    324     // Toggle contents textures purged to make sure it toggles can_draw.
    325     set_reduce_memory_result(true);
    326     host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
    327         host_impl_->memory_allocation_limit_bytes() - 1));
    328     host_impl_->SetDiscardBackBufferWhenNotVisible(true);
    329     if (always_draw) {
    330       EXPECT_TRUE(host_impl_->CanDraw());
    331     } else {
    332       EXPECT_FALSE(host_impl_->CanDraw());
    333     }
    334     EXPECT_TRUE(on_can_draw_state_changed_called_);
    335     on_can_draw_state_changed_called_ = false;
    336 
    337     host_impl_->active_tree()->ResetContentsTexturesPurged();
    338     EXPECT_TRUE(host_impl_->CanDraw());
    339     EXPECT_TRUE(on_can_draw_state_changed_called_);
    340     on_can_draw_state_changed_called_ = false;
    341   }
    342 
    343  protected:
    344   virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
    345     return CreateFakeOutputSurface();
    346   }
    347 
    348   void DrawOneFrame() {
    349     LayerTreeHostImpl::FrameData frame_data;
    350     host_impl_->PrepareToDraw(&frame_data, gfx::Rect());
    351     host_impl_->DidDrawAllLayers(frame_data);
    352   }
    353 
    354   FakeProxy proxy_;
    355   DebugScopedSetImplThread always_impl_thread_;
    356   DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
    357 
    358   scoped_ptr<LayerTreeHostImpl> host_impl_;
    359   FakeRenderingStatsInstrumentation stats_instrumentation_;
    360   bool did_try_initialize_renderer_;
    361   bool on_can_draw_state_changed_called_;
    362   bool has_pending_tree_;
    363   bool did_request_commit_;
    364   bool did_request_redraw_;
    365   bool did_upload_visible_tile_;
    366   bool reduce_memory_result_;
    367   base::TimeDelta requested_scrollbar_animation_delay_;
    368   size_t current_limit_bytes_;
    369   int current_priority_cutoff_value_;
    370 };
    371 
    372 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
    373   bool always_draw = false;
    374   CheckNotifyCalledIfCanDrawChanged(always_draw);
    375 }
    376 
    377 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
    378   LayerTreeSettings settings;
    379   settings.impl_side_painting = true;
    380   host_impl_ = LayerTreeHostImpl::Create(
    381       settings, this, &proxy_, &stats_instrumentation_);
    382   host_impl_->InitializeRenderer(
    383       FakeOutputSurface::CreateAlwaysDrawAndSwap3d().PassAs<OutputSurface>());
    384   host_impl_->SetViewportSize(gfx::Size(10, 10));
    385 
    386   bool always_draw = true;
    387   CheckNotifyCalledIfCanDrawChanged(always_draw);
    388 }
    389 
    390 class TestWebGraphicsContext3DMakeCurrentFails
    391     : public TestWebGraphicsContext3D {
    392  public:
    393   virtual bool makeContextCurrent() OVERRIDE { return false; }
    394 };
    395 
    396 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
    397   ASSERT_FALSE(host_impl_->active_tree()->root_layer());
    398 
    399   scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
    400   ASSERT_EQ(scroll_info->scrolls.size(), 0u);
    401 }
    402 
    403 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
    404   {
    405     scoped_ptr<LayerImpl> root =
    406         LayerImpl::Create(host_impl_->active_tree(), 1);
    407     root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
    408     root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
    409     root->children()[1]->AddChild(
    410         LayerImpl::Create(host_impl_->active_tree(), 4));
    411     root->children()[1]->AddChild(
    412         LayerImpl::Create(host_impl_->active_tree(), 5));
    413     root->children()[1]->children()[0]->AddChild(
    414         LayerImpl::Create(host_impl_->active_tree(), 6));
    415     host_impl_->active_tree()->SetRootLayer(root.Pass());
    416   }
    417   LayerImpl* root = host_impl_->active_tree()->root_layer();
    418 
    419   ExpectClearedScrollDeltasRecursive(root);
    420 
    421   scoped_ptr<ScrollAndScaleSet> scroll_info;
    422 
    423   scroll_info = host_impl_->ProcessScrollDeltas();
    424   ASSERT_EQ(scroll_info->scrolls.size(), 0u);
    425   ExpectClearedScrollDeltasRecursive(root);
    426 
    427   scroll_info = host_impl_->ProcessScrollDeltas();
    428   ASSERT_EQ(scroll_info->scrolls.size(), 0u);
    429   ExpectClearedScrollDeltasRecursive(root);
    430 }
    431 
    432 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
    433   gfx::Vector2d scroll_offset(20, 30);
    434   gfx::Vector2d scroll_delta(11, -15);
    435   {
    436     scoped_ptr<LayerImpl> root =
    437         LayerImpl::Create(host_impl_->active_tree(), 1);
    438     root->SetMaxScrollOffset(gfx::Vector2d(100, 100));
    439     root->SetScrollOffset(scroll_offset);
    440     root->SetScrollable(true);
    441     root->ScrollBy(scroll_delta);
    442     host_impl_->active_tree()->SetRootLayer(root.Pass());
    443   }
    444   LayerImpl* root = host_impl_->active_tree()->root_layer();
    445 
    446   scoped_ptr<ScrollAndScaleSet> scroll_info;
    447 
    448   scroll_info = host_impl_->ProcessScrollDeltas();
    449   ASSERT_EQ(scroll_info->scrolls.size(), 1u);
    450   EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta);
    451   ExpectContains(*scroll_info, root->id(), scroll_delta);
    452 
    453   gfx::Vector2d scroll_delta2(-5, 27);
    454   root->ScrollBy(scroll_delta2);
    455   scroll_info = host_impl_->ProcessScrollDeltas();
    456   ASSERT_EQ(scroll_info->scrolls.size(), 1u);
    457   EXPECT_VECTOR_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
    458   ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
    459 
    460   root->ScrollBy(gfx::Vector2d());
    461   scroll_info = host_impl_->ProcessScrollDeltas();
    462   EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
    463 }
    464 
    465 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
    466   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    467   host_impl_->SetViewportSize(gfx::Size(50, 50));
    468   InitializeRendererAndDrawFrame();
    469 
    470   EXPECT_EQ(InputHandler::ScrollStarted,
    471             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
    472   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
    473   host_impl_->ScrollEnd();
    474   EXPECT_TRUE(did_request_redraw_);
    475   EXPECT_TRUE(did_request_commit_);
    476 }
    477 
    478 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
    479   // We should not crash when trying to scroll an empty layer tree.
    480   EXPECT_EQ(InputHandler::ScrollIgnored,
    481             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
    482 }
    483 
    484 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
    485   LayerTreeSettings settings;
    486   host_impl_ = LayerTreeHostImpl::Create(settings,
    487                                          this,
    488                                          &proxy_,
    489                                          &stats_instrumentation_);
    490 
    491   // Initialization will fail here.
    492   host_impl_->InitializeRenderer(FakeOutputSurface::Create3d(
    493       scoped_ptr<WebKit::WebGraphicsContext3D>(
    494           new TestWebGraphicsContext3DMakeCurrentFails))
    495       .PassAs<OutputSurface>());
    496   host_impl_->SetViewportSize(gfx::Size(10, 10));
    497 
    498   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    499 
    500   // We should not crash when trying to scroll after the renderer initialization
    501   // fails.
    502   EXPECT_EQ(InputHandler::ScrollIgnored,
    503             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
    504 }
    505 
    506 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
    507   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
    508   host_impl_->SetViewportSize(gfx::Size(50, 50));
    509   InitializeRendererAndDrawFrame();
    510 
    511   // We should not crash if the tree is replaced while we are scrolling.
    512   EXPECT_EQ(InputHandler::ScrollStarted,
    513             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
    514   host_impl_->active_tree()->DetachLayerTree();
    515 
    516   scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
    517 
    518   // We should still be scrolling, because the scrolled layer also exists in the
    519   // new tree.
    520   gfx::Vector2d scroll_delta(0, 10);
    521   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
    522   host_impl_->ScrollEnd();
    523   scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
    524   ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
    525 }
    526 
    527 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
    528   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    529   host_impl_->SetViewportSize(gfx::Size(50, 50));
    530   InitializeRendererAndDrawFrame();
    531 
    532   // We should be able to scroll even if the root layer loses its render surface
    533   // after the most recent render.
    534   host_impl_->active_tree()->root_layer()->ClearRenderSurface();
    535   host_impl_->active_tree()->set_needs_update_draw_properties();
    536 
    537   EXPECT_EQ(InputHandler::ScrollStarted,
    538             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
    539 }
    540 
    541 TEST_F(LayerTreeHostImplTest, WheelEventHandlers) {
    542   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    543   host_impl_->SetViewportSize(gfx::Size(50, 50));
    544   InitializeRendererAndDrawFrame();
    545   LayerImpl* root = host_impl_->active_tree()->root_layer();
    546 
    547   root->SetHaveWheelEventHandlers(true);
    548 
    549   // With registered event handlers, wheel scrolls have to go to the main
    550   // thread.
    551   EXPECT_EQ(InputHandler::ScrollOnMainThread,
    552             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
    553 
    554   // But gesture scrolls can still be handled.
    555   EXPECT_EQ(InputHandler::ScrollStarted,
    556             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
    557 }
    558 
    559 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
    560   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    561   host_impl_->SetViewportSize(gfx::Size(50, 50));
    562   InitializeRendererAndDrawFrame();
    563 
    564   // Ignore the fling since no layer is being scrolled
    565   EXPECT_EQ(InputHandler::ScrollIgnored,
    566             host_impl_->FlingScrollBegin());
    567 
    568   // Start scrolling a layer
    569   EXPECT_EQ(InputHandler::ScrollStarted,
    570             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
    571 
    572   // Now the fling should go ahead since we've started scrolling a layer
    573   EXPECT_EQ(InputHandler::ScrollStarted,
    574             host_impl_->FlingScrollBegin());
    575 }
    576 
    577 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
    578   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    579   host_impl_->SetViewportSize(gfx::Size(50, 50));
    580   InitializeRendererAndDrawFrame();
    581 
    582   // Ignore the fling since no layer is being scrolled
    583   EXPECT_EQ(InputHandler::ScrollIgnored,
    584             host_impl_->FlingScrollBegin());
    585 
    586   // Start scrolling a layer
    587   EXPECT_EQ(InputHandler::ScrollStarted,
    588             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
    589 
    590   // Now the fling should go ahead since we've started scrolling a layer
    591   EXPECT_EQ(InputHandler::ScrollStarted,
    592             host_impl_->FlingScrollBegin());
    593 }
    594 
    595 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
    596   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    597   host_impl_->SetViewportSize(gfx::Size(50, 50));
    598   InitializeRendererAndDrawFrame();
    599   LayerImpl* root = host_impl_->active_tree()->root_layer();
    600 
    601   root->SetShouldScrollOnMainThread(true);
    602 
    603   // Start scrolling a layer
    604   EXPECT_EQ(InputHandler::ScrollOnMainThread,
    605             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
    606 
    607   // The fling should be ignored since there's no layer being scrolled impl-side
    608   EXPECT_EQ(InputHandler::ScrollIgnored,
    609             host_impl_->FlingScrollBegin());
    610 }
    611 
    612 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
    613   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    614   host_impl_->SetViewportSize(gfx::Size(50, 50));
    615   InitializeRendererAndDrawFrame();
    616   LayerImpl* root = host_impl_->active_tree()->root_layer();
    617 
    618   root->SetShouldScrollOnMainThread(true);
    619 
    620   EXPECT_EQ(InputHandler::ScrollOnMainThread,
    621             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
    622   EXPECT_EQ(InputHandler::ScrollOnMainThread,
    623             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
    624 }
    625 
    626 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
    627   SetupScrollAndContentsLayers(gfx::Size(200, 200));
    628   host_impl_->SetViewportSize(gfx::Size(100, 100));
    629 
    630   LayerImpl* root = host_impl_->active_tree()->root_layer();
    631   root->SetContentsScale(2.f, 2.f);
    632   root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
    633 
    634   InitializeRendererAndDrawFrame();
    635 
    636   // All scroll types inside the non-fast scrollable region should fail.
    637   EXPECT_EQ(InputHandler::ScrollOnMainThread,
    638             host_impl_->ScrollBegin(gfx::Point(25, 25),
    639                                     InputHandler::Wheel));
    640   EXPECT_EQ(InputHandler::ScrollOnMainThread,
    641             host_impl_->ScrollBegin(gfx::Point(25, 25),
    642                                     InputHandler::Gesture));
    643 
    644   // All scroll types outside this region should succeed.
    645   EXPECT_EQ(InputHandler::ScrollStarted,
    646             host_impl_->ScrollBegin(gfx::Point(75, 75),
    647                                     InputHandler::Wheel));
    648   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
    649   host_impl_->ScrollEnd();
    650   EXPECT_EQ(InputHandler::ScrollStarted,
    651             host_impl_->ScrollBegin(gfx::Point(75, 75),
    652                                     InputHandler::Gesture));
    653   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
    654   host_impl_->ScrollEnd();
    655 }
    656 
    657 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
    658   SetupScrollAndContentsLayers(gfx::Size(200, 200));
    659   host_impl_->SetViewportSize(gfx::Size(100, 100));
    660 
    661   LayerImpl* root = host_impl_->active_tree()->root_layer();
    662   root->SetContentsScale(2.f, 2.f);
    663   root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
    664   root->SetPosition(gfx::PointF(-25.f, 0.f));
    665 
    666   InitializeRendererAndDrawFrame();
    667 
    668   // This point would fall into the non-fast scrollable region except that we've
    669   // moved the layer down by 25 pixels.
    670   EXPECT_EQ(InputHandler::ScrollStarted,
    671             host_impl_->ScrollBegin(gfx::Point(40, 10),
    672                                     InputHandler::Wheel));
    673   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
    674   host_impl_->ScrollEnd();
    675 
    676   // This point is still inside the non-fast region.
    677   EXPECT_EQ(InputHandler::ScrollOnMainThread,
    678             host_impl_->ScrollBegin(gfx::Point(10, 10),
    679                                     InputHandler::Wheel));
    680 }
    681 
    682 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
    683   SetupScrollAndContentsLayers(gfx::Size(200, 200));
    684   host_impl_->SetViewportSize(gfx::Size(100, 100));
    685 
    686   InitializeRendererAndDrawFrame();
    687 
    688   EXPECT_EQ(InputHandler::ScrollStarted,
    689             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
    690 
    691   // Trying to scroll to the left/top will not succeed.
    692   EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
    693   EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
    694   EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
    695 
    696   // Scrolling to the right/bottom will succeed.
    697   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
    698   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
    699   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
    700 
    701   // Scrolling to left/top will now succeed.
    702   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
    703   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
    704   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
    705 
    706   // Scrolling diagonally against an edge will succeed.
    707   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
    708   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
    709   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
    710 
    711   // Trying to scroll more than the available space will also succeed.
    712   EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
    713 }
    714 
    715 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
    716   SetupScrollAndContentsLayers(gfx::Size(200, 2000));
    717   host_impl_->SetViewportSize(gfx::Size(100, 1000));
    718 
    719   InitializeRendererAndDrawFrame();
    720 
    721   EXPECT_EQ(InputHandler::ScrollStarted,
    722             host_impl_->ScrollBegin(gfx::Point(),
    723                                     InputHandler::Wheel));
    724 
    725   // Trying to scroll without a vertical scrollbar will fail.
    726   EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
    727       gfx::Point(), SCROLL_FORWARD));
    728   EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
    729       gfx::Point(), SCROLL_BACKWARD));
    730 
    731   scoped_ptr<cc::ScrollbarLayerImpl> vertical_scrollbar(
    732       cc::ScrollbarLayerImpl::Create(
    733           host_impl_->active_tree(),
    734           20,
    735           VERTICAL));
    736   vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
    737   host_impl_->RootScrollLayer()->SetVerticalScrollbarLayer(
    738       vertical_scrollbar.get());
    739 
    740   // Trying to scroll with a vertical scrollbar will succeed.
    741   EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
    742       gfx::Point(), SCROLL_FORWARD));
    743   EXPECT_FLOAT_EQ(875.f, host_impl_->RootScrollLayer()->ScrollDelta().y());
    744   EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
    745       gfx::Point(), SCROLL_BACKWARD));
    746 }
    747 
    748 TEST_F(LayerTreeHostImplTest,
    749        ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
    750   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    751   host_impl_->SetViewportSize(gfx::Size(50, 50));
    752   InitializeRendererAndDrawFrame();
    753 
    754   // We should be able to hit test for touch event handlers even if the root
    755   // layer loses its render surface after the most recent render.
    756   host_impl_->active_tree()->root_layer()->ClearRenderSurface();
    757   host_impl_->active_tree()->set_needs_update_draw_properties();
    758 
    759   EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
    760 }
    761 
    762 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
    763   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
    764   host_impl_->SetViewportSize(gfx::Size(50, 50));
    765   InitializeRendererAndDrawFrame();
    766 
    767   EXPECT_EQ(scroll_layer, host_impl_->RootScrollLayer());
    768 
    769   float min_page_scale = 1.f, max_page_scale = 4.f;
    770 
    771   // The impl-based pinch zoom should adjust the max scroll position.
    772   {
    773     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
    774                                                            min_page_scale,
    775                                                            max_page_scale);
    776     host_impl_->active_tree()->SetPageScaleDelta(1.f);
    777     scroll_layer->SetScrollDelta(gfx::Vector2d());
    778 
    779     float page_scale_delta = 2.f;
    780     host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
    781     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
    782     host_impl_->PinchGestureEnd();
    783     host_impl_->ScrollEnd();
    784     EXPECT_TRUE(did_request_redraw_);
    785     EXPECT_TRUE(did_request_commit_);
    786 
    787     scoped_ptr<ScrollAndScaleSet> scroll_info =
    788         host_impl_->ProcessScrollDeltas();
    789     EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
    790 
    791     EXPECT_EQ(gfx::Vector2d(75, 75).ToString(),
    792               scroll_layer->max_scroll_offset().ToString());
    793   }
    794 
    795   // Scrolling after a pinch gesture should always be in local space.  The
    796   // scroll deltas do not have the page scale factor applied.
    797   {
    798     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
    799                                                            min_page_scale,
    800                                                            max_page_scale);
    801     host_impl_->active_tree()->SetPageScaleDelta(1.f);
    802     scroll_layer->SetScrollDelta(gfx::Vector2d());
    803 
    804     float page_scale_delta = 2.f;
    805     host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
    806     host_impl_->PinchGestureBegin();
    807     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
    808     host_impl_->PinchGestureEnd();
    809     host_impl_->ScrollEnd();
    810 
    811     gfx::Vector2d scroll_delta(0, 10);
    812     EXPECT_EQ(InputHandler::ScrollStarted,
    813               host_impl_->ScrollBegin(gfx::Point(5, 5),
    814                                       InputHandler::Wheel));
    815     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
    816     host_impl_->ScrollEnd();
    817 
    818     scoped_ptr<ScrollAndScaleSet> scroll_info =
    819         host_impl_->ProcessScrollDeltas();
    820     ExpectContains(*scroll_info.get(),
    821                    scroll_layer->id(),
    822                    scroll_delta);
    823   }
    824 }
    825 
    826 TEST_F(LayerTreeHostImplTest, PinchGesture) {
    827   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    828   host_impl_->SetViewportSize(gfx::Size(50, 50));
    829   InitializeRendererAndDrawFrame();
    830 
    831   LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
    832   DCHECK(scroll_layer);
    833 
    834   float min_page_scale = 1.f;
    835   float max_page_scale = 4.f;
    836 
    837   // Basic pinch zoom in gesture
    838   {
    839     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
    840                                                            min_page_scale,
    841                                                            max_page_scale);
    842     scroll_layer->SetScrollDelta(gfx::Vector2d());
    843 
    844     float page_scale_delta = 2.f;
    845     host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
    846     host_impl_->PinchGestureBegin();
    847     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
    848     host_impl_->PinchGestureEnd();
    849     host_impl_->ScrollEnd();
    850     EXPECT_TRUE(did_request_redraw_);
    851     EXPECT_TRUE(did_request_commit_);
    852 
    853     scoped_ptr<ScrollAndScaleSet> scroll_info =
    854         host_impl_->ProcessScrollDeltas();
    855     EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
    856   }
    857 
    858   // Zoom-in clamping
    859   {
    860     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
    861                                                            min_page_scale,
    862                                                            max_page_scale);
    863     scroll_layer->SetScrollDelta(gfx::Vector2d());
    864     float page_scale_delta = 10.f;
    865 
    866     host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::Gesture);
    867     host_impl_->PinchGestureBegin();
    868     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
    869     host_impl_->PinchGestureEnd();
    870     host_impl_->ScrollEnd();
    871 
    872     scoped_ptr<ScrollAndScaleSet> scroll_info =
    873         host_impl_->ProcessScrollDeltas();
    874     EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
    875   }
    876 
    877   // Zoom-out clamping
    878   {
    879     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
    880                                                            min_page_scale,
    881                                                            max_page_scale);
    882     scroll_layer->SetScrollDelta(gfx::Vector2d());
    883     scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
    884 
    885     float page_scale_delta = 0.1f;
    886     host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
    887     host_impl_->PinchGestureBegin();
    888     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
    889     host_impl_->PinchGestureEnd();
    890     host_impl_->ScrollEnd();
    891 
    892     scoped_ptr<ScrollAndScaleSet> scroll_info =
    893         host_impl_->ProcessScrollDeltas();
    894     EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
    895 
    896     EXPECT_TRUE(scroll_info->scrolls.empty());
    897   }
    898 
    899   // Two-finger panning should not happen based on pinch events only
    900   {
    901     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
    902                                                            min_page_scale,
    903                                                            max_page_scale);
    904     scroll_layer->SetScrollDelta(gfx::Vector2d());
    905     scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
    906 
    907     float page_scale_delta = 1.f;
    908     host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
    909     host_impl_->PinchGestureBegin();
    910     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
    911     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
    912     host_impl_->PinchGestureEnd();
    913     host_impl_->ScrollEnd();
    914 
    915     scoped_ptr<ScrollAndScaleSet> scroll_info =
    916         host_impl_->ProcessScrollDeltas();
    917     EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
    918     EXPECT_TRUE(scroll_info->scrolls.empty());
    919   }
    920 
    921   // Two-finger panning should work with interleaved scroll events
    922   {
    923     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
    924                                                            min_page_scale,
    925                                                            max_page_scale);
    926     scroll_layer->SetScrollDelta(gfx::Vector2d());
    927     scroll_layer->SetScrollOffset(gfx::Vector2d(20, 20));
    928 
    929     float page_scale_delta = 1.f;
    930     host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::Gesture);
    931     host_impl_->PinchGestureBegin();
    932     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
    933     host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
    934     host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
    935     host_impl_->PinchGestureEnd();
    936     host_impl_->ScrollEnd();
    937 
    938     scoped_ptr<ScrollAndScaleSet> scroll_info =
    939         host_impl_->ProcessScrollDeltas();
    940     EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
    941     ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
    942   }
    943 
    944   // Two-finger panning should work when starting fully zoomed out.
    945   {
    946     host_impl_->active_tree()->SetPageScaleFactorAndLimits(0.5f,
    947                                                            0.5f,
    948                                                            4.f);
    949     scroll_layer->SetScrollDelta(gfx::Vector2d());
    950     scroll_layer->SetScrollOffset(gfx::Vector2d(0, 0));
    951     host_impl_->active_tree()->UpdateMaxScrollOffset();
    952 
    953     host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Gesture);
    954     host_impl_->PinchGestureBegin();
    955     host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
    956     host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
    957     host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
    958     host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
    959     host_impl_->PinchGestureEnd();
    960     host_impl_->ScrollEnd();
    961 
    962     scoped_ptr<ScrollAndScaleSet> scroll_info =
    963         host_impl_->ProcessScrollDeltas();
    964     EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
    965     ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
    966   }
    967 }
    968 
    969 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
    970   SetupScrollAndContentsLayers(gfx::Size(100, 100));
    971   host_impl_->SetViewportSize(gfx::Size(50, 50));
    972   InitializeRendererAndDrawFrame();
    973 
    974   LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
    975   DCHECK(scroll_layer);
    976 
    977   float min_page_scale = 0.5f;
    978   float max_page_scale = 4.f;
    979   base::TimeTicks start_time = base::TimeTicks() +
    980                                base::TimeDelta::FromSeconds(1);
    981   base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
    982   base::TimeTicks halfway_through_animation = start_time + duration / 2;
    983   base::TimeTicks end_time = start_time + duration;
    984 
    985   // Non-anchor zoom-in
    986   {
    987     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
    988                                                            min_page_scale,
    989                                                            max_page_scale);
    990     scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
    991 
    992     host_impl_->StartPageScaleAnimation(gfx::Vector2d(),
    993                                         false,
    994                                         2.f,
    995                                         start_time,
    996                                         duration);
    997     host_impl_->Animate(halfway_through_animation, base::Time());
    998     EXPECT_TRUE(did_request_redraw_);
    999     host_impl_->Animate(end_time, base::Time());
   1000     EXPECT_TRUE(did_request_commit_);
   1001 
   1002     scoped_ptr<ScrollAndScaleSet> scroll_info =
   1003         host_impl_->ProcessScrollDeltas();
   1004     EXPECT_EQ(scroll_info->page_scale_delta, 2);
   1005     ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
   1006   }
   1007 
   1008   // Anchor zoom-out
   1009   {
   1010     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
   1011                                                            min_page_scale,
   1012                                                            max_page_scale);
   1013     scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
   1014 
   1015     host_impl_->StartPageScaleAnimation(gfx::Vector2d(25, 25),
   1016                                         true,
   1017                                         min_page_scale,
   1018                                         start_time, duration);
   1019     host_impl_->Animate(end_time, base::Time());
   1020     EXPECT_TRUE(did_request_redraw_);
   1021     EXPECT_TRUE(did_request_commit_);
   1022 
   1023     scoped_ptr<ScrollAndScaleSet> scroll_info =
   1024         host_impl_->ProcessScrollDeltas();
   1025     EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
   1026     // Pushed to (0,0) via clamping against contents layer size.
   1027     ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
   1028   }
   1029 }
   1030 
   1031 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
   1032   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   1033   host_impl_->SetViewportSize(gfx::Size(50, 50));
   1034   InitializeRendererAndDrawFrame();
   1035 
   1036   LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
   1037   DCHECK(scroll_layer);
   1038 
   1039   float min_page_scale = 0.5f;
   1040   float max_page_scale = 4.f;
   1041   base::TimeTicks start_time = base::TimeTicks() +
   1042                                base::TimeDelta::FromSeconds(1);
   1043   base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
   1044   base::TimeTicks halfway_through_animation = start_time + duration / 2;
   1045   base::TimeTicks end_time = start_time + duration;
   1046 
   1047   // Anchor zoom with unchanged page scale should not change scroll or scale.
   1048   {
   1049     host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
   1050                                                            min_page_scale,
   1051                                                            max_page_scale);
   1052     scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
   1053 
   1054     host_impl_->StartPageScaleAnimation(gfx::Vector2d(),
   1055                                         true,
   1056                                         1.f,
   1057                                         start_time,
   1058                                         duration);
   1059     host_impl_->Animate(halfway_through_animation, base::Time());
   1060     EXPECT_TRUE(did_request_redraw_);
   1061     host_impl_->Animate(end_time, base::Time());
   1062     EXPECT_TRUE(did_request_commit_);
   1063 
   1064     scoped_ptr<ScrollAndScaleSet> scroll_info =
   1065         host_impl_->ProcessScrollDeltas();
   1066     EXPECT_EQ(scroll_info->page_scale_delta, 1);
   1067     ExpectNone(*scroll_info, scroll_layer->id());
   1068   }
   1069 }
   1070 
   1071 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
   1072  public:
   1073   LayerTreeHostImplOverridePhysicalTime(
   1074       const LayerTreeSettings& settings,
   1075       LayerTreeHostImplClient* client,
   1076       Proxy* proxy,
   1077       RenderingStatsInstrumentation* rendering_stats_instrumentation)
   1078       : LayerTreeHostImpl(settings,
   1079                           client,
   1080                           proxy,
   1081                           rendering_stats_instrumentation) {}
   1082 
   1083 
   1084   virtual base::TimeTicks CurrentPhysicalTimeTicks() const OVERRIDE {
   1085     return fake_current_physical_time_;
   1086   }
   1087 
   1088   void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
   1089     fake_current_physical_time_ = fake_now;
   1090   }
   1091 
   1092  private:
   1093   base::TimeTicks fake_current_physical_time_;
   1094 };
   1095 
   1096 TEST_F(LayerTreeHostImplTest, ScrollbarLinearFadeScheduling) {
   1097   LayerTreeSettings settings;
   1098   settings.use_linear_fade_scrollbar_animator = true;
   1099   settings.scrollbar_linear_fade_delay_ms = 20;
   1100   settings.scrollbar_linear_fade_length_ms = 20;
   1101 
   1102   gfx::Size viewport_size(10, 10);
   1103   gfx::Size content_size(100, 100);
   1104 
   1105   LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
   1106       new LayerTreeHostImplOverridePhysicalTime(
   1107           settings, this, &proxy_, &stats_instrumentation_);
   1108   host_impl_ = make_scoped_ptr<LayerTreeHostImpl>(host_impl_override_time);
   1109   host_impl_->InitializeRenderer(CreateOutputSurface());
   1110   host_impl_->SetViewportSize(viewport_size);
   1111 
   1112   scoped_ptr<LayerImpl> root =
   1113       LayerImpl::Create(host_impl_->active_tree(), 1);
   1114   root->SetBounds(viewport_size);
   1115 
   1116   scoped_ptr<LayerImpl> scroll =
   1117       LayerImpl::Create(host_impl_->active_tree(), 2);
   1118   scroll->SetScrollable(true);
   1119   scroll->SetScrollOffset(gfx::Vector2d());
   1120   scroll->SetMaxScrollOffset(gfx::Vector2d(content_size.width(),
   1121                                            content_size.height()));
   1122   scroll->SetBounds(content_size);
   1123   scroll->SetContentBounds(content_size);
   1124 
   1125   scoped_ptr<LayerImpl> contents =
   1126       LayerImpl::Create(host_impl_->active_tree(), 3);
   1127   contents->SetDrawsContent(true);
   1128   contents->SetBounds(content_size);
   1129   contents->SetContentBounds(content_size);
   1130 
   1131   scoped_ptr<ScrollbarLayerImpl> scrollbar = ScrollbarLayerImpl::Create(
   1132       host_impl_->active_tree(),
   1133       4,
   1134       VERTICAL);
   1135   scroll->SetVerticalScrollbarLayer(scrollbar.get());
   1136 
   1137   scroll->AddChild(contents.Pass());
   1138   root->AddChild(scroll.Pass());
   1139   root->AddChild(scrollbar.PassAs<LayerImpl>());
   1140 
   1141   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1142   host_impl_->active_tree()->DidBecomeActive();
   1143   InitializeRendererAndDrawFrame();
   1144 
   1145   base::TimeTicks fake_now = base::TimeTicks::Now();
   1146   host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
   1147 
   1148   // If no scroll happened recently, StartScrollbarAnimation should have no
   1149   // effect.
   1150   host_impl_->StartScrollbarAnimation();
   1151   EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
   1152   EXPECT_FALSE(did_request_redraw_);
   1153 
   1154   // After a scroll, a fade animation should be scheduled about 20ms from now.
   1155   host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel);
   1156   host_impl_->ScrollEnd();
   1157   host_impl_->StartScrollbarAnimation();
   1158   EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
   1159             requested_scrollbar_animation_delay_);
   1160   EXPECT_FALSE(did_request_redraw_);
   1161   requested_scrollbar_animation_delay_ = base::TimeDelta();
   1162 
   1163   // After the fade begins, we should start getting redraws instead of a
   1164   // scheduled animation.
   1165   fake_now += base::TimeDelta::FromMilliseconds(25);
   1166   host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
   1167   host_impl_->StartScrollbarAnimation();
   1168   EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
   1169   EXPECT_TRUE(did_request_redraw_);
   1170   did_request_redraw_ = false;
   1171 
   1172   // If no scroll happened recently, StartScrollbarAnimation should have no
   1173   // effect.
   1174   fake_now += base::TimeDelta::FromMilliseconds(25);
   1175   host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
   1176   host_impl_->StartScrollbarAnimation();
   1177   EXPECT_EQ(base::TimeDelta(), requested_scrollbar_animation_delay_);
   1178   EXPECT_FALSE(did_request_redraw_);
   1179 
   1180   // Setting the scroll offset outside a scroll should also cause the scrollbar
   1181   // to appear and to schedule a fade.
   1182   host_impl_->RootScrollLayer()->SetScrollOffset(gfx::Vector2d(5, 5));
   1183   host_impl_->StartScrollbarAnimation();
   1184   EXPECT_LT(base::TimeDelta::FromMilliseconds(19),
   1185             requested_scrollbar_animation_delay_);
   1186   EXPECT_FALSE(did_request_redraw_);
   1187   requested_scrollbar_animation_delay_ = base::TimeDelta();
   1188 
   1189   // None of the above should have called CurrentFrameTimeTicks, so if we call
   1190   // it now we should get the current time.
   1191   fake_now += base::TimeDelta::FromMilliseconds(10);
   1192   host_impl_override_time->SetCurrentPhysicalTimeTicksForTest(fake_now);
   1193   EXPECT_EQ(fake_now, host_impl_->CurrentFrameTimeTicks());
   1194 }
   1195 
   1196 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
   1197   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   1198   host_impl_->SetViewportSize(gfx::Size(50, 50));
   1199   host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
   1200   InitializeRendererAndDrawFrame();
   1201   {
   1202     CompositorFrameMetadata metadata =
   1203         host_impl_->MakeCompositorFrameMetadata();
   1204     EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
   1205     EXPECT_EQ(1.f, metadata.page_scale_factor);
   1206     EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.viewport_size);
   1207     EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
   1208     EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
   1209     EXPECT_EQ(4.f, metadata.max_page_scale_factor);
   1210   }
   1211 
   1212   // Scrolling should update metadata immediately.
   1213   EXPECT_EQ(InputHandler::ScrollStarted,
   1214             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
   1215   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
   1216   {
   1217     CompositorFrameMetadata metadata =
   1218         host_impl_->MakeCompositorFrameMetadata();
   1219     EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
   1220   }
   1221   host_impl_->ScrollEnd();
   1222   {
   1223     CompositorFrameMetadata metadata =
   1224         host_impl_->MakeCompositorFrameMetadata();
   1225     EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
   1226   }
   1227 
   1228   // Page scale should update metadata correctly (shrinking only the viewport).
   1229   host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
   1230   host_impl_->PinchGestureBegin();
   1231   host_impl_->PinchGestureUpdate(2.f, gfx::Point());
   1232   host_impl_->PinchGestureEnd();
   1233   host_impl_->ScrollEnd();
   1234   {
   1235     CompositorFrameMetadata metadata =
   1236         host_impl_->MakeCompositorFrameMetadata();
   1237     EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
   1238     EXPECT_EQ(2.f, metadata.page_scale_factor);
   1239     EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.viewport_size);
   1240     EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
   1241     EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
   1242     EXPECT_EQ(4.f, metadata.max_page_scale_factor);
   1243   }
   1244 
   1245   // Likewise if set from the main thread.
   1246   host_impl_->ProcessScrollDeltas();
   1247   host_impl_->active_tree()->SetPageScaleFactorAndLimits(4.f, 0.5f, 4.f);
   1248   host_impl_->active_tree()->SetPageScaleDelta(1.f);
   1249   {
   1250     CompositorFrameMetadata metadata =
   1251         host_impl_->MakeCompositorFrameMetadata();
   1252     EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
   1253     EXPECT_EQ(4.f, metadata.page_scale_factor);
   1254     EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.viewport_size);
   1255     EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
   1256     EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
   1257     EXPECT_EQ(4.f, metadata.max_page_scale_factor);
   1258   }
   1259 }
   1260 
   1261 class DidDrawCheckLayer : public TiledLayerImpl {
   1262  public:
   1263   static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
   1264     return scoped_ptr<LayerImpl>(new DidDrawCheckLayer(tree_impl, id));
   1265   }
   1266 
   1267   virtual bool WillDraw(DrawMode draw_mode, ResourceProvider* provider)
   1268       OVERRIDE {
   1269     will_draw_called_ = true;
   1270     if (will_draw_returns_false_)
   1271       return false;
   1272     return TiledLayerImpl::WillDraw(draw_mode, provider);
   1273   }
   1274 
   1275   virtual void AppendQuads(QuadSink* quad_sink,
   1276                            AppendQuadsData* append_quads_data) OVERRIDE {
   1277     append_quads_called_ = true;
   1278     TiledLayerImpl::AppendQuads(quad_sink, append_quads_data);
   1279   }
   1280 
   1281   virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
   1282     did_draw_called_ = true;
   1283     TiledLayerImpl::DidDraw(provider);
   1284   }
   1285 
   1286   bool will_draw_called() const { return will_draw_called_; }
   1287   bool append_quads_called() const { return append_quads_called_; }
   1288   bool did_draw_called() const { return did_draw_called_; }
   1289 
   1290   void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
   1291 
   1292   void ClearDidDrawCheck() {
   1293     will_draw_called_ = false;
   1294     append_quads_called_ = false;
   1295     did_draw_called_ = false;
   1296   }
   1297 
   1298  protected:
   1299   DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
   1300       : TiledLayerImpl(tree_impl, id),
   1301         will_draw_returns_false_(false),
   1302         will_draw_called_(false),
   1303         append_quads_called_(false),
   1304         did_draw_called_(false) {
   1305     SetAnchorPoint(gfx::PointF());
   1306     SetBounds(gfx::Size(10, 10));
   1307     SetContentBounds(gfx::Size(10, 10));
   1308     SetDrawsContent(true);
   1309     set_skips_draw(false);
   1310     draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
   1311 
   1312     scoped_ptr<LayerTilingData> tiler =
   1313         LayerTilingData::Create(gfx::Size(100, 100),
   1314                                 LayerTilingData::HAS_BORDER_TEXELS);
   1315     tiler->SetBounds(content_bounds());
   1316     SetTilingData(*tiler.get());
   1317   }
   1318 
   1319  private:
   1320   bool will_draw_returns_false_;
   1321   bool will_draw_called_;
   1322   bool append_quads_called_;
   1323   bool did_draw_called_;
   1324 };
   1325 
   1326 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
   1327   // The root layer is always drawn, so run this test on a child layer that
   1328   // will be masked out by the root layer's bounds.
   1329   host_impl_->active_tree()->SetRootLayer(
   1330       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
   1331   DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
   1332       host_impl_->active_tree()->root_layer());
   1333 
   1334   root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
   1335   DidDrawCheckLayer* layer =
   1336       static_cast<DidDrawCheckLayer*>(root->children()[0]);
   1337 
   1338   {
   1339     LayerTreeHostImpl::FrameData frame;
   1340     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
   1341     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1342     host_impl_->DidDrawAllLayers(frame);
   1343 
   1344     EXPECT_TRUE(layer->will_draw_called());
   1345     EXPECT_TRUE(layer->append_quads_called());
   1346     EXPECT_TRUE(layer->did_draw_called());
   1347   }
   1348 
   1349   {
   1350     LayerTreeHostImpl::FrameData frame;
   1351 
   1352     layer->set_will_draw_returns_false();
   1353     layer->ClearDidDrawCheck();
   1354 
   1355     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect(10, 10)));
   1356     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1357     host_impl_->DidDrawAllLayers(frame);
   1358 
   1359     EXPECT_TRUE(layer->will_draw_called());
   1360     EXPECT_FALSE(layer->append_quads_called());
   1361     EXPECT_FALSE(layer->did_draw_called());
   1362   }
   1363 }
   1364 
   1365 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
   1366   // The root layer is always drawn, so run this test on a child layer that
   1367   // will be masked out by the root layer's bounds.
   1368   host_impl_->active_tree()->SetRootLayer(
   1369       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
   1370   DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
   1371       host_impl_->active_tree()->root_layer());
   1372   root->SetMasksToBounds(true);
   1373 
   1374   root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
   1375   DidDrawCheckLayer* layer =
   1376       static_cast<DidDrawCheckLayer*>(root->children()[0]);
   1377   // Ensure visible_content_rect for layer is empty.
   1378   layer->SetPosition(gfx::PointF(100.f, 100.f));
   1379   layer->SetBounds(gfx::Size(10, 10));
   1380   layer->SetContentBounds(gfx::Size(10, 10));
   1381 
   1382   LayerTreeHostImpl::FrameData frame;
   1383 
   1384   EXPECT_FALSE(layer->will_draw_called());
   1385   EXPECT_FALSE(layer->did_draw_called());
   1386 
   1387   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1388   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1389   host_impl_->DidDrawAllLayers(frame);
   1390 
   1391   EXPECT_FALSE(layer->will_draw_called());
   1392   EXPECT_FALSE(layer->did_draw_called());
   1393 
   1394   EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
   1395 
   1396   // Ensure visible_content_rect for layer is not empty
   1397   layer->SetPosition(gfx::PointF());
   1398 
   1399   EXPECT_FALSE(layer->will_draw_called());
   1400   EXPECT_FALSE(layer->did_draw_called());
   1401 
   1402   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1403   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1404   host_impl_->DidDrawAllLayers(frame);
   1405 
   1406   EXPECT_TRUE(layer->will_draw_called());
   1407   EXPECT_TRUE(layer->did_draw_called());
   1408 
   1409   EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
   1410 }
   1411 
   1412 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
   1413   gfx::Size big_size(1000, 1000);
   1414   host_impl_->SetViewportSize(big_size);
   1415 
   1416   host_impl_->active_tree()->SetRootLayer(
   1417       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
   1418   DidDrawCheckLayer* root =
   1419       static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
   1420 
   1421   root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
   1422   DidDrawCheckLayer* occluded_layer =
   1423       static_cast<DidDrawCheckLayer*>(root->children()[0]);
   1424 
   1425   root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
   1426   DidDrawCheckLayer* top_layer =
   1427       static_cast<DidDrawCheckLayer*>(root->children()[1]);
   1428   // This layer covers the occluded_layer above. Make this layer large so it can
   1429   // occlude.
   1430   top_layer->SetBounds(big_size);
   1431   top_layer->SetContentBounds(big_size);
   1432   top_layer->SetContentsOpaque(true);
   1433 
   1434   LayerTreeHostImpl::FrameData frame;
   1435 
   1436   EXPECT_FALSE(occluded_layer->will_draw_called());
   1437   EXPECT_FALSE(occluded_layer->did_draw_called());
   1438   EXPECT_FALSE(top_layer->will_draw_called());
   1439   EXPECT_FALSE(top_layer->did_draw_called());
   1440 
   1441   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1442   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1443   host_impl_->DidDrawAllLayers(frame);
   1444 
   1445   EXPECT_FALSE(occluded_layer->will_draw_called());
   1446   EXPECT_FALSE(occluded_layer->did_draw_called());
   1447   EXPECT_TRUE(top_layer->will_draw_called());
   1448   EXPECT_TRUE(top_layer->did_draw_called());
   1449 }
   1450 
   1451 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
   1452   host_impl_->active_tree()->SetRootLayer(
   1453       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
   1454   DidDrawCheckLayer* root =
   1455       static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
   1456 
   1457   root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
   1458   DidDrawCheckLayer* layer1 =
   1459       static_cast<DidDrawCheckLayer*>(root->children()[0]);
   1460 
   1461   layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
   1462   DidDrawCheckLayer* layer2 =
   1463       static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
   1464 
   1465   layer1->SetOpacity(0.3f);
   1466   layer1->SetPreserves3d(false);
   1467 
   1468   EXPECT_FALSE(root->did_draw_called());
   1469   EXPECT_FALSE(layer1->did_draw_called());
   1470   EXPECT_FALSE(layer2->did_draw_called());
   1471 
   1472   LayerTreeHostImpl::FrameData frame;
   1473   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1474   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1475   host_impl_->DidDrawAllLayers(frame);
   1476 
   1477   EXPECT_TRUE(root->did_draw_called());
   1478   EXPECT_TRUE(layer1->did_draw_called());
   1479   EXPECT_TRUE(layer2->did_draw_called());
   1480 
   1481   EXPECT_NE(root->render_surface(), layer1->render_surface());
   1482   EXPECT_TRUE(!!layer1->render_surface());
   1483 }
   1484 
   1485 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
   1486  public:
   1487   static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
   1488                                       int id,
   1489                                       bool tile_missing,
   1490                                       bool skips_draw,
   1491                                       bool animating,
   1492                                       ResourceProvider* resource_provider) {
   1493     return scoped_ptr<LayerImpl>(new MissingTextureAnimatingLayer(
   1494         tree_impl,
   1495         id,
   1496         tile_missing,
   1497         skips_draw,
   1498         animating,
   1499         resource_provider));
   1500   }
   1501 
   1502  private:
   1503   MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
   1504                                int id,
   1505                                bool tile_missing,
   1506                                bool skips_draw,
   1507                                bool animating,
   1508                                ResourceProvider* resource_provider)
   1509       : DidDrawCheckLayer(tree_impl, id) {
   1510     scoped_ptr<LayerTilingData> tiling_data =
   1511         LayerTilingData::Create(gfx::Size(10, 10),
   1512                                 LayerTilingData::NO_BORDER_TEXELS);
   1513     tiling_data->SetBounds(bounds());
   1514     SetTilingData(*tiling_data.get());
   1515     set_skips_draw(skips_draw);
   1516     if (!tile_missing) {
   1517       ResourceProvider::ResourceId resource =
   1518           resource_provider->CreateResource(gfx::Size(1, 1),
   1519                                             GL_RGBA,
   1520                                             ResourceProvider::TextureUsageAny);
   1521       resource_provider->AllocateForTesting(resource);
   1522       PushTileProperties(0, 0, resource, gfx::Rect(), false);
   1523     }
   1524     if (animating)
   1525       AddAnimatedTransformToLayer(this, 10.0, 3, 0);
   1526   }
   1527 };
   1528 
   1529 TEST_F(LayerTreeHostImplTest, PrepareToDrawFailsWhenAnimationUsesCheckerboard) {
   1530   // When the texture is not missing, we draw as usual.
   1531   host_impl_->active_tree()->SetRootLayer(
   1532       DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
   1533   DidDrawCheckLayer* root =
   1534       static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
   1535   root->AddChild(
   1536       MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
   1537                                            2,
   1538                                            false,
   1539                                            false,
   1540                                            true,
   1541                                            host_impl_->resource_provider()));
   1542 
   1543   LayerTreeHostImpl::FrameData frame;
   1544 
   1545   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1546   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1547   host_impl_->DidDrawAllLayers(frame);
   1548 
   1549   // When a texture is missing and we're not animating, we draw as usual with
   1550   // checkerboarding.
   1551   host_impl_->active_tree()->SetRootLayer(
   1552       DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
   1553   root =
   1554       static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
   1555   root->AddChild(
   1556       MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
   1557                                            4,
   1558                                            true,
   1559                                            false,
   1560                                            false,
   1561                                            host_impl_->resource_provider()));
   1562 
   1563   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1564   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1565   host_impl_->DidDrawAllLayers(frame);
   1566 
   1567   // When a texture is missing and we're animating, we don't want to draw
   1568   // anything.
   1569   host_impl_->active_tree()->SetRootLayer(
   1570       DidDrawCheckLayer::Create(host_impl_->active_tree(), 5));
   1571   root =
   1572       static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
   1573   root->AddChild(
   1574       MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
   1575                                            6,
   1576                                            true,
   1577                                            false,
   1578                                            true,
   1579                                            host_impl_->resource_provider()));
   1580 
   1581   EXPECT_FALSE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1582   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1583   host_impl_->DidDrawAllLayers(frame);
   1584 
   1585   // When the layer skips draw and we're animating, we still draw the frame.
   1586   host_impl_->active_tree()->SetRootLayer(
   1587       DidDrawCheckLayer::Create(host_impl_->active_tree(), 7));
   1588   root =
   1589       static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
   1590   root->AddChild(
   1591       MissingTextureAnimatingLayer::Create(host_impl_->active_tree(),
   1592                                            8,
   1593                                            false,
   1594                                            true,
   1595                                            true,
   1596                                            host_impl_->resource_provider()));
   1597 
   1598   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1599   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1600   host_impl_->DidDrawAllLayers(frame);
   1601 }
   1602 
   1603 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
   1604   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   1605   root->SetScrollable(false);
   1606   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1607   InitializeRendererAndDrawFrame();
   1608 
   1609   // Scroll event is ignored because layer is not scrollable.
   1610   EXPECT_EQ(InputHandler::ScrollIgnored,
   1611             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
   1612   EXPECT_FALSE(did_request_redraw_);
   1613   EXPECT_FALSE(did_request_commit_);
   1614 }
   1615 
   1616 TEST_F(LayerTreeHostImplTest, ScrollNonScrollableRootWithTopControls) {
   1617   LayerTreeSettings settings;
   1618   settings.calculate_top_controls_position = true;
   1619   settings.top_controls_height = 50;
   1620 
   1621   host_impl_ = LayerTreeHostImpl::Create(settings,
   1622                                          this,
   1623                                          &proxy_,
   1624                                          &stats_instrumentation_);
   1625   host_impl_->InitializeRenderer(CreateOutputSurface());
   1626   host_impl_->SetViewportSize(gfx::Size(10, 10));
   1627 
   1628   gfx::Size layer_size(5, 5);
   1629   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   1630   root->SetScrollable(true);
   1631   root->SetMaxScrollOffset(gfx::Vector2d(layer_size.width(),
   1632                                          layer_size.height()));
   1633   root->SetBounds(layer_size);
   1634   root->SetContentBounds(layer_size);
   1635   root->SetPosition(gfx::PointF());
   1636   root->SetAnchorPoint(gfx::PointF());
   1637   root->SetDrawsContent(false);
   1638   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1639   host_impl_->active_tree()->FindRootScrollLayer();
   1640   InitializeRendererAndDrawFrame();
   1641 
   1642   EXPECT_EQ(InputHandler::ScrollIgnored,
   1643             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
   1644 
   1645   host_impl_->top_controls_manager()->ScrollBegin();
   1646   host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
   1647   host_impl_->top_controls_manager()->ScrollEnd();
   1648   EXPECT_EQ(host_impl_->top_controls_manager()->content_top_offset(), 0.f);
   1649 
   1650   EXPECT_EQ(InputHandler::ScrollStarted,
   1651             host_impl_->ScrollBegin(gfx::Point(),
   1652                                     InputHandler::Gesture));
   1653 }
   1654 
   1655 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
   1656   // Test the configuration where a non-composited root layer is embedded in a
   1657   // scrollable outer layer.
   1658   gfx::Size surface_size(10, 10);
   1659 
   1660   scoped_ptr<LayerImpl> content_layer =
   1661       LayerImpl::Create(host_impl_->active_tree(), 1);
   1662   content_layer->SetDrawsContent(true);
   1663   content_layer->SetPosition(gfx::PointF());
   1664   content_layer->SetAnchorPoint(gfx::PointF());
   1665   content_layer->SetBounds(surface_size);
   1666   content_layer->SetContentBounds(gfx::Size(surface_size.width() * 2,
   1667                                             surface_size.height() * 2));
   1668   content_layer->SetContentsScale(2.f, 2.f);
   1669 
   1670   scoped_ptr<LayerImpl> scroll_layer =
   1671       LayerImpl::Create(host_impl_->active_tree(), 2);
   1672   scroll_layer->SetScrollable(true);
   1673   scroll_layer->SetMaxScrollOffset(gfx::Vector2d(surface_size.width(),
   1674                                                  surface_size.height()));
   1675   scroll_layer->SetBounds(surface_size);
   1676   scroll_layer->SetContentBounds(surface_size);
   1677   scroll_layer->SetPosition(gfx::PointF());
   1678   scroll_layer->SetAnchorPoint(gfx::PointF());
   1679   scroll_layer->AddChild(content_layer.Pass());
   1680 
   1681   host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
   1682   host_impl_->SetViewportSize(surface_size);
   1683   InitializeRendererAndDrawFrame();
   1684 
   1685   EXPECT_EQ(InputHandler::ScrollStarted,
   1686             host_impl_->ScrollBegin(gfx::Point(5, 5),
   1687                                     InputHandler::Wheel));
   1688   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
   1689   host_impl_->ScrollEnd();
   1690   EXPECT_TRUE(did_request_redraw_);
   1691   EXPECT_TRUE(did_request_commit_);
   1692 }
   1693 
   1694 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
   1695   gfx::Size surface_size(10, 10);
   1696   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   1697   root->SetBounds(surface_size);
   1698   root->SetContentBounds(surface_size);
   1699   root->AddChild(CreateScrollableLayer(2, surface_size));
   1700   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1701   host_impl_->SetViewportSize(surface_size);
   1702   InitializeRendererAndDrawFrame();
   1703 
   1704   EXPECT_EQ(InputHandler::ScrollStarted,
   1705             host_impl_->ScrollBegin(gfx::Point(5, 5),
   1706                                     InputHandler::Wheel));
   1707   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
   1708   host_impl_->ScrollEnd();
   1709   EXPECT_TRUE(did_request_redraw_);
   1710   EXPECT_TRUE(did_request_commit_);
   1711 }
   1712 
   1713 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
   1714   gfx::Size surface_size(10, 10);
   1715   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   1716   root->AddChild(CreateScrollableLayer(2, surface_size));
   1717   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1718   host_impl_->SetViewportSize(surface_size);
   1719   InitializeRendererAndDrawFrame();
   1720 
   1721   // Scroll event is ignored because the input coordinate is outside the layer
   1722   // boundaries.
   1723   EXPECT_EQ(InputHandler::ScrollIgnored,
   1724             host_impl_->ScrollBegin(gfx::Point(15, 5),
   1725                                     InputHandler::Wheel));
   1726   EXPECT_FALSE(did_request_redraw_);
   1727   EXPECT_FALSE(did_request_commit_);
   1728 }
   1729 
   1730 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
   1731   gfx::Size surface_size(10, 10);
   1732   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   1733   scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
   1734   host_impl_->SetViewportSize(surface_size);
   1735 
   1736   gfx::Transform matrix;
   1737   matrix.RotateAboutXAxis(180.0);
   1738   child->SetTransform(matrix);
   1739   child->SetDoubleSided(false);
   1740 
   1741   root->AddChild(child.Pass());
   1742   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1743   InitializeRendererAndDrawFrame();
   1744 
   1745   // Scroll event is ignored because the scrollable layer is not facing the
   1746   // viewer and there is nothing scrollable behind it.
   1747   EXPECT_EQ(InputHandler::ScrollIgnored,
   1748             host_impl_->ScrollBegin(gfx::Point(5, 5),
   1749                                     InputHandler::Wheel));
   1750   EXPECT_FALSE(did_request_redraw_);
   1751   EXPECT_FALSE(did_request_commit_);
   1752 }
   1753 
   1754 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
   1755   gfx::Size surface_size(10, 10);
   1756   scoped_ptr<LayerImpl> content_layer = CreateScrollableLayer(1, surface_size);
   1757   content_layer->SetShouldScrollOnMainThread(true);
   1758   content_layer->SetScrollable(false);
   1759 
   1760   scoped_ptr<LayerImpl> scroll_layer = CreateScrollableLayer(2, surface_size);
   1761   scroll_layer->AddChild(content_layer.Pass());
   1762 
   1763   host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
   1764   host_impl_->SetViewportSize(surface_size);
   1765   InitializeRendererAndDrawFrame();
   1766 
   1767   // Scrolling fails because the content layer is asking to be scrolled on the
   1768   // main thread.
   1769   EXPECT_EQ(InputHandler::ScrollOnMainThread,
   1770             host_impl_->ScrollBegin(gfx::Point(5, 5),
   1771                                     InputHandler::Wheel));
   1772 }
   1773 
   1774 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
   1775   gfx::Size surface_size(10, 10);
   1776   float page_scale = 2.f;
   1777   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   1778   scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
   1779   root->AddChild(root_scrolling.Pass());
   1780   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1781   host_impl_->active_tree()->DidBecomeActive();
   1782   host_impl_->SetViewportSize(surface_size);
   1783   InitializeRendererAndDrawFrame();
   1784 
   1785   LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
   1786 
   1787   gfx::Vector2d scroll_delta(0, 10);
   1788   gfx::Vector2d expected_scroll_delta = scroll_delta;
   1789   gfx::Vector2d expected_max_scroll = root_scroll->max_scroll_offset();
   1790   EXPECT_EQ(InputHandler::ScrollStarted,
   1791             host_impl_->ScrollBegin(gfx::Point(5, 5),
   1792                                     InputHandler::Wheel));
   1793   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   1794   host_impl_->ScrollEnd();
   1795 
   1796   // Set new page scale from main thread.
   1797   host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
   1798                                                          page_scale,
   1799                                                          page_scale);
   1800 
   1801   scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
   1802   ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
   1803 
   1804   // The scroll range should also have been updated.
   1805   EXPECT_EQ(expected_max_scroll, root_scroll->max_scroll_offset());
   1806 
   1807   // The page scale delta remains constant because the impl thread did not
   1808   // scale.
   1809   EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
   1810 }
   1811 
   1812 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
   1813   gfx::Size surface_size(10, 10);
   1814   float page_scale = 2.f;
   1815   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   1816   scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
   1817   root->AddChild(root_scrolling.Pass());
   1818   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1819   host_impl_->active_tree()->DidBecomeActive();
   1820   host_impl_->SetViewportSize(surface_size);
   1821   host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 1.f, page_scale);
   1822   InitializeRendererAndDrawFrame();
   1823 
   1824   LayerImpl* root_scroll = host_impl_->active_tree()->RootScrollLayer();
   1825 
   1826   gfx::Vector2d scroll_delta(0, 10);
   1827   gfx::Vector2d expected_scroll_delta = scroll_delta;
   1828   gfx::Vector2d expected_max_scroll = root_scroll->max_scroll_offset();
   1829   EXPECT_EQ(InputHandler::ScrollStarted,
   1830             host_impl_->ScrollBegin(gfx::Point(5, 5),
   1831                                     InputHandler::Wheel));
   1832   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   1833   host_impl_->ScrollEnd();
   1834 
   1835   // Set new page scale on impl thread by pinching.
   1836   host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
   1837   host_impl_->PinchGestureBegin();
   1838   host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
   1839   host_impl_->PinchGestureEnd();
   1840   host_impl_->ScrollEnd();
   1841   DrawOneFrame();
   1842 
   1843   // The scroll delta is not scaled because the main thread did not scale.
   1844   scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
   1845   ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
   1846 
   1847   // The scroll range should also have been updated.
   1848   EXPECT_EQ(expected_max_scroll, root_scroll->max_scroll_offset());
   1849 
   1850   // The page scale delta should match the new scale on the impl side.
   1851   EXPECT_EQ(page_scale, host_impl_->active_tree()->total_page_scale_factor());
   1852 }
   1853 
   1854 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
   1855   gfx::Size surface_size(10, 10);
   1856   float default_page_scale = 1.f;
   1857   gfx::Transform default_page_scale_matrix;
   1858   default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
   1859 
   1860   float new_page_scale = 2.f;
   1861   gfx::Transform new_page_scale_matrix;
   1862   new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
   1863 
   1864   // Create a normal scrollable root layer and another scrollable child layer.
   1865   LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
   1866   LayerImpl* root = host_impl_->active_tree()->root_layer();
   1867   LayerImpl* child = scroll->children()[0];
   1868 
   1869   scoped_ptr<LayerImpl> scrollable_child =
   1870       CreateScrollableLayer(4, surface_size);
   1871   child->AddChild(scrollable_child.Pass());
   1872   LayerImpl* grand_child = child->children()[0];
   1873 
   1874   // Set new page scale on impl thread by pinching.
   1875   host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture);
   1876   host_impl_->PinchGestureBegin();
   1877   host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
   1878   host_impl_->PinchGestureEnd();
   1879   host_impl_->ScrollEnd();
   1880   DrawOneFrame();
   1881 
   1882   EXPECT_EQ(1.f, root->contents_scale_x());
   1883   EXPECT_EQ(1.f, root->contents_scale_y());
   1884   EXPECT_EQ(1.f, scroll->contents_scale_x());
   1885   EXPECT_EQ(1.f, scroll->contents_scale_y());
   1886   EXPECT_EQ(1.f, child->contents_scale_x());
   1887   EXPECT_EQ(1.f, child->contents_scale_y());
   1888   EXPECT_EQ(1.f, grand_child->contents_scale_x());
   1889   EXPECT_EQ(1.f, grand_child->contents_scale_y());
   1890 
   1891   // Make sure all the layers are drawn with the page scale delta applied, i.e.,
   1892   // the page scale delta on the root layer is applied hierarchically.
   1893   LayerTreeHostImpl::FrameData frame;
   1894   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   1895   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   1896   host_impl_->DidDrawAllLayers(frame);
   1897 
   1898   EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
   1899   EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
   1900   EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
   1901   EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
   1902   EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
   1903   EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
   1904   EXPECT_EQ(new_page_scale,
   1905             grand_child->draw_transform().matrix().getDouble(0, 0));
   1906   EXPECT_EQ(new_page_scale,
   1907             grand_child->draw_transform().matrix().getDouble(1, 1));
   1908 }
   1909 
   1910 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
   1911   gfx::Size surface_size(10, 10);
   1912   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   1913   scoped_ptr<LayerImpl> root_scrolling =
   1914       LayerImpl::Create(host_impl_->active_tree(), 2);
   1915   root_scrolling->SetBounds(surface_size);
   1916   root_scrolling->SetContentBounds(surface_size);
   1917   root_scrolling->SetScrollable(true);
   1918   root->AddChild(root_scrolling.Pass());
   1919   int child_scroll_layer_id = 3;
   1920   scoped_ptr<LayerImpl> child_scrolling =
   1921       CreateScrollableLayer(child_scroll_layer_id, surface_size);
   1922   LayerImpl* child = child_scrolling.get();
   1923   root->AddChild(child_scrolling.Pass());
   1924   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1925   host_impl_->active_tree()->DidBecomeActive();
   1926   host_impl_->SetViewportSize(surface_size);
   1927   InitializeRendererAndDrawFrame();
   1928 
   1929   gfx::Vector2d scroll_delta(0, 10);
   1930   gfx::Vector2d expected_scroll_delta(scroll_delta);
   1931   gfx::Vector2d expected_max_scroll(child->max_scroll_offset());
   1932   EXPECT_EQ(InputHandler::ScrollStarted,
   1933             host_impl_->ScrollBegin(gfx::Point(5, 5),
   1934                                     InputHandler::Wheel));
   1935   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   1936   host_impl_->ScrollEnd();
   1937 
   1938   float page_scale = 2.f;
   1939   host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
   1940                                                          1.f,
   1941                                                          page_scale);
   1942 
   1943   DrawOneFrame();
   1944 
   1945   scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
   1946   ExpectContains(
   1947       *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
   1948 
   1949   // The scroll range should not have changed.
   1950   EXPECT_EQ(child->max_scroll_offset(), expected_max_scroll);
   1951 
   1952   // The page scale delta remains constant because the impl thread did not
   1953   // scale.
   1954   EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
   1955 }
   1956 
   1957 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
   1958   // Scroll a child layer beyond its maximum scroll range and make sure the
   1959   // parent layer is scrolled on the axis on which the child was unable to
   1960   // scroll.
   1961   gfx::Size surface_size(10, 10);
   1962   scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, surface_size);
   1963 
   1964   scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(3, surface_size);
   1965   grand_child->SetScrollOffset(gfx::Vector2d(0, 5));
   1966 
   1967   scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
   1968   child->SetScrollOffset(gfx::Vector2d(3, 0));
   1969   child->AddChild(grand_child.Pass());
   1970 
   1971   root->AddChild(child.Pass());
   1972   host_impl_->active_tree()->SetRootLayer(root.Pass());
   1973   host_impl_->active_tree()->DidBecomeActive();
   1974   host_impl_->SetViewportSize(surface_size);
   1975   InitializeRendererAndDrawFrame();
   1976   {
   1977     gfx::Vector2d scroll_delta(-8, -7);
   1978     EXPECT_EQ(InputHandler::ScrollStarted,
   1979               host_impl_->ScrollBegin(gfx::Point(),
   1980                                       InputHandler::Wheel));
   1981     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   1982     host_impl_->ScrollEnd();
   1983 
   1984     scoped_ptr<ScrollAndScaleSet> scroll_info =
   1985         host_impl_->ProcessScrollDeltas();
   1986 
   1987     // The grand child should have scrolled up to its limit.
   1988     LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
   1989     LayerImpl* grand_child = child->children()[0];
   1990     ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
   1991 
   1992     // The child should have only scrolled on the other axis.
   1993     ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
   1994   }
   1995 }
   1996 
   1997 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
   1998   // Scroll a child layer beyond its maximum scroll range and make sure the
   1999   // the scroll doesn't bubble up to the parent layer.
   2000   gfx::Size surface_size(10, 10);
   2001   scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
   2002   scoped_ptr<LayerImpl> root_scrolling = CreateScrollableLayer(2, surface_size);
   2003 
   2004   scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(4, surface_size);
   2005   grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
   2006 
   2007   scoped_ptr<LayerImpl> child = CreateScrollableLayer(3, surface_size);
   2008   child->SetScrollOffset(gfx::Vector2d(0, 3));
   2009   child->AddChild(grand_child.Pass());
   2010 
   2011   root_scrolling->AddChild(child.Pass());
   2012   root->AddChild(root_scrolling.Pass());
   2013   host_impl_->active_tree()->SetRootLayer(root.Pass());
   2014   host_impl_->active_tree()->DidBecomeActive();
   2015   host_impl_->SetViewportSize(surface_size);
   2016   InitializeRendererAndDrawFrame();
   2017   {
   2018     gfx::Vector2d scroll_delta(0, -10);
   2019     EXPECT_EQ(InputHandler::ScrollStarted,
   2020               host_impl_->ScrollBegin(gfx::Point(),
   2021                                       InputHandler::NonBubblingGesture));
   2022     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2023     host_impl_->ScrollEnd();
   2024 
   2025     scoped_ptr<ScrollAndScaleSet> scroll_info =
   2026         host_impl_->ProcessScrollDeltas();
   2027 
   2028     // The grand child should have scrolled up to its limit.
   2029     LayerImpl* child =
   2030         host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
   2031     LayerImpl* grand_child = child->children()[0];
   2032     ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
   2033 
   2034     // The child should not have scrolled.
   2035     ExpectNone(*scroll_info.get(), child->id());
   2036 
   2037     // The next time we scroll we should only scroll the parent.
   2038     scroll_delta = gfx::Vector2d(0, -3);
   2039     EXPECT_EQ(InputHandler::ScrollStarted,
   2040               host_impl_->ScrollBegin(gfx::Point(5, 5),
   2041                                       InputHandler::NonBubblingGesture));
   2042     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
   2043     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2044     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
   2045     host_impl_->ScrollEnd();
   2046 
   2047     scroll_info = host_impl_->ProcessScrollDeltas();
   2048 
   2049     // The child should have scrolled up to its limit.
   2050     ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
   2051 
   2052     // The grand child should not have scrolled.
   2053     ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
   2054 
   2055     // After scrolling the parent, another scroll on the opposite direction
   2056     // should still scroll the child.
   2057     scroll_delta = gfx::Vector2d(0, 7);
   2058     EXPECT_EQ(InputHandler::ScrollStarted,
   2059               host_impl_->ScrollBegin(gfx::Point(5, 5),
   2060                                       InputHandler::NonBubblingGesture));
   2061     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
   2062     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2063     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
   2064     host_impl_->ScrollEnd();
   2065 
   2066     scroll_info = host_impl_->ProcessScrollDeltas();
   2067 
   2068     // The grand child should have scrolled.
   2069     ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
   2070 
   2071     // The child should not have scrolled.
   2072     ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
   2073 
   2074 
   2075     // Scrolling should be adjusted from viewport space.
   2076     host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 2.f, 2.f);
   2077     host_impl_->active_tree()->SetPageScaleDelta(1.f);
   2078 
   2079     scroll_delta = gfx::Vector2d(0, -2);
   2080     EXPECT_EQ(InputHandler::ScrollStarted,
   2081               host_impl_->ScrollBegin(gfx::Point(1, 1),
   2082                                       InputHandler::NonBubblingGesture));
   2083     EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
   2084     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2085     host_impl_->ScrollEnd();
   2086 
   2087     scroll_info = host_impl_->ProcessScrollDeltas();
   2088 
   2089     // Should have scrolled by half the amount in layer space (5 - 2/2)
   2090     ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
   2091   }
   2092 }
   2093 
   2094 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
   2095   // When we try to scroll a non-scrollable child layer, the scroll delta
   2096   // should be applied to one of its ancestors if possible.
   2097   gfx::Size surface_size(10, 10);
   2098   gfx::Size content_size(20, 20);
   2099   scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
   2100   scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
   2101 
   2102   child->SetScrollable(false);
   2103   root->AddChild(child.Pass());
   2104 
   2105   host_impl_->SetViewportSize(surface_size);
   2106   host_impl_->active_tree()->SetRootLayer(root.Pass());
   2107   host_impl_->active_tree()->DidBecomeActive();
   2108   InitializeRendererAndDrawFrame();
   2109   {
   2110     gfx::Vector2d scroll_delta(0, 4);
   2111     EXPECT_EQ(InputHandler::ScrollStarted,
   2112               host_impl_->ScrollBegin(gfx::Point(5, 5),
   2113                                       InputHandler::Wheel));
   2114     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2115     host_impl_->ScrollEnd();
   2116 
   2117     scoped_ptr<ScrollAndScaleSet> scroll_info =
   2118         host_impl_->ProcessScrollDeltas();
   2119 
   2120     // Only the root should have scrolled.
   2121     ASSERT_EQ(scroll_info->scrolls.size(), 1u);
   2122     ExpectContains(*scroll_info.get(),
   2123                    host_impl_->active_tree()->root_layer()->id(),
   2124                    scroll_delta);
   2125   }
   2126 }
   2127 
   2128 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
   2129   gfx::Size surface_size(10, 10);
   2130   host_impl_->active_tree()->SetRootLayer(
   2131       CreateScrollableLayer(1, surface_size));
   2132   host_impl_->active_tree()->DidBecomeActive();
   2133   host_impl_->SetViewportSize(surface_size);
   2134 
   2135   // Draw one frame and then immediately rebuild the layer tree to mimic a tree
   2136   // synchronization.
   2137   InitializeRendererAndDrawFrame();
   2138   host_impl_->active_tree()->DetachLayerTree();
   2139   host_impl_->active_tree()->SetRootLayer(
   2140       CreateScrollableLayer(2, surface_size));
   2141   host_impl_->active_tree()->DidBecomeActive();
   2142 
   2143   // Scrolling should still work even though we did not draw yet.
   2144   EXPECT_EQ(InputHandler::ScrollStarted,
   2145             host_impl_->ScrollBegin(gfx::Point(5, 5),
   2146                                     InputHandler::Wheel));
   2147 }
   2148 
   2149 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
   2150   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
   2151 
   2152   // Rotate the root layer 90 degrees counter-clockwise about its center.
   2153   gfx::Transform rotate_transform;
   2154   rotate_transform.Rotate(-90.0);
   2155   host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
   2156 
   2157   gfx::Size surface_size(50, 50);
   2158   host_impl_->SetViewportSize(surface_size);
   2159   InitializeRendererAndDrawFrame();
   2160 
   2161   // Scroll to the right in screen coordinates with a gesture.
   2162   gfx::Vector2d gesture_scroll_delta(10, 0);
   2163   EXPECT_EQ(InputHandler::ScrollStarted,
   2164             host_impl_->ScrollBegin(gfx::Point(),
   2165                                     InputHandler::Gesture));
   2166   host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
   2167   host_impl_->ScrollEnd();
   2168 
   2169   // The layer should have scrolled down in its local coordinates.
   2170   scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
   2171   ExpectContains(*scroll_info.get(),
   2172                  scroll_layer->id(),
   2173                  gfx::Vector2d(0, gesture_scroll_delta.x()));
   2174 
   2175   // Reset and scroll down with the wheel.
   2176   scroll_layer->SetScrollDelta(gfx::Vector2dF());
   2177   gfx::Vector2d wheel_scroll_delta(0, 10);
   2178   EXPECT_EQ(InputHandler::ScrollStarted,
   2179             host_impl_->ScrollBegin(gfx::Point(),
   2180                                     InputHandler::Wheel));
   2181   host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
   2182   host_impl_->ScrollEnd();
   2183 
   2184   // The layer should have scrolled down in its local coordinates.
   2185   scroll_info = host_impl_->ProcessScrollDeltas();
   2186   ExpectContains(*scroll_info.get(),
   2187                  scroll_layer->id(),
   2188                  wheel_scroll_delta);
   2189 }
   2190 
   2191 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
   2192   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
   2193   int child_layer_id = 4;
   2194   float child_layer_angle = -20.f;
   2195 
   2196   // Create a child layer that is rotated to a non-axis-aligned angle.
   2197   scoped_ptr<LayerImpl> child = CreateScrollableLayer(
   2198       child_layer_id,
   2199       scroll_layer->content_bounds());
   2200   gfx::Transform rotate_transform;
   2201   rotate_transform.Translate(-50.0, -50.0);
   2202   rotate_transform.Rotate(child_layer_angle);
   2203   rotate_transform.Translate(50.0, 50.0);
   2204   child->SetTransform(rotate_transform);
   2205 
   2206   // Only allow vertical scrolling.
   2207   child->SetMaxScrollOffset(gfx::Vector2d(0, child->content_bounds().height()));
   2208   scroll_layer->AddChild(child.Pass());
   2209 
   2210   gfx::Size surface_size(50, 50);
   2211   host_impl_->SetViewportSize(surface_size);
   2212   InitializeRendererAndDrawFrame();
   2213   {
   2214     // Scroll down in screen coordinates with a gesture.
   2215     gfx::Vector2d gesture_scroll_delta(0, 10);
   2216     EXPECT_EQ(InputHandler::ScrollStarted,
   2217               host_impl_->ScrollBegin(gfx::Point(),
   2218                                       InputHandler::Gesture));
   2219     host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
   2220     host_impl_->ScrollEnd();
   2221 
   2222     // The child layer should have scrolled down in its local coordinates an
   2223     // amount proportional to the angle between it and the input scroll delta.
   2224     gfx::Vector2d expected_scroll_delta(
   2225         0,
   2226         gesture_scroll_delta.y() *
   2227             std::cos(MathUtil::Deg2Rad(child_layer_angle)));
   2228     scoped_ptr<ScrollAndScaleSet> scroll_info =
   2229         host_impl_->ProcessScrollDeltas();
   2230     ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
   2231 
   2232     // The root scroll layer should not have scrolled, because the input delta
   2233     // was close to the layer's axis of movement.
   2234     EXPECT_EQ(scroll_info->scrolls.size(), 1u);
   2235   }
   2236   {
   2237     // Now reset and scroll the same amount horizontally.
   2238     scroll_layer->children()[1]->SetScrollDelta(
   2239         gfx::Vector2dF());
   2240     gfx::Vector2d gesture_scroll_delta(10, 0);
   2241     EXPECT_EQ(InputHandler::ScrollStarted,
   2242               host_impl_->ScrollBegin(gfx::Point(),
   2243                                       InputHandler::Gesture));
   2244     host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
   2245     host_impl_->ScrollEnd();
   2246 
   2247     // The child layer should have scrolled down in its local coordinates an
   2248     // amount proportional to the angle between it and the input scroll delta.
   2249     gfx::Vector2d expected_scroll_delta(
   2250         0,
   2251         -gesture_scroll_delta.x() *
   2252             std::sin(MathUtil::Deg2Rad(child_layer_angle)));
   2253     scoped_ptr<ScrollAndScaleSet> scroll_info =
   2254         host_impl_->ProcessScrollDeltas();
   2255     ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
   2256 
   2257     // The root scroll layer should have scrolled more, since the input scroll
   2258     // delta was mostly orthogonal to the child layer's vertical scroll axis.
   2259     gfx::Vector2d expected_root_scroll_delta(
   2260         gesture_scroll_delta.x() *
   2261             std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
   2262         0);
   2263     ExpectContains(*scroll_info.get(),
   2264                    scroll_layer->id(),
   2265                    expected_root_scroll_delta);
   2266   }
   2267 }
   2268 
   2269 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
   2270   LayerImpl* scroll_layer =
   2271       SetupScrollAndContentsLayers(gfx::Size(100, 100));
   2272 
   2273   // Scale the layer to twice its normal size.
   2274   int scale = 2;
   2275   gfx::Transform scale_transform;
   2276   scale_transform.Scale(scale, scale);
   2277   scroll_layer->SetTransform(scale_transform);
   2278 
   2279   gfx::Size surface_size(50, 50);
   2280   host_impl_->SetViewportSize(surface_size);
   2281   InitializeRendererAndDrawFrame();
   2282 
   2283   // Scroll down in screen coordinates with a gesture.
   2284   gfx::Vector2d scroll_delta(0, 10);
   2285   EXPECT_EQ(InputHandler::ScrollStarted,
   2286             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
   2287   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2288   host_impl_->ScrollEnd();
   2289 
   2290   // The layer should have scrolled down in its local coordinates, but half the
   2291   // amount.
   2292   scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
   2293   ExpectContains(*scroll_info.get(),
   2294                  scroll_layer->id(),
   2295                  gfx::Vector2d(0, scroll_delta.y() / scale));
   2296 
   2297   // Reset and scroll down with the wheel.
   2298   scroll_layer->SetScrollDelta(gfx::Vector2dF());
   2299   gfx::Vector2d wheel_scroll_delta(0, 10);
   2300   EXPECT_EQ(InputHandler::ScrollStarted,
   2301             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
   2302   host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
   2303   host_impl_->ScrollEnd();
   2304 
   2305   // The scale should not have been applied to the scroll delta.
   2306   scroll_info = host_impl_->ProcessScrollDeltas();
   2307   ExpectContains(*scroll_info.get(),
   2308                  scroll_layer->id(),
   2309                  wheel_scroll_delta);
   2310 }
   2311 
   2312 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
   2313  public:
   2314   TestScrollOffsetDelegate() : page_scale_factor_(0.f) {}
   2315 
   2316   virtual ~TestScrollOffsetDelegate() {}
   2317 
   2318   virtual void SetMaxScrollOffset(gfx::Vector2dF max_scroll_offset) OVERRIDE {
   2319     max_scroll_offset_ = max_scroll_offset;
   2320   }
   2321 
   2322   virtual void SetTotalScrollOffset(gfx::Vector2dF new_value) OVERRIDE {
   2323     last_set_scroll_offset_ = new_value;
   2324   }
   2325 
   2326   virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
   2327     return getter_return_value_;
   2328   }
   2329 
   2330   virtual bool IsExternalFlingActive() const OVERRIDE { return false; }
   2331 
   2332   virtual void SetTotalPageScaleFactor(float page_scale_factor) OVERRIDE {
   2333     page_scale_factor_ = page_scale_factor;
   2334   }
   2335 
   2336   virtual void SetScrollableSize(gfx::SizeF scrollable_size) OVERRIDE {
   2337     scrollable_size_ = scrollable_size;
   2338   }
   2339 
   2340   gfx::Vector2dF last_set_scroll_offset() {
   2341     return last_set_scroll_offset_;
   2342   }
   2343 
   2344   void set_getter_return_value(gfx::Vector2dF value) {
   2345     getter_return_value_ = value;
   2346   }
   2347 
   2348   gfx::Vector2dF max_scroll_offset() const {
   2349     return max_scroll_offset_;
   2350   }
   2351 
   2352   gfx::SizeF scrollable_size() const {
   2353     return scrollable_size_;
   2354   }
   2355 
   2356   float page_scale_factor() const {
   2357     return page_scale_factor_;
   2358   }
   2359 
   2360  private:
   2361   gfx::Vector2dF last_set_scroll_offset_;
   2362   gfx::Vector2dF getter_return_value_;
   2363   gfx::Vector2dF max_scroll_offset_;
   2364   gfx::SizeF scrollable_size_;
   2365   float page_scale_factor_;
   2366 };
   2367 
   2368 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
   2369   TestScrollOffsetDelegate scroll_delegate;
   2370   host_impl_->SetViewportSize(gfx::Size(10, 20));
   2371   LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
   2372 
   2373   // Setting the delegate results in the current scroll offset being set.
   2374   gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
   2375   scroll_layer->SetScrollOffset(gfx::Vector2d());
   2376   scroll_layer->SetScrollDelta(initial_scroll_delta);
   2377   host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
   2378   EXPECT_EQ(initial_scroll_delta.ToString(),
   2379             scroll_delegate.last_set_scroll_offset().ToString());
   2380 
   2381   // Setting the delegate results in the scrollable_size, max_scroll_offset and
   2382   // page_scale being set.
   2383   EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
   2384   EXPECT_EQ(gfx::Vector2dF(90, 80), scroll_delegate.max_scroll_offset());
   2385   EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
   2386 
   2387   // Updating page scale immediately updates the delegate.
   2388   host_impl_->active_tree()->SetPageScaleFactorAndLimits(2.f, 0.5f, 4.f);
   2389   EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
   2390   host_impl_->active_tree()->SetPageScaleDelta(1.5f);
   2391   EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
   2392   host_impl_->active_tree()->SetPageScaleDelta(1.f);
   2393   host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
   2394   EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
   2395 
   2396   // Scrolling should be relative to the offset as returned by the delegate.
   2397   gfx::Vector2dF scroll_delta(0.f, 10.f);
   2398   gfx::Vector2dF current_offset(7.f, 8.f);
   2399 
   2400   scroll_delegate.set_getter_return_value(current_offset);
   2401   EXPECT_EQ(InputHandler::ScrollStarted,
   2402             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
   2403 
   2404   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2405   EXPECT_EQ(current_offset + scroll_delta,
   2406             scroll_delegate.last_set_scroll_offset());
   2407 
   2408   current_offset = gfx::Vector2dF(42.f, 41.f);
   2409   scroll_delegate.set_getter_return_value(current_offset);
   2410   host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2411   EXPECT_EQ(current_offset + scroll_delta,
   2412             scroll_delegate.last_set_scroll_offset());
   2413   host_impl_->ScrollEnd();
   2414 
   2415   // Forces a full tree synchronization and ensures that the scroll delegate
   2416   // sees the correct size of the new tree.
   2417   gfx::Size new_size(42, 24);
   2418   host_impl_->CreatePendingTree();
   2419   CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
   2420   host_impl_->ActivatePendingTree();
   2421   EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
   2422 
   2423   // Un-setting the delegate should propagate the delegate's current offset to
   2424   // the root scrollable layer.
   2425   current_offset = gfx::Vector2dF(13.f, 12.f);
   2426   scroll_delegate.set_getter_return_value(current_offset);
   2427   host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
   2428 
   2429   EXPECT_EQ(current_offset.ToString(),
   2430             scroll_layer->TotalScrollOffset().ToString());
   2431 }
   2432 
   2433 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
   2434   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   2435   host_impl_->SetViewportSize(gfx::Size(50, 50));
   2436   host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
   2437   InitializeRendererAndDrawFrame();
   2438   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
   2439   EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
   2440 
   2441   // In-bounds scrolling does not affect overscroll.
   2442   EXPECT_EQ(InputHandler::ScrollStarted,
   2443             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
   2444   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
   2445   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
   2446   EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
   2447 
   2448   // Overscroll events are reflected immediately.
   2449   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
   2450   EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
   2451   EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
   2452 
   2453   // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
   2454   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
   2455   EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
   2456   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
   2457   EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
   2458   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
   2459   EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
   2460   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
   2461   EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
   2462   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
   2463   EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
   2464   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
   2465   EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
   2466 
   2467   // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
   2468   // as no scroll occurs.
   2469   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
   2470   EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
   2471   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
   2472   EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
   2473   // Overscroll resets on valid scroll.
   2474   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
   2475   EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
   2476   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
   2477   EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
   2478   host_impl_->ScrollEnd();
   2479 
   2480   EXPECT_EQ(InputHandler::ScrollStarted,
   2481             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
   2482   // Fling velocity is reflected immediately.
   2483   host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
   2484   EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
   2485   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
   2486   EXPECT_EQ(gfx::Vector2dF(0, -20), host_impl_->accumulated_root_overscroll());
   2487   EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
   2488 }
   2489 
   2490 
   2491 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
   2492   // Scroll child layers beyond their maximum scroll range and make sure root
   2493   // overscroll does not accumulate.
   2494   gfx::Size surface_size(10, 10);
   2495   scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, surface_size);
   2496 
   2497   scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(3, surface_size);
   2498   grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
   2499 
   2500   scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
   2501   child->SetScrollOffset(gfx::Vector2d(0, 3));
   2502   child->AddChild(grand_child.Pass());
   2503 
   2504   root->AddChild(child.Pass());
   2505   host_impl_->active_tree()->SetRootLayer(root.Pass());
   2506   host_impl_->active_tree()->DidBecomeActive();
   2507   host_impl_->SetViewportSize(surface_size);
   2508   InitializeRendererAndDrawFrame();
   2509   {
   2510     gfx::Vector2d scroll_delta(0, -10);
   2511     EXPECT_EQ(InputHandler::ScrollStarted,
   2512               host_impl_->ScrollBegin(gfx::Point(),
   2513                                       InputHandler::NonBubblingGesture));
   2514     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2515     EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
   2516     host_impl_->ScrollEnd();
   2517 
   2518     LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
   2519     LayerImpl* grand_child = child->children()[0];
   2520 
   2521     // The next time we scroll we should only scroll the parent, but overscroll
   2522     // should still not reach the root layer.
   2523     scroll_delta = gfx::Vector2d(0, -30);
   2524     EXPECT_EQ(InputHandler::ScrollStarted,
   2525               host_impl_->ScrollBegin(gfx::Point(5, 5),
   2526                                       InputHandler::NonBubblingGesture));
   2527     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
   2528     EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
   2529     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2530     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
   2531     EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
   2532     host_impl_->ScrollEnd();
   2533 
   2534     // After scrolling the parent, another scroll on the opposite direction
   2535     // should scroll the child, resetting the fling velocity.
   2536     scroll_delta = gfx::Vector2d(0, 70);
   2537     host_impl_->NotifyCurrentFlingVelocity(gfx::Vector2dF(10, 0));
   2538     EXPECT_EQ(gfx::Vector2dF(10, 0), host_impl_->current_fling_velocity());
   2539     EXPECT_EQ(InputHandler::ScrollStarted,
   2540               host_impl_->ScrollBegin(gfx::Point(5, 5),
   2541                                       InputHandler::NonBubblingGesture));
   2542     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
   2543     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2544     EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
   2545     EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
   2546     EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
   2547     host_impl_->ScrollEnd();
   2548   }
   2549 }
   2550 
   2551 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
   2552   // When we try to scroll a non-scrollable child layer, the scroll delta
   2553   // should be applied to one of its ancestors if possible. Overscroll should
   2554   // be reflected only when it has bubbled up to the root scrolling layer.
   2555   gfx::Size surface_size(10, 10);
   2556   gfx::Size content_size(20, 20);
   2557   scoped_ptr<LayerImpl> root = CreateScrollableLayer(1, content_size);
   2558   scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, content_size);
   2559 
   2560   child->SetScrollable(false);
   2561   root->AddChild(child.Pass());
   2562 
   2563   host_impl_->SetViewportSize(surface_size);
   2564   host_impl_->active_tree()->SetRootLayer(root.Pass());
   2565   host_impl_->active_tree()->DidBecomeActive();
   2566   InitializeRendererAndDrawFrame();
   2567   {
   2568     gfx::Vector2d scroll_delta(0, 8);
   2569     EXPECT_EQ(InputHandler::ScrollStarted,
   2570               host_impl_->ScrollBegin(gfx::Point(5, 5),
   2571                                       InputHandler::Wheel));
   2572     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2573     EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
   2574     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2575     EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
   2576     host_impl_->ScrollBy(gfx::Point(), scroll_delta);
   2577     EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
   2578     host_impl_->ScrollEnd();
   2579   }
   2580 }
   2581 
   2582 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
   2583   LayerTreeSettings settings;
   2584   settings.always_overscroll = true;
   2585   host_impl_ = LayerTreeHostImpl::Create(
   2586       settings, this, &proxy_, &stats_instrumentation_);
   2587 
   2588   SetupScrollAndContentsLayers(gfx::Size(50, 50));
   2589   host_impl_->SetViewportSize(gfx::Size(50, 50));
   2590   host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f);
   2591   InitializeRendererAndDrawFrame();
   2592   EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
   2593   EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
   2594 
   2595   // Even though the layer can't scroll the overscroll still happens.
   2596   EXPECT_EQ(InputHandler::ScrollStarted,
   2597             host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
   2598   host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
   2599   EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
   2600   EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
   2601 }
   2602 
   2603 class BlendStateTrackerContext: public TestWebGraphicsContext3D {
   2604  public:
   2605   BlendStateTrackerContext() : blend_(false) {}
   2606 
   2607   virtual void enable(WebKit::WGC3Denum cap) OVERRIDE {
   2608     if (cap == GL_BLEND)
   2609       blend_ = true;
   2610   }
   2611 
   2612   virtual void disable(WebKit::WGC3Denum cap) OVERRIDE {
   2613     if (cap == GL_BLEND)
   2614       blend_ = false;
   2615   }
   2616 
   2617   bool blend() const { return blend_; }
   2618 
   2619  private:
   2620   bool blend_;
   2621 };
   2622 
   2623 class BlendStateCheckLayer : public LayerImpl {
   2624  public:
   2625   static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
   2626                                       int id,
   2627                                       ResourceProvider* resource_provider) {
   2628     return scoped_ptr<LayerImpl>(new BlendStateCheckLayer(tree_impl,
   2629                                                           id,
   2630                                                           resource_provider));
   2631   }
   2632 
   2633   virtual void AppendQuads(QuadSink* quad_sink,
   2634                            AppendQuadsData* append_quads_data) OVERRIDE {
   2635     quads_appended_ = true;
   2636 
   2637     gfx::Rect opaque_rect;
   2638     if (contents_opaque())
   2639       opaque_rect = quad_rect_;
   2640     else
   2641       opaque_rect = opaque_content_rect_;
   2642 
   2643     SharedQuadState* shared_quad_state =
   2644         quad_sink->UseSharedQuadState(CreateSharedQuadState());
   2645     scoped_ptr<TileDrawQuad> test_blending_draw_quad = TileDrawQuad::Create();
   2646     test_blending_draw_quad->SetNew(shared_quad_state,
   2647                                     quad_rect_,
   2648                                     opaque_rect,
   2649                                     resource_id_,
   2650                                     gfx::RectF(0.f, 0.f, 1.f, 1.f),
   2651                                     gfx::Size(1, 1),
   2652                                     false);
   2653     test_blending_draw_quad->visible_rect = quad_visible_rect_;
   2654     EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
   2655     EXPECT_EQ(has_render_surface_, !!render_surface());
   2656     quad_sink->Append(test_blending_draw_quad.PassAs<DrawQuad>(),
   2657                       append_quads_data);
   2658   }
   2659 
   2660   void SetExpectation(bool blend, bool has_render_surface) {
   2661     blend_ = blend;
   2662     has_render_surface_ = has_render_surface;
   2663     quads_appended_ = false;
   2664   }
   2665 
   2666   bool quads_appended() const { return quads_appended_; }
   2667 
   2668   void SetQuadRect(gfx::Rect rect) { quad_rect_ = rect; }
   2669   void SetQuadVisibleRect(gfx::Rect rect) { quad_visible_rect_ = rect; }
   2670   void SetOpaqueContentRect(gfx::Rect rect) { opaque_content_rect_ = rect; }
   2671 
   2672  private:
   2673   BlendStateCheckLayer(LayerTreeImpl* tree_impl,
   2674                        int id,
   2675                        ResourceProvider* resource_provider)
   2676       : LayerImpl(tree_impl, id),
   2677         blend_(false),
   2678         has_render_surface_(false),
   2679         quads_appended_(false),
   2680         quad_rect_(5, 5, 5, 5),
   2681         quad_visible_rect_(5, 5, 5, 5),
   2682         resource_id_(resource_provider->CreateResource(
   2683             gfx::Size(1, 1),
   2684             GL_RGBA,
   2685             ResourceProvider::TextureUsageAny)) {
   2686     resource_provider->AllocateForTesting(resource_id_);
   2687     SetAnchorPoint(gfx::PointF());
   2688     SetBounds(gfx::Size(10, 10));
   2689     SetContentBounds(gfx::Size(10, 10));
   2690     SetDrawsContent(true);
   2691   }
   2692 
   2693   bool blend_;
   2694   bool has_render_surface_;
   2695   bool quads_appended_;
   2696   gfx::Rect quad_rect_;
   2697   gfx::Rect opaque_content_rect_;
   2698   gfx::Rect quad_visible_rect_;
   2699   ResourceProvider::ResourceId resource_id_;
   2700 };
   2701 
   2702 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
   2703   {
   2704     scoped_ptr<LayerImpl> root =
   2705         LayerImpl::Create(host_impl_->active_tree(), 1);
   2706     root->SetAnchorPoint(gfx::PointF());
   2707     root->SetBounds(gfx::Size(10, 10));
   2708     root->SetContentBounds(root->bounds());
   2709     root->SetDrawsContent(false);
   2710     host_impl_->active_tree()->SetRootLayer(root.Pass());
   2711   }
   2712   LayerImpl* root = host_impl_->active_tree()->root_layer();
   2713 
   2714   root->AddChild(
   2715       BlendStateCheckLayer::Create(host_impl_->active_tree(),
   2716                                    2,
   2717                                    host_impl_->resource_provider()));
   2718   BlendStateCheckLayer* layer1 =
   2719       static_cast<BlendStateCheckLayer*>(root->children()[0]);
   2720   layer1->SetPosition(gfx::PointF(2.f, 2.f));
   2721 
   2722   LayerTreeHostImpl::FrameData frame;
   2723 
   2724   // Opaque layer, drawn without blending.
   2725   layer1->SetContentsOpaque(true);
   2726   layer1->SetExpectation(false, false);
   2727   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2728   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2729   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2730   EXPECT_TRUE(layer1->quads_appended());
   2731   host_impl_->DidDrawAllLayers(frame);
   2732 
   2733   // Layer with translucent content and painting, so drawn with blending.
   2734   layer1->SetContentsOpaque(false);
   2735   layer1->SetExpectation(true, false);
   2736   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2737   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2738   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2739   EXPECT_TRUE(layer1->quads_appended());
   2740   host_impl_->DidDrawAllLayers(frame);
   2741 
   2742   // Layer with translucent opacity, drawn with blending.
   2743   layer1->SetContentsOpaque(true);
   2744   layer1->SetOpacity(0.5f);
   2745   layer1->SetExpectation(true, false);
   2746   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2747   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2748   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2749   EXPECT_TRUE(layer1->quads_appended());
   2750   host_impl_->DidDrawAllLayers(frame);
   2751 
   2752   // Layer with translucent opacity and painting, drawn with blending.
   2753   layer1->SetContentsOpaque(true);
   2754   layer1->SetOpacity(0.5f);
   2755   layer1->SetExpectation(true, false);
   2756   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2757   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2758   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2759   EXPECT_TRUE(layer1->quads_appended());
   2760   host_impl_->DidDrawAllLayers(frame);
   2761 
   2762   layer1->AddChild(
   2763       BlendStateCheckLayer::Create(host_impl_->active_tree(),
   2764                                    3,
   2765                                    host_impl_->resource_provider()));
   2766   BlendStateCheckLayer* layer2 =
   2767       static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
   2768   layer2->SetPosition(gfx::PointF(4.f, 4.f));
   2769 
   2770   // 2 opaque layers, drawn without blending.
   2771   layer1->SetContentsOpaque(true);
   2772   layer1->SetOpacity(1.f);
   2773   layer1->SetExpectation(false, false);
   2774   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2775   layer2->SetContentsOpaque(true);
   2776   layer2->SetOpacity(1.f);
   2777   layer2->SetExpectation(false, false);
   2778   layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2779   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2780   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2781   EXPECT_TRUE(layer1->quads_appended());
   2782   EXPECT_TRUE(layer2->quads_appended());
   2783   host_impl_->DidDrawAllLayers(frame);
   2784 
   2785   // Parent layer with translucent content, drawn with blending.
   2786   // Child layer with opaque content, drawn without blending.
   2787   layer1->SetContentsOpaque(false);
   2788   layer1->SetExpectation(true, false);
   2789   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2790   layer2->SetExpectation(false, false);
   2791   layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2792   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2793   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2794   EXPECT_TRUE(layer1->quads_appended());
   2795   EXPECT_TRUE(layer2->quads_appended());
   2796   host_impl_->DidDrawAllLayers(frame);
   2797 
   2798   // Parent layer with translucent content but opaque painting, drawn without
   2799   // blending.
   2800   // Child layer with opaque content, drawn without blending.
   2801   layer1->SetContentsOpaque(true);
   2802   layer1->SetExpectation(false, false);
   2803   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2804   layer2->SetExpectation(false, false);
   2805   layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2806   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2807   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2808   EXPECT_TRUE(layer1->quads_appended());
   2809   EXPECT_TRUE(layer2->quads_appended());
   2810   host_impl_->DidDrawAllLayers(frame);
   2811 
   2812   // Parent layer with translucent opacity and opaque content. Since it has a
   2813   // drawing child, it's drawn to a render surface which carries the opacity,
   2814   // so it's itself drawn without blending.
   2815   // Child layer with opaque content, drawn without blending (parent surface
   2816   // carries the inherited opacity).
   2817   layer1->SetContentsOpaque(true);
   2818   layer1->SetOpacity(0.5f);
   2819   layer1->SetExpectation(false, true);
   2820   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2821   layer2->SetExpectation(false, false);
   2822   layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2823   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2824   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2825   EXPECT_TRUE(layer1->quads_appended());
   2826   EXPECT_TRUE(layer2->quads_appended());
   2827   host_impl_->DidDrawAllLayers(frame);
   2828 
   2829   // Draw again, but with child non-opaque, to make sure
   2830   // layer1 not culled.
   2831   layer1->SetContentsOpaque(true);
   2832   layer1->SetOpacity(1.f);
   2833   layer1->SetExpectation(false, false);
   2834   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2835   layer2->SetContentsOpaque(true);
   2836   layer2->SetOpacity(0.5f);
   2837   layer2->SetExpectation(true, false);
   2838   layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2839   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2840   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2841   EXPECT_TRUE(layer1->quads_appended());
   2842   EXPECT_TRUE(layer2->quads_appended());
   2843   host_impl_->DidDrawAllLayers(frame);
   2844 
   2845   // A second way of making the child non-opaque.
   2846   layer1->SetContentsOpaque(true);
   2847   layer1->SetOpacity(1.f);
   2848   layer1->SetExpectation(false, false);
   2849   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2850   layer2->SetContentsOpaque(false);
   2851   layer2->SetOpacity(1.f);
   2852   layer2->SetExpectation(true, false);
   2853   layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2854   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2855   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2856   EXPECT_TRUE(layer1->quads_appended());
   2857   EXPECT_TRUE(layer2->quads_appended());
   2858   host_impl_->DidDrawAllLayers(frame);
   2859 
   2860   // And when the layer says its not opaque but is painted opaque, it is not
   2861   // blended.
   2862   layer1->SetContentsOpaque(true);
   2863   layer1->SetOpacity(1.f);
   2864   layer1->SetExpectation(false, false);
   2865   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2866   layer2->SetContentsOpaque(true);
   2867   layer2->SetOpacity(1.f);
   2868   layer2->SetExpectation(false, false);
   2869   layer2->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2870   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2871   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2872   EXPECT_TRUE(layer1->quads_appended());
   2873   EXPECT_TRUE(layer2->quads_appended());
   2874   host_impl_->DidDrawAllLayers(frame);
   2875 
   2876   // Layer with partially opaque contents, drawn with blending.
   2877   layer1->SetContentsOpaque(false);
   2878   layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
   2879   layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
   2880   layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
   2881   layer1->SetExpectation(true, false);
   2882   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2883   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2884   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2885   EXPECT_TRUE(layer1->quads_appended());
   2886   host_impl_->DidDrawAllLayers(frame);
   2887 
   2888   // Layer with partially opaque contents partially culled, drawn with blending.
   2889   layer1->SetContentsOpaque(false);
   2890   layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
   2891   layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
   2892   layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
   2893   layer1->SetExpectation(true, false);
   2894   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2895   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2896   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2897   EXPECT_TRUE(layer1->quads_appended());
   2898   host_impl_->DidDrawAllLayers(frame);
   2899 
   2900   // Layer with partially opaque contents culled, drawn with blending.
   2901   layer1->SetContentsOpaque(false);
   2902   layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
   2903   layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
   2904   layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
   2905   layer1->SetExpectation(true, false);
   2906   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2907   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2908   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2909   EXPECT_TRUE(layer1->quads_appended());
   2910   host_impl_->DidDrawAllLayers(frame);
   2911 
   2912   // Layer with partially opaque contents and translucent contents culled, drawn
   2913   // without blending.
   2914   layer1->SetContentsOpaque(false);
   2915   layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
   2916   layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
   2917   layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
   2918   layer1->SetExpectation(false, false);
   2919   layer1->set_update_rect(gfx::RectF(layer1->content_bounds()));
   2920   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2921   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   2922   EXPECT_TRUE(layer1->quads_appended());
   2923   host_impl_->DidDrawAllLayers(frame);
   2924 }
   2925 
   2926 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
   2927  public:
   2928   void CreateLayerTreeHostImpl(bool always_draw) {
   2929     LayerTreeSettings settings;
   2930     settings.minimum_occlusion_tracking_size = gfx::Size();
   2931     settings.impl_side_painting = true;
   2932     host_impl_ = LayerTreeHostImpl::Create(
   2933         settings, this, &proxy_, &stats_instrumentation_);
   2934     scoped_ptr<OutputSurface> output_surface;
   2935     if (always_draw) {
   2936       output_surface = FakeOutputSurface::CreateAlwaysDrawAndSwap3d()
   2937           .PassAs<OutputSurface>();
   2938     } else {
   2939       output_surface = CreateFakeOutputSurface();
   2940     }
   2941     host_impl_->InitializeRenderer(output_surface.Pass());
   2942     viewport_size_ = gfx::Size(1000, 1000);
   2943   }
   2944 
   2945   void SetupActiveTreeLayers() {
   2946     host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
   2947     host_impl_->active_tree()->SetRootLayer(
   2948         LayerImpl::Create(host_impl_->active_tree(), 1));
   2949     host_impl_->active_tree()->root_layer()->AddChild(
   2950         BlendStateCheckLayer::Create(host_impl_->active_tree(),
   2951                                      2,
   2952                                      host_impl_->resource_provider()));
   2953     child_ = static_cast<BlendStateCheckLayer*>(
   2954         host_impl_->active_tree()->root_layer()->children()[0]);
   2955     child_->SetExpectation(false, false);
   2956     child_->SetContentsOpaque(true);
   2957   }
   2958 
   2959   // Expect no gutter rects.
   2960   void TestLayerCoversFullViewport() {
   2961     gfx::Rect layer_rect(viewport_size_);
   2962     child_->SetPosition(layer_rect.origin());
   2963     child_->SetBounds(layer_rect.size());
   2964     child_->SetContentBounds(layer_rect.size());
   2965     child_->SetQuadRect(gfx::Rect(layer_rect.size()));
   2966     child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
   2967 
   2968     LayerTreeHostImpl::FrameData frame;
   2969     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2970     ASSERT_EQ(1u, frame.render_passes.size());
   2971 
   2972     size_t num_gutter_quads = 0;
   2973     for (size_t i = 0; i < frame.render_passes[0]->quad_list.size(); ++i)
   2974       num_gutter_quads += (frame.render_passes[0]->quad_list[i]->material ==
   2975                            DrawQuad::SOLID_COLOR) ? 1 : 0;
   2976     EXPECT_EQ(0u, num_gutter_quads);
   2977     EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
   2978 
   2979     LayerTestCommon::VerifyQuadsExactlyCoverRect(
   2980         frame.render_passes[0]->quad_list, gfx::Rect(viewport_size_));
   2981     host_impl_->DidDrawAllLayers(frame);
   2982   }
   2983 
   2984   // Expect fullscreen gutter rect.
   2985   void TestEmptyLayer() {
   2986     gfx::Rect layer_rect(0, 0, 0, 0);
   2987     child_->SetPosition(layer_rect.origin());
   2988     child_->SetBounds(layer_rect.size());
   2989     child_->SetContentBounds(layer_rect.size());
   2990     child_->SetQuadRect(gfx::Rect(layer_rect.size()));
   2991     child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
   2992 
   2993     LayerTreeHostImpl::FrameData frame;
   2994     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   2995     ASSERT_EQ(1u, frame.render_passes.size());
   2996 
   2997     size_t num_gutter_quads = 0;
   2998     for (size_t i = 0; i < frame.render_passes[0]->quad_list.size(); ++i)
   2999       num_gutter_quads += (frame.render_passes[0]->quad_list[i]->material ==
   3000                            DrawQuad::SOLID_COLOR) ? 1 : 0;
   3001     EXPECT_EQ(1u, num_gutter_quads);
   3002     EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
   3003 
   3004     LayerTestCommon::VerifyQuadsExactlyCoverRect(
   3005         frame.render_passes[0]->quad_list, gfx::Rect(viewport_size_));
   3006     host_impl_->DidDrawAllLayers(frame);
   3007   }
   3008 
   3009   // Expect four surrounding gutter rects.
   3010   void TestLayerInMiddleOfViewport() {
   3011     gfx::Rect layer_rect(500, 500, 200, 200);
   3012     child_->SetPosition(layer_rect.origin());
   3013     child_->SetBounds(layer_rect.size());
   3014     child_->SetContentBounds(layer_rect.size());
   3015     child_->SetQuadRect(gfx::Rect(layer_rect.size()));
   3016     child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
   3017 
   3018     LayerTreeHostImpl::FrameData frame;
   3019     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3020     ASSERT_EQ(1u, frame.render_passes.size());
   3021 
   3022     size_t num_gutter_quads = 0;
   3023     for (size_t i = 0; i < frame.render_passes[0]->quad_list.size(); ++i)
   3024       num_gutter_quads += (frame.render_passes[0]->quad_list[i]->material ==
   3025                            DrawQuad::SOLID_COLOR) ? 1 : 0;
   3026     EXPECT_EQ(4u, num_gutter_quads);
   3027     EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
   3028 
   3029     LayerTestCommon::VerifyQuadsExactlyCoverRect(
   3030         frame.render_passes[0]->quad_list, gfx::Rect(viewport_size_));
   3031     host_impl_->DidDrawAllLayers(frame);
   3032   }
   3033 
   3034   // Expect no gutter rects.
   3035   void TestLayerIsLargerThanViewport() {
   3036     gfx::Rect layer_rect(viewport_size_.width() + 10,
   3037                          viewport_size_.height() + 10);
   3038     child_->SetPosition(layer_rect.origin());
   3039     child_->SetBounds(layer_rect.size());
   3040     child_->SetContentBounds(layer_rect.size());
   3041     child_->SetQuadRect(gfx::Rect(layer_rect.size()));
   3042     child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
   3043 
   3044     LayerTreeHostImpl::FrameData frame;
   3045     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3046     ASSERT_EQ(1u, frame.render_passes.size());
   3047 
   3048     size_t num_gutter_quads = 0;
   3049     for (size_t i = 0; i < frame.render_passes[0]->quad_list.size(); ++i)
   3050       num_gutter_quads += (frame.render_passes[0]->quad_list[i]->material ==
   3051                            DrawQuad::SOLID_COLOR) ? 1 : 0;
   3052     EXPECT_EQ(0u, num_gutter_quads);
   3053     EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
   3054 
   3055     host_impl_->DidDrawAllLayers(frame);
   3056   }
   3057 
   3058   virtual void DidActivatePendingTree() OVERRIDE {
   3059     did_activate_pending_tree_ = true;
   3060   }
   3061 
   3062  protected:
   3063   gfx::Size viewport_size_;
   3064   BlendStateCheckLayer* child_;
   3065   bool did_activate_pending_tree_;
   3066 };
   3067 
   3068 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
   3069   bool always_draw = false;
   3070   CreateLayerTreeHostImpl(always_draw);
   3071 
   3072   host_impl_->SetViewportSize(viewport_size_);
   3073   SetupActiveTreeLayers();
   3074   TestLayerCoversFullViewport();
   3075   TestEmptyLayer();
   3076   TestLayerInMiddleOfViewport();
   3077   TestLayerIsLargerThanViewport();
   3078 }
   3079 
   3080 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
   3081   bool always_draw = true;
   3082   CreateLayerTreeHostImpl(always_draw);
   3083 
   3084   // Pending tree to force active_tree size invalid. Not used otherwise.
   3085   host_impl_->CreatePendingTree();
   3086   host_impl_->SetViewportSize(viewport_size_);
   3087   EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
   3088 
   3089   SetupActiveTreeLayers();
   3090   TestEmptyLayer();
   3091   TestLayerInMiddleOfViewport();
   3092   TestLayerIsLargerThanViewport();
   3093 }
   3094 
   3095 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
   3096   bool always_draw = true;
   3097   CreateLayerTreeHostImpl(always_draw);
   3098 
   3099   // Set larger viewport and activate it to active tree.
   3100   host_impl_->CreatePendingTree();
   3101   gfx::Size larger_viewport(viewport_size_.width() + 100,
   3102                             viewport_size_.height() + 100);
   3103   host_impl_->SetViewportSize(larger_viewport);
   3104   EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
   3105   did_activate_pending_tree_ = false;
   3106   host_impl_->ActivatePendingTreeIfNeeded();
   3107   EXPECT_TRUE(did_activate_pending_tree_);
   3108   EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
   3109 
   3110   // Shrink pending tree viewport without activating.
   3111   host_impl_->CreatePendingTree();
   3112   host_impl_->SetViewportSize(viewport_size_);
   3113   EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
   3114 
   3115   SetupActiveTreeLayers();
   3116   TestEmptyLayer();
   3117   TestLayerInMiddleOfViewport();
   3118   TestLayerIsLargerThanViewport();
   3119 }
   3120 
   3121 class ReshapeTrackerContext: public TestWebGraphicsContext3D {
   3122  public:
   3123   ReshapeTrackerContext()
   3124     : reshape_called_(false),
   3125       last_reshape_width_(-1),
   3126       last_reshape_height_(-1),
   3127       last_reshape_scale_factor_(-1.f) {
   3128   }
   3129 
   3130   virtual void reshapeWithScaleFactor(
   3131       int width, int height, float scale_factor) OVERRIDE {
   3132     reshape_called_ = true;
   3133     last_reshape_width_ = width;
   3134     last_reshape_height_ = height;
   3135     last_reshape_scale_factor_ = scale_factor;
   3136   }
   3137 
   3138   bool reshape_called() const { return reshape_called_; }
   3139   void clear_reshape_called() { reshape_called_ = false; }
   3140   int last_reshape_width() { return last_reshape_width_; }
   3141   int last_reshape_height() { return last_reshape_height_; }
   3142   int last_reshape_scale_factor() { return last_reshape_scale_factor_; }
   3143 
   3144  private:
   3145   bool reshape_called_;
   3146   int last_reshape_width_;
   3147   int last_reshape_height_;
   3148   float last_reshape_scale_factor_;
   3149 };
   3150 
   3151 class FakeDrawableLayerImpl: public LayerImpl {
   3152  public:
   3153   static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
   3154     return scoped_ptr<LayerImpl>(new FakeDrawableLayerImpl(tree_impl, id));
   3155   }
   3156  protected:
   3157   FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
   3158       : LayerImpl(tree_impl, id) {}
   3159 };
   3160 
   3161 // Only reshape when we know we are going to draw. Otherwise, the reshape
   3162 // can leave the window at the wrong size if we never draw and the proper
   3163 // viewport size is never set.
   3164 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
   3165   scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(
   3166       scoped_ptr<WebKit::WebGraphicsContext3D>(new ReshapeTrackerContext))
   3167       .PassAs<OutputSurface>();
   3168   ReshapeTrackerContext* reshape_tracker =
   3169       static_cast<ReshapeTrackerContext*>(output_surface->context3d());
   3170   host_impl_->InitializeRenderer(output_surface.Pass());
   3171 
   3172   scoped_ptr<LayerImpl> root =
   3173       FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
   3174   root->SetAnchorPoint(gfx::PointF());
   3175   root->SetBounds(gfx::Size(10, 10));
   3176   root->SetContentBounds(gfx::Size(10, 10));
   3177   root->SetDrawsContent(true);
   3178   host_impl_->active_tree()->SetRootLayer(root.Pass());
   3179   EXPECT_FALSE(reshape_tracker->reshape_called());
   3180   reshape_tracker->clear_reshape_called();
   3181 
   3182   LayerTreeHostImpl::FrameData frame;
   3183   host_impl_->SetViewportSize(gfx::Size(10, 10));
   3184   host_impl_->SetDeviceScaleFactor(1.f);
   3185   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3186   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3187   EXPECT_TRUE(reshape_tracker->reshape_called());
   3188   EXPECT_EQ(reshape_tracker->last_reshape_width(), 10);
   3189   EXPECT_EQ(reshape_tracker->last_reshape_height(), 10);
   3190   EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 1.f);
   3191   host_impl_->DidDrawAllLayers(frame);
   3192   reshape_tracker->clear_reshape_called();
   3193 
   3194   host_impl_->SetViewportSize(gfx::Size(20, 30));
   3195   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3196   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3197   EXPECT_TRUE(reshape_tracker->reshape_called());
   3198   EXPECT_EQ(reshape_tracker->last_reshape_width(), 20);
   3199   EXPECT_EQ(reshape_tracker->last_reshape_height(), 30);
   3200   EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 1.f);
   3201   host_impl_->DidDrawAllLayers(frame);
   3202   reshape_tracker->clear_reshape_called();
   3203 
   3204   host_impl_->SetDeviceScaleFactor(2.f);
   3205   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3206   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3207   EXPECT_TRUE(reshape_tracker->reshape_called());
   3208   EXPECT_EQ(reshape_tracker->last_reshape_width(), 20);
   3209   EXPECT_EQ(reshape_tracker->last_reshape_height(), 30);
   3210   EXPECT_EQ(reshape_tracker->last_reshape_scale_factor(), 2.f);
   3211   host_impl_->DidDrawAllLayers(frame);
   3212   reshape_tracker->clear_reshape_called();
   3213 }
   3214 
   3215 class SwapTrackerContext : public TestWebGraphicsContext3D {
   3216  public:
   3217   SwapTrackerContext() : last_update_type_(NoUpdate) {}
   3218 
   3219   virtual void prepareTexture() OVERRIDE {
   3220     update_rect_ = gfx::Rect(width_, height_);
   3221     last_update_type_ = PrepareTexture;
   3222   }
   3223 
   3224   virtual void postSubBufferCHROMIUM(int x, int y, int width, int height)
   3225       OVERRIDE {
   3226     update_rect_ = gfx::Rect(x, y, width, height);
   3227     last_update_type_ = PostSubBuffer;
   3228   }
   3229 
   3230   virtual WebKit::WebString getString(WebKit::WGC3Denum name) OVERRIDE {
   3231     if (name == GL_EXTENSIONS) {
   3232       return WebKit::WebString(
   3233           "GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
   3234     }
   3235 
   3236     return WebKit::WebString();
   3237   }
   3238 
   3239   gfx::Rect update_rect() const { return update_rect_; }
   3240 
   3241   enum UpdateType {
   3242     NoUpdate = 0,
   3243     PrepareTexture,
   3244     PostSubBuffer
   3245   };
   3246 
   3247   UpdateType last_update_type() {
   3248     return last_update_type_;
   3249   }
   3250 
   3251  private:
   3252   gfx::Rect update_rect_;
   3253   UpdateType last_update_type_;
   3254 };
   3255 
   3256 // Make sure damage tracking propagates all the way to the graphics context,
   3257 // where it should request to swap only the sub-buffer that is damaged.
   3258 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
   3259   scoped_ptr<OutputSurface> output_surface =
   3260       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   3261           new SwapTrackerContext)).PassAs<OutputSurface>();
   3262   SwapTrackerContext* swap_tracker =
   3263       static_cast<SwapTrackerContext*>(output_surface->context3d());
   3264 
   3265   // This test creates its own LayerTreeHostImpl, so
   3266   // that we can force partial swap enabled.
   3267   LayerTreeSettings settings;
   3268   settings.partial_swap_enabled = true;
   3269   scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
   3270       LayerTreeHostImpl::Create(settings,
   3271                                 this,
   3272                                 &proxy_,
   3273                                 &stats_instrumentation_);
   3274   layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
   3275   layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
   3276 
   3277   scoped_ptr<LayerImpl> root =
   3278       FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
   3279   scoped_ptr<LayerImpl> child =
   3280       FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
   3281   child->SetPosition(gfx::PointF(12.f, 13.f));
   3282   child->SetAnchorPoint(gfx::PointF());
   3283   child->SetBounds(gfx::Size(14, 15));
   3284   child->SetContentBounds(gfx::Size(14, 15));
   3285   child->SetDrawsContent(true);
   3286   root->SetAnchorPoint(gfx::PointF());
   3287   root->SetBounds(gfx::Size(500, 500));
   3288   root->SetContentBounds(gfx::Size(500, 500));
   3289   root->SetDrawsContent(true);
   3290   root->AddChild(child.Pass());
   3291   layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
   3292 
   3293   LayerTreeHostImpl::FrameData frame;
   3294 
   3295   // First frame, the entire screen should get swapped.
   3296   EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   3297   layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   3298   layer_tree_host_impl->DidDrawAllLayers(frame);
   3299   layer_tree_host_impl->SwapBuffers(frame);
   3300   gfx::Rect actual_swap_rect = swap_tracker->update_rect();
   3301   gfx::Rect expected_swap_rect = gfx::Rect(0, 0, 500, 500);
   3302   EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
   3303   EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
   3304   EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
   3305   EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
   3306   EXPECT_EQ(swap_tracker->last_update_type(),
   3307             SwapTrackerContext::PrepareTexture);
   3308   // Second frame, only the damaged area should get swapped. Damage should be
   3309   // the union of old and new child rects.
   3310   // expected damage rect: gfx::Rect(26, 28);
   3311   // expected swap rect: vertically flipped, with origin at bottom left corner.
   3312   layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
   3313       gfx::PointF());
   3314   EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   3315   layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   3316   host_impl_->DidDrawAllLayers(frame);
   3317   layer_tree_host_impl->SwapBuffers(frame);
   3318   actual_swap_rect = swap_tracker->update_rect();
   3319   expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
   3320   EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
   3321   EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
   3322   EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
   3323   EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
   3324   EXPECT_EQ(swap_tracker->last_update_type(),
   3325             SwapTrackerContext::PostSubBuffer);
   3326 
   3327   // Make sure that partial swap is constrained to the viewport dimensions
   3328   // expected damage rect: gfx::Rect(500, 500);
   3329   // expected swap rect: flipped damage rect, but also clamped to viewport
   3330   layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
   3331   // This will damage everything.
   3332   layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
   3333       SK_ColorBLACK);
   3334   EXPECT_TRUE(layer_tree_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   3335   layer_tree_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   3336   host_impl_->DidDrawAllLayers(frame);
   3337   layer_tree_host_impl->SwapBuffers(frame);
   3338   actual_swap_rect = swap_tracker->update_rect();
   3339   expected_swap_rect = gfx::Rect(10, 10);
   3340   EXPECT_EQ(expected_swap_rect.x(), actual_swap_rect.x());
   3341   EXPECT_EQ(expected_swap_rect.y(), actual_swap_rect.y());
   3342   EXPECT_EQ(expected_swap_rect.width(), actual_swap_rect.width());
   3343   EXPECT_EQ(expected_swap_rect.height(), actual_swap_rect.height());
   3344   EXPECT_EQ(swap_tracker->last_update_type(),
   3345             SwapTrackerContext::PrepareTexture);
   3346 }
   3347 
   3348 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
   3349   scoped_ptr<LayerImpl> root =
   3350       FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
   3351   scoped_ptr<LayerImpl> child =
   3352       FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
   3353   child->SetAnchorPoint(gfx::PointF());
   3354   child->SetBounds(gfx::Size(10, 10));
   3355   child->SetContentBounds(gfx::Size(10, 10));
   3356   child->SetDrawsContent(true);
   3357   root->SetAnchorPoint(gfx::PointF());
   3358   root->SetBounds(gfx::Size(10, 10));
   3359   root->SetContentBounds(gfx::Size(10, 10));
   3360   root->SetDrawsContent(true);
   3361   root->SetForceRenderSurface(true);
   3362   root->AddChild(child.Pass());
   3363 
   3364   host_impl_->active_tree()->SetRootLayer(root.Pass());
   3365 
   3366   LayerTreeHostImpl::FrameData frame;
   3367 
   3368   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3369   EXPECT_EQ(1u, frame.render_surface_layer_list->size());
   3370   EXPECT_EQ(1u, frame.render_passes.size());
   3371   host_impl_->DidDrawAllLayers(frame);
   3372 }
   3373 
   3374 class FakeLayerWithQuads : public LayerImpl {
   3375  public:
   3376   static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
   3377     return scoped_ptr<LayerImpl>(new FakeLayerWithQuads(tree_impl, id));
   3378   }
   3379 
   3380   virtual void AppendQuads(QuadSink* quad_sink,
   3381                            AppendQuadsData* append_quads_data) OVERRIDE {
   3382     SharedQuadState* shared_quad_state =
   3383         quad_sink->UseSharedQuadState(CreateSharedQuadState());
   3384 
   3385     SkColor gray = SkColorSetRGB(100, 100, 100);
   3386     gfx::Rect quad_rect(content_bounds());
   3387     scoped_ptr<SolidColorDrawQuad> my_quad = SolidColorDrawQuad::Create();
   3388     my_quad->SetNew(shared_quad_state, quad_rect, gray, false);
   3389     quad_sink->Append(my_quad.PassAs<DrawQuad>(), append_quads_data);
   3390   }
   3391 
   3392  private:
   3393   FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
   3394       : LayerImpl(tree_impl, id) {}
   3395 };
   3396 
   3397 class MockContext : public TestWebGraphicsContext3D {
   3398  public:
   3399   MOCK_METHOD1(useProgram, void(WebKit::WebGLId program));
   3400   MOCK_METHOD5(uniform4f, void(WebKit::WGC3Dint location,
   3401                                WebKit::WGC3Dfloat x,
   3402                                WebKit::WGC3Dfloat y,
   3403                                WebKit::WGC3Dfloat z,
   3404                                WebKit::WGC3Dfloat w));
   3405   MOCK_METHOD4(uniformMatrix4fv, void(WebKit::WGC3Dint location,
   3406                                       WebKit::WGC3Dsizei count,
   3407                                       WebKit::WGC3Dboolean transpose,
   3408                                       const WebKit::WGC3Dfloat* value));
   3409   MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode,
   3410                                   WebKit::WGC3Dsizei count,
   3411                                   WebKit::WGC3Denum type,
   3412                                   WebKit::WGC3Dintptr offset));
   3413   MOCK_METHOD1(getString, WebKit::WebString(WebKit::WGC3Denum name));
   3414   MOCK_METHOD0(getRequestableExtensionsCHROMIUM, WebKit::WebString());
   3415   MOCK_METHOD1(enable, void(WebKit::WGC3Denum cap));
   3416   MOCK_METHOD1(disable, void(WebKit::WGC3Denum cap));
   3417   MOCK_METHOD4(scissor, void(WebKit::WGC3Dint x,
   3418                              WebKit::WGC3Dint y,
   3419                              WebKit::WGC3Dsizei width,
   3420                              WebKit::WGC3Dsizei height));
   3421 };
   3422 
   3423 class MockContextHarness {
   3424  private:
   3425   MockContext* context_;
   3426 
   3427  public:
   3428   explicit MockContextHarness(MockContext* context)
   3429       : context_(context) {
   3430     // Catch "uninteresting" calls
   3431     EXPECT_CALL(*context_, useProgram(_))
   3432         .Times(0);
   3433 
   3434     EXPECT_CALL(*context_, drawElements(_, _, _, _))
   3435         .Times(0);
   3436 
   3437     // These are not asserted
   3438     EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
   3439         .WillRepeatedly(Return());
   3440 
   3441     EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
   3442         .WillRepeatedly(Return());
   3443 
   3444     // Any other strings are empty
   3445     EXPECT_CALL(*context_, getString(_))
   3446         .WillRepeatedly(Return(WebKit::WebString()));
   3447 
   3448     // Support for partial swap, if needed
   3449     EXPECT_CALL(*context_, getString(GL_EXTENSIONS))
   3450         .WillRepeatedly(Return(
   3451             WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
   3452 
   3453     EXPECT_CALL(*context_, getRequestableExtensionsCHROMIUM())
   3454         .WillRepeatedly(Return(
   3455             WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
   3456 
   3457     // Any un-sanctioned calls to enable() are OK
   3458     EXPECT_CALL(*context_, enable(_))
   3459         .WillRepeatedly(Return());
   3460 
   3461     // Any un-sanctioned calls to disable() are OK
   3462     EXPECT_CALL(*context_, disable(_))
   3463         .WillRepeatedly(Return());
   3464   }
   3465 
   3466   void MustDrawSolidQuad() {
   3467     EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
   3468         .WillOnce(Return())
   3469         .RetiresOnSaturation();
   3470 
   3471     EXPECT_CALL(*context_, useProgram(_))
   3472         .WillOnce(Return())
   3473         .RetiresOnSaturation();
   3474   }
   3475 
   3476   void MustSetScissor(int x, int y, int width, int height) {
   3477     EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
   3478         .WillRepeatedly(Return());
   3479 
   3480     EXPECT_CALL(*context_, scissor(x, y, width, height))
   3481         .Times(AtLeast(1))
   3482         .WillRepeatedly(Return());
   3483   }
   3484 
   3485   void MustSetNoScissor() {
   3486     EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
   3487         .WillRepeatedly(Return());
   3488 
   3489     EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
   3490         .Times(0);
   3491 
   3492     EXPECT_CALL(*context_, scissor(_, _, _, _))
   3493         .Times(0);
   3494   }
   3495 };
   3496 
   3497 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
   3498   scoped_ptr<OutputSurface> output_surface =
   3499       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   3500           new MockContext)).PassAs<OutputSurface>();
   3501   MockContext* mock_context =
   3502       static_cast<MockContext*>(output_surface->context3d());
   3503   MockContextHarness harness(mock_context);
   3504 
   3505   // Run test case
   3506   CreateLayerTreeHost(false, output_surface.Pass());
   3507   SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
   3508 
   3509   // Without partial swap, and no clipping, no scissor is set.
   3510   harness.MustDrawSolidQuad();
   3511   harness.MustSetNoScissor();
   3512   {
   3513     LayerTreeHostImpl::FrameData frame;
   3514     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3515     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3516     host_impl_->DidDrawAllLayers(frame);
   3517   }
   3518   Mock::VerifyAndClearExpectations(&mock_context);
   3519 
   3520   // Without partial swap, but a layer does clip its subtree, one scissor is
   3521   // set.
   3522   host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
   3523   harness.MustDrawSolidQuad();
   3524   harness.MustSetScissor(0, 0, 10, 10);
   3525   {
   3526     LayerTreeHostImpl::FrameData frame;
   3527     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3528     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3529     host_impl_->DidDrawAllLayers(frame);
   3530   }
   3531   Mock::VerifyAndClearExpectations(&mock_context);
   3532 }
   3533 
   3534 TEST_F(LayerTreeHostImplTest, PartialSwap) {
   3535   scoped_ptr<OutputSurface> output_surface =
   3536       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   3537           new MockContext)).PassAs<OutputSurface>();
   3538   MockContext* mock_context =
   3539       static_cast<MockContext*>(output_surface->context3d());
   3540   MockContextHarness harness(mock_context);
   3541 
   3542   CreateLayerTreeHost(true, output_surface.Pass());
   3543   SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
   3544 
   3545   // The first frame is not a partially-swapped one.
   3546   harness.MustSetScissor(0, 0, 10, 10);
   3547   harness.MustDrawSolidQuad();
   3548   {
   3549     LayerTreeHostImpl::FrameData frame;
   3550     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3551     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3552     host_impl_->DidDrawAllLayers(frame);
   3553   }
   3554   Mock::VerifyAndClearExpectations(&mock_context);
   3555 
   3556   // Damage a portion of the frame.
   3557   host_impl_->active_tree()->root_layer()->set_update_rect(
   3558       gfx::Rect(0, 0, 2, 3));
   3559 
   3560   // The second frame will be partially-swapped (the y coordinates are flipped).
   3561   harness.MustSetScissor(0, 7, 2, 3);
   3562   harness.MustDrawSolidQuad();
   3563   {
   3564     LayerTreeHostImpl::FrameData frame;
   3565     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3566     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3567     host_impl_->DidDrawAllLayers(frame);
   3568   }
   3569   Mock::VerifyAndClearExpectations(&mock_context);
   3570 }
   3571 
   3572 class PartialSwapContext : public TestWebGraphicsContext3D {
   3573  public:
   3574   virtual WebKit::WebString getString(WebKit::WGC3Denum name) OVERRIDE {
   3575     if (name == GL_EXTENSIONS)
   3576       return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
   3577     return WebKit::WebString();
   3578   }
   3579 
   3580   virtual WebKit::WebString getRequestableExtensionsCHROMIUM() OVERRIDE {
   3581     return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
   3582   }
   3583 
   3584   // Unlimited texture size.
   3585   virtual void getIntegerv(WebKit::WGC3Denum pname, WebKit::WGC3Dint* value)
   3586       OVERRIDE {
   3587     if (pname == GL_MAX_TEXTURE_SIZE)
   3588       *value = 8192;
   3589     else if (pname == GL_ACTIVE_TEXTURE)
   3590       *value = GL_TEXTURE0;
   3591   }
   3592 };
   3593 
   3594 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
   3595     bool partial_swap,
   3596     LayerTreeHostImplClient* client,
   3597     Proxy* proxy,
   3598     RenderingStatsInstrumentation* stats_instrumentation) {
   3599   scoped_ptr<OutputSurface> output_surface =
   3600       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   3601           new PartialSwapContext)).PassAs<OutputSurface>();
   3602 
   3603   LayerTreeSettings settings;
   3604   settings.partial_swap_enabled = partial_swap;
   3605   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   3606       LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation);
   3607   my_host_impl->InitializeRenderer(output_surface.Pass());
   3608   my_host_impl->SetViewportSize(gfx::Size(100, 100));
   3609 
   3610   /*
   3611     Layers are created as follows:
   3612 
   3613     +--------------------+
   3614     |                  1 |
   3615     |  +-----------+     |
   3616     |  |         2 |     |
   3617     |  | +-------------------+
   3618     |  | |   3               |
   3619     |  | +-------------------+
   3620     |  |           |     |
   3621     |  +-----------+     |
   3622     |                    |
   3623     |                    |
   3624     +--------------------+
   3625 
   3626     Layers 1, 2 have render surfaces
   3627   */
   3628   scoped_ptr<LayerImpl> root =
   3629       LayerImpl::Create(my_host_impl->active_tree(), 1);
   3630   scoped_ptr<LayerImpl> child =
   3631       LayerImpl::Create(my_host_impl->active_tree(), 2);
   3632   scoped_ptr<LayerImpl> grand_child =
   3633       FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
   3634 
   3635   gfx::Rect root_rect(0, 0, 100, 100);
   3636   gfx::Rect child_rect(10, 10, 50, 50);
   3637   gfx::Rect grand_child_rect(5, 5, 150, 150);
   3638 
   3639   root->CreateRenderSurface();
   3640   root->SetAnchorPoint(gfx::PointF());
   3641   root->SetPosition(root_rect.origin());
   3642   root->SetBounds(root_rect.size());
   3643   root->SetContentBounds(root->bounds());
   3644   root->draw_properties().visible_content_rect = root_rect;
   3645   root->SetDrawsContent(false);
   3646   root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
   3647 
   3648   child->SetAnchorPoint(gfx::PointF());
   3649   child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
   3650   child->SetOpacity(0.5f);
   3651   child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
   3652   child->SetContentBounds(child->bounds());
   3653   child->draw_properties().visible_content_rect = child_rect;
   3654   child->SetDrawsContent(false);
   3655   child->SetForceRenderSurface(true);
   3656 
   3657   grand_child->SetAnchorPoint(gfx::PointF());
   3658   grand_child->SetPosition(grand_child_rect.origin());
   3659   grand_child->SetBounds(grand_child_rect.size());
   3660   grand_child->SetContentBounds(grand_child->bounds());
   3661   grand_child->draw_properties().visible_content_rect = grand_child_rect;
   3662   grand_child->SetDrawsContent(true);
   3663 
   3664   child->AddChild(grand_child.Pass());
   3665   root->AddChild(child.Pass());
   3666 
   3667   my_host_impl->active_tree()->SetRootLayer(root.Pass());
   3668   return my_host_impl.Pass();
   3669 }
   3670 
   3671 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
   3672   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   3673       SetupLayersForOpacity(true, this, &proxy_, &stats_instrumentation_);
   3674   {
   3675     LayerTreeHostImpl::FrameData frame;
   3676     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   3677 
   3678     // Verify all quads have been computed
   3679     ASSERT_EQ(2U, frame.render_passes.size());
   3680     ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
   3681     ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
   3682     EXPECT_EQ(DrawQuad::SOLID_COLOR,
   3683               frame.render_passes[0]->quad_list[0]->material);
   3684     EXPECT_EQ(DrawQuad::RENDER_PASS,
   3685               frame.render_passes[1]->quad_list[0]->material);
   3686 
   3687     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   3688     my_host_impl->DidDrawAllLayers(frame);
   3689   }
   3690 }
   3691 
   3692 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
   3693   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   3694       SetupLayersForOpacity(false, this, &proxy_, &stats_instrumentation_);
   3695   {
   3696     LayerTreeHostImpl::FrameData frame;
   3697     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   3698 
   3699     // Verify all quads have been computed
   3700     ASSERT_EQ(2U, frame.render_passes.size());
   3701     ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
   3702     ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
   3703     EXPECT_EQ(DrawQuad::SOLID_COLOR,
   3704               frame.render_passes[0]->quad_list[0]->material);
   3705     EXPECT_EQ(DrawQuad::RENDER_PASS,
   3706               frame.render_passes[1]->quad_list[0]->material);
   3707 
   3708     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   3709     my_host_impl->DidDrawAllLayers(frame);
   3710   }
   3711 }
   3712 
   3713 // Fake WebKit::WebGraphicsContext3D that tracks the number of textures in use.
   3714 class TrackingWebGraphicsContext3D : public TestWebGraphicsContext3D {
   3715  public:
   3716   TrackingWebGraphicsContext3D()
   3717       : TestWebGraphicsContext3D(),
   3718         num_textures_(0) {}
   3719 
   3720   virtual WebKit::WebGLId createTexture() OVERRIDE {
   3721     WebKit::WebGLId id = TestWebGraphicsContext3D::createTexture();
   3722 
   3723     textures_[id] = true;
   3724     ++num_textures_;
   3725     return id;
   3726   }
   3727 
   3728   virtual void deleteTexture(WebKit::WebGLId id) OVERRIDE {
   3729     if (textures_.find(id) == textures_.end())
   3730       return;
   3731 
   3732     textures_[id] = false;
   3733     --num_textures_;
   3734   }
   3735 
   3736   virtual WebKit::WebString getString(WebKit::WGC3Denum name) OVERRIDE {
   3737     if (name == GL_EXTENSIONS) {
   3738       return WebKit::WebString(
   3739           "GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
   3740     }
   3741 
   3742     return WebKit::WebString();
   3743   }
   3744 
   3745   unsigned num_textures() const { return num_textures_; }
   3746 
   3747  private:
   3748   base::hash_map<WebKit::WebGLId, bool> textures_;
   3749   unsigned num_textures_;
   3750 };
   3751 
   3752 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
   3753   scoped_ptr<TestWebGraphicsContext3D> context =
   3754       TestWebGraphicsContext3D::Create();
   3755   TestWebGraphicsContext3D* context3d = context.get();
   3756   scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(
   3757       context.PassAs<WebKit::WebGraphicsContext3D>()).PassAs<OutputSurface>();
   3758   host_impl_->InitializeRenderer(output_surface.Pass());
   3759 
   3760   scoped_ptr<LayerImpl> root_layer =
   3761       LayerImpl::Create(host_impl_->active_tree(), 1);
   3762   root_layer->SetBounds(gfx::Size(10, 10));
   3763   root_layer->SetAnchorPoint(gfx::PointF());
   3764 
   3765   scoped_refptr<VideoFrame> softwareFrame =
   3766       media::VideoFrame::CreateColorFrame(
   3767           gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
   3768   FakeVideoFrameProvider provider;
   3769   provider.set_frame(softwareFrame);
   3770   scoped_ptr<VideoLayerImpl> video_layer =
   3771       VideoLayerImpl::Create(host_impl_->active_tree(), 4, &provider);
   3772   video_layer->SetBounds(gfx::Size(10, 10));
   3773   video_layer->SetAnchorPoint(gfx::PointF());
   3774   video_layer->SetContentBounds(gfx::Size(10, 10));
   3775   video_layer->SetDrawsContent(true);
   3776   root_layer->AddChild(video_layer.PassAs<LayerImpl>());
   3777 
   3778   scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
   3779       IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
   3780   io_surface_layer->SetBounds(gfx::Size(10, 10));
   3781   io_surface_layer->SetAnchorPoint(gfx::PointF());
   3782   io_surface_layer->SetContentBounds(gfx::Size(10, 10));
   3783   io_surface_layer->SetDrawsContent(true);
   3784   io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
   3785   root_layer->AddChild(io_surface_layer.PassAs<LayerImpl>());
   3786 
   3787   host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
   3788 
   3789   EXPECT_EQ(0u, context3d->NumTextures());
   3790 
   3791   LayerTreeHostImpl::FrameData frame;
   3792   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3793   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3794   host_impl_->DidDrawAllLayers(frame);
   3795   host_impl_->SwapBuffers(frame);
   3796 
   3797   EXPECT_GT(context3d->NumTextures(), 0u);
   3798 
   3799   // Kill the layer tree.
   3800   host_impl_->active_tree()->SetRootLayer(
   3801       LayerImpl::Create(host_impl_->active_tree(), 100));
   3802   // There should be no textures left in use after.
   3803   EXPECT_EQ(0u, context3d->NumTextures());
   3804 }
   3805 
   3806 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
   3807  public:
   3808   MOCK_METHOD1(useProgram, void(WebKit::WebGLId program));
   3809   MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode,
   3810                                   WebKit::WGC3Dsizei count,
   3811                                   WebKit::WGC3Denum type,
   3812                                   WebKit::WGC3Dintptr offset));
   3813 };
   3814 
   3815 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
   3816   scoped_ptr<OutputSurface> output_surface =
   3817       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   3818           new MockDrawQuadsToFillScreenContext)).PassAs<OutputSurface>();
   3819   MockDrawQuadsToFillScreenContext* mock_context =
   3820       static_cast<MockDrawQuadsToFillScreenContext*>(
   3821           output_surface->context3d());
   3822 
   3823   // Run test case
   3824   CreateLayerTreeHost(false, output_surface.Pass());
   3825   SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
   3826   host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
   3827 
   3828   // Verify one quad is drawn when transparent background set is not set.
   3829   host_impl_->active_tree()->set_has_transparent_background(false);
   3830   EXPECT_CALL(*mock_context, useProgram(_))
   3831       .Times(1);
   3832   EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
   3833       .Times(1);
   3834   LayerTreeHostImpl::FrameData frame;
   3835   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3836   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3837   host_impl_->DidDrawAllLayers(frame);
   3838   Mock::VerifyAndClearExpectations(&mock_context);
   3839 
   3840   // Verify no quads are drawn when transparent background is set.
   3841   host_impl_->active_tree()->set_has_transparent_background(true);
   3842   host_impl_->SetFullRootLayerDamage();
   3843   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   3844   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   3845   host_impl_->DidDrawAllLayers(frame);
   3846   Mock::VerifyAndClearExpectations(&mock_context);
   3847 }
   3848 
   3849 static void AddDrawingLayerTo(LayerImpl* parent,
   3850                               int id,
   3851                               gfx::Rect layer_rect,
   3852                               LayerImpl** result) {
   3853   scoped_ptr<LayerImpl> layer =
   3854       FakeLayerWithQuads::Create(parent->layer_tree_impl(), id);
   3855   LayerImpl* layer_ptr = layer.get();
   3856   layer_ptr->SetAnchorPoint(gfx::PointF());
   3857   layer_ptr->SetPosition(gfx::PointF(layer_rect.origin()));
   3858   layer_ptr->SetBounds(layer_rect.size());
   3859   layer_ptr->SetContentBounds(layer_rect.size());
   3860   layer_ptr->SetDrawsContent(true);  // only children draw content
   3861   layer_ptr->SetContentsOpaque(true);
   3862   parent->AddChild(layer.Pass());
   3863   if (result)
   3864     *result = layer_ptr;
   3865 }
   3866 
   3867 static void SetupLayersForTextureCaching(
   3868     LayerTreeHostImpl* layer_tree_host_impl,
   3869     LayerImpl*& root_ptr,
   3870     LayerImpl*& intermediate_layer_ptr,
   3871     LayerImpl*& surface_layer_ptr,
   3872     LayerImpl*& child_ptr,
   3873     gfx::Size root_size) {
   3874   scoped_ptr<OutputSurface> output_surface =
   3875       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   3876           new PartialSwapContext)).PassAs<OutputSurface>();
   3877 
   3878   layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
   3879   layer_tree_host_impl->SetViewportSize(root_size);
   3880 
   3881   scoped_ptr<LayerImpl> root =
   3882       LayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
   3883   root_ptr = root.get();
   3884 
   3885   root->SetAnchorPoint(gfx::PointF());
   3886   root->SetPosition(gfx::PointF());
   3887   root->SetBounds(root_size);
   3888   root->SetContentBounds(root_size);
   3889   root->SetDrawsContent(true);
   3890   layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
   3891 
   3892   AddDrawingLayerTo(root_ptr,
   3893                     2,
   3894                     gfx::Rect(10, 10, root_size.width(), root_size.height()),
   3895                     &intermediate_layer_ptr);
   3896   // Only children draw content.
   3897   intermediate_layer_ptr->SetDrawsContent(false);
   3898 
   3899   // Surface layer is the layer that changes its opacity
   3900   // It will contain other layers that draw content.
   3901   AddDrawingLayerTo(intermediate_layer_ptr,
   3902                     3,
   3903                     gfx::Rect(10, 10, root_size.width(), root_size.height()),
   3904                     &surface_layer_ptr);
   3905   // Only children draw content.
   3906   surface_layer_ptr->SetDrawsContent(false);
   3907   surface_layer_ptr->SetOpacity(0.5f);
   3908   surface_layer_ptr->SetForceRenderSurface(true);
   3909 
   3910   // Child of the surface layer will produce some quads
   3911   AddDrawingLayerTo(surface_layer_ptr,
   3912                     4,
   3913                     gfx::Rect(5,
   3914                               5,
   3915                               root_size.width() - 25,
   3916                               root_size.height() - 25),
   3917                     &child_ptr);
   3918 }
   3919 
   3920 class GLRendererWithReleaseTextures : public GLRenderer {
   3921  public:
   3922   using GLRenderer::ReleaseRenderPassTextures;
   3923 };
   3924 
   3925 TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusion) {
   3926   LayerTreeSettings settings;
   3927   settings.minimum_occlusion_tracking_size = gfx::Size();
   3928   settings.cache_render_pass_contents = true;
   3929   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   3930       LayerTreeHostImpl::Create(settings,
   3931                                 this,
   3932                                 &proxy_,
   3933                                 &stats_instrumentation_);
   3934 
   3935   // Layers are structure as follows:
   3936   //
   3937   //  R +-- S1 +- L10 (owning)
   3938   //    |      +- L11
   3939   //    |      +- L12
   3940   //    |
   3941   //    +-- S2 +- L20 (owning)
   3942   //           +- L21
   3943   //
   3944   // Occlusion:
   3945   // L12 occludes L11 (internal)
   3946   // L20 occludes L10 (external)
   3947   // L21 occludes L20 (internal)
   3948 
   3949   LayerImpl* root_ptr;
   3950   LayerImpl* layer_s1_ptr;
   3951   LayerImpl* layer_s2_ptr;
   3952 
   3953   scoped_ptr<OutputSurface> output_surface =
   3954       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   3955           new PartialSwapContext)).PassAs<OutputSurface>();
   3956 
   3957   gfx::Size root_size(1000, 1000);
   3958 
   3959   my_host_impl->InitializeRenderer(output_surface.Pass());
   3960   my_host_impl->SetViewportSize(root_size);
   3961 
   3962   scoped_ptr<LayerImpl> root =
   3963       LayerImpl::Create(my_host_impl->active_tree(), 1);
   3964   root_ptr = root.get();
   3965 
   3966   root->SetAnchorPoint(gfx::PointF());
   3967   root->SetPosition(gfx::PointF());
   3968   root->SetBounds(root_size);
   3969   root->SetContentBounds(root_size);
   3970   root->SetDrawsContent(true);
   3971   root->SetMasksToBounds(true);
   3972   my_host_impl->active_tree()->SetRootLayer(root.Pass());
   3973 
   3974   AddDrawingLayerTo(root_ptr, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr);
   3975   layer_s1_ptr->SetForceRenderSurface(true);
   3976 
   3977   AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(10, 10, 10, 10), 0);  // L11
   3978   AddDrawingLayerTo(layer_s1_ptr, 4, gfx::Rect(0, 0, 30, 30), 0);  // L12
   3979 
   3980   AddDrawingLayerTo(root_ptr, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr);
   3981   layer_s2_ptr->SetForceRenderSurface(true);
   3982 
   3983   AddDrawingLayerTo(layer_s2_ptr, 6, gfx::Rect(20, 20, 5, 5), 0);  // L21
   3984 
   3985   // Initial draw - must receive all quads
   3986   {
   3987     LayerTreeHostImpl::FrameData frame;
   3988     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   3989 
   3990     // Must receive 3 render passes.
   3991     // For Root, there are 2 quads; for S1, there are 2 quads (1 is occluded);
   3992     // for S2, there is 2 quads.
   3993     ASSERT_EQ(3U, frame.render_passes.size());
   3994 
   3995     EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
   3996     EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
   3997     EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
   3998 
   3999     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4000     my_host_impl->DidDrawAllLayers(frame);
   4001   }
   4002 
   4003   // "Unocclude" surface S1 and repeat draw.
   4004   // Must remove S2's render pass since it's cached;
   4005   // Must keep S1 quads because texture contained external occlusion.
   4006   gfx::Transform transform = layer_s2_ptr->transform();
   4007   transform.Translate(150.0, 150.0);
   4008   layer_s2_ptr->SetTransform(transform);
   4009   {
   4010     LayerTreeHostImpl::FrameData frame;
   4011     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4012 
   4013     // Must receive 2 render passes.
   4014     // For Root, there are 2 quads
   4015     // For S1, the number of quads depends on what got unoccluded, so not
   4016     // asserted beyond being positive.
   4017     // For S2, there is no render pass
   4018     ASSERT_EQ(2U, frame.render_passes.size());
   4019 
   4020     EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
   4021     EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
   4022 
   4023     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4024     my_host_impl->DidDrawAllLayers(frame);
   4025   }
   4026 
   4027   // "Re-occlude" surface S1 and repeat draw.
   4028   // Must remove S1's render pass since it is now available in full.
   4029   // S2 has no change so must also be removed.
   4030   transform = layer_s2_ptr->transform();
   4031   transform.Translate(-15.0, -15.0);
   4032   layer_s2_ptr->SetTransform(transform);
   4033   {
   4034     LayerTreeHostImpl::FrameData frame;
   4035     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4036 
   4037     // Must receive 1 render pass - for the root.
   4038     ASSERT_EQ(1U, frame.render_passes.size());
   4039 
   4040     EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
   4041 
   4042     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4043     my_host_impl->DidDrawAllLayers(frame);
   4044   }
   4045 }
   4046 
   4047 TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionEarlyOut) {
   4048   LayerTreeSettings settings;
   4049   settings.minimum_occlusion_tracking_size = gfx::Size();
   4050   settings.cache_render_pass_contents = true;
   4051   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   4052       LayerTreeHostImpl::Create(settings,
   4053                                 this,
   4054                                 &proxy_,
   4055                                 &stats_instrumentation_);
   4056 
   4057   // Layers are structure as follows:
   4058   //
   4059   //  R +-- S1 +- L10 (owning, non drawing)
   4060   //    |      +- L11 (corner, unoccluded)
   4061   //    |      +- L12 (corner, unoccluded)
   4062   //    |      +- L13 (corner, unoccluded)
   4063   //    |      +- L14 (corner, entirely occluded)
   4064   //    |
   4065   //    +-- S2 +- L20 (owning, drawing)
   4066   //
   4067 
   4068   LayerImpl* root_ptr;
   4069   LayerImpl* layer_s1_ptr;
   4070   LayerImpl* layer_s2_ptr;
   4071 
   4072   scoped_ptr<OutputSurface> output_surface =
   4073       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   4074           new PartialSwapContext)).PassAs<OutputSurface>();
   4075 
   4076   gfx::Size root_size(1000, 1000);
   4077 
   4078   my_host_impl->InitializeRenderer(output_surface.Pass());
   4079   my_host_impl->SetViewportSize(root_size);
   4080 
   4081   scoped_ptr<LayerImpl> root =
   4082       LayerImpl::Create(my_host_impl->active_tree(), 1);
   4083   root_ptr = root.get();
   4084 
   4085   root->SetAnchorPoint(gfx::PointF());
   4086   root->SetPosition(gfx::PointF());
   4087   root->SetBounds(root_size);
   4088   root->SetContentBounds(root_size);
   4089   root->SetDrawsContent(true);
   4090   root->SetMasksToBounds(true);
   4091   my_host_impl->active_tree()->SetRootLayer(root.Pass());
   4092 
   4093   AddDrawingLayerTo(root_ptr, 2, gfx::Rect(0, 0, 800, 800), &layer_s1_ptr);
   4094   layer_s1_ptr->SetForceRenderSurface(true);
   4095   layer_s1_ptr->SetDrawsContent(false);
   4096 
   4097   AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(0, 0, 300, 300), 0);  // L11
   4098   AddDrawingLayerTo(layer_s1_ptr, 4, gfx::Rect(0, 500, 300, 300), 0);  // L12
   4099   AddDrawingLayerTo(layer_s1_ptr, 5, gfx::Rect(500, 0, 300, 300), 0);  // L13
   4100   AddDrawingLayerTo(layer_s1_ptr, 6, gfx::Rect(500, 500, 300, 300), 0);  // L14
   4101   AddDrawingLayerTo(layer_s1_ptr, 9, gfx::Rect(500, 500, 300, 300), 0);  // L14
   4102 
   4103   AddDrawingLayerTo(root_ptr, 7, gfx::Rect(450, 450, 450, 450), &layer_s2_ptr);
   4104   layer_s2_ptr->SetForceRenderSurface(true);
   4105 
   4106   // Initial draw - must receive all quads
   4107   {
   4108     LayerTreeHostImpl::FrameData frame;
   4109     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4110 
   4111     // Must receive 3 render passes.
   4112     // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
   4113     // 1 quad.
   4114     ASSERT_EQ(3U, frame.render_passes.size());
   4115 
   4116     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4117 
   4118     // L14 is culled, so only 3 quads.
   4119     EXPECT_EQ(3U, frame.render_passes[1]->quad_list.size());
   4120     EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
   4121 
   4122     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4123     my_host_impl->DidDrawAllLayers(frame);
   4124   }
   4125 
   4126   // "Unocclude" surface S1 and repeat draw.
   4127   // Must remove S2's render pass since it's cached;
   4128   // Must keep S1 quads because texture contained external occlusion.
   4129   gfx::Transform transform = layer_s2_ptr->transform();
   4130   transform.Translate(100.0, 100.0);
   4131   layer_s2_ptr->SetTransform(transform);
   4132   {
   4133     LayerTreeHostImpl::FrameData frame;
   4134     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4135 
   4136     // Must receive 2 render passes.
   4137     // For Root, there are 2 quads
   4138     // For S1, the number of quads depends on what got unoccluded, so not
   4139     // asserted beyond being positive.
   4140     // For S2, there is no render pass
   4141     ASSERT_EQ(2U, frame.render_passes.size());
   4142 
   4143     EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
   4144     EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
   4145 
   4146     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4147     my_host_impl->DidDrawAllLayers(frame);
   4148   }
   4149 
   4150   // "Re-occlude" surface S1 and repeat draw.
   4151   // Must remove S1's render pass since it is now available in full.
   4152   // S2 has no change so must also be removed.
   4153   transform = layer_s2_ptr->transform();
   4154   transform.Translate(-15.0, -15.0);
   4155   layer_s2_ptr->SetTransform(transform);
   4156   {
   4157     LayerTreeHostImpl::FrameData frame;
   4158     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4159 
   4160     // Must receive 1 render pass - for the root.
   4161     ASSERT_EQ(1U, frame.render_passes.size());
   4162 
   4163     EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
   4164 
   4165     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4166     my_host_impl->DidDrawAllLayers(frame);
   4167   }
   4168 }
   4169 
   4170 TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionExternalOverInternal) {
   4171   LayerTreeSettings settings;
   4172   settings.minimum_occlusion_tracking_size = gfx::Size();
   4173   settings.cache_render_pass_contents = true;
   4174   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   4175       LayerTreeHostImpl::Create(settings,
   4176                                 this,
   4177                                 &proxy_,
   4178                                 &stats_instrumentation_);
   4179 
   4180   // Layers are structured as follows:
   4181   //
   4182   //  R +-- S1 +- L10 (owning, drawing)
   4183   //    |      +- L11 (corner, occluded by L12)
   4184   //    |      +- L12 (opposite corner)
   4185   //    |
   4186   //    +-- S2 +- L20 (owning, drawing)
   4187   //
   4188 
   4189   LayerImpl* root_ptr;
   4190   LayerImpl* layer_s1_ptr;
   4191   LayerImpl* layer_s2_ptr;
   4192 
   4193   scoped_ptr<OutputSurface> output_surface =
   4194       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   4195           new PartialSwapContext)).PassAs<OutputSurface>();
   4196 
   4197   gfx::Size root_size(1000, 1000);
   4198 
   4199   my_host_impl->InitializeRenderer(output_surface.Pass());
   4200   my_host_impl->SetViewportSize(root_size);
   4201 
   4202   scoped_ptr<LayerImpl> root =
   4203       LayerImpl::Create(my_host_impl->active_tree(), 1);
   4204   root_ptr = root.get();
   4205 
   4206   root->SetAnchorPoint(gfx::PointF());
   4207   root->SetPosition(gfx::PointF());
   4208   root->SetBounds(root_size);
   4209   root->SetContentBounds(root_size);
   4210   root->SetDrawsContent(true);
   4211   root->SetMasksToBounds(true);
   4212   my_host_impl->active_tree()->SetRootLayer(root.Pass());
   4213 
   4214   AddDrawingLayerTo(root_ptr, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr);
   4215   layer_s1_ptr->SetForceRenderSurface(true);
   4216 
   4217   AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(0, 0, 300, 300), 0);  // L11
   4218   AddDrawingLayerTo(layer_s1_ptr, 4, gfx::Rect(100, 0, 300, 300), 0);  // L12
   4219 
   4220   AddDrawingLayerTo(root_ptr, 7, gfx::Rect(200, 0, 300, 300), &layer_s2_ptr);
   4221   layer_s2_ptr->SetForceRenderSurface(true);
   4222 
   4223   // Initial draw - must receive all quads
   4224   {
   4225     LayerTreeHostImpl::FrameData frame;
   4226     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4227 
   4228     // Must receive 3 render passes.
   4229     // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
   4230     // 1 quad.
   4231     ASSERT_EQ(3U, frame.render_passes.size());
   4232 
   4233     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4234     EXPECT_EQ(3U, frame.render_passes[1]->quad_list.size());
   4235     EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
   4236 
   4237     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4238     my_host_impl->DidDrawAllLayers(frame);
   4239   }
   4240 
   4241   // "Unocclude" surface S1 and repeat draw.
   4242   // Must remove S2's render pass since it's cached;
   4243   // Must keep S1 quads because texture contained external occlusion.
   4244   gfx::Transform transform = layer_s2_ptr->transform();
   4245   transform.Translate(300.0, 0.0);
   4246   layer_s2_ptr->SetTransform(transform);
   4247   {
   4248     LayerTreeHostImpl::FrameData frame;
   4249     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4250 
   4251     // Must receive 2 render passes.
   4252     // For Root, there are 2 quads
   4253     // For S1, the number of quads depends on what got unoccluded, so not
   4254     // asserted beyond being positive.
   4255     // For S2, there is no render pass
   4256     ASSERT_EQ(2U, frame.render_passes.size());
   4257 
   4258     EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
   4259     EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
   4260 
   4261     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4262     my_host_impl->DidDrawAllLayers(frame);
   4263   }
   4264 }
   4265 
   4266 TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionExternalNotAligned) {
   4267   LayerTreeSettings settings;
   4268   settings.cache_render_pass_contents = true;
   4269   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   4270       LayerTreeHostImpl::Create(settings,
   4271                                 this,
   4272                                 &proxy_,
   4273                                 &stats_instrumentation_);
   4274 
   4275   // Layers are structured as follows:
   4276   //
   4277   //  R +-- S1 +- L10 (rotated, drawing)
   4278   //           +- L11 (occupies half surface)
   4279 
   4280   LayerImpl* root_ptr;
   4281   LayerImpl* layer_s1_ptr;
   4282 
   4283   scoped_ptr<OutputSurface> output_surface =
   4284       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   4285           new PartialSwapContext)).PassAs<OutputSurface>();
   4286 
   4287   gfx::Size root_size(1000, 1000);
   4288 
   4289   my_host_impl->InitializeRenderer(output_surface.Pass());
   4290   my_host_impl->SetViewportSize(root_size);
   4291 
   4292   scoped_ptr<LayerImpl> root =
   4293       LayerImpl::Create(my_host_impl->active_tree(), 1);
   4294   root_ptr = root.get();
   4295 
   4296   root->SetAnchorPoint(gfx::PointF());
   4297   root->SetPosition(gfx::PointF());
   4298   root->SetBounds(root_size);
   4299   root->SetContentBounds(root_size);
   4300   root->SetDrawsContent(true);
   4301   root->SetMasksToBounds(true);
   4302   my_host_impl->active_tree()->SetRootLayer(root.Pass());
   4303 
   4304   AddDrawingLayerTo(root_ptr, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr);
   4305   layer_s1_ptr->SetForceRenderSurface(true);
   4306   gfx::Transform transform = layer_s1_ptr->transform();
   4307   transform.Translate(200.0, 200.0);
   4308   transform.Rotate(45.0);
   4309   transform.Translate(-200.0, -200.0);
   4310   layer_s1_ptr->SetTransform(transform);
   4311 
   4312   AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(200, 0, 200, 400), 0);  // L11
   4313 
   4314   // Initial draw - must receive all quads
   4315   {
   4316     LayerTreeHostImpl::FrameData frame;
   4317     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4318 
   4319     // Must receive 2 render passes.
   4320     ASSERT_EQ(2U, frame.render_passes.size());
   4321 
   4322     EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
   4323     EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
   4324 
   4325     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4326     my_host_impl->DidDrawAllLayers(frame);
   4327   }
   4328 
   4329   // Change opacity and draw. Verify we used cached texture.
   4330   layer_s1_ptr->SetOpacity(0.2f);
   4331   {
   4332     LayerTreeHostImpl::FrameData frame;
   4333     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4334 
   4335     // One render pass must be gone due to cached texture.
   4336     ASSERT_EQ(1U, frame.render_passes.size());
   4337 
   4338     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4339 
   4340     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4341     my_host_impl->DidDrawAllLayers(frame);
   4342   }
   4343 }
   4344 
   4345 TEST_F(LayerTreeHostImplTest, TextureCachingWithOcclusionPartialSwap) {
   4346   LayerTreeSettings settings;
   4347   settings.minimum_occlusion_tracking_size = gfx::Size();
   4348   settings.partial_swap_enabled = true;
   4349   settings.cache_render_pass_contents = true;
   4350   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   4351       LayerTreeHostImpl::Create(settings,
   4352                                 this,
   4353                                 &proxy_,
   4354                                 &stats_instrumentation_);
   4355 
   4356   // Layers are structure as follows:
   4357   //
   4358   //  R +-- S1 +- L10 (owning)
   4359   //    |      +- L11
   4360   //    |      +- L12
   4361   //    |
   4362   //    +-- S2 +- L20 (owning)
   4363   //           +- L21
   4364   //
   4365   // Occlusion:
   4366   // L12 occludes L11 (internal)
   4367   // L20 occludes L10 (external)
   4368   // L21 occludes L20 (internal)
   4369 
   4370   LayerImpl* root_ptr;
   4371   LayerImpl* layer_s1_ptr;
   4372   LayerImpl* layer_s2_ptr;
   4373 
   4374   scoped_ptr<OutputSurface> output_surface =
   4375       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   4376           new PartialSwapContext)).PassAs<OutputSurface>();
   4377 
   4378   gfx::Size root_size(1000, 1000);
   4379 
   4380   my_host_impl->InitializeRenderer(output_surface.Pass());
   4381   my_host_impl->SetViewportSize(root_size);
   4382 
   4383   scoped_ptr<LayerImpl> root =
   4384       LayerImpl::Create(my_host_impl->active_tree(), 1);
   4385   root_ptr = root.get();
   4386 
   4387   root->SetAnchorPoint(gfx::PointF());
   4388   root->SetPosition(gfx::PointF());
   4389   root->SetBounds(root_size);
   4390   root->SetContentBounds(root_size);
   4391   root->SetDrawsContent(true);
   4392   root->SetMasksToBounds(true);
   4393   my_host_impl->active_tree()->SetRootLayer(root.Pass());
   4394 
   4395   AddDrawingLayerTo(root_ptr, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr);
   4396   layer_s1_ptr->SetForceRenderSurface(true);
   4397 
   4398   AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(10, 10, 10, 10), 0);  // L11
   4399   AddDrawingLayerTo(layer_s1_ptr, 4, gfx::Rect(0, 0, 30, 30), 0);  // L12
   4400 
   4401   AddDrawingLayerTo(root_ptr, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr);
   4402   layer_s2_ptr->SetForceRenderSurface(true);
   4403 
   4404   AddDrawingLayerTo(layer_s2_ptr, 6, gfx::Rect(20, 20, 5, 5), 0);  // L21
   4405 
   4406   // Initial draw - must receive all quads
   4407   {
   4408     LayerTreeHostImpl::FrameData frame;
   4409     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4410 
   4411     // Must receive 3 render passes.
   4412     // For Root, there are 2 quads; for S1, there are 2 quads (one is occluded);
   4413     // for S2, there is 2 quads.
   4414     ASSERT_EQ(3U, frame.render_passes.size());
   4415 
   4416     EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
   4417     EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
   4418     EXPECT_EQ(2U, frame.render_passes[2]->quad_list.size());
   4419 
   4420     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4421     my_host_impl->DidDrawAllLayers(frame);
   4422   }
   4423 
   4424   // "Unocclude" surface S1 and repeat draw.
   4425   // Must remove S2's render pass since it's cached;
   4426   // Must keep S1 quads because texture contained external occlusion.
   4427   gfx::Transform transform = layer_s2_ptr->transform();
   4428   transform.Translate(150.0, 150.0);
   4429   layer_s2_ptr->SetTransform(transform);
   4430   {
   4431     LayerTreeHostImpl::FrameData frame;
   4432     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4433 
   4434     // Must receive 2 render passes.
   4435     // For Root, there are 2 quads.
   4436     // For S1, there are 2 quads.
   4437     // For S2, there is no render pass
   4438     ASSERT_EQ(2U, frame.render_passes.size());
   4439 
   4440     EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
   4441     EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
   4442 
   4443     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4444     my_host_impl->DidDrawAllLayers(frame);
   4445   }
   4446 
   4447   // "Re-occlude" surface S1 and repeat draw.
   4448   // Must remove S1's render pass since it is now available in full.
   4449   // S2 has no change so must also be removed.
   4450   transform = layer_s2_ptr->transform();
   4451   transform.Translate(-15.0, -15.0);
   4452   layer_s2_ptr->SetTransform(transform);
   4453   {
   4454     LayerTreeHostImpl::FrameData frame;
   4455     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4456 
   4457     // Root render pass only.
   4458     ASSERT_EQ(1U, frame.render_passes.size());
   4459 
   4460     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4461     my_host_impl->DidDrawAllLayers(frame);
   4462   }
   4463 }
   4464 
   4465 TEST_F(LayerTreeHostImplTest, TextureCachingWithScissor) {
   4466   LayerTreeSettings settings;
   4467   settings.minimum_occlusion_tracking_size = gfx::Size();
   4468   settings.cache_render_pass_contents = true;
   4469   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   4470       LayerTreeHostImpl::Create(settings,
   4471                                 this,
   4472                                 &proxy_,
   4473                                 &stats_instrumentation_);
   4474 
   4475   /*
   4476     Layers are created as follows:
   4477 
   4478     +--------------------+
   4479     |                  1 |
   4480     |  +-----------+     |
   4481     |  |         2 |     |
   4482     |  | +-------------------+
   4483     |  | |   3               |
   4484     |  | +-------------------+
   4485     |  |           |     |
   4486     |  +-----------+     |
   4487     |                    |
   4488     |                    |
   4489     +--------------------+
   4490 
   4491     Layers 1, 2 have render surfaces
   4492   */
   4493   scoped_ptr<LayerImpl> root =
   4494       LayerImpl::Create(my_host_impl->active_tree(), 1);
   4495   scoped_ptr<TiledLayerImpl> child =
   4496       TiledLayerImpl::Create(my_host_impl->active_tree(), 2);
   4497   scoped_ptr<LayerImpl> grand_child =
   4498       LayerImpl::Create(my_host_impl->active_tree(), 3);
   4499 
   4500   gfx::Rect root_rect(0, 0, 100, 100);
   4501   gfx::Rect child_rect(10, 10, 50, 50);
   4502   gfx::Rect grand_child_rect(5, 5, 150, 150);
   4503 
   4504   scoped_ptr<OutputSurface> output_surface =
   4505       FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
   4506           new PartialSwapContext)).PassAs<OutputSurface>();
   4507   my_host_impl->InitializeRenderer(output_surface.Pass());
   4508 
   4509   root->SetAnchorPoint(gfx::PointF());
   4510   root->SetPosition(gfx::PointF(root_rect.x(), root_rect.y()));
   4511   root->SetBounds(gfx::Size(root_rect.width(), root_rect.height()));
   4512   root->SetContentBounds(root->bounds());
   4513   root->SetDrawsContent(true);
   4514   root->SetMasksToBounds(true);
   4515 
   4516   child->SetAnchorPoint(gfx::PointF());
   4517   child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
   4518   child->SetOpacity(0.5f);
   4519   child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
   4520   child->SetContentBounds(child->bounds());
   4521   child->SetDrawsContent(true);
   4522   child->set_skips_draw(false);
   4523 
   4524   // child layer has 10x10 tiles.
   4525   scoped_ptr<LayerTilingData> tiler =
   4526       LayerTilingData::Create(gfx::Size(10, 10),
   4527                               LayerTilingData::HAS_BORDER_TEXELS);
   4528   tiler->SetBounds(child->content_bounds());
   4529   child->SetTilingData(*tiler.get());
   4530 
   4531   grand_child->SetAnchorPoint(gfx::PointF());
   4532   grand_child->SetPosition(grand_child_rect.origin());
   4533   grand_child->SetBounds(grand_child_rect.size());
   4534   grand_child->SetContentBounds(grand_child->bounds());
   4535   grand_child->SetDrawsContent(true);
   4536 
   4537   TiledLayerImpl* child_ptr = child.get();
   4538   RenderPass::Id child_pass_id(child_ptr->id(), 0);
   4539 
   4540   child->AddChild(grand_child.Pass());
   4541   root->AddChild(child.PassAs<LayerImpl>());
   4542   my_host_impl->active_tree()->SetRootLayer(root.Pass());
   4543   my_host_impl->SetViewportSize(root_rect.size());
   4544 
   4545   EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
   4546       child_pass_id));
   4547   {
   4548     LayerTreeHostImpl::FrameData frame;
   4549     host_impl_->SetFullRootLayerDamage();
   4550     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4551     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4552     my_host_impl->DidDrawAllLayers(frame);
   4553   }
   4554 
   4555   // We should have cached textures for surface 2.
   4556   EXPECT_TRUE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
   4557       child_pass_id));
   4558   {
   4559     LayerTreeHostImpl::FrameData frame;
   4560     host_impl_->SetFullRootLayerDamage();
   4561     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4562     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4563     my_host_impl->DidDrawAllLayers(frame);
   4564   }
   4565 
   4566   // We should still have cached textures for surface 2 after drawing with no
   4567   // damage.
   4568   EXPECT_TRUE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
   4569       child_pass_id));
   4570 
   4571   // Damage a single tile of surface 2.
   4572   child_ptr->set_update_rect(gfx::Rect(10, 10, 10, 10));
   4573   {
   4574     LayerTreeHostImpl::FrameData frame;
   4575     host_impl_->SetFullRootLayerDamage();
   4576     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4577     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4578     my_host_impl->DidDrawAllLayers(frame);
   4579   }
   4580 
   4581   // We should have a cached texture for surface 2 again even though it was
   4582   // damaged.
   4583   EXPECT_TRUE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
   4584       child_pass_id));
   4585 }
   4586 
   4587 TEST_F(LayerTreeHostImplTest, SurfaceTextureCaching) {
   4588   LayerTreeSettings settings;
   4589   settings.minimum_occlusion_tracking_size = gfx::Size();
   4590   settings.partial_swap_enabled = true;
   4591   settings.cache_render_pass_contents = true;
   4592   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   4593       LayerTreeHostImpl::Create(settings,
   4594                                 this,
   4595                                 &proxy_,
   4596                                 &stats_instrumentation_);
   4597 
   4598   LayerImpl* root_ptr;
   4599   LayerImpl* intermediate_layer_ptr;
   4600   LayerImpl* surface_layer_ptr;
   4601   LayerImpl* child_ptr;
   4602 
   4603   SetupLayersForTextureCaching(my_host_impl.get(),
   4604                                root_ptr,
   4605                                intermediate_layer_ptr,
   4606                                surface_layer_ptr,
   4607                                child_ptr,
   4608                                gfx::Size(100, 100));
   4609   {
   4610     LayerTreeHostImpl::FrameData frame;
   4611     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4612 
   4613     // Must receive two render passes, each with one quad
   4614     ASSERT_EQ(2U, frame.render_passes.size());
   4615     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4616     EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
   4617 
   4618     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4619               frame.render_passes[1]->quad_list[0]->material);
   4620     const RenderPassDrawQuad* quad =
   4621         RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
   4622     RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
   4623     ASSERT_TRUE(target_pass);
   4624     EXPECT_FALSE(target_pass->damage_rect.IsEmpty());
   4625 
   4626     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4627     my_host_impl->DidDrawAllLayers(frame);
   4628   }
   4629 
   4630   // Draw without any change
   4631   {
   4632     LayerTreeHostImpl::FrameData frame;
   4633     my_host_impl->SetFullRootLayerDamage();
   4634     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4635 
   4636     // Must receive one render pass, as the other one should be culled
   4637     ASSERT_EQ(1U, frame.render_passes.size());
   4638 
   4639     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4640     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4641               frame.render_passes[0]->quad_list[0]->material);
   4642     const RenderPassDrawQuad* quad =
   4643         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   4644     EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
   4645                 frame.render_passes_by_id.end());
   4646 
   4647     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4648     my_host_impl->DidDrawAllLayers(frame);
   4649   }
   4650 
   4651   // Change opacity and draw
   4652   surface_layer_ptr->SetOpacity(0.6f);
   4653   {
   4654     LayerTreeHostImpl::FrameData frame;
   4655     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4656 
   4657     // Must receive one render pass, as the other one should be culled
   4658     ASSERT_EQ(1U, frame.render_passes.size());
   4659 
   4660     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4661     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4662               frame.render_passes[0]->quad_list[0]->material);
   4663     const RenderPassDrawQuad* quad =
   4664         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   4665     EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
   4666                 frame.render_passes_by_id.end());
   4667 
   4668     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4669     my_host_impl->DidDrawAllLayers(frame);
   4670   }
   4671 
   4672   // Change less benign property and draw - should have contents changed flag
   4673   surface_layer_ptr->SetStackingOrderChanged(true);
   4674   {
   4675     LayerTreeHostImpl::FrameData frame;
   4676     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4677 
   4678     // Must receive two render passes, each with one quad
   4679     ASSERT_EQ(2U, frame.render_passes.size());
   4680 
   4681     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4682     EXPECT_EQ(DrawQuad::SOLID_COLOR,
   4683               frame.render_passes[0]->quad_list[0]->material);
   4684 
   4685     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4686               frame.render_passes[1]->quad_list[0]->material);
   4687     const RenderPassDrawQuad* quad =
   4688         RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
   4689     RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
   4690     ASSERT_TRUE(target_pass);
   4691     EXPECT_FALSE(target_pass->damage_rect.IsEmpty());
   4692 
   4693     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4694     my_host_impl->DidDrawAllLayers(frame);
   4695   }
   4696 
   4697   // Change opacity again, and evict the cached surface texture.
   4698   surface_layer_ptr->SetOpacity(0.5f);
   4699   static_cast<GLRendererWithReleaseTextures*>(
   4700       my_host_impl->renderer())->ReleaseRenderPassTextures();
   4701 
   4702   // Change opacity and draw
   4703   surface_layer_ptr->SetOpacity(0.6f);
   4704   {
   4705     LayerTreeHostImpl::FrameData frame;
   4706     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4707 
   4708     // Must receive two render passes
   4709     ASSERT_EQ(2U, frame.render_passes.size());
   4710 
   4711     // Even though not enough properties changed, the entire thing must be
   4712     // redrawn as we don't have cached textures
   4713     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4714     EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
   4715 
   4716     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4717               frame.render_passes[1]->quad_list[0]->material);
   4718     const RenderPassDrawQuad* quad =
   4719         RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
   4720     RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
   4721     ASSERT_TRUE(target_pass);
   4722     EXPECT_TRUE(target_pass->damage_rect.IsEmpty());
   4723 
   4724     // Was our surface evicted?
   4725     EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
   4726         target_pass->id));
   4727 
   4728     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4729     my_host_impl->DidDrawAllLayers(frame);
   4730   }
   4731 
   4732   // Draw without any change, to make sure the state is clear
   4733   {
   4734     LayerTreeHostImpl::FrameData frame;
   4735     my_host_impl->SetFullRootLayerDamage();
   4736     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4737 
   4738     // Must receive one render pass, as the other one should be culled
   4739     ASSERT_EQ(1U, frame.render_passes.size());
   4740 
   4741     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4742     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4743               frame.render_passes[0]->quad_list[0]->material);
   4744     const RenderPassDrawQuad* quad =
   4745         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   4746     EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
   4747                 frame.render_passes_by_id.end());
   4748 
   4749     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4750     my_host_impl->DidDrawAllLayers(frame);
   4751   }
   4752 
   4753   // Change location of the intermediate layer
   4754   gfx::Transform transform = intermediate_layer_ptr->transform();
   4755   transform.matrix().setDouble(0, 3, 1.0001);
   4756   intermediate_layer_ptr->SetTransform(transform);
   4757   {
   4758     LayerTreeHostImpl::FrameData frame;
   4759     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4760 
   4761     // Must receive one render pass, as the other one should be culled.
   4762     ASSERT_EQ(1U, frame.render_passes.size());
   4763     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4764 
   4765     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4766               frame.render_passes[0]->quad_list[0]->material);
   4767     const RenderPassDrawQuad* quad =
   4768         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   4769     EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
   4770                 frame.render_passes_by_id.end());
   4771 
   4772     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4773     my_host_impl->DidDrawAllLayers(frame);
   4774   }
   4775 }
   4776 
   4777 TEST_F(LayerTreeHostImplTest, SurfaceTextureCachingNoPartialSwap) {
   4778   LayerTreeSettings settings;
   4779   settings.minimum_occlusion_tracking_size = gfx::Size();
   4780   settings.cache_render_pass_contents = true;
   4781   scoped_ptr<LayerTreeHostImpl> my_host_impl =
   4782       LayerTreeHostImpl::Create(settings,
   4783                                 this,
   4784                                 &proxy_,
   4785                                 &stats_instrumentation_);
   4786 
   4787   LayerImpl* root_ptr;
   4788   LayerImpl* intermediate_layer_ptr;
   4789   LayerImpl* surface_layer_ptr;
   4790   LayerImpl* child_ptr;
   4791 
   4792   SetupLayersForTextureCaching(my_host_impl.get(),
   4793                                root_ptr,
   4794                                intermediate_layer_ptr,
   4795                                surface_layer_ptr,
   4796                                child_ptr,
   4797                                gfx::Size(100, 100));
   4798   {
   4799     LayerTreeHostImpl::FrameData frame;
   4800     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4801 
   4802     // Must receive two render passes, each with one quad
   4803     ASSERT_EQ(2U, frame.render_passes.size());
   4804     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4805     EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
   4806 
   4807     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4808               frame.render_passes[1]->quad_list[0]->material);
   4809     const RenderPassDrawQuad* quad =
   4810         RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
   4811     RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
   4812     EXPECT_FALSE(target_pass->damage_rect.IsEmpty());
   4813 
   4814     EXPECT_FALSE(frame.render_passes[0]->damage_rect.IsEmpty());
   4815     EXPECT_FALSE(frame.render_passes[1]->damage_rect.IsEmpty());
   4816 
   4817     EXPECT_FALSE(
   4818         frame.render_passes[0]->has_occlusion_from_outside_target_surface);
   4819     EXPECT_FALSE(
   4820         frame.render_passes[1]->has_occlusion_from_outside_target_surface);
   4821 
   4822     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4823     my_host_impl->DidDrawAllLayers(frame);
   4824   }
   4825 
   4826   // Draw without any change
   4827   {
   4828     LayerTreeHostImpl::FrameData frame;
   4829     my_host_impl->SetFullRootLayerDamage();
   4830     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4831 
   4832     // Even though there was no change, we set the damage to entire viewport.
   4833     // One of the passes should be culled as a result, since contents didn't
   4834     // change and we have cached texture.
   4835     ASSERT_EQ(1U, frame.render_passes.size());
   4836     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4837 
   4838     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4839     my_host_impl->DidDrawAllLayers(frame);
   4840   }
   4841 
   4842   // Change opacity and draw
   4843   surface_layer_ptr->SetOpacity(0.6f);
   4844   {
   4845     LayerTreeHostImpl::FrameData frame;
   4846     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4847 
   4848     // Must receive one render pass, as the other one should be culled
   4849     ASSERT_EQ(1U, frame.render_passes.size());
   4850 
   4851     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4852     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4853               frame.render_passes[0]->quad_list[0]->material);
   4854     const RenderPassDrawQuad* quad =
   4855         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   4856     EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
   4857                 frame.render_passes_by_id.end());
   4858 
   4859     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4860     my_host_impl->DidDrawAllLayers(frame);
   4861   }
   4862 
   4863   // Change less benign property and draw - should have contents changed flag
   4864   surface_layer_ptr->SetStackingOrderChanged(true);
   4865   {
   4866     LayerTreeHostImpl::FrameData frame;
   4867     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4868 
   4869     // Must receive two render passes, each with one quad
   4870     ASSERT_EQ(2U, frame.render_passes.size());
   4871 
   4872     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4873     EXPECT_EQ(DrawQuad::SOLID_COLOR,
   4874               frame.render_passes[0]->quad_list[0]->material);
   4875 
   4876     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4877               frame.render_passes[1]->quad_list[0]->material);
   4878     const RenderPassDrawQuad* quad =
   4879         RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
   4880     RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
   4881     ASSERT_TRUE(target_pass);
   4882     EXPECT_FALSE(target_pass->damage_rect.IsEmpty());
   4883 
   4884     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4885     my_host_impl->DidDrawAllLayers(frame);
   4886   }
   4887 
   4888   // Change opacity again, and evict the cached surface texture.
   4889   surface_layer_ptr->SetOpacity(0.5f);
   4890   static_cast<GLRendererWithReleaseTextures*>(
   4891       my_host_impl->renderer())->ReleaseRenderPassTextures();
   4892 
   4893   // Change opacity and draw
   4894   surface_layer_ptr->SetOpacity(0.6f);
   4895   {
   4896     LayerTreeHostImpl::FrameData frame;
   4897     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4898 
   4899     // Must receive two render passes
   4900     ASSERT_EQ(2U, frame.render_passes.size());
   4901 
   4902     // Even though not enough properties changed, the entire thing must be
   4903     // redrawn as we don't have cached textures
   4904     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4905     EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
   4906 
   4907     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4908               frame.render_passes[1]->quad_list[0]->material);
   4909     const RenderPassDrawQuad* quad =
   4910         RenderPassDrawQuad::MaterialCast(frame.render_passes[1]->quad_list[0]);
   4911     RenderPass* target_pass = frame.render_passes_by_id[quad->render_pass_id];
   4912     ASSERT_TRUE(target_pass);
   4913     EXPECT_TRUE(target_pass->damage_rect.IsEmpty());
   4914 
   4915     // Was our surface evicted?
   4916     EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
   4917         target_pass->id));
   4918 
   4919     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4920     my_host_impl->DidDrawAllLayers(frame);
   4921   }
   4922 
   4923   // Draw without any change, to make sure the state is clear
   4924   {
   4925     LayerTreeHostImpl::FrameData frame;
   4926     my_host_impl->SetFullRootLayerDamage();
   4927     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4928 
   4929     // Even though there was no change, we set the damage to entire viewport.
   4930     // One of the passes should be culled as a result, since contents didn't
   4931     // change and we have cached texture.
   4932     ASSERT_EQ(1U, frame.render_passes.size());
   4933     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4934 
   4935     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4936     my_host_impl->DidDrawAllLayers(frame);
   4937   }
   4938 
   4939   // Change location of the intermediate layer
   4940   gfx::Transform transform = intermediate_layer_ptr->transform();
   4941   transform.matrix().setDouble(0, 3, 1.0001);
   4942   intermediate_layer_ptr->SetTransform(transform);
   4943   {
   4944     LayerTreeHostImpl::FrameData frame;
   4945     EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
   4946 
   4947     // Must receive one render pass, as the other one should be culled.
   4948     ASSERT_EQ(1U, frame.render_passes.size());
   4949     EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
   4950 
   4951     EXPECT_EQ(DrawQuad::RENDER_PASS,
   4952               frame.render_passes[0]->quad_list[0]->material);
   4953     const RenderPassDrawQuad* quad =
   4954         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   4955     EXPECT_TRUE(frame.render_passes_by_id.find(quad->render_pass_id) ==
   4956                 frame.render_passes_by_id.end());
   4957 
   4958     my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
   4959     my_host_impl->DidDrawAllLayers(frame);
   4960   }
   4961 }
   4962 
   4963 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
   4964   set_reduce_memory_result(false);
   4965 
   4966   // If changing the memory limit wouldn't result in changing what was
   4967   // committed, then no commit should be requested.
   4968   set_reduce_memory_result(false);
   4969   host_impl_->set_max_memory_needed_bytes(
   4970       host_impl_->memory_allocation_limit_bytes() - 1);
   4971   host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
   4972       host_impl_->memory_allocation_limit_bytes() - 1));
   4973     host_impl_->SetDiscardBackBufferWhenNotVisible(true);
   4974   EXPECT_FALSE(did_request_commit_);
   4975   did_request_commit_ = false;
   4976 
   4977   // If changing the memory limit would result in changing what was
   4978   // committed, then a commit should be requested, even though nothing was
   4979   // evicted.
   4980   set_reduce_memory_result(false);
   4981   host_impl_->set_max_memory_needed_bytes(
   4982       host_impl_->memory_allocation_limit_bytes());
   4983   host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
   4984       host_impl_->memory_allocation_limit_bytes() - 1));
   4985   host_impl_->SetDiscardBackBufferWhenNotVisible(true);
   4986   EXPECT_TRUE(did_request_commit_);
   4987   did_request_commit_ = false;
   4988 
   4989   // Especially if changing the memory limit caused evictions, we need
   4990   // to re-commit.
   4991   set_reduce_memory_result(true);
   4992   host_impl_->set_max_memory_needed_bytes(1);
   4993   host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
   4994       host_impl_->memory_allocation_limit_bytes() - 1));
   4995   host_impl_->SetDiscardBackBufferWhenNotVisible(true);
   4996   EXPECT_TRUE(did_request_commit_);
   4997   did_request_commit_ = false;
   4998 
   4999   // But if we set it to the same value that it was before, we shouldn't
   5000   // re-commit.
   5001   host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
   5002       host_impl_->memory_allocation_limit_bytes()));
   5003   host_impl_->SetDiscardBackBufferWhenNotVisible(true);
   5004   EXPECT_FALSE(did_request_commit_);
   5005 }
   5006 
   5007 struct RenderPassRemovalTestData : public LayerTreeHostImpl::FrameData {
   5008   ScopedPtrHashMap<RenderPass::Id, TestRenderPass> render_pass_cache;
   5009   scoped_ptr<SharedQuadState> shared_quad_state;
   5010 };
   5011 
   5012 class TestRenderer : public GLRenderer, public RendererClient {
   5013  public:
   5014   static scoped_ptr<TestRenderer> Create(ResourceProvider* resource_provider,
   5015                                          OutputSurface* output_surface,
   5016                                          Proxy* proxy) {
   5017     scoped_ptr<TestRenderer> renderer(new TestRenderer(resource_provider,
   5018                                                        output_surface,
   5019                                                        proxy));
   5020     if (!renderer->Initialize())
   5021       return scoped_ptr<TestRenderer>();
   5022 
   5023     return renderer.Pass();
   5024   }
   5025 
   5026   void ClearCachedTextures() { textures_.clear(); }
   5027   void SetHaveCachedResourcesForRenderPassId(RenderPass::Id id) {
   5028     textures_.insert(id);
   5029   }
   5030 
   5031   virtual bool HaveCachedResourcesForRenderPassId(RenderPass::Id id) const
   5032       OVERRIDE {
   5033     return textures_.count(id);
   5034   }
   5035 
   5036   // RendererClient implementation.
   5037   virtual gfx::Rect DeviceViewport() const OVERRIDE {
   5038     return gfx::Rect(viewport_size_);
   5039   }
   5040   virtual float DeviceScaleFactor() const OVERRIDE {
   5041     return 1.f;
   5042   }
   5043   virtual const LayerTreeSettings& Settings() const OVERRIDE {
   5044     return settings_;
   5045   }
   5046   virtual void SetFullRootLayerDamage() OVERRIDE {}
   5047   virtual bool HasImplThread() const OVERRIDE { return false; }
   5048   virtual bool ShouldClearRootRenderPass() const OVERRIDE { return true; }
   5049   virtual CompositorFrameMetadata MakeCompositorFrameMetadata() const
   5050       OVERRIDE { return CompositorFrameMetadata(); }
   5051   virtual bool AllowPartialSwap() const OVERRIDE {
   5052     return true;
   5053   }
   5054   virtual bool ExternalStencilTestEnabled() const OVERRIDE { return false; }
   5055 
   5056  protected:
   5057   TestRenderer(ResourceProvider* resource_provider,
   5058                OutputSurface* output_surface,
   5059                Proxy* proxy)
   5060       : GLRenderer(this, output_surface, resource_provider, 0) {}
   5061 
   5062  private:
   5063   LayerTreeSettings settings_;
   5064   gfx::Size viewport_size_;
   5065   base::hash_set<RenderPass::Id> textures_;
   5066 };
   5067 
   5068 static void ConfigureRenderPassTestData(const char* test_script,
   5069                                         RenderPassRemovalTestData* test_data,
   5070                                         TestRenderer* renderer) {
   5071   renderer->ClearCachedTextures();
   5072 
   5073   // One shared state for all quads - we don't need the correct details
   5074   test_data->shared_quad_state = SharedQuadState::Create();
   5075   test_data->shared_quad_state->SetAll(gfx::Transform(),
   5076                                        gfx::Size(),
   5077                                        gfx::Rect(),
   5078                                        gfx::Rect(),
   5079                                        false,
   5080                                        1.f);
   5081 
   5082   const char* current_char = test_script;
   5083 
   5084   // Pre-create root pass
   5085   RenderPass::Id root_render_pass_id =
   5086       RenderPass::Id(test_script[0], test_script[1]);
   5087   scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
   5088   pass->SetNew(root_render_pass_id, gfx::Rect(), gfx::Rect(), gfx::Transform());
   5089   test_data->render_pass_cache.add(root_render_pass_id, pass.Pass());
   5090   while (*current_char) {
   5091     int layer_id = *current_char;
   5092     current_char++;
   5093     ASSERT_TRUE(current_char);
   5094     int index = *current_char;
   5095     current_char++;
   5096 
   5097     RenderPass::Id render_pass_id = RenderPass::Id(layer_id, index);
   5098 
   5099     bool is_replica = false;
   5100     if (!test_data->render_pass_cache.contains(render_pass_id))
   5101       is_replica = true;
   5102 
   5103     scoped_ptr<TestRenderPass> render_pass =
   5104         test_data->render_pass_cache.take(render_pass_id);
   5105 
   5106     // Cycle through quad data and create all quads.
   5107     while (*current_char && *current_char != '\n') {
   5108       if (*current_char == 's') {
   5109         // Solid color draw quad.
   5110         scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
   5111         quad->SetNew(test_data->shared_quad_state.get(),
   5112                      gfx::Rect(0, 0, 10, 10),
   5113                      SK_ColorWHITE,
   5114                      false);
   5115 
   5116         render_pass->AppendQuad(quad.PassAs<DrawQuad>());
   5117         current_char++;
   5118       } else if ((*current_char >= 'A') && (*current_char <= 'Z')) {
   5119         // RenderPass draw quad.
   5120         int layer_id = *current_char;
   5121         current_char++;
   5122         ASSERT_TRUE(current_char);
   5123         int index = *current_char;
   5124         current_char++;
   5125         RenderPass::Id new_render_pass_id = RenderPass::Id(layer_id, index);
   5126         ASSERT_NE(root_render_pass_id, new_render_pass_id);
   5127         bool has_texture = false;
   5128         bool contents_changed = true;
   5129 
   5130         if (*current_char == '[') {
   5131           current_char++;
   5132           while (*current_char && *current_char != ']') {
   5133             switch (*current_char) {
   5134               case 'c':
   5135                 contents_changed = false;
   5136                 break;
   5137               case 't':
   5138                 has_texture = true;
   5139                 break;
   5140             }
   5141             current_char++;
   5142           }
   5143           if (*current_char == ']')
   5144             current_char++;
   5145         }
   5146 
   5147         if (test_data->render_pass_cache.find(new_render_pass_id) ==
   5148             test_data->render_pass_cache.end()) {
   5149           if (has_texture)
   5150             renderer->SetHaveCachedResourcesForRenderPassId(new_render_pass_id);
   5151 
   5152           scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
   5153           pass->SetNew(new_render_pass_id,
   5154                        gfx::Rect(),
   5155                        gfx::Rect(),
   5156                        gfx::Transform());
   5157           test_data->render_pass_cache.add(new_render_pass_id, pass.Pass());
   5158         }
   5159 
   5160         gfx::Rect quad_rect = gfx::Rect(0, 0, 1, 1);
   5161         gfx::Rect contents_changed_rect =
   5162             contents_changed ? quad_rect : gfx::Rect();
   5163         scoped_ptr<RenderPassDrawQuad> quad = RenderPassDrawQuad::Create();
   5164         quad->SetNew(test_data->shared_quad_state.get(),
   5165                      quad_rect,
   5166                      new_render_pass_id,
   5167                      is_replica,
   5168                      1,
   5169                      contents_changed_rect,
   5170                      gfx::RectF(0.f, 0.f, 1.f, 1.f),
   5171                      FilterOperations(),
   5172                      skia::RefPtr<SkImageFilter>(),
   5173                      FilterOperations());
   5174         render_pass->AppendQuad(quad.PassAs<DrawQuad>());
   5175       }
   5176     }
   5177     test_data->render_passes_by_id[render_pass_id] = render_pass.get();
   5178     test_data->render_passes.insert(test_data->render_passes.begin(),
   5179                                     render_pass.PassAs<RenderPass>());
   5180     if (*current_char)
   5181       current_char++;
   5182   }
   5183 }
   5184 
   5185 void DumpRenderPassTestData(const RenderPassRemovalTestData& test_data,
   5186                             char* buffer) {
   5187   char* pos = buffer;
   5188   for (RenderPassList::const_reverse_iterator it =
   5189            test_data.render_passes.rbegin();
   5190        it != test_data.render_passes.rend();
   5191        ++it) {
   5192     const RenderPass* current_pass = *it;
   5193     *pos = current_pass->id.layer_id;
   5194     pos++;
   5195     *pos = current_pass->id.index;
   5196     pos++;
   5197 
   5198     QuadList::const_iterator quad_list_iterator =
   5199         current_pass->quad_list.begin();
   5200     while (quad_list_iterator != current_pass->quad_list.end()) {
   5201       DrawQuad* current_quad = *quad_list_iterator;
   5202       switch (current_quad->material) {
   5203         case DrawQuad::SOLID_COLOR:
   5204           *pos = 's';
   5205           pos++;
   5206           break;
   5207         case DrawQuad::RENDER_PASS:
   5208           *pos = RenderPassDrawQuad::MaterialCast(current_quad)->
   5209                      render_pass_id.layer_id;
   5210           pos++;
   5211           *pos = RenderPassDrawQuad::MaterialCast(current_quad)->
   5212                      render_pass_id.index;
   5213           pos++;
   5214           break;
   5215         default:
   5216           *pos = 'x';
   5217           pos++;
   5218           break;
   5219       }
   5220 
   5221       quad_list_iterator++;
   5222     }
   5223     *pos = '\n';
   5224     pos++;
   5225   }
   5226   *pos = '\0';
   5227 }
   5228 
   5229 // Each RenderPassList is represented by a string which describes the
   5230 // configuration.
   5231 // The syntax of the string is as follows:
   5232 //
   5233 //                                                   RsssssX[c]ssYsssZ[t]ssW[ct]
   5234 // Identifies the render pass------------------------^ ^^^ ^ ^   ^     ^     ^
   5235 // These are solid color quads--------------------------+  | |   |     |     |
   5236 // Identifies RenderPassDrawQuad's RenderPass--------------+ |   |     |     |
   5237 // This quad's contents didn't change------------------------+   |     |     |
   5238 // This quad's contents changed and it has no texture------------+     |     |
   5239 // This quad has texture but its contents changed----------------------+     |
   5240 // This quad's contents didn't change and it has texture - will be removed---+
   5241 //
   5242 // Expected results have exactly the same syntax, except they do not use square
   5243 // brackets, since we only check the structure, not attributes.
   5244 //
   5245 // Test case configuration consists of initialization script and expected
   5246 // results, all in the same format.
   5247 struct TestCase {
   5248   const char* name;
   5249   const char* init_script;
   5250   const char* expected_result;
   5251 };
   5252 
   5253 TestCase remove_render_passes_cases[] = {
   5254   {
   5255     "Single root pass",
   5256     "R0ssss\n",
   5257     "R0ssss\n"
   5258   }, {
   5259     "Single pass - no quads",
   5260     "R0\n",
   5261     "R0\n"
   5262   }, {
   5263     "Two passes, no removal",
   5264     "R0ssssA0sss\n"
   5265     "A0ssss\n",
   5266     "R0ssssA0sss\n"
   5267     "A0ssss\n"
   5268   }, {
   5269     "Two passes, remove last",
   5270     "R0ssssA0[ct]sss\n"
   5271     "A0ssss\n",
   5272     "R0ssssA0sss\n"
   5273   }, {
   5274     "Have texture but contents changed - leave pass",
   5275     "R0ssssA0[t]sss\n"
   5276     "A0ssss\n",
   5277     "R0ssssA0sss\n"
   5278     "A0ssss\n"
   5279   }, {
   5280     "Contents didn't change but no texture - leave pass",
   5281     "R0ssssA0[c]sss\n"
   5282     "A0ssss\n",
   5283     "R0ssssA0sss\n"
   5284     "A0ssss\n"
   5285   }, {
   5286     "Replica: two quads reference the same pass; remove",
   5287     "R0ssssA0[ct]A0[ct]sss\n"
   5288     "A0ssss\n",
   5289     "R0ssssA0A0sss\n"
   5290   }, {
   5291     "Replica: two quads reference the same pass; leave",
   5292     "R0ssssA0[c]A0[c]sss\n"
   5293     "A0ssss\n",
   5294     "R0ssssA0A0sss\n"
   5295     "A0ssss\n",
   5296   }, {
   5297     "Many passes, remove all",
   5298     "R0ssssA0[ct]sss\n"
   5299     "A0sssB0[ct]C0[ct]s\n"
   5300     "B0sssD0[ct]ssE0[ct]F0[ct]\n"
   5301     "E0ssssss\n"
   5302     "C0G0[ct]\n"
   5303     "D0sssssss\n"
   5304     "F0sssssss\n"
   5305     "G0sss\n",
   5306 
   5307     "R0ssssA0sss\n"
   5308   }, {
   5309     "Deep recursion, remove all",
   5310 
   5311     "R0sssssA0[ct]ssss\n"
   5312     "A0ssssB0sss\n"
   5313     "B0C0\n"
   5314     "C0D0\n"
   5315     "D0E0\n"
   5316     "E0F0\n"
   5317     "F0G0\n"
   5318     "G0H0\n"
   5319     "H0sssI0sss\n"
   5320     "I0J0\n"
   5321     "J0ssss\n",
   5322 
   5323     "R0sssssA0ssss\n"
   5324   }, {
   5325     "Wide recursion, remove all",
   5326     "R0A0[ct]B0[ct]C0[ct]D0[ct]E0[ct]F0[ct]G0[ct]H0[ct]I0[ct]J0[ct]\n"
   5327     "A0s\n"
   5328     "B0s\n"
   5329     "C0ssss\n"
   5330     "D0ssss\n"
   5331     "E0s\n"
   5332     "F0\n"
   5333     "G0s\n"
   5334     "H0s\n"
   5335     "I0s\n"
   5336     "J0ssss\n",
   5337 
   5338     "R0A0B0C0D0E0F0G0H0I0J0\n"
   5339   }, {
   5340     "Remove passes regardless of cache state",
   5341     "R0ssssA0[ct]sss\n"
   5342     "A0sssB0C0s\n"
   5343     "B0sssD0[c]ssE0[t]F0\n"
   5344     "E0ssssss\n"
   5345     "C0G0\n"
   5346     "D0sssssss\n"
   5347     "F0sssssss\n"
   5348     "G0sss\n",
   5349 
   5350     "R0ssssA0sss\n"
   5351   }, {
   5352     "Leave some passes, remove others",
   5353 
   5354     "R0ssssA0[c]sss\n"
   5355     "A0sssB0[t]C0[ct]s\n"
   5356     "B0sssD0[c]ss\n"
   5357     "C0G0\n"
   5358     "D0sssssss\n"
   5359     "G0sss\n",
   5360 
   5361     "R0ssssA0sss\n"
   5362     "A0sssB0C0s\n"
   5363     "B0sssD0ss\n"
   5364     "D0sssssss\n"
   5365   }, {
   5366     0, 0, 0
   5367   }
   5368 };
   5369 
   5370 static void VerifyRenderPassTestData(
   5371     const TestCase& test_case,
   5372     const RenderPassRemovalTestData& test_data) {
   5373   char actual_result[1024];
   5374   DumpRenderPassTestData(test_data, actual_result);
   5375   EXPECT_STREQ(test_case.expected_result, actual_result) << "In test case: " <<
   5376       test_case.name;
   5377 }
   5378 
   5379 TEST_F(LayerTreeHostImplTest, TestRemoveRenderPasses) {
   5380   scoped_ptr<OutputSurface> output_surface(CreateOutputSurface());
   5381   ASSERT_TRUE(output_surface->context3d());
   5382   scoped_ptr<ResourceProvider> resource_provider =
   5383       ResourceProvider::Create(output_surface.get(), 0);
   5384 
   5385   scoped_ptr<TestRenderer> renderer =
   5386       TestRenderer::Create(resource_provider.get(),
   5387                            output_surface.get(),
   5388                            &proxy_);
   5389 
   5390   int test_case_index = 0;
   5391   while (remove_render_passes_cases[test_case_index].name) {
   5392     RenderPassRemovalTestData test_data;
   5393     ConfigureRenderPassTestData(
   5394         remove_render_passes_cases[test_case_index].init_script,
   5395         &test_data,
   5396         renderer.get());
   5397     LayerTreeHostImpl::RemoveRenderPasses(
   5398         LayerTreeHostImpl::CullRenderPassesWithCachedTextures(renderer.get()),
   5399         &test_data);
   5400     VerifyRenderPassTestData(remove_render_passes_cases[test_case_index],
   5401                              test_data);
   5402     test_case_index++;
   5403   }
   5404 }
   5405 
   5406 class LayerTreeHostImplTestWithDelegatingRenderer
   5407     : public LayerTreeHostImplTest {
   5408  protected:
   5409   virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
   5410     return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
   5411   }
   5412 
   5413   void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
   5414     bool expect_to_draw = !expected_damage.IsEmpty();
   5415 
   5416     LayerTreeHostImpl::FrameData frame;
   5417     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5418 
   5419     if (!expect_to_draw) {
   5420       // With no damage, we don't draw, and no quads are created.
   5421       ASSERT_EQ(0u, frame.render_passes.size());
   5422     } else {
   5423       ASSERT_EQ(1u, frame.render_passes.size());
   5424 
   5425       // Verify the damage rect for the root render pass.
   5426       const RenderPass* root_render_pass = frame.render_passes.back();
   5427       EXPECT_RECT_EQ(expected_damage, root_render_pass->damage_rect);
   5428 
   5429       // Verify the root and child layers' quads are generated and not being
   5430       // culled.
   5431       ASSERT_EQ(2u, root_render_pass->quad_list.size());
   5432 
   5433       LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
   5434       gfx::RectF expected_child_visible_rect(child->content_bounds());
   5435       EXPECT_RECT_EQ(expected_child_visible_rect,
   5436                      root_render_pass->quad_list[0]->visible_rect);
   5437 
   5438       LayerImpl* root = host_impl_->active_tree()->root_layer();
   5439       gfx::RectF expected_root_visible_rect(root->content_bounds());
   5440       EXPECT_RECT_EQ(expected_root_visible_rect,
   5441                      root_render_pass->quad_list[1]->visible_rect);
   5442     }
   5443 
   5444     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5445     host_impl_->DidDrawAllLayers(frame);
   5446     EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
   5447   }
   5448 };
   5449 
   5450 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
   5451   scoped_ptr<SolidColorLayerImpl> root =
   5452       SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
   5453   root->SetAnchorPoint(gfx::PointF());
   5454   root->SetPosition(gfx::PointF());
   5455   root->SetBounds(gfx::Size(10, 10));
   5456   root->SetContentBounds(gfx::Size(10, 10));
   5457   root->SetDrawsContent(true);
   5458 
   5459   // Child layer is in the bottom right corner.
   5460   scoped_ptr<SolidColorLayerImpl> child =
   5461       SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
   5462   child->SetAnchorPoint(gfx::PointF(0.f, 0.f));
   5463   child->SetPosition(gfx::PointF(9.f, 9.f));
   5464   child->SetBounds(gfx::Size(1, 1));
   5465   child->SetContentBounds(gfx::Size(1, 1));
   5466   child->SetDrawsContent(true);
   5467   root->AddChild(child.PassAs<LayerImpl>());
   5468 
   5469   host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
   5470 
   5471   // Draw a frame. In the first frame, the entire viewport should be damaged.
   5472   gfx::Rect full_frame_damage = host_impl_->DeviceViewport();
   5473   DrawFrameAndTestDamage(full_frame_damage);
   5474 
   5475   // The second frame has damage that doesn't touch the child layer. Its quads
   5476   // should still be generated.
   5477   gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
   5478   host_impl_->active_tree()->root_layer()->set_update_rect(small_damage);
   5479   DrawFrameAndTestDamage(small_damage);
   5480 
   5481   // The third frame should have no damage, so no quads should be generated.
   5482   gfx::Rect no_damage;
   5483   DrawFrameAndTestDamage(no_damage);
   5484 }
   5485 
   5486 class FakeMaskLayerImpl : public LayerImpl {
   5487  public:
   5488   static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
   5489                                               int id) {
   5490     return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
   5491   }
   5492 
   5493   virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
   5494     return 0;
   5495   }
   5496 
   5497  private:
   5498   FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
   5499       : LayerImpl(tree_impl, id) {}
   5500 };
   5501 
   5502 TEST_F(LayerTreeHostImplTest, MaskLayerWithScaling) {
   5503   LayerTreeSettings settings;
   5504   settings.layer_transforms_should_scale_layer_contents = true;
   5505   host_impl_ = LayerTreeHostImpl::Create(settings,
   5506                                          this,
   5507                                          &proxy_,
   5508                                          &stats_instrumentation_);
   5509   host_impl_->InitializeRenderer(CreateOutputSurface());
   5510   host_impl_->SetViewportSize(gfx::Size(10, 10));
   5511 
   5512   // Root
   5513   //  |
   5514   //  +-- Scaling Layer (adds a 2x scale)
   5515   //       |
   5516   //       +-- Content Layer
   5517   //             +--Mask
   5518   scoped_ptr<LayerImpl> scoped_root =
   5519       LayerImpl::Create(host_impl_->active_tree(), 1);
   5520   LayerImpl* root = scoped_root.get();
   5521   host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
   5522 
   5523   scoped_ptr<LayerImpl> scoped_scaling_layer =
   5524       LayerImpl::Create(host_impl_->active_tree(), 2);
   5525   LayerImpl* scaling_layer = scoped_scaling_layer.get();
   5526   root->AddChild(scoped_scaling_layer.Pass());
   5527 
   5528   scoped_ptr<LayerImpl> scoped_content_layer =
   5529       LayerImpl::Create(host_impl_->active_tree(), 3);
   5530   LayerImpl* content_layer = scoped_content_layer.get();
   5531   scaling_layer->AddChild(scoped_content_layer.Pass());
   5532 
   5533   scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
   5534       FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
   5535   FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
   5536   content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
   5537 
   5538   gfx::Size root_size(100, 100);
   5539   root->SetBounds(root_size);
   5540   root->SetContentBounds(root_size);
   5541   root->SetPosition(gfx::PointF());
   5542   root->SetAnchorPoint(gfx::PointF());
   5543 
   5544   gfx::Size scaling_layer_size(50, 50);
   5545   scaling_layer->SetBounds(scaling_layer_size);
   5546   scaling_layer->SetContentBounds(scaling_layer_size);
   5547   scaling_layer->SetPosition(gfx::PointF());
   5548   scaling_layer->SetAnchorPoint(gfx::PointF());
   5549   gfx::Transform scale;
   5550   scale.Scale(2.f, 2.f);
   5551   scaling_layer->SetTransform(scale);
   5552 
   5553   content_layer->SetBounds(scaling_layer_size);
   5554   content_layer->SetContentBounds(scaling_layer_size);
   5555   content_layer->SetPosition(gfx::PointF());
   5556   content_layer->SetAnchorPoint(gfx::PointF());
   5557   content_layer->SetDrawsContent(true);
   5558 
   5559   mask_layer->SetBounds(scaling_layer_size);
   5560   mask_layer->SetContentBounds(scaling_layer_size);
   5561   mask_layer->SetPosition(gfx::PointF());
   5562   mask_layer->SetAnchorPoint(gfx::PointF());
   5563   mask_layer->SetDrawsContent(true);
   5564 
   5565 
   5566   // Check that the tree scaling is correctly taken into account for the mask,
   5567   // that should fully map onto the quad.
   5568   float device_scale_factor = 1.f;
   5569   host_impl_->SetViewportSize(root_size);
   5570   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   5571   {
   5572     LayerTreeHostImpl::FrameData frame;
   5573     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5574 
   5575     ASSERT_EQ(1u, frame.render_passes.size());
   5576     ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
   5577     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5578               frame.render_passes[0]->quad_list[0]->material);
   5579     const RenderPassDrawQuad* render_pass_quad =
   5580         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   5581     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
   5582               render_pass_quad->rect.ToString());
   5583     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5584               render_pass_quad->mask_uv_rect.ToString());
   5585 
   5586     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5587     host_impl_->DidDrawAllLayers(frame);
   5588   }
   5589 
   5590 
   5591   // Applying a DSF should change the render surface size, but won't affect
   5592   // which part of the mask is used.
   5593   device_scale_factor = 2.f;
   5594   gfx::Size device_viewport =
   5595       gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
   5596   host_impl_->SetViewportSize(device_viewport);
   5597   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   5598   host_impl_->active_tree()->set_needs_update_draw_properties();
   5599   {
   5600     LayerTreeHostImpl::FrameData frame;
   5601     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5602 
   5603     ASSERT_EQ(1u, frame.render_passes.size());
   5604     ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
   5605     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5606               frame.render_passes[0]->quad_list[0]->material);
   5607     const RenderPassDrawQuad* render_pass_quad =
   5608         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   5609     EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
   5610               render_pass_quad->rect.ToString());
   5611     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5612               render_pass_quad->mask_uv_rect.ToString());
   5613 
   5614     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5615     host_impl_->DidDrawAllLayers(frame);
   5616   }
   5617 
   5618 
   5619   // Applying an equivalent content scale on the content layer and the mask
   5620   // should still result in the same part of the mask being used.
   5621   gfx::Size content_bounds =
   5622       gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size,
   5623                                         device_scale_factor));
   5624   content_layer->SetContentBounds(content_bounds);
   5625   content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
   5626   mask_layer->SetContentBounds(content_bounds);
   5627   mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
   5628   host_impl_->active_tree()->set_needs_update_draw_properties();
   5629   {
   5630     LayerTreeHostImpl::FrameData frame;
   5631     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5632 
   5633     ASSERT_EQ(1u, frame.render_passes.size());
   5634     ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
   5635     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5636               frame.render_passes[0]->quad_list[0]->material);
   5637     const RenderPassDrawQuad* render_pass_quad =
   5638         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   5639     EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
   5640               render_pass_quad->rect.ToString());
   5641     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5642               render_pass_quad->mask_uv_rect.ToString());
   5643 
   5644     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5645     host_impl_->DidDrawAllLayers(frame);
   5646   }
   5647 }
   5648 
   5649 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
   5650   // The mask layer has bounds 100x100 but is attached to a layer with bounds
   5651   // 50x50.
   5652 
   5653   scoped_ptr<LayerImpl> scoped_root =
   5654       LayerImpl::Create(host_impl_->active_tree(), 1);
   5655   LayerImpl* root = scoped_root.get();
   5656   host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
   5657 
   5658   scoped_ptr<LayerImpl> scoped_content_layer =
   5659       LayerImpl::Create(host_impl_->active_tree(), 3);
   5660   LayerImpl* content_layer = scoped_content_layer.get();
   5661   root->AddChild(scoped_content_layer.Pass());
   5662 
   5663   scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
   5664       FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
   5665   FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
   5666   content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
   5667 
   5668   gfx::Size root_size(100, 100);
   5669   root->SetBounds(root_size);
   5670   root->SetContentBounds(root_size);
   5671   root->SetPosition(gfx::PointF());
   5672   root->SetAnchorPoint(gfx::PointF());
   5673 
   5674   gfx::Size layer_size(50, 50);
   5675   content_layer->SetBounds(layer_size);
   5676   content_layer->SetContentBounds(layer_size);
   5677   content_layer->SetPosition(gfx::PointF());
   5678   content_layer->SetAnchorPoint(gfx::PointF());
   5679   content_layer->SetDrawsContent(true);
   5680 
   5681   gfx::Size mask_size(100, 100);
   5682   mask_layer->SetBounds(mask_size);
   5683   mask_layer->SetContentBounds(mask_size);
   5684   mask_layer->SetPosition(gfx::PointF());
   5685   mask_layer->SetAnchorPoint(gfx::PointF());
   5686   mask_layer->SetDrawsContent(true);
   5687 
   5688   // Check that the mask fills the surface.
   5689   float device_scale_factor = 1.f;
   5690   host_impl_->SetViewportSize(root_size);
   5691   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   5692   {
   5693     LayerTreeHostImpl::FrameData frame;
   5694     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5695 
   5696     ASSERT_EQ(1u, frame.render_passes.size());
   5697     ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
   5698     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5699               frame.render_passes[0]->quad_list[0]->material);
   5700     const RenderPassDrawQuad* render_pass_quad =
   5701         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   5702     EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
   5703               render_pass_quad->rect.ToString());
   5704     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5705               render_pass_quad->mask_uv_rect.ToString());
   5706 
   5707     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5708     host_impl_->DidDrawAllLayers(frame);
   5709   }
   5710 
   5711   // Applying a DSF should change the render surface size, but won't affect
   5712   // which part of the mask is used.
   5713   device_scale_factor = 2.f;
   5714   gfx::Size device_viewport =
   5715       gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
   5716   host_impl_->SetViewportSize(device_viewport);
   5717   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   5718   host_impl_->active_tree()->set_needs_update_draw_properties();
   5719   {
   5720     LayerTreeHostImpl::FrameData frame;
   5721     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5722 
   5723     ASSERT_EQ(1u, frame.render_passes.size());
   5724     ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
   5725     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5726               frame.render_passes[0]->quad_list[0]->material);
   5727     const RenderPassDrawQuad* render_pass_quad =
   5728         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   5729     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
   5730               render_pass_quad->rect.ToString());
   5731     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5732               render_pass_quad->mask_uv_rect.ToString());
   5733 
   5734     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5735     host_impl_->DidDrawAllLayers(frame);
   5736   }
   5737 
   5738   // Applying an equivalent content scale on the content layer and the mask
   5739   // should still result in the same part of the mask being used.
   5740   gfx::Size layer_size_large =
   5741       gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
   5742   content_layer->SetContentBounds(layer_size_large);
   5743   content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
   5744   gfx::Size mask_size_large =
   5745       gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
   5746   mask_layer->SetContentBounds(mask_size_large);
   5747   mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
   5748   host_impl_->active_tree()->set_needs_update_draw_properties();
   5749   {
   5750     LayerTreeHostImpl::FrameData frame;
   5751     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5752 
   5753     ASSERT_EQ(1u, frame.render_passes.size());
   5754     ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
   5755     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5756               frame.render_passes[0]->quad_list[0]->material);
   5757     const RenderPassDrawQuad* render_pass_quad =
   5758         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   5759     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
   5760               render_pass_quad->rect.ToString());
   5761     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5762               render_pass_quad->mask_uv_rect.ToString());
   5763 
   5764     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5765     host_impl_->DidDrawAllLayers(frame);
   5766   }
   5767 
   5768   // Applying a different contents scale to the mask layer means it will have
   5769   // a larger texture, but it should use the same tex coords to cover the
   5770   // layer it masks.
   5771   mask_layer->SetContentBounds(mask_size);
   5772   mask_layer->SetContentsScale(1.f, 1.f);
   5773   host_impl_->active_tree()->set_needs_update_draw_properties();
   5774   {
   5775     LayerTreeHostImpl::FrameData frame;
   5776     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5777 
   5778     ASSERT_EQ(1u, frame.render_passes.size());
   5779     ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
   5780     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5781               frame.render_passes[0]->quad_list[0]->material);
   5782     const RenderPassDrawQuad* render_pass_quad =
   5783         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   5784     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
   5785               render_pass_quad->rect.ToString());
   5786     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5787               render_pass_quad->mask_uv_rect.ToString());
   5788 
   5789     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5790     host_impl_->DidDrawAllLayers(frame);
   5791   }
   5792 }
   5793 
   5794 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
   5795   // The replica's mask layer has bounds 100x100 but the replica is of a
   5796   // layer with bounds 50x50.
   5797 
   5798   scoped_ptr<LayerImpl> scoped_root =
   5799       LayerImpl::Create(host_impl_->active_tree(), 1);
   5800   LayerImpl* root = scoped_root.get();
   5801   host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
   5802 
   5803   scoped_ptr<LayerImpl> scoped_content_layer =
   5804       LayerImpl::Create(host_impl_->active_tree(), 3);
   5805   LayerImpl* content_layer = scoped_content_layer.get();
   5806   root->AddChild(scoped_content_layer.Pass());
   5807 
   5808   scoped_ptr<LayerImpl> scoped_replica_layer =
   5809       LayerImpl::Create(host_impl_->active_tree(), 2);
   5810   LayerImpl* replica_layer = scoped_replica_layer.get();
   5811   content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
   5812 
   5813   scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
   5814       FakeMaskLayerImpl::Create(host_impl_->active_tree(), 4);
   5815   FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
   5816   replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
   5817 
   5818   gfx::Size root_size(100, 100);
   5819   root->SetBounds(root_size);
   5820   root->SetContentBounds(root_size);
   5821   root->SetPosition(gfx::PointF());
   5822   root->SetAnchorPoint(gfx::PointF());
   5823 
   5824   gfx::Size layer_size(50, 50);
   5825   content_layer->SetBounds(layer_size);
   5826   content_layer->SetContentBounds(layer_size);
   5827   content_layer->SetPosition(gfx::PointF());
   5828   content_layer->SetAnchorPoint(gfx::PointF());
   5829   content_layer->SetDrawsContent(true);
   5830 
   5831   gfx::Size mask_size(100, 100);
   5832   mask_layer->SetBounds(mask_size);
   5833   mask_layer->SetContentBounds(mask_size);
   5834   mask_layer->SetPosition(gfx::PointF());
   5835   mask_layer->SetAnchorPoint(gfx::PointF());
   5836   mask_layer->SetDrawsContent(true);
   5837 
   5838   // Check that the mask fills the surface.
   5839   float device_scale_factor = 1.f;
   5840   host_impl_->SetViewportSize(root_size);
   5841   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   5842   {
   5843     LayerTreeHostImpl::FrameData frame;
   5844     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5845 
   5846     ASSERT_EQ(1u, frame.render_passes.size());
   5847     ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
   5848     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5849               frame.render_passes[0]->quad_list[1]->material);
   5850     const RenderPassDrawQuad* replica_quad =
   5851         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
   5852     EXPECT_TRUE(replica_quad->is_replica);
   5853     EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
   5854               replica_quad->rect.ToString());
   5855     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5856               replica_quad->mask_uv_rect.ToString());
   5857 
   5858     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5859     host_impl_->DidDrawAllLayers(frame);
   5860   }
   5861 
   5862   // Applying a DSF should change the render surface size, but won't affect
   5863   // which part of the mask is used.
   5864   device_scale_factor = 2.f;
   5865   gfx::Size device_viewport =
   5866       gfx::ToFlooredSize(gfx::ScaleSize(root_size, device_scale_factor));
   5867   host_impl_->SetViewportSize(device_viewport);
   5868   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   5869   host_impl_->active_tree()->set_needs_update_draw_properties();
   5870   {
   5871     LayerTreeHostImpl::FrameData frame;
   5872     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5873 
   5874     ASSERT_EQ(1u, frame.render_passes.size());
   5875     ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
   5876     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5877               frame.render_passes[0]->quad_list[1]->material);
   5878     const RenderPassDrawQuad* replica_quad =
   5879         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
   5880     EXPECT_TRUE(replica_quad->is_replica);
   5881     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
   5882               replica_quad->rect.ToString());
   5883     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5884               replica_quad->mask_uv_rect.ToString());
   5885 
   5886     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5887     host_impl_->DidDrawAllLayers(frame);
   5888   }
   5889 
   5890   // Applying an equivalent content scale on the content layer and the mask
   5891   // should still result in the same part of the mask being used.
   5892   gfx::Size layer_size_large =
   5893       gfx::ToRoundedSize(gfx::ScaleSize(layer_size, device_scale_factor));
   5894   content_layer->SetContentBounds(layer_size_large);
   5895   content_layer->SetContentsScale(device_scale_factor, device_scale_factor);
   5896   gfx::Size mask_size_large =
   5897       gfx::ToRoundedSize(gfx::ScaleSize(mask_size, device_scale_factor));
   5898   mask_layer->SetContentBounds(mask_size_large);
   5899   mask_layer->SetContentsScale(device_scale_factor, device_scale_factor);
   5900   host_impl_->active_tree()->set_needs_update_draw_properties();
   5901   {
   5902     LayerTreeHostImpl::FrameData frame;
   5903     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5904 
   5905     ASSERT_EQ(1u, frame.render_passes.size());
   5906     ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
   5907     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5908               frame.render_passes[0]->quad_list[1]->material);
   5909     const RenderPassDrawQuad* replica_quad =
   5910         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
   5911     EXPECT_TRUE(replica_quad->is_replica);
   5912     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
   5913               replica_quad->rect.ToString());
   5914     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5915               replica_quad->mask_uv_rect.ToString());
   5916 
   5917     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5918     host_impl_->DidDrawAllLayers(frame);
   5919   }
   5920 
   5921   // Applying a different contents scale to the mask layer means it will have
   5922   // a larger texture, but it should use the same tex coords to cover the
   5923   // layer it masks.
   5924   mask_layer->SetContentBounds(mask_size);
   5925   mask_layer->SetContentsScale(1.f, 1.f);
   5926   host_impl_->active_tree()->set_needs_update_draw_properties();
   5927   {
   5928     LayerTreeHostImpl::FrameData frame;
   5929     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   5930 
   5931     ASSERT_EQ(1u, frame.render_passes.size());
   5932     ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
   5933     ASSERT_EQ(DrawQuad::RENDER_PASS,
   5934               frame.render_passes[0]->quad_list[1]->material);
   5935     const RenderPassDrawQuad* replica_quad =
   5936         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
   5937     EXPECT_TRUE(replica_quad->is_replica);
   5938     EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
   5939               replica_quad->rect.ToString());
   5940     EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(),
   5941               replica_quad->mask_uv_rect.ToString());
   5942 
   5943     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   5944     host_impl_->DidDrawAllLayers(frame);
   5945   }
   5946 }
   5947 
   5948 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerForSurfaceWithUnclippedChild) {
   5949   // The replica is of a layer with bounds 50x50, but it has a child that causes
   5950   // the surface bounds to be larger.
   5951 
   5952   scoped_ptr<LayerImpl> scoped_root =
   5953       LayerImpl::Create(host_impl_->active_tree(), 1);
   5954   LayerImpl* root = scoped_root.get();
   5955   host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
   5956 
   5957   scoped_ptr<LayerImpl> scoped_content_layer =
   5958       LayerImpl::Create(host_impl_->active_tree(), 2);
   5959   LayerImpl* content_layer = scoped_content_layer.get();
   5960   root->AddChild(scoped_content_layer.Pass());
   5961 
   5962   scoped_ptr<LayerImpl> scoped_content_child_layer =
   5963       LayerImpl::Create(host_impl_->active_tree(), 3);
   5964   LayerImpl* content_child_layer = scoped_content_child_layer.get();
   5965   content_layer->AddChild(scoped_content_child_layer.Pass());
   5966 
   5967   scoped_ptr<LayerImpl> scoped_replica_layer =
   5968       LayerImpl::Create(host_impl_->active_tree(), 4);
   5969   LayerImpl* replica_layer = scoped_replica_layer.get();
   5970   content_layer->SetReplicaLayer(scoped_replica_layer.Pass());
   5971 
   5972   scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
   5973       FakeMaskLayerImpl::Create(host_impl_->active_tree(), 5);
   5974   FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
   5975   replica_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
   5976 
   5977   gfx::Size root_size(100, 100);
   5978   root->SetBounds(root_size);
   5979   root->SetContentBounds(root_size);
   5980   root->SetPosition(gfx::PointF());
   5981   root->SetAnchorPoint(gfx::PointF());
   5982 
   5983   gfx::Size layer_size(50, 50);
   5984   content_layer->SetBounds(layer_size);
   5985   content_layer->SetContentBounds(layer_size);
   5986   content_layer->SetPosition(gfx::PointF());
   5987   content_layer->SetAnchorPoint(gfx::PointF());
   5988   content_layer->SetDrawsContent(true);
   5989 
   5990   gfx::Size child_size(50, 50);
   5991   content_child_layer->SetBounds(child_size);
   5992   content_child_layer->SetContentBounds(child_size);
   5993   content_child_layer->SetPosition(gfx::Point(50, 0));
   5994   content_child_layer->SetAnchorPoint(gfx::PointF());
   5995   content_child_layer->SetDrawsContent(true);
   5996 
   5997   gfx::Size mask_size(50, 50);
   5998   mask_layer->SetBounds(mask_size);
   5999   mask_layer->SetContentBounds(mask_size);
   6000   mask_layer->SetPosition(gfx::PointF());
   6001   mask_layer->SetAnchorPoint(gfx::PointF());
   6002   mask_layer->SetDrawsContent(true);
   6003 
   6004   float device_scale_factor = 1.f;
   6005   host_impl_->SetViewportSize(root_size);
   6006   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   6007   {
   6008     LayerTreeHostImpl::FrameData frame;
   6009     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   6010 
   6011     ASSERT_EQ(1u, frame.render_passes.size());
   6012     ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
   6013 
   6014     // The surface is 100x50.
   6015     ASSERT_EQ(DrawQuad::RENDER_PASS,
   6016               frame.render_passes[0]->quad_list[0]->material);
   6017     const RenderPassDrawQuad* render_pass_quad =
   6018         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   6019     EXPECT_FALSE(render_pass_quad->is_replica);
   6020     EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
   6021               render_pass_quad->rect.ToString());
   6022 
   6023     // The mask covers the owning layer only.
   6024     ASSERT_EQ(DrawQuad::RENDER_PASS,
   6025               frame.render_passes[0]->quad_list[1]->material);
   6026     const RenderPassDrawQuad* replica_quad =
   6027         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
   6028     EXPECT_TRUE(replica_quad->is_replica);
   6029     EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
   6030               replica_quad->rect.ToString());
   6031     EXPECT_EQ(gfx::RectF(0.f, 0.f, 2.f, 1.f).ToString(),
   6032               replica_quad->mask_uv_rect.ToString());
   6033 
   6034     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   6035     host_impl_->DidDrawAllLayers(frame);
   6036   }
   6037 
   6038   // Move the child to (-50, 0) instead. Now the mask should be moved to still
   6039   // cover the layer being replicated.
   6040   content_child_layer->SetPosition(gfx::Point(-50, 0));
   6041   {
   6042     LayerTreeHostImpl::FrameData frame;
   6043     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   6044 
   6045     ASSERT_EQ(1u, frame.render_passes.size());
   6046     ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
   6047 
   6048     // The surface is 100x50 with its origin at (-50, 0).
   6049     ASSERT_EQ(DrawQuad::RENDER_PASS,
   6050               frame.render_passes[0]->quad_list[0]->material);
   6051     const RenderPassDrawQuad* render_pass_quad =
   6052         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   6053     EXPECT_FALSE(render_pass_quad->is_replica);
   6054     EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
   6055               render_pass_quad->rect.ToString());
   6056 
   6057     // The mask covers the owning layer only.
   6058     ASSERT_EQ(DrawQuad::RENDER_PASS,
   6059               frame.render_passes[0]->quad_list[1]->material);
   6060     const RenderPassDrawQuad* replica_quad =
   6061         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[1]);
   6062     EXPECT_TRUE(replica_quad->is_replica);
   6063     EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
   6064               replica_quad->rect.ToString());
   6065     EXPECT_EQ(gfx::RectF(-1.f, 0.f, 2.f, 1.f).ToString(),
   6066               replica_quad->mask_uv_rect.ToString());
   6067 
   6068     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   6069     host_impl_->DidDrawAllLayers(frame);
   6070   }
   6071 }
   6072 
   6073 TEST_F(LayerTreeHostImplTest, MaskLayerForSurfaceWithClippedLayer) {
   6074   // The masked layer has bounds 50x50, but it has a child that causes
   6075   // the surface bounds to be larger. It also has a parent that clips the
   6076   // masked layer and its surface.
   6077 
   6078   scoped_ptr<LayerImpl> scoped_root =
   6079       LayerImpl::Create(host_impl_->active_tree(), 1);
   6080   LayerImpl* root = scoped_root.get();
   6081   host_impl_->active_tree()->SetRootLayer(scoped_root.Pass());
   6082 
   6083   scoped_ptr<LayerImpl> scoped_clipping_layer =
   6084       LayerImpl::Create(host_impl_->active_tree(), 2);
   6085   LayerImpl* clipping_layer = scoped_clipping_layer.get();
   6086   root->AddChild(scoped_clipping_layer.Pass());
   6087 
   6088   scoped_ptr<LayerImpl> scoped_content_layer =
   6089       LayerImpl::Create(host_impl_->active_tree(), 3);
   6090   LayerImpl* content_layer = scoped_content_layer.get();
   6091   clipping_layer->AddChild(scoped_content_layer.Pass());
   6092 
   6093   scoped_ptr<LayerImpl> scoped_content_child_layer =
   6094       LayerImpl::Create(host_impl_->active_tree(), 4);
   6095   LayerImpl* content_child_layer = scoped_content_child_layer.get();
   6096   content_layer->AddChild(scoped_content_child_layer.Pass());
   6097 
   6098   scoped_ptr<FakeMaskLayerImpl> scoped_mask_layer =
   6099       FakeMaskLayerImpl::Create(host_impl_->active_tree(), 6);
   6100   FakeMaskLayerImpl* mask_layer = scoped_mask_layer.get();
   6101   content_layer->SetMaskLayer(scoped_mask_layer.PassAs<LayerImpl>());
   6102 
   6103   gfx::Size root_size(100, 100);
   6104   root->SetBounds(root_size);
   6105   root->SetContentBounds(root_size);
   6106   root->SetPosition(gfx::PointF());
   6107   root->SetAnchorPoint(gfx::PointF());
   6108 
   6109   gfx::Rect clipping_rect(20, 10, 10, 20);
   6110   clipping_layer->SetBounds(clipping_rect.size());
   6111   clipping_layer->SetContentBounds(clipping_rect.size());
   6112   clipping_layer->SetPosition(clipping_rect.origin());
   6113   clipping_layer->SetAnchorPoint(gfx::PointF());
   6114   clipping_layer->SetMasksToBounds(true);
   6115 
   6116   gfx::Size layer_size(50, 50);
   6117   content_layer->SetBounds(layer_size);
   6118   content_layer->SetContentBounds(layer_size);
   6119   content_layer->SetPosition(gfx::Point() - clipping_rect.OffsetFromOrigin());
   6120   content_layer->SetAnchorPoint(gfx::PointF());
   6121   content_layer->SetDrawsContent(true);
   6122 
   6123   gfx::Size child_size(50, 50);
   6124   content_child_layer->SetBounds(child_size);
   6125   content_child_layer->SetContentBounds(child_size);
   6126   content_child_layer->SetPosition(gfx::Point(50, 0));
   6127   content_child_layer->SetAnchorPoint(gfx::PointF());
   6128   content_child_layer->SetDrawsContent(true);
   6129 
   6130   gfx::Size mask_size(100, 100);
   6131   mask_layer->SetBounds(mask_size);
   6132   mask_layer->SetContentBounds(mask_size);
   6133   mask_layer->SetPosition(gfx::PointF());
   6134   mask_layer->SetAnchorPoint(gfx::PointF());
   6135   mask_layer->SetDrawsContent(true);
   6136 
   6137   float device_scale_factor = 1.f;
   6138   host_impl_->SetViewportSize(root_size);
   6139   host_impl_->SetDeviceScaleFactor(device_scale_factor);
   6140   {
   6141     LayerTreeHostImpl::FrameData frame;
   6142     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   6143 
   6144     ASSERT_EQ(1u, frame.render_passes.size());
   6145     ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
   6146 
   6147     // The surface is clipped to 10x20.
   6148     ASSERT_EQ(DrawQuad::RENDER_PASS,
   6149               frame.render_passes[0]->quad_list[0]->material);
   6150     const RenderPassDrawQuad* render_pass_quad =
   6151         RenderPassDrawQuad::MaterialCast(frame.render_passes[0]->quad_list[0]);
   6152     EXPECT_FALSE(render_pass_quad->is_replica);
   6153     EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
   6154               render_pass_quad->rect.ToString());
   6155 
   6156     // The masked layer is 50x50, but the surface size is 10x20. So the texture
   6157     // coords in the mask are scaled by 10/50 and 20/50.
   6158     // The surface is clipped to (20,10) so the mask texture coords are offset
   6159     // by 20/50 and 10/50
   6160     EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f, 10.f, 10.f, 20.f),
   6161                              1.f / 50.f).ToString(),
   6162               render_pass_quad->mask_uv_rect.ToString());
   6163 
   6164     host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   6165     host_impl_->DidDrawAllLayers(frame);
   6166   }
   6167 }
   6168 
   6169 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
   6170  public:
   6171   CompositorFrameMetadataTest()
   6172       : swap_buffers_complete_(0) {}
   6173 
   6174   virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {
   6175     swap_buffers_complete_++;
   6176   }
   6177 
   6178   int swap_buffers_complete_;
   6179 };
   6180 
   6181 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
   6182   SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
   6183   {
   6184     LayerTreeHostImpl::FrameData frame;
   6185     EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   6186     host_impl_->DrawLayers(&frame, base::TimeTicks());
   6187     host_impl_->DidDrawAllLayers(frame);
   6188   }
   6189   CompositorFrameAck ack;
   6190   host_impl_->OnSwapBuffersComplete(&ack);
   6191   EXPECT_EQ(swap_buffers_complete_, 1);
   6192 }
   6193 
   6194 class CountingSoftwareDevice : public SoftwareOutputDevice {
   6195  public:
   6196   CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
   6197 
   6198   virtual SkCanvas* BeginPaint(gfx::Rect damage_rect) OVERRIDE {
   6199     ++frames_began_;
   6200     return SoftwareOutputDevice::BeginPaint(damage_rect);
   6201   }
   6202   virtual void EndPaint(SoftwareFrameData* frame_data) OVERRIDE {
   6203     ++frames_ended_;
   6204     SoftwareOutputDevice::EndPaint(frame_data);
   6205   }
   6206 
   6207   int frames_began_, frames_ended_;
   6208 };
   6209 
   6210 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
   6211   // No main thread evictions in resourceless software mode.
   6212   set_reduce_memory_result(false);
   6213   SetupScrollAndContentsLayers(gfx::Size(100, 100));
   6214   host_impl_->SetViewportSize(gfx::Size(50, 50));
   6215   CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
   6216   FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
   6217       scoped_ptr<SoftwareOutputDevice>(software_device)).release();
   6218   EXPECT_TRUE(host_impl_->InitializeRenderer(
   6219       scoped_ptr<OutputSurface>(output_surface)));
   6220 
   6221   output_surface->set_forced_draw_to_software_device(true);
   6222   EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
   6223 
   6224   EXPECT_EQ(0, software_device->frames_began_);
   6225   EXPECT_EQ(0, software_device->frames_ended_);
   6226 
   6227   DrawFrame();
   6228 
   6229   EXPECT_EQ(1, software_device->frames_began_);
   6230   EXPECT_EQ(1, software_device->frames_ended_);
   6231 
   6232   // Call other API methods that are likely to hit NULL pointer in this mode.
   6233   EXPECT_TRUE(host_impl_->AsValue());
   6234   EXPECT_TRUE(host_impl_->ActivationStateAsValue());
   6235 }
   6236 
   6237 TEST_F(LayerTreeHostImplTest,
   6238        ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
   6239   set_reduce_memory_result(false);
   6240   FakeOutputSurface* output_surface = FakeOutputSurface::CreateDeferredGL(
   6241       scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())).release();
   6242   host_impl_->InitializeRenderer(
   6243       scoped_ptr<OutputSurface>(output_surface));
   6244 
   6245   output_surface->set_forced_draw_to_software_device(true);
   6246   EXPECT_TRUE(output_surface->ForcedDrawToSoftwareDevice());
   6247 
   6248   // SolidColorLayerImpl will be drawn.
   6249   scoped_ptr<SolidColorLayerImpl> root_layer =
   6250       SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
   6251 
   6252   // VideoLayerImpl will not be drawn.
   6253   FakeVideoFrameProvider provider;
   6254   scoped_ptr<VideoLayerImpl> video_layer =
   6255       VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
   6256   video_layer->SetBounds(gfx::Size(10, 10));
   6257   video_layer->SetContentBounds(gfx::Size(10, 10));
   6258   video_layer->SetDrawsContent(true);
   6259   root_layer->AddChild(video_layer.PassAs<LayerImpl>());
   6260   SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
   6261 
   6262   LayerTreeHostImpl::FrameData frame;
   6263   EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
   6264   host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
   6265   host_impl_->DidDrawAllLayers(frame);
   6266 
   6267   EXPECT_EQ(1u, frame.will_draw_layers.size());
   6268   EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
   6269 }
   6270 
   6271 TEST_F(LayerTreeHostImplTest, DeferredInitializeSmoke) {
   6272   set_reduce_memory_result(false);
   6273   scoped_ptr<FakeOutputSurface> output_surface(
   6274       FakeOutputSurface::CreateDeferredGL(
   6275           scoped_ptr<SoftwareOutputDevice>(new CountingSoftwareDevice())));
   6276   FakeOutputSurface* output_surface_ptr = output_surface.get();
   6277   EXPECT_TRUE(
   6278       host_impl_->InitializeRenderer(output_surface.PassAs<OutputSurface>()));
   6279 
   6280   // Add two layers.
   6281   scoped_ptr<SolidColorLayerImpl> root_layer =
   6282       SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
   6283   FakeVideoFrameProvider provider;
   6284   scoped_ptr<VideoLayerImpl> video_layer =
   6285       VideoLayerImpl::Create(host_impl_->active_tree(), 2, &provider);
   6286   video_layer->SetBounds(gfx::Size(10, 10));
   6287   video_layer->SetContentBounds(gfx::Size(10, 10));
   6288   video_layer->SetDrawsContent(true);
   6289   root_layer->AddChild(video_layer.PassAs<LayerImpl>());
   6290   SetupRootLayerImpl(root_layer.PassAs<LayerImpl>());
   6291 
   6292   // Software draw.
   6293   DrawFrame();
   6294 
   6295   // DeferredInitialize and hardware draw.
   6296   EXPECT_FALSE(did_try_initialize_renderer_);
   6297   EXPECT_TRUE(output_surface_ptr->SetAndInitializeContext3D(
   6298       scoped_ptr<WebKit::WebGraphicsContext3D>(
   6299           TestWebGraphicsContext3D::Create())));
   6300   EXPECT_TRUE(did_try_initialize_renderer_);
   6301 
   6302   // Defer intialized GL draw.
   6303   DrawFrame();
   6304 
   6305   // Revert back to software.
   6306   did_try_initialize_renderer_ = false;
   6307   output_surface_ptr->ReleaseGL();
   6308   EXPECT_TRUE(did_try_initialize_renderer_);
   6309   DrawFrame();
   6310 }
   6311 
   6312 class ContextThatDoesNotSupportMemoryManagmentExtensions
   6313     : public TestWebGraphicsContext3D {
   6314  public:
   6315   // WebGraphicsContext3D methods.
   6316   virtual WebKit::WebString getString(WebKit::WGC3Denum name) {
   6317     return WebKit::WebString();
   6318   }
   6319 };
   6320 
   6321 // Checks that we have a non-0 default allocation if we pass a context that
   6322 // doesn't support memory management extensions.
   6323 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
   6324   LayerTreeSettings settings;
   6325   host_impl_ = LayerTreeHostImpl::Create(settings,
   6326                                          this,
   6327                                          &proxy_,
   6328                                          &stats_instrumentation_);
   6329 
   6330   host_impl_->InitializeRenderer(FakeOutputSurface::Create3d(
   6331       scoped_ptr<WebKit::WebGraphicsContext3D>(
   6332           new ContextThatDoesNotSupportMemoryManagmentExtensions))
   6333       .PassAs<OutputSurface>());
   6334   EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
   6335 }
   6336 
   6337 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
   6338   ManagedMemoryPolicy policy1(
   6339       456, ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
   6340       123, ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE, 1000);
   6341   int visible_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
   6342       policy1.priority_cutoff_when_visible);
   6343   int not_visible_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
   6344       policy1.priority_cutoff_when_not_visible);
   6345 
   6346   host_impl_->SetVisible(true);
   6347   host_impl_->SetMemoryPolicy(policy1);
   6348   EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
   6349   EXPECT_EQ(visible_cutoff_value, current_priority_cutoff_value_);
   6350 
   6351   host_impl_->SetVisible(false);
   6352   EXPECT_EQ(policy1.bytes_limit_when_not_visible, current_limit_bytes_);
   6353   EXPECT_EQ(not_visible_cutoff_value, current_priority_cutoff_value_);
   6354 
   6355   host_impl_->SetVisible(true);
   6356   EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
   6357   EXPECT_EQ(visible_cutoff_value, current_priority_cutoff_value_);
   6358 }
   6359 
   6360 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
   6361   scoped_ptr<TestWebGraphicsContext3D> context =
   6362       TestWebGraphicsContext3D::Create();
   6363   TestWebGraphicsContext3D* context3d = context.get();
   6364   scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(
   6365       context.PassAs<WebKit::WebGraphicsContext3D>()).PassAs<OutputSurface>();
   6366   host_impl_->InitializeRenderer(output_surface.Pass());
   6367 
   6368   EXPECT_EQ(0u, context3d->NumTextures());
   6369 
   6370   UIResourceId ui_resource_id = 1;
   6371   scoped_refptr<UIResourceBitmap> bitmap = UIResourceBitmap::Create(
   6372       new uint8_t[1], UIResourceBitmap::RGBA8, gfx::Size(1, 1));
   6373   host_impl_->CreateUIResource(ui_resource_id, bitmap);
   6374   EXPECT_EQ(1u, context3d->NumTextures());
   6375   ResourceProvider::ResourceId id1 =
   6376       host_impl_->ResourceIdForUIResource(ui_resource_id);
   6377   EXPECT_NE(0u, id1);
   6378 
   6379   // Multiple requests with the same id is allowed.  The previous texture is
   6380   // deleted.
   6381   host_impl_->CreateUIResource(ui_resource_id, bitmap);
   6382   EXPECT_EQ(1u, context3d->NumTextures());
   6383   ResourceProvider::ResourceId id2 =
   6384       host_impl_->ResourceIdForUIResource(ui_resource_id);
   6385   EXPECT_NE(0u, id2);
   6386   EXPECT_NE(id1, id2);
   6387 
   6388   // Deleting invalid UIResourceId is allowed and does not change state.
   6389   host_impl_->DeleteUIResource(-1);
   6390   EXPECT_EQ(1u, context3d->NumTextures());
   6391 
   6392   // Should return zero for invalid UIResourceId.  Number of textures should
   6393   // not change.
   6394   EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
   6395   EXPECT_EQ(1u, context3d->NumTextures());
   6396 
   6397   host_impl_->DeleteUIResource(ui_resource_id);
   6398   EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
   6399   EXPECT_EQ(0u, context3d->NumTextures());
   6400 
   6401   // Should not change state for multiple deletion on one UIResourceId
   6402   host_impl_->DeleteUIResource(ui_resource_id);
   6403   EXPECT_EQ(0u, context3d->NumTextures());
   6404 }
   6405 
   6406 }  // namespace
   6407 }  // namespace cc
   6408