Fix revert "[chromeos] Remove dependencies of StatisticsProvider on chrome."
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blob0b541c498302a5cc7b8b6070b06cd2368572fab8
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.
5 #include "cc/trees/layer_tree_host_impl.h"
7 #include <cmath>
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"
52 using ::testing::Mock;
53 using ::testing::Return;
54 using ::testing::AnyNumber;
55 using ::testing::AtLeast;
56 using ::testing::_;
57 using media::VideoFrame;
59 namespace cc {
60 namespace {
62 class 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();
78 virtual void OverrideSettings(LayerTreeSettings* settings) {}
80 virtual void SetUp() OVERRIDE {
81 LayerTreeSettings settings;
82 settings.minimum_occlusion_tracking_size = gfx::Size();
83 OverrideSettings(&settings);
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));
93 virtual void TearDown() OVERRIDE {}
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;
103 virtual void OnHasPendingTreeStateChanged(bool has_pending_tree) OVERRIDE {
104 has_pending_tree_ = has_pending_tree;
106 virtual void SetNeedsRedrawOnImplThread() OVERRIDE {
107 did_request_redraw_ = true;
109 virtual void SetNeedsRedrawRectOnImplThread(gfx::Rect damage_rect) OVERRIDE {
110 did_request_redraw_ = true;
112 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE {
113 did_upload_visible_tile_ = true;
115 virtual void SetNeedsCommitOnImplThread() OVERRIDE {
116 did_request_commit_ = true;
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_;
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 {}
135 void set_reduce_memory_result(bool reduce_memory_result) {
136 reduce_memory_result_ = reduce_memory_result;
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;
145 host_impl_ = LayerTreeHostImpl::Create(settings,
146 this,
147 &proxy_,
148 &stats_instrumentation_);
150 host_impl_->InitializeRenderer(output_surface.Pass());
151 host_impl_->SetViewportSize(gfx::Size(10, 10));
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());
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]);
170 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
171 int id,
172 gfx::Vector2d scroll_delta) {
173 int times_encountered = 0;
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++;
182 ASSERT_EQ(times_encountered, 1);
185 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
186 int times_encountered = 0;
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++;
194 ASSERT_EQ(0, times_encountered);
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());
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();
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();
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);
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);
247 protected:
248 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
249 return CreateFakeOutputSurface();
252 void DrawOneFrame() {
253 LayerTreeHostImpl::FrameData frame_data;
254 host_impl_->PrepareToDraw(&frame_data, gfx::Rect());
255 host_impl_->DidDrawAllLayers(frame_data);
258 FakeProxy proxy_;
259 DebugScopedSetImplThread always_impl_thread_;
260 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
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_;
272 class TestWebGraphicsContext3DMakeCurrentFails
273 : public TestWebGraphicsContext3D {
274 public:
275 virtual bool makeContextCurrent() OVERRIDE { return false; }
278 TEST_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;
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;
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;
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;
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;
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;
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;
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;
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;
335 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
336 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
338 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
339 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
342 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
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());
356 LayerImpl* root = host_impl_->active_tree()->root_layer();
358 ExpectClearedScrollDeltasRecursive(root);
360 scoped_ptr<ScrollAndScaleSet> scroll_info;
362 scroll_info = host_impl_->ProcessScrollDeltas();
363 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
364 ExpectClearedScrollDeltasRecursive(root);
366 scroll_info = host_impl_->ProcessScrollDeltas();
367 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
368 ExpectClearedScrollDeltasRecursive(root);
371 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
372 gfx::Vector2d scroll_offset(20, 30);
373 gfx::Vector2d scroll_delta(11, -15);
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());
383 LayerImpl* root = host_impl_->active_tree()->root_layer();
385 scoped_ptr<ScrollAndScaleSet> scroll_info;
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);
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);
399 root->ScrollBy(gfx::Vector2d());
400 scroll_info = host_impl_->ProcessScrollDeltas();
401 EXPECT_EQ(root->sent_scroll_delta(), scroll_delta + scroll_delta2);
404 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
405 SetupScrollAndContentsLayers(gfx::Size(100, 100));
406 host_impl_->SetViewportSize(gfx::Size(50, 50));
407 InitializeRendererAndDrawFrame();
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_);
417 TEST_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));
423 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
424 LayerTreeSettings settings;
425 host_impl_ = LayerTreeHostImpl::Create(settings,
426 this,
427 &proxy_,
428 &stats_instrumentation_);
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));
437 SetupScrollAndContentsLayers(gfx::Size(100, 100));
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));
445 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
446 int scroll_layer_id = 1;
448 SetupScrollAndContentsLayers(gfx::Size(100, 100));
449 host_impl_->SetViewportSize(gfx::Size(50, 50));
450 InitializeRendererAndDrawFrame();
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();
457 SetupScrollAndContentsLayers(gfx::Size(100, 100));
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);
468 TEST_F(LayerTreeHostImplTest, ClearRootRenderSurfaceAndScroll) {
469 SetupScrollAndContentsLayers(gfx::Size(100, 100));
470 host_impl_->SetViewportSize(gfx::Size(50, 50));
471 InitializeRendererAndDrawFrame();
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();
478 EXPECT_EQ(InputHandler::ScrollStarted,
479 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
482 TEST_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();
488 root->SetHaveWheelEventHandlers(true);
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));
495 // But gesture scrolls can still be handled.
496 EXPECT_EQ(InputHandler::ScrollStarted,
497 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
500 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
501 SetupScrollAndContentsLayers(gfx::Size(100, 100));
502 host_impl_->SetViewportSize(gfx::Size(50, 50));
503 InitializeRendererAndDrawFrame();
505 // Ignore the fling since no layer is being scrolled
506 EXPECT_EQ(InputHandler::ScrollIgnored,
507 host_impl_->FlingScrollBegin());
509 // Start scrolling a layer
510 EXPECT_EQ(InputHandler::ScrollStarted,
511 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
513 // Now the fling should go ahead since we've started scrolling a layer
514 EXPECT_EQ(InputHandler::ScrollStarted,
515 host_impl_->FlingScrollBegin());
518 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
519 SetupScrollAndContentsLayers(gfx::Size(100, 100));
520 host_impl_->SetViewportSize(gfx::Size(50, 50));
521 InitializeRendererAndDrawFrame();
523 // Ignore the fling since no layer is being scrolled
524 EXPECT_EQ(InputHandler::ScrollIgnored,
525 host_impl_->FlingScrollBegin());
527 // Start scrolling a layer
528 EXPECT_EQ(InputHandler::ScrollStarted,
529 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel));
531 // Now the fling should go ahead since we've started scrolling a layer
532 EXPECT_EQ(InputHandler::ScrollStarted,
533 host_impl_->FlingScrollBegin());
536 TEST_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();
542 root->SetShouldScrollOnMainThread(true);
544 // Start scrolling a layer
545 EXPECT_EQ(InputHandler::ScrollOnMainThread,
546 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
548 // The fling should be ignored since there's no layer being scrolled impl-side
549 EXPECT_EQ(InputHandler::ScrollIgnored,
550 host_impl_->FlingScrollBegin());
553 TEST_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();
559 root->SetShouldScrollOnMainThread(true);
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));
567 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
568 SetupScrollAndContentsLayers(gfx::Size(200, 200));
569 host_impl_->SetViewportSize(gfx::Size(100, 100));
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));
575 InitializeRendererAndDrawFrame();
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));
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();
598 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
599 SetupScrollAndContentsLayers(gfx::Size(200, 200));
600 host_impl_->SetViewportSize(gfx::Size(100, 100));
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));
607 InitializeRendererAndDrawFrame();
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();
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));
623 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
624 SetupScrollAndContentsLayers(gfx::Size(200, 200));
625 host_impl_->SetViewportSize(gfx::Size(100, 100));
627 InitializeRendererAndDrawFrame();
629 EXPECT_EQ(InputHandler::ScrollStarted,
630 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
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)));
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)));
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)));
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)));
652 // Trying to scroll more than the available space will also succeed.
653 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
656 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
657 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
658 host_impl_->SetViewportSize(gfx::Size(100, 1000));
660 InitializeRendererAndDrawFrame();
662 EXPECT_EQ(InputHandler::ScrollStarted,
663 host_impl_->ScrollBegin(gfx::Point(),
664 InputHandler::Wheel));
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));
672 scoped_ptr<cc::ScrollbarLayerImpl> vertical_scrollbar(
673 cc::ScrollbarLayerImpl::Create(
674 host_impl_->active_tree(),
676 scoped_ptr<ScrollbarGeometryFixedThumb>()));
677 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
678 host_impl_->RootScrollLayer()->SetVerticalScrollbarLayer(
679 vertical_scrollbar.get());
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));
689 TEST_F(LayerTreeHostImplTest,
690 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion) {
691 SetupScrollAndContentsLayers(gfx::Size(100, 100));
692 host_impl_->SetViewportSize(gfx::Size(50, 50));
693 InitializeRendererAndDrawFrame();
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();
700 EXPECT_EQ(host_impl_->HaveTouchEventHandlersAt(gfx::Point()), false);
703 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
704 SetupScrollAndContentsLayers(gfx::Size(100, 100));
705 host_impl_->SetViewportSize(gfx::Size(50, 50));
706 InitializeRendererAndDrawFrame();
708 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
709 DCHECK(scroll_layer);
711 float min_page_scale = 1.f, max_page_scale = 4.f;
713 // The impl-based pinch zoom should adjust the max scroll position.
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());
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_);
728 scoped_ptr<ScrollAndScaleSet> scroll_info =
729 host_impl_->ProcessScrollDeltas();
730 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
732 EXPECT_EQ(gfx::Vector2d(75, 75),
733 host_impl_->active_tree()->root_layer()->max_scroll_offset());
736 // Scrolling after a pinch gesture should always be in local space. The
737 // scroll deltas do not have the page scale factor applied.
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());
745 float page_scale_delta = 2.f;
746 host_impl_->PinchGestureBegin();
747 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
748 host_impl_->PinchGestureEnd();
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();
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);
765 TEST_F(LayerTreeHostImplTest, PinchGesture) {
766 SetupScrollAndContentsLayers(gfx::Size(100, 100));
767 host_impl_->SetViewportSize(gfx::Size(50, 50));
768 InitializeRendererAndDrawFrame();
770 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
771 DCHECK(scroll_layer);
773 float min_page_scale = 1.f;
774 float max_page_scale = 4.f;
776 // Basic pinch zoom in gesture
778 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
779 min_page_scale,
780 max_page_scale);
781 scroll_layer->SetScrollDelta(gfx::Vector2d());
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_);
790 scoped_ptr<ScrollAndScaleSet> scroll_info =
791 host_impl_->ProcessScrollDeltas();
792 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
795 // Zoom-in clamping
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;
803 host_impl_->PinchGestureBegin();
804 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
805 host_impl_->PinchGestureEnd();
807 scoped_ptr<ScrollAndScaleSet> scroll_info =
808 host_impl_->ProcessScrollDeltas();
809 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
812 // Zoom-out clamping
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));
820 float page_scale_delta = 0.1f;
821 host_impl_->PinchGestureBegin();
822 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
823 host_impl_->PinchGestureEnd();
825 scoped_ptr<ScrollAndScaleSet> scroll_info =
826 host_impl_->ProcessScrollDeltas();
827 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
829 EXPECT_TRUE(scroll_info->scrolls.empty());
832 // Two-finger panning should not happen based on pinch events only
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));
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();
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());
852 // Two-finger panning should work with interleaved scroll events
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));
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();
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));
876 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
877 SetupScrollAndContentsLayers(gfx::Size(100, 100));
878 host_impl_->SetViewportSize(gfx::Size(50, 50));
879 InitializeRendererAndDrawFrame();
881 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
882 DCHECK(scroll_layer);
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;
892 // Non-anchor zoom-in
894 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
895 min_page_scale,
896 max_page_scale);
897 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
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_);
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));
915 // Anchor zoom-out
917 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
918 min_page_scale,
919 max_page_scale);
920 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
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_);
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));
938 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
939 SetupScrollAndContentsLayers(gfx::Size(100, 100));
940 host_impl_->SetViewportSize(gfx::Size(50, 50));
941 InitializeRendererAndDrawFrame();
943 LayerImpl* scroll_layer = host_impl_->RootScrollLayer();
944 DCHECK(scroll_layer);
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;
954 // Anchor zoom with unchanged page scale should not change scroll or scale.
956 host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f,
957 min_page_scale,
958 max_page_scale);
959 scroll_layer->SetScrollOffset(gfx::Vector2d(50, 50));
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_);
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());
978 TEST_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();
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);
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));
999 CompositorFrameMetadata metadata =
1000 host_impl_->MakeCompositorFrameMetadata();
1001 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1003 host_impl_->ScrollEnd();
1005 CompositorFrameMetadata metadata =
1006 host_impl_->MakeCompositorFrameMetadata();
1007 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
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();
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);
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);
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);
1041 class 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));
1047 virtual void DidDraw(ResourceProvider* provider) OVERRIDE {
1048 did_draw_called_ = true;
1051 virtual void WillDraw(ResourceProvider* provider) OVERRIDE {
1052 will_draw_called_ = true;
1055 bool did_draw_called() const { return did_draw_called_; }
1056 bool will_draw_called() const { return will_draw_called_; }
1058 void ClearDidDrawCheck() {
1059 did_draw_called_ = false;
1060 will_draw_called_ = false;
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);
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());
1082 private:
1083 bool did_draw_called_;
1084 bool will_draw_called_;
1087 TEST_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);
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));
1104 LayerTreeHostImpl::FrameData frame;
1106 EXPECT_FALSE(layer->will_draw_called());
1107 EXPECT_FALSE(layer->did_draw_called());
1109 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1110 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
1111 host_impl_->DidDrawAllLayers(frame);
1113 EXPECT_FALSE(layer->will_draw_called());
1114 EXPECT_FALSE(layer->did_draw_called());
1116 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
1118 // Ensure visible_content_rect for layer is not empty
1119 layer->SetPosition(gfx::PointF());
1121 EXPECT_FALSE(layer->will_draw_called());
1122 EXPECT_FALSE(layer->did_draw_called());
1124 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1125 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
1126 host_impl_->DidDrawAllLayers(frame);
1128 EXPECT_TRUE(layer->will_draw_called());
1129 EXPECT_TRUE(layer->did_draw_called());
1131 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
1134 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
1135 gfx::Size big_size(1000, 1000);
1136 host_impl_->SetViewportSize(big_size);
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());
1143 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1144 DidDrawCheckLayer* occluded_layer =
1145 static_cast<DidDrawCheckLayer*>(root->children()[0]);
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);
1156 LayerTreeHostImpl::FrameData frame;
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());
1163 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1164 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
1165 host_impl_->DidDrawAllLayers(frame);
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());
1173 TEST_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());
1179 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
1180 DidDrawCheckLayer* layer1 =
1181 static_cast<DidDrawCheckLayer*>(root->children()[0]);
1183 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
1184 DidDrawCheckLayer* layer2 =
1185 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
1187 layer1->SetOpacity(0.3f);
1188 layer1->SetPreserves3d(false);
1190 EXPECT_FALSE(root->did_draw_called());
1191 EXPECT_FALSE(layer1->did_draw_called());
1192 EXPECT_FALSE(layer2->did_draw_called());
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);
1199 EXPECT_TRUE(root->did_draw_called());
1200 EXPECT_TRUE(layer1->did_draw_called());
1201 EXPECT_TRUE(layer2->did_draw_called());
1203 EXPECT_NE(root->render_surface(), layer1->render_surface());
1204 EXPECT_TRUE(!!layer1->render_surface());
1207 class 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,
1218 tile_missing,
1219 skips_draw,
1220 animating,
1221 resource_provider));
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(),
1241 GL_RGBA,
1242 ResourceProvider::TextureUsageAny);
1243 resource_provider->AllocateForTesting(resource);
1244 PushTileProperties(0, 0, resource, gfx::Rect(), false);
1246 if (animating)
1247 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1251 TEST_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(),
1260 false,
1261 false,
1262 true,
1263 host_impl_->resource_provider()));
1265 LayerTreeHostImpl::FrameData frame;
1267 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1268 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
1269 host_impl_->DidDrawAllLayers(frame);
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(),
1280 true,
1281 false,
1282 false,
1283 host_impl_->resource_provider()));
1285 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1286 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
1287 host_impl_->DidDrawAllLayers(frame);
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(),
1298 true,
1299 false,
1300 true,
1301 host_impl_->resource_provider()));
1303 EXPECT_FALSE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1304 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
1305 host_impl_->DidDrawAllLayers(frame);
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(),
1315 false,
1316 true,
1317 true,
1318 host_impl_->resource_provider()));
1320 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
1321 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
1322 host_impl_->DidDrawAllLayers(frame);
1325 TEST_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();
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_);
1338 TEST_F(LayerTreeHostImplTest, ScrollNonScrollableRootWithTopControls) {
1339 LayerTreeSettings settings;
1340 settings.calculate_top_controls_position = true;
1341 settings.top_controls_height = 50;
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));
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();
1364 EXPECT_EQ(InputHandler::ScrollIgnored,
1365 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
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);
1372 EXPECT_EQ(InputHandler::ScrollStarted,
1373 host_impl_->ScrollBegin(gfx::Point(),
1374 InputHandler::Gesture));
1377 TEST_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);
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);
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());
1403 host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
1404 host_impl_->SetViewportSize(surface_size);
1405 InitializeRendererAndDrawFrame();
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_);
1416 TEST_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();
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_);
1435 TEST_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();
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_);
1452 TEST_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);
1458 gfx::Transform matrix;
1459 matrix.RotateAboutXAxis(180.0);
1460 child->SetTransform(matrix);
1461 child->SetDoubleSided(false);
1463 root->AddChild(child.Pass());
1464 host_impl_->active_tree()->SetRootLayer(root.Pass());
1465 InitializeRendererAndDrawFrame();
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_);
1476 TEST_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);
1482 scoped_ptr<LayerImpl> scroll_layer = CreateScrollableLayer(2, surface_size);
1483 scroll_layer->AddChild(content_layer.Pass());
1485 host_impl_->active_tree()->SetRootLayer(scroll_layer.Pass());
1486 host_impl_->SetViewportSize(surface_size);
1487 InitializeRendererAndDrawFrame();
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));
1496 TEST_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();
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();
1515 // Set new page scale from main thread.
1516 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
1517 page_scale,
1518 page_scale);
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);
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());
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());
1534 TEST_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();
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();
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();
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);
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());
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());
1574 TEST_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);
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);
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];
1589 scoped_ptr<LayerImpl> scrollable_child =
1590 CreateScrollableLayer(3, surface_size);
1591 child->AddChild(scrollable_child.Pass());
1592 LayerImpl* grand_child = child->children()[0];
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();
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());
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);
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));
1624 TEST_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();
1638 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
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();
1649 float page_scale = 2.f;
1650 host_impl_->active_tree()->SetPageScaleFactorAndLimits(page_scale,
1651 1.f,
1652 page_scale);
1654 DrawOneFrame();
1656 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1657 ExpectContains(*scroll_info.get(), scroll_layer_id, expected_scroll_delta);
1659 // The scroll range should not have changed.
1660 EXPECT_EQ(child->max_scroll_offset(), expected_max_scroll);
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());
1667 TEST_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);
1674 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(3, surface_size);
1675 grand_child->SetScrollOffset(gfx::Vector2d(0, 5));
1677 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
1678 child->SetScrollOffset(gfx::Vector2d(3, 0));
1679 child->AddChild(grand_child.Pass());
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();
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();
1694 scoped_ptr<ScrollAndScaleSet> scroll_info =
1695 host_impl_->ProcessScrollDeltas();
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));
1702 // The child should have only scrolled on the other axis.
1703 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
1707 TEST_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);
1713 scoped_ptr<LayerImpl> grand_child = CreateScrollableLayer(3, surface_size);
1714 grand_child->SetScrollOffset(gfx::Vector2d(0, 2));
1716 scoped_ptr<LayerImpl> child = CreateScrollableLayer(2, surface_size);
1717 child->SetScrollOffset(gfx::Vector2d(0, 3));
1718 child->AddChild(grand_child.Pass());
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();
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();
1733 scoped_ptr<ScrollAndScaleSet> scroll_info =
1734 host_impl_->ProcessScrollDeltas();
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));
1741 // The child should not have scrolled.
1742 ExpectNone(*scroll_info.get(), child->id());
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();
1754 scroll_info = host_impl_->ProcessScrollDeltas();
1756 // The child should have scrolled up to its limit.
1757 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
1759 // The grand child should not have scrolled.
1760 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
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();
1773 scroll_info = host_impl_->ProcessScrollDeltas();
1775 // The grand child should have scrolled.
1776 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
1778 // The child should not have scrolled.
1779 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
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);
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();
1794 scroll_info = host_impl_->ProcessScrollDeltas();
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));
1801 TEST_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);
1809 child->SetScrollable(false);
1810 root->AddChild(child.Pass());
1812 host_impl_->SetViewportSize(surface_size);
1813 host_impl_->active_tree()->SetRootLayer(root.Pass());
1814 host_impl_->active_tree()->DidBecomeActive();
1815 InitializeRendererAndDrawFrame();
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();
1824 scoped_ptr<ScrollAndScaleSet> scroll_info =
1825 host_impl_->ProcessScrollDeltas();
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);
1835 TEST_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);
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();
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));
1856 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
1857 SetupScrollAndContentsLayers(gfx::Size(100, 100));
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);
1864 gfx::Size surface_size(50, 50);
1865 host_impl_->SetViewportSize(surface_size);
1866 InitializeRendererAndDrawFrame();
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();
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()));
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();
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);
1898 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
1899 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1900 int child_layer_id = 3;
1901 float child_layer_angle = -20.f;
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);
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());
1917 gfx::Size surface_size(50, 50);
1918 host_impl_->SetViewportSize(surface_size);
1919 InitializeRendererAndDrawFrame();
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();
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(
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);
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);
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();
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(
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);
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),
1970 ExpectContains(*scroll_info.get(),
1971 host_impl_->active_tree()->root_layer()->id(),
1972 expected_root_scroll_delta);
1976 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
1977 SetupScrollAndContentsLayers(gfx::Size(100, 100));
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);
1985 gfx::Size surface_size(50, 50);
1986 host_impl_->SetViewportSize(surface_size);
1987 InitializeRendererAndDrawFrame();
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();
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));
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();
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);
2018 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
2019 public:
2020 TestScrollOffsetDelegate() {}
2021 virtual ~TestScrollOffsetDelegate() {}
2023 virtual void SetTotalScrollOffset(gfx::Vector2dF new_value) OVERRIDE {
2024 last_set_scroll_offset_ = new_value;
2027 virtual gfx::Vector2dF GetTotalScrollOffset() OVERRIDE {
2028 return getter_return_value_;
2031 gfx::Vector2dF last_set_scroll_offset() {
2032 return last_set_scroll_offset_;
2035 void set_getter_return_value(gfx::Vector2dF value) {
2036 getter_return_value_ = value;
2039 private:
2040 gfx::Vector2dF last_set_scroll_offset_;
2041 gfx::Vector2dF getter_return_value_;
2044 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
2045 TestScrollOffsetDelegate scroll_delegate;
2046 SetupScrollAndContentsLayers(gfx::Size(100, 100));
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());
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);
2059 scroll_delegate.set_getter_return_value(current_offset);
2060 EXPECT_EQ(InputHandler::ScrollStarted,
2061 host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture));
2063 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2064 EXPECT_EQ(current_offset + scroll_delta,
2065 scroll_delegate.last_set_scroll_offset());
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();
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);
2080 EXPECT_EQ(current_offset,
2081 host_impl_->active_tree()->root_layer()->TotalScrollOffset());
2084 class BlendStateTrackerContext: public TestWebGraphicsContext3D {
2085 public:
2086 BlendStateTrackerContext() : blend_(false) {}
2088 virtual void enable(WebKit::WGC3Denum cap) OVERRIDE {
2089 if (cap == GL_BLEND)
2090 blend_ = true;
2093 virtual void disable(WebKit::WGC3Denum cap) OVERRIDE {
2094 if (cap == GL_BLEND)
2095 blend_ = false;
2098 bool blend() const { return blend_; }
2100 private:
2101 bool blend_;
2104 class 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,
2111 resource_provider));
2114 virtual void AppendQuads(QuadSink* quad_sink,
2115 AppendQuadsData* append_quads_data) OVERRIDE {
2116 quads_appended_ = true;
2118 gfx::Rect opaque_rect;
2119 if (contents_opaque())
2120 opaque_rect = quad_rect_;
2121 else
2122 opaque_rect = opaque_content_rect_;
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);
2141 void SetExpectation(bool blend, bool has_render_surface) {
2142 blend_ = blend;
2143 has_render_surface_ = has_render_surface;
2144 quads_appended_ = false;
2147 bool quads_appended() const { return quads_appended_; }
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; }
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);
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_;
2183 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
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());
2193 LayerImpl* root = host_impl_->active_tree()->root_layer();
2195 root->AddChild(
2196 BlendStateCheckLayer::Create(host_impl_->active_tree(),
2198 host_impl_->resource_provider()));
2199 BlendStateCheckLayer* layer1 =
2200 static_cast<BlendStateCheckLayer*>(root->children()[0]);
2201 layer1->SetPosition(gfx::PointF(2.f, 2.f));
2203 LayerTreeHostImpl::FrameData frame;
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);
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);
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);
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);
2243 layer1->AddChild(
2244 BlendStateCheckLayer::Create(host_impl_->active_tree(),
2246 host_impl_->resource_provider()));
2247 BlendStateCheckLayer* layer2 =
2248 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
2249 layer2->SetPosition(gfx::PointF(4.f, 4.f));
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
2407 TEST_F(LayerTreeHostImplTest, ViewportCovered) {
2408 host_impl_->InitializeRenderer(CreateOutputSurface());
2409 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
2411 gfx::Size viewport_size(1000, 1000);
2412 host_impl_->SetViewportSize(viewport_size);
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(),
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);
2425 // No gutter rects
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()));
2434 LayerTreeHostImpl::FrameData frame;
2435 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2436 ASSERT_EQ(1u, frame.render_passes.size());
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());
2445 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2446 frame.render_passes[0]->quad_list, gfx::Rect(viewport_size));
2447 host_impl_->DidDrawAllLayers(frame);
2450 // Empty visible content area (fullscreen gutter rect)
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()));
2459 LayerTreeHostImpl::FrameData frame;
2460 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2461 ASSERT_EQ(1u, frame.render_passes.size());
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());
2470 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2471 frame.render_passes[0]->quad_list, gfx::Rect(viewport_size));
2472 host_impl_->DidDrawAllLayers(frame);
2475 // Content area in middle of clip rect (four surrounding gutter rects)
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()));
2484 LayerTreeHostImpl::FrameData frame;
2485 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
2486 ASSERT_EQ(1u, frame.render_passes.size());
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());
2495 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2496 frame.render_passes[0]->quad_list, gfx::Rect(viewport_size));
2497 host_impl_->DidDrawAllLayers(frame);
2502 class ReshapeTrackerContext: public TestWebGraphicsContext3D {
2503 public:
2504 ReshapeTrackerContext() : reshape_called_(false) {}
2506 virtual void reshape(int width, int height) OVERRIDE {
2507 reshape_called_ = true;
2510 bool reshape_called() const { return reshape_called_; }
2512 private:
2513 bool reshape_called_;
2516 class 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));
2521 protected:
2522 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
2523 : LayerImpl(tree_impl, id) {}
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.
2529 TEST_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());
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());
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);
2553 class 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);
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");
2566 return WebKit::WebString();
2569 gfx::Rect partial_swap_rect() const { return partial_swap_rect_; }
2571 private:
2572 gfx::Rect partial_swap_rect_;
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.
2577 TEST_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());
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));
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());
2612 LayerTreeHostImpl::FrameData frame;
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());
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());
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());
2661 TEST_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());
2677 host_impl_->active_tree()->SetRootLayer(root.Pass());
2679 LayerTreeHostImpl::FrameData frame;
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);
2687 class 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));
2693 virtual void AppendQuads(QuadSink* quad_sink,
2694 AppendQuadsData* append_quads_data) OVERRIDE {
2695 SharedQuadState* shared_quad_state =
2696 quad_sink->UseSharedQuadState(CreateSharedQuadState());
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);
2705 private:
2706 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
2707 : LayerImpl(tree_impl, id) {}
2710 class 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));
2736 class MockContextHarness {
2737 private:
2738 MockContext* context_;
2740 public:
2741 explicit MockContextHarness(MockContext* context)
2742 : context_(context) {
2743 // Catch "uninteresting" calls
2744 EXPECT_CALL(*context_, useProgram(_))
2745 .Times(0);
2747 EXPECT_CALL(*context_, drawElements(_, _, _, _))
2748 .Times(0);
2750 // These are not asserted
2751 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
2752 .WillRepeatedly(Return());
2754 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
2755 .WillRepeatedly(Return());
2757 // Any other strings are empty
2758 EXPECT_CALL(*context_, getString(_))
2759 .WillRepeatedly(Return(WebKit::WebString()));
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")));
2766 EXPECT_CALL(*context_, getRequestableExtensionsCHROMIUM())
2767 .WillRepeatedly(Return(
2768 WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
2770 // Any un-sanctioned calls to enable() are OK
2771 EXPECT_CALL(*context_, enable(_))
2772 .WillRepeatedly(Return());
2774 // Any un-sanctioned calls to disable() are OK
2775 EXPECT_CALL(*context_, disable(_))
2776 .WillRepeatedly(Return());
2779 void MustDrawSolidQuad() {
2780 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
2781 .WillOnce(Return())
2782 .RetiresOnSaturation();
2784 EXPECT_CALL(*context_, useProgram(_))
2785 .WillOnce(Return())
2786 .RetiresOnSaturation();
2789 void MustSetScissor(int x, int y, int width, int height) {
2790 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
2791 .WillRepeatedly(Return());
2793 EXPECT_CALL(*context_, scissor(x, y, width, height))
2794 .Times(AtLeast(1))
2795 .WillRepeatedly(Return());
2798 void MustSetNoScissor() {
2799 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
2800 .WillRepeatedly(Return());
2802 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
2803 .Times(0);
2805 EXPECT_CALL(*context_, scissor(_, _, _, _))
2806 .Times(0);
2810 TEST_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);
2818 // Run test case
2819 CreateLayerTreeHost(false, output_surface.Pass());
2820 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
2822 // Without partial swap, and no clipping, no scissor is set.
2823 harness.MustDrawSolidQuad();
2824 harness.MustSetNoScissor();
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);
2831 Mock::VerifyAndClearExpectations(&mock_context);
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);
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);
2844 Mock::VerifyAndClearExpectations(&mock_context);
2847 TEST_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);
2855 CreateLayerTreeHost(true, output_surface.Pass());
2856 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
2858 // The first frame is not a partially-swapped one.
2859 harness.MustSetScissor(0, 0, 10, 10);
2860 harness.MustDrawSolidQuad();
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);
2867 Mock::VerifyAndClearExpectations(&mock_context);
2869 // Damage a portion of the frame.
2870 host_impl_->active_tree()->root_layer()->set_update_rect(
2871 gfx::Rect(0, 0, 2, 3));
2873 // The second frame will be partially-swapped (the y coordinates are flipped).
2874 harness.MustSetScissor(0, 7, 2, 3);
2875 harness.MustDrawSolidQuad();
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);
2882 Mock::VerifyAndClearExpectations(&mock_context);
2885 class 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();
2893 virtual WebKit::WebString getRequestableExtensionsCHROMIUM() OVERRIDE {
2894 return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
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;
2905 static 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>();
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));
2922 Layers are created as follows:
2924 +--------------------+
2925 | 1 |
2926 | +-----------+ |
2927 | | 2 | |
2928 | | +-------------------+
2929 | | | 3 |
2930 | | +-------------------+
2931 | | | |
2932 | +-----------+ |
2935 +--------------------+
2937 Layers 1, 2 have render surfaces
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);
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);
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()));
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);
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);
2975 child->AddChild(grand_child.Pass());
2976 root->AddChild(child.Pass());
2978 my_host_impl->active_tree()->SetRootLayer(root.Pass());
2979 return my_host_impl.Pass();
2982 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
2983 scoped_ptr<LayerTreeHostImpl> my_host_impl =
2984 SetupLayersForOpacity(true, this, &proxy_, &stats_instrumentation_);
2986 LayerTreeHostImpl::FrameData frame;
2987 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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);
2998 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
2999 my_host_impl->DidDrawAllLayers(frame);
3003 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
3004 scoped_ptr<LayerTreeHostImpl> my_host_impl =
3005 SetupLayersForOpacity(false, this, &proxy_, &stats_instrumentation_);
3007 LayerTreeHostImpl::FrameData frame;
3008 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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);
3019 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3020 my_host_impl->DidDrawAllLayers(frame);
3024 // Fake WebKit::WebGraphicsContext3D that tracks the number of textures in use.
3025 class TrackingWebGraphicsContext3D : public TestWebGraphicsContext3D {
3026 public:
3027 TrackingWebGraphicsContext3D()
3028 : TestWebGraphicsContext3D(),
3029 num_textures_(0) {}
3031 virtual WebKit::WebGLId createTexture() OVERRIDE {
3032 WebKit::WebGLId id = TestWebGraphicsContext3D::createTexture();
3034 textures_[id] = true;
3035 ++num_textures_;
3036 return id;
3039 virtual void deleteTexture(WebKit::WebGLId id) OVERRIDE {
3040 if (textures_.find(id) == textures_.end())
3041 return;
3043 textures_[id] = false;
3044 --num_textures_;
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");
3053 return WebKit::WebString();
3056 unsigned num_textures() const { return num_textures_; }
3058 private:
3059 base::hash_map<WebKit::WebGLId, bool> textures_;
3060 unsigned num_textures_;
3063 TEST_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());
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());
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>());
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>());
3098 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
3100 EXPECT_EQ(0u, context3d->NumTextures());
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);
3108 EXPECT_GT(context3d->NumTextures(), 0u);
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());
3117 class 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));
3126 TEST_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());
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);
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);
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);
3160 static 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;
3178 static 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>();
3189 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
3190 layer_tree_host_impl->SetViewportSize(root_size);
3192 scoped_ptr<LayerImpl> root =
3193 LayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
3194 root_ptr = root.get();
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());
3203 AddDrawingLayerTo(root_ptr,
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);
3210 // Surface layer is the layer that changes its opacity
3211 // It will contain other layers that draw content.
3212 AddDrawingLayerTo(intermediate_layer_ptr,
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);
3221 // Child of the surface layer will produce some quads
3222 AddDrawingLayerTo(surface_layer_ptr,
3224 gfx::Rect(5,
3226 root_size.width() - 25,
3227 root_size.height() - 25),
3228 &child_ptr);
3231 class GLRendererWithReleaseTextures : public GLRenderer {
3232 public:
3233 using GLRenderer::ReleaseRenderPassTextures;
3236 TEST_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_);
3246 // Layers are structure as follows:
3248 // R +-- S1 +- L10 (owning)
3249 // | +- L11
3250 // | +- L12
3251 // |
3252 // +-- S2 +- L20 (owning)
3253 // +- L21
3255 // Occlusion:
3256 // L12 occludes L11 (internal)
3257 // L20 occludes L10 (external)
3258 // L21 occludes L20 (internal)
3260 LayerImpl* root_ptr;
3261 LayerImpl* layer_s1_ptr;
3262 LayerImpl* layer_s2_ptr;
3264 scoped_ptr<OutputSurface> output_surface =
3265 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
3266 new PartialSwapContext)).PassAs<OutputSurface>();
3268 gfx::Size root_size(1000, 1000);
3270 my_host_impl->InitializeRenderer(output_surface.Pass());
3271 my_host_impl->SetViewportSize(root_size);
3273 scoped_ptr<LayerImpl> root =
3274 LayerImpl::Create(my_host_impl->active_tree(), 1);
3275 root_ptr = root.get();
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());
3285 AddDrawingLayerTo(root_ptr, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr);
3286 layer_s1_ptr->SetForceRenderSurface(true);
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
3291 AddDrawingLayerTo(root_ptr, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr);
3292 layer_s2_ptr->SetForceRenderSurface(true);
3294 AddDrawingLayerTo(layer_s2_ptr, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
3296 // Initial draw - must receive all quads
3298 LayerTreeHostImpl::FrameData frame;
3299 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
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());
3310 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3311 my_host_impl->DidDrawAllLayers(frame);
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);
3321 LayerTreeHostImpl::FrameData frame;
3322 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
3331 EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
3332 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
3334 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3335 my_host_impl->DidDrawAllLayers(frame);
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);
3345 LayerTreeHostImpl::FrameData frame;
3346 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3348 // Must receive 1 render pass - for the root.
3349 ASSERT_EQ(1U, frame.render_passes.size());
3351 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
3353 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3354 my_host_impl->DidDrawAllLayers(frame);
3358 TEST_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_);
3368 // Layers are structure as follows:
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)
3379 LayerImpl* root_ptr;
3380 LayerImpl* layer_s1_ptr;
3381 LayerImpl* layer_s2_ptr;
3383 scoped_ptr<OutputSurface> output_surface =
3384 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
3385 new PartialSwapContext)).PassAs<OutputSurface>();
3387 gfx::Size root_size(1000, 1000);
3389 my_host_impl->InitializeRenderer(output_surface.Pass());
3390 my_host_impl->SetViewportSize(root_size);
3392 scoped_ptr<LayerImpl> root =
3393 LayerImpl::Create(my_host_impl->active_tree(), 1);
3394 root_ptr = root.get();
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());
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);
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
3414 AddDrawingLayerTo(root_ptr, 7, gfx::Rect(450, 450, 450, 450), &layer_s2_ptr);
3415 layer_s2_ptr->SetForceRenderSurface(true);
3417 // Initial draw - must receive all quads
3419 LayerTreeHostImpl::FrameData frame;
3420 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
3427 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
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());
3433 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3434 my_host_impl->DidDrawAllLayers(frame);
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);
3444 LayerTreeHostImpl::FrameData frame;
3445 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
3454 EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
3455 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
3457 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3458 my_host_impl->DidDrawAllLayers(frame);
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);
3468 LayerTreeHostImpl::FrameData frame;
3469 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3471 // Must receive 1 render pass - for the root.
3472 ASSERT_EQ(1U, frame.render_passes.size());
3474 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
3476 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3477 my_host_impl->DidDrawAllLayers(frame);
3481 TEST_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_);
3491 // Layers are structured as follows:
3493 // R +-- S1 +- L10 (owning, drawing)
3494 // | +- L11 (corner, occluded by L12)
3495 // | +- L12 (opposite corner)
3496 // |
3497 // +-- S2 +- L20 (owning, drawing)
3500 LayerImpl* root_ptr;
3501 LayerImpl* layer_s1_ptr;
3502 LayerImpl* layer_s2_ptr;
3504 scoped_ptr<OutputSurface> output_surface =
3505 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
3506 new PartialSwapContext)).PassAs<OutputSurface>();
3508 gfx::Size root_size(1000, 1000);
3510 my_host_impl->InitializeRenderer(output_surface.Pass());
3511 my_host_impl->SetViewportSize(root_size);
3513 scoped_ptr<LayerImpl> root =
3514 LayerImpl::Create(my_host_impl->active_tree(), 1);
3515 root_ptr = root.get();
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());
3525 AddDrawingLayerTo(root_ptr, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr);
3526 layer_s1_ptr->SetForceRenderSurface(true);
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
3531 AddDrawingLayerTo(root_ptr, 7, gfx::Rect(200, 0, 300, 300), &layer_s2_ptr);
3532 layer_s2_ptr->SetForceRenderSurface(true);
3534 // Initial draw - must receive all quads
3536 LayerTreeHostImpl::FrameData frame;
3537 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
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());
3548 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3549 my_host_impl->DidDrawAllLayers(frame);
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);
3559 LayerTreeHostImpl::FrameData frame;
3560 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
3569 EXPECT_GT(frame.render_passes[0]->quad_list.size(), 0U);
3570 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
3572 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3573 my_host_impl->DidDrawAllLayers(frame);
3577 TEST_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_);
3586 // Layers are structured as follows:
3588 // R +-- S1 +- L10 (rotated, drawing)
3589 // +- L11 (occupies half surface)
3591 LayerImpl* root_ptr;
3592 LayerImpl* layer_s1_ptr;
3594 scoped_ptr<OutputSurface> output_surface =
3595 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
3596 new PartialSwapContext)).PassAs<OutputSurface>();
3598 gfx::Size root_size(1000, 1000);
3600 my_host_impl->InitializeRenderer(output_surface.Pass());
3601 my_host_impl->SetViewportSize(root_size);
3603 scoped_ptr<LayerImpl> root =
3604 LayerImpl::Create(my_host_impl->active_tree(), 1);
3605 root_ptr = root.get();
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());
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);
3623 AddDrawingLayerTo(layer_s1_ptr, 3, gfx::Rect(200, 0, 200, 400), 0); // L11
3625 // Initial draw - must receive all quads
3627 LayerTreeHostImpl::FrameData frame;
3628 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3630 // Must receive 2 render passes.
3631 ASSERT_EQ(2U, frame.render_passes.size());
3633 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
3634 EXPECT_EQ(1U, frame.render_passes[1]->quad_list.size());
3636 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3637 my_host_impl->DidDrawAllLayers(frame);
3640 // Change opacity and draw. Verify we used cached texture.
3641 layer_s1_ptr->SetOpacity(0.2f);
3643 LayerTreeHostImpl::FrameData frame;
3644 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3646 // One render pass must be gone due to cached texture.
3647 ASSERT_EQ(1U, frame.render_passes.size());
3649 EXPECT_EQ(1U, frame.render_passes[0]->quad_list.size());
3651 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3652 my_host_impl->DidDrawAllLayers(frame);
3656 TEST_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_);
3667 // Layers are structure as follows:
3669 // R +-- S1 +- L10 (owning)
3670 // | +- L11
3671 // | +- L12
3672 // |
3673 // +-- S2 +- L20 (owning)
3674 // +- L21
3676 // Occlusion:
3677 // L12 occludes L11 (internal)
3678 // L20 occludes L10 (external)
3679 // L21 occludes L20 (internal)
3681 LayerImpl* root_ptr;
3682 LayerImpl* layer_s1_ptr;
3683 LayerImpl* layer_s2_ptr;
3685 scoped_ptr<OutputSurface> output_surface =
3686 FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(
3687 new PartialSwapContext)).PassAs<OutputSurface>();
3689 gfx::Size root_size(1000, 1000);
3691 my_host_impl->InitializeRenderer(output_surface.Pass());
3692 my_host_impl->SetViewportSize(root_size);
3694 scoped_ptr<LayerImpl> root =
3695 LayerImpl::Create(my_host_impl->active_tree(), 1);
3696 root_ptr = root.get();
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());
3706 AddDrawingLayerTo(root_ptr, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr);
3707 layer_s1_ptr->SetForceRenderSurface(true);
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
3712 AddDrawingLayerTo(root_ptr, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr);
3713 layer_s2_ptr->SetForceRenderSurface(true);
3715 AddDrawingLayerTo(layer_s2_ptr, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
3717 // Initial draw - must receive all quads
3719 LayerTreeHostImpl::FrameData frame;
3720 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
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());
3731 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3732 my_host_impl->DidDrawAllLayers(frame);
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);
3742 LayerTreeHostImpl::FrameData frame;
3743 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
3751 EXPECT_EQ(2U, frame.render_passes[0]->quad_list.size());
3752 EXPECT_EQ(2U, frame.render_passes[1]->quad_list.size());
3754 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3755 my_host_impl->DidDrawAllLayers(frame);
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);
3765 LayerTreeHostImpl::FrameData frame;
3766 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3768 // Root render pass only.
3769 ASSERT_EQ(1U, frame.render_passes.size());
3771 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3772 my_host_impl->DidDrawAllLayers(frame);
3776 TEST_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_);
3787 Layers are created as follows:
3789 +--------------------+
3790 | 1 |
3791 | +-----------+ |
3792 | | 2 | |
3793 | | +-------------------+
3794 | | | 3 |
3795 | | +-------------------+
3796 | | | |
3797 | +-----------+ |
3800 +--------------------+
3802 Layers 1, 2 have render surfaces
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);
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);
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());
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);
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);
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());
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);
3848 TiledLayerImpl* child_ptr = child.get();
3849 RenderPass::Id child_pass_id(child_ptr->id(), 0);
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());
3856 EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
3857 child_pass_id));
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);
3866 // We should have cached textures for surface 2.
3867 EXPECT_TRUE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
3868 child_pass_id));
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);
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));
3882 // Damage a single tile of surface 2.
3883 child_ptr->set_update_rect(gfx::Rect(10, 10, 10, 10));
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);
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));
3898 TEST_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_);
3909 LayerImpl* root_ptr;
3910 LayerImpl* intermediate_layer_ptr;
3911 LayerImpl* surface_layer_ptr;
3912 LayerImpl* child_ptr;
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));
3921 LayerTreeHostImpl::FrameData frame;
3922 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
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());
3937 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3938 my_host_impl->DidDrawAllLayers(frame);
3941 // Draw without any change
3943 LayerTreeHostImpl::FrameData frame;
3944 my_host_impl->SetFullRootLayerDamage();
3945 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3947 // Must receive one render pass, as the other one should be culled
3948 ASSERT_EQ(1U, frame.render_passes.size());
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());
3958 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3959 my_host_impl->DidDrawAllLayers(frame);
3962 // Change opacity and draw
3963 surface_layer_ptr->SetOpacity(0.6f);
3965 LayerTreeHostImpl::FrameData frame;
3966 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3968 // Must receive one render pass, as the other one should be culled
3969 ASSERT_EQ(1U, frame.render_passes.size());
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());
3979 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
3980 my_host_impl->DidDrawAllLayers(frame);
3983 // Change less benign property and draw - should have contents changed flag
3984 surface_layer_ptr->SetStackingOrderChanged(true);
3986 LayerTreeHostImpl::FrameData frame;
3987 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
3989 // Must receive two render passes, each with one quad
3990 ASSERT_EQ(2U, frame.render_passes.size());
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);
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());
4004 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4005 my_host_impl->DidDrawAllLayers(frame);
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();
4013 // Change opacity and draw
4014 surface_layer_ptr->SetOpacity(0.6f);
4016 LayerTreeHostImpl::FrameData frame;
4017 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4019 // Must receive two render passes
4020 ASSERT_EQ(2U, frame.render_passes.size());
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());
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());
4035 // Was our surface evicted?
4036 EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
4037 target_pass->id));
4039 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4040 my_host_impl->DidDrawAllLayers(frame);
4043 // Draw without any change, to make sure the state is clear
4045 LayerTreeHostImpl::FrameData frame;
4046 my_host_impl->SetFullRootLayerDamage();
4047 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4049 // Must receive one render pass, as the other one should be culled
4050 ASSERT_EQ(1U, frame.render_passes.size());
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());
4060 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4061 my_host_impl->DidDrawAllLayers(frame);
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);
4069 LayerTreeHostImpl::FrameData frame;
4070 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
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());
4083 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4084 my_host_impl->DidDrawAllLayers(frame);
4088 TEST_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_);
4098 LayerImpl* root_ptr;
4099 LayerImpl* intermediate_layer_ptr;
4100 LayerImpl* surface_layer_ptr;
4101 LayerImpl* child_ptr;
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));
4110 LayerTreeHostImpl::FrameData frame;
4111 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
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());
4125 EXPECT_FALSE(frame.render_passes[0]->damage_rect.IsEmpty());
4126 EXPECT_FALSE(frame.render_passes[1]->damage_rect.IsEmpty());
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);
4133 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4134 my_host_impl->DidDrawAllLayers(frame);
4137 // Draw without any change
4139 LayerTreeHostImpl::FrameData frame;
4140 my_host_impl->SetFullRootLayerDamage();
4141 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
4149 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4150 my_host_impl->DidDrawAllLayers(frame);
4153 // Change opacity and draw
4154 surface_layer_ptr->SetOpacity(0.6f);
4156 LayerTreeHostImpl::FrameData frame;
4157 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4159 // Must receive one render pass, as the other one should be culled
4160 ASSERT_EQ(1U, frame.render_passes.size());
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());
4170 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4171 my_host_impl->DidDrawAllLayers(frame);
4174 // Change less benign property and draw - should have contents changed flag
4175 surface_layer_ptr->SetStackingOrderChanged(true);
4177 LayerTreeHostImpl::FrameData frame;
4178 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4180 // Must receive two render passes, each with one quad
4181 ASSERT_EQ(2U, frame.render_passes.size());
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);
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());
4195 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4196 my_host_impl->DidDrawAllLayers(frame);
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();
4204 // Change opacity and draw
4205 surface_layer_ptr->SetOpacity(0.6f);
4207 LayerTreeHostImpl::FrameData frame;
4208 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
4210 // Must receive two render passes
4211 ASSERT_EQ(2U, frame.render_passes.size());
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());
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());
4226 // Was our surface evicted?
4227 EXPECT_FALSE(my_host_impl->renderer()->HaveCachedResourcesForRenderPassId(
4228 target_pass->id));
4230 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4231 my_host_impl->DidDrawAllLayers(frame);
4234 // Draw without any change, to make sure the state is clear
4236 LayerTreeHostImpl::FrameData frame;
4237 my_host_impl->SetFullRootLayerDamage();
4238 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
4246 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4247 my_host_impl->DidDrawAllLayers(frame);
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);
4255 LayerTreeHostImpl::FrameData frame;
4256 EXPECT_TRUE(my_host_impl->PrepareToDraw(&frame, gfx::Rect()));
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());
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());
4269 my_host_impl->DrawLayers(&frame, base::TimeTicks::Now());
4270 my_host_impl->DidDrawAllLayers(frame);
4274 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
4275 set_reduce_memory_result(false);
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;
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;
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;
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_);
4314 struct RenderPassRemovalTestData : public LayerTreeHostImpl::FrameData {
4315 ScopedPtrHashMap<RenderPass::Id, TestRenderPass> render_pass_cache;
4316 scoped_ptr<SharedQuadState> shared_quad_state;
4319 class 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>();
4330 return renderer.Pass();
4333 void ClearCachedTextures() { textures_.clear(); }
4334 void SetHaveCachedResourcesForRenderPassId(RenderPass::Id id) {
4335 textures_.insert(id);
4338 virtual bool HaveCachedResourcesForRenderPassId(RenderPass::Id id) const
4339 OVERRIDE {
4340 return textures_.count(id);
4343 // RendererClient implementation.
4344 virtual gfx::Size DeviceViewportSize() const OVERRIDE {
4345 return viewport_size_;
4347 virtual const LayerTreeSettings& Settings() const OVERRIDE {
4348 return settings_;
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;
4363 protected:
4364 TestRenderer(ResourceProvider* resource_provider,
4365 OutputSurface* output_surface,
4366 Proxy* proxy)
4367 : GLRenderer(this, output_surface, resource_provider, 0) {}
4369 private:
4370 LayerTreeSettings settings_;
4371 gfx::Size viewport_size_;
4372 base::hash_set<RenderPass::Id> textures_;
4375 static void ConfigureRenderPassTestData(const char* test_script,
4376 RenderPassRemovalTestData* test_data,
4377 TestRenderer* renderer) {
4378 renderer->ClearCachedTextures();
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);
4389 const char* current_char = test_script;
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++;
4404 RenderPass::Id render_pass_id = RenderPass::Id(layer_id, index);
4406 bool is_replica = false;
4407 if (!test_data->render_pass_cache.contains(render_pass_id))
4408 is_replica = true;
4410 scoped_ptr<TestRenderPass> render_pass =
4411 test_data->render_pass_cache.take(render_pass_id);
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);
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;
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;
4448 current_char++;
4450 if (*current_char == ']')
4451 current_char++;
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);
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());
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,
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>());
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++;
4492 void 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++;
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;
4528 quad_list_iterator++;
4530 *pos = '\n';
4531 pos++;
4533 *pos = '\0';
4536 // Each RenderPassList is represented by a string which describes the
4537 // configuration.
4538 // The syntax of the string is as follows:
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---+
4549 // Expected results have exactly the same syntax, except they do not use square
4550 // brackets, since we only check the structure, not attributes.
4552 // Test case configuration consists of initialization script and expected
4553 // results, all in the same format.
4554 struct TestCase {
4555 const char* name;
4556 const char* init_script;
4557 const char* expected_result;
4560 TestCase remove_render_passes_cases[] = {
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",
4614 "R0ssssA0sss\n"
4615 }, {
4616 "Deep recursion, remove all",
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",
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",
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",
4657 "R0ssssA0sss\n"
4658 }, {
4659 "Leave some passes, remove others",
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",
4668 "R0ssssA0sss\n"
4669 "A0sssB0C0s\n"
4670 "B0sssD0ss\n"
4671 "D0sssssss\n"
4672 }, {
4673 0, 0, 0
4677 static 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;
4686 TEST_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);
4692 scoped_ptr<TestRenderer> renderer =
4693 TestRenderer::Create(resource_provider.get(),
4694 output_surface.get(),
4695 &proxy_);
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++;
4713 class LayerTreeHostImplTestWithDelegatingRenderer
4714 : public LayerTreeHostImplTest {
4715 protected:
4716 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
4717 return FakeOutputSurface::CreateDelegating3d().PassAs<OutputSurface>();
4720 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
4721 bool expect_to_draw = !expected_damage.IsEmpty();
4723 LayerTreeHostImpl::FrameData frame;
4724 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
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);
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());
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);
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);
4751 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
4752 host_impl_->DidDrawAllLayers(frame);
4753 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
4757 TEST_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);
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>());
4776 host_impl_->active_tree()->SetRootLayer(root.PassAs<LayerImpl>());
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);
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);
4788 // The third frame should have no damage, so no quads should be generated.
4789 gfx::Rect no_damage;
4790 DrawFrameAndTestDamage(no_damage);
4793 class 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));
4800 virtual ResourceProvider::ResourceId ContentsResourceId() const OVERRIDE {
4801 return 0;
4804 private:
4805 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
4806 : LayerImpl(tree_impl, id) {}
4809 TEST_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());
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());
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());
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>());
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());
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);
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);
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);
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);
4870 LayerTreeHostImpl::FrameData frame;
4871 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
4884 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
4885 host_impl_->DidDrawAllLayers(frame);
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();
4898 LayerTreeHostImpl::FrameData frame;
4899 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
4912 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
4913 host_impl_->DidDrawAllLayers(frame);
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();
4928 LayerTreeHostImpl::FrameData frame;
4929 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
4942 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
4943 host_impl_->DidDrawAllLayers(frame);
4947 TEST_F(LayerTreeHostImplTest, MaskLayerWithDifferentBounds) {
4948 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4949 // 50x50.
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());
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());
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>());
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());
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);
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);
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);
4991 LayerTreeHostImpl::FrameData frame;
4992 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
5005 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5006 host_impl_->DidDrawAllLayers(frame);
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();
5018 LayerTreeHostImpl::FrameData frame;
5019 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
5032 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5033 host_impl_->DidDrawAllLayers(frame);
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();
5048 LayerTreeHostImpl::FrameData frame;
5049 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
5062 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5063 host_impl_->DidDrawAllLayers(frame);
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();
5073 LayerTreeHostImpl::FrameData frame;
5074 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
5087 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5088 host_impl_->DidDrawAllLayers(frame);
5092 TEST_F(LayerTreeHostImplTest, ReflectionMaskLayerWithDifferentBounds) {
5093 // The replica's mask layer has bounds 100x100 but the replica is of a
5094 // layer with bounds 50x50.
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());
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());
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());
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>());
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());
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);
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);
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);
5141 LayerTreeHostImpl::FrameData frame;
5142 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
5156 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5157 host_impl_->DidDrawAllLayers(frame);
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();
5169 LayerTreeHostImpl::FrameData frame;
5170 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
5184 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5185 host_impl_->DidDrawAllLayers(frame);
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();
5200 LayerTreeHostImpl::FrameData frame;
5201 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
5215 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5216 host_impl_->DidDrawAllLayers(frame);
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();
5226 LayerTreeHostImpl::FrameData frame;
5227 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
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());
5241 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5242 host_impl_->DidDrawAllLayers(frame);
5246 TEST_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.
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());
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());
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());
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());
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>());
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());
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);
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);
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);
5302 float device_scale_factor = 1.f;
5303 host_impl_->SetViewportSize(root_size);
5304 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5306 LayerTreeHostImpl::FrameData frame;
5307 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5309 ASSERT_EQ(1u, frame.render_passes.size());
5310 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
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());
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());
5332 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5333 host_impl_->DidDrawAllLayers(frame);
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));
5340 LayerTreeHostImpl::FrameData frame;
5341 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5343 ASSERT_EQ(1u, frame.render_passes.size());
5344 ASSERT_EQ(2u, frame.render_passes[0]->quad_list.size());
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());
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());
5366 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5367 host_impl_->DidDrawAllLayers(frame);
5371 TEST_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.
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());
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());
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());
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());
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>());
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());
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);
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);
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);
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);
5435 float device_scale_factor = 1.f;
5436 host_impl_->SetViewportSize(root_size);
5437 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5439 LayerTreeHostImpl::FrameData frame;
5440 EXPECT_TRUE(host_impl_->PrepareToDraw(&frame, gfx::Rect()));
5442 ASSERT_EQ(1u, frame.render_passes.size());
5443 ASSERT_EQ(1u, frame.render_passes[0]->quad_list.size());
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());
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());
5462 host_impl_->DrawLayers(&frame, base::TimeTicks::Now());
5463 host_impl_->DidDrawAllLayers(frame);
5467 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5468 public:
5469 CompositorFrameMetadataTest()
5470 : swap_buffers_complete_(0) {}
5472 virtual void OverrideSettings(LayerTreeSettings* settings) OVERRIDE {
5473 settings->compositor_frame_message = true;
5475 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE {
5476 swap_buffers_complete_++;
5479 int swap_buffers_complete_;
5482 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5483 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
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);
5490 CompositorFrameAck ack;
5491 host_impl_->OnSendFrameToParentCompositorAck(ack);
5492 EXPECT_EQ(swap_buffers_complete_, 1);
5495 } // namespace
5496 } // namespace cc