Reland "Non-SFI mode: Switch to newlib. (patchset #4 id:60001 of https://codereview...
[chromium-blink-merge.git] / cc / surfaces / display_scheduler_unittest.cc
blob2309b0a39063fbbd8785b581d31d61f874d9f114
1 // Copyright 2015 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/surfaces/display_scheduler.h"
7 #include "base/logging.h"
8 #include "base/test/null_task_runner.h"
9 #include "base/test/simple_test_tick_clock.h"
10 #include "base/trace_event/trace_event.h"
11 #include "cc/output/begin_frame_args.h"
12 #include "cc/surfaces/display.h"
13 #include "cc/test/scheduler_test_common.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace cc {
17 namespace {
19 class FakeDisplaySchedulerClient : public DisplaySchedulerClient {
20 public:
21 FakeDisplaySchedulerClient() : draw_and_swap_count_(0) {}
23 ~FakeDisplaySchedulerClient() override {}
25 bool DrawAndSwap() override {
26 draw_and_swap_count_++;
27 return true;
30 void Reset() { draw_and_swap_count_ = 0; }
32 int draw_and_swap_count() const { return draw_and_swap_count_; }
34 protected:
35 int draw_and_swap_count_;
38 class TestDisplayScheduler : public DisplayScheduler {
39 public:
40 TestDisplayScheduler(DisplaySchedulerClient* client,
41 BeginFrameSource* begin_frame_source,
42 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
43 int max_pending_swaps)
44 : DisplayScheduler(client,
45 begin_frame_source,
46 task_runner,
47 max_pending_swaps),
48 scheduler_begin_frame_deadline_count_(0) {}
50 base::TimeTicks DesiredBeginFrameDeadlineTimeForTest() {
51 return DesiredBeginFrameDeadlineTime();
54 void BeginFrameDeadlineForTest() { OnBeginFrameDeadline(); }
56 void ScheduleBeginFrameDeadline() override {
57 scheduler_begin_frame_deadline_count_++;
58 DisplayScheduler::ScheduleBeginFrameDeadline();
61 int scheduler_begin_frame_deadline_count() {
62 return scheduler_begin_frame_deadline_count_;
65 protected:
66 int scheduler_begin_frame_deadline_count_;
69 class DisplaySchedulerTest : public testing::Test {
70 public:
71 DisplaySchedulerTest() : now_src_(new base::SimpleTestTickClock()) {
72 const int max_pending_swaps = 1;
73 now_src_->Advance(base::TimeDelta::FromMicroseconds(10000));
74 null_task_runner_ = make_scoped_refptr(new base::NullTaskRunner);
75 client_ = make_scoped_ptr(new FakeDisplaySchedulerClient);
76 scheduler_ = make_scoped_ptr(
77 new TestDisplayScheduler(client_.get(), &fake_begin_frame_source_,
78 null_task_runner_, max_pending_swaps));
81 ~DisplaySchedulerTest() override {}
83 void SetUp() override { scheduler_->SetRootSurfaceResourcesLocked(false); }
85 void BeginFrameForTest() {
86 base::TimeTicks frame_time = now_src_->NowTicks();
87 base::TimeDelta interval = BeginFrameArgs::DefaultInterval();
88 base::TimeTicks deadline = frame_time + interval;
89 fake_begin_frame_source_.TestOnBeginFrame(
90 BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
91 interval, BeginFrameArgs::NORMAL));
94 protected:
95 base::SimpleTestTickClock& now_src() { return *now_src_; }
96 FakeDisplaySchedulerClient& client() { return *client_; }
97 DisplayScheduler& scheduler() { return *scheduler_; }
99 scoped_ptr<base::SimpleTestTickClock> now_src_;
100 scoped_refptr<base::NullTaskRunner> null_task_runner_;
102 FakeBeginFrameSource fake_begin_frame_source_;
103 scoped_ptr<FakeDisplaySchedulerClient> client_;
104 scoped_ptr<TestDisplayScheduler> scheduler_;
107 TEST_F(DisplaySchedulerTest, EntireDisplayDamagedDrawsImmediately) {
108 SurfaceId root_surface_id(1);
109 BeginFrameForTest();
110 EXPECT_LT(now_src().NowTicks(),
111 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
112 scheduler_->EntireDisplayDamaged(root_surface_id);
113 EXPECT_GE(now_src().NowTicks(),
114 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
117 TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
118 SurfaceId root_surface_id(0);
119 SurfaceId sid1(1);
120 SurfaceId sid2(2);
122 // Set the root surface
123 scheduler_->EntireDisplayDamaged(root_surface_id);
125 // Get scheduler to detect surface 1 as active by drawing
126 // two frames in a row with damage from surface 1.
127 BeginFrameForTest();
128 scheduler_->SurfaceDamaged(sid1);
129 scheduler_->BeginFrameDeadlineForTest();
130 BeginFrameForTest();
131 scheduler_->SurfaceDamaged(sid1);
132 scheduler_->BeginFrameDeadlineForTest();
134 // Damage only from surface 2 (inactive) does not trigger deadline early.
135 BeginFrameForTest();
136 scheduler_->SurfaceDamaged(sid2);
137 EXPECT_LT(now_src().NowTicks(),
138 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
140 // Damage from surface 1 triggers deadline early.
141 scheduler_->SurfaceDamaged(sid1);
142 EXPECT_GE(now_src().NowTicks(),
143 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
144 scheduler_->BeginFrameDeadlineForTest();
146 // Make both surface 1 and 2 active.
147 BeginFrameForTest();
148 scheduler_->SurfaceDamaged(sid2);
149 scheduler_->SurfaceDamaged(sid1);
150 scheduler_->BeginFrameDeadlineForTest();
152 // Deadline doesn't trigger early until surface 1 and 2 are both damaged.
153 BeginFrameForTest();
154 EXPECT_LT(now_src().NowTicks(),
155 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
156 scheduler_->SurfaceDamaged(sid1);
157 EXPECT_LT(now_src().NowTicks(),
158 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
159 scheduler_->SurfaceDamaged(sid2);
160 EXPECT_GE(now_src().NowTicks(),
161 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
162 scheduler_->BeginFrameDeadlineForTest();
164 // Make the system idle
165 BeginFrameForTest();
166 scheduler_->BeginFrameDeadlineForTest();
167 BeginFrameForTest();
168 scheduler_->BeginFrameDeadlineForTest();
170 // Deadline should trigger early if child surfaces are idle and
171 // we get damage on the root surface.
172 BeginFrameForTest();
173 EXPECT_LT(now_src().NowTicks(),
174 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
175 scheduler_->SurfaceDamaged(root_surface_id);
176 EXPECT_GE(now_src().NowTicks(),
177 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
178 scheduler_->BeginFrameDeadlineForTest();
181 TEST_F(DisplaySchedulerTest, OutputSurfaceLost) {
182 SurfaceId sid1(1);
184 // DrawAndSwap normally.
185 BeginFrameForTest();
186 EXPECT_LT(now_src().NowTicks(),
187 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
188 EXPECT_EQ(0, client_->draw_and_swap_count());
189 scheduler_->SurfaceDamaged(sid1);
190 scheduler_->BeginFrameDeadlineForTest();
191 EXPECT_EQ(1, client_->draw_and_swap_count());
193 // Deadline triggers immediately on OutputSurfaceLost.
194 BeginFrameForTest();
195 EXPECT_LT(now_src().NowTicks(),
196 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
197 scheduler_->OutputSurfaceLost();
198 EXPECT_GE(now_src().NowTicks(),
199 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
201 // Deadline does not DrawAndSwap after OutputSurfaceLost.
202 EXPECT_EQ(1, client_->draw_and_swap_count());
203 scheduler_->SurfaceDamaged(sid1);
204 scheduler_->BeginFrameDeadlineForTest();
205 EXPECT_EQ(1, client_->draw_and_swap_count());
208 TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) {
209 SurfaceId sid1(1);
210 base::TimeTicks late_deadline;
212 // DrawAndSwap normally.
213 BeginFrameForTest();
214 EXPECT_LT(now_src().NowTicks(),
215 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
216 EXPECT_EQ(0, client_->draw_and_swap_count());
217 scheduler_->SurfaceDamaged(sid1);
218 scheduler_->BeginFrameDeadlineForTest();
219 EXPECT_EQ(1, client_->draw_and_swap_count());
221 // Deadline triggers late while root resources are locked.
222 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
223 BeginFrameForTest();
224 scheduler_->SurfaceDamaged(sid1);
225 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
226 scheduler_->SetRootSurfaceResourcesLocked(true);
227 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
229 // Deadline does not DrawAndSwap while root resources are locked.
230 EXPECT_EQ(1, client_->draw_and_swap_count());
231 scheduler_->SurfaceDamaged(sid1);
232 scheduler_->BeginFrameDeadlineForTest();
233 EXPECT_EQ(1, client_->draw_and_swap_count());
235 // Deadline triggers normally when root resources are unlocked.
236 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
237 BeginFrameForTest();
238 scheduler_->SurfaceDamaged(sid1);
239 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
240 scheduler_->SetRootSurfaceResourcesLocked(false);
241 EXPECT_EQ(base::TimeTicks(),
242 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
244 EXPECT_EQ(1, client_->draw_and_swap_count());
245 scheduler_->BeginFrameDeadlineForTest();
246 EXPECT_EQ(2, client_->draw_and_swap_count());
249 TEST_F(DisplaySchedulerTest, DidSwapBuffers) {
250 SurfaceId sid1(1);
251 SurfaceId sid2(2);
252 base::TimeTicks expected_deadline;
254 // Get scheduler to detect surface 1 and 2 as active.
255 BeginFrameForTest();
256 scheduler_->SurfaceDamaged(sid1);
257 scheduler_->SurfaceDamaged(sid2);
258 scheduler_->BeginFrameDeadlineForTest();
259 BeginFrameForTest();
260 scheduler_->SurfaceDamaged(sid1);
261 scheduler_->SurfaceDamaged(sid2);
262 scheduler_->BeginFrameDeadlineForTest();
264 // DrawAndSwap normally.
265 BeginFrameForTest();
266 EXPECT_LT(now_src().NowTicks(),
267 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
268 EXPECT_EQ(2, client_->draw_and_swap_count());
269 scheduler_->SurfaceDamaged(sid1);
270 scheduler_->SurfaceDamaged(sid2);
271 scheduler_->BeginFrameDeadlineForTest();
272 EXPECT_EQ(3, client_->draw_and_swap_count());
273 scheduler_->DidSwapBuffers();
275 // Deadline triggers normally when swap throttled.
276 expected_deadline =
277 fake_begin_frame_source_.TestLastUsedBeginFrameArgs().deadline -
278 BeginFrameArgs::DefaultEstimatedParentDrawTime();
279 BeginFrameForTest();
280 // Damage surface 1, but not surface 2 so we avoid triggering deadline
281 // early because all surfaces are ready.
282 scheduler_->SurfaceDamaged(sid1);
283 EXPECT_EQ(expected_deadline,
284 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
286 // Don't draw and swap in deadline while swap throttled.
287 EXPECT_EQ(3, client_->draw_and_swap_count());
288 scheduler_->BeginFrameDeadlineForTest();
289 EXPECT_EQ(3, client_->draw_and_swap_count());
291 // Deadline triggers normally once not swap throttled.
292 // Damage from previous BeginFrame should cary over, so don't damage again.
293 expected_deadline =
294 fake_begin_frame_source_.TestLastUsedBeginFrameArgs().deadline -
295 BeginFrameArgs::DefaultEstimatedParentDrawTime();
296 scheduler_->DidSwapBuffersComplete();
297 BeginFrameForTest();
298 EXPECT_EQ(expected_deadline,
299 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
300 // Still waiting for surface 2. Once it updates, deadline should trigger
301 // immediately again.
302 scheduler_->SurfaceDamaged(sid2);
303 EXPECT_EQ(scheduler_->DesiredBeginFrameDeadlineTimeForTest(),
304 base::TimeTicks());
305 // Draw and swap now that we aren't throttled.
306 EXPECT_EQ(3, client_->draw_and_swap_count());
307 scheduler_->BeginFrameDeadlineForTest();
308 EXPECT_EQ(4, client_->draw_and_swap_count());
311 // This test verfies that we try to reschedule the deadline
312 // after any event that may change what deadline we want.
313 TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) {
314 SurfaceId root_surface_id(1);
315 SurfaceId sid1(2);
316 int count = 1;
317 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
319 BeginFrameForTest();
320 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
322 scheduler_->BeginFrameDeadlineForTest();
323 scheduler_->DidSwapBuffers();
324 BeginFrameForTest();
325 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
327 scheduler_->DidSwapBuffersComplete();
328 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
330 scheduler_->EntireDisplayDamaged(root_surface_id);
331 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
333 scheduler_->SurfaceDamaged(sid1);
334 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
336 scheduler_->SetRootSurfaceResourcesLocked(true);
337 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
339 scheduler_->OutputSurfaceLost();
340 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
343 } // namespace
344 } // namespace cc