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"
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
;
57 using media::VideoFrame
;
62 class LayerTreeHostImplTest
: public testing::Test
,
63 public LayerTreeHostImplClient
{
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
,
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
)
132 virtual void DidReceiveLastInputEventForVSync(base::TimeTicks frame_time
)
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
,
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
,
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
)
178 EXPECT_VECTOR_EQ(scroll_delta
, scroll_info
.scrolls
[i
].scroll_delta
);
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
)
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,
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
);
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
);
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
{
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
,
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
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
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
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
,
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
,
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(),
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
,
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
);
797 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
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
);
814 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
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
,
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
,
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
,
897 scroll_layer
->SetScrollOffset(gfx::Vector2d(50, 50));
899 host_impl_
->StartPageScaleAnimation(gfx::Vector2d(),
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));
917 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
920 scroll_layer
->SetScrollOffset(gfx::Vector2d(50, 50));
922 host_impl_
->StartPageScaleAnimation(gfx::Vector2d(25, 25),
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
,
959 scroll_layer
->SetScrollOffset(gfx::Vector2d(50, 50));
961 host_impl_
->StartPageScaleAnimation(gfx::Vector2d(),
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
{
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;
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());
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
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
{
1209 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
1214 ResourceProvider
* resource_provider
) {
1215 return scoped_ptr
<LayerImpl
>(new MissingTextureAnimatingLayer(
1221 resource_provider
));
1225 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
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(),
1242 ResourceProvider::TextureUsageAny
);
1243 resource_provider
->AllocateForTesting(resource
);
1244 PushTileProperties(0, 0, resource
, gfx::Rect(), false);
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());
1258 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
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
1273 host_impl_
->active_tree()->SetRootLayer(
1274 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
1276 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1278 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
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
1291 host_impl_
->active_tree()->SetRootLayer(
1292 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 5));
1294 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1296 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
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));
1311 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1313 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
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
,
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
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
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
,
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
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();
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();
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
,
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
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
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(),
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
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(
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(
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.
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
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
{
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
;
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
{
2086 BlendStateTrackerContext() : blend_(false) {}
2088 virtual void enable(WebKit::WGC3Denum cap
) OVERRIDE
{
2089 if (cap
== GL_BLEND
)
2093 virtual void disable(WebKit::WGC3Denum cap
) OVERRIDE
{
2094 if (cap
== GL_BLEND
)
2098 bool blend() const { return blend_
; }
2104 class BlendStateCheckLayer
: public LayerImpl
{
2106 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
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_
;
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
,
2131 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
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
>(),
2141 void SetExpectation(bool blend
, bool has_render_surface
) {
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
; }
2154 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
2156 ResourceProvider
* resource_provider
)
2157 : LayerImpl(tree_impl
, id
),
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(
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);
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();
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
);
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
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
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);
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
{
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_
; }
2513 bool reshape_called_
;
2516 class FakeDrawableLayerImpl
: public LayerImpl
{
2518 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2519 return scoped_ptr
<LayerImpl
>(new FakeDrawableLayerImpl(tree_impl
, id
));
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
{
2555 virtual void postSubBufferCHROMIUM(int x
, int y
, int width
, int height
)
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_
; }
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
,
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(
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
{
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
);
2706 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
2707 : LayerImpl(tree_impl
, id
) {}
2710 class MockContext
: public TestWebGraphicsContext3D
{
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
,
2732 WebKit::WGC3Dsizei width
,
2733 WebKit::WGC3Dsizei height
));
2736 class MockContextHarness
{
2738 MockContext
* context_
;
2741 explicit MockContextHarness(MockContext
* context
)
2742 : context_(context
) {
2743 // Catch "uninteresting" calls
2744 EXPECT_CALL(*context_
, useProgram(_
))
2747 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
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))
2782 .RetiresOnSaturation();
2784 EXPECT_CALL(*context_
, useProgram(_
))
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
))
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
))
2805 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
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
);
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
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
{
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
)
2900 if (pname
== GL_MAX_TEXTURE_SIZE
)
2905 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
2907 LayerTreeHostImplClient
* client
,
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 +--------------------+
2928 | | +-------------------+
2930 | | +-------------------+
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
{
3027 TrackingWebGraphicsContext3D()
3028 : TestWebGraphicsContext3D(),
3031 virtual WebKit::WebGLId
createTexture() OVERRIDE
{
3032 WebKit::WebGLId id
= TestWebGraphicsContext3D::createTexture();
3034 textures_
[id
] = true;
3039 virtual void deleteTexture(WebKit::WebGLId id
) OVERRIDE
{
3040 if (textures_
.find(id
) == textures_
.end())
3043 textures_
[id
] = false;
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_
; }
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
{
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());
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(_
))
3143 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
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
,
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());
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
,
3226 root_size
.width() - 25,
3227 root_size
.height() - 25),
3231 class GLRendererWithReleaseTextures
: public GLRenderer
{
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
,
3244 &stats_instrumentation_
);
3246 // Layers are structure as follows:
3248 // R +-- S1 +- L10 (owning)
3252 // +-- S2 +- L20 (owning)
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
,
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)
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
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
,
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)
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
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
,
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
,
3665 &stats_instrumentation_
);
3667 // Layers are structure as follows:
3669 // R +-- S1 +- L10 (owning)
3673 // +-- S2 +- L20 (owning)
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
,
3784 &stats_instrumentation_
);
3787 Layers are created as follows:
3789 +--------------------+
3793 | | +-------------------+
3795 | | +-------------------+
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(
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(
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
3879 EXPECT_TRUE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
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
3894 EXPECT_TRUE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
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
,
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(),
3916 intermediate_layer_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(
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
,
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(),
4105 intermediate_layer_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());
4129 frame
.render_passes
[0]->has_occlusion_from_outside_target_surface
);
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(
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
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
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
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
{
4321 static scoped_ptr
<TestRenderer
> Create(ResourceProvider
* resource_provider
,
4322 OutputSurface
* output_surface
,
4324 scoped_ptr
<TestRenderer
> renderer(new TestRenderer(resource_provider
,
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
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
{
4350 virtual void SetFullRootLayerDamage() OVERRIDE
{}
4351 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
4353 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
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
{
4364 TestRenderer(ResourceProvider
* resource_provider
,
4365 OutputSurface
* output_surface
,
4367 : GLRenderer(this, output_surface
, resource_provider
, 0) {}
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(),
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
;
4400 ASSERT_TRUE(current_char
);
4401 int index
= *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
))
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),
4423 render_pass
->AppendQuad(quad
.PassAs
<DrawQuad
>());
4425 } else if ((*current_char
>= 'A') && (*current_char
<= 'Z')) {
4426 // RenderPass draw quad.
4427 int layer_id
= *current_char
;
4429 ASSERT_TRUE(current_char
);
4430 int index
= *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
== '[') {
4439 while (*current_char
&& *current_char
!= ']') {
4440 switch (*current_char
) {
4442 contents_changed
= false;
4450 if (*current_char
== ']')
4454 if (test_data
->render_pass_cache
.find(new_render_pass_id
) ==
4455 test_data
->render_pass_cache
.end()) {
4457 renderer
->SetHaveCachedResourcesForRenderPassId(new_render_pass_id
);
4459 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
4460 pass
->SetNew(new_render_pass_id
,
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(),
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
>());
4492 void DumpRenderPassTestData(const RenderPassRemovalTestData
& test_data
,
4495 for (RenderPassList::const_reverse_iterator it
=
4496 test_data
.render_passes
.rbegin();
4497 it
!= test_data
.render_passes
.rend();
4499 const RenderPass
* current_pass
= *it
;
4500 *pos
= current_pass
->id
.layer_id
;
4502 *pos
= current_pass
->id
.index
;
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
:
4514 case DrawQuad::RENDER_PASS
:
4515 *pos
= RenderPassDrawQuad::MaterialCast(current_quad
)->
4516 render_pass_id
.layer_id
;
4518 *pos
= RenderPassDrawQuad::MaterialCast(current_quad
)->
4519 render_pass_id
.index
;
4528 quad_list_iterator
++;
4536 // Each RenderPassList is represented by a string which describes the
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.
4556 const char* init_script
;
4557 const char* expected_result
;
4560 TestCase remove_render_passes_cases
[] = {
4566 "Single pass - no quads",
4570 "Two passes, no removal",
4576 "Two passes, remove last",
4581 "Have texture but contents changed - leave pass",
4587 "Contents didn't change but no texture - leave pass",
4593 "Replica: two quads reference the same pass; remove",
4594 "R0ssssA0[ct]A0[ct]sss\n"
4598 "Replica: two quads reference the same pass; leave",
4599 "R0ssssA0[c]A0[c]sss\n"
4604 "Many passes, remove all",
4606 "A0sssB0[ct]C0[ct]s\n"
4607 "B0sssD0[ct]ssE0[ct]F0[ct]\n"
4616 "Deep recursion, remove all",
4618 "R0sssssA0[ct]ssss\n"
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"
4645 "R0A0B0C0D0E0F0G0H0I0J0\n"
4647 "Remove passes regardless of cache state",
4650 "B0sssD0[c]ssE0[t]F0\n"
4659 "Leave some passes, remove others",
4662 "A0sssB0[t]C0[ct]s\n"
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: " <<
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(),
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
,
4704 LayerTreeHostImpl::RemoveRenderPasses(
4705 LayerTreeHostImpl::CullRenderPassesWithCachedTextures(renderer
.get()),
4707 VerifyRenderPassTestData(remove_render_passes_cases
[test_case_index
],
4713 class LayerTreeHostImplTestWithDelegatingRenderer
4714 : public LayerTreeHostImplTest
{
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());
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
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
{
4795 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4797 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
4800 virtual ResourceProvider::ResourceId
ContentsResourceId() const OVERRIDE
{
4805 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
4806 : LayerImpl(tree_impl
, id
) {}
4809 TEST_F(LayerTreeHostImplTest
, MaskLayerWithScaling
) {
4812 // +-- Scaling Layer (adds a 2x scale)
4814 // +-- Content Layer
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
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
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
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
{
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);