1 // Copyright 2012 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.h"
7 #include "cc/test/fake_content_layer.h"
8 #include "cc/test/fake_content_layer_client.h"
9 #include "cc/test/fake_painted_scrollbar_layer.h"
10 #include "cc/test/layer_tree_test.h"
11 #include "cc/trees/damage_tracker.h"
12 #include "cc/trees/layer_tree_impl.h"
17 // These tests deal with damage tracking.
18 class LayerTreeHostDamageTest
: public LayerTreeTest
{};
20 class LayerTreeHostDamageTestNoDamageDoesNotSwap
21 : public LayerTreeHostDamageTest
{
22 virtual void BeginTest() OVERRIDE
{
23 expect_swap_and_succeed_
= 0;
25 did_swap_and_succeed_
= 0;
26 PostSetNeedsCommitToMainThread();
29 virtual void SetupTree() OVERRIDE
{
30 scoped_refptr
<FakeContentLayer
> root
= FakeContentLayer::Create(&client_
);
31 root
->SetBounds(gfx::Size(10, 10));
33 // Most of the layer isn't visible.
34 content_
= FakeContentLayer::Create(&client_
);
35 content_
->SetBounds(gfx::Size(2000, 100));
36 root
->AddChild(content_
);
38 layer_tree_host()->SetRootLayer(root
);
39 LayerTreeHostDamageTest::SetupTree();
42 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl
* host_impl
,
43 LayerTreeHostImpl::FrameData
* frame_data
,
44 bool result
) OVERRIDE
{
47 int source_frame
= host_impl
->active_tree()->source_frame_number();
48 switch (source_frame
) {
50 // The first frame has damage, so we should draw and swap.
51 ++expect_swap_and_succeed_
;
54 // The second frame has no damage, so we should not draw and swap.
57 // The third frame has damage again, so we should draw and swap.
58 ++expect_swap_and_succeed_
;
61 // The fourth frame has no visible damage, so we should not draw and
69 virtual void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
,
70 bool result
) OVERRIDE
{
73 ++did_swap_and_succeed_
;
74 EXPECT_EQ(expect_swap_and_succeed_
, did_swap_and_succeed_
);
77 virtual void DidCommit() OVERRIDE
{
78 int next_frame
= layer_tree_host()->source_frame_number();
81 layer_tree_host()->SetNeedsCommit();
84 // Cause visible damage.
85 content_
->SetNeedsDisplayRect(
86 gfx::Rect(layer_tree_host()->device_viewport_size()));
89 // Cause non-visible damage.
90 content_
->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
91 layer_tree_host()->SetNeedsCommit();
96 virtual void AfterTest() OVERRIDE
{
97 EXPECT_EQ(4, did_swaps_
);
98 EXPECT_EQ(2, expect_swap_and_succeed_
);
99 EXPECT_EQ(expect_swap_and_succeed_
, did_swap_and_succeed_
);
102 FakeContentLayerClient client_
;
103 scoped_refptr
<FakeContentLayer
> content_
;
104 int expect_swap_and_succeed_
;
106 int did_swap_and_succeed_
;
109 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageDoesNotSwap
);
111 class LayerTreeHostDamageTestNoDamageReadbackDoesDraw
112 : public LayerTreeHostDamageTest
{
113 virtual void BeginTest() OVERRIDE
{
114 PostSetNeedsCommitToMainThread();
117 virtual void SetupTree() OVERRIDE
{
118 scoped_refptr
<FakeContentLayer
> root
= FakeContentLayer::Create(&client_
);
119 root
->SetBounds(gfx::Size(10, 10));
121 // Most of the layer isn't visible.
122 content_
= FakeContentLayer::Create(&client_
);
123 content_
->SetBounds(gfx::Size(100, 100));
124 root
->AddChild(content_
);
126 layer_tree_host()->SetRootLayer(root
);
127 LayerTreeHostDamageTest::SetupTree();
130 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl
* host_impl
,
131 LayerTreeHostImpl::FrameData
* frame_data
,
132 bool result
) OVERRIDE
{
135 int source_frame
= host_impl
->active_tree()->source_frame_number();
136 switch (source_frame
) {
138 // The first frame draws and clears any damage.
141 // The second frame is a readback, we should have damage in the readback
142 // rect, but not swap.
143 RenderSurfaceImpl
* root_surface
=
144 host_impl
->active_tree()->root_layer()->render_surface();
145 gfx::RectF root_damage
=
146 root_surface
->damage_tracker()->current_damage_rect();
147 root_damage
.Intersect(root_surface
->content_rect());
148 EXPECT_TRUE(root_damage
.Contains(gfx::Rect(3, 3, 1, 1)));
152 // CompositeAndReadback causes a follow-up commit.
161 virtual void DidCommitAndDrawFrame() OVERRIDE
{
162 int next_frame
= layer_tree_host()->source_frame_number();
163 switch (next_frame
) {
166 layer_tree_host()->CompositeAndReadback(static_cast<void*>(&pixels
),
167 gfx::Rect(3, 3, 1, 1));
174 virtual void AfterTest() OVERRIDE
{}
176 FakeContentLayerClient client_
;
177 scoped_refptr
<FakeContentLayer
> content_
;
180 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestNoDamageReadbackDoesDraw
);
182 class LayerTreeHostDamageTestForcedFullDamage
: public LayerTreeHostDamageTest
{
183 virtual void BeginTest() OVERRIDE
{
184 PostSetNeedsCommitToMainThread();
187 virtual void SetupTree() OVERRIDE
{
188 root_
= FakeContentLayer::Create(&client_
);
189 child_
= FakeContentLayer::Create(&client_
);
191 root_
->SetBounds(gfx::Size(500, 500));
192 child_
->SetPosition(gfx::Point(100, 100));
193 child_
->SetBounds(gfx::Size(30, 30));
195 root_
->AddChild(child_
);
196 layer_tree_host()->SetRootLayer(root_
);
197 LayerTreeHostDamageTest::SetupTree();
200 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl
* host_impl
,
201 LayerTreeHostImpl::FrameData
* frame_data
,
202 bool result
) OVERRIDE
{
205 RenderSurfaceImpl
* root_surface
=
206 host_impl
->active_tree()->root_layer()->render_surface();
207 gfx::RectF root_damage
=
208 root_surface
->damage_tracker()->current_damage_rect();
209 root_damage
.Intersect(root_surface
->content_rect());
211 int source_frame
= host_impl
->active_tree()->source_frame_number();
212 switch (source_frame
) {
214 // The first frame draws and clears any damage.
215 EXPECT_EQ(gfx::RectF(root_surface
->content_rect()).ToString(),
216 root_damage
.ToString());
217 EXPECT_FALSE(frame_data
->has_no_damage
);
220 // If we get a frame without damage then we don't draw.
221 EXPECT_EQ(gfx::RectF().ToString(), root_damage
.ToString());
222 EXPECT_TRUE(frame_data
->has_no_damage
);
224 // Then we set full damage for the next frame.
225 host_impl
->SetFullRootLayerDamage();
228 // The whole frame should be damaged as requested.
229 EXPECT_EQ(gfx::RectF(root_surface
->content_rect()).ToString(),
230 root_damage
.ToString());
231 EXPECT_FALSE(frame_data
->has_no_damage
);
233 // Just a part of the next frame should be damaged.
234 child_damage_rect_
= gfx::RectF(10, 11, 12, 13);
237 if (!delegating_renderer() &&
238 !host_impl
->settings().impl_side_painting
) {
239 // The update rect in the child should be damaged.
240 // TODO(danakj): Remove this when impl side painting is always on.
241 EXPECT_EQ(gfx::RectF(100+10, 100+11, 12, 13).ToString(),
242 root_damage
.ToString());
244 // When using a delegating renderer, or using impl side painting, the
245 // entire child is considered damaged as we need to replace its
246 // resources with newly created ones.
247 EXPECT_EQ(gfx::RectF(child_
->position(), child_
->bounds()).ToString(),
248 root_damage
.ToString());
250 EXPECT_FALSE(frame_data
->has_no_damage
);
252 // If we damage part of the frame, but also damage the full
253 // frame, then the whole frame should be damaged.
254 child_damage_rect_
= gfx::RectF(10, 11, 12, 13);
255 host_impl
->SetFullRootLayerDamage();
258 // The whole frame is damaged.
259 EXPECT_EQ(gfx::RectF(root_surface
->content_rect()).ToString(),
260 root_damage
.ToString());
261 EXPECT_FALSE(frame_data
->has_no_damage
);
269 virtual void DidCommitAndDrawFrame() OVERRIDE
{
271 layer_tree_host()->SetNeedsCommit();
273 if (!child_damage_rect_
.IsEmpty()) {
274 child_
->SetNeedsDisplayRect(child_damage_rect_
);
275 child_damage_rect_
= gfx::RectF();
279 virtual void AfterTest() OVERRIDE
{}
281 FakeContentLayerClient client_
;
282 scoped_refptr
<FakeContentLayer
> root_
;
283 scoped_refptr
<FakeContentLayer
> child_
;
284 gfx::RectF child_damage_rect_
;
287 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostDamageTestForcedFullDamage
);
289 class LayerTreeHostDamageTestScrollbarDoesDamage
290 : public LayerTreeHostDamageTest
{
291 virtual void BeginTest() OVERRIDE
{
293 PostSetNeedsCommitToMainThread();
296 virtual void SetupTree() OVERRIDE
{
297 scoped_refptr
<Layer
> root_layer
= Layer::Create();
298 root_layer
->SetBounds(gfx::Size(400, 400));
299 layer_tree_host()->SetRootLayer(root_layer
);
301 scoped_refptr
<Layer
> content_layer
= FakeContentLayer::Create(&client_
);
302 content_layer
->SetScrollable(true);
303 content_layer
->SetScrollOffset(gfx::Vector2d(10, 20));
304 content_layer
->SetMaxScrollOffset(gfx::Vector2d(30, 50));
305 content_layer
->SetBounds(gfx::Size(100, 200));
306 root_layer
->AddChild(content_layer
);
308 scoped_refptr
<Layer
> scrollbar_layer
=
309 FakePaintedScrollbarLayer::Create(false, true, content_layer
->id());
310 scrollbar_layer
->SetPosition(gfx::Point(300, 300));
311 scrollbar_layer
->SetBounds(gfx::Size(10, 100));
312 root_layer
->AddChild(scrollbar_layer
);
314 gfx::RectF
content_rect(content_layer
->position(),
315 content_layer
->bounds());
316 gfx::RectF
scrollbar_rect(scrollbar_layer
->position(),
317 scrollbar_layer
->bounds());
318 EXPECT_FALSE(content_rect
.Intersects(scrollbar_rect
));
320 LayerTreeHostDamageTest::SetupTree();
323 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl
* host_impl
,
324 LayerTreeHostImpl::FrameData
* frame_data
,
325 bool result
) OVERRIDE
{
327 RenderSurfaceImpl
* root_surface
=
328 host_impl
->active_tree()->root_layer()->render_surface();
329 gfx::RectF root_damage
=
330 root_surface
->damage_tracker()->current_damage_rect();
331 root_damage
.Intersect(root_surface
->content_rect());
332 switch (did_swaps_
) {
334 // The first frame has damage, so we should draw and swap.
337 // The second frame should not damage the scrollbars.
338 EXPECT_FALSE(root_damage
.Intersects(gfx::Rect(300, 300, 10, 100)));
341 // The third frame should damage the scrollbars.
342 EXPECT_TRUE(root_damage
.Contains(gfx::Rect(300, 300, 10, 100)));
345 // The fourth frame should damage the scrollbars.
346 EXPECT_TRUE(root_damage
.Contains(gfx::Rect(300, 300, 10, 100)));
353 virtual void SwapBuffersOnThread(LayerTreeHostImpl
* host_impl
,
354 bool result
) OVERRIDE
{
357 LayerImpl
* root
= host_impl
->active_tree()->root_layer();
358 LayerImpl
* scroll_layer
= root
->children()[0];
359 switch (did_swaps_
) {
361 // Test that modifying the position of the content layer (not
362 // scrolling) won't damage the scrollbar. Do this before the other
363 // tests, as they can cause commits that will later damage the
364 // scrollbar. http://crbug.com/276657
365 scroll_layer
->SetPosition(gfx::Point(1, 1));
366 scroll_layer
->SetScrollOffset(scroll_layer
->scroll_offset());
367 host_impl
->SetNeedsRedraw();
370 host_impl
->ScrollBegin(gfx::Point(1, 1), InputHandler::Wheel
);
371 EXPECT_TRUE(host_impl
->ScrollBy(gfx::Point(),
372 gfx::Vector2dF(10.0, 10.0)));
375 scroll_layer
->SetMaxScrollOffset(gfx::Vector2d(60, 100));
376 host_impl
->SetNeedsRedraw();
381 virtual void AfterTest() OVERRIDE
{
382 // Extra commits may happen and cause swaps: http://crbug.com/276657
383 EXPECT_LE(4, did_swaps_
);
386 FakeContentLayerClient client_
;
390 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage
);