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_metadata.h"
27 #include "cc/output/gl_renderer.h"
28 #include "cc/quads/render_pass_draw_quad.h"
29 #include "cc/quads/solid_color_draw_quad.h"
30 #include "cc/quads/texture_draw_quad.h"
31 #include "cc/quads/tile_draw_quad.h"
32 #include "cc/resources/layer_tiling_data.h"
33 #include "cc/test/animation_test_common.h"
34 #include "cc/test/fake_output_surface.h"
35 #include "cc/test/fake_proxy.h"
36 #include "cc/test/fake_rendering_stats_instrumentation.h"
37 #include "cc/test/fake_video_frame_provider.h"
38 #include "cc/test/fake_web_scrollbar_theme_geometry.h"
39 #include "cc/test/geometry_test_utils.h"
40 #include "cc/test/layer_test_common.h"
41 #include "cc/test/render_pass_test_common.h"
42 #include "cc/test/test_web_graphics_context_3d.h"
43 #include "cc/trees/layer_tree_impl.h"
44 #include "cc/trees/single_thread_proxy.h"
45 #include "media/base/media.h"
46 #include "testing/gmock/include/gmock/gmock.h"
47 #include "testing/gtest/include/gtest/gtest.h"
48 #include "ui/gfx/size_conversions.h"
49 #include "ui/gfx/vector2d_conversions.h"
51 using ::testing::Mock
;
52 using ::testing::Return
;
53 using ::testing::AnyNumber
;
54 using ::testing::AtLeast
;
56 using media::VideoFrame
;
61 class LayerTreeHostImplTest
: public testing::Test
,
62 public LayerTreeHostImplClient
{
64 LayerTreeHostImplTest()
65 : proxy_(scoped_ptr
<Thread
>(NULL
)),
66 always_impl_thread_(&proxy_
),
67 always_main_thread_blocked_(&proxy_
),
68 on_can_draw_state_changed_called_(false),
69 has_pending_tree_(false),
70 did_request_commit_(false),
71 did_request_redraw_(false),
72 did_upload_visible_tile_(false),
73 reduce_memory_result_(true) {
74 media::InitializeMediaLibraryForTesting();
77 virtual void SetUp() OVERRIDE
{
78 LayerTreeSettings settings
;
79 settings
.minimum_occlusion_tracking_size
= gfx::Size();
81 host_impl_
= LayerTreeHostImpl::Create(settings
,
84 &stats_instrumentation_
);
85 host_impl_
->InitializeRenderer(CreateOutputSurface());
86 host_impl_
->SetViewportSize(gfx::Size(10, 10));
89 virtual void TearDown() OVERRIDE
{}
91 virtual void DidLoseOutputSurfaceOnImplThread() OVERRIDE
{}
92 virtual void OnSwapBuffersCompleteOnImplThread() OVERRIDE
{}
93 virtual void OnVSyncParametersChanged(base::TimeTicks timebase
,
94 base::TimeDelta interval
) OVERRIDE
{}
95 virtual void DidVSync(base::TimeTicks frame_time
) OVERRIDE
{}
96 virtual void OnCanDrawStateChanged(bool can_draw
) OVERRIDE
{
97 on_can_draw_state_changed_called_
= true;
99 virtual void OnHasPendingTreeStateChanged(bool has_pending_tree
) OVERRIDE
{
100 has_pending_tree_
= has_pending_tree
;
102 virtual void SetNeedsRedrawOnImplThread() OVERRIDE
{
103 did_request_redraw_
= true;
105 virtual void DidInitializeVisibleTileOnImplThread() OVERRIDE
{
106 did_upload_visible_tile_
= true;
108 virtual void SetNeedsCommitOnImplThread() OVERRIDE
{
109 did_request_commit_
= true;
111 virtual void SetNeedsManageTilesOnImplThread() OVERRIDE
{}
112 virtual void PostAnimationEventsToMainThreadOnImplThread(
113 scoped_ptr
<AnimationEventsVector
> events
,
114 base::Time wall_clock_time
) OVERRIDE
{}
115 virtual bool ReduceContentsTextureMemoryOnImplThread(
116 size_t limit_bytes
, int priority_cutoff
) OVERRIDE
{
117 return reduce_memory_result_
;
119 virtual void ReduceWastedContentsTextureMemoryOnImplThread() OVERRIDE
{}
120 virtual void SendManagedMemoryStats() OVERRIDE
{}
121 virtual bool IsInsideDraw() OVERRIDE
{ return false; }
122 virtual void RenewTreePriority() OVERRIDE
{}
123 virtual void RequestScrollbarAnimationOnImplThread(base::TimeDelta delay
)
126 void set_reduce_memory_result(bool reduce_memory_result
) {
127 reduce_memory_result_
= reduce_memory_result
;
130 void CreateLayerTreeHost(bool partial_swap
,
131 scoped_ptr
<OutputSurface
> output_surface
) {
132 LayerTreeSettings settings
;
133 settings
.minimum_occlusion_tracking_size
= gfx::Size();
134 settings
.partial_swap_enabled
= partial_swap
;
136 host_impl_
= LayerTreeHostImpl::Create(settings
,
139 &stats_instrumentation_
);
141 host_impl_
->InitializeRenderer(output_surface
.Pass());
142 host_impl_
->SetViewportSize(gfx::Size(10, 10));
145 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
146 root
->SetAnchorPoint(gfx::PointF());
147 root
->SetPosition(gfx::PointF());
148 root
->SetBounds(gfx::Size(10, 10));
149 root
->SetContentBounds(gfx::Size(10, 10));
150 root
->SetDrawsContent(true);
151 root
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
152 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
155 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
156 ASSERT_EQ(layer
->scroll_delta(), gfx::Vector2d());
157 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
158 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
161 static void ExpectContains(const ScrollAndScaleSet
& scroll_info
,
163 gfx::Vector2d scroll_delta
) {
164 int times_encountered
= 0;
166 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
167 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
169 EXPECT_VECTOR_EQ(scroll_delta
, scroll_info
.scrolls
[i
].scroll_delta
);
173 ASSERT_EQ(times_encountered
, 1);
176 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
177 int times_encountered
= 0;
179 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
180 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
185 ASSERT_EQ(0, times_encountered
);
188 void SetupScrollAndContentsLayers(gfx::Size content_size
) {
189 scoped_ptr
<LayerImpl
> root
=
190 LayerImpl::Create(host_impl_
->active_tree(), 1);
191 root
->SetScrollable(true);
192 root
->SetScrollOffset(gfx::Vector2d());
193 root
->SetMaxScrollOffset(gfx::Vector2d(content_size
.width(),
194 content_size
.height()));
195 root
->SetBounds(content_size
);
196 root
->SetContentBounds(content_size
);
197 root
->SetPosition(gfx::PointF());
198 root
->SetAnchorPoint(gfx::PointF());
200 scoped_ptr
<LayerImpl
> contents
=
201 LayerImpl::Create(host_impl_
->active_tree(), 2);
202 contents
->SetDrawsContent(true);
203 contents
->SetBounds(content_size
);
204 contents
->SetContentBounds(content_size
);
205 contents
->SetPosition(gfx::PointF());
206 contents
->SetAnchorPoint(gfx::PointF());
207 root
->AddChild(contents
.Pass());
208 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
209 host_impl_
->active_tree()->DidBecomeActive();
212 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
, gfx::Size size
) {
213 scoped_ptr
<LayerImpl
> layer
=
214 LayerImpl::Create(host_impl_
->active_tree(), id
);
215 layer
->SetScrollable(true);
216 layer
->SetDrawsContent(true);
217 layer
->SetBounds(size
);
218 layer
->SetContentBounds(size
);
219 layer
->SetMaxScrollOffset(gfx::Vector2d(size
.width() * 2,
224 void InitializeRendererAndDrawFrame() {
225 host_impl_
->InitializeRenderer(CreateOutputSurface());
226 LayerTreeHostImpl::FrameData frame
;
227 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
228 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
229 host_impl_
->DidDrawAllLayers(frame
);
232 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
233 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
234 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
235 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
236 float device_scale_factor
);
239 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
240 return CreateFakeOutputSurface();
243 void DrawOneFrame() {
244 LayerTreeHostImpl::FrameData frame_data
;
245 host_impl_
->PrepareToDraw(&frame_data
, gfx::Rect());
246 host_impl_
->DidDrawAllLayers(frame_data
);
250 DebugScopedSetImplThread always_impl_thread_
;
251 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
253 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
254 FakeRenderingStatsInstrumentation stats_instrumentation_
;
255 bool on_can_draw_state_changed_called_
;
256 bool has_pending_tree_
;
257 bool did_request_commit_
;
258 bool did_request_redraw_
;
259 bool did_upload_visible_tile_
;
260 bool reduce_memory_result_
;
263 class TestWebGraphicsContext3DMakeCurrentFails
264 : public TestWebGraphicsContext3D
{
266 virtual bool makeContextCurrent() OVERRIDE
{ return false; }
269 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
270 // Note: It is not possible to disable the renderer once it has been set,
271 // so we do not need to test that disabling the renderer notifies us
272 // that can_draw changed.
273 EXPECT_FALSE(host_impl_
->CanDraw());
274 on_can_draw_state_changed_called_
= false;
276 SetupScrollAndContentsLayers(gfx::Size(100, 100));
277 EXPECT_TRUE(host_impl_
->CanDraw());
278 EXPECT_TRUE(on_can_draw_state_changed_called_
);
279 on_can_draw_state_changed_called_
= false;
281 // Toggle the root layer to make sure it toggles can_draw
282 host_impl_
->active_tree()->SetRootLayer(scoped_ptr
<LayerImpl
>());
283 EXPECT_FALSE(host_impl_
->CanDraw());
284 EXPECT_TRUE(on_can_draw_state_changed_called_
);
285 on_can_draw_state_changed_called_
= false;
287 SetupScrollAndContentsLayers(gfx::Size(100, 100));
288 EXPECT_TRUE(host_impl_
->CanDraw());
289 EXPECT_TRUE(on_can_draw_state_changed_called_
);
290 on_can_draw_state_changed_called_
= false;
292 // Toggle the device viewport size to make sure it toggles can_draw.
293 host_impl_
->SetViewportSize(gfx::Size());
294 EXPECT_FALSE(host_impl_
->CanDraw());
295 EXPECT_TRUE(on_can_draw_state_changed_called_
);
296 on_can_draw_state_changed_called_
= false;
298 host_impl_
->SetViewportSize(gfx::Size(100, 100));
299 EXPECT_TRUE(host_impl_
->CanDraw());
300 EXPECT_TRUE(on_can_draw_state_changed_called_
);
301 on_can_draw_state_changed_called_
= false;
303 // Toggle contents textures purged without causing any evictions,
304 // and make sure that it does not change can_draw.
305 set_reduce_memory_result(false);
306 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
307 host_impl_
->memory_allocation_limit_bytes() - 1));
308 EXPECT_TRUE(host_impl_
->CanDraw());
309 EXPECT_FALSE(on_can_draw_state_changed_called_
);
310 on_can_draw_state_changed_called_
= false;
312 // Toggle contents textures purged to make sure it toggles can_draw.
313 set_reduce_memory_result(true);
314 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
315 host_impl_
->memory_allocation_limit_bytes() - 1));
316 EXPECT_FALSE(host_impl_
->CanDraw());
317 EXPECT_TRUE(on_can_draw_state_changed_called_
);
318 on_can_draw_state_changed_called_
= false;
320 host_impl_
->active_tree()->ResetContentsTexturesPurged();
321 EXPECT_TRUE(host_impl_
->CanDraw());
322 EXPECT_TRUE(on_can_draw_state_changed_called_
);
323 on_can_draw_state_changed_called_
= false;
326 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
327 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
329 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
330 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
333 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
335 scoped_ptr
<LayerImpl
> root
=
336 LayerImpl::Create(host_impl_
->active_tree(), 1);
337 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
338 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
339 root
->children()[1]->AddChild(
340 LayerImpl::Create(host_impl_
->active_tree(), 4));
341 root
->children()[1]->AddChild(
342 LayerImpl::Create(host_impl_
->active_tree(), 5));
343 root
->children()[1]->children()[0]->AddChild(
344 LayerImpl::Create(host_impl_
->active_tree(), 6));
345 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
347 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
349 ExpectClearedScrollDeltasRecursive(root
);
351 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
353 scroll_info
= host_impl_
->ProcessScrollDeltas();
354 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
355 ExpectClearedScrollDeltasRecursive(root
);
357 scroll_info
= host_impl_
->ProcessScrollDeltas();
358 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
359 ExpectClearedScrollDeltasRecursive(root
);
362 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
363 gfx::Vector2d
scroll_offset(20, 30);
364 gfx::Vector2d
scroll_delta(11, -15);
366 scoped_ptr
<LayerImpl
> root
=
367 LayerImpl::Create(host_impl_
->active_tree(), 1);
368 root
->SetScrollOffset(scroll_offset
);
369 root
->SetScrollable(true);
370 root
->SetMaxScrollOffset(gfx::Vector2d(100, 100));
371 root
->ScrollBy(scroll_delta
);
372 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
374 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
376 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
378 scroll_info
= host_impl_
->ProcessScrollDeltas();
379 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
380 EXPECT_VECTOR_EQ(root
->sent_scroll_delta(), scroll_delta
);
381 ExpectContains(*scroll_info
, root
->id(), scroll_delta
);
383 gfx::Vector2d
scroll_delta2(-5, 27);
384 root
->ScrollBy(scroll_delta2
);
385 scroll_info
= host_impl_
->ProcessScrollDeltas();
386 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
387 EXPECT_VECTOR_EQ(root
->sent_scroll_delta(), scroll_delta
+ scroll_delta2
);
388 ExpectContains(*scroll_info
, root
->id(), scroll_delta
+ scroll_delta2
);
390 root
->ScrollBy(gfx::Vector2d());
391 scroll_info
= host_impl_
->ProcessScrollDeltas();
392 EXPECT_EQ(root
->sent_scroll_delta(), scroll_delta
+ scroll_delta2
);
395 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
396 SetupScrollAndContentsLayers(gfx::Size(100, 100));
397 host_impl_
->SetViewportSize(gfx::Size(50, 50));
398 InitializeRendererAndDrawFrame();
400 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
401 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
402 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
403 host_impl_
->ScrollEnd();
404 EXPECT_TRUE(did_request_redraw_
);
405 EXPECT_TRUE(did_request_commit_
);
408 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
409 // We should not crash when trying to scroll an empty layer tree.
410 EXPECT_EQ(InputHandlerClient::ScrollIgnored
,
411 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
414 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
415 LayerTreeSettings settings
;
416 host_impl_
= LayerTreeHostImpl::Create(settings
,
419 &stats_instrumentation_
);
421 // Initialization will fail here.
422 host_impl_
->InitializeRenderer(FakeOutputSurface::Create3d(
423 scoped_ptr
<WebKit::WebGraphicsContext3D
>(
424 new TestWebGraphicsContext3DMakeCurrentFails
))
425 .PassAs
<OutputSurface
>());
426 host_impl_
->SetViewportSize(gfx::Size(10, 10));
428 SetupScrollAndContentsLayers(gfx::Size(100, 100));
430 // We should not crash when trying to scroll after the renderer initialization
432 EXPECT_EQ(InputHandlerClient::ScrollIgnored
,
433 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
436 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
437 int scroll_layer_id
= 1;
439 SetupScrollAndContentsLayers(gfx::Size(100, 100));
440 host_impl_
->SetViewportSize(gfx::Size(50, 50));
441 InitializeRendererAndDrawFrame();
443 // We should not crash if the tree is replaced while we are scrolling.
444 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
445 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
446 host_impl_
->active_tree()->DetachLayerTree();
448 SetupScrollAndContentsLayers(gfx::Size(100, 100));
450 // We should still be scrolling, because the scrolled layer also exists in the
452 gfx::Vector2d
scroll_delta(0, 10);
453 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
454 host_impl_
->ScrollEnd();
455 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
456 ExpectContains(*scroll_info
, scroll_layer_id
, scroll_delta
);
459 TEST_F(LayerTreeHostImplTest
, ClearRootRenderSurfaceAndScroll
) {
460 SetupScrollAndContentsLayers(gfx::Size(100, 100));
461 host_impl_
->SetViewportSize(gfx::Size(50, 50));
462 InitializeRendererAndDrawFrame();
464 // We should be able to scroll even if the root layer loses its render surface
465 // after the most recent render.
466 host_impl_
->active_tree()->root_layer()->ClearRenderSurface();
467 host_impl_
->active_tree()->set_needs_update_draw_properties();
469 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
470 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
473 TEST_F(LayerTreeHostImplTest
, WheelEventHandlers
) {
474 SetupScrollAndContentsLayers(gfx::Size(100, 100));
475 host_impl_
->SetViewportSize(gfx::Size(50, 50));
476 InitializeRendererAndDrawFrame();
477 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
479 root
->SetHaveWheelEventHandlers(true);
481 // With registered event handlers, wheel scrolls have to go to the main
483 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
484 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
486 // But gesture scrolls can still be handled.
487 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
488 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Gesture
));
491 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
492 SetupScrollAndContentsLayers(gfx::Size(100, 100));
493 host_impl_
->SetViewportSize(gfx::Size(50, 50));
494 InitializeRendererAndDrawFrame();
495 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
497 root
->SetShouldScrollOnMainThread(true);
499 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
500 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
501 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
502 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Gesture
));
505 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
506 SetupScrollAndContentsLayers(gfx::Size(200, 200));
507 host_impl_
->SetViewportSize(gfx::Size(100, 100));
509 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
510 root
->SetContentsScale(2.f
, 2.f
);
511 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
513 InitializeRendererAndDrawFrame();
515 // All scroll types inside the non-fast scrollable region should fail.
516 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
517 host_impl_
->ScrollBegin(gfx::Point(25, 25),
518 InputHandlerClient::Wheel
));
519 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
520 host_impl_
->ScrollBegin(gfx::Point(25, 25),
521 InputHandlerClient::Gesture
));
523 // All scroll types outside this region should succeed.
524 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
525 host_impl_
->ScrollBegin(gfx::Point(75, 75),
526 InputHandlerClient::Wheel
));
527 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
528 host_impl_
->ScrollEnd();
529 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
530 host_impl_
->ScrollBegin(gfx::Point(75, 75),
531 InputHandlerClient::Gesture
));
532 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
533 host_impl_
->ScrollEnd();
536 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
537 SetupScrollAndContentsLayers(gfx::Size(200, 200));
538 host_impl_
->SetViewportSize(gfx::Size(100, 100));
540 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
541 root
->SetContentsScale(2.f
, 2.f
);
542 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
543 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
545 InitializeRendererAndDrawFrame();
547 // This point would fall into the non-fast scrollable region except that we've
548 // moved the layer down by 25 pixels.
549 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
550 host_impl_
->ScrollBegin(gfx::Point(40, 10),
551 InputHandlerClient::Wheel
));
552 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
553 host_impl_
->ScrollEnd();
555 // This point is still inside the non-fast region.
556 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
557 host_impl_
->ScrollBegin(gfx::Point(10, 10),
558 InputHandlerClient::Wheel
));
561 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
562 SetupScrollAndContentsLayers(gfx::Size(200, 200));
563 host_impl_
->SetViewportSize(gfx::Size(100, 100));
565 InitializeRendererAndDrawFrame();
567 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
568 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Gesture
));
570 // Trying to scroll to the left/top will not succeed.
571 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
572 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
573 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
575 // Scrolling to the right/bottom will succeed.
576 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)));
577 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)));
578 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)));
580 // Scrolling to left/top will now succeed.
581 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
582 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)));
583 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)));
585 // Scrolling diagonally against an edge will succeed.
586 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)));
587 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)));
588 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)));
590 // Trying to scroll more than the available space will also succeed.
591 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)));
594 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
595 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
596 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
598 InitializeRendererAndDrawFrame();
600 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
601 host_impl_
->ScrollBegin(gfx::Point(),
602 InputHandlerClient::Wheel
));
604 // Trying to scroll without a vertical scrollbar will fail.
605 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
606 gfx::Point(), WebKit::WebScrollbar::ScrollForward
));
607 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
608 gfx::Point(), WebKit::WebScrollbar::ScrollBackward
));
610 scoped_ptr
<cc::ScrollbarLayerImpl
> vertical_scrollbar(
611 cc::ScrollbarLayerImpl::Create(
612 host_impl_
->active_tree(),
614 scoped_ptr
<ScrollbarGeometryFixedThumb
>()));
615 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
616 host_impl_
->RootScrollLayer()->SetVerticalScrollbarLayer(
617 vertical_scrollbar
.get());
619 // Trying to scroll with a vertical scrollbar will succeed.
620 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
621 gfx::Point(), WebKit::WebScrollbar::ScrollForward
));
622 EXPECT_FLOAT_EQ(875.f
, host_impl_
->RootScrollLayer()->scroll_delta().y());
623 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
624 gfx::Point(), WebKit::WebScrollbar::ScrollBackward
));
627 TEST_F(LayerTreeHostImplTest
,
628 ClearRootRenderSurfaceAndHitTestTouchHandlerRegion
) {
629 SetupScrollAndContentsLayers(gfx::Size(100, 100));
630 host_impl_
->SetViewportSize(gfx::Size(50, 50));
631 InitializeRendererAndDrawFrame();
633 // We should be able to hit test for touch event handlers even if the root
634 // layer loses its render surface after the most recent render.
635 host_impl_
->active_tree()->root_layer()->ClearRenderSurface();
636 host_impl_
->active_tree()->set_needs_update_draw_properties();
638 EXPECT_EQ(host_impl_
->HaveTouchEventHandlersAt(gfx::Point()), false);
641 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
642 SetupScrollAndContentsLayers(gfx::Size(100, 100));
643 host_impl_
->SetViewportSize(gfx::Size(50, 50));
644 InitializeRendererAndDrawFrame();
646 LayerImpl
* scroll_layer
= host_impl_
->RootScrollLayer();
647 DCHECK(scroll_layer
);
649 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
650 gfx::Transform identity_scale_transform
;
652 // The impl-based pinch zoom should adjust the max scroll position.
654 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
657 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
658 scroll_layer
->SetImplTransform(identity_scale_transform
);
659 scroll_layer
->SetScrollDelta(gfx::Vector2d());
661 float page_scale_delta
= 2.f
;
662 host_impl_
->PinchGestureBegin();
663 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
664 host_impl_
->PinchGestureEnd();
665 EXPECT_TRUE(did_request_redraw_
);
666 EXPECT_TRUE(did_request_commit_
);
668 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
669 host_impl_
->ProcessScrollDeltas();
670 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
672 EXPECT_EQ(gfx::Vector2d(75, 75),
673 host_impl_
->active_tree()->root_layer()->max_scroll_offset());
676 // Scrolling after a pinch gesture should always be in local space. The
677 // scroll deltas do not have the page scale factor applied.
679 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
682 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
683 scroll_layer
->SetImplTransform(identity_scale_transform
);
684 scroll_layer
->SetScrollDelta(gfx::Vector2d());
686 float page_scale_delta
= 2.f
;
687 host_impl_
->PinchGestureBegin();
688 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
689 host_impl_
->PinchGestureEnd();
691 gfx::Vector2d
scroll_delta(0, 10);
692 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
693 host_impl_
->ScrollBegin(gfx::Point(5, 5),
694 InputHandlerClient::Wheel
));
695 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
696 host_impl_
->ScrollEnd();
698 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
699 host_impl_
->ProcessScrollDeltas();
700 ExpectContains(*scroll_info
.get(),
701 host_impl_
->active_tree()->root_layer()->id(),
706 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
707 SetupScrollAndContentsLayers(gfx::Size(100, 100));
708 host_impl_
->SetViewportSize(gfx::Size(50, 50));
709 InitializeRendererAndDrawFrame();
711 LayerImpl
* scroll_layer
= host_impl_
->RootScrollLayer();
712 DCHECK(scroll_layer
);
714 float min_page_scale
= 1.f
;
715 float max_page_scale
= 4.f
;
716 gfx::Transform identity_scale_transform
;
718 // Basic pinch zoom in gesture
720 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
723 scroll_layer
->SetImplTransform(identity_scale_transform
);
724 scroll_layer
->SetScrollDelta(gfx::Vector2d());
726 float page_scale_delta
= 2.f
;
727 host_impl_
->PinchGestureBegin();
728 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
729 host_impl_
->PinchGestureEnd();
730 EXPECT_TRUE(did_request_redraw_
);
731 EXPECT_TRUE(did_request_commit_
);
733 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
734 host_impl_
->ProcessScrollDeltas();
735 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
740 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
743 scroll_layer
->SetImplTransform(identity_scale_transform
);
744 scroll_layer
->SetScrollDelta(gfx::Vector2d());
745 float page_scale_delta
= 10.f
;
747 host_impl_
->PinchGestureBegin();
748 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
749 host_impl_
->PinchGestureEnd();
751 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
752 host_impl_
->ProcessScrollDeltas();
753 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
758 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
761 scroll_layer
->SetImplTransform(identity_scale_transform
);
762 scroll_layer
->SetScrollDelta(gfx::Vector2d());
763 scroll_layer
->SetScrollOffset(gfx::Vector2d(50, 50));
765 float page_scale_delta
= 0.1f
;
766 host_impl_
->PinchGestureBegin();
767 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
768 host_impl_
->PinchGestureEnd();
770 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
771 host_impl_
->ProcessScrollDeltas();
772 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
774 EXPECT_TRUE(scroll_info
->scrolls
.empty());
777 // Two-finger panning should not happen based on pinch events only
779 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
782 scroll_layer
->SetImplTransform(identity_scale_transform
);
783 scroll_layer
->SetScrollDelta(gfx::Vector2d());
784 scroll_layer
->SetScrollOffset(gfx::Vector2d(20, 20));
786 float page_scale_delta
= 1.f
;
787 host_impl_
->PinchGestureBegin();
788 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
789 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
790 host_impl_
->PinchGestureEnd();
792 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
793 host_impl_
->ProcessScrollDeltas();
794 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
795 EXPECT_TRUE(scroll_info
->scrolls
.empty());
798 // Two-finger panning should work with interleaved scroll events
800 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
803 scroll_layer
->SetImplTransform(identity_scale_transform
);
804 scroll_layer
->SetScrollDelta(gfx::Vector2d());
805 scroll_layer
->SetScrollOffset(gfx::Vector2d(20, 20));
807 float page_scale_delta
= 1.f
;
808 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandlerClient::Wheel
);
809 host_impl_
->PinchGestureBegin();
810 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
811 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
812 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
813 host_impl_
->PinchGestureEnd();
814 host_impl_
->ScrollEnd();
816 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
817 host_impl_
->ProcessScrollDeltas();
818 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
819 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-10, -10));
823 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
824 SetupScrollAndContentsLayers(gfx::Size(100, 100));
825 host_impl_
->SetViewportSize(gfx::Size(50, 50));
826 InitializeRendererAndDrawFrame();
828 LayerImpl
* scroll_layer
= host_impl_
->RootScrollLayer();
829 DCHECK(scroll_layer
);
831 float min_page_scale
= 0.5f
;
832 float max_page_scale
= 4.f
;
833 base::TimeTicks start_time
= base::TimeTicks() +
834 base::TimeDelta::FromSeconds(1);
835 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
836 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
837 base::TimeTicks end_time
= start_time
+ duration
;
838 gfx::Transform identity_scale_transform
;
840 // Non-anchor zoom-in
842 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
845 scroll_layer
->SetImplTransform(identity_scale_transform
);
846 scroll_layer
->SetScrollOffset(gfx::Vector2d(50, 50));
848 host_impl_
->StartPageScaleAnimation(gfx::Vector2d(),
853 host_impl_
->Animate(halfway_through_animation
, base::Time());
854 EXPECT_TRUE(did_request_redraw_
);
855 host_impl_
->Animate(end_time
, base::Time());
856 EXPECT_TRUE(did_request_commit_
);
858 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
859 host_impl_
->ProcessScrollDeltas();
860 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
861 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
866 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
869 scroll_layer
->SetImplTransform(identity_scale_transform
);
870 scroll_layer
->SetScrollOffset(gfx::Vector2d(50, 50));
872 host_impl_
->StartPageScaleAnimation(gfx::Vector2d(25, 25),
875 start_time
, duration
);
876 host_impl_
->Animate(end_time
, base::Time());
877 EXPECT_TRUE(did_request_redraw_
);
878 EXPECT_TRUE(did_request_commit_
);
880 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
881 host_impl_
->ProcessScrollDeltas();
882 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
883 // Pushed to (0,0) via clamping against contents layer size.
884 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
888 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
889 SetupScrollAndContentsLayers(gfx::Size(100, 100));
890 host_impl_
->SetViewportSize(gfx::Size(50, 50));
891 InitializeRendererAndDrawFrame();
893 LayerImpl
* scroll_layer
= host_impl_
->RootScrollLayer();
894 DCHECK(scroll_layer
);
896 float min_page_scale
= 0.5f
;
897 float max_page_scale
= 4.f
;
898 base::TimeTicks start_time
= base::TimeTicks() +
899 base::TimeDelta::FromSeconds(1);
900 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
901 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
902 base::TimeTicks end_time
= start_time
+ duration
;
903 gfx::Transform identity_scale_transform
;
905 // Anchor zoom with unchanged page scale should not change scroll or scale.
907 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
,
910 scroll_layer
->SetImplTransform(identity_scale_transform
);
911 scroll_layer
->SetScrollOffset(gfx::Vector2d(50, 50));
913 host_impl_
->StartPageScaleAnimation(gfx::Vector2d(),
918 host_impl_
->Animate(halfway_through_animation
, base::Time());
919 EXPECT_TRUE(did_request_redraw_
);
920 host_impl_
->Animate(end_time
, base::Time());
921 EXPECT_TRUE(did_request_commit_
);
923 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
924 host_impl_
->ProcessScrollDeltas();
925 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
926 ExpectNone(*scroll_info
, scroll_layer
->id());
930 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
931 SetupScrollAndContentsLayers(gfx::Size(100, 100));
932 host_impl_
->SetViewportSize(gfx::Size(50, 50));
933 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 0.5f
, 4.f
);
934 InitializeRendererAndDrawFrame();
936 CompositorFrameMetadata metadata
=
937 host_impl_
->MakeCompositorFrameMetadata();
938 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
939 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
940 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.viewport_size
);
941 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
942 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
943 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
946 // Scrolling should update metadata immediately.
947 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
948 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
949 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
951 CompositorFrameMetadata metadata
=
952 host_impl_
->MakeCompositorFrameMetadata();
953 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
955 host_impl_
->ScrollEnd();
957 CompositorFrameMetadata metadata
=
958 host_impl_
->MakeCompositorFrameMetadata();
959 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
962 // Page scale should update metadata correctly (shrinking only the viewport).
963 host_impl_
->PinchGestureBegin();
964 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
965 host_impl_
->PinchGestureEnd();
967 CompositorFrameMetadata metadata
=
968 host_impl_
->MakeCompositorFrameMetadata();
969 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
970 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
971 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.viewport_size
);
972 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
973 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
974 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
977 // Likewise if set from the main thread.
978 host_impl_
->ProcessScrollDeltas();
979 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(4.f
, 0.5f
, 4.f
);
980 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
982 CompositorFrameMetadata metadata
=
983 host_impl_
->MakeCompositorFrameMetadata();
984 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
985 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
986 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.viewport_size
);
987 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
988 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
989 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
993 class DidDrawCheckLayer
: public TiledLayerImpl
{
995 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
996 return scoped_ptr
<LayerImpl
>(new DidDrawCheckLayer(tree_impl
, id
));
999 virtual void DidDraw(ResourceProvider
* provider
) OVERRIDE
{
1000 did_draw_called_
= true;
1003 virtual void WillDraw(ResourceProvider
* provider
) OVERRIDE
{
1004 will_draw_called_
= true;
1007 bool did_draw_called() const { return did_draw_called_
; }
1008 bool will_draw_called() const { return will_draw_called_
; }
1010 void ClearDidDrawCheck() {
1011 did_draw_called_
= false;
1012 will_draw_called_
= false;
1016 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
1017 : TiledLayerImpl(tree_impl
, id
),
1018 did_draw_called_(false),
1019 will_draw_called_(false) {
1020 SetAnchorPoint(gfx::PointF());
1021 SetBounds(gfx::Size(10, 10));
1022 SetContentBounds(gfx::Size(10, 10));
1023 SetDrawsContent(true);
1024 set_skips_draw(false);
1025 draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
1027 scoped_ptr
<LayerTilingData
> tiler
=
1028 LayerTilingData::Create(gfx::Size(100, 100),
1029 LayerTilingData::HAS_BORDER_TEXELS
);
1030 tiler
->SetBounds(content_bounds());
1031 SetTilingData(*tiler
.get());
1035 bool did_draw_called_
;
1036 bool will_draw_called_
;
1039 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
1040 // The root layer is always drawn, so run this test on a child layer that
1041 // will be masked out by the root layer's bounds.
1042 host_impl_
->active_tree()->SetRootLayer(
1043 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1044 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
1045 host_impl_
->active_tree()->root_layer());
1046 root
->SetMasksToBounds(true);
1048 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
1049 DidDrawCheckLayer
* layer
=
1050 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
1051 // Ensure visible_content_rect for layer is empty.
1052 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
1053 layer
->SetBounds(gfx::Size(10, 10));
1054 layer
->SetContentBounds(gfx::Size(10, 10));
1056 LayerTreeHostImpl::FrameData frame
;
1058 EXPECT_FALSE(layer
->will_draw_called());
1059 EXPECT_FALSE(layer
->did_draw_called());
1061 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1062 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1063 host_impl_
->DidDrawAllLayers(frame
);
1065 EXPECT_FALSE(layer
->will_draw_called());
1066 EXPECT_FALSE(layer
->did_draw_called());
1068 EXPECT_TRUE(layer
->visible_content_rect().IsEmpty());
1070 // Ensure visible_content_rect for layer is not empty
1071 layer
->SetPosition(gfx::PointF());
1073 EXPECT_FALSE(layer
->will_draw_called());
1074 EXPECT_FALSE(layer
->did_draw_called());
1076 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1077 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1078 host_impl_
->DidDrawAllLayers(frame
);
1080 EXPECT_TRUE(layer
->will_draw_called());
1081 EXPECT_TRUE(layer
->did_draw_called());
1083 EXPECT_FALSE(layer
->visible_content_rect().IsEmpty());
1086 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
1087 gfx::Size
big_size(1000, 1000);
1088 host_impl_
->SetViewportSize(big_size
);
1090 host_impl_
->active_tree()->SetRootLayer(
1091 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1092 DidDrawCheckLayer
* root
=
1093 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1095 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
1096 DidDrawCheckLayer
* occluded_layer
=
1097 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
1099 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
1100 DidDrawCheckLayer
* top_layer
=
1101 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
1102 // This layer covers the occluded_layer above. Make this layer large so it can
1104 top_layer
->SetBounds(big_size
);
1105 top_layer
->SetContentBounds(big_size
);
1106 top_layer
->SetContentsOpaque(true);
1108 LayerTreeHostImpl::FrameData frame
;
1110 EXPECT_FALSE(occluded_layer
->will_draw_called());
1111 EXPECT_FALSE(occluded_layer
->did_draw_called());
1112 EXPECT_FALSE(top_layer
->will_draw_called());
1113 EXPECT_FALSE(top_layer
->did_draw_called());
1115 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1116 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1117 host_impl_
->DidDrawAllLayers(frame
);
1119 EXPECT_FALSE(occluded_layer
->will_draw_called());
1120 EXPECT_FALSE(occluded_layer
->did_draw_called());
1121 EXPECT_TRUE(top_layer
->will_draw_called());
1122 EXPECT_TRUE(top_layer
->did_draw_called());
1125 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
1126 host_impl_
->active_tree()->SetRootLayer(
1127 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1128 DidDrawCheckLayer
* root
=
1129 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1131 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
1132 DidDrawCheckLayer
* layer1
=
1133 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
1135 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
1136 DidDrawCheckLayer
* layer2
=
1137 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
1139 layer1
->SetOpacity(0.3f
);
1140 layer1
->SetPreserves3d(false);
1142 EXPECT_FALSE(root
->did_draw_called());
1143 EXPECT_FALSE(layer1
->did_draw_called());
1144 EXPECT_FALSE(layer2
->did_draw_called());
1146 LayerTreeHostImpl::FrameData frame
;
1147 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1148 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1149 host_impl_
->DidDrawAllLayers(frame
);
1151 EXPECT_TRUE(root
->did_draw_called());
1152 EXPECT_TRUE(layer1
->did_draw_called());
1153 EXPECT_TRUE(layer2
->did_draw_called());
1155 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
1156 EXPECT_TRUE(!!layer1
->render_surface());
1159 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
1161 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
1166 ResourceProvider
* resource_provider
) {
1167 return scoped_ptr
<LayerImpl
>(new MissingTextureAnimatingLayer(
1173 resource_provider
));
1177 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
1182 ResourceProvider
* resource_provider
)
1183 : DidDrawCheckLayer(tree_impl
, id
) {
1184 scoped_ptr
<LayerTilingData
> tiling_data
=
1185 LayerTilingData::Create(gfx::Size(10, 10),
1186 LayerTilingData::NO_BORDER_TEXELS
);
1187 tiling_data
->SetBounds(bounds());
1188 SetTilingData(*tiling_data
.get());
1189 set_skips_draw(skips_draw
);
1190 if (!tile_missing
) {
1191 ResourceProvider::ResourceId resource
=
1192 resource_provider
->CreateResource(gfx::Size(),
1194 ResourceProvider::TextureUsageAny
);
1195 resource_provider
->AllocateForTesting(resource
);
1196 PushTileProperties(0, 0, resource
, gfx::Rect(), false);
1199 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
1203 TEST_F(LayerTreeHostImplTest
, PrepareToDrawFailsWhenAnimationUsesCheckerboard
) {
1204 // When the texture is not missing, we draw as usual.
1205 host_impl_
->active_tree()->SetRootLayer(
1206 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
1207 DidDrawCheckLayer
* root
=
1208 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1210 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
1215 host_impl_
->resource_provider()));
1217 LayerTreeHostImpl::FrameData frame
;
1219 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1220 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1221 host_impl_
->DidDrawAllLayers(frame
);
1223 // When a texture is missing and we're not animating, we draw as usual with
1225 host_impl_
->active_tree()->SetRootLayer(
1226 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
1228 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1230 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
1235 host_impl_
->resource_provider()));
1237 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1238 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1239 host_impl_
->DidDrawAllLayers(frame
);
1241 // When a texture is missing and we're animating, we don't want to draw
1243 host_impl_
->active_tree()->SetRootLayer(
1244 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 5));
1246 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1248 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
1253 host_impl_
->resource_provider()));
1255 EXPECT_FALSE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1256 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1257 host_impl_
->DidDrawAllLayers(frame
);
1259 // When the layer skips draw and we're animating, we still draw the frame.
1260 host_impl_
->active_tree()->SetRootLayer(
1261 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 7));
1263 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
1265 MissingTextureAnimatingLayer::Create(host_impl_
->active_tree(),
1270 host_impl_
->resource_provider()));
1272 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1273 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1274 host_impl_
->DidDrawAllLayers(frame
);
1277 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
1278 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
1279 root
->SetScrollable(false);
1280 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1281 InitializeRendererAndDrawFrame();
1283 // Scroll event is ignored because layer is not scrollable.
1284 EXPECT_EQ(InputHandlerClient::ScrollIgnored
,
1285 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
1286 EXPECT_FALSE(did_request_redraw_
);
1287 EXPECT_FALSE(did_request_commit_
);
1290 TEST_F(LayerTreeHostImplTest
, ScrollNonScrollableRootWithTopControls
) {
1291 LayerTreeSettings settings
;
1292 settings
.calculate_top_controls_position
= true;
1293 settings
.top_controls_height
= 50;
1295 host_impl_
= LayerTreeHostImpl::Create(settings
,
1298 &stats_instrumentation_
);
1299 host_impl_
->InitializeRenderer(CreateOutputSurface());
1300 host_impl_
->SetViewportSize(gfx::Size(10, 10));
1302 gfx::Size
layer_size(5, 5);
1303 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
1304 root
->SetScrollable(true);
1305 root
->SetMaxScrollOffset(gfx::Vector2d(layer_size
.width(),
1306 layer_size
.height()));
1307 root
->SetBounds(layer_size
);
1308 root
->SetContentBounds(layer_size
);
1309 root
->SetPosition(gfx::PointF());
1310 root
->SetAnchorPoint(gfx::PointF());
1311 root
->SetDrawsContent(false);
1312 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1313 host_impl_
->active_tree()->FindRootScrollLayer();
1314 InitializeRendererAndDrawFrame();
1316 EXPECT_EQ(InputHandlerClient::ScrollIgnored
,
1317 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Gesture
));
1319 host_impl_
->top_controls_manager()->ScrollBegin();
1320 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
1321 host_impl_
->top_controls_manager()->ScrollEnd();
1322 EXPECT_EQ(host_impl_
->top_controls_manager()->content_top_offset(), 0.f
);
1324 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1325 host_impl_
->ScrollBegin(gfx::Point(),
1326 InputHandlerClient::Gesture
));
1329 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
1330 // Test the configuration where a non-composited root layer is embedded in a
1331 // scrollable outer layer.
1332 gfx::Size
surface_size(10, 10);
1334 scoped_ptr
<LayerImpl
> content_layer
=
1335 LayerImpl::Create(host_impl_
->active_tree(), 1);
1336 content_layer
->SetDrawsContent(true);
1337 content_layer
->SetPosition(gfx::PointF());
1338 content_layer
->SetAnchorPoint(gfx::PointF());
1339 content_layer
->SetBounds(surface_size
);
1340 content_layer
->SetContentBounds(gfx::Size(surface_size
.width() * 2,
1341 surface_size
.height() * 2));
1342 content_layer
->SetContentsScale(2.f
, 2.f
);
1344 scoped_ptr
<LayerImpl
> scroll_layer
=
1345 LayerImpl::Create(host_impl_
->active_tree(), 2);
1346 scroll_layer
->SetScrollable(true);
1347 scroll_layer
->SetMaxScrollOffset(gfx::Vector2d(surface_size
.width(),
1348 surface_size
.height()));
1349 scroll_layer
->SetBounds(surface_size
);
1350 scroll_layer
->SetContentBounds(surface_size
);
1351 scroll_layer
->SetPosition(gfx::PointF());
1352 scroll_layer
->SetAnchorPoint(gfx::PointF());
1353 scroll_layer
->AddChild(content_layer
.Pass());
1355 host_impl_
->active_tree()->SetRootLayer(scroll_layer
.Pass());
1356 host_impl_
->SetViewportSize(surface_size
);
1357 InitializeRendererAndDrawFrame();
1359 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1360 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1361 InputHandlerClient::Wheel
));
1362 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1363 host_impl_
->ScrollEnd();
1364 EXPECT_TRUE(did_request_redraw_
);
1365 EXPECT_TRUE(did_request_commit_
);
1368 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
1369 gfx::Size
surface_size(10, 10);
1370 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
1371 root
->SetBounds(surface_size
);
1372 root
->SetContentBounds(surface_size
);
1373 root
->AddChild(CreateScrollableLayer(2, surface_size
));
1374 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1375 host_impl_
->SetViewportSize(surface_size
);
1376 InitializeRendererAndDrawFrame();
1378 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1379 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1380 InputHandlerClient::Wheel
));
1381 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1382 host_impl_
->ScrollEnd();
1383 EXPECT_TRUE(did_request_redraw_
);
1384 EXPECT_TRUE(did_request_commit_
);
1387 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
1388 gfx::Size
surface_size(10, 10);
1389 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
1390 root
->AddChild(CreateScrollableLayer(2, surface_size
));
1391 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1392 host_impl_
->SetViewportSize(surface_size
);
1393 InitializeRendererAndDrawFrame();
1395 // Scroll event is ignored because the input coordinate is outside the layer
1397 EXPECT_EQ(InputHandlerClient::ScrollIgnored
,
1398 host_impl_
->ScrollBegin(gfx::Point(15, 5),
1399 InputHandlerClient::Wheel
));
1400 EXPECT_FALSE(did_request_redraw_
);
1401 EXPECT_FALSE(did_request_commit_
);
1404 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
1405 gfx::Size
surface_size(10, 10);
1406 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
1407 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(2, surface_size
);
1408 host_impl_
->SetViewportSize(surface_size
);
1410 gfx::Transform matrix
;
1411 matrix
.RotateAboutXAxis(180.0);
1412 child
->SetTransform(matrix
);
1413 child
->SetDoubleSided(false);
1415 root
->AddChild(child
.Pass());
1416 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1417 InitializeRendererAndDrawFrame();
1419 // Scroll event is ignored because the scrollable layer is not facing the
1420 // viewer and there is nothing scrollable behind it.
1421 EXPECT_EQ(InputHandlerClient::ScrollIgnored
,
1422 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1423 InputHandlerClient::Wheel
));
1424 EXPECT_FALSE(did_request_redraw_
);
1425 EXPECT_FALSE(did_request_commit_
);
1428 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
1429 gfx::Size
surface_size(10, 10);
1430 scoped_ptr
<LayerImpl
> content_layer
= CreateScrollableLayer(1, surface_size
);
1431 content_layer
->SetShouldScrollOnMainThread(true);
1432 content_layer
->SetScrollable(false);
1434 scoped_ptr
<LayerImpl
> scroll_layer
= CreateScrollableLayer(2, surface_size
);
1435 scroll_layer
->AddChild(content_layer
.Pass());
1437 host_impl_
->active_tree()->SetRootLayer(scroll_layer
.Pass());
1438 host_impl_
->SetViewportSize(surface_size
);
1439 InitializeRendererAndDrawFrame();
1441 // Scrolling fails because the content layer is asking to be scrolled on the
1443 EXPECT_EQ(InputHandlerClient::ScrollOnMainThread
,
1444 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1445 InputHandlerClient::Wheel
));
1448 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
1449 gfx::Size
surface_size(10, 10);
1450 float page_scale
= 2.f
;
1451 scoped_ptr
<LayerImpl
> root
= CreateScrollableLayer(1, surface_size
);
1452 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1453 host_impl_
->active_tree()->DidBecomeActive();
1454 host_impl_
->SetViewportSize(surface_size
);
1455 InitializeRendererAndDrawFrame();
1457 gfx::Vector2d
scroll_delta(0, 10);
1458 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
1459 gfx::Vector2d expected_max_scroll
=
1460 host_impl_
->active_tree()->root_layer()->max_scroll_offset();
1461 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1462 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1463 InputHandlerClient::Wheel
));
1464 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1465 host_impl_
->ScrollEnd();
1467 // Set new page scale from main thread.
1468 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(page_scale
,
1472 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1473 ExpectContains(*scroll_info
.get(),
1474 host_impl_
->active_tree()->root_layer()->id(),
1475 expected_scroll_delta
);
1477 // The scroll range should also have been updated.
1478 EXPECT_EQ(expected_max_scroll
,
1479 host_impl_
->active_tree()->root_layer()->max_scroll_offset());
1481 // The page scale delta remains constant because the impl thread did not
1483 // TODO(shawnsingh): If possible, use gfx::Transform() or Skia equality
1484 // functions. At the moment we avoid that because skia does exact bit-wise
1485 // equality checking that does not consider -0 == +0.
1486 // http://code.google.com/p/chromium/issues/detail?id=162747
1488 host_impl_
->active_tree()->root_layer()->
1489 impl_transform().matrix().getDouble(0, 0));
1491 host_impl_
->active_tree()->root_layer()->
1492 impl_transform().matrix().getDouble(0, 1));
1494 host_impl_
->active_tree()->root_layer()->
1495 impl_transform().matrix().getDouble(0, 2));
1497 host_impl_
->active_tree()->root_layer()->
1498 impl_transform().matrix().getDouble(0, 3));
1500 host_impl_
->active_tree()->root_layer()->
1501 impl_transform().matrix().getDouble(1, 0));
1503 host_impl_
->active_tree()->root_layer()->
1504 impl_transform().matrix().getDouble(1, 1));
1506 host_impl_
->active_tree()->root_layer()->
1507 impl_transform().matrix().getDouble(1, 2));
1509 host_impl_
->active_tree()->root_layer()->
1510 impl_transform().matrix().getDouble(1, 3));
1512 host_impl_
->active_tree()->root_layer()->
1513 impl_transform().matrix().getDouble(2, 0));
1515 host_impl_
->active_tree()->root_layer()->
1516 impl_transform().matrix().getDouble(2, 1));
1518 host_impl_
->active_tree()->root_layer()->
1519 impl_transform().matrix().getDouble(2, 2));
1521 host_impl_
->active_tree()->root_layer()->
1522 impl_transform().matrix().getDouble(2, 3));
1524 host_impl_
->active_tree()->root_layer()->
1525 impl_transform().matrix().getDouble(3, 0));
1527 host_impl_
->active_tree()->root_layer()->
1528 impl_transform().matrix().getDouble(3, 1));
1530 host_impl_
->active_tree()->root_layer()->
1531 impl_transform().matrix().getDouble(3, 2));
1533 host_impl_
->active_tree()->root_layer()->
1534 impl_transform().matrix().getDouble(3, 3));
1537 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
1538 gfx::Size
surface_size(10, 10);
1539 float page_scale
= 2.f
;
1540 scoped_ptr
<LayerImpl
> root
= CreateScrollableLayer(1, surface_size
);
1541 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1542 host_impl_
->active_tree()->DidBecomeActive();
1543 host_impl_
->SetViewportSize(surface_size
);
1544 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(1.f
, 1.f
, page_scale
);
1545 InitializeRendererAndDrawFrame();
1547 gfx::Vector2d
scroll_delta(0, 10);
1548 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
1549 gfx::Vector2d expected_max_scroll
=
1550 host_impl_
->active_tree()->root_layer()->max_scroll_offset();
1551 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1552 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1553 InputHandlerClient::Wheel
));
1554 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1555 host_impl_
->ScrollEnd();
1557 // Set new page scale on impl thread by pinching.
1558 host_impl_
->PinchGestureBegin();
1559 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
1560 host_impl_
->PinchGestureEnd();
1563 // The scroll delta is not scaled because the main thread did not scale.
1564 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1565 ExpectContains(*scroll_info
.get(),
1566 host_impl_
->active_tree()->root_layer()->id(),
1567 expected_scroll_delta
);
1569 // The scroll range should also have been updated.
1570 EXPECT_EQ(expected_max_scroll
,
1571 host_impl_
->active_tree()->root_layer()->max_scroll_offset());
1573 // The page scale delta should match the new scale on the impl side.
1574 gfx::Transform expected_scale
;
1575 expected_scale
.Scale(page_scale
, page_scale
);
1576 EXPECT_EQ(expected_scale
,
1577 host_impl_
->active_tree()->root_layer()->impl_transform());
1580 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
1581 gfx::Size
surface_size(10, 10);
1582 float default_page_scale
= 1.f
;
1583 gfx::Transform default_page_scale_matrix
;
1584 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
1586 float new_page_scale
= 2.f
;
1587 gfx::Transform new_page_scale_matrix
;
1588 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
1590 // Create a normal scrollable root layer and another scrollable child layer.
1591 SetupScrollAndContentsLayers(surface_size
);
1592 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
1593 LayerImpl
* child
= root
->children()[0];
1595 scoped_ptr
<LayerImpl
> scrollable_child
=
1596 CreateScrollableLayer(3, surface_size
);
1597 child
->AddChild(scrollable_child
.Pass());
1598 LayerImpl
* grand_child
= child
->children()[0];
1600 // Set new page scale on impl thread by pinching.
1601 host_impl_
->PinchGestureBegin();
1602 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
1603 host_impl_
->PinchGestureEnd();
1606 // The page scale delta should only be applied to the scrollable root layer.
1607 EXPECT_EQ(root
->impl_transform(), new_page_scale_matrix
);
1608 EXPECT_EQ(child
->impl_transform(), default_page_scale_matrix
);
1609 EXPECT_EQ(grand_child
->impl_transform(), default_page_scale_matrix
);
1611 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
1612 // the page scale delta on the root layer is applied hierarchically.
1613 LayerTreeHostImpl::FrameData frame
;
1614 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
1615 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
1616 host_impl_
->DidDrawAllLayers(frame
);
1618 EXPECT_EQ(new_page_scale
, root
->draw_transform().matrix().getDouble(0, 0));
1619 EXPECT_EQ(new_page_scale
, root
->draw_transform().matrix().getDouble(1, 1));
1620 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
1621 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
1622 EXPECT_EQ(new_page_scale
,
1623 grand_child
->draw_transform().matrix().getDouble(0, 0));
1624 EXPECT_EQ(new_page_scale
,
1625 grand_child
->draw_transform().matrix().getDouble(1, 1));
1628 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
1629 gfx::Size
surface_size(10, 10);
1630 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
1631 root
->SetBounds(surface_size
);
1632 root
->SetContentBounds(surface_size
);
1633 // Also mark the root scrollable so it becomes the root scroll layer.
1634 root
->SetScrollable(true);
1635 int scroll_layer_id
= 2;
1636 root
->AddChild(CreateScrollableLayer(scroll_layer_id
, surface_size
));
1637 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1638 host_impl_
->active_tree()->DidBecomeActive();
1639 host_impl_
->SetViewportSize(surface_size
);
1640 InitializeRendererAndDrawFrame();
1642 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
1644 gfx::Vector2d
scroll_delta(0, 10);
1645 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
1646 gfx::Vector2d
expected_max_scroll(child
->max_scroll_offset());
1647 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1648 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1649 InputHandlerClient::Wheel
));
1650 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1651 host_impl_
->ScrollEnd();
1653 float page_scale
= 2.f
;
1654 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(page_scale
,
1660 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1661 ExpectContains(*scroll_info
.get(), scroll_layer_id
, expected_scroll_delta
);
1663 // The scroll range should not have changed.
1664 EXPECT_EQ(child
->max_scroll_offset(), expected_max_scroll
);
1666 // The page scale delta remains constant because the impl thread did not
1668 gfx::Transform identity_transform
;
1669 EXPECT_EQ(child
->impl_transform(), gfx::Transform());
1672 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
1673 // Scroll a child layer beyond its maximum scroll range and make sure the
1674 // parent layer is scrolled on the axis on which the child was unable to
1676 gfx::Size
surface_size(10, 10);
1677 scoped_ptr
<LayerImpl
> root
= CreateScrollableLayer(1, surface_size
);
1679 scoped_ptr
<LayerImpl
> grand_child
= CreateScrollableLayer(3, surface_size
);
1680 grand_child
->SetScrollOffset(gfx::Vector2d(0, 5));
1682 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(2, surface_size
);
1683 child
->SetScrollOffset(gfx::Vector2d(3, 0));
1684 child
->AddChild(grand_child
.Pass());
1686 root
->AddChild(child
.Pass());
1687 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1688 host_impl_
->active_tree()->DidBecomeActive();
1689 host_impl_
->SetViewportSize(surface_size
);
1690 InitializeRendererAndDrawFrame();
1692 gfx::Vector2d
scroll_delta(-8, -7);
1693 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1694 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1695 InputHandlerClient::Wheel
));
1696 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1697 host_impl_
->ScrollEnd();
1699 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1700 host_impl_
->ProcessScrollDeltas();
1702 // The grand child should have scrolled up to its limit.
1703 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
1704 LayerImpl
* grand_child
= child
->children()[0];
1705 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -5));
1707 // The child should have only scrolled on the other axis.
1708 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(-3, 0));
1712 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
1713 // Scroll a child layer beyond its maximum scroll range and make sure the
1714 // the scroll doesn't bubble up to the parent layer.
1715 gfx::Size
surface_size(10, 10);
1716 scoped_ptr
<LayerImpl
> root
= CreateScrollableLayer(1, surface_size
);
1718 scoped_ptr
<LayerImpl
> grand_child
= CreateScrollableLayer(3, surface_size
);
1719 grand_child
->SetScrollOffset(gfx::Vector2d(0, 2));
1721 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(2, surface_size
);
1722 child
->SetScrollOffset(gfx::Vector2d(0, 3));
1723 child
->AddChild(grand_child
.Pass());
1725 root
->AddChild(child
.Pass());
1726 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1727 host_impl_
->active_tree()->DidBecomeActive();
1728 host_impl_
->SetViewportSize(surface_size
);
1729 InitializeRendererAndDrawFrame();
1731 gfx::Vector2d
scroll_delta(0, -10);
1732 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1733 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1734 InputHandlerClient::NonBubblingGesture
));
1735 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1736 host_impl_
->ScrollEnd();
1738 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1739 host_impl_
->ProcessScrollDeltas();
1741 // The grand child should have scrolled up to its limit.
1742 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
1743 LayerImpl
* grand_child
= child
->children()[0];
1744 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
1746 // The child should not have scrolled.
1747 ExpectNone(*scroll_info
.get(), child
->id());
1749 // The next time we scroll we should only scroll the parent.
1750 scroll_delta
= gfx::Vector2d(0, -3);
1751 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1752 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1753 InputHandlerClient::NonBubblingGesture
));
1754 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
1755 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1756 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
1757 host_impl_
->ScrollEnd();
1759 scroll_info
= host_impl_
->ProcessScrollDeltas();
1761 // The child should have scrolled up to its limit.
1762 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
1764 // The grand child should not have scrolled.
1765 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
1767 // After scrolling the parent, another scroll on the opposite direction
1768 // should still scroll the child.
1769 scroll_delta
= gfx::Vector2d(0, 7);
1770 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1771 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1772 InputHandlerClient::NonBubblingGesture
));
1773 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
1774 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1775 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
1776 host_impl_
->ScrollEnd();
1778 scroll_info
= host_impl_
->ProcessScrollDeltas();
1780 // The grand child should have scrolled.
1781 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 5));
1783 // The child should not have scrolled.
1784 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
1787 // Scrolling should be adjusted from viewport space.
1788 host_impl_
->active_tree()->SetPageScaleFactorAndLimits(2.f
, 2.f
, 2.f
);
1789 host_impl_
->active_tree()->SetPageScaleDelta(1.f
);
1790 gfx::Transform scale_transform
;
1791 scale_transform
.Scale(2.f
, 2.f
);
1792 host_impl_
->active_tree()->root_layer()->SetImplTransform(scale_transform
);
1794 scroll_delta
= gfx::Vector2d(0, -2);
1795 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1796 host_impl_
->ScrollBegin(gfx::Point(1, 1),
1797 InputHandlerClient::NonBubblingGesture
));
1798 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
1799 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1800 host_impl_
->ScrollEnd();
1802 scroll_info
= host_impl_
->ProcessScrollDeltas();
1804 // Should have scrolled by half the amount in layer space (5 - 2/2)
1805 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 4));
1809 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
1810 // When we try to scroll a non-scrollable child layer, the scroll delta
1811 // should be applied to one of its ancestors if possible.
1812 gfx::Size
surface_size(10, 10);
1813 gfx::Size
content_size(20, 20);
1814 scoped_ptr
<LayerImpl
> root
= CreateScrollableLayer(1, content_size
);
1815 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(2, content_size
);
1817 child
->SetScrollable(false);
1818 root
->AddChild(child
.Pass());
1820 host_impl_
->SetViewportSize(surface_size
);
1821 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1822 host_impl_
->active_tree()->DidBecomeActive();
1823 InitializeRendererAndDrawFrame();
1825 gfx::Vector2d
scroll_delta(0, 4);
1826 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1827 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1828 InputHandlerClient::Wheel
));
1829 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1830 host_impl_
->ScrollEnd();
1832 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1833 host_impl_
->ProcessScrollDeltas();
1835 // Only the root should have scrolled.
1836 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
1837 ExpectContains(*scroll_info
.get(),
1838 host_impl_
->active_tree()->root_layer()->id(),
1843 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
1844 gfx::Size
surface_size(10, 10);
1845 host_impl_
->active_tree()->SetRootLayer(
1846 CreateScrollableLayer(1, surface_size
));
1847 host_impl_
->active_tree()->DidBecomeActive();
1848 host_impl_
->SetViewportSize(surface_size
);
1850 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
1852 InitializeRendererAndDrawFrame();
1853 host_impl_
->active_tree()->DetachLayerTree();
1854 host_impl_
->active_tree()->SetRootLayer(
1855 CreateScrollableLayer(2, surface_size
));
1856 host_impl_
->active_tree()->DidBecomeActive();
1858 // Scrolling should still work even though we did not draw yet.
1859 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1860 host_impl_
->ScrollBegin(gfx::Point(5, 5),
1861 InputHandlerClient::Wheel
));
1864 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
1865 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1867 // Rotate the root layer 90 degrees counter-clockwise about its center.
1868 gfx::Transform rotate_transform
;
1869 rotate_transform
.Rotate(-90.0);
1870 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
1872 gfx::Size
surface_size(50, 50);
1873 host_impl_
->SetViewportSize(surface_size
);
1874 InitializeRendererAndDrawFrame();
1876 // Scroll to the right in screen coordinates with a gesture.
1877 gfx::Vector2d
gesture_scroll_delta(10, 0);
1878 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1879 host_impl_
->ScrollBegin(gfx::Point(),
1880 InputHandlerClient::Gesture
));
1881 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
1882 host_impl_
->ScrollEnd();
1884 // The layer should have scrolled down in its local coordinates.
1885 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1886 ExpectContains(*scroll_info
.get(),
1887 host_impl_
->active_tree()->root_layer()->id(),
1888 gfx::Vector2d(0, gesture_scroll_delta
.x()));
1890 // Reset and scroll down with the wheel.
1891 host_impl_
->active_tree()->root_layer()->SetScrollDelta(gfx::Vector2dF());
1892 gfx::Vector2d
wheel_scroll_delta(0, 10);
1893 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1894 host_impl_
->ScrollBegin(gfx::Point(),
1895 InputHandlerClient::Wheel
));
1896 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
1897 host_impl_
->ScrollEnd();
1899 // The layer should have scrolled down in its local coordinates.
1900 scroll_info
= host_impl_
->ProcessScrollDeltas();
1901 ExpectContains(*scroll_info
.get(),
1902 host_impl_
->active_tree()->root_layer()->id(),
1903 wheel_scroll_delta
);
1906 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
1907 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1908 int child_layer_id
= 3;
1909 float child_layer_angle
= -20.f
;
1911 // Create a child layer that is rotated to a non-axis-aligned angle.
1912 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
1914 host_impl_
->active_tree()->root_layer()->content_bounds());
1915 gfx::Transform rotate_transform
;
1916 rotate_transform
.Translate(-50.0, -50.0);
1917 rotate_transform
.Rotate(child_layer_angle
);
1918 rotate_transform
.Translate(50.0, 50.0);
1919 child
->SetTransform(rotate_transform
);
1921 // Only allow vertical scrolling.
1922 child
->SetMaxScrollOffset(gfx::Vector2d(0, child
->content_bounds().height()));
1923 host_impl_
->active_tree()->root_layer()->AddChild(child
.Pass());
1925 gfx::Size
surface_size(50, 50);
1926 host_impl_
->SetViewportSize(surface_size
);
1927 InitializeRendererAndDrawFrame();
1929 // Scroll down in screen coordinates with a gesture.
1930 gfx::Vector2d
gesture_scroll_delta(0, 10);
1931 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1932 host_impl_
->ScrollBegin(gfx::Point(),
1933 InputHandlerClient::Gesture
));
1934 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
1935 host_impl_
->ScrollEnd();
1937 // The child layer should have scrolled down in its local coordinates an
1938 // amount proportional to the angle between it and the input scroll delta.
1939 gfx::Vector2d
expected_scroll_delta(
1941 gesture_scroll_delta
.y() *
1942 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
1943 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1944 host_impl_
->ProcessScrollDeltas();
1945 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
1947 // The root layer should not have scrolled, because the input delta was
1948 // close to the layer's axis of movement.
1949 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
1952 // Now reset and scroll the same amount horizontally.
1953 host_impl_
->active_tree()->root_layer()->children()[1]->SetScrollDelta(
1955 gfx::Vector2d
gesture_scroll_delta(10, 0);
1956 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
1957 host_impl_
->ScrollBegin(gfx::Point(),
1958 InputHandlerClient::Gesture
));
1959 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
1960 host_impl_
->ScrollEnd();
1962 // The child layer should have scrolled down in its local coordinates an
1963 // amount proportional to the angle between it and the input scroll delta.
1964 gfx::Vector2d
expected_scroll_delta(
1966 -gesture_scroll_delta
.x() *
1967 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
1968 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1969 host_impl_
->ProcessScrollDeltas();
1970 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
1972 // The root layer should have scrolled more, since the input scroll delta
1973 // was mostly orthogonal to the child layer's vertical scroll axis.
1974 gfx::Vector2d
expected_root_scroll_delta(
1975 gesture_scroll_delta
.x() *
1976 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
1978 ExpectContains(*scroll_info
.get(),
1979 host_impl_
->active_tree()->root_layer()->id(),
1980 expected_root_scroll_delta
);
1984 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
1985 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1987 // Scale the layer to twice its normal size.
1989 gfx::Transform scale_transform
;
1990 scale_transform
.Scale(scale
, scale
);
1991 host_impl_
->active_tree()->root_layer()->SetTransform(scale_transform
);
1993 gfx::Size
surface_size(50, 50);
1994 host_impl_
->SetViewportSize(surface_size
);
1995 InitializeRendererAndDrawFrame();
1997 // Scroll down in screen coordinates with a gesture.
1998 gfx::Vector2d
scroll_delta(0, 10);
1999 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
2000 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Gesture
));
2001 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2002 host_impl_
->ScrollEnd();
2004 // The layer should have scrolled down in its local coordinates, but half the
2006 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
2007 ExpectContains(*scroll_info
.get(),
2008 host_impl_
->active_tree()->root_layer()->id(),
2009 gfx::Vector2d(0, scroll_delta
.y() / scale
));
2011 // Reset and scroll down with the wheel.
2012 host_impl_
->active_tree()->root_layer()->SetScrollDelta(gfx::Vector2dF());
2013 gfx::Vector2d
wheel_scroll_delta(0, 10);
2014 EXPECT_EQ(InputHandlerClient::ScrollStarted
,
2015 host_impl_
->ScrollBegin(gfx::Point(), InputHandlerClient::Wheel
));
2016 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
2017 host_impl_
->ScrollEnd();
2019 // The scale should not have been applied to the scroll delta.
2020 scroll_info
= host_impl_
->ProcessScrollDeltas();
2021 ExpectContains(*scroll_info
.get(),
2022 host_impl_
->active_tree()->root_layer()->id(),
2023 wheel_scroll_delta
);
2026 class BlendStateTrackerContext
: public TestWebGraphicsContext3D
{
2028 BlendStateTrackerContext() : blend_(false) {}
2030 virtual void enable(WebKit::WGC3Denum cap
) OVERRIDE
{
2031 if (cap
== GL_BLEND
)
2035 virtual void disable(WebKit::WGC3Denum cap
) OVERRIDE
{
2036 if (cap
== GL_BLEND
)
2040 bool blend() const { return blend_
; }
2046 class BlendStateCheckLayer
: public LayerImpl
{
2048 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2050 ResourceProvider
* resource_provider
) {
2051 return scoped_ptr
<LayerImpl
>(new BlendStateCheckLayer(tree_impl
,
2053 resource_provider
));
2056 virtual void AppendQuads(QuadSink
* quad_sink
,
2057 AppendQuadsData
* append_quads_data
) OVERRIDE
{
2058 quads_appended_
= true;
2060 gfx::Rect opaque_rect
;
2061 if (contents_opaque())
2062 opaque_rect
= quad_rect_
;
2064 opaque_rect
= opaque_content_rect_
;
2066 SharedQuadState
* shared_quad_state
=
2067 quad_sink
->UseSharedQuadState(CreateSharedQuadState());
2068 scoped_ptr
<TileDrawQuad
> test_blending_draw_quad
= TileDrawQuad::Create();
2069 test_blending_draw_quad
->SetNew(shared_quad_state
,
2073 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
2076 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
2077 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
2078 EXPECT_EQ(has_render_surface_
, !!render_surface());
2079 quad_sink
->Append(test_blending_draw_quad
.PassAs
<DrawQuad
>(),
2083 void SetExpectation(bool blend
, bool has_render_surface
) {
2085 has_render_surface_
= has_render_surface
;
2086 quads_appended_
= false;
2089 bool quads_appended() const { return quads_appended_
; }
2091 void SetQuadRect(gfx::Rect rect
) { quad_rect_
= rect
; }
2092 void SetQuadVisibleRect(gfx::Rect rect
) { quad_visible_rect_
= rect
; }
2093 void SetOpaqueContentRect(gfx::Rect rect
) { opaque_content_rect_
= rect
; }
2096 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
2098 ResourceProvider
* resource_provider
)
2099 : LayerImpl(tree_impl
, id
),
2101 has_render_surface_(false),
2102 quads_appended_(false),
2103 quad_rect_(5, 5, 5, 5),
2104 quad_visible_rect_(5, 5, 5, 5),
2105 resource_id_(resource_provider
->CreateResource(
2108 ResourceProvider::TextureUsageAny
)) {
2109 resource_provider
->AllocateForTesting(resource_id_
);
2110 SetAnchorPoint(gfx::PointF());
2111 SetBounds(gfx::Size(10, 10));
2112 SetContentBounds(gfx::Size(10, 10));
2113 SetDrawsContent(true);
2117 bool has_render_surface_
;
2118 bool quads_appended_
;
2119 gfx::Rect quad_rect_
;
2120 gfx::Rect opaque_content_rect_
;
2121 gfx::Rect quad_visible_rect_
;
2122 ResourceProvider::ResourceId resource_id_
;
2125 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
2127 scoped_ptr
<LayerImpl
> root
=
2128 LayerImpl::Create(host_impl_
->active_tree(), 1);
2129 root
->SetAnchorPoint(gfx::PointF());
2130 root
->SetBounds(gfx::Size(10, 10));
2131 root
->SetContentBounds(root
->bounds());
2132 root
->SetDrawsContent(false);
2133 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2135 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
2138 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
2140 host_impl_
->resource_provider()));
2141 BlendStateCheckLayer
* layer1
=
2142 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
2143 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
2145 LayerTreeHostImpl::FrameData frame
;
2147 // Opaque layer, drawn without blending.
2148 layer1
->SetContentsOpaque(true);
2149 layer1
->SetExpectation(false, false);
2150 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2151 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2152 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2153 EXPECT_TRUE(layer1
->quads_appended());
2154 host_impl_
->DidDrawAllLayers(frame
);
2156 // Layer with translucent content and painting, so drawn with blending.
2157 layer1
->SetContentsOpaque(false);
2158 layer1
->SetExpectation(true, false);
2159 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2160 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2161 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2162 EXPECT_TRUE(layer1
->quads_appended());
2163 host_impl_
->DidDrawAllLayers(frame
);
2165 // Layer with translucent opacity, drawn with blending.
2166 layer1
->SetContentsOpaque(true);
2167 layer1
->SetOpacity(0.5f
);
2168 layer1
->SetExpectation(true, false);
2169 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2170 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2171 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2172 EXPECT_TRUE(layer1
->quads_appended());
2173 host_impl_
->DidDrawAllLayers(frame
);
2175 // Layer with translucent opacity and painting, drawn with blending.
2176 layer1
->SetContentsOpaque(true);
2177 layer1
->SetOpacity(0.5f
);
2178 layer1
->SetExpectation(true, false);
2179 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2180 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2181 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2182 EXPECT_TRUE(layer1
->quads_appended());
2183 host_impl_
->DidDrawAllLayers(frame
);
2186 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
2188 host_impl_
->resource_provider()));
2189 BlendStateCheckLayer
* layer2
=
2190 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
2191 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
2193 // 2 opaque layers, drawn without blending.
2194 layer1
->SetContentsOpaque(true);
2195 layer1
->SetOpacity(1.f
);
2196 layer1
->SetExpectation(false, false);
2197 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2198 layer2
->SetContentsOpaque(true);
2199 layer2
->SetOpacity(1.f
);
2200 layer2
->SetExpectation(false, false);
2201 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2202 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2203 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2204 EXPECT_TRUE(layer1
->quads_appended());
2205 EXPECT_TRUE(layer2
->quads_appended());
2206 host_impl_
->DidDrawAllLayers(frame
);
2208 // Parent layer with translucent content, drawn with blending.
2209 // Child layer with opaque content, drawn without blending.
2210 layer1
->SetContentsOpaque(false);
2211 layer1
->SetExpectation(true, false);
2212 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2213 layer2
->SetExpectation(false, false);
2214 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2215 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2216 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2217 EXPECT_TRUE(layer1
->quads_appended());
2218 EXPECT_TRUE(layer2
->quads_appended());
2219 host_impl_
->DidDrawAllLayers(frame
);
2221 // Parent layer with translucent content but opaque painting, drawn without
2223 // Child layer with opaque content, drawn without blending.
2224 layer1
->SetContentsOpaque(true);
2225 layer1
->SetExpectation(false, false);
2226 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2227 layer2
->SetExpectation(false, false);
2228 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2229 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2230 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2231 EXPECT_TRUE(layer1
->quads_appended());
2232 EXPECT_TRUE(layer2
->quads_appended());
2233 host_impl_
->DidDrawAllLayers(frame
);
2235 // Parent layer with translucent opacity and opaque content. Since it has a
2236 // drawing child, it's drawn to a render surface which carries the opacity,
2237 // so it's itself drawn without blending.
2238 // Child layer with opaque content, drawn without blending (parent surface
2239 // carries the inherited opacity).
2240 layer1
->SetContentsOpaque(true);
2241 layer1
->SetOpacity(0.5f
);
2242 layer1
->SetExpectation(false, true);
2243 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2244 layer2
->SetExpectation(false, false);
2245 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2246 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2247 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2248 EXPECT_TRUE(layer1
->quads_appended());
2249 EXPECT_TRUE(layer2
->quads_appended());
2250 host_impl_
->DidDrawAllLayers(frame
);
2252 // Draw again, but with child non-opaque, to make sure
2253 // layer1 not culled.
2254 layer1
->SetContentsOpaque(true);
2255 layer1
->SetOpacity(1.f
);
2256 layer1
->SetExpectation(false, false);
2257 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2258 layer2
->SetContentsOpaque(true);
2259 layer2
->SetOpacity(0.5f
);
2260 layer2
->SetExpectation(true, false);
2261 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2262 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2263 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2264 EXPECT_TRUE(layer1
->quads_appended());
2265 EXPECT_TRUE(layer2
->quads_appended());
2266 host_impl_
->DidDrawAllLayers(frame
);
2268 // A second way of making the child non-opaque.
2269 layer1
->SetContentsOpaque(true);
2270 layer1
->SetOpacity(1.f
);
2271 layer1
->SetExpectation(false, false);
2272 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2273 layer2
->SetContentsOpaque(false);
2274 layer2
->SetOpacity(1.f
);
2275 layer2
->SetExpectation(true, false);
2276 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2277 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2278 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2279 EXPECT_TRUE(layer1
->quads_appended());
2280 EXPECT_TRUE(layer2
->quads_appended());
2281 host_impl_
->DidDrawAllLayers(frame
);
2283 // And when the layer says its not opaque but is painted opaque, it is not
2285 layer1
->SetContentsOpaque(true);
2286 layer1
->SetOpacity(1.f
);
2287 layer1
->SetExpectation(false, false);
2288 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2289 layer2
->SetContentsOpaque(true);
2290 layer2
->SetOpacity(1.f
);
2291 layer2
->SetExpectation(false, false);
2292 layer2
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2293 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2294 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2295 EXPECT_TRUE(layer1
->quads_appended());
2296 EXPECT_TRUE(layer2
->quads_appended());
2297 host_impl_
->DidDrawAllLayers(frame
);
2299 // Layer with partially opaque contents, drawn with blending.
2300 layer1
->SetContentsOpaque(false);
2301 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
2302 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
2303 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
2304 layer1
->SetExpectation(true, false);
2305 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2306 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2307 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2308 EXPECT_TRUE(layer1
->quads_appended());
2309 host_impl_
->DidDrawAllLayers(frame
);
2311 // Layer with partially opaque contents partially culled, drawn with blending.
2312 layer1
->SetContentsOpaque(false);
2313 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
2314 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
2315 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
2316 layer1
->SetExpectation(true, false);
2317 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2318 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2319 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2320 EXPECT_TRUE(layer1
->quads_appended());
2321 host_impl_
->DidDrawAllLayers(frame
);
2323 // Layer with partially opaque contents culled, drawn with blending.
2324 layer1
->SetContentsOpaque(false);
2325 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
2326 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
2327 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
2328 layer1
->SetExpectation(true, false);
2329 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2330 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2331 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2332 EXPECT_TRUE(layer1
->quads_appended());
2333 host_impl_
->DidDrawAllLayers(frame
);
2335 // Layer with partially opaque contents and translucent contents culled, drawn
2336 // without blending.
2337 layer1
->SetContentsOpaque(false);
2338 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
2339 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
2340 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
2341 layer1
->SetExpectation(false, false);
2342 layer1
->set_update_rect(gfx::RectF(layer1
->content_bounds()));
2343 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2344 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2345 EXPECT_TRUE(layer1
->quads_appended());
2346 host_impl_
->DidDrawAllLayers(frame
);
2349 TEST_F(LayerTreeHostImplTest
, ViewportCovered
) {
2350 host_impl_
->InitializeRenderer(CreateOutputSurface());
2351 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
2353 gfx::Size
viewport_size(1000, 1000);
2354 host_impl_
->SetViewportSize(viewport_size
);
2356 host_impl_
->active_tree()->SetRootLayer(
2357 LayerImpl::Create(host_impl_
->active_tree(), 1));
2358 host_impl_
->active_tree()->root_layer()->AddChild(
2359 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
2361 host_impl_
->resource_provider()));
2362 BlendStateCheckLayer
* child
= static_cast<BlendStateCheckLayer
*>(
2363 host_impl_
->active_tree()->root_layer()->children()[0]);
2364 child
->SetExpectation(false, false);
2365 child
->SetContentsOpaque(true);
2369 gfx::Rect
layer_rect(0, 0, 1000, 1000);
2370 child
->SetPosition(layer_rect
.origin());
2371 child
->SetBounds(layer_rect
.size());
2372 child
->SetContentBounds(layer_rect
.size());
2373 child
->SetQuadRect(gfx::Rect(layer_rect
.size()));
2374 child
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
2376 LayerTreeHostImpl::FrameData frame
;
2377 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2378 ASSERT_EQ(1u, frame
.render_passes
.size());
2380 size_t num_gutter_quads
= 0;
2381 for (size_t i
= 0; i
< frame
.render_passes
[0]->quad_list
.size(); ++i
)
2382 num_gutter_quads
+= (frame
.render_passes
[0]->quad_list
[i
]->material
==
2383 DrawQuad::SOLID_COLOR
) ? 1 : 0;
2384 EXPECT_EQ(0u, num_gutter_quads
);
2385 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
2387 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2388 frame
.render_passes
[0]->quad_list
, gfx::Rect(viewport_size
));
2389 host_impl_
->DidDrawAllLayers(frame
);
2392 // Empty visible content area (fullscreen gutter rect)
2394 gfx::Rect
layer_rect(0, 0, 0, 0);
2395 child
->SetPosition(layer_rect
.origin());
2396 child
->SetBounds(layer_rect
.size());
2397 child
->SetContentBounds(layer_rect
.size());
2398 child
->SetQuadRect(gfx::Rect(layer_rect
.size()));
2399 child
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
2401 LayerTreeHostImpl::FrameData frame
;
2402 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2403 ASSERT_EQ(1u, frame
.render_passes
.size());
2405 size_t num_gutter_quads
= 0;
2406 for (size_t i
= 0; i
< frame
.render_passes
[0]->quad_list
.size(); ++i
)
2407 num_gutter_quads
+= (frame
.render_passes
[0]->quad_list
[i
]->material
==
2408 DrawQuad::SOLID_COLOR
) ? 1 : 0;
2409 EXPECT_EQ(1u, num_gutter_quads
);
2410 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
2412 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2413 frame
.render_passes
[0]->quad_list
, gfx::Rect(viewport_size
));
2414 host_impl_
->DidDrawAllLayers(frame
);
2417 // Content area in middle of clip rect (four surrounding gutter rects)
2419 gfx::Rect
layer_rect(500, 500, 200, 200);
2420 child
->SetPosition(layer_rect
.origin());
2421 child
->SetBounds(layer_rect
.size());
2422 child
->SetContentBounds(layer_rect
.size());
2423 child
->SetQuadRect(gfx::Rect(layer_rect
.size()));
2424 child
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
2426 LayerTreeHostImpl::FrameData frame
;
2427 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2428 ASSERT_EQ(1u, frame
.render_passes
.size());
2430 size_t num_gutter_quads
= 0;
2431 for (size_t i
= 0; i
< frame
.render_passes
[0]->quad_list
.size(); ++i
)
2432 num_gutter_quads
+= (frame
.render_passes
[0]->quad_list
[i
]->material
==
2433 DrawQuad::SOLID_COLOR
) ? 1 : 0;
2434 EXPECT_EQ(4u, num_gutter_quads
);
2435 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
2437 LayerTestCommon::VerifyQuadsExactlyCoverRect(
2438 frame
.render_passes
[0]->quad_list
, gfx::Rect(viewport_size
));
2439 host_impl_
->DidDrawAllLayers(frame
);
2444 class ReshapeTrackerContext
: public TestWebGraphicsContext3D
{
2446 ReshapeTrackerContext() : reshape_called_(false) {}
2448 virtual void reshape(int width
, int height
) OVERRIDE
{
2449 reshape_called_
= true;
2452 bool reshape_called() const { return reshape_called_
; }
2455 bool reshape_called_
;
2458 class FakeDrawableLayerImpl
: public LayerImpl
{
2460 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2461 return scoped_ptr
<LayerImpl
>(new FakeDrawableLayerImpl(tree_impl
, id
));
2464 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
2465 : LayerImpl(tree_impl
, id
) {}
2468 // Only reshape when we know we are going to draw. Otherwise, the reshape
2469 // can leave the window at the wrong size if we never draw and the proper
2470 // viewport size is never set.
2471 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
2472 scoped_ptr
<OutputSurface
> output_surface
= FakeOutputSurface::Create3d(
2473 scoped_ptr
<WebKit::WebGraphicsContext3D
>(new ReshapeTrackerContext
))
2474 .PassAs
<OutputSurface
>();
2475 ReshapeTrackerContext
* reshape_tracker
=
2476 static_cast<ReshapeTrackerContext
*>(output_surface
->context3d());
2477 host_impl_
->InitializeRenderer(output_surface
.Pass());
2479 scoped_ptr
<LayerImpl
> root
=
2480 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
2481 root
->SetAnchorPoint(gfx::PointF());
2482 root
->SetBounds(gfx::Size(10, 10));
2483 root
->SetContentBounds(gfx::Size(10, 10));
2484 root
->SetDrawsContent(true);
2485 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2486 EXPECT_FALSE(reshape_tracker
->reshape_called());
2488 LayerTreeHostImpl::FrameData frame
;
2489 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2490 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2491 EXPECT_TRUE(reshape_tracker
->reshape_called());
2492 host_impl_
->DidDrawAllLayers(frame
);
2495 class PartialSwapTrackerContext
: public TestWebGraphicsContext3D
{
2497 virtual void postSubBufferCHROMIUM(int x
, int y
, int width
, int height
)
2499 partial_swap_rect_
= gfx::Rect(x
, y
, width
, height
);
2502 virtual WebKit::WebString
getString(WebKit::WGC3Denum name
) OVERRIDE
{
2503 if (name
== GL_EXTENSIONS
) {
2504 return WebKit::WebString(
2505 "GL_CHROMIUM_post_sub_buffer GL_CHROMIUM_set_visibility");
2508 return WebKit::WebString();
2511 gfx::Rect
partial_swap_rect() const { return partial_swap_rect_
; }
2514 gfx::Rect partial_swap_rect_
;
2517 // Make sure damage tracking propagates all the way to the graphics context,
2518 // where it should request to swap only the sub-buffer that is damaged.
2519 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
2520 scoped_ptr
<OutputSurface
> output_surface
=
2521 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
2522 new PartialSwapTrackerContext
)).PassAs
<OutputSurface
>();
2523 PartialSwapTrackerContext
* partial_swap_tracker
=
2524 static_cast<PartialSwapTrackerContext
*>(output_surface
->context3d());
2526 // This test creates its own LayerTreeHostImpl, so
2527 // that we can force partial swap enabled.
2528 LayerTreeSettings settings
;
2529 settings
.partial_swap_enabled
= true;
2530 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
2531 LayerTreeHostImpl::Create(settings
,
2534 &stats_instrumentation_
);
2535 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
2536 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
2538 scoped_ptr
<LayerImpl
> root
=
2539 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
2540 scoped_ptr
<LayerImpl
> child
=
2541 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
2542 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
2543 child
->SetAnchorPoint(gfx::PointF());
2544 child
->SetBounds(gfx::Size(14, 15));
2545 child
->SetContentBounds(gfx::Size(14, 15));
2546 child
->SetDrawsContent(true);
2547 root
->SetAnchorPoint(gfx::PointF());
2548 root
->SetBounds(gfx::Size(500, 500));
2549 root
->SetContentBounds(gfx::Size(500, 500));
2550 root
->SetDrawsContent(true);
2551 root
->AddChild(child
.Pass());
2552 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
2554 LayerTreeHostImpl::FrameData frame
;
2556 // First frame, the entire screen should get swapped.
2557 EXPECT_TRUE(layer_tree_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2558 layer_tree_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2559 layer_tree_host_impl
->DidDrawAllLayers(frame
);
2560 layer_tree_host_impl
->SwapBuffers(frame
);
2561 gfx::Rect actual_swap_rect
= partial_swap_tracker
->partial_swap_rect();
2562 gfx::Rect expected_swap_rect
= gfx::Rect(0, 0, 500, 500);
2563 EXPECT_EQ(expected_swap_rect
.x(), actual_swap_rect
.x());
2564 EXPECT_EQ(expected_swap_rect
.y(), actual_swap_rect
.y());
2565 EXPECT_EQ(expected_swap_rect
.width(), actual_swap_rect
.width());
2566 EXPECT_EQ(expected_swap_rect
.height(), actual_swap_rect
.height());
2568 // Second frame, only the damaged area should get swapped. Damage should be
2569 // the union of old and new child rects.
2570 // expected damage rect: gfx::Rect(26, 28);
2571 // expected swap rect: vertically flipped, with origin at bottom left corner.
2572 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
2574 EXPECT_TRUE(layer_tree_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2575 layer_tree_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2576 host_impl_
->DidDrawAllLayers(frame
);
2577 layer_tree_host_impl
->SwapBuffers(frame
);
2578 actual_swap_rect
= partial_swap_tracker
->partial_swap_rect();
2579 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
2580 EXPECT_EQ(expected_swap_rect
.x(), actual_swap_rect
.x());
2581 EXPECT_EQ(expected_swap_rect
.y(), actual_swap_rect
.y());
2582 EXPECT_EQ(expected_swap_rect
.width(), actual_swap_rect
.width());
2583 EXPECT_EQ(expected_swap_rect
.height(), actual_swap_rect
.height());
2585 // Make sure that partial swap is constrained to the viewport dimensions
2586 // expected damage rect: gfx::Rect(500, 500);
2587 // expected swap rect: flipped damage rect, but also clamped to viewport
2588 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
2589 // This will damage everything.
2590 layer_tree_host_impl
->active_tree()->root_layer()->SetOpacity(0.7f
);
2591 EXPECT_TRUE(layer_tree_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2592 layer_tree_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2593 host_impl_
->DidDrawAllLayers(frame
);
2594 layer_tree_host_impl
->SwapBuffers(frame
);
2595 actual_swap_rect
= partial_swap_tracker
->partial_swap_rect();
2596 expected_swap_rect
= gfx::Rect(10, 10);
2597 EXPECT_EQ(expected_swap_rect
.x(), actual_swap_rect
.x());
2598 EXPECT_EQ(expected_swap_rect
.y(), actual_swap_rect
.y());
2599 EXPECT_EQ(expected_swap_rect
.width(), actual_swap_rect
.width());
2600 EXPECT_EQ(expected_swap_rect
.height(), actual_swap_rect
.height());
2603 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
2604 scoped_ptr
<LayerImpl
> root
=
2605 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
2606 scoped_ptr
<LayerImpl
> child
=
2607 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
2608 child
->SetAnchorPoint(gfx::PointF());
2609 child
->SetBounds(gfx::Size(10, 10));
2610 child
->SetContentBounds(gfx::Size(10, 10));
2611 child
->SetDrawsContent(true);
2612 root
->SetAnchorPoint(gfx::PointF());
2613 root
->SetBounds(gfx::Size(10, 10));
2614 root
->SetContentBounds(gfx::Size(10, 10));
2615 root
->SetDrawsContent(true);
2616 root
->SetOpacity(0.7f
);
2617 root
->AddChild(child
.Pass());
2619 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2621 LayerTreeHostImpl::FrameData frame
;
2623 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2624 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
2625 EXPECT_EQ(1u, frame
.render_passes
.size());
2626 host_impl_
->DidDrawAllLayers(frame
);
2629 class FakeLayerWithQuads
: public LayerImpl
{
2631 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2632 return scoped_ptr
<LayerImpl
>(new FakeLayerWithQuads(tree_impl
, id
));
2635 virtual void AppendQuads(QuadSink
* quad_sink
,
2636 AppendQuadsData
* append_quads_data
) OVERRIDE
{
2637 SharedQuadState
* shared_quad_state
=
2638 quad_sink
->UseSharedQuadState(CreateSharedQuadState());
2640 SkColor gray
= SkColorSetRGB(100, 100, 100);
2641 gfx::Rect
quad_rect(content_bounds());
2642 scoped_ptr
<SolidColorDrawQuad
> my_quad
= SolidColorDrawQuad::Create();
2643 my_quad
->SetNew(shared_quad_state
, quad_rect
, gray
);
2644 quad_sink
->Append(my_quad
.PassAs
<DrawQuad
>(), append_quads_data
);
2648 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
2649 : LayerImpl(tree_impl
, id
) {}
2652 class MockContext
: public TestWebGraphicsContext3D
{
2654 MOCK_METHOD1(useProgram
, void(WebKit::WebGLId program
));
2655 MOCK_METHOD5(uniform4f
, void(WebKit::WGC3Dint location
,
2656 WebKit::WGC3Dfloat x
,
2657 WebKit::WGC3Dfloat y
,
2658 WebKit::WGC3Dfloat z
,
2659 WebKit::WGC3Dfloat w
));
2660 MOCK_METHOD4(uniformMatrix4fv
, void(WebKit::WGC3Dint location
,
2661 WebKit::WGC3Dsizei count
,
2662 WebKit::WGC3Dboolean transpose
,
2663 const WebKit::WGC3Dfloat
* value
));
2664 MOCK_METHOD4(drawElements
, void(WebKit::WGC3Denum mode
,
2665 WebKit::WGC3Dsizei count
,
2666 WebKit::WGC3Denum type
,
2667 WebKit::WGC3Dintptr offset
));
2668 MOCK_METHOD1(getString
, WebKit::WebString(WebKit::WGC3Denum name
));
2669 MOCK_METHOD0(getRequestableExtensionsCHROMIUM
, WebKit::WebString());
2670 MOCK_METHOD1(enable
, void(WebKit::WGC3Denum cap
));
2671 MOCK_METHOD1(disable
, void(WebKit::WGC3Denum cap
));
2672 MOCK_METHOD4(scissor
, void(WebKit::WGC3Dint x
,
2674 WebKit::WGC3Dsizei width
,
2675 WebKit::WGC3Dsizei height
));
2678 class MockContextHarness
{
2680 MockContext
* context_
;
2683 explicit MockContextHarness(MockContext
* context
)
2684 : context_(context
) {
2685 // Catch "uninteresting" calls
2686 EXPECT_CALL(*context_
, useProgram(_
))
2689 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
2692 // These are not asserted
2693 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
2694 .WillRepeatedly(Return());
2696 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
2697 .WillRepeatedly(Return());
2699 // Any other strings are empty
2700 EXPECT_CALL(*context_
, getString(_
))
2701 .WillRepeatedly(Return(WebKit::WebString()));
2703 // Support for partial swap, if needed
2704 EXPECT_CALL(*context_
, getString(GL_EXTENSIONS
))
2705 .WillRepeatedly(Return(
2706 WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
2708 EXPECT_CALL(*context_
, getRequestableExtensionsCHROMIUM())
2709 .WillRepeatedly(Return(
2710 WebKit::WebString("GL_CHROMIUM_post_sub_buffer")));
2712 // Any un-sanctioned calls to enable() are OK
2713 EXPECT_CALL(*context_
, enable(_
))
2714 .WillRepeatedly(Return());
2716 // Any un-sanctioned calls to disable() are OK
2717 EXPECT_CALL(*context_
, disable(_
))
2718 .WillRepeatedly(Return());
2721 void MustDrawSolidQuad() {
2722 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
2724 .RetiresOnSaturation();
2726 EXPECT_CALL(*context_
, useProgram(_
))
2728 .RetiresOnSaturation();
2731 void MustSetScissor(int x
, int y
, int width
, int height
) {
2732 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
2733 .WillRepeatedly(Return());
2735 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
2737 .WillRepeatedly(Return());
2740 void MustSetNoScissor() {
2741 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
2742 .WillRepeatedly(Return());
2744 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
2747 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
2752 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
2753 scoped_ptr
<OutputSurface
> output_surface
=
2754 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
2755 new MockContext
)).PassAs
<OutputSurface
>();
2756 MockContext
* mock_context
=
2757 static_cast<MockContext
*>(output_surface
->context3d());
2758 MockContextHarness
harness(mock_context
);
2761 CreateLayerTreeHost(false, output_surface
.Pass());
2762 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
2764 // Without partial swap, and no clipping, no scissor is set.
2765 harness
.MustDrawSolidQuad();
2766 harness
.MustSetNoScissor();
2768 LayerTreeHostImpl::FrameData frame
;
2769 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2770 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2771 host_impl_
->DidDrawAllLayers(frame
);
2773 Mock::VerifyAndClearExpectations(&mock_context
);
2775 // Without partial swap, but a layer does clip its subtree, one scissor is
2777 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
2778 harness
.MustDrawSolidQuad();
2779 harness
.MustSetScissor(0, 0, 10, 10);
2781 LayerTreeHostImpl::FrameData frame
;
2782 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2783 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2784 host_impl_
->DidDrawAllLayers(frame
);
2786 Mock::VerifyAndClearExpectations(&mock_context
);
2789 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
2790 scoped_ptr
<OutputSurface
> output_surface
=
2791 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
2792 new MockContext
)).PassAs
<OutputSurface
>();
2793 MockContext
* mock_context
=
2794 static_cast<MockContext
*>(output_surface
->context3d());
2795 MockContextHarness
harness(mock_context
);
2797 CreateLayerTreeHost(true, output_surface
.Pass());
2798 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
2800 // The first frame is not a partially-swapped one.
2801 harness
.MustSetScissor(0, 0, 10, 10);
2802 harness
.MustDrawSolidQuad();
2804 LayerTreeHostImpl::FrameData frame
;
2805 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2806 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2807 host_impl_
->DidDrawAllLayers(frame
);
2809 Mock::VerifyAndClearExpectations(&mock_context
);
2811 // Damage a portion of the frame.
2812 host_impl_
->active_tree()->root_layer()->set_update_rect(
2813 gfx::Rect(0, 0, 2, 3));
2815 // The second frame will be partially-swapped (the y coordinates are flipped).
2816 harness
.MustSetScissor(0, 7, 2, 3);
2817 harness
.MustDrawSolidQuad();
2819 LayerTreeHostImpl::FrameData frame
;
2820 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
2821 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
2822 host_impl_
->DidDrawAllLayers(frame
);
2824 Mock::VerifyAndClearExpectations(&mock_context
);
2827 class PartialSwapContext
: public TestWebGraphicsContext3D
{
2829 virtual WebKit::WebString
getString(WebKit::WGC3Denum name
) OVERRIDE
{
2830 if (name
== GL_EXTENSIONS
)
2831 return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
2832 return WebKit::WebString();
2835 virtual WebKit::WebString
getRequestableExtensionsCHROMIUM() OVERRIDE
{
2836 return WebKit::WebString("GL_CHROMIUM_post_sub_buffer");
2839 // Unlimited texture size.
2840 virtual void getIntegerv(WebKit::WGC3Denum pname
, WebKit::WGC3Dint
* value
)
2842 if (pname
== GL_MAX_TEXTURE_SIZE
)
2847 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
2849 LayerTreeHostImplClient
* client
,
2851 RenderingStatsInstrumentation
* stats_instrumentation
) {
2852 scoped_ptr
<OutputSurface
> output_surface
=
2853 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
2854 new PartialSwapContext
)).PassAs
<OutputSurface
>();
2856 LayerTreeSettings settings
;
2857 settings
.partial_swap_enabled
= partial_swap
;
2858 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
2859 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
);
2860 my_host_impl
->InitializeRenderer(output_surface
.Pass());
2861 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
2864 Layers are created as follows:
2866 +--------------------+
2870 | | +-------------------+
2872 | | +-------------------+
2877 +--------------------+
2879 Layers 1, 2 have render surfaces
2881 scoped_ptr
<LayerImpl
> root
=
2882 LayerImpl::Create(my_host_impl
->active_tree(), 1);
2883 scoped_ptr
<LayerImpl
> child
=
2884 LayerImpl::Create(my_host_impl
->active_tree(), 2);
2885 scoped_ptr
<LayerImpl
> grand_child
=
2886 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
2888 gfx::Rect
root_rect(0, 0, 100, 100);
2889 gfx::Rect
child_rect(10, 10, 50, 50);
2890 gfx::Rect
grand_child_rect(5, 5, 150, 150);
2892 root
->CreateRenderSurface();
2893 root
->SetAnchorPoint(gfx::PointF());
2894 root
->SetPosition(root_rect
.origin());
2895 root
->SetBounds(root_rect
.size());
2896 root
->SetContentBounds(root
->bounds());
2897 root
->draw_properties().visible_content_rect
= root_rect
;
2898 root
->SetDrawsContent(false);
2899 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
2901 child
->SetAnchorPoint(gfx::PointF());
2902 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
2903 child
->SetOpacity(0.5f
);
2904 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
2905 child
->SetContentBounds(child
->bounds());
2906 child
->draw_properties().visible_content_rect
= child_rect
;
2907 child
->SetDrawsContent(false);
2908 child
->SetForceRenderSurface(true);
2910 grand_child
->SetAnchorPoint(gfx::PointF());
2911 grand_child
->SetPosition(grand_child_rect
.origin());
2912 grand_child
->SetBounds(grand_child_rect
.size());
2913 grand_child
->SetContentBounds(grand_child
->bounds());
2914 grand_child
->draw_properties().visible_content_rect
= grand_child_rect
;
2915 grand_child
->SetDrawsContent(true);
2917 child
->AddChild(grand_child
.Pass());
2918 root
->AddChild(child
.Pass());
2920 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
2921 return my_host_impl
.Pass();
2924 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
2925 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
2926 SetupLayersForOpacity(true, this, &proxy_
, &stats_instrumentation_
);
2928 LayerTreeHostImpl::FrameData frame
;
2929 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2931 // Verify all quads have been computed
2932 ASSERT_EQ(2U, frame
.render_passes
.size());
2933 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
2934 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
2935 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
2936 frame
.render_passes
[0]->quad_list
[0]->material
);
2937 EXPECT_EQ(DrawQuad::RENDER_PASS
,
2938 frame
.render_passes
[1]->quad_list
[0]->material
);
2940 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2941 my_host_impl
->DidDrawAllLayers(frame
);
2945 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
2946 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
2947 SetupLayersForOpacity(false, this, &proxy_
, &stats_instrumentation_
);
2949 LayerTreeHostImpl::FrameData frame
;
2950 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
2952 // Verify all quads have been computed
2953 ASSERT_EQ(2U, frame
.render_passes
.size());
2954 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
2955 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
2956 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
2957 frame
.render_passes
[0]->quad_list
[0]->material
);
2958 EXPECT_EQ(DrawQuad::RENDER_PASS
,
2959 frame
.render_passes
[1]->quad_list
[0]->material
);
2961 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
2962 my_host_impl
->DidDrawAllLayers(frame
);
2966 // Fake WebKit::WebGraphicsContext3D that tracks the number of textures in use.
2967 class TrackingWebGraphicsContext3D
: public TestWebGraphicsContext3D
{
2969 TrackingWebGraphicsContext3D()
2970 : TestWebGraphicsContext3D(),
2973 virtual WebKit::WebGLId
createTexture() OVERRIDE
{
2974 WebKit::WebGLId id
= TestWebGraphicsContext3D::createTexture();
2976 textures_
[id
] = true;
2981 virtual void deleteTexture(WebKit::WebGLId id
) OVERRIDE
{
2982 if (textures_
.find(id
) == textures_
.end())
2985 textures_
[id
] = false;
2989 virtual WebKit::WebString
getString(WebKit::WGC3Denum name
) OVERRIDE
{
2990 if (name
== GL_EXTENSIONS
) {
2991 return WebKit::WebString(
2992 "GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2995 return WebKit::WebString();
2998 unsigned num_textures() const { return num_textures_
; }
3001 base::hash_map
<WebKit::WebGLId
, bool> textures_
;
3002 unsigned num_textures_
;
3005 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
3006 scoped_ptr
<TestWebGraphicsContext3D
> context
=
3007 TestWebGraphicsContext3D::Create();
3008 TestWebGraphicsContext3D
* context3d
= context
.get();
3009 scoped_ptr
<OutputSurface
> output_surface
= FakeOutputSurface::Create3d(
3010 context
.PassAs
<WebKit::WebGraphicsContext3D
>()).PassAs
<OutputSurface
>();
3011 host_impl_
->InitializeRenderer(output_surface
.Pass());
3013 scoped_ptr
<LayerImpl
> root_layer
=
3014 LayerImpl::Create(host_impl_
->active_tree(), 1);
3015 root_layer
->SetBounds(gfx::Size(10, 10));
3016 root_layer
->SetAnchorPoint(gfx::PointF());
3018 scoped_refptr
<VideoFrame
> softwareFrame
=
3019 media::VideoFrame::CreateColorFrame(
3020 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
3021 FakeVideoFrameProvider provider
;
3022 provider
.set_frame(softwareFrame
);
3023 scoped_ptr
<VideoLayerImpl
> video_layer
=
3024 VideoLayerImpl::Create(host_impl_
->active_tree(), 4, &provider
);
3025 video_layer
->SetBounds(gfx::Size(10, 10));
3026 video_layer
->SetAnchorPoint(gfx::PointF());
3027 video_layer
->SetContentBounds(gfx::Size(10, 10));
3028 video_layer
->SetDrawsContent(true);
3029 root_layer
->AddChild(video_layer
.PassAs
<LayerImpl
>());
3031 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
3032 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
3033 io_surface_layer
->SetBounds(gfx::Size(10, 10));
3034 io_surface_layer
->SetAnchorPoint(gfx::PointF());
3035 io_surface_layer
->SetContentBounds(gfx::Size(10, 10));
3036 io_surface_layer
->SetDrawsContent(true);
3037 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
3038 root_layer
->AddChild(io_surface_layer
.PassAs
<LayerImpl
>());
3040 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
3042 EXPECT_EQ(0u, context3d
->NumTextures());
3044 LayerTreeHostImpl::FrameData frame
;
3045 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
3046 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
3047 host_impl_
->DidDrawAllLayers(frame
);
3048 host_impl_
->SwapBuffers(frame
);
3050 EXPECT_GT(context3d
->NumTextures(), 0u);
3052 // Kill the layer tree.
3053 host_impl_
->active_tree()->SetRootLayer(
3054 LayerImpl::Create(host_impl_
->active_tree(), 100));
3055 // There should be no textures left in use after.
3056 EXPECT_EQ(0u, context3d
->NumTextures());
3059 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
3061 MOCK_METHOD1(useProgram
, void(WebKit::WebGLId program
));
3062 MOCK_METHOD4(drawElements
, void(WebKit::WGC3Denum mode
,
3063 WebKit::WGC3Dsizei count
,
3064 WebKit::WGC3Denum type
,
3065 WebKit::WGC3Dintptr offset
));
3068 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
3069 scoped_ptr
<OutputSurface
> output_surface
=
3070 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3071 new MockDrawQuadsToFillScreenContext
)).PassAs
<OutputSurface
>();
3072 MockDrawQuadsToFillScreenContext
* mock_context
=
3073 static_cast<MockDrawQuadsToFillScreenContext
*>(
3074 output_surface
->context3d());
3077 CreateLayerTreeHost(false, output_surface
.Pass());
3078 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
3079 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
3081 // Verify one quad is drawn when transparent background set is not set.
3082 host_impl_
->active_tree()->set_has_transparent_background(false);
3083 EXPECT_CALL(*mock_context
, useProgram(_
))
3085 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
3087 LayerTreeHostImpl::FrameData frame
;
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
);
3093 // Verify no quads are drawn when transparent background is set.
3094 host_impl_
->active_tree()->set_has_transparent_background(true);
3095 host_impl_
->SetFullRootLayerDamage();
3096 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
3097 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
3098 host_impl_
->DidDrawAllLayers(frame
);
3099 Mock::VerifyAndClearExpectations(&mock_context
);
3102 static void AddDrawingLayerTo(LayerImpl
* parent
,
3104 gfx::Rect layer_rect
,
3105 LayerImpl
** result
) {
3106 scoped_ptr
<LayerImpl
> layer
=
3107 FakeLayerWithQuads::Create(parent
->layer_tree_impl(), id
);
3108 LayerImpl
* layer_ptr
= layer
.get();
3109 layer_ptr
->SetAnchorPoint(gfx::PointF());
3110 layer_ptr
->SetPosition(gfx::PointF(layer_rect
.origin()));
3111 layer_ptr
->SetBounds(layer_rect
.size());
3112 layer_ptr
->SetContentBounds(layer_rect
.size());
3113 layer_ptr
->SetDrawsContent(true); // only children draw content
3114 layer_ptr
->SetContentsOpaque(true);
3115 parent
->AddChild(layer
.Pass());
3117 *result
= layer_ptr
;
3120 static void SetupLayersForTextureCaching(
3121 LayerTreeHostImpl
* layer_tree_host_impl
,
3122 LayerImpl
*& root_ptr
,
3123 LayerImpl
*& intermediate_layer_ptr
,
3124 LayerImpl
*& surface_layer_ptr
,
3125 LayerImpl
*& child_ptr
,
3126 gfx::Size root_size
) {
3127 scoped_ptr
<OutputSurface
> output_surface
=
3128 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3129 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3131 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
3132 layer_tree_host_impl
->SetViewportSize(root_size
);
3134 scoped_ptr
<LayerImpl
> root
=
3135 LayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
3136 root_ptr
= root
.get();
3138 root
->SetAnchorPoint(gfx::PointF());
3139 root
->SetPosition(gfx::PointF());
3140 root
->SetBounds(root_size
);
3141 root
->SetContentBounds(root_size
);
3142 root
->SetDrawsContent(true);
3143 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3145 AddDrawingLayerTo(root_ptr
,
3147 gfx::Rect(10, 10, root_size
.width(), root_size
.height()),
3148 &intermediate_layer_ptr
);
3149 // Only children draw content.
3150 intermediate_layer_ptr
->SetDrawsContent(false);
3152 // Surface layer is the layer that changes its opacity
3153 // It will contain other layers that draw content.
3154 AddDrawingLayerTo(intermediate_layer_ptr
,
3156 gfx::Rect(10, 10, root_size
.width(), root_size
.height()),
3157 &surface_layer_ptr
);
3158 // Only children draw content.
3159 surface_layer_ptr
->SetDrawsContent(false);
3160 surface_layer_ptr
->SetOpacity(0.5f
);
3161 surface_layer_ptr
->SetForceRenderSurface(true);
3163 // Child of the surface layer will produce some quads
3164 AddDrawingLayerTo(surface_layer_ptr
,
3168 root_size
.width() - 25,
3169 root_size
.height() - 25),
3173 class GLRendererWithReleaseTextures
: public GLRenderer
{
3175 using GLRenderer::ReleaseRenderPassTextures
;
3178 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusion
) {
3179 LayerTreeSettings settings
;
3180 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3181 settings
.cache_render_pass_contents
= true;
3182 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3183 LayerTreeHostImpl::Create(settings
,
3186 &stats_instrumentation_
);
3188 // Layers are structure as follows:
3190 // R +-- S1 +- L10 (owning)
3194 // +-- S2 +- L20 (owning)
3198 // L12 occludes L11 (internal)
3199 // L20 occludes L10 (external)
3200 // L21 occludes L20 (internal)
3202 LayerImpl
* root_ptr
;
3203 LayerImpl
* layer_s1_ptr
;
3204 LayerImpl
* layer_s2_ptr
;
3206 scoped_ptr
<OutputSurface
> output_surface
=
3207 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3208 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3210 gfx::Size
root_size(1000, 1000);
3212 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3213 my_host_impl
->SetViewportSize(root_size
);
3215 scoped_ptr
<LayerImpl
> root
=
3216 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3217 root_ptr
= root
.get();
3219 root
->SetAnchorPoint(gfx::PointF());
3220 root
->SetPosition(gfx::PointF());
3221 root
->SetBounds(root_size
);
3222 root
->SetContentBounds(root_size
);
3223 root
->SetDrawsContent(true);
3224 root
->SetMasksToBounds(true);
3225 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3227 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr
);
3228 layer_s1_ptr
->SetForceRenderSurface(true);
3230 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(10, 10, 10, 10), 0); // L11
3231 AddDrawingLayerTo(layer_s1_ptr
, 4, gfx::Rect(0, 0, 30, 30), 0); // L12
3233 AddDrawingLayerTo(root_ptr
, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr
);
3234 layer_s2_ptr
->SetForceRenderSurface(true);
3236 AddDrawingLayerTo(layer_s2_ptr
, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
3238 // Initial draw - must receive all quads
3240 LayerTreeHostImpl::FrameData frame
;
3241 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3243 // Must receive 3 render passes.
3244 // For Root, there are 2 quads; for S1, there are 2 quads (1 is occluded);
3245 // for S2, there is 2 quads.
3246 ASSERT_EQ(3U, frame
.render_passes
.size());
3248 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3249 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3250 EXPECT_EQ(2U, frame
.render_passes
[2]->quad_list
.size());
3252 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3253 my_host_impl
->DidDrawAllLayers(frame
);
3256 // "Unocclude" surface S1 and repeat draw.
3257 // Must remove S2's render pass since it's cached;
3258 // Must keep S1 quads because texture contained external occlusion.
3259 gfx::Transform transform
= layer_s2_ptr
->transform();
3260 transform
.Translate(150.0, 150.0);
3261 layer_s2_ptr
->SetTransform(transform
);
3263 LayerTreeHostImpl::FrameData frame
;
3264 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3266 // Must receive 2 render passes.
3267 // For Root, there are 2 quads
3268 // For S1, the number of quads depends on what got unoccluded, so not
3269 // asserted beyond being positive.
3270 // For S2, there is no render pass
3271 ASSERT_EQ(2U, frame
.render_passes
.size());
3273 EXPECT_GT(frame
.render_passes
[0]->quad_list
.size(), 0U);
3274 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3276 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3277 my_host_impl
->DidDrawAllLayers(frame
);
3280 // "Re-occlude" surface S1 and repeat draw.
3281 // Must remove S1's render pass since it is now available in full.
3282 // S2 has no change so must also be removed.
3283 transform
= layer_s2_ptr
->transform();
3284 transform
.Translate(-15.0, -15.0);
3285 layer_s2_ptr
->SetTransform(transform
);
3287 LayerTreeHostImpl::FrameData frame
;
3288 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3290 // Must receive 1 render pass - for the root.
3291 ASSERT_EQ(1U, frame
.render_passes
.size());
3293 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3295 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3296 my_host_impl
->DidDrawAllLayers(frame
);
3300 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusionEarlyOut
) {
3301 LayerTreeSettings settings
;
3302 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3303 settings
.cache_render_pass_contents
= true;
3304 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3305 LayerTreeHostImpl::Create(settings
,
3308 &stats_instrumentation_
);
3310 // Layers are structure as follows:
3312 // R +-- S1 +- L10 (owning, non drawing)
3313 // | +- L11 (corner, unoccluded)
3314 // | +- L12 (corner, unoccluded)
3315 // | +- L13 (corner, unoccluded)
3316 // | +- L14 (corner, entirely occluded)
3318 // +-- S2 +- L20 (owning, drawing)
3321 LayerImpl
* root_ptr
;
3322 LayerImpl
* layer_s1_ptr
;
3323 LayerImpl
* layer_s2_ptr
;
3325 scoped_ptr
<OutputSurface
> output_surface
=
3326 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3327 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3329 gfx::Size
root_size(1000, 1000);
3331 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3332 my_host_impl
->SetViewportSize(root_size
);
3334 scoped_ptr
<LayerImpl
> root
=
3335 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3336 root_ptr
= root
.get();
3338 root
->SetAnchorPoint(gfx::PointF());
3339 root
->SetPosition(gfx::PointF());
3340 root
->SetBounds(root_size
);
3341 root
->SetContentBounds(root_size
);
3342 root
->SetDrawsContent(true);
3343 root
->SetMasksToBounds(true);
3344 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3346 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(0, 0, 800, 800), &layer_s1_ptr
);
3347 layer_s1_ptr
->SetForceRenderSurface(true);
3348 layer_s1_ptr
->SetDrawsContent(false);
3350 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(0, 0, 300, 300), 0); // L11
3351 AddDrawingLayerTo(layer_s1_ptr
, 4, gfx::Rect(0, 500, 300, 300), 0); // L12
3352 AddDrawingLayerTo(layer_s1_ptr
, 5, gfx::Rect(500, 0, 300, 300), 0); // L13
3353 AddDrawingLayerTo(layer_s1_ptr
, 6, gfx::Rect(500, 500, 300, 300), 0); // L14
3354 AddDrawingLayerTo(layer_s1_ptr
, 9, gfx::Rect(500, 500, 300, 300), 0); // L14
3356 AddDrawingLayerTo(root_ptr
, 7, gfx::Rect(450, 450, 450, 450), &layer_s2_ptr
);
3357 layer_s2_ptr
->SetForceRenderSurface(true);
3359 // Initial draw - must receive all quads
3361 LayerTreeHostImpl::FrameData frame
;
3362 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3364 // Must receive 3 render passes.
3365 // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
3367 ASSERT_EQ(3U, frame
.render_passes
.size());
3369 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3371 // L14 is culled, so only 3 quads.
3372 EXPECT_EQ(3U, frame
.render_passes
[1]->quad_list
.size());
3373 EXPECT_EQ(2U, frame
.render_passes
[2]->quad_list
.size());
3375 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3376 my_host_impl
->DidDrawAllLayers(frame
);
3379 // "Unocclude" surface S1 and repeat draw.
3380 // Must remove S2's render pass since it's cached;
3381 // Must keep S1 quads because texture contained external occlusion.
3382 gfx::Transform transform
= layer_s2_ptr
->transform();
3383 transform
.Translate(100.0, 100.0);
3384 layer_s2_ptr
->SetTransform(transform
);
3386 LayerTreeHostImpl::FrameData frame
;
3387 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3389 // Must receive 2 render passes.
3390 // For Root, there are 2 quads
3391 // For S1, the number of quads depends on what got unoccluded, so not
3392 // asserted beyond being positive.
3393 // For S2, there is no render pass
3394 ASSERT_EQ(2U, frame
.render_passes
.size());
3396 EXPECT_GT(frame
.render_passes
[0]->quad_list
.size(), 0U);
3397 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3399 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3400 my_host_impl
->DidDrawAllLayers(frame
);
3403 // "Re-occlude" surface S1 and repeat draw.
3404 // Must remove S1's render pass since it is now available in full.
3405 // S2 has no change so must also be removed.
3406 transform
= layer_s2_ptr
->transform();
3407 transform
.Translate(-15.0, -15.0);
3408 layer_s2_ptr
->SetTransform(transform
);
3410 LayerTreeHostImpl::FrameData frame
;
3411 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3413 // Must receive 1 render pass - for the root.
3414 ASSERT_EQ(1U, frame
.render_passes
.size());
3416 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3418 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3419 my_host_impl
->DidDrawAllLayers(frame
);
3423 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusionExternalOverInternal
) {
3424 LayerTreeSettings settings
;
3425 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3426 settings
.cache_render_pass_contents
= true;
3427 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3428 LayerTreeHostImpl::Create(settings
,
3431 &stats_instrumentation_
);
3433 // Layers are structured as follows:
3435 // R +-- S1 +- L10 (owning, drawing)
3436 // | +- L11 (corner, occluded by L12)
3437 // | +- L12 (opposite corner)
3439 // +-- S2 +- L20 (owning, drawing)
3442 LayerImpl
* root_ptr
;
3443 LayerImpl
* layer_s1_ptr
;
3444 LayerImpl
* layer_s2_ptr
;
3446 scoped_ptr
<OutputSurface
> output_surface
=
3447 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3448 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3450 gfx::Size
root_size(1000, 1000);
3452 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3453 my_host_impl
->SetViewportSize(root_size
);
3455 scoped_ptr
<LayerImpl
> root
=
3456 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3457 root_ptr
= root
.get();
3459 root
->SetAnchorPoint(gfx::PointF());
3460 root
->SetPosition(gfx::PointF());
3461 root
->SetBounds(root_size
);
3462 root
->SetContentBounds(root_size
);
3463 root
->SetDrawsContent(true);
3464 root
->SetMasksToBounds(true);
3465 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3467 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr
);
3468 layer_s1_ptr
->SetForceRenderSurface(true);
3470 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(0, 0, 300, 300), 0); // L11
3471 AddDrawingLayerTo(layer_s1_ptr
, 4, gfx::Rect(100, 0, 300, 300), 0); // L12
3473 AddDrawingLayerTo(root_ptr
, 7, gfx::Rect(200, 0, 300, 300), &layer_s2_ptr
);
3474 layer_s2_ptr
->SetForceRenderSurface(true);
3476 // Initial draw - must receive all quads
3478 LayerTreeHostImpl::FrameData frame
;
3479 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3481 // Must receive 3 render passes.
3482 // For Root, there are 2 quads; for S1, there are 3 quads; for S2, there is
3484 ASSERT_EQ(3U, frame
.render_passes
.size());
3486 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3487 EXPECT_EQ(3U, frame
.render_passes
[1]->quad_list
.size());
3488 EXPECT_EQ(2U, frame
.render_passes
[2]->quad_list
.size());
3490 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3491 my_host_impl
->DidDrawAllLayers(frame
);
3494 // "Unocclude" surface S1 and repeat draw.
3495 // Must remove S2's render pass since it's cached;
3496 // Must keep S1 quads because texture contained external occlusion.
3497 gfx::Transform transform
= layer_s2_ptr
->transform();
3498 transform
.Translate(300.0, 0.0);
3499 layer_s2_ptr
->SetTransform(transform
);
3501 LayerTreeHostImpl::FrameData frame
;
3502 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3504 // Must receive 2 render passes.
3505 // For Root, there are 2 quads
3506 // For S1, the number of quads depends on what got unoccluded, so not
3507 // asserted beyond being positive.
3508 // For S2, there is no render pass
3509 ASSERT_EQ(2U, frame
.render_passes
.size());
3511 EXPECT_GT(frame
.render_passes
[0]->quad_list
.size(), 0U);
3512 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3514 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3515 my_host_impl
->DidDrawAllLayers(frame
);
3519 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusionExternalNotAligned
) {
3520 LayerTreeSettings settings
;
3521 settings
.cache_render_pass_contents
= true;
3522 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3523 LayerTreeHostImpl::Create(settings
,
3526 &stats_instrumentation_
);
3528 // Layers are structured as follows:
3530 // R +-- S1 +- L10 (rotated, drawing)
3531 // +- L11 (occupies half surface)
3533 LayerImpl
* root_ptr
;
3534 LayerImpl
* layer_s1_ptr
;
3536 scoped_ptr
<OutputSurface
> output_surface
=
3537 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3538 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3540 gfx::Size
root_size(1000, 1000);
3542 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3543 my_host_impl
->SetViewportSize(root_size
);
3545 scoped_ptr
<LayerImpl
> root
=
3546 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3547 root_ptr
= root
.get();
3549 root
->SetAnchorPoint(gfx::PointF());
3550 root
->SetPosition(gfx::PointF());
3551 root
->SetBounds(root_size
);
3552 root
->SetContentBounds(root_size
);
3553 root
->SetDrawsContent(true);
3554 root
->SetMasksToBounds(true);
3555 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3557 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(0, 0, 400, 400), &layer_s1_ptr
);
3558 layer_s1_ptr
->SetForceRenderSurface(true);
3559 gfx::Transform transform
= layer_s1_ptr
->transform();
3560 transform
.Translate(200.0, 200.0);
3561 transform
.Rotate(45.0);
3562 transform
.Translate(-200.0, -200.0);
3563 layer_s1_ptr
->SetTransform(transform
);
3565 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(200, 0, 200, 400), 0); // L11
3567 // Initial draw - must receive all quads
3569 LayerTreeHostImpl::FrameData frame
;
3570 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3572 // Must receive 2 render passes.
3573 ASSERT_EQ(2U, frame
.render_passes
.size());
3575 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3576 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
3578 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3579 my_host_impl
->DidDrawAllLayers(frame
);
3582 // Change opacity and draw. Verify we used cached texture.
3583 layer_s1_ptr
->SetOpacity(0.2f
);
3585 LayerTreeHostImpl::FrameData frame
;
3586 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3588 // One render pass must be gone due to cached texture.
3589 ASSERT_EQ(1U, frame
.render_passes
.size());
3591 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3593 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3594 my_host_impl
->DidDrawAllLayers(frame
);
3598 TEST_F(LayerTreeHostImplTest
, TextureCachingWithOcclusionPartialSwap
) {
3599 LayerTreeSettings settings
;
3600 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3601 settings
.partial_swap_enabled
= true;
3602 settings
.cache_render_pass_contents
= true;
3603 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3604 LayerTreeHostImpl::Create(settings
,
3607 &stats_instrumentation_
);
3609 // Layers are structure as follows:
3611 // R +-- S1 +- L10 (owning)
3615 // +-- S2 +- L20 (owning)
3619 // L12 occludes L11 (internal)
3620 // L20 occludes L10 (external)
3621 // L21 occludes L20 (internal)
3623 LayerImpl
* root_ptr
;
3624 LayerImpl
* layer_s1_ptr
;
3625 LayerImpl
* layer_s2_ptr
;
3627 scoped_ptr
<OutputSurface
> output_surface
=
3628 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3629 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3631 gfx::Size
root_size(1000, 1000);
3633 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3634 my_host_impl
->SetViewportSize(root_size
);
3636 scoped_ptr
<LayerImpl
> root
=
3637 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3638 root_ptr
= root
.get();
3640 root
->SetAnchorPoint(gfx::PointF());
3641 root
->SetPosition(gfx::PointF());
3642 root
->SetBounds(root_size
);
3643 root
->SetContentBounds(root_size
);
3644 root
->SetDrawsContent(true);
3645 root
->SetMasksToBounds(true);
3646 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3648 AddDrawingLayerTo(root_ptr
, 2, gfx::Rect(300, 300, 300, 300), &layer_s1_ptr
);
3649 layer_s1_ptr
->SetForceRenderSurface(true);
3651 AddDrawingLayerTo(layer_s1_ptr
, 3, gfx::Rect(10, 10, 10, 10), 0); // L11
3652 AddDrawingLayerTo(layer_s1_ptr
, 4, gfx::Rect(0, 0, 30, 30), 0); // L12
3654 AddDrawingLayerTo(root_ptr
, 5, gfx::Rect(550, 250, 300, 400), &layer_s2_ptr
);
3655 layer_s2_ptr
->SetForceRenderSurface(true);
3657 AddDrawingLayerTo(layer_s2_ptr
, 6, gfx::Rect(20, 20, 5, 5), 0); // L21
3659 // Initial draw - must receive all quads
3661 LayerTreeHostImpl::FrameData frame
;
3662 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3664 // Must receive 3 render passes.
3665 // For Root, there are 2 quads; for S1, there are 2 quads (one is occluded);
3666 // for S2, there is 2 quads.
3667 ASSERT_EQ(3U, frame
.render_passes
.size());
3669 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3670 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3671 EXPECT_EQ(2U, frame
.render_passes
[2]->quad_list
.size());
3673 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3674 my_host_impl
->DidDrawAllLayers(frame
);
3677 // "Unocclude" surface S1 and repeat draw.
3678 // Must remove S2's render pass since it's cached;
3679 // Must keep S1 quads because texture contained external occlusion.
3680 gfx::Transform transform
= layer_s2_ptr
->transform();
3681 transform
.Translate(150.0, 150.0);
3682 layer_s2_ptr
->SetTransform(transform
);
3684 LayerTreeHostImpl::FrameData frame
;
3685 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3687 // Must receive 2 render passes.
3688 // For Root, there are 2 quads.
3689 // For S1, there are 2 quads.
3690 // For S2, there is no render pass
3691 ASSERT_EQ(2U, frame
.render_passes
.size());
3693 EXPECT_EQ(2U, frame
.render_passes
[0]->quad_list
.size());
3694 EXPECT_EQ(2U, frame
.render_passes
[1]->quad_list
.size());
3696 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3697 my_host_impl
->DidDrawAllLayers(frame
);
3700 // "Re-occlude" surface S1 and repeat draw.
3701 // Must remove S1's render pass since it is now available in full.
3702 // S2 has no change so must also be removed.
3703 transform
= layer_s2_ptr
->transform();
3704 transform
.Translate(-15.0, -15.0);
3705 layer_s2_ptr
->SetTransform(transform
);
3707 LayerTreeHostImpl::FrameData frame
;
3708 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3710 // Root render pass only.
3711 ASSERT_EQ(1U, frame
.render_passes
.size());
3713 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3714 my_host_impl
->DidDrawAllLayers(frame
);
3718 TEST_F(LayerTreeHostImplTest
, TextureCachingWithScissor
) {
3719 LayerTreeSettings settings
;
3720 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3721 settings
.cache_render_pass_contents
= true;
3722 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3723 LayerTreeHostImpl::Create(settings
,
3726 &stats_instrumentation_
);
3729 Layers are created as follows:
3731 +--------------------+
3735 | | +-------------------+
3737 | | +-------------------+
3742 +--------------------+
3744 Layers 1, 2 have render surfaces
3746 scoped_ptr
<LayerImpl
> root
=
3747 LayerImpl::Create(my_host_impl
->active_tree(), 1);
3748 scoped_ptr
<TiledLayerImpl
> child
=
3749 TiledLayerImpl::Create(my_host_impl
->active_tree(), 2);
3750 scoped_ptr
<LayerImpl
> grand_child
=
3751 LayerImpl::Create(my_host_impl
->active_tree(), 3);
3753 gfx::Rect
root_rect(0, 0, 100, 100);
3754 gfx::Rect
child_rect(10, 10, 50, 50);
3755 gfx::Rect
grand_child_rect(5, 5, 150, 150);
3757 scoped_ptr
<OutputSurface
> output_surface
=
3758 FakeOutputSurface::Create3d(scoped_ptr
<WebKit::WebGraphicsContext3D
>(
3759 new PartialSwapContext
)).PassAs
<OutputSurface
>();
3760 my_host_impl
->InitializeRenderer(output_surface
.Pass());
3762 root
->SetAnchorPoint(gfx::PointF());
3763 root
->SetPosition(gfx::PointF(root_rect
.x(), root_rect
.y()));
3764 root
->SetBounds(gfx::Size(root_rect
.width(), root_rect
.height()));
3765 root
->SetContentBounds(root
->bounds());
3766 root
->SetDrawsContent(true);
3767 root
->SetMasksToBounds(true);
3769 child
->SetAnchorPoint(gfx::PointF());
3770 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
3771 child
->SetOpacity(0.5f
);
3772 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
3773 child
->SetContentBounds(child
->bounds());
3774 child
->SetDrawsContent(true);
3775 child
->set_skips_draw(false);
3777 // child layer has 10x10 tiles.
3778 scoped_ptr
<LayerTilingData
> tiler
=
3779 LayerTilingData::Create(gfx::Size(10, 10),
3780 LayerTilingData::HAS_BORDER_TEXELS
);
3781 tiler
->SetBounds(child
->content_bounds());
3782 child
->SetTilingData(*tiler
.get());
3784 grand_child
->SetAnchorPoint(gfx::PointF());
3785 grand_child
->SetPosition(grand_child_rect
.origin());
3786 grand_child
->SetBounds(grand_child_rect
.size());
3787 grand_child
->SetContentBounds(grand_child
->bounds());
3788 grand_child
->SetDrawsContent(true);
3790 TiledLayerImpl
* child_ptr
= child
.get();
3791 RenderPass::Id
child_pass_id(child_ptr
->id(), 0);
3793 child
->AddChild(grand_child
.Pass());
3794 root
->AddChild(child
.PassAs
<LayerImpl
>());
3795 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
3796 my_host_impl
->SetViewportSize(root_rect
.size());
3798 EXPECT_FALSE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3801 LayerTreeHostImpl::FrameData frame
;
3802 host_impl_
->SetFullRootLayerDamage();
3803 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3804 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3805 my_host_impl
->DidDrawAllLayers(frame
);
3808 // We should have cached textures for surface 2.
3809 EXPECT_TRUE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3812 LayerTreeHostImpl::FrameData frame
;
3813 host_impl_
->SetFullRootLayerDamage();
3814 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3815 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3816 my_host_impl
->DidDrawAllLayers(frame
);
3819 // We should still have cached textures for surface 2 after drawing with no
3821 EXPECT_TRUE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3824 // Damage a single tile of surface 2.
3825 child_ptr
->set_update_rect(gfx::Rect(10, 10, 10, 10));
3827 LayerTreeHostImpl::FrameData frame
;
3828 host_impl_
->SetFullRootLayerDamage();
3829 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3830 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3831 my_host_impl
->DidDrawAllLayers(frame
);
3834 // We should have a cached texture for surface 2 again even though it was
3836 EXPECT_TRUE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3840 TEST_F(LayerTreeHostImplTest
, SurfaceTextureCaching
) {
3841 LayerTreeSettings settings
;
3842 settings
.minimum_occlusion_tracking_size
= gfx::Size();
3843 settings
.partial_swap_enabled
= true;
3844 settings
.cache_render_pass_contents
= true;
3845 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
3846 LayerTreeHostImpl::Create(settings
,
3849 &stats_instrumentation_
);
3851 LayerImpl
* root_ptr
;
3852 LayerImpl
* intermediate_layer_ptr
;
3853 LayerImpl
* surface_layer_ptr
;
3854 LayerImpl
* child_ptr
;
3856 SetupLayersForTextureCaching(my_host_impl
.get(),
3858 intermediate_layer_ptr
,
3861 gfx::Size(100, 100));
3863 LayerTreeHostImpl::FrameData frame
;
3864 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3866 // Must receive two render passes, each with one quad
3867 ASSERT_EQ(2U, frame
.render_passes
.size());
3868 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3869 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
3871 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3872 frame
.render_passes
[1]->quad_list
[0]->material
);
3873 const RenderPassDrawQuad
* quad
=
3874 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
3875 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
3876 ASSERT_TRUE(target_pass
);
3877 EXPECT_FALSE(target_pass
->damage_rect
.IsEmpty());
3879 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3880 my_host_impl
->DidDrawAllLayers(frame
);
3883 // Draw without any change
3885 LayerTreeHostImpl::FrameData frame
;
3886 my_host_impl
->SetFullRootLayerDamage();
3887 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3889 // Must receive one render pass, as the other one should be culled
3890 ASSERT_EQ(1U, frame
.render_passes
.size());
3892 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3893 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3894 frame
.render_passes
[0]->quad_list
[0]->material
);
3895 const RenderPassDrawQuad
* quad
=
3896 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
3897 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
3898 frame
.render_passes_by_id
.end());
3900 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3901 my_host_impl
->DidDrawAllLayers(frame
);
3904 // Change opacity and draw
3905 surface_layer_ptr
->SetOpacity(0.6f
);
3907 LayerTreeHostImpl::FrameData frame
;
3908 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3910 // Must receive one render pass, as the other one should be culled
3911 ASSERT_EQ(1U, frame
.render_passes
.size());
3913 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3914 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3915 frame
.render_passes
[0]->quad_list
[0]->material
);
3916 const RenderPassDrawQuad
* quad
=
3917 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
3918 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
3919 frame
.render_passes_by_id
.end());
3921 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3922 my_host_impl
->DidDrawAllLayers(frame
);
3925 // Change less benign property and draw - should have contents changed flag
3926 surface_layer_ptr
->SetStackingOrderChanged(true);
3928 LayerTreeHostImpl::FrameData frame
;
3929 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3931 // Must receive two render passes, each with one quad
3932 ASSERT_EQ(2U, frame
.render_passes
.size());
3934 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3935 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
3936 frame
.render_passes
[0]->quad_list
[0]->material
);
3938 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3939 frame
.render_passes
[1]->quad_list
[0]->material
);
3940 const RenderPassDrawQuad
* quad
=
3941 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
3942 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
3943 ASSERT_TRUE(target_pass
);
3944 EXPECT_FALSE(target_pass
->damage_rect
.IsEmpty());
3946 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3947 my_host_impl
->DidDrawAllLayers(frame
);
3950 // Change opacity again, and evict the cached surface texture.
3951 surface_layer_ptr
->SetOpacity(0.5f
);
3952 static_cast<GLRendererWithReleaseTextures
*>(
3953 my_host_impl
->renderer())->ReleaseRenderPassTextures();
3955 // Change opacity and draw
3956 surface_layer_ptr
->SetOpacity(0.6f
);
3958 LayerTreeHostImpl::FrameData frame
;
3959 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3961 // Must receive two render passes
3962 ASSERT_EQ(2U, frame
.render_passes
.size());
3964 // Even though not enough properties changed, the entire thing must be
3965 // redrawn as we don't have cached textures
3966 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3967 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
3969 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3970 frame
.render_passes
[1]->quad_list
[0]->material
);
3971 const RenderPassDrawQuad
* quad
=
3972 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
3973 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
3974 ASSERT_TRUE(target_pass
);
3975 EXPECT_TRUE(target_pass
->damage_rect
.IsEmpty());
3977 // Was our surface evicted?
3978 EXPECT_FALSE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
3981 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
3982 my_host_impl
->DidDrawAllLayers(frame
);
3985 // Draw without any change, to make sure the state is clear
3987 LayerTreeHostImpl::FrameData frame
;
3988 my_host_impl
->SetFullRootLayerDamage();
3989 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
3991 // Must receive one render pass, as the other one should be culled
3992 ASSERT_EQ(1U, frame
.render_passes
.size());
3994 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
3995 EXPECT_EQ(DrawQuad::RENDER_PASS
,
3996 frame
.render_passes
[0]->quad_list
[0]->material
);
3997 const RenderPassDrawQuad
* quad
=
3998 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
3999 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
4000 frame
.render_passes_by_id
.end());
4002 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4003 my_host_impl
->DidDrawAllLayers(frame
);
4006 // Change location of the intermediate layer
4007 gfx::Transform transform
= intermediate_layer_ptr
->transform();
4008 transform
.matrix().setDouble(0, 3, 1.0001);
4009 intermediate_layer_ptr
->SetTransform(transform
);
4011 LayerTreeHostImpl::FrameData frame
;
4012 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4014 // Must receive one render pass, as the other one should be culled.
4015 ASSERT_EQ(1U, frame
.render_passes
.size());
4016 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4018 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4019 frame
.render_passes
[0]->quad_list
[0]->material
);
4020 const RenderPassDrawQuad
* quad
=
4021 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4022 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
4023 frame
.render_passes_by_id
.end());
4025 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4026 my_host_impl
->DidDrawAllLayers(frame
);
4030 TEST_F(LayerTreeHostImplTest
, SurfaceTextureCachingNoPartialSwap
) {
4031 LayerTreeSettings settings
;
4032 settings
.minimum_occlusion_tracking_size
= gfx::Size();
4033 settings
.cache_render_pass_contents
= true;
4034 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
4035 LayerTreeHostImpl::Create(settings
,
4038 &stats_instrumentation_
);
4040 LayerImpl
* root_ptr
;
4041 LayerImpl
* intermediate_layer_ptr
;
4042 LayerImpl
* surface_layer_ptr
;
4043 LayerImpl
* child_ptr
;
4045 SetupLayersForTextureCaching(my_host_impl
.get(),
4047 intermediate_layer_ptr
,
4050 gfx::Size(100, 100));
4052 LayerTreeHostImpl::FrameData frame
;
4053 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4055 // Must receive two render passes, each with one quad
4056 ASSERT_EQ(2U, frame
.render_passes
.size());
4057 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4058 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
4060 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4061 frame
.render_passes
[1]->quad_list
[0]->material
);
4062 const RenderPassDrawQuad
* quad
=
4063 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
4064 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
4065 EXPECT_FALSE(target_pass
->damage_rect
.IsEmpty());
4067 EXPECT_FALSE(frame
.render_passes
[0]->damage_rect
.IsEmpty());
4068 EXPECT_FALSE(frame
.render_passes
[1]->damage_rect
.IsEmpty());
4071 frame
.render_passes
[0]->has_occlusion_from_outside_target_surface
);
4073 frame
.render_passes
[1]->has_occlusion_from_outside_target_surface
);
4075 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4076 my_host_impl
->DidDrawAllLayers(frame
);
4079 // Draw without any change
4081 LayerTreeHostImpl::FrameData frame
;
4082 my_host_impl
->SetFullRootLayerDamage();
4083 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4085 // Even though there was no change, we set the damage to entire viewport.
4086 // One of the passes should be culled as a result, since contents didn't
4087 // change and we have cached texture.
4088 ASSERT_EQ(1U, frame
.render_passes
.size());
4089 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4091 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4092 my_host_impl
->DidDrawAllLayers(frame
);
4095 // Change opacity and draw
4096 surface_layer_ptr
->SetOpacity(0.6f
);
4098 LayerTreeHostImpl::FrameData frame
;
4099 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4101 // Must receive one render pass, as the other one should be culled
4102 ASSERT_EQ(1U, frame
.render_passes
.size());
4104 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4105 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4106 frame
.render_passes
[0]->quad_list
[0]->material
);
4107 const RenderPassDrawQuad
* quad
=
4108 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4109 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
4110 frame
.render_passes_by_id
.end());
4112 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4113 my_host_impl
->DidDrawAllLayers(frame
);
4116 // Change less benign property and draw - should have contents changed flag
4117 surface_layer_ptr
->SetStackingOrderChanged(true);
4119 LayerTreeHostImpl::FrameData frame
;
4120 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4122 // Must receive two render passes, each with one quad
4123 ASSERT_EQ(2U, frame
.render_passes
.size());
4125 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4126 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
4127 frame
.render_passes
[0]->quad_list
[0]->material
);
4129 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4130 frame
.render_passes
[1]->quad_list
[0]->material
);
4131 const RenderPassDrawQuad
* quad
=
4132 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
4133 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
4134 ASSERT_TRUE(target_pass
);
4135 EXPECT_FALSE(target_pass
->damage_rect
.IsEmpty());
4137 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4138 my_host_impl
->DidDrawAllLayers(frame
);
4141 // Change opacity again, and evict the cached surface texture.
4142 surface_layer_ptr
->SetOpacity(0.5f
);
4143 static_cast<GLRendererWithReleaseTextures
*>(
4144 my_host_impl
->renderer())->ReleaseRenderPassTextures();
4146 // Change opacity and draw
4147 surface_layer_ptr
->SetOpacity(0.6f
);
4149 LayerTreeHostImpl::FrameData frame
;
4150 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4152 // Must receive two render passes
4153 ASSERT_EQ(2U, frame
.render_passes
.size());
4155 // Even though not enough properties changed, the entire thing must be
4156 // redrawn as we don't have cached textures
4157 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4158 EXPECT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
4160 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4161 frame
.render_passes
[1]->quad_list
[0]->material
);
4162 const RenderPassDrawQuad
* quad
=
4163 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[1]->quad_list
[0]);
4164 RenderPass
* target_pass
= frame
.render_passes_by_id
[quad
->render_pass_id
];
4165 ASSERT_TRUE(target_pass
);
4166 EXPECT_TRUE(target_pass
->damage_rect
.IsEmpty());
4168 // Was our surface evicted?
4169 EXPECT_FALSE(my_host_impl
->renderer()->HaveCachedResourcesForRenderPassId(
4172 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4173 my_host_impl
->DidDrawAllLayers(frame
);
4176 // Draw without any change, to make sure the state is clear
4178 LayerTreeHostImpl::FrameData frame
;
4179 my_host_impl
->SetFullRootLayerDamage();
4180 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4182 // Even though there was no change, we set the damage to entire viewport.
4183 // One of the passes should be culled as a result, since contents didn't
4184 // change and we have cached texture.
4185 ASSERT_EQ(1U, frame
.render_passes
.size());
4186 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4188 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4189 my_host_impl
->DidDrawAllLayers(frame
);
4192 // Change location of the intermediate layer
4193 gfx::Transform transform
= intermediate_layer_ptr
->transform();
4194 transform
.matrix().setDouble(0, 3, 1.0001);
4195 intermediate_layer_ptr
->SetTransform(transform
);
4197 LayerTreeHostImpl::FrameData frame
;
4198 EXPECT_TRUE(my_host_impl
->PrepareToDraw(&frame
, gfx::Rect()));
4200 // Must receive one render pass, as the other one should be culled.
4201 ASSERT_EQ(1U, frame
.render_passes
.size());
4202 EXPECT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
4204 EXPECT_EQ(DrawQuad::RENDER_PASS
,
4205 frame
.render_passes
[0]->quad_list
[0]->material
);
4206 const RenderPassDrawQuad
* quad
=
4207 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4208 EXPECT_TRUE(frame
.render_passes_by_id
.find(quad
->render_pass_id
) ==
4209 frame
.render_passes_by_id
.end());
4211 my_host_impl
->DrawLayers(&frame
, base::TimeTicks::Now());
4212 my_host_impl
->DidDrawAllLayers(frame
);
4216 TEST_F(LayerTreeHostImplTest
, ReleaseContentsTextureShouldTriggerCommit
) {
4217 set_reduce_memory_result(false);
4219 // If changing the memory limit wouldn't result in changing what was
4220 // committed, then no commit should be requested.
4221 set_reduce_memory_result(false);
4222 host_impl_
->set_max_memory_needed_bytes(
4223 host_impl_
->memory_allocation_limit_bytes() - 1);
4224 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
4225 host_impl_
->memory_allocation_limit_bytes() - 1));
4226 EXPECT_FALSE(did_request_commit_
);
4227 did_request_commit_
= false;
4229 // If changing the memory limit would result in changing what was
4230 // committed, then a commit should be requested, even though nothing was
4232 set_reduce_memory_result(false);
4233 host_impl_
->set_max_memory_needed_bytes(
4234 host_impl_
->memory_allocation_limit_bytes());
4235 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
4236 host_impl_
->memory_allocation_limit_bytes() - 1));
4237 EXPECT_TRUE(did_request_commit_
);
4238 did_request_commit_
= false;
4240 // Especially if changing the memory limit caused evictions, we need
4242 set_reduce_memory_result(true);
4243 host_impl_
->set_max_memory_needed_bytes(1);
4244 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
4245 host_impl_
->memory_allocation_limit_bytes() - 1));
4246 EXPECT_TRUE(did_request_commit_
);
4247 did_request_commit_
= false;
4249 // But if we set it to the same value that it was before, we shouldn't
4251 host_impl_
->SetManagedMemoryPolicy(ManagedMemoryPolicy(
4252 host_impl_
->memory_allocation_limit_bytes()));
4253 EXPECT_FALSE(did_request_commit_
);
4256 struct RenderPassRemovalTestData
: public LayerTreeHostImpl::FrameData
{
4257 ScopedPtrHashMap
<RenderPass::Id
, TestRenderPass
> render_pass_cache
;
4258 scoped_ptr
<SharedQuadState
> shared_quad_state
;
4261 class TestRenderer
: public GLRenderer
, public RendererClient
{
4263 static scoped_ptr
<TestRenderer
> Create(ResourceProvider
* resource_provider
,
4264 OutputSurface
* output_surface
,
4266 scoped_ptr
<TestRenderer
> renderer(new TestRenderer(resource_provider
,
4269 if (!renderer
->Initialize())
4270 return scoped_ptr
<TestRenderer
>();
4272 return renderer
.Pass();
4275 void ClearCachedTextures() { textures_
.clear(); }
4276 void SetHaveCachedResourcesForRenderPassId(RenderPass::Id id
) {
4277 textures_
.insert(id
);
4280 virtual bool HaveCachedResourcesForRenderPassId(RenderPass::Id id
) const
4282 return textures_
.count(id
);
4285 // RendererClient implementation.
4286 virtual gfx::Size
DeviceViewportSize() const OVERRIDE
{
4287 return viewport_size_
;
4289 virtual const LayerTreeSettings
& Settings() const OVERRIDE
{
4292 virtual void DidLoseOutputSurface() OVERRIDE
{}
4293 virtual void OnSwapBuffersComplete() OVERRIDE
{}
4294 virtual void SetFullRootLayerDamage() OVERRIDE
{}
4295 virtual void SetManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
4297 virtual void EnforceManagedMemoryPolicy(const ManagedMemoryPolicy
& policy
)
4299 virtual bool HasImplThread() const OVERRIDE
{ return false; }
4300 virtual bool ShouldClearRootRenderPass() const OVERRIDE
{ return true; }
4301 virtual CompositorFrameMetadata
MakeCompositorFrameMetadata() const
4302 OVERRIDE
{ return CompositorFrameMetadata(); }
4303 virtual bool AllowPartialSwap() const OVERRIDE
{
4308 TestRenderer(ResourceProvider
* resource_provider
,
4309 OutputSurface
* output_surface
,
4311 : GLRenderer(this, output_surface
, resource_provider
, 0) {}
4314 LayerTreeSettings settings_
;
4315 gfx::Size viewport_size_
;
4316 base::hash_set
<RenderPass::Id
> textures_
;
4319 static void ConfigureRenderPassTestData(const char* test_script
,
4320 RenderPassRemovalTestData
* test_data
,
4321 TestRenderer
* renderer
) {
4322 renderer
->ClearCachedTextures();
4324 // One shared state for all quads - we don't need the correct details
4325 test_data
->shared_quad_state
= SharedQuadState::Create();
4326 test_data
->shared_quad_state
->SetAll(gfx::Transform(),
4333 const char* current_char
= test_script
;
4335 // Pre-create root pass
4336 RenderPass::Id root_render_pass_id
=
4337 RenderPass::Id(test_script
[0], test_script
[1]);
4338 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
4339 pass
->SetNew(root_render_pass_id
, gfx::Rect(), gfx::Rect(), gfx::Transform());
4340 test_data
->render_pass_cache
.add(root_render_pass_id
, pass
.Pass());
4341 while (*current_char
) {
4342 int layer_id
= *current_char
;
4344 ASSERT_TRUE(current_char
);
4345 int index
= *current_char
;
4348 RenderPass::Id render_pass_id
= RenderPass::Id(layer_id
, index
);
4350 bool is_replica
= false;
4351 if (!test_data
->render_pass_cache
.contains(render_pass_id
))
4354 scoped_ptr
<TestRenderPass
> render_pass
=
4355 test_data
->render_pass_cache
.take(render_pass_id
);
4357 // Cycle through quad data and create all quads.
4358 while (*current_char
&& *current_char
!= '\n') {
4359 if (*current_char
== 's') {
4360 // Solid color draw quad.
4361 scoped_ptr
<SolidColorDrawQuad
> quad
= SolidColorDrawQuad::Create();
4362 quad
->SetNew(test_data
->shared_quad_state
.get(),
4363 gfx::Rect(0, 0, 10, 10),
4366 render_pass
->AppendQuad(quad
.PassAs
<DrawQuad
>());
4368 } else if ((*current_char
>= 'A') && (*current_char
<= 'Z')) {
4369 // RenderPass draw quad.
4370 int layer_id
= *current_char
;
4372 ASSERT_TRUE(current_char
);
4373 int index
= *current_char
;
4375 RenderPass::Id new_render_pass_id
= RenderPass::Id(layer_id
, index
);
4376 ASSERT_NE(root_render_pass_id
, new_render_pass_id
);
4377 bool has_texture
= false;
4378 bool contents_changed
= true;
4380 if (*current_char
== '[') {
4382 while (*current_char
&& *current_char
!= ']') {
4383 switch (*current_char
) {
4385 contents_changed
= false;
4393 if (*current_char
== ']')
4397 if (test_data
->render_pass_cache
.find(new_render_pass_id
) ==
4398 test_data
->render_pass_cache
.end()) {
4400 renderer
->SetHaveCachedResourcesForRenderPassId(new_render_pass_id
);
4402 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
4403 pass
->SetNew(new_render_pass_id
,
4407 test_data
->render_pass_cache
.add(new_render_pass_id
, pass
.Pass());
4410 gfx::Rect quad_rect
= gfx::Rect(0, 0, 1, 1);
4411 gfx::Rect contents_changed_rect
=
4412 contents_changed
? quad_rect
: gfx::Rect();
4413 scoped_ptr
<RenderPassDrawQuad
> quad
= RenderPassDrawQuad::Create();
4414 quad
->SetNew(test_data
->shared_quad_state
.get(),
4419 contents_changed_rect
,
4420 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
4421 WebKit::WebFilterOperations(),
4422 skia::RefPtr
<SkImageFilter
>(),
4423 WebKit::WebFilterOperations());
4424 render_pass
->AppendQuad(quad
.PassAs
<DrawQuad
>());
4427 test_data
->render_passes_by_id
[render_pass_id
] = render_pass
.get();
4428 test_data
->render_passes
.insert(test_data
->render_passes
.begin(),
4429 render_pass
.PassAs
<RenderPass
>());
4435 void DumpRenderPassTestData(const RenderPassRemovalTestData
& test_data
,
4438 for (RenderPassList::const_reverse_iterator it
=
4439 test_data
.render_passes
.rbegin();
4440 it
!= test_data
.render_passes
.rend();
4442 const RenderPass
* current_pass
= *it
;
4443 *pos
= current_pass
->id
.layer_id
;
4445 *pos
= current_pass
->id
.index
;
4448 QuadList::const_iterator quad_list_iterator
=
4449 current_pass
->quad_list
.begin();
4450 while (quad_list_iterator
!= current_pass
->quad_list
.end()) {
4451 DrawQuad
* current_quad
= *quad_list_iterator
;
4452 switch (current_quad
->material
) {
4453 case DrawQuad::SOLID_COLOR
:
4457 case DrawQuad::RENDER_PASS
:
4458 *pos
= RenderPassDrawQuad::MaterialCast(current_quad
)->
4459 render_pass_id
.layer_id
;
4461 *pos
= RenderPassDrawQuad::MaterialCast(current_quad
)->
4462 render_pass_id
.index
;
4471 quad_list_iterator
++;
4479 // Each RenderPassList is represented by a string which describes the
4481 // The syntax of the string is as follows:
4483 // RsssssX[c]ssYsssZ[t]ssW[ct]
4484 // Identifies the render pass------------------------^ ^^^ ^ ^ ^ ^ ^
4485 // These are solid color quads--------------------------+ | | | | |
4486 // Identifies RenderPassDrawQuad's RenderPass--------------+ | | | |
4487 // This quad's contents didn't change------------------------+ | | |
4488 // This quad's contents changed and it has no texture------------+ | |
4489 // This quad has texture but its contents changed----------------------+ |
4490 // This quad's contents didn't change and it has texture - will be removed---+
4492 // Expected results have exactly the same syntax, except they do not use square
4493 // brackets, since we only check the structure, not attributes.
4495 // Test case configuration consists of initialization script and expected
4496 // results, all in the same format.
4499 const char* init_script
;
4500 const char* expected_result
;
4503 TestCase remove_render_passes_cases
[] = {
4510 "Single pass - no quads",
4515 "Two passes, no removal",
4522 "Two passes, remove last",
4528 "Have texture but contents changed - leave pass",
4535 "Contents didn't change but no texture - leave pass",
4542 "Replica: two quads reference the same pass; remove",
4543 "R0ssssA0[ct]A0[ct]sss\n"
4548 "Replica: two quads reference the same pass; leave",
4549 "R0ssssA0[c]A0[c]sss\n"
4555 "Many passes, remove all",
4557 "A0sssB0[ct]C0[ct]s\n"
4558 "B0sssD0[ct]ssE0[ct]F0[ct]\n"
4568 "Deep recursion, remove all",
4570 "R0sssssA0[ct]ssss\n"
4585 "Wide recursion, remove all",
4586 "R0A0[ct]B0[ct]C0[ct]D0[ct]E0[ct]F0[ct]G0[ct]H0[ct]I0[ct]J0[ct]\n"
4598 "R0A0B0C0D0E0F0G0H0I0J0\n"
4601 "Remove passes regardless of cache state",
4604 "B0sssD0[c]ssE0[t]F0\n"
4614 "Leave some passes, remove others",
4617 "A0sssB0[t]C0[ct]s\n"
4633 static void VerifyRenderPassTestData(
4634 const TestCase
& test_case
,
4635 const RenderPassRemovalTestData
& test_data
) {
4636 char actual_result
[1024];
4637 DumpRenderPassTestData(test_data
, actual_result
);
4638 EXPECT_STREQ(test_case
.expected_result
, actual_result
) << "In test case: " <<
4642 TEST_F(LayerTreeHostImplTest
, TestRemoveRenderPasses
) {
4643 scoped_ptr
<OutputSurface
> output_surface(CreateOutputSurface());
4644 ASSERT_TRUE(output_surface
->context3d());
4645 scoped_ptr
<ResourceProvider
> resource_provider
=
4646 ResourceProvider::Create(output_surface
.get(), 0);
4648 scoped_ptr
<TestRenderer
> renderer
=
4649 TestRenderer::Create(resource_provider
.get(),
4650 output_surface
.get(),
4653 int test_case_index
= 0;
4654 while (remove_render_passes_cases
[test_case_index
].name
) {
4655 RenderPassRemovalTestData test_data
;
4656 ConfigureRenderPassTestData(
4657 remove_render_passes_cases
[test_case_index
].init_script
,
4660 LayerTreeHostImpl::RemoveRenderPasses(
4661 LayerTreeHostImpl::CullRenderPassesWithCachedTextures(renderer
.get()),
4663 VerifyRenderPassTestData(remove_render_passes_cases
[test_case_index
],
4669 class LayerTreeHostImplTestWithDelegatingRenderer
4670 : public LayerTreeHostImplTest
{
4672 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() OVERRIDE
{
4673 return FakeOutputSurface::CreateDelegating3d().PassAs
<OutputSurface
>();
4676 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
4677 bool expect_to_draw
= !expected_damage
.IsEmpty();
4679 LayerTreeHostImpl::FrameData frame
;
4680 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4682 if (!expect_to_draw
) {
4683 // With no damage, we don't draw, and no quads are created.
4684 ASSERT_EQ(0u, frame
.render_passes
.size());
4686 ASSERT_EQ(1u, frame
.render_passes
.size());
4688 // Verify the damage rect for the root render pass.
4689 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
4690 EXPECT_RECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
4692 // Verify the root and child layers' quads are generated and not being
4694 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
4696 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
4697 gfx::RectF
expected_child_visible_rect(child
->content_bounds());
4698 EXPECT_RECT_EQ(expected_child_visible_rect
,
4699 root_render_pass
->quad_list
[0]->visible_rect
);
4701 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
4702 gfx::RectF
expected_root_visible_rect(root
->content_bounds());
4703 EXPECT_RECT_EQ(expected_root_visible_rect
,
4704 root_render_pass
->quad_list
[1]->visible_rect
);
4707 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4708 host_impl_
->DidDrawAllLayers(frame
);
4709 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
4713 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
4714 scoped_ptr
<SolidColorLayerImpl
> root
=
4715 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
4716 root
->SetAnchorPoint(gfx::PointF());
4717 root
->SetPosition(gfx::PointF());
4718 root
->SetBounds(gfx::Size(10, 10));
4719 root
->SetContentBounds(gfx::Size(10, 10));
4720 root
->SetDrawsContent(true);
4722 // Child layer is in the bottom right corner.
4723 scoped_ptr
<SolidColorLayerImpl
> child
=
4724 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
4725 child
->SetAnchorPoint(gfx::PointF(0.f
, 0.f
));
4726 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
4727 child
->SetBounds(gfx::Size(1, 1));
4728 child
->SetContentBounds(gfx::Size(1, 1));
4729 child
->SetDrawsContent(true);
4730 root
->AddChild(child
.PassAs
<LayerImpl
>());
4732 host_impl_
->active_tree()->SetRootLayer(root
.PassAs
<LayerImpl
>());
4734 // Draw a frame. In the first frame, the entire viewport should be damaged.
4735 gfx::Rect full_frame_damage
= gfx::Rect(host_impl_
->device_viewport_size());
4736 DrawFrameAndTestDamage(full_frame_damage
);
4738 // The second frame has damage that doesn't touch the child layer. Its quads
4739 // should still be generated.
4740 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
4741 host_impl_
->active_tree()->root_layer()->set_update_rect(small_damage
);
4742 DrawFrameAndTestDamage(small_damage
);
4744 // The third frame should have no damage, so no quads should be generated.
4745 gfx::Rect no_damage
;
4746 DrawFrameAndTestDamage(no_damage
);
4749 class FakeMaskLayerImpl
: public LayerImpl
{
4751 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4753 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
4756 virtual ResourceProvider::ResourceId
ContentsResourceId() const OVERRIDE
{
4761 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
4762 : LayerImpl(tree_impl
, id
) {}
4765 TEST_F(LayerTreeHostImplTest
, MaskLayerWithScaling
) {
4768 // +-- Scaling Layer (adds a 2x scale)
4770 // +-- Content Layer
4772 scoped_ptr
<LayerImpl
> scoped_root
=
4773 LayerImpl::Create(host_impl_
->active_tree(), 1);
4774 LayerImpl
* root
= scoped_root
.get();
4775 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
4777 scoped_ptr
<LayerImpl
> scoped_scaling_layer
=
4778 LayerImpl::Create(host_impl_
->active_tree(), 2);
4779 LayerImpl
* scaling_layer
= scoped_scaling_layer
.get();
4780 root
->AddChild(scoped_scaling_layer
.Pass());
4782 scoped_ptr
<LayerImpl
> scoped_content_layer
=
4783 LayerImpl::Create(host_impl_
->active_tree(), 3);
4784 LayerImpl
* content_layer
= scoped_content_layer
.get();
4785 scaling_layer
->AddChild(scoped_content_layer
.Pass());
4787 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
4788 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 4);
4789 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
4790 content_layer
->SetMaskLayer(scoped_mask_layer
.PassAs
<LayerImpl
>());
4792 gfx::Size
root_size(100, 100);
4793 root
->SetBounds(root_size
);
4794 root
->SetContentBounds(root_size
);
4795 root
->SetPosition(gfx::PointF());
4796 root
->SetAnchorPoint(gfx::PointF());
4798 gfx::Size
scaling_layer_size(50, 50);
4799 scaling_layer
->SetBounds(scaling_layer_size
);
4800 scaling_layer
->SetContentBounds(scaling_layer_size
);
4801 scaling_layer
->SetPosition(gfx::PointF());
4802 scaling_layer
->SetAnchorPoint(gfx::PointF());
4803 gfx::Transform scale
;
4804 scale
.Scale(2.f
, 2.f
);
4805 scaling_layer
->SetTransform(scale
);
4807 content_layer
->SetBounds(scaling_layer_size
);
4808 content_layer
->SetContentBounds(scaling_layer_size
);
4809 content_layer
->SetPosition(gfx::PointF());
4810 content_layer
->SetAnchorPoint(gfx::PointF());
4811 content_layer
->SetDrawsContent(true);
4813 mask_layer
->SetBounds(scaling_layer_size
);
4814 mask_layer
->SetContentBounds(scaling_layer_size
);
4815 mask_layer
->SetPosition(gfx::PointF());
4816 mask_layer
->SetAnchorPoint(gfx::PointF());
4817 mask_layer
->SetDrawsContent(true);
4820 // Check that the tree scaling is correctly taken into account for the mask,
4821 // that should fully map onto the quad.
4822 float device_scale_factor
= 1.f
;
4823 host_impl_
->SetViewportSize(root_size
);
4824 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4826 LayerTreeHostImpl::FrameData frame
;
4827 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4829 ASSERT_EQ(1u, frame
.render_passes
.size());
4830 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4831 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4832 frame
.render_passes
[0]->quad_list
[0]->material
);
4833 const RenderPassDrawQuad
* render_pass_quad
=
4834 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4835 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4836 render_pass_quad
->rect
.ToString());
4837 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4838 render_pass_quad
->mask_uv_rect
.ToString());
4840 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4841 host_impl_
->DidDrawAllLayers(frame
);
4845 // Applying a DSF should change the render surface size, but won't affect
4846 // which part of the mask is used.
4847 device_scale_factor
= 2.f
;
4848 gfx::Size device_viewport
=
4849 gfx::ToFlooredSize(gfx::ScaleSize(root_size
, device_scale_factor
));
4850 host_impl_
->SetViewportSize(device_viewport
);
4851 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4852 host_impl_
->active_tree()->set_needs_update_draw_properties();
4854 LayerTreeHostImpl::FrameData frame
;
4855 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4857 ASSERT_EQ(1u, frame
.render_passes
.size());
4858 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4859 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4860 frame
.render_passes
[0]->quad_list
[0]->material
);
4861 const RenderPassDrawQuad
* render_pass_quad
=
4862 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4863 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4864 render_pass_quad
->rect
.ToString());
4865 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4866 render_pass_quad
->mask_uv_rect
.ToString());
4868 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4869 host_impl_
->DidDrawAllLayers(frame
);
4873 // Applying an equivalent content scale on the content layer and the mask
4874 // should still result in the same part of the mask being used.
4875 gfx::Size content_bounds
=
4876 gfx::ToRoundedSize(gfx::ScaleSize(scaling_layer_size
,
4877 device_scale_factor
));
4878 content_layer
->SetContentBounds(content_bounds
);
4879 content_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
4880 mask_layer
->SetContentBounds(content_bounds
);
4881 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
4882 host_impl_
->active_tree()->set_needs_update_draw_properties();
4884 LayerTreeHostImpl::FrameData frame
;
4885 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4887 ASSERT_EQ(1u, frame
.render_passes
.size());
4888 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4889 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4890 frame
.render_passes
[0]->quad_list
[0]->material
);
4891 const RenderPassDrawQuad
* render_pass_quad
=
4892 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4893 EXPECT_EQ(gfx::Rect(0, 0, 200, 200).ToString(),
4894 render_pass_quad
->rect
.ToString());
4895 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4896 render_pass_quad
->mask_uv_rect
.ToString());
4898 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4899 host_impl_
->DidDrawAllLayers(frame
);
4903 TEST_F(LayerTreeHostImplTest
, MaskLayerWithDifferentBounds
) {
4904 // The mask layer has bounds 100x100 but is attached to a layer with bounds
4907 scoped_ptr
<LayerImpl
> scoped_root
=
4908 LayerImpl::Create(host_impl_
->active_tree(), 1);
4909 LayerImpl
* root
= scoped_root
.get();
4910 host_impl_
->active_tree()->SetRootLayer(scoped_root
.Pass());
4912 scoped_ptr
<LayerImpl
> scoped_content_layer
=
4913 LayerImpl::Create(host_impl_
->active_tree(), 3);
4914 LayerImpl
* content_layer
= scoped_content_layer
.get();
4915 root
->AddChild(scoped_content_layer
.Pass());
4917 scoped_ptr
<FakeMaskLayerImpl
> scoped_mask_layer
=
4918 FakeMaskLayerImpl::Create(host_impl_
->active_tree(), 4);
4919 FakeMaskLayerImpl
* mask_layer
= scoped_mask_layer
.get();
4920 content_layer
->SetMaskLayer(scoped_mask_layer
.PassAs
<LayerImpl
>());
4922 gfx::Size
root_size(100, 100);
4923 root
->SetBounds(root_size
);
4924 root
->SetContentBounds(root_size
);
4925 root
->SetPosition(gfx::PointF());
4926 root
->SetAnchorPoint(gfx::PointF());
4928 gfx::Size
layer_size(50, 50);
4929 content_layer
->SetBounds(layer_size
);
4930 content_layer
->SetContentBounds(layer_size
);
4931 content_layer
->SetPosition(gfx::PointF());
4932 content_layer
->SetAnchorPoint(gfx::PointF());
4933 content_layer
->SetDrawsContent(true);
4935 gfx::Size
mask_size(100, 100);
4936 mask_layer
->SetBounds(mask_size
);
4937 mask_layer
->SetContentBounds(mask_size
);
4938 mask_layer
->SetPosition(gfx::PointF());
4939 mask_layer
->SetAnchorPoint(gfx::PointF());
4940 mask_layer
->SetDrawsContent(true);
4943 // Check that the mask fills the surface.
4944 float device_scale_factor
= 1.f
;
4945 host_impl_
->SetViewportSize(root_size
);
4946 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4948 LayerTreeHostImpl::FrameData frame
;
4949 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4951 ASSERT_EQ(1u, frame
.render_passes
.size());
4952 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4953 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4954 frame
.render_passes
[0]->quad_list
[0]->material
);
4955 const RenderPassDrawQuad
* render_pass_quad
=
4956 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4957 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
4958 render_pass_quad
->rect
.ToString());
4959 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4960 render_pass_quad
->mask_uv_rect
.ToString());
4962 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4963 host_impl_
->DidDrawAllLayers(frame
);
4967 // Applying a DSF should change the render surface size, but won't affect
4968 // which part of the mask is used.
4969 device_scale_factor
= 2.f
;
4970 gfx::Size device_viewport
=
4971 gfx::ToFlooredSize(gfx::ScaleSize(root_size
, device_scale_factor
));
4972 host_impl_
->SetViewportSize(device_viewport
);
4973 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4974 host_impl_
->active_tree()->set_needs_update_draw_properties();
4976 LayerTreeHostImpl::FrameData frame
;
4977 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
4979 ASSERT_EQ(1u, frame
.render_passes
.size());
4980 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4981 ASSERT_EQ(DrawQuad::RENDER_PASS
,
4982 frame
.render_passes
[0]->quad_list
[0]->material
);
4983 const RenderPassDrawQuad
* render_pass_quad
=
4984 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
4985 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
4986 render_pass_quad
->rect
.ToString());
4987 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
4988 render_pass_quad
->mask_uv_rect
.ToString());
4990 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
4991 host_impl_
->DidDrawAllLayers(frame
);
4995 // Applying an equivalent content scale on the content layer and the mask
4996 // should still result in the same part of the mask being used.
4997 gfx::Size layer_size_large
=
4998 gfx::ToRoundedSize(gfx::ScaleSize(layer_size
, device_scale_factor
));
4999 content_layer
->SetContentBounds(layer_size_large
);
5000 content_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5001 gfx::Size mask_size_large
=
5002 gfx::ToRoundedSize(gfx::ScaleSize(mask_size
, device_scale_factor
));
5003 mask_layer
->SetContentBounds(mask_size_large
);
5004 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5005 host_impl_
->active_tree()->set_needs_update_draw_properties();
5007 LayerTreeHostImpl::FrameData frame
;
5008 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5010 ASSERT_EQ(1u, frame
.render_passes
.size());
5011 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5012 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5013 frame
.render_passes
[0]->quad_list
[0]->material
);
5014 const RenderPassDrawQuad
* render_pass_quad
=
5015 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
5016 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5017 render_pass_quad
->rect
.ToString());
5018 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5019 render_pass_quad
->mask_uv_rect
.ToString());
5021 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5022 host_impl_
->DidDrawAllLayers(frame
);
5025 // Applying a different contents scale to the mask layer will still result
5026 // in the mask covering the owning layer.
5027 mask_layer
->SetContentBounds(mask_size
);
5028 mask_layer
->SetContentsScale(device_scale_factor
, device_scale_factor
);
5029 host_impl_
->active_tree()->set_needs_update_draw_properties();
5031 LayerTreeHostImpl::FrameData frame
;
5032 EXPECT_TRUE(host_impl_
->PrepareToDraw(&frame
, gfx::Rect()));
5034 ASSERT_EQ(1u, frame
.render_passes
.size());
5035 ASSERT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5036 ASSERT_EQ(DrawQuad::RENDER_PASS
,
5037 frame
.render_passes
[0]->quad_list
[0]->material
);
5038 const RenderPassDrawQuad
* render_pass_quad
=
5039 RenderPassDrawQuad::MaterialCast(frame
.render_passes
[0]->quad_list
[0]);
5040 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
5041 render_pass_quad
->rect
.ToString());
5042 EXPECT_EQ(gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
).ToString(),
5043 render_pass_quad
->mask_uv_rect
.ToString());
5045 host_impl_
->DrawLayers(&frame
, base::TimeTicks::Now());
5046 host_impl_
->DidDrawAllLayers(frame
);