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