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
->scroll_delta(), 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(InputHandlerClient::ScrollStarted
,
410 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollIgnored
,
420 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollIgnored
,
442 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
454 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
479 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollOnMainThread
,
493 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
495 // But gesture scrolls can still be handled.
496 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
497 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollIgnored
,
507 host_impl_
->FlingScrollBegin());
509 // Start scrolling a layer
510 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
511 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Gesture
));
513 // Now the fling should go ahead since we've started scrolling a layer
514 EXPECT_EQ(InputHandlerClient::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(InputHandlerClient::ScrollIgnored
,
525 host_impl_
->FlingScrollBegin());
527 // Start scrolling a layer
528 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
529 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
531 // Now the fling should go ahead since we've started scrolling a layer
532 EXPECT_EQ(InputHandlerClient::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(InputHandlerClient::ScrollOnMainThread
,
546 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Gesture
));
548 // The fling should be ignored since there's no layer being scrolled impl-side
549 EXPECT_EQ(InputHandlerClient::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(InputHandlerClient::ScrollOnMainThread
,
562 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
563 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
564 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollOnMainThread
,
579 host_impl_
->ScrollBegin(gfx::Point(25, 25),
580 InputHandlerClient::Wheel
));
581 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
582 host_impl_
->ScrollBegin(gfx::Point(25, 25),
583 InputHandlerClient::Gesture
));
585 // All scroll types outside this region should succeed.
586 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
587 host_impl_
->ScrollBegin(gfx::Point(75, 75),
588 InputHandlerClient::Wheel
));
589 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
590 host_impl_
->ScrollEnd();
591 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
592 host_impl_
->ScrollBegin(gfx::Point(75, 75),
593 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
612 host_impl_
->ScrollBegin(gfx::Point(40, 10),
613 InputHandlerClient::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(InputHandlerClient::ScrollOnMainThread
,
619 host_impl_
->ScrollBegin(gfx::Point(10, 10),
620 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
630 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
663 host_impl_
->ScrollBegin(gfx::Point(),
664 InputHandlerClient::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()->scroll_delta().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(InputHandlerClient::ScrollStarted
,
752 host_impl_
->ScrollBegin(gfx::Point(5, 5),
753 InputHandlerClient::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), InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
996 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollIgnored
,
1333 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollIgnored
,
1365 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1373 host_impl_
->ScrollBegin(gfx::Point(),
1374 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1408 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1409 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1427 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1428 InputHandlerClient::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(InputHandlerClient::ScrollIgnored
,
1446 host_impl_
->ScrollBegin(gfx::Point(15, 5),
1447 InputHandlerClient::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(InputHandlerClient::ScrollIgnored
,
1470 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1471 InputHandlerClient::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(InputHandlerClient::ScrollOnMainThread
,
1492 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1493 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1510 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1511 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1549 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1550 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1644 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1645 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1689 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1690 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1728 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1729 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1747 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1748 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1766 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1767 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1788 host_impl_
->ScrollBegin(gfx::Point(1, 1),
1789 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1819 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1820 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1852 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1853 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1871 host_impl_
->ScrollBegin(gfx::Point(),
1872 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1886 host_impl_
->ScrollBegin(gfx::Point(),
1887 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1924 host_impl_
->ScrollBegin(gfx::Point(),
1925 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1949 host_impl_
->ScrollBegin(gfx::Point(),
1950 InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
1992 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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(InputHandlerClient::ScrollStarted
,
2007 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::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 BlendStateTrackerContext
: public TestWebGraphicsContext3D
{
2020 BlendStateTrackerContext() : blend_(false) {}
2022 virtual void enable(WebKit::WGC3Denum cap
) OVERRIDE
{
2023 if (cap
== GL_BLEND
)
2027 virtual void disable(WebKit::WGC3Denum cap
) OVERRIDE
{
2028 if (cap
== GL_BLEND
)
2032 bool blend() const { return blend_
; }
2038 class BlendStateCheckLayer
: public LayerImpl
{
2040 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2042 ResourceProvider
* resource_provider
) {
2043 return scoped_ptr
<LayerImpl
>(new BlendStateCheckLayer(tree_impl
,
2045 resource_provider
));
2048 virtual void AppendQuads(QuadSink
* quad_sink
,
2049 AppendQuadsData
* append_quads_data
) OVERRIDE
{
2050 quads_appended_
= true;
2052 gfx::Rect opaque_rect
;
2053 if (contents_opaque())
2054 opaque_rect
= quad_rect_
;
2056 opaque_rect
= opaque_content_rect_
;
2058 SharedQuadState
* shared_quad_state
=
2059 quad_sink
->UseSharedQuadState(CreateSharedQuadState());
2060 scoped_ptr
<TileDrawQuad
> test_blending_draw_quad
= TileDrawQuad::Create();
2061 test_blending_draw_quad
->SetNew(shared_quad_state
,
2065 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
2068 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
2069 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
2070 EXPECT_EQ(has_render_surface_
, !!render_surface());
2071 quad_sink
->Append(test_blending_draw_quad
.PassAs
<DrawQuad
>(),
2075 void SetExpectation(bool blend
, bool has_render_surface
) {
2077 has_render_surface_
= has_render_surface
;
2078 quads_appended_
= false;
2081 bool quads_appended() const { return quads_appended_
; }
2083 void SetQuadRect(gfx::Rect rect
) { quad_rect_
= rect
; }
2084 void SetQuadVisibleRect(gfx::Rect rect
) { quad_visible_rect_
= rect
; }
2085 void SetOpaqueContentRect(gfx::Rect rect
) { opaque_content_rect_
= rect
; }
2088 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
2090 ResourceProvider
* resource_provider
)
2091 : LayerImpl(tree_impl
, id
),
2093 has_render_surface_(false),
2094 quads_appended_(false),
2095 quad_rect_(5, 5, 5, 5),
2096 quad_visible_rect_(5, 5, 5, 5),
2097 resource_id_(resource_provider
->CreateResource(
2100 ResourceProvider::TextureUsageAny
)) {
2101 resource_provider
->AllocateForTesting(resource_id_
);
2102 SetAnchorPoint(gfx::PointF());
2103 SetBounds(gfx::Size(10, 10));
2104 SetContentBounds(gfx::Size(10, 10));
2105 SetDrawsContent(true);
2109 bool has_render_surface_
;
2110 bool quads_appended_
;
2111 gfx::Rect quad_rect_
;
2112 gfx::Rect opaque_content_rect_
;
2113 gfx::Rect quad_visible_rect_
;
2114 ResourceProvider::ResourceId resource_id_
;
2117 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
2119 scoped_ptr
<LayerImpl
> root
=
2120 LayerImpl::Create(host_impl_
->active_tree(), 1);
2121 root
->SetAnchorPoint(gfx::PointF());
2122 root
->SetBounds(gfx::Size(10, 10));
2123 root
->SetContentBounds(root
->bounds());
2124 root
->SetDrawsContent(false);
2125 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2127 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
2130 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
2132 host_impl_
->resource_provider()));
2133 BlendStateCheckLayer
* layer1
=
2134 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
2135 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
2137 LayerTreeHostImpl::FrameData frame
;
2139 // Opaque layer, drawn without blending.
2140 layer1
->SetContentsOpaque(true);
2141 layer1
->SetExpectation(false, false);
2142 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2143 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2144 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2145 EXPECT_TRUE(layer1
->quads_appended());
2146 host_impl_
->DidDrawAllLayers(frame
);
2148 // Layer with translucent content and painting, so drawn with blending.
2149 layer1
->SetContentsOpaque(false);
2150 layer1
->SetExpectation(true, false);
2151 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2152 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2153 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2154 EXPECT_TRUE(layer1
->quads_appended());
2155 host_impl_
->DidDrawAllLayers(frame
);
2157 // Layer with translucent opacity, drawn with blending.
2158 layer1
->SetContentsOpaque(true);
2159 layer1
->SetOpacity(0.5f
);
2160 layer1
->SetExpectation(true, false);
2161 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2162 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2163 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2164 EXPECT_TRUE(layer1
->quads_appended());
2165 host_impl_
->DidDrawAllLayers(frame
);
2167 // Layer with translucent opacity and painting, drawn with blending.
2168 layer1
->SetContentsOpaque(true);
2169 layer1
->SetOpacity(0.5f
);
2170 layer1
->SetExpectation(true, false);
2171 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2172 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2173 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2174 EXPECT_TRUE(layer1
->quads_appended());
2175 host_impl_
->DidDrawAllLayers(frame
);
2178 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
2180 host_impl_
->resource_provider()));
2181 BlendStateCheckLayer
* layer2
=
2182 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
2183 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
2185 // 2 opaque layers, drawn without blending.
2186 layer1
->SetContentsOpaque(true);
2187 layer1
->SetOpacity(1.f
);
2188 layer1
->SetExpectation(false, false);
2189 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2190 layer2
->SetContentsOpaque(true);
2191 layer2
->SetOpacity(1.f
);
2192 layer2
->SetExpectation(false, false);
2193 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2194 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2195 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2196 EXPECT_TRUE(layer1
->quads_appended());
2197 EXPECT_TRUE(layer2
->quads_appended());
2198 host_impl_
->DidDrawAllLayers(frame
);
2200 // Parent layer with translucent content, drawn with blending.
2201 // Child layer with opaque content, drawn without blending.
2202 layer1
->SetContentsOpaque(false);
2203 layer1
->SetExpectation(true, false);
2204 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2205 layer2
->SetExpectation(false, false);
2206 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2207 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2208 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2209 EXPECT_TRUE(layer1
->quads_appended());
2210 EXPECT_TRUE(layer2
->quads_appended());
2211 host_impl_
->DidDrawAllLayers(frame
);
2213 // Parent layer with translucent content but opaque painting, drawn without
2215 // Child layer with opaque content, drawn without blending.
2216 layer1
->SetContentsOpaque(true);
2217 layer1
->SetExpectation(false, false);
2218 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2219 layer2
->SetExpectation(false, false);
2220 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2221 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2222 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2223 EXPECT_TRUE(layer1
->quads_appended());
2224 EXPECT_TRUE(layer2
->quads_appended());
2225 host_impl_
->DidDrawAllLayers(frame
);
2227 // Parent layer with translucent opacity and opaque content. Since it has a
2228 // drawing child, it's drawn to a render surface which carries the opacity,
2229 // so it's itself drawn without blending.
2230 // Child layer with opaque content, drawn without blending (parent surface
2231 // carries the inherited opacity).
2232 layer1
->SetContentsOpaque(true);
2233 layer1
->SetOpacity(0.5f
);
2234 layer1
->SetExpectation(false, true);
2235 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2236 layer2
->SetExpectation(false, false);
2237 layer2
->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 EXPECT_TRUE(layer2
->quads_appended());
2242 host_impl_
->DidDrawAllLayers(frame
);
2244 // Draw again, but with child non-opaque, to make sure
2245 // layer1 not culled.
2246 layer1
->SetContentsOpaque(true);
2247 layer1
->SetOpacity(1.f
);
2248 layer1
->SetExpectation(false, false);
2249 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2250 layer2
->SetContentsOpaque(true);
2251 layer2
->SetOpacity(0.5f
);
2252 layer2
->SetExpectation(true, false);
2253 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2254 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2255 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2256 EXPECT_TRUE(layer1
->quads_appended());
2257 EXPECT_TRUE(layer2
->quads_appended());
2258 host_impl_
->DidDrawAllLayers(frame
);
2260 // A second way of making the child non-opaque.
2261 layer1
->SetContentsOpaque(true);
2262 layer1
->SetOpacity(1.f
);
2263 layer1
->SetExpectation(false, false);
2264 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2265 layer2
->SetContentsOpaque(false);
2266 layer2
->SetOpacity(1.f
);
2267 layer2
->SetExpectation(true, false);
2268 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2269 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2270 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2271 EXPECT_TRUE(layer1
->quads_appended());
2272 EXPECT_TRUE(layer2
->quads_appended());
2273 host_impl_
->DidDrawAllLayers(frame
);
2275 // And when the layer says its not opaque but is painted opaque, it is not
2277 layer1
->SetContentsOpaque(true);
2278 layer1
->SetOpacity(1.f
);
2279 layer1
->SetExpectation(false, false);
2280 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2281 layer2
->SetContentsOpaque(true);
2282 layer2
->SetOpacity(1.f
);
2283 layer2
->SetExpectation(false, false);
2284 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2285 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2286 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2287 EXPECT_TRUE(layer1
->quads_appended());
2288 EXPECT_TRUE(layer2
->quads_appended());
2289 host_impl_
->DidDrawAllLayers(frame
);
2291 // Layer with partially opaque contents, drawn with blending.
2292 layer1
->SetContentsOpaque(false);
2293 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
2294 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
2295 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
2296 layer1
->SetExpectation(true, false);
2297 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2298 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2299 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2300 EXPECT_TRUE(layer1
->quads_appended());
2301 host_impl_
->DidDrawAllLayers(frame
);
2303 // Layer with partially opaque contents partially culled, drawn with blending.
2304 layer1
->SetContentsOpaque(false);
2305 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
2306 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
2307 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
2308 layer1
->SetExpectation(true, false);
2309 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2310 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2311 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2312 EXPECT_TRUE(layer1
->quads_appended());
2313 host_impl_
->DidDrawAllLayers(frame
);
2315 // Layer with partially opaque contents culled, drawn with blending.
2316 layer1
->SetContentsOpaque(false);
2317 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
2318 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
2319 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
2320 layer1
->SetExpectation(true, false);
2321 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2322 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2323 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2324 EXPECT_TRUE(layer1
->quads_appended());
2325 host_impl_
->DidDrawAllLayers(frame
);
2327 // Layer with partially opaque contents and translucent contents culled, drawn
2328 // without blending.
2329 layer1
->SetContentsOpaque(false);
2330 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
2331 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
2332 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
2333 layer1
->SetExpectation(false, false);
2334 layer1
->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 host_impl_
->DidDrawAllLayers(frame
);
2341 TEST_F(LayerTreeHostImplTest
, ViewportCovered
) {
2342 host_impl_
->InitializeRenderer(CreateOutputSurface());
2343 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
2345 gfx::Size
viewport_size(1000, 1000);
2346 host_impl_
->SetViewportSize(viewport_size
);
2348 host_impl_
->active_tree()->SetRootLayer(
2349 LayerImpl::Create(host_impl_
->active_tree(), 1));
2350 host_impl_
->active_tree()->root_layer()->AddChild(
2351 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
2353 host_impl_
->resource_provider()));
2354 BlendStateCheckLayer
* child
= static_cast<BlendStateCheckLayer
*>(
2355 host_impl_
->active_tree()->root_layer()->children()[0]);
2356 child
->SetExpectation(false, false);
2357 child
->SetContentsOpaque(true);
2361 gfx::Rect
layer_rect(0, 0, 1000, 1000);
2362 child
->SetPosition(layer_rect
.origin());
2363 child
->SetBounds(layer_rect
.size());
2364 child
->SetContentBounds(layer_rect
.size());
2365 child
->SetQuadRect(gfx::Rect(layer_rect
.size()));
2366 child
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
2368 LayerTreeHostImpl::FrameData frame
;
2369 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2370 ASSERT_EQ(1u, frame
.render_passes
.size());
2372 size_t num_gutter_quads
= 0;
2373 for (size_t i
= 0; i
< frame
.render_passes
[0]->quad_list
.size(); ++i
)
2374 num_gutter_quads
+= (frame
.render_passes
[0]->quad_list
[i
]->material
==
2375 DrawQuad::SOLID_COLOR
) ? 1 : 0;
2376 EXPECT_EQ(0u, num_gutter_quads
);
2377 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
2379 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2380 frame
.render_passes
[0]->quad_list
, gfx::Rect(viewport_size
));
2381 host_impl_
->DidDrawAllLayers(frame
);
2384 // Empty visible content area (fullscreen gutter rect)
2386 gfx::Rect
layer_rect(0, 0, 0, 0);
2387 child
->SetPosition(layer_rect
.origin());
2388 child
->SetBounds(layer_rect
.size());
2389 child
->SetContentBounds(layer_rect
.size());
2390 child
->SetQuadRect(gfx::Rect(layer_rect
.size()));
2391 child
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
2393 LayerTreeHostImpl::FrameData frame
;
2394 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2395 ASSERT_EQ(1u, frame
.render_passes
.size());
2397 size_t num_gutter_quads
= 0;
2398 for (size_t i
= 0; i
< frame
.render_passes
[0]->quad_list
.size(); ++i
)
2399 num_gutter_quads
+= (frame
.render_passes
[0]->quad_list
[i
]->material
==
2400 DrawQuad::SOLID_COLOR
) ? 1 : 0;
2401 EXPECT_EQ(1u, num_gutter_quads
);
2402 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
2404 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2405 frame
.render_passes
[0]->quad_list
, gfx::Rect(viewport_size
));
2406 host_impl_
->DidDrawAllLayers(frame
);
2409 // Content area in middle of clip rect (four surrounding gutter rects)
2411 gfx::Rect
layer_rect(500, 500, 200, 200);
2412 child
->SetPosition(layer_rect
.origin());
2413 child
->SetBounds(layer_rect
.size());
2414 child
->SetContentBounds(layer_rect
.size());
2415 child
->SetQuadRect(gfx::Rect(layer_rect
.size()));
2416 child
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
2418 LayerTreeHostImpl::FrameData frame
;
2419 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2420 ASSERT_EQ(1u, frame
.render_passes
.size());
2422 size_t num_gutter_quads
= 0;
2423 for (size_t i
= 0; i
< frame
.render_passes
[0]->quad_list
.size(); ++i
)
2424 num_gutter_quads
+= (frame
.render_passes
[0]->quad_list
[i
]->material
==
2425 DrawQuad::SOLID_COLOR
) ? 1 : 0;
2426 EXPECT_EQ(4u, num_gutter_quads
);
2427 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
2429 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2430 frame
.render_passes
[0]->quad_list
, gfx::Rect(viewport_size
));
2431 host_impl_
->DidDrawAllLayers(frame
);
2436 class ReshapeTrackerContext
: public TestWebGraphicsContext3D
{
2438 ReshapeTrackerContext() : reshape_called_(false) {}
2440 virtual void reshape(int width
, int height
) OVERRIDE
{
2441 reshape_called_
= true;
2444 bool reshape_called() const { return reshape_called_
; }
2447 bool reshape_called_
;
2450 class FakeDrawableLayerImpl
: public LayerImpl
{
2452 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2453 return scoped_ptr
<LayerImpl
>(new FakeDrawableLayerImpl(tree_impl
, id
));
2456 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
2457 : LayerImpl(tree_impl
, id
) {}
2460 // Only reshape when we know we are going to draw. Otherwise, the reshape
2461 // can leave the window at the wrong size if we never draw and the proper
2462 // viewport size is never set.
2463 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
2464 scoped_ptr
<OutputSurface
> output_surface
= FakeOutputSurface::Create3d(
2465 scoped_ptr
<WebKit::WebGraphicsContext3D
>(new ReshapeTrackerContext
))
2466 .PassAs
<OutputSurface
>();
2467 ReshapeTrackerContext
* reshape_tracker
=
2468 static_cast<ReshapeTrackerContext
*>(output_surface
->context3d());
2469 host_impl_
->InitializeRenderer(output_surface
.Pass());
2471 scoped_ptr
<LayerImpl
> root
=
2472 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
2473 root
->SetAnchorPoint(gfx::PointF());
2474 root
->SetBounds(gfx::Size(10, 10));
2475 root
->SetContentBounds(gfx::Size(10, 10));
2476 root
->SetDrawsContent(true);
2477 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2478 EXPECT_FALSE(reshape_tracker
->reshape_called());
2480 LayerTreeHostImpl::FrameData frame
;
2481 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2482 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2483 EXPECT_TRUE(reshape_tracker
->reshape_called());
2484 host_impl_
->DidDrawAllLayers(frame
);
2487 class PartialSwapTrackerContext
: public TestWebGraphicsContext3D
{
2489 virtual void postSubBufferCHROMIUM(int x
, int y
, int width
, int height
)
2491 partial_swap_rect_
= gfx::Rect(x
, y
, width
, height
);
2494 virtual WebKit::WebString
getString(WebKit::WGC3Denum name
) OVERRIDE
{
2495 if (name
== GL_EXTENSIONS
) {
2496 return WebKit::WebString(
2497 "GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
2500 return WebKit::WebString();
2503 gfx::Rect
partial_swap_rect() const { return partial_swap_rect_
; }
2506 gfx::Rect partial_swap_rect_
;
2509 // Make sure damage tracking propagates all the way to the graphics context,
2510 // where it should request to swap only the sub-buffer that is damaged.
2511 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
2512 scoped_ptr
<OutputSurface
> output_surface
=
2513 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
2514 new PartialSwapTrackerContext
)).PassAs
<OutputSurface
>();
2515 PartialSwapTrackerContext
* partial_swap_tracker
=
2516 static_cast<PartialSwapTrackerContext
*>(output_surface
->context3d());
2518 // This test creates its own LayerTreeHostImpl, so
2519 // that we can force partial swap enabled.
2520 LayerTreeSettings settings
;
2521 settings
.partial_swap_enabled
= true;
2522 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
2523 LayerTreeHostImpl::Create(settings
,
2526 &stats_instrumentation_
);
2527 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
2528 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
2530 scoped_ptr
<LayerImpl
> root
=
2531 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
2532 scoped_ptr
<LayerImpl
> child
=
2533 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
2534 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
2535 child
->SetAnchorPoint(gfx::PointF());
2536 child
->SetBounds(gfx::Size(14, 15));
2537 child
->SetContentBounds(gfx::Size(14, 15));
2538 child
->SetDrawsContent(true);
2539 root
->SetAnchorPoint(gfx::PointF());
2540 root
->SetBounds(gfx::Size(500, 500));
2541 root
->SetContentBounds(gfx::Size(500, 500));
2542 root
->SetDrawsContent(true);
2543 root
->AddChild(child
.Pass());
2544 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
2546 LayerTreeHostImpl::FrameData frame
;
2548 // First frame, the entire screen should get swapped.
2549 EXPECT_TRUE(layer_tree_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2550 layer_tree_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2551 layer_tree_host_impl
->DidDrawAllLayers(frame
);
2552 layer_tree_host_impl
->SwapBuffers(frame
);
2553 gfx::Rect actual_swap_rect
= partial_swap_tracker
->partial_swap_rect();
2554 gfx::Rect expected_swap_rect
= gfx::Rect(0, 0, 500, 500);
2555 EXPECT_EQ(expected_swap_rect
.x(), actual_swap_rect
.x());
2556 EXPECT_EQ(expected_swap_rect
.y(), actual_swap_rect
.y());
2557 EXPECT_EQ(expected_swap_rect
.width(), actual_swap_rect
.width());
2558 EXPECT_EQ(expected_swap_rect
.height(), actual_swap_rect
.height());
2560 // Second frame, only the damaged area should get swapped. Damage should be
2561 // the union of old and new child rects.
2562 // expected damage rect: gfx::Rect(26, 28);
2563 // expected swap rect: vertically flipped, with origin at bottom left corner.
2564 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
2566 EXPECT_TRUE(layer_tree_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2567 layer_tree_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2568 host_impl_
->DidDrawAllLayers(frame
);
2569 layer_tree_host_impl
->SwapBuffers(frame
);
2570 actual_swap_rect
= partial_swap_tracker
->partial_swap_rect();
2571 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
2572 EXPECT_EQ(expected_swap_rect
.x(), actual_swap_rect
.x());
2573 EXPECT_EQ(expected_swap_rect
.y(), actual_swap_rect
.y());
2574 EXPECT_EQ(expected_swap_rect
.width(), actual_swap_rect
.width());
2575 EXPECT_EQ(expected_swap_rect
.height(), actual_swap_rect
.height());
2577 // Make sure that partial swap is constrained to the viewport dimensions
2578 // expected damage rect: gfx::Rect(500, 500);
2579 // expected swap rect: flipped damage rect, but also clamped to viewport
2580 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
2581 // This will damage everything.
2582 layer_tree_host_impl
->active_tree()->root_layer()->SetOpacity(0.7f
);
2583 EXPECT_TRUE(layer_tree_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2584 layer_tree_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2585 host_impl_
->DidDrawAllLayers(frame
);
2586 layer_tree_host_impl
->SwapBuffers(frame
);
2587 actual_swap_rect
= partial_swap_tracker
->partial_swap_rect();
2588 expected_swap_rect
= gfx::Rect(10, 10);
2589 EXPECT_EQ(expected_swap_rect
.x(), actual_swap_rect
.x());
2590 EXPECT_EQ(expected_swap_rect
.y(), actual_swap_rect
.y());
2591 EXPECT_EQ(expected_swap_rect
.width(), actual_swap_rect
.width());
2592 EXPECT_EQ(expected_swap_rect
.height(), actual_swap_rect
.height());
2595 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
2596 scoped_ptr
<LayerImpl
> root
=
2597 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
2598 scoped_ptr
<LayerImpl
> child
=
2599 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
2600 child
->SetAnchorPoint(gfx::PointF());
2601 child
->SetBounds(gfx::Size(10, 10));
2602 child
->SetContentBounds(gfx::Size(10, 10));
2603 child
->SetDrawsContent(true);
2604 root
->SetAnchorPoint(gfx::PointF());
2605 root
->SetBounds(gfx::Size(10, 10));
2606 root
->SetContentBounds(gfx::Size(10, 10));
2607 root
->SetDrawsContent(true);
2608 root
->SetOpacity(0.7f
);
2609 root
->AddChild(child
.Pass());
2611 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2613 LayerTreeHostImpl::FrameData frame
;
2615 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2616 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
2617 EXPECT_EQ(1u, frame
.render_passes
.size());
2618 host_impl_
->DidDrawAllLayers(frame
);
2621 class FakeLayerWithQuads
: public LayerImpl
{
2623 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2624 return scoped_ptr
<LayerImpl
>(new FakeLayerWithQuads(tree_impl
, id
));
2627 virtual void AppendQuads(QuadSink
* quad_sink
,
2628 AppendQuadsData
* append_quads_data
) OVERRIDE
{
2629 SharedQuadState
* shared_quad_state
=
2630 quad_sink
->UseSharedQuadState(CreateSharedQuadState());
2632 SkColor gray
= SkColorSetRGB(100, 100, 100);
2633 gfx::Rect
quad_rect(content_bounds());
2634 scoped_ptr
<SolidColorDrawQuad
> my_quad
= SolidColorDrawQuad::Create();
2635 my_quad
->SetNew(shared_quad_state
, quad_rect
, gray
);
2636 quad_sink
->Append(my_quad
.PassAs
<DrawQuad
>(), append_quads_data
);
2640 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
2641 : LayerImpl(tree_impl
, id
) {}
2644 class MockContext
: public TestWebGraphicsContext3D
{
2646 MOCK_METHOD1(useProgram
, void(WebKit::WebGLId program
));
2647 MOCK_METHOD5(uniform4f
, void(WebKit::WGC3Dint location
,
2648 WebKit::WGC3Dfloat x
,
2649 WebKit::WGC3Dfloat y
,
2650 WebKit::WGC3Dfloat z
,
2651 WebKit::WGC3Dfloat w
));
2652 MOCK_METHOD4(uniformMatrix4fv
, void(WebKit::WGC3Dint location
,
2653 WebKit::WGC3Dsizei count
,
2654 WebKit::WGC3Dboolean transpose
,
2655 const WebKit::WGC3Dfloat
* value
));
2656 MOCK_METHOD4(drawElements
, void(WebKit::WGC3Denum mode
,
2657 WebKit::WGC3Dsizei count
,
2658 WebKit::WGC3Denum type
,
2659 WebKit::WGC3Dintptr offset
));
2660 MOCK_METHOD1(getString
, WebKit::WebString(WebKit::WGC3Denum name
));
2661 MOCK_METHOD0(getRequestableExtensionsCHROMIUM
, WebKit::WebString());
2662 MOCK_METHOD1(enable
, void(WebKit::WGC3Denum cap
));
2663 MOCK_METHOD1(disable
, void(WebKit::WGC3Denum cap
));
2664 MOCK_METHOD4(scissor
, void(WebKit::WGC3Dint x
,
2666 WebKit::WGC3Dsizei width
,
2667 WebKit::WGC3Dsizei height
));
2670 class MockContextHarness
{
2672 MockContext
* context_
;
2675 explicit MockContextHarness(MockContext
* context
)
2676 : context_(context
) {
2677 // Catch "uninteresting" calls
2678 EXPECT_CALL(*context_
, useProgram(_
))
2681 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
2684 // These are not asserted
2685 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
2686 .WillRepeatedly(Return());
2688 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
2689 .WillRepeatedly(Return());
2691 // Any other strings are empty
2692 EXPECT_CALL(*context_
, getString(_
))
2693 .WillRepeatedly(Return(WebKit::WebString()));
2695 // Support for partial swap, if needed
2696 EXPECT_CALL(*context_
, getString(GL_EXTENSIONS
))
2697 .WillRepeatedly(Return(
2698 WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
2700 EXPECT_CALL(*context_
, getRequestableExtensionsCHROMIUM())
2701 .WillRepeatedly(Return(
2702 WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
2704 // Any un-sanctioned calls to enable() are OK
2705 EXPECT_CALL(*context_
, enable(_
))
2706 .WillRepeatedly(Return());
2708 // Any un-sanctioned calls to disable() are OK
2709 EXPECT_CALL(*context_
, disable(_
))
2710 .WillRepeatedly(Return());
2713 void MustDrawSolidQuad() {
2714 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
2716 .RetiresOnSaturation();
2718 EXPECT_CALL(*context_
, useProgram(_
))
2720 .RetiresOnSaturation();
2723 void MustSetScissor(int x
, int y
, int width
, int height
) {
2724 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
2725 .WillRepeatedly(Return());
2727 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
2729 .WillRepeatedly(Return());
2732 void MustSetNoScissor() {
2733 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
2734 .WillRepeatedly(Return());
2736 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
2739 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
2744 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
2745 scoped_ptr
<OutputSurface
> output_surface
=
2746 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
2747 new MockContext
)).PassAs
<OutputSurface
>();
2748 MockContext
* mock_context
=
2749 static_cast<MockContext
*>(output_surface
->context3d());
2750 MockContextHarness
harness(mock_context
);
2753 CreateLayerTreeHost(false, output_surface
.Pass());
2754 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
2756 // Without partial swap, and no clipping, no scissor is set.
2757 harness
.MustDrawSolidQuad();
2758 harness
.MustSetNoScissor();
2760 LayerTreeHostImpl::FrameData frame
;
2761 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2762 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2763 host_impl_
->DidDrawAllLayers(frame
);
2765 Mock::VerifyAndClearExpectations(&mock_context
);
2767 // Without partial swap, but a layer does clip its subtree, one scissor is
2769 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
2770 harness
.MustDrawSolidQuad();
2771 harness
.MustSetScissor(0, 0, 10, 10);
2773 LayerTreeHostImpl::FrameData frame
;
2774 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2775 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2776 host_impl_
->DidDrawAllLayers(frame
);
2778 Mock::VerifyAndClearExpectations(&mock_context
);
2781 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
2782 scoped_ptr
<OutputSurface
> output_surface
=
2783 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
2784 new MockContext
)).PassAs
<OutputSurface
>();
2785 MockContext
* mock_context
=
2786 static_cast<MockContext
*>(output_surface
->context3d());
2787 MockContextHarness
harness(mock_context
);
2789 CreateLayerTreeHost(true, output_surface
.Pass());
2790 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
2792 // The first frame is not a partially-swapped one.
2793 harness
.MustSetScissor(0, 0, 10, 10);
2794 harness
.MustDrawSolidQuad();
2796 LayerTreeHostImpl::FrameData frame
;
2797 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2798 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2799 host_impl_
->DidDrawAllLayers(frame
);
2801 Mock::VerifyAndClearExpectations(&mock_context
);
2803 // Damage a portion of the frame.
2804 host_impl_
->active_tree()->root_layer()->set_update_rect(
2805 gfx::Rect(0, 0, 2, 3));
2807 // The second frame will be partially-swapped (the y coordinates are flipped).
2808 harness
.MustSetScissor(0, 7, 2, 3);
2809 harness
.MustDrawSolidQuad();
2811 LayerTreeHostImpl::FrameData frame
;
2812 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2813 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2814 host_impl_
->DidDrawAllLayers(frame
);
2816 Mock::VerifyAndClearExpectations(&mock_context
);
2819 class PartialSwapContext
: public TestWebGraphicsContext3D
{
2821 virtual WebKit::WebString
getString(WebKit::WGC3Denum name
) OVERRIDE
{
2822 if (name
== GL_EXTENSIONS
)
2823 return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
2824 return WebKit::WebString();
2827 virtual WebKit::WebString
getRequestableExtensionsCHROMIUM() OVERRIDE
{
2828 return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
2831 // Unlimited texture size.
2832 virtual void getIntegerv(WebKit::WGC3Denum pname
, WebKit::WGC3Dint
* value
)
2834 if (pname
== GL_MAX_TEXTURE_SIZE
)
2839 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
2841 LayerTreeHostImplClient
* client
,
2843 RenderingStatsInstrumentation
* stats_instrumentation
) {
2844 scoped_ptr
<OutputSurface
> output_surface
=
2845 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
2846 new PartialSwapContext
)).PassAs
<OutputSurface
>();
2848 LayerTreeSettings settings
;
2849 settings
.partial_swap_enabled
= partial_swap
;
2850 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
2851 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
);
2852 my_host_impl
->InitializeRenderer(output_surface
.Pass());
2853 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
2856 Layers are created as follows:
2858 +--------------------+
2862 | | +-------------------+
2864 | | +-------------------+
2869 +--------------------+
2871 Layers 1, 2 have render surfaces
2873 scoped_ptr
<LayerImpl
> root
=
2874 LayerImpl::Create(my_host_impl
->active_tree(), 1);
2875 scoped_ptr
<LayerImpl
> child
=
2876 LayerImpl::Create(my_host_impl
->active_tree(), 2);
2877 scoped_ptr
<LayerImpl
> grand_child
=
2878 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
2880 gfx::Rect
root_rect(0, 0, 100, 100);
2881 gfx::Rect
child_rect(10, 10, 50, 50);
2882 gfx::Rect
grand_child_rect(5, 5, 150, 150);
2884 root
->CreateRenderSurface();
2885 root
->SetAnchorPoint(gfx::PointF());
2886 root
->SetPosition(root_rect
.origin());
2887 root
->SetBounds(root_rect
.size());
2888 root
->SetContentBounds(root
->bounds());
2889 root
->draw_properties().visible_content_rect
= root_rect
;
2890 root
->SetDrawsContent(false);
2891 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
2893 child
->SetAnchorPoint(gfx::PointF());
2894 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
2895 child
->SetOpacity(0.5f
);
2896 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
2897 child
->SetContentBounds(child
->bounds());
2898 child
->draw_properties().visible_content_rect
= child_rect
;
2899 child
->SetDrawsContent(false);
2900 child
->SetForceRenderSurface(true);
2902 grand_child
->SetAnchorPoint(gfx::PointF());
2903 grand_child
->SetPosition(grand_child_rect
.origin());
2904 grand_child
->SetBounds(grand_child_rect
.size());
2905 grand_child
->SetContentBounds(grand_child
->bounds());
2906 grand_child
->draw_properties().visible_content_rect
= grand_child_rect
;
2907 grand_child
->SetDrawsContent(true);
2909 child
->AddChild(grand_child
.Pass());
2910 root
->AddChild(child
.Pass());
2912 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
2913 return my_host_impl
.Pass();
2916 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
2917 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
2918 SetupLayersForOpacity(true, this, &proxy_
, &stats_instrumentation_
);
2920 LayerTreeHostImpl::FrameData frame
;
2921 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2923 // Verify all quads have been computed
2924 ASSERT_EQ(2U, frame
.render_passes
.size());
2925 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
2926 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
2927 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
2928 frame
.render_passes
[0]->quad_list
[0]->material
);
2929 EXPECT_EQ(DrawQuad::RENDER_PASS
,
2930 frame
.render_passes
[1]->quad_list
[0]->material
);
2932 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2933 my_host_impl
->DidDrawAllLayers(frame
);
2937 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
2938 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
2939 SetupLayersForOpacity(false, this, &proxy_
, &stats_instrumentation_
);
2941 LayerTreeHostImpl::FrameData frame
;
2942 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2944 // Verify all quads have been computed
2945 ASSERT_EQ(2U, frame
.render_passes
.size());
2946 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
2947 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
2948 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
2949 frame
.render_passes
[0]->quad_list
[0]->material
);
2950 EXPECT_EQ(DrawQuad::RENDER_PASS
,
2951 frame
.render_passes
[1]->quad_list
[0]->material
);
2953 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2954 my_host_impl
->DidDrawAllLayers(frame
);
2958 // Fake WebKit::WebGraphicsContext3D that tracks the number of textures in use.
2959 class TrackingWebGraphicsContext3D
: public TestWebGraphicsContext3D
{
2961 TrackingWebGraphicsContext3D()
2962 : TestWebGraphicsContext3D(),
2965 virtual WebKit::WebGLId
createTexture() OVERRIDE
{
2966 WebKit::WebGLId id
= TestWebGraphicsContext3D::createTexture();
2968 textures_
[id
] = true;
2973 virtual void deleteTexture(WebKit::WebGLId id
) OVERRIDE
{
2974 if (textures_
.find(id
) == textures_
.end())
2977 textures_
[id
] = false;
2981 virtual WebKit::WebString
getString(WebKit::WGC3Denum name
) OVERRIDE
{
2982 if (name
== GL_EXTENSIONS
) {
2983 return WebKit::WebString(
2984 "GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2987 return WebKit::WebString();
2990 unsigned num_textures() const { return num_textures_
; }
2993 base::hash_map
<WebKit::WebGLId
, bool> textures_
;
2994 unsigned num_textures_
;
2997 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
2998 scoped_ptr
<TestWebGraphicsContext3D
> context
=
2999 TestWebGraphicsContext3D::Create();
3000 TestWebGraphicsContext3D
* context3d
= context
.get();
3001 scoped_ptr
<OutputSurface
> output_surface
= FakeOutputSurface::Create3d(
3002 context
.PassAs
<WebKit::WebGraphicsContext3D
>()).PassAs
<OutputSurface
>();
3003 host_impl_
->InitializeRenderer(output_surface
.Pass());
3005 scoped_ptr
<LayerImpl
> root_layer
=
3006 LayerImpl::Create(host_impl_
->active_tree(), 1);
3007 root_layer
->SetBounds(gfx::Size(10, 10));
3008 root_layer
->SetAnchorPoint(gfx::PointF());
3010 scoped_refptr
<VideoFrame
> softwareFrame
=
3011 media::VideoFrame::CreateColorFrame(
3012 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
3013 FakeVideoFrameProvider provider
;
3014 provider
.set_frame(softwareFrame
);
3015 scoped_ptr
<VideoLayerImpl
> video_layer
=
3016 VideoLayerImpl::Create(host_impl_
->active_tree(), 4, &provider
);
3017 video_layer
->SetBounds(gfx::Size(10, 10));
3018 video_layer
->SetAnchorPoint(gfx::PointF());
3019 video_layer
->SetContentBounds(gfx::Size(10, 10));
3020 video_layer
->SetDrawsContent(true);
3021 root_layer
->AddChild(video_layer
.PassAs
<LayerImpl
>());
3023 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
3024 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
3025 io_surface_layer
->SetBounds(gfx::Size(10, 10));
3026 io_surface_layer
->SetAnchorPoint(gfx::PointF());
3027 io_surface_layer
->SetContentBounds(gfx::Size(10, 10));
3028 io_surface_layer
->SetDrawsContent(true);
3029 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
3030 root_layer
->AddChild(io_surface_layer
.PassAs
<LayerImpl
>());
3032 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
3034 EXPECT_EQ(0u, context3d
->NumTextures());
3036 LayerTreeHostImpl::FrameData frame
;
3037 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
3038 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
3039 host_impl_
->DidDrawAllLayers(frame
);
3040 host_impl_
->SwapBuffers(frame
);
3042 EXPECT_GT(context3d
->NumTextures(), 0u);
3044 // Kill the layer tree.
3045 host_impl_
->active_tree()->SetRootLayer(
3046 LayerImpl::Create(host_impl_
->active_tree(), 100));
3047 // There should be no textures left in use after.
3048 EXPECT_EQ(0u, context3d
->NumTextures());
3051 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
3053 MOCK_METHOD1(useProgram
, void(WebKit::WebGLId program
));
3054 MOCK_METHOD4(drawElements
, void(WebKit::WGC3Denum mode
,
3055 WebKit::WGC3Dsizei count
,
3056 WebKit::WGC3Denum type
,
3057 WebKit::WGC3Dintptr offset
));
3060 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
3061 scoped_ptr
<OutputSurface
> output_surface
=
3062 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3063 new MockDrawQuadsToFillScreenContext
)).PassAs
<OutputSurface
>();
3064 MockDrawQuadsToFillScreenContext
* mock_context
=
3065 static_cast<MockDrawQuadsToFillScreenContext
*>(
3066 output_surface
->context3d());
3069 CreateLayerTreeHost(false, output_surface
.Pass());
3070 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
3071 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
3073 // Verify one quad is drawn when transparent background set is not set.
3074 host_impl_
->active_tree()->set_has_transparent_background(false);
3075 EXPECT_CALL(*mock_context
, useProgram(_
))
3077 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
3079 LayerTreeHostImpl::FrameData frame
;
3080 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
3081 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
3082 host_impl_
->DidDrawAllLayers(frame
);
3083 Mock::VerifyAndClearExpectations(&mock_context
);
3085 // Verify no quads are drawn when transparent background is set.
3086 host_impl_
->active_tree()->set_has_transparent_background(true);
3087 host_impl_
->SetFullRootLayerDamage();
3088 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
3089 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
3090 host_impl_
->DidDrawAllLayers(frame
);
3091 Mock::VerifyAndClearExpectations(&mock_context
);
3094 static void AddDrawingLayerTo(LayerImpl
* parent
,
3096 gfx::Rect layer_rect
,
3097 LayerImpl
** result
) {
3098 scoped_ptr
<LayerImpl
> layer
=
3099 FakeLayerWithQuads::Create(parent
->layer_tree_impl(), id
);
3100 LayerImpl
* layer_ptr
= layer
.get();
3101 layer_ptr
->SetAnchorPoint(gfx::PointF());
3102 layer_ptr
->SetPosition(gfx::PointF(layer_rect
.origin()));
3103 layer_ptr
->SetBounds(layer_rect
.size());
3104 layer_ptr
->SetContentBounds(layer_rect
.size());
3105 layer_ptr
->SetDrawsContent(true); // only children draw content
3106 layer_ptr
->SetContentsOpaque(true);
3107 parent
->AddChild(layer
.Pass());
3109 *result
= layer_ptr
;
3112 static void SetupLayersForTextureCaching(
3113 LayerTreeHostImpl
* layer_tree_host_impl
,
3114 LayerImpl
*& root_ptr
,
3115 LayerImpl
*& intermediate_layer_ptr
,
3116 LayerImpl
*& surface_layer_ptr
,
3117 LayerImpl
*& child_ptr
,
3118 gfx::Size root_size
) {
3119 scoped_ptr
<OutputSurface
> output_surface
=
3120 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3121 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3123 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
3124 layer_tree_host_impl
->SetViewportSize(root_size
);
3126 scoped_ptr
<LayerImpl
> root
=
3127 LayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
3128 root_ptr
= root
.get();
3130 root
->SetAnchorPoint(gfx::PointF());
3131 root
->SetPosition(gfx::PointF());
3132 root
->SetBounds(root_size
);
3133 root
->SetContentBounds(root_size
);
3134 root
->SetDrawsContent(true);
3135 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3137 AddDrawingLayerTo(root_ptr
,
3139 gfx::Rect(10, 10, root_size
.width(), root_size
.height()),
3140 &intermediate_layer_ptr
);
3141 // Only children draw content.
3142 intermediate_layer_ptr
->SetDrawsContent(false);
3144 // Surface layer is the layer that changes its opacity
3145 // It will contain other layers that draw content.
3146 AddDrawingLayerTo(intermediate_layer_ptr
,
3148 gfx::Rect(10, 10, root_size
.width(), root_size
.height()),
3149 &surface_layer_ptr
);
3150 // Only children draw content.
3151 surface_layer_ptr
->SetDrawsContent(false);
3152 surface_layer_ptr
->SetOpacity(0.5f
);
3153 surface_layer_ptr
->SetForceRenderSurface(true);
3155 // Child of the surface layer will produce some quads
3156 AddDrawingLayerTo(surface_layer_ptr
,
3160 root_size
.width() - 25,
3161 root_size
.height() - 25),
3165 class GLRendererWithReleaseTextures
: public GLRenderer
{
3167 using GLRenderer::ReleaseRenderPassTextures
;
3170 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusion
) {
3171 LayerTreeSettings settings
;
3172 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3173 settings
.cache_render_pass_contents
= true;
3174 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3175 LayerTreeHostImpl::Create(settings
,
3178 &stats_instrumentation_
);
3180 // Layers are structure as follows:
3182 // R +-- S1 +- L10 (owning)
3186 // +-- S2 +- L20 (owning)
3190 // L12 occludes L11 (internal)
3191 // L20 occludes L10 (external)
3192 // L21 occludes L20 (internal)
3194 LayerImpl
* root_ptr
;
3195 LayerImpl
* layer_s1_ptr
;
3196 LayerImpl
* layer_s2_ptr
;
3198 scoped_ptr
<OutputSurface
> output_surface
=
3199 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3200 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3202 gfx::Size
root_size(1000, 1000);
3204 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3205 my_host_impl
->SetViewportSize(root_size
);
3207 scoped_ptr
<LayerImpl
> root
=
3208 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3209 root_ptr
= root
.get();
3211 root
->SetAnchorPoint(gfx::PointF());
3212 root
->SetPosition(gfx::PointF());
3213 root
->SetBounds(root_size
);
3214 root
->SetContentBounds(root_size
);
3215 root
->SetDrawsContent(true);
3216 root
->SetMasksToBounds(true);
3217 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3219 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr
);
3220 layer_s1_ptr
->SetForceRenderSurface(true);
3222 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(10, 10, 10, 10), 0); // L11
3223 AddDrawingLayerTo(layer_s1_ptr
, 4, gfx::Rect(0, 0, 30, 30), 0); // L12
3225 AddDrawingLayerTo(root_ptr
, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr
);
3226 layer_s2_ptr
->SetForceRenderSurface(true);
3228 AddDrawingLayerTo(layer_s2_ptr
, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
3230 // Initial draw - must receive all quads
3232 LayerTreeHostImpl::FrameData frame
;
3233 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3235 // Must receive 3 render passes.
3236 // For Root, there are 2 quads; for S1, there are 2 quads (1 is occluded);
3237 // for S2, there is 2 quads.
3238 ASSERT_EQ(3U, frame
.render_passes
.size());
3240 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3241 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3242 EXPECT_EQ(2U, frame
.render_passes
[2]->quad_list
.size());
3244 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3245 my_host_impl
->DidDrawAllLayers(frame
);
3248 // "Unocclude" surface S1 and repeat draw.
3249 // Must remove S2's render pass since it's cached;
3250 // Must keep S1 quads because texture contained external occlusion.
3251 gfx::Transform transform
= layer_s2_ptr
->transform();
3252 transform
.Translate(150.0, 150.0);
3253 layer_s2_ptr
->SetTransform(transform
);
3255 LayerTreeHostImpl::FrameData frame
;
3256 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3258 // Must receive 2 render passes.
3259 // For Root, there are 2 quads
3260 // For S1, the number of quads depends on what got unoccluded, so not
3261 // asserted beyond being positive.
3262 // For S2, there is no render pass
3263 ASSERT_EQ(2U, frame
.render_passes
.size());
3265 EXPECT_GT(frame
.render_passes
[0]->quad_list
.size(), 0U);
3266 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3268 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3269 my_host_impl
->DidDrawAllLayers(frame
);
3272 // "Re-occlude" surface S1 and repeat draw.
3273 // Must remove S1's render pass since it is now available in full.
3274 // S2 has no change so must also be removed.
3275 transform
= layer_s2_ptr
->transform();
3276 transform
.Translate(-15.0, -15.0);
3277 layer_s2_ptr
->SetTransform(transform
);
3279 LayerTreeHostImpl::FrameData frame
;
3280 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3282 // Must receive 1 render pass - for the root.
3283 ASSERT_EQ(1U, frame
.render_passes
.size());
3285 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3287 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3288 my_host_impl
->DidDrawAllLayers(frame
);
3292 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusionEarlyOut
) {
3293 LayerTreeSettings settings
;
3294 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3295 settings
.cache_render_pass_contents
= true;
3296 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3297 LayerTreeHostImpl::Create(settings
,
3300 &stats_instrumentation_
);
3302 // Layers are structure as follows:
3304 // R +-- S1 +- L10 (owning, non drawing)
3305 // | +- L11 (corner, unoccluded)
3306 // | +- L12 (corner, unoccluded)
3307 // | +- L13 (corner, unoccluded)
3308 // | +- L14 (corner, entirely occluded)
3310 // +-- S2 +- L20 (owning, drawing)
3313 LayerImpl
* root_ptr
;
3314 LayerImpl
* layer_s1_ptr
;
3315 LayerImpl
* layer_s2_ptr
;
3317 scoped_ptr
<OutputSurface
> output_surface
=
3318 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3319 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3321 gfx::Size
root_size(1000, 1000);
3323 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3324 my_host_impl
->SetViewportSize(root_size
);
3326 scoped_ptr
<LayerImpl
> root
=
3327 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3328 root_ptr
= root
.get();
3330 root
->SetAnchorPoint(gfx::PointF());
3331 root
->SetPosition(gfx::PointF());
3332 root
->SetBounds(root_size
);
3333 root
->SetContentBounds(root_size
);
3334 root
->SetDrawsContent(true);
3335 root
->SetMasksToBounds(true);
3336 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3338 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(0, 0, 800, 800), &layer_s1_ptr
);
3339 layer_s1_ptr
->SetForceRenderSurface(true);
3340 layer_s1_ptr
->SetDrawsContent(false);
3342 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(0, 0, 300, 300), 0); // L11
3343 AddDrawingLayerTo(layer_s1_ptr
, 4, gfx::Rect(0, 500, 300, 300), 0); // L12
3344 AddDrawingLayerTo(layer_s1_ptr
, 5, gfx::Rect(500, 0, 300, 300), 0); // L13
3345 AddDrawingLayerTo(layer_s1_ptr
, 6, gfx::Rect(500, 500, 300, 300), 0); // L14
3346 AddDrawingLayerTo(layer_s1_ptr
, 9, gfx::Rect(500, 500, 300, 300), 0); // L14
3348 AddDrawingLayerTo(root_ptr
, 7, gfx::Rect(450, 450, 450, 450), &layer_s2_ptr
);
3349 layer_s2_ptr
->SetForceRenderSurface(true);
3351 // Initial draw - must receive all quads
3353 LayerTreeHostImpl::FrameData frame
;
3354 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3356 // Must receive 3 render passes.
3357 // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
3359 ASSERT_EQ(3U, frame
.render_passes
.size());
3361 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3363 // L14 is culled, so only 3 quads.
3364 EXPECT_EQ(3U, frame
.render_passes
[1]->quad_list
.size());
3365 EXPECT_EQ(2U, frame
.render_passes
[2]->quad_list
.size());
3367 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3368 my_host_impl
->DidDrawAllLayers(frame
);
3371 // "Unocclude" surface S1 and repeat draw.
3372 // Must remove S2's render pass since it's cached;
3373 // Must keep S1 quads because texture contained external occlusion.
3374 gfx::Transform transform
= layer_s2_ptr
->transform();
3375 transform
.Translate(100.0, 100.0);
3376 layer_s2_ptr
->SetTransform(transform
);
3378 LayerTreeHostImpl::FrameData frame
;
3379 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3381 // Must receive 2 render passes.
3382 // For Root, there are 2 quads
3383 // For S1, the number of quads depends on what got unoccluded, so not
3384 // asserted beyond being positive.
3385 // For S2, there is no render pass
3386 ASSERT_EQ(2U, frame
.render_passes
.size());
3388 EXPECT_GT(frame
.render_passes
[0]->quad_list
.size(), 0U);
3389 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3391 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3392 my_host_impl
->DidDrawAllLayers(frame
);
3395 // "Re-occlude" surface S1 and repeat draw.
3396 // Must remove S1's render pass since it is now available in full.
3397 // S2 has no change so must also be removed.
3398 transform
= layer_s2_ptr
->transform();
3399 transform
.Translate(-15.0, -15.0);
3400 layer_s2_ptr
->SetTransform(transform
);
3402 LayerTreeHostImpl::FrameData frame
;
3403 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3405 // Must receive 1 render pass - for the root.
3406 ASSERT_EQ(1U, frame
.render_passes
.size());
3408 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3410 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3411 my_host_impl
->DidDrawAllLayers(frame
);
3415 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusionExternalOverInternal
) {
3416 LayerTreeSettings settings
;
3417 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3418 settings
.cache_render_pass_contents
= true;
3419 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3420 LayerTreeHostImpl::Create(settings
,
3423 &stats_instrumentation_
);
3425 // Layers are structured as follows:
3427 // R +-- S1 +- L10 (owning, drawing)
3428 // | +- L11 (corner, occluded by L12)
3429 // | +- L12 (opposite corner)
3431 // +-- S2 +- L20 (owning, drawing)
3434 LayerImpl
* root_ptr
;
3435 LayerImpl
* layer_s1_ptr
;
3436 LayerImpl
* layer_s2_ptr
;
3438 scoped_ptr
<OutputSurface
> output_surface
=
3439 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3440 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3442 gfx::Size
root_size(1000, 1000);
3444 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3445 my_host_impl
->SetViewportSize(root_size
);
3447 scoped_ptr
<LayerImpl
> root
=
3448 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3449 root_ptr
= root
.get();
3451 root
->SetAnchorPoint(gfx::PointF());
3452 root
->SetPosition(gfx::PointF());
3453 root
->SetBounds(root_size
);
3454 root
->SetContentBounds(root_size
);
3455 root
->SetDrawsContent(true);
3456 root
->SetMasksToBounds(true);
3457 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3459 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr
);
3460 layer_s1_ptr
->SetForceRenderSurface(true);
3462 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(0, 0, 300, 300), 0); // L11
3463 AddDrawingLayerTo(layer_s1_ptr
, 4, gfx::Rect(100, 0, 300, 300), 0); // L12
3465 AddDrawingLayerTo(root_ptr
, 7, gfx::Rect(200, 0, 300, 300), &layer_s2_ptr
);
3466 layer_s2_ptr
->SetForceRenderSurface(true);
3468 // Initial draw - must receive all quads
3470 LayerTreeHostImpl::FrameData frame
;
3471 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3473 // Must receive 3 render passes.
3474 // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
3476 ASSERT_EQ(3U, frame
.render_passes
.size());
3478 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3479 EXPECT_EQ(3U, frame
.render_passes
[1]->quad_list
.size());
3480 EXPECT_EQ(2U, frame
.render_passes
[2]->quad_list
.size());
3482 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3483 my_host_impl
->DidDrawAllLayers(frame
);
3486 // "Unocclude" surface S1 and repeat draw.
3487 // Must remove S2's render pass since it's cached;
3488 // Must keep S1 quads because texture contained external occlusion.
3489 gfx::Transform transform
= layer_s2_ptr
->transform();
3490 transform
.Translate(300.0, 0.0);
3491 layer_s2_ptr
->SetTransform(transform
);
3493 LayerTreeHostImpl::FrameData frame
;
3494 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3496 // Must receive 2 render passes.
3497 // For Root, there are 2 quads
3498 // For S1, the number of quads depends on what got unoccluded, so not
3499 // asserted beyond being positive.
3500 // For S2, there is no render pass
3501 ASSERT_EQ(2U, frame
.render_passes
.size());
3503 EXPECT_GT(frame
.render_passes
[0]->quad_list
.size(), 0U);
3504 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3506 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3507 my_host_impl
->DidDrawAllLayers(frame
);
3511 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusionExternalNotAligned
) {
3512 LayerTreeSettings settings
;
3513 settings
.cache_render_pass_contents
= true;
3514 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3515 LayerTreeHostImpl::Create(settings
,
3518 &stats_instrumentation_
);
3520 // Layers are structured as follows:
3522 // R +-- S1 +- L10 (rotated, drawing)
3523 // +- L11 (occupies half surface)
3525 LayerImpl
* root_ptr
;
3526 LayerImpl
* layer_s1_ptr
;
3528 scoped_ptr
<OutputSurface
> output_surface
=
3529 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3530 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3532 gfx::Size
root_size(1000, 1000);
3534 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3535 my_host_impl
->SetViewportSize(root_size
);
3537 scoped_ptr
<LayerImpl
> root
=
3538 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3539 root_ptr
= root
.get();
3541 root
->SetAnchorPoint(gfx::PointF());
3542 root
->SetPosition(gfx::PointF());
3543 root
->SetBounds(root_size
);
3544 root
->SetContentBounds(root_size
);
3545 root
->SetDrawsContent(true);
3546 root
->SetMasksToBounds(true);
3547 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3549 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr
);
3550 layer_s1_ptr
->SetForceRenderSurface(true);
3551 gfx::Transform transform
= layer_s1_ptr
->transform();
3552 transform
.Translate(200.0, 200.0);
3553 transform
.Rotate(45.0);
3554 transform
.Translate(-200.0, -200.0);
3555 layer_s1_ptr
->SetTransform(transform
);
3557 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(200, 0, 200, 400), 0); // L11
3559 // Initial draw - must receive all quads
3561 LayerTreeHostImpl::FrameData frame
;
3562 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3564 // Must receive 2 render passes.
3565 ASSERT_EQ(2U, frame
.render_passes
.size());
3567 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3568 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
3570 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3571 my_host_impl
->DidDrawAllLayers(frame
);
3574 // Change opacity and draw. Verify we used cached texture.
3575 layer_s1_ptr
->SetOpacity(0.2f
);
3577 LayerTreeHostImpl::FrameData frame
;
3578 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3580 // One render pass must be gone due to cached texture.
3581 ASSERT_EQ(1U, frame
.render_passes
.size());
3583 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3585 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3586 my_host_impl
->DidDrawAllLayers(frame
);
3590 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusionPartialSwap
) {
3591 LayerTreeSettings settings
;
3592 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3593 settings
.partial_swap_enabled
= true;
3594 settings
.cache_render_pass_contents
= true;
3595 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3596 LayerTreeHostImpl::Create(settings
,
3599 &stats_instrumentation_
);
3601 // Layers are structure as follows:
3603 // R +-- S1 +- L10 (owning)
3607 // +-- S2 +- L20 (owning)
3611 // L12 occludes L11 (internal)
3612 // L20 occludes L10 (external)
3613 // L21 occludes L20 (internal)
3615 LayerImpl
* root_ptr
;
3616 LayerImpl
* layer_s1_ptr
;
3617 LayerImpl
* layer_s2_ptr
;
3619 scoped_ptr
<OutputSurface
> output_surface
=
3620 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3621 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3623 gfx::Size
root_size(1000, 1000);
3625 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3626 my_host_impl
->SetViewportSize(root_size
);
3628 scoped_ptr
<LayerImpl
> root
=
3629 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3630 root_ptr
= root
.get();
3632 root
->SetAnchorPoint(gfx::PointF());
3633 root
->SetPosition(gfx::PointF());
3634 root
->SetBounds(root_size
);
3635 root
->SetContentBounds(root_size
);
3636 root
->SetDrawsContent(true);
3637 root
->SetMasksToBounds(true);
3638 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3640 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr
);
3641 layer_s1_ptr
->SetForceRenderSurface(true);
3643 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(10, 10, 10, 10), 0); // L11
3644 AddDrawingLayerTo(layer_s1_ptr
, 4, gfx::Rect(0, 0, 30, 30), 0); // L12
3646 AddDrawingLayerTo(root_ptr
, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr
);
3647 layer_s2_ptr
->SetForceRenderSurface(true);
3649 AddDrawingLayerTo(layer_s2_ptr
, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
3651 // Initial draw - must receive all quads
3653 LayerTreeHostImpl::FrameData frame
;
3654 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3656 // Must receive 3 render passes.
3657 // For Root, there are 2 quads; for S1, there are 2 quads (one is occluded);
3658 // for S2, there is 2 quads.
3659 ASSERT_EQ(3U, frame
.render_passes
.size());
3661 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3662 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3663 EXPECT_EQ(2U, frame
.render_passes
[2]->quad_list
.size());
3665 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3666 my_host_impl
->DidDrawAllLayers(frame
);
3669 // "Unocclude" surface S1 and repeat draw.
3670 // Must remove S2's render pass since it's cached;
3671 // Must keep S1 quads because texture contained external occlusion.
3672 gfx::Transform transform
= layer_s2_ptr
->transform();
3673 transform
.Translate(150.0, 150.0);
3674 layer_s2_ptr
->SetTransform(transform
);
3676 LayerTreeHostImpl::FrameData frame
;
3677 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3679 // Must receive 2 render passes.
3680 // For Root, there are 2 quads.
3681 // For S1, there are 2 quads.
3682 // For S2, there is no render pass
3683 ASSERT_EQ(2U, frame
.render_passes
.size());
3685 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3686 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3688 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3689 my_host_impl
->DidDrawAllLayers(frame
);
3692 // "Re-occlude" surface S1 and repeat draw.
3693 // Must remove S1's render pass since it is now available in full.
3694 // S2 has no change so must also be removed.
3695 transform
= layer_s2_ptr
->transform();
3696 transform
.Translate(-15.0, -15.0);
3697 layer_s2_ptr
->SetTransform(transform
);
3699 LayerTreeHostImpl::FrameData frame
;
3700 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3702 // Root render pass only.
3703 ASSERT_EQ(1U, frame
.render_passes
.size());
3705 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3706 my_host_impl
->DidDrawAllLayers(frame
);
3710 TEST_F(LayerTreeHostImplTest
, TextureCachingWithScissor
) {
3711 LayerTreeSettings settings
;
3712 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3713 settings
.cache_render_pass_contents
= true;
3714 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3715 LayerTreeHostImpl::Create(settings
,
3718 &stats_instrumentation_
);
3721 Layers are created as follows:
3723 +--------------------+
3727 | | +-------------------+
3729 | | +-------------------+
3734 +--------------------+
3736 Layers 1, 2 have render surfaces
3738 scoped_ptr
<LayerImpl
> root
=
3739 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3740 scoped_ptr
<TiledLayerImpl
> child
=
3741 TiledLayerImpl::Create(my_host_impl
->active_tree(), 2);
3742 scoped_ptr
<LayerImpl
> grand_child
=
3743 LayerImpl::Create(my_host_impl
->active_tree(), 3);
3745 gfx::Rect
root_rect(0, 0, 100, 100);
3746 gfx::Rect
child_rect(10, 10, 50, 50);
3747 gfx::Rect
grand_child_rect(5, 5, 150, 150);
3749 scoped_ptr
<OutputSurface
> output_surface
=
3750 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3751 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3752 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3754 root
->SetAnchorPoint(gfx::PointF());
3755 root
->SetPosition(gfx::PointF(root_rect
.x(), root_rect
.y()));
3756 root
->SetBounds(gfx::Size(root_rect
.width(), root_rect
.height()));
3757 root
->SetContentBounds(root
->bounds());
3758 root
->SetDrawsContent(true);
3759 root
->SetMasksToBounds(true);
3761 child
->SetAnchorPoint(gfx::PointF());
3762 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
3763 child
->SetOpacity(0.5f
);
3764 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
3765 child
->SetContentBounds(child
->bounds());
3766 child
->SetDrawsContent(true);
3767 child
->set_skips_draw(false);
3769 // child layer has 10x10 tiles.
3770 scoped_ptr
<LayerTilingData
> tiler
=
3771 LayerTilingData::Create(gfx::Size(10, 10),
3772 LayerTilingData::HAS_BORDER_TEXELS
);
3773 tiler
->SetBounds(child
->content_bounds());
3774 child
->SetTilingData(*tiler
.get());
3776 grand_child
->SetAnchorPoint(gfx::PointF());
3777 grand_child
->SetPosition(grand_child_rect
.origin());
3778 grand_child
->SetBounds(grand_child_rect
.size());
3779 grand_child
->SetContentBounds(grand_child
->bounds());
3780 grand_child
->SetDrawsContent(true);
3782 TiledLayerImpl
* child_ptr
= child
.get();
3783 RenderPass::Id
child_pass_id(child_ptr
->id(), 0);
3785 child
->AddChild(grand_child
.Pass());
3786 root
->AddChild(child
.PassAs
<LayerImpl
>());
3787 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3788 my_host_impl
->SetViewportSize(root_rect
.size());
3790 EXPECT_FALSE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3793 LayerTreeHostImpl::FrameData frame
;
3794 host_impl_
->SetFullRootLayerDamage();
3795 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3796 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3797 my_host_impl
->DidDrawAllLayers(frame
);
3800 // We should have cached textures for surface 2.
3801 EXPECT_TRUE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3804 LayerTreeHostImpl::FrameData frame
;
3805 host_impl_
->SetFullRootLayerDamage();
3806 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3807 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3808 my_host_impl
->DidDrawAllLayers(frame
);
3811 // We should still have cached textures for surface 2 after drawing with no
3813 EXPECT_TRUE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3816 // Damage a single tile of surface 2.
3817 child_ptr
->set_update_rect(gfx::Rect(10, 10, 10, 10));
3819 LayerTreeHostImpl::FrameData frame
;
3820 host_impl_
->SetFullRootLayerDamage();
3821 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3822 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3823 my_host_impl
->DidDrawAllLayers(frame
);
3826 // We should have a cached texture for surface 2 again even though it was
3828 EXPECT_TRUE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3832 TEST_F(LayerTreeHostImplTest
, SurfaceTextureCaching
) {
3833 LayerTreeSettings settings
;
3834 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3835 settings
.partial_swap_enabled
= true;
3836 settings
.cache_render_pass_contents
= true;
3837 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3838 LayerTreeHostImpl::Create(settings
,
3841 &stats_instrumentation_
);
3843 LayerImpl
* root_ptr
;
3844 LayerImpl
* intermediate_layer_ptr
;
3845 LayerImpl
* surface_layer_ptr
;
3846 LayerImpl
* child_ptr
;
3848 SetupLayersForTextureCaching(my_host_impl
.get(),
3850 intermediate_layer_ptr
,
3853 gfx::Size(100, 100));
3855 LayerTreeHostImpl::FrameData frame
;
3856 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3858 // Must receive two render passes, each with one quad
3859 ASSERT_EQ(2U, frame
.render_passes
.size());
3860 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3861 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
3863 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3864 frame
.render_passes
[1]->quad_list
[0]->material
);
3865 const RenderPassDrawQuad
* quad
=
3866 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
3867 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
3868 ASSERT_TRUE(target_pass
);
3869 EXPECT_FALSE(target_pass
->damage_rect
.IsEmpty());
3871 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3872 my_host_impl
->DidDrawAllLayers(frame
);
3875 // Draw without any change
3877 LayerTreeHostImpl::FrameData frame
;
3878 my_host_impl
->SetFullRootLayerDamage();
3879 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3881 // Must receive one render pass, as the other one should be culled
3882 ASSERT_EQ(1U, frame
.render_passes
.size());
3884 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3885 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3886 frame
.render_passes
[0]->quad_list
[0]->material
);
3887 const RenderPassDrawQuad
* quad
=
3888 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
3889 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
3890 frame
.render_passes_by_id
.end());
3892 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3893 my_host_impl
->DidDrawAllLayers(frame
);
3896 // Change opacity and draw
3897 surface_layer_ptr
->SetOpacity(0.6f
);
3899 LayerTreeHostImpl::FrameData frame
;
3900 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3902 // Must receive one render pass, as the other one should be culled
3903 ASSERT_EQ(1U, frame
.render_passes
.size());
3905 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3906 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3907 frame
.render_passes
[0]->quad_list
[0]->material
);
3908 const RenderPassDrawQuad
* quad
=
3909 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
3910 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
3911 frame
.render_passes_by_id
.end());
3913 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3914 my_host_impl
->DidDrawAllLayers(frame
);
3917 // Change less benign property and draw - should have contents changed flag
3918 surface_layer_ptr
->SetStackingOrderChanged(true);
3920 LayerTreeHostImpl::FrameData frame
;
3921 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3923 // Must receive two render passes, each with one quad
3924 ASSERT_EQ(2U, frame
.render_passes
.size());
3926 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3927 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
3928 frame
.render_passes
[0]->quad_list
[0]->material
);
3930 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3931 frame
.render_passes
[1]->quad_list
[0]->material
);
3932 const RenderPassDrawQuad
* quad
=
3933 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
3934 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
3935 ASSERT_TRUE(target_pass
);
3936 EXPECT_FALSE(target_pass
->damage_rect
.IsEmpty());
3938 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3939 my_host_impl
->DidDrawAllLayers(frame
);
3942 // Change opacity again, and evict the cached surface texture.
3943 surface_layer_ptr
->SetOpacity(0.5f
);
3944 static_cast<GLRendererWithReleaseTextures
*>(
3945 my_host_impl
->renderer())->ReleaseRenderPassTextures();
3947 // Change opacity and draw
3948 surface_layer_ptr
->SetOpacity(0.6f
);
3950 LayerTreeHostImpl::FrameData frame
;
3951 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3953 // Must receive two render passes
3954 ASSERT_EQ(2U, frame
.render_passes
.size());
3956 // Even though not enough properties changed, the entire thing must be
3957 // redrawn as we don't have cached textures
3958 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3959 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
3961 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3962 frame
.render_passes
[1]->quad_list
[0]->material
);
3963 const RenderPassDrawQuad
* quad
=
3964 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
3965 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
3966 ASSERT_TRUE(target_pass
);
3967 EXPECT_TRUE(target_pass
->damage_rect
.IsEmpty());
3969 // Was our surface evicted?
3970 EXPECT_FALSE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3973 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3974 my_host_impl
->DidDrawAllLayers(frame
);
3977 // Draw without any change, to make sure the state is clear
3979 LayerTreeHostImpl::FrameData frame
;
3980 my_host_impl
->SetFullRootLayerDamage();
3981 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3983 // Must receive one render pass, as the other one should be culled
3984 ASSERT_EQ(1U, frame
.render_passes
.size());
3986 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3987 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3988 frame
.render_passes
[0]->quad_list
[0]->material
);
3989 const RenderPassDrawQuad
* quad
=
3990 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
3991 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
3992 frame
.render_passes_by_id
.end());
3994 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3995 my_host_impl
->DidDrawAllLayers(frame
);
3998 // Change location of the intermediate layer
3999 gfx::Transform transform
= intermediate_layer_ptr
->transform();
4000 transform
.matrix().setDouble(0, 3, 1.0001);
4001 intermediate_layer_ptr
->SetTransform(transform
);
4003 LayerTreeHostImpl::FrameData frame
;
4004 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4006 // Must receive one render pass, as the other one should be culled.
4007 ASSERT_EQ(1U, frame
.render_passes
.size());
4008 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4010 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4011 frame
.render_passes
[0]->quad_list
[0]->material
);
4012 const RenderPassDrawQuad
* quad
=
4013 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4014 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
4015 frame
.render_passes_by_id
.end());
4017 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4018 my_host_impl
->DidDrawAllLayers(frame
);
4022 TEST_F(LayerTreeHostImplTest
, SurfaceTextureCachingNoPartialSwap
) {
4023 LayerTreeSettings settings
;
4024 settings
.minimum_occlusion_tracking_size
= gfx::Size();
4025 settings
.cache_render_pass_contents
= true;
4026 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
4027 LayerTreeHostImpl::Create(settings
,
4030 &stats_instrumentation_
);
4032 LayerImpl
* root_ptr
;
4033 LayerImpl
* intermediate_layer_ptr
;
4034 LayerImpl
* surface_layer_ptr
;
4035 LayerImpl
* child_ptr
;
4037 SetupLayersForTextureCaching(my_host_impl
.get(),
4039 intermediate_layer_ptr
,
4042 gfx::Size(100, 100));
4044 LayerTreeHostImpl::FrameData frame
;
4045 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4047 // Must receive two render passes, each with one quad
4048 ASSERT_EQ(2U, frame
.render_passes
.size());
4049 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4050 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
4052 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4053 frame
.render_passes
[1]->quad_list
[0]->material
);
4054 const RenderPassDrawQuad
* quad
=
4055 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
4056 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
4057 EXPECT_FALSE(target_pass
->damage_rect
.IsEmpty());
4059 EXPECT_FALSE(frame
.render_passes
[0]->damage_rect
.IsEmpty());
4060 EXPECT_FALSE(frame
.render_passes
[1]->damage_rect
.IsEmpty());
4063 frame
.render_passes
[0]->has_occlusion_from_outside_target_surface
);
4065 frame
.render_passes
[1]->has_occlusion_from_outside_target_surface
);
4067 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4068 my_host_impl
->DidDrawAllLayers(frame
);
4071 // Draw without any change
4073 LayerTreeHostImpl::FrameData frame
;
4074 my_host_impl
->SetFullRootLayerDamage();
4075 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4077 // Even though there was no change, we set the damage to entire viewport.
4078 // One of the passes should be culled as a result, since contents didn't
4079 // change and we have cached texture.
4080 ASSERT_EQ(1U, frame
.render_passes
.size());
4081 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4083 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4084 my_host_impl
->DidDrawAllLayers(frame
);
4087 // Change opacity and draw
4088 surface_layer_ptr
->SetOpacity(0.6f
);
4090 LayerTreeHostImpl::FrameData frame
;
4091 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4093 // Must receive one render pass, as the other one should be culled
4094 ASSERT_EQ(1U, frame
.render_passes
.size());
4096 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4097 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4098 frame
.render_passes
[0]->quad_list
[0]->material
);
4099 const RenderPassDrawQuad
* quad
=
4100 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4101 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
4102 frame
.render_passes_by_id
.end());
4104 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4105 my_host_impl
->DidDrawAllLayers(frame
);
4108 // Change less benign property and draw - should have contents changed flag
4109 surface_layer_ptr
->SetStackingOrderChanged(true);
4111 LayerTreeHostImpl::FrameData frame
;
4112 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4114 // Must receive two render passes, each with one quad
4115 ASSERT_EQ(2U, frame
.render_passes
.size());
4117 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4118 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
4119 frame
.render_passes
[0]->quad_list
[0]->material
);
4121 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4122 frame
.render_passes
[1]->quad_list
[0]->material
);
4123 const RenderPassDrawQuad
* quad
=
4124 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
4125 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
4126 ASSERT_TRUE(target_pass
);
4127 EXPECT_FALSE(target_pass
->damage_rect
.IsEmpty());
4129 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4130 my_host_impl
->DidDrawAllLayers(frame
);
4133 // Change opacity again, and evict the cached surface texture.
4134 surface_layer_ptr
->SetOpacity(0.5f
);
4135 static_cast<GLRendererWithReleaseTextures
*>(
4136 my_host_impl
->renderer())->ReleaseRenderPassTextures();
4138 // Change opacity and draw
4139 surface_layer_ptr
->SetOpacity(0.6f
);
4141 LayerTreeHostImpl::FrameData frame
;
4142 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4144 // Must receive two render passes
4145 ASSERT_EQ(2U, frame
.render_passes
.size());
4147 // Even though not enough properties changed, the entire thing must be
4148 // redrawn as we don't have cached textures
4149 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4150 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
4152 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4153 frame
.render_passes
[1]->quad_list
[0]->material
);
4154 const RenderPassDrawQuad
* quad
=
4155 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
4156 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
4157 ASSERT_TRUE(target_pass
);
4158 EXPECT_TRUE(target_pass
->damage_rect
.IsEmpty());
4160 // Was our surface evicted?
4161 EXPECT_FALSE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
4164 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4165 my_host_impl
->DidDrawAllLayers(frame
);
4168 // Draw without any change, to make sure the state is clear
4170 LayerTreeHostImpl::FrameData frame
;
4171 my_host_impl
->SetFullRootLayerDamage();
4172 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4174 // Even though there was no change, we set the damage to entire viewport.
4175 // One of the passes should be culled as a result, since contents didn't
4176 // change and we have cached texture.
4177 ASSERT_EQ(1U, frame
.render_passes
.size());
4178 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4180 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4181 my_host_impl
->DidDrawAllLayers(frame
);
4184 // Change location of the intermediate layer
4185 gfx::Transform transform
= intermediate_layer_ptr
->transform();
4186 transform
.matrix().setDouble(0, 3, 1.0001);
4187 intermediate_layer_ptr
->SetTransform(transform
);
4189 LayerTreeHostImpl::FrameData frame
;
4190 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4192 // Must receive one render pass, as the other one should be culled.
4193 ASSERT_EQ(1U, frame
.render_passes
.size());
4194 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4196 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4197 frame
.render_passes
[0]->quad_list
[0]->material
);
4198 const RenderPassDrawQuad
* quad
=
4199 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4200 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
4201 frame
.render_passes_by_id
.end());
4203 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4204 my_host_impl
->DidDrawAllLayers(frame
);
4208 TEST_F(LayerTreeHostImplTest
, ReleaseContentsTextureShouldTriggerCommit
) {
4209 set_reduce_memory_result(false);
4211 // If changing the memory limit wouldn't result in changing what was
4212 // committed, then no commit should be requested.
4213 set_reduce_memory_result(false);
4214 host_impl_
->set_max_memory_needed_bytes(
4215 host_impl_
->memory_allocation_limit_bytes() - 1);
4216 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
4217 host_impl_
->memory_allocation_limit_bytes() - 1));
4218 EXPECT_FALSE(did_request_commit_
);
4219 did_request_commit_
= false;
4221 // If changing the memory limit would result in changing what was
4222 // committed, then a commit should be requested, even though nothing was
4224 set_reduce_memory_result(false);
4225 host_impl_
->set_max_memory_needed_bytes(
4226 host_impl_
->memory_allocation_limit_bytes());
4227 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
4228 host_impl_
->memory_allocation_limit_bytes() - 1));
4229 EXPECT_TRUE(did_request_commit_
);
4230 did_request_commit_
= false;
4232 // Especially if changing the memory limit caused evictions, we need
4234 set_reduce_memory_result(true);
4235 host_impl_
->set_max_memory_needed_bytes(1);
4236 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
4237 host_impl_
->memory_allocation_limit_bytes() - 1));
4238 EXPECT_TRUE(did_request_commit_
);
4239 did_request_commit_
= false;
4241 // But if we set it to the same value that it was before, we shouldn't
4243 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
4244 host_impl_
->memory_allocation_limit_bytes()));
4245 EXPECT_FALSE(did_request_commit_
);
4248 struct RenderPassRemovalTestData
: public LayerTreeHostImpl::FrameData
{
4249 ScopedPtrHashMap
<RenderPass::Id
, TestRenderPass
> render_pass_cache
;
4250 scoped_ptr
<SharedQuadState
> shared_quad_state
;
4253 class TestRenderer
: public GLRenderer
, public RendererClient
{
4255 static scoped_ptr
<TestRenderer
> Create(ResourceProvider
* resource_provider
,
4256 OutputSurface
* output_surface
,
4258 scoped_ptr
<TestRenderer
> renderer(new TestRenderer(resource_provider
,
4261 if (!renderer
->Initialize())
4262 return scoped_ptr
<TestRenderer
>();
4264 return renderer
.Pass();
4267 void ClearCachedTextures() { textures_
.clear(); }
4268 void SetHaveCachedResourcesForRenderPassId(RenderPass::Id id
) {
4269 textures_
.insert(id
);
4272 virtual bool HaveCachedResourcesForRenderPassId(RenderPass::Id id
) const
4274 return textures_
.count(id
);
4277 // RendererClient implementation.
4278 virtual gfx::Size
DeviceViewportSize() const OVERRIDE
{
4279 return viewport_size_
;
4281 virtual const LayerTreeSettings
& Settings() const OVERRIDE
{
4284 virtual void SetFullRootLayerDamage() OVERRIDE
{}
4285 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
4287 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
4289 virtual bool HasImplThread() const OVERRIDE
{ return false; }
4290 virtual bool ShouldClearRootRenderPass() const OVERRIDE
{ return true; }
4291 virtual CompositorFrameMetadata
MakeCompositorFrameMetadata() const
4292 OVERRIDE
{ return CompositorFrameMetadata(); }
4293 virtual bool AllowPartialSwap() const OVERRIDE
{
4298 TestRenderer(ResourceProvider
* resource_provider
,
4299 OutputSurface
* output_surface
,
4301 : GLRenderer(this, output_surface
, resource_provider
, 0) {}
4304 LayerTreeSettings settings_
;
4305 gfx::Size viewport_size_
;
4306 base::hash_set
<RenderPass::Id
> textures_
;
4309 static void ConfigureRenderPassTestData(const char* test_script
,
4310 RenderPassRemovalTestData
* test_data
,
4311 TestRenderer
* renderer
) {
4312 renderer
->ClearCachedTextures();
4314 // One shared state for all quads - we don't need the correct details
4315 test_data
->shared_quad_state
= SharedQuadState::Create();
4316 test_data
->shared_quad_state
->SetAll(gfx::Transform(),
4323 const char* current_char
= test_script
;
4325 // Pre-create root pass
4326 RenderPass::Id root_render_pass_id
=
4327 RenderPass::Id(test_script
[0], test_script
[1]);
4328 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
4329 pass
->SetNew(root_render_pass_id
, gfx::Rect(), gfx::Rect(), gfx::Transform());
4330 test_data
->render_pass_cache
.add(root_render_pass_id
, pass
.Pass());
4331 while (*current_char
) {
4332 int layer_id
= *current_char
;
4334 ASSERT_TRUE(current_char
);
4335 int index
= *current_char
;
4338 RenderPass::Id render_pass_id
= RenderPass::Id(layer_id
, index
);
4340 bool is_replica
= false;
4341 if (!test_data
->render_pass_cache
.contains(render_pass_id
))
4344 scoped_ptr
<TestRenderPass
> render_pass
=
4345 test_data
->render_pass_cache
.take(render_pass_id
);
4347 // Cycle through quad data and create all quads.
4348 while (*current_char
&& *current_char
!= '\n') {
4349 if (*current_char
== 's') {
4350 // Solid color draw quad.
4351 scoped_ptr
<SolidColorDrawQuad
> quad
= SolidColorDrawQuad::Create();
4352 quad
->SetNew(test_data
->shared_quad_state
.get(),
4353 gfx::Rect(0, 0, 10, 10),
4356 render_pass
->AppendQuad(quad
.PassAs
<DrawQuad
>());
4358 } else if ((*current_char
>= 'A') && (*current_char
<= 'Z')) {
4359 // RenderPass draw quad.
4360 int layer_id
= *current_char
;
4362 ASSERT_TRUE(current_char
);
4363 int index
= *current_char
;
4365 RenderPass::Id new_render_pass_id
= RenderPass::Id(layer_id
, index
);
4366 ASSERT_NE(root_render_pass_id
, new_render_pass_id
);
4367 bool has_texture
= false;
4368 bool contents_changed
= true;
4370 if (*current_char
== '[') {
4372 while (*current_char
&& *current_char
!= ']') {
4373 switch (*current_char
) {
4375 contents_changed
= false;
4383 if (*current_char
== ']')
4387 if (test_data
->render_pass_cache
.find(new_render_pass_id
) ==
4388 test_data
->render_pass_cache
.end()) {
4390 renderer
->SetHaveCachedResourcesForRenderPassId(new_render_pass_id
);
4392 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
4393 pass
->SetNew(new_render_pass_id
,
4397 test_data
->render_pass_cache
.add(new_render_pass_id
, pass
.Pass());
4400 gfx::Rect quad_rect
= gfx::Rect(0, 0, 1, 1);
4401 gfx::Rect contents_changed_rect
=
4402 contents_changed
? quad_rect
: gfx::Rect();
4403 scoped_ptr
<RenderPassDrawQuad
> quad
= RenderPassDrawQuad::Create();
4404 quad
->SetNew(test_data
->shared_quad_state
.get(),
4409 contents_changed_rect
,
4410 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
4411 WebKit::WebFilterOperations(),
4412 skia::RefPtr
<SkImageFilter
>(),
4413 WebKit::WebFilterOperations());
4414 render_pass
->AppendQuad(quad
.PassAs
<DrawQuad
>());
4417 test_data
->render_passes_by_id
[render_pass_id
] = render_pass
.get();
4418 test_data
->render_passes
.insert(test_data
->render_passes
.begin(),
4419 render_pass
.PassAs
<RenderPass
>());
4425 void DumpRenderPassTestData(const RenderPassRemovalTestData
& test_data
,
4428 for (RenderPassList::const_reverse_iterator it
=
4429 test_data
.render_passes
.rbegin();
4430 it
!= test_data
.render_passes
.rend();
4432 const RenderPass
* current_pass
= *it
;
4433 *pos
= current_pass
->id
.layer_id
;
4435 *pos
= current_pass
->id
.index
;
4438 QuadList::const_iterator quad_list_iterator
=
4439 current_pass
->quad_list
.begin();
4440 while (quad_list_iterator
!= current_pass
->quad_list
.end()) {
4441 DrawQuad
* current_quad
= *quad_list_iterator
;
4442 switch (current_quad
->material
) {
4443 case DrawQuad::SOLID_COLOR
:
4447 case DrawQuad::RENDER_PASS
:
4448 *pos
= RenderPassDrawQuad::MaterialCast(current_quad
)->
4449 render_pass_id
.layer_id
;
4451 *pos
= RenderPassDrawQuad::MaterialCast(current_quad
)->
4452 render_pass_id
.index
;
4461 quad_list_iterator
++;
4469 // Each RenderPassList is represented by a string which describes the
4471 // The syntax of the string is as follows:
4473 // RsssssX[c]ssYsssZ[t]ssW[ct]
4474 // Identifies the render pass------------------------^ ^^^ ^ ^ ^ ^ ^
4475 // These are solid color quads--------------------------+ | | | | |
4476 // Identifies RenderPassDrawQuad's RenderPass--------------+ | | | |
4477 // This quad's contents didn't change------------------------+ | | |
4478 // This quad's contents changed and it has no texture------------+ | |
4479 // This quad has texture but its contents changed----------------------+ |
4480 // This quad's contents didn't change and it has texture - will be removed---+
4482 // Expected results have exactly the same syntax, except they do not use square
4483 // brackets, since we only check the structure, not attributes.
4485 // Test case configuration consists of initialization script and expected
4486 // results, all in the same format.
4489 const char* init_script
;
4490 const char* expected_result
;
4493 TestCase remove_render_passes_cases
[] = {
4499 "Single pass - no quads",
4503 "Two passes, no removal",
4509 "Two passes, remove last",
4514 "Have texture but contents changed - leave pass",
4520 "Contents didn't change but no texture - leave pass",
4526 "Replica: two quads reference the same pass; remove",
4527 "R0ssssA0[ct]A0[ct]sss\n"
4531 "Replica: two quads reference the same pass; leave",
4532 "R0ssssA0[c]A0[c]sss\n"
4537 "Many passes, remove all",
4539 "A0sssB0[ct]C0[ct]s\n"
4540 "B0sssD0[ct]ssE0[ct]F0[ct]\n"
4549 "Deep recursion, remove all",
4551 "R0sssssA0[ct]ssss\n"
4565 "Wide recursion, remove all",
4566 "R0A0[ct]B0[ct]C0[ct]D0[ct]E0[ct]F0[ct]G0[ct]H0[ct]I0[ct]J0[ct]\n"
4578 "R0A0B0C0D0E0F0G0H0I0J0\n"
4580 "Remove passes regardless of cache state",
4583 "B0sssD0[c]ssE0[t]F0\n"
4592 "Leave some passes, remove others",
4595 "A0sssB0[t]C0[ct]s\n"
4610 static void VerifyRenderPassTestData(
4611 const TestCase
& test_case
,
4612 const RenderPassRemovalTestData
& test_data
) {
4613 char actual_result
[1024];
4614 DumpRenderPassTestData(test_data
, actual_result
);
4615 EXPECT_STREQ(test_case
.expected_result
, actual_result
) << "In test case: " <<
4619 TEST_F(LayerTreeHostImplTest
, TestRemoveRenderPasses
) {
4620 scoped_ptr
<OutputSurface
> output_surface(CreateOutputSurface());
4621 ASSERT_TRUE(output_surface
->context3d());
4622 scoped_ptr
<ResourceProvider
> resource_provider
=
4623 ResourceProvider::Create(output_surface
.get(), 0);
4625 scoped_ptr
<TestRenderer
> renderer
=
4626 TestRenderer::Create(resource_provider
.get(),
4627 output_surface
.get(),
4630 int test_case_index
= 0;
4631 while (remove_render_passes_cases
[test_case_index
].name
) {
4632 RenderPassRemovalTestData test_data
;
4633 ConfigureRenderPassTestData(
4634 remove_render_passes_cases
[test_case_index
].init_script
,
4637 LayerTreeHostImpl::RemoveRenderPasses(
4638 LayerTreeHostImpl::CullRenderPassesWithCachedTextures(renderer
.get()),
4640 VerifyRenderPassTestData(remove_render_passes_cases
[test_case_index
],
4646 class LayerTreeHostImplTestWithDelegatingRenderer
4647 : public LayerTreeHostImplTest
{
4649 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() OVERRIDE
{
4650 return FakeOutputSurface::CreateDelegating3d().PassAs
<OutputSurface
>();
4653 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
4654 bool expect_to_draw
= !expected_damage
.IsEmpty();
4656 LayerTreeHostImpl::FrameData frame
;
4657 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4659 if (!expect_to_draw
) {
4660 // With no damage, we don't draw, and no quads are created.
4661 ASSERT_EQ(0u, frame
.render_passes
.size());
4663 ASSERT_EQ(1u, frame
.render_passes
.size());
4665 // Verify the damage rect for the root render pass.
4666 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
4667 EXPECT_RECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
4669 // Verify the root and child layers' quads are generated and not being
4671 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
4673 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
4674 gfx::RectF
expected_child_visible_rect(child
->content_bounds());
4675 EXPECT_RECT_EQ(expected_child_visible_rect
,
4676 root_render_pass
->quad_list
[0]->visible_rect
);
4678 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
4679 gfx::RectF
expected_root_visible_rect(root
->content_bounds());
4680 EXPECT_RECT_EQ(expected_root_visible_rect
,
4681 root_render_pass
->quad_list
[1]->visible_rect
);
4684 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4685 host_impl_
->DidDrawAllLayers(frame
);
4686 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
4690 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
4691 scoped_ptr
<SolidColorLayerImpl
> root
=
4692 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
4693 root
->SetAnchorPoint(gfx::PointF());
4694 root
->SetPosition(gfx::PointF());
4695 root
->SetBounds(gfx::Size(10, 10));
4696 root
->SetContentBounds(gfx::Size(10, 10));
4697 root
->SetDrawsContent(true);
4699 // Child layer is in the bottom right corner.
4700 scoped_ptr
<SolidColorLayerImpl
> child
=
4701 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
4702 child
->SetAnchorPoint(gfx::PointF(0.f
, 0.f
));
4703 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
4704 child
->SetBounds(gfx::Size(1, 1));
4705 child
->SetContentBounds(gfx::Size(1, 1));
4706 child
->SetDrawsContent(true);
4707 root
->AddChild(child
.PassAs
<LayerImpl
>());
4709 host_impl_
->active_tree()->SetRootLayer(root
.PassAs
<LayerImpl
>());
4711 // Draw a frame. In the first frame, the entire viewport should be damaged.
4712 gfx::Rect full_frame_damage
= gfx::Rect(host_impl_
->device_viewport_size());
4713 DrawFrameAndTestDamage(full_frame_damage
);
4715 // The second frame has damage that doesn't touch the child layer. Its quads
4716 // should still be generated.
4717 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
4718 host_impl_
->active_tree()->root_layer()->set_update_rect(small_damage
);
4719 DrawFrameAndTestDamage(small_damage
);
4721 // The third frame should have no damage, so no quads should be generated.
4722 gfx::Rect no_damage
;
4723 DrawFrameAndTestDamage(no_damage
);
4726 class FakeMaskLayerImpl
: public LayerImpl
{
4728 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4730 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
4733 virtual ResourceProvider::ResourceId
ContentsResourceId() const OVERRIDE
{
4738 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
4739 : LayerImpl(tree_impl
, id
) {}
4742 TEST_F(LayerTreeHostImplTest
, MaskLayerWithScaling
) {
4745 // +-- Scaling Layer (adds a 2x scale)
4747 // +-- Content Layer
4749 scoped_ptr
<LayerImpl
> scoped_root
=
4750 LayerImpl::Create(host_impl_
->active_tree(), 1);
4751 LayerImpl
* root
= scoped_root
.get();
4752 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
4754 scoped_ptr
<LayerImpl
> scoped_scaling_layer
=
4755 LayerImpl::Create(host_impl_
->active_tree(), 2);
4756 LayerImpl
* scaling_layer
= scoped_scaling_layer
.get();
4757 root
->AddChild(scoped_scaling_layer
.Pass());
4759 scoped_ptr
<LayerImpl
> scoped_content_layer
=
4760 LayerImpl::Create(host_impl_
->active_tree(), 3);
4761 LayerImpl
* content_layer
= scoped_content_layer
.get();
4762 scaling_layer
->AddChild(scoped_content_layer
.Pass());
4764 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
4765 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 4);
4766 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
4767 content_layer
->SetMaskLayer(scoped_mask_layer
.PassAs
<LayerImpl
>());
4769 gfx::Size
root_size(100, 100);
4770 root
->SetBounds(root_size
);
4771 root
->SetContentBounds(root_size
);
4772 root
->SetPosition(gfx::PointF());
4773 root
->SetAnchorPoint(gfx::PointF());
4775 gfx::Size
scaling_layer_size(50, 50);
4776 scaling_layer
->SetBounds(scaling_layer_size
);
4777 scaling_layer
->SetContentBounds(scaling_layer_size
);
4778 scaling_layer
->SetPosition(gfx::PointF());
4779 scaling_layer
->SetAnchorPoint(gfx::PointF());
4780 gfx::Transform scale
;
4781 scale
.Scale(2.f
, 2.f
);
4782 scaling_layer
->SetTransform(scale
);
4784 content_layer
->SetBounds(scaling_layer_size
);
4785 content_layer
->SetContentBounds(scaling_layer_size
);
4786 content_layer
->SetPosition(gfx::PointF());
4787 content_layer
->SetAnchorPoint(gfx::PointF());
4788 content_layer
->SetDrawsContent(true);
4790 mask_layer
->SetBounds(scaling_layer_size
);
4791 mask_layer
->SetContentBounds(scaling_layer_size
);
4792 mask_layer
->SetPosition(gfx::PointF());
4793 mask_layer
->SetAnchorPoint(gfx::PointF());
4794 mask_layer
->SetDrawsContent(true);
4797 // Check that the tree scaling is correctly taken into account for the mask,
4798 // that should fully map onto the quad.
4799 float device_scale_factor
= 1.f
;
4800 host_impl_
->SetViewportSize(root_size
);
4801 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4803 LayerTreeHostImpl::FrameData frame
;
4804 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4806 ASSERT_EQ(1u, frame
.render_passes
.size());
4807 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4808 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4809 frame
.render_passes
[0]->quad_list
[0]->material
);
4810 const RenderPassDrawQuad
* render_pass_quad
=
4811 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4812 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4813 render_pass_quad
->rect
.ToString());
4814 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4815 render_pass_quad
->mask_uv_rect
.ToString());
4817 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4818 host_impl_
->DidDrawAllLayers(frame
);
4822 // Applying a DSF should change the render surface size, but won't affect
4823 // which part of the mask is used.
4824 device_scale_factor
= 2.f
;
4825 gfx::Size device_viewport
=
4826 gfx::ToFlooredSize(gfx::ScaleSize(root_size
, device_scale_factor
));
4827 host_impl_
->SetViewportSize(device_viewport
);
4828 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4829 host_impl_
->active_tree()->set_needs_update_draw_properties();
4831 LayerTreeHostImpl::FrameData frame
;
4832 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4834 ASSERT_EQ(1u, frame
.render_passes
.size());
4835 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4836 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4837 frame
.render_passes
[0]->quad_list
[0]->material
);
4838 const RenderPassDrawQuad
* render_pass_quad
=
4839 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4840 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4841 render_pass_quad
->rect
.ToString());
4842 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4843 render_pass_quad
->mask_uv_rect
.ToString());
4845 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4846 host_impl_
->DidDrawAllLayers(frame
);
4850 // Applying an equivalent content scale on the content layer and the mask
4851 // should still result in the same part of the mask being used.
4852 gfx::Size content_bounds
=
4853 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size
,
4854 device_scale_factor
));
4855 content_layer
->SetContentBounds(content_bounds
);
4856 content_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
4857 mask_layer
->SetContentBounds(content_bounds
);
4858 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
4859 host_impl_
->active_tree()->set_needs_update_draw_properties();
4861 LayerTreeHostImpl::FrameData frame
;
4862 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4864 ASSERT_EQ(1u, frame
.render_passes
.size());
4865 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4866 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4867 frame
.render_passes
[0]->quad_list
[0]->material
);
4868 const RenderPassDrawQuad
* render_pass_quad
=
4869 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4870 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4871 render_pass_quad
->rect
.ToString());
4872 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4873 render_pass_quad
->mask_uv_rect
.ToString());
4875 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4876 host_impl_
->DidDrawAllLayers(frame
);
4880 TEST_F(LayerTreeHostImplTest
, MaskLayerWithDifferentBounds
) {
4881 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4884 scoped_ptr
<LayerImpl
> scoped_root
=
4885 LayerImpl::Create(host_impl_
->active_tree(), 1);
4886 LayerImpl
* root
= scoped_root
.get();
4887 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
4889 scoped_ptr
<LayerImpl
> scoped_content_layer
=
4890 LayerImpl::Create(host_impl_
->active_tree(), 3);
4891 LayerImpl
* content_layer
= scoped_content_layer
.get();
4892 root
->AddChild(scoped_content_layer
.Pass());
4894 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
4895 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 4);
4896 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
4897 content_layer
->SetMaskLayer(scoped_mask_layer
.PassAs
<LayerImpl
>());
4899 gfx::Size
root_size(100, 100);
4900 root
->SetBounds(root_size
);
4901 root
->SetContentBounds(root_size
);
4902 root
->SetPosition(gfx::PointF());
4903 root
->SetAnchorPoint(gfx::PointF());
4905 gfx::Size
layer_size(50, 50);
4906 content_layer
->SetBounds(layer_size
);
4907 content_layer
->SetContentBounds(layer_size
);
4908 content_layer
->SetPosition(gfx::PointF());
4909 content_layer
->SetAnchorPoint(gfx::PointF());
4910 content_layer
->SetDrawsContent(true);
4912 gfx::Size
mask_size(100, 100);
4913 mask_layer
->SetBounds(mask_size
);
4914 mask_layer
->SetContentBounds(mask_size
);
4915 mask_layer
->SetPosition(gfx::PointF());
4916 mask_layer
->SetAnchorPoint(gfx::PointF());
4917 mask_layer
->SetDrawsContent(true);
4919 // Check that the mask fills the surface.
4920 float device_scale_factor
= 1.f
;
4921 host_impl_
->SetViewportSize(root_size
);
4922 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4924 LayerTreeHostImpl::FrameData frame
;
4925 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4927 ASSERT_EQ(1u, frame
.render_passes
.size());
4928 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4929 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4930 frame
.render_passes
[0]->quad_list
[0]->material
);
4931 const RenderPassDrawQuad
* render_pass_quad
=
4932 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4933 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4934 render_pass_quad
->rect
.ToString());
4935 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4936 render_pass_quad
->mask_uv_rect
.ToString());
4938 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4939 host_impl_
->DidDrawAllLayers(frame
);
4942 // Applying a DSF should change the render surface size, but won't affect
4943 // which part of the mask is used.
4944 device_scale_factor
= 2.f
;
4945 gfx::Size device_viewport
=
4946 gfx::ToFlooredSize(gfx::ScaleSize(root_size
, device_scale_factor
));
4947 host_impl_
->SetViewportSize(device_viewport
);
4948 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4949 host_impl_
->active_tree()->set_needs_update_draw_properties();
4951 LayerTreeHostImpl::FrameData frame
;
4952 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4954 ASSERT_EQ(1u, frame
.render_passes
.size());
4955 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4956 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4957 frame
.render_passes
[0]->quad_list
[0]->material
);
4958 const RenderPassDrawQuad
* render_pass_quad
=
4959 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4960 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4961 render_pass_quad
->rect
.ToString());
4962 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4963 render_pass_quad
->mask_uv_rect
.ToString());
4965 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4966 host_impl_
->DidDrawAllLayers(frame
);
4969 // Applying an equivalent content scale on the content layer and the mask
4970 // should still result in the same part of the mask being used.
4971 gfx::Size layer_size_large
=
4972 gfx::ToRoundedSize(gfx::ScaleSize(layer_size
, device_scale_factor
));
4973 content_layer
->SetContentBounds(layer_size_large
);
4974 content_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
4975 gfx::Size mask_size_large
=
4976 gfx::ToRoundedSize(gfx::ScaleSize(mask_size
, device_scale_factor
));
4977 mask_layer
->SetContentBounds(mask_size_large
);
4978 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
4979 host_impl_
->active_tree()->set_needs_update_draw_properties();
4981 LayerTreeHostImpl::FrameData frame
;
4982 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4984 ASSERT_EQ(1u, frame
.render_passes
.size());
4985 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4986 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4987 frame
.render_passes
[0]->quad_list
[0]->material
);
4988 const RenderPassDrawQuad
* render_pass_quad
=
4989 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4990 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4991 render_pass_quad
->rect
.ToString());
4992 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4993 render_pass_quad
->mask_uv_rect
.ToString());
4995 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4996 host_impl_
->DidDrawAllLayers(frame
);
4999 // Applying a different contents scale to the mask layer means it will have
5000 // a larger texture, but it should use the same tex coords to cover the
5002 mask_layer
->SetContentBounds(mask_size
);
5003 mask_layer
->SetContentsScale(1.f
, 1.f
);
5004 host_impl_
->active_tree()->set_needs_update_draw_properties();
5006 LayerTreeHostImpl::FrameData frame
;
5007 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5009 ASSERT_EQ(1u, frame
.render_passes
.size());
5010 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5011 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5012 frame
.render_passes
[0]->quad_list
[0]->material
);
5013 const RenderPassDrawQuad
* render_pass_quad
=
5014 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
5015 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5016 render_pass_quad
->rect
.ToString());
5017 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5018 render_pass_quad
->mask_uv_rect
.ToString());
5020 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5021 host_impl_
->DidDrawAllLayers(frame
);
5025 TEST_F(LayerTreeHostImplTest
, ReflectionMaskLayerWithDifferentBounds
) {
5026 // The replica's mask layer has bounds 100x100 but the replica is of a
5027 // layer with bounds 50x50.
5029 scoped_ptr
<LayerImpl
> scoped_root
=
5030 LayerImpl::Create(host_impl_
->active_tree(), 1);
5031 LayerImpl
* root
= scoped_root
.get();
5032 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
5034 scoped_ptr
<LayerImpl
> scoped_content_layer
=
5035 LayerImpl::Create(host_impl_
->active_tree(), 3);
5036 LayerImpl
* content_layer
= scoped_content_layer
.get();
5037 root
->AddChild(scoped_content_layer
.Pass());
5039 scoped_ptr
<LayerImpl
> scoped_replica_layer
=
5040 LayerImpl::Create(host_impl_
->active_tree(), 2);
5041 LayerImpl
* replica_layer
= scoped_replica_layer
.get();
5042 content_layer
->SetReplicaLayer(scoped_replica_layer
.Pass());
5044 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
5045 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 4);
5046 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
5047 replica_layer
->SetMaskLayer(scoped_mask_layer
.PassAs
<LayerImpl
>());
5049 gfx::Size
root_size(100, 100);
5050 root
->SetBounds(root_size
);
5051 root
->SetContentBounds(root_size
);
5052 root
->SetPosition(gfx::PointF());
5053 root
->SetAnchorPoint(gfx::PointF());
5055 gfx::Size
layer_size(50, 50);
5056 content_layer
->SetBounds(layer_size
);
5057 content_layer
->SetContentBounds(layer_size
);
5058 content_layer
->SetPosition(gfx::PointF());
5059 content_layer
->SetAnchorPoint(gfx::PointF());
5060 content_layer
->SetDrawsContent(true);
5062 gfx::Size
mask_size(100, 100);
5063 mask_layer
->SetBounds(mask_size
);
5064 mask_layer
->SetContentBounds(mask_size
);
5065 mask_layer
->SetPosition(gfx::PointF());
5066 mask_layer
->SetAnchorPoint(gfx::PointF());
5067 mask_layer
->SetDrawsContent(true);
5069 // Check that the mask fills the surface.
5070 float device_scale_factor
= 1.f
;
5071 host_impl_
->SetViewportSize(root_size
);
5072 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5074 LayerTreeHostImpl::FrameData frame
;
5075 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5077 ASSERT_EQ(1u, frame
.render_passes
.size());
5078 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5079 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5080 frame
.render_passes
[0]->quad_list
[1]->material
);
5081 const RenderPassDrawQuad
* replica_quad
=
5082 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[1]);
5083 EXPECT_TRUE(replica_quad
->is_replica
);
5084 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
5085 replica_quad
->rect
.ToString());
5086 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5087 replica_quad
->mask_uv_rect
.ToString());
5089 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5090 host_impl_
->DidDrawAllLayers(frame
);
5093 // Applying a DSF should change the render surface size, but won't affect
5094 // which part of the mask is used.
5095 device_scale_factor
= 2.f
;
5096 gfx::Size device_viewport
=
5097 gfx::ToFlooredSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5098 host_impl_
->SetViewportSize(device_viewport
);
5099 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5100 host_impl_
->active_tree()->set_needs_update_draw_properties();
5102 LayerTreeHostImpl::FrameData frame
;
5103 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5105 ASSERT_EQ(1u, frame
.render_passes
.size());
5106 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5107 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5108 frame
.render_passes
[0]->quad_list
[1]->material
);
5109 const RenderPassDrawQuad
* replica_quad
=
5110 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[1]);
5111 EXPECT_TRUE(replica_quad
->is_replica
);
5112 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5113 replica_quad
->rect
.ToString());
5114 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5115 replica_quad
->mask_uv_rect
.ToString());
5117 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5118 host_impl_
->DidDrawAllLayers(frame
);
5121 // Applying an equivalent content scale on the content layer and the mask
5122 // should still result in the same part of the mask being used.
5123 gfx::Size layer_size_large
=
5124 gfx::ToRoundedSize(gfx::ScaleSize(layer_size
, device_scale_factor
));
5125 content_layer
->SetContentBounds(layer_size_large
);
5126 content_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5127 gfx::Size mask_size_large
=
5128 gfx::ToRoundedSize(gfx::ScaleSize(mask_size
, device_scale_factor
));
5129 mask_layer
->SetContentBounds(mask_size_large
);
5130 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5131 host_impl_
->active_tree()->set_needs_update_draw_properties();
5133 LayerTreeHostImpl::FrameData frame
;
5134 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5136 ASSERT_EQ(1u, frame
.render_passes
.size());
5137 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5138 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5139 frame
.render_passes
[0]->quad_list
[1]->material
);
5140 const RenderPassDrawQuad
* replica_quad
=
5141 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[1]);
5142 EXPECT_TRUE(replica_quad
->is_replica
);
5143 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5144 replica_quad
->rect
.ToString());
5145 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5146 replica_quad
->mask_uv_rect
.ToString());
5148 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5149 host_impl_
->DidDrawAllLayers(frame
);
5152 // Applying a different contents scale to the mask layer means it will have
5153 // a larger texture, but it should use the same tex coords to cover the
5155 mask_layer
->SetContentBounds(mask_size
);
5156 mask_layer
->SetContentsScale(1.f
, 1.f
);
5157 host_impl_
->active_tree()->set_needs_update_draw_properties();
5159 LayerTreeHostImpl::FrameData frame
;
5160 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5162 ASSERT_EQ(1u, frame
.render_passes
.size());
5163 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5164 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5165 frame
.render_passes
[0]->quad_list
[1]->material
);
5166 const RenderPassDrawQuad
* replica_quad
=
5167 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[1]);
5168 EXPECT_TRUE(replica_quad
->is_replica
);
5169 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5170 replica_quad
->rect
.ToString());
5171 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5172 replica_quad
->mask_uv_rect
.ToString());
5174 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5175 host_impl_
->DidDrawAllLayers(frame
);
5179 TEST_F(LayerTreeHostImplTest
, ReflectionMaskLayerForSurfaceWithUnclippedChild
) {
5180 // The replica is of a layer with bounds 50x50, but it has a child that causes
5181 // the surface bounds to be larger.
5183 scoped_ptr
<LayerImpl
> scoped_root
=
5184 LayerImpl::Create(host_impl_
->active_tree(), 1);
5185 LayerImpl
* root
= scoped_root
.get();
5186 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
5188 scoped_ptr
<LayerImpl
> scoped_content_layer
=
5189 LayerImpl::Create(host_impl_
->active_tree(), 2);
5190 LayerImpl
* content_layer
= scoped_content_layer
.get();
5191 root
->AddChild(scoped_content_layer
.Pass());
5193 scoped_ptr
<LayerImpl
> scoped_content_child_layer
=
5194 LayerImpl::Create(host_impl_
->active_tree(), 3);
5195 LayerImpl
* content_child_layer
= scoped_content_child_layer
.get();
5196 content_layer
->AddChild(scoped_content_child_layer
.Pass());
5198 scoped_ptr
<LayerImpl
> scoped_replica_layer
=
5199 LayerImpl::Create(host_impl_
->active_tree(), 4);
5200 LayerImpl
* replica_layer
= scoped_replica_layer
.get();
5201 content_layer
->SetReplicaLayer(scoped_replica_layer
.Pass());
5203 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
5204 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 5);
5205 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
5206 replica_layer
->SetMaskLayer(scoped_mask_layer
.PassAs
<LayerImpl
>());
5208 gfx::Size
root_size(100, 100);
5209 root
->SetBounds(root_size
);
5210 root
->SetContentBounds(root_size
);
5211 root
->SetPosition(gfx::PointF());
5212 root
->SetAnchorPoint(gfx::PointF());
5214 gfx::Size
layer_size(50, 50);
5215 content_layer
->SetBounds(layer_size
);
5216 content_layer
->SetContentBounds(layer_size
);
5217 content_layer
->SetPosition(gfx::PointF());
5218 content_layer
->SetAnchorPoint(gfx::PointF());
5219 content_layer
->SetDrawsContent(true);
5221 gfx::Size
child_size(50, 50);
5222 content_child_layer
->SetBounds(child_size
);
5223 content_child_layer
->SetContentBounds(child_size
);
5224 content_child_layer
->SetPosition(gfx::Point(50, 0));
5225 content_child_layer
->SetAnchorPoint(gfx::PointF());
5226 content_child_layer
->SetDrawsContent(true);
5228 gfx::Size
mask_size(50, 50);
5229 mask_layer
->SetBounds(mask_size
);
5230 mask_layer
->SetContentBounds(mask_size
);
5231 mask_layer
->SetPosition(gfx::PointF());
5232 mask_layer
->SetAnchorPoint(gfx::PointF());
5233 mask_layer
->SetDrawsContent(true);
5235 float device_scale_factor
= 1.f
;
5236 host_impl_
->SetViewportSize(root_size
);
5237 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5239 LayerTreeHostImpl::FrameData frame
;
5240 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5242 ASSERT_EQ(1u, frame
.render_passes
.size());
5243 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5245 // The surface is 100x50.
5246 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5247 frame
.render_passes
[0]->quad_list
[0]->material
);
5248 const RenderPassDrawQuad
* render_pass_quad
=
5249 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
5250 EXPECT_FALSE(render_pass_quad
->is_replica
);
5251 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5252 render_pass_quad
->rect
.ToString());
5254 // The mask covers the owning layer only.
5255 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5256 frame
.render_passes
[0]->quad_list
[1]->material
);
5257 const RenderPassDrawQuad
* replica_quad
=
5258 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[1]);
5259 EXPECT_TRUE(replica_quad
->is_replica
);
5260 EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(),
5261 replica_quad
->rect
.ToString());
5262 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 2.f
, 1.f
).ToString(),
5263 replica_quad
->mask_uv_rect
.ToString());
5265 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5266 host_impl_
->DidDrawAllLayers(frame
);
5269 // Move the child to (-50, 0) instead. Now the mask should be moved to still
5270 // cover the layer being replicated.
5271 content_child_layer
->SetPosition(gfx::Point(-50, 0));
5273 LayerTreeHostImpl::FrameData frame
;
5274 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5276 ASSERT_EQ(1u, frame
.render_passes
.size());
5277 ASSERT_EQ(2u, frame
.render_passes
[0]->quad_list
.size());
5279 // The surface is 100x50 with its origin at (-50, 0).
5280 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5281 frame
.render_passes
[0]->quad_list
[0]->material
);
5282 const RenderPassDrawQuad
* render_pass_quad
=
5283 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
5284 EXPECT_FALSE(render_pass_quad
->is_replica
);
5285 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5286 render_pass_quad
->rect
.ToString());
5288 // The mask covers the owning layer only.
5289 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5290 frame
.render_passes
[0]->quad_list
[1]->material
);
5291 const RenderPassDrawQuad
* replica_quad
=
5292 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[1]);
5293 EXPECT_TRUE(replica_quad
->is_replica
);
5294 EXPECT_EQ(gfx::Rect(-50, 0, 100, 50).ToString(),
5295 replica_quad
->rect
.ToString());
5296 EXPECT_EQ(gfx::RectF(-1.f
, 0.f
, 2.f
, 1.f
).ToString(),
5297 replica_quad
->mask_uv_rect
.ToString());
5299 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5300 host_impl_
->DidDrawAllLayers(frame
);
5304 TEST_F(LayerTreeHostImplTest
, MaskLayerForSurfaceWithClippedLayer
) {
5305 // The masked layer has bounds 50x50, but it has a child that causes
5306 // the surface bounds to be larger. It also has a parent that clips the
5307 // masked layer and its surface.
5309 scoped_ptr
<LayerImpl
> scoped_root
=
5310 LayerImpl::Create(host_impl_
->active_tree(), 1);
5311 LayerImpl
* root
= scoped_root
.get();
5312 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
5314 scoped_ptr
<LayerImpl
> scoped_clipping_layer
=
5315 LayerImpl::Create(host_impl_
->active_tree(), 2);
5316 LayerImpl
* clipping_layer
= scoped_clipping_layer
.get();
5317 root
->AddChild(scoped_clipping_layer
.Pass());
5319 scoped_ptr
<LayerImpl
> scoped_content_layer
=
5320 LayerImpl::Create(host_impl_
->active_tree(), 3);
5321 LayerImpl
* content_layer
= scoped_content_layer
.get();
5322 clipping_layer
->AddChild(scoped_content_layer
.Pass());
5324 scoped_ptr
<LayerImpl
> scoped_content_child_layer
=
5325 LayerImpl::Create(host_impl_
->active_tree(), 4);
5326 LayerImpl
* content_child_layer
= scoped_content_child_layer
.get();
5327 content_layer
->AddChild(scoped_content_child_layer
.Pass());
5329 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
5330 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 6);
5331 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
5332 content_layer
->SetMaskLayer(scoped_mask_layer
.PassAs
<LayerImpl
>());
5334 gfx::Size
root_size(100, 100);
5335 root
->SetBounds(root_size
);
5336 root
->SetContentBounds(root_size
);
5337 root
->SetPosition(gfx::PointF());
5338 root
->SetAnchorPoint(gfx::PointF());
5340 gfx::Rect
clipping_rect(20, 10, 10, 20);
5341 clipping_layer
->SetBounds(clipping_rect
.size());
5342 clipping_layer
->SetContentBounds(clipping_rect
.size());
5343 clipping_layer
->SetPosition(clipping_rect
.origin());
5344 clipping_layer
->SetAnchorPoint(gfx::PointF());
5345 clipping_layer
->SetMasksToBounds(true);
5347 gfx::Size
layer_size(50, 50);
5348 content_layer
->SetBounds(layer_size
);
5349 content_layer
->SetContentBounds(layer_size
);
5350 content_layer
->SetPosition(gfx::Point() - clipping_rect
.OffsetFromOrigin());
5351 content_layer
->SetAnchorPoint(gfx::PointF());
5352 content_layer
->SetDrawsContent(true);
5354 gfx::Size
child_size(50, 50);
5355 content_child_layer
->SetBounds(child_size
);
5356 content_child_layer
->SetContentBounds(child_size
);
5357 content_child_layer
->SetPosition(gfx::Point(50, 0));
5358 content_child_layer
->SetAnchorPoint(gfx::PointF());
5359 content_child_layer
->SetDrawsContent(true);
5361 gfx::Size
mask_size(100, 100);
5362 mask_layer
->SetBounds(mask_size
);
5363 mask_layer
->SetContentBounds(mask_size
);
5364 mask_layer
->SetPosition(gfx::PointF());
5365 mask_layer
->SetAnchorPoint(gfx::PointF());
5366 mask_layer
->SetDrawsContent(true);
5368 float device_scale_factor
= 1.f
;
5369 host_impl_
->SetViewportSize(root_size
);
5370 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5372 LayerTreeHostImpl::FrameData frame
;
5373 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5375 ASSERT_EQ(1u, frame
.render_passes
.size());
5376 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5378 // The surface is clipped to 10x20.
5379 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5380 frame
.render_passes
[0]->quad_list
[0]->material
);
5381 const RenderPassDrawQuad
* render_pass_quad
=
5382 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
5383 EXPECT_FALSE(render_pass_quad
->is_replica
);
5384 EXPECT_EQ(gfx::Rect(20, 10, 10, 20).ToString(),
5385 render_pass_quad
->rect
.ToString());
5387 // The masked layer is 50x50, but the surface size is 10x20. So the texture
5388 // coords in the mask are scaled by 10/50 and 20/50.
5389 // The surface is clipped to (20,10) so the mask texture coords are offset
5390 // by 20/50 and 10/50
5391 EXPECT_EQ(gfx::ScaleRect(gfx::RectF(20.f
, 10.f
, 10.f
, 20.f
),
5392 1.f
/ 50.f
).ToString(),
5393 render_pass_quad
->mask_uv_rect
.ToString());
5395 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5396 host_impl_
->DidDrawAllLayers(frame
);
5400 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
5402 CompositorFrameMetadataTest()
5403 : swap_buffers_complete_(0) {}
5405 virtual void OverrideSettings(LayerTreeSettings
* settings
) OVERRIDE
{
5406 settings
->compositor_frame_message
= true;
5408 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE
{
5409 swap_buffers_complete_
++;
5412 int swap_buffers_complete_
;
5415 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
5416 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5418 LayerTreeHostImpl::FrameData frame
;
5419 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5420 host_impl_
->DrawLayers(&frame
, base::TimeTicks());
5421 host_impl_
->DidDrawAllLayers(frame
);
5423 CompositorFrameAck ack
;
5424 host_impl_
->OnSendFrameToParentCompositorAck(ack
);
5425 EXPECT_EQ(swap_buffers_complete_
, 1);