Fix LayerTreeHostDamageTestScrollbarDoesDamage
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_damage.cc
bloba3a8af30c53b9c67775eeef86033e32536a19388
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"
14 namespace cc {
15 namespace {
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;
24 did_swaps_ = 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 {
45 EXPECT_TRUE(result);
47 int source_frame = host_impl->active_tree()->source_frame_number();
48 switch (source_frame) {
49 case 0:
50 // The first frame has damage, so we should draw and swap.
51 ++expect_swap_and_succeed_;
52 break;
53 case 1:
54 // The second frame has no damage, so we should not draw and swap.
55 break;
56 case 2:
57 // The third frame has damage again, so we should draw and swap.
58 ++expect_swap_and_succeed_;
59 break;
60 case 3:
61 // The fourth frame has no visible damage, so we should not draw and
62 // swap.
63 EndTest();
64 break;
66 return result;
69 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
70 bool result) OVERRIDE {
71 ++did_swaps_;
72 if (result)
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();
79 switch (next_frame) {
80 case 1:
81 layer_tree_host()->SetNeedsCommit();
82 break;
83 case 2:
84 // Cause visible damage.
85 content_->SetNeedsDisplayRect(
86 gfx::Rect(layer_tree_host()->device_viewport_size()));
87 break;
88 case 3:
89 // Cause non-visible damage.
90 content_->SetNeedsDisplayRect(gfx::Rect(1990, 1990, 10, 10));
91 layer_tree_host()->SetNeedsCommit();
92 break;
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_;
105 int did_swaps_;
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 {
133 EXPECT_TRUE(result);
135 int source_frame = host_impl->active_tree()->source_frame_number();
136 switch (source_frame) {
137 case 0:
138 // The first frame draws and clears any damage.
139 break;
140 case 1: {
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)));
149 break;
151 case 2:
152 // CompositeAndReadback causes a follow-up commit.
153 break;
154 case 3:
155 NOTREACHED();
156 break;
158 return result;
161 virtual void DidCommitAndDrawFrame() OVERRIDE {
162 int next_frame = layer_tree_host()->source_frame_number();
163 switch (next_frame) {
164 case 1: {
165 char pixels[4];
166 layer_tree_host()->CompositeAndReadback(static_cast<void*>(&pixels),
167 gfx::Rect(3, 3, 1, 1));
168 EndTest();
169 break;
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 {
203 EXPECT_TRUE(result);
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) {
213 case 0:
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);
218 break;
219 case 1:
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();
226 break;
227 case 2:
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);
235 break;
236 case 3:
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());
243 } else {
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();
256 break;
257 case 4:
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);
263 EndTest();
264 break;
266 return result;
269 virtual void DidCommitAndDrawFrame() OVERRIDE {
270 if (!TestEnded())
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 {
292 did_swaps_ = 0;
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 {
326 EXPECT_TRUE(result);
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_) {
333 case 0:
334 // The first frame has damage, so we should draw and swap.
335 break;
336 case 1:
337 // The second frame should not damage the scrollbars.
338 EXPECT_FALSE(root_damage.Intersects(gfx::Rect(300, 300, 10, 100)));
339 break;
340 case 2:
341 // The third frame should damage the scrollbars.
342 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
343 break;
344 case 3:
345 // The fourth frame should damage the scrollbars.
346 EXPECT_TRUE(root_damage.Contains(gfx::Rect(300, 300, 10, 100)));
347 EndTest();
348 break;
350 return result;
353 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
354 bool result) OVERRIDE {
355 ++did_swaps_;
356 EXPECT_TRUE(result);
357 LayerImpl* root = host_impl->active_tree()->root_layer();
358 LayerImpl* scroll_layer = root->children()[0];
359 switch (did_swaps_) {
360 case 1:
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();
368 break;
369 case 2:
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)));
373 break;
374 case 3:
375 scroll_layer->SetMaxScrollOffset(gfx::Vector2d(60, 100));
376 host_impl->SetNeedsRedraw();
377 break;
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_;
387 int did_swaps_;
390 MULTI_THREAD_TEST_F(LayerTreeHostDamageTestScrollbarDoesDamage);
392 } // namespace
393 } // namespace cc