Infobar material design refresh: bg color
[chromium-blink-merge.git] / cc / surfaces / display_scheduler_unittest.cc
blob0f2725dbc713d64c2b72f77a51a33875a0bf802a
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 const int kMaxPendingSwaps = 1;
21 class FakeDisplaySchedulerClient : public DisplaySchedulerClient {
22 public:
23 FakeDisplaySchedulerClient() : draw_and_swap_count_(0) {}
25 ~FakeDisplaySchedulerClient() override {}
27 bool DrawAndSwap() override {
28 draw_and_swap_count_++;
29 return true;
32 void Reset() { draw_and_swap_count_ = 0; }
34 int draw_and_swap_count() const { return draw_and_swap_count_; }
36 protected:
37 int draw_and_swap_count_;
40 class TestDisplayScheduler : public DisplayScheduler {
41 public:
42 TestDisplayScheduler(DisplaySchedulerClient* client,
43 BeginFrameSource* begin_frame_source,
44 base::SingleThreadTaskRunner* task_runner,
45 int max_pending_swaps)
46 : DisplayScheduler(client,
47 begin_frame_source,
48 task_runner,
49 max_pending_swaps),
50 scheduler_begin_frame_deadline_count_(0) {}
52 base::TimeTicks DesiredBeginFrameDeadlineTimeForTest() {
53 return DesiredBeginFrameDeadlineTime();
56 void BeginFrameDeadlineForTest() { OnBeginFrameDeadline(); }
58 void ScheduleBeginFrameDeadline() override {
59 scheduler_begin_frame_deadline_count_++;
60 DisplayScheduler::ScheduleBeginFrameDeadline();
63 int scheduler_begin_frame_deadline_count() {
64 return scheduler_begin_frame_deadline_count_;
67 protected:
68 int scheduler_begin_frame_deadline_count_;
71 class DisplaySchedulerTest : public testing::Test {
72 public:
73 DisplaySchedulerTest()
74 : now_src_(new base::SimpleTestTickClock()),
75 task_runner_(new base::NullTaskRunner),
76 client_(new FakeDisplaySchedulerClient),
77 scheduler_(new TestDisplayScheduler(client_.get(),
78 &fake_begin_frame_source_,
79 task_runner_.get(),
80 kMaxPendingSwaps)) {
81 now_src_->Advance(base::TimeDelta::FromMicroseconds(10000));
84 ~DisplaySchedulerTest() override {}
86 void SetUp() override { scheduler_->SetRootSurfaceResourcesLocked(false); }
88 void BeginFrameForTest() {
89 base::TimeTicks frame_time = now_src_->NowTicks();
90 base::TimeDelta interval = BeginFrameArgs::DefaultInterval();
91 base::TimeTicks deadline = frame_time + interval;
92 fake_begin_frame_source_.TestOnBeginFrame(
93 BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
94 interval, BeginFrameArgs::NORMAL));
97 protected:
98 base::SimpleTestTickClock& now_src() { return *now_src_; }
99 FakeDisplaySchedulerClient& client() { return *client_; }
100 DisplayScheduler& scheduler() { return *scheduler_; }
102 FakeBeginFrameSource fake_begin_frame_source_;
104 scoped_ptr<base::SimpleTestTickClock> now_src_;
105 scoped_refptr<base::NullTaskRunner> task_runner_;
106 scoped_ptr<FakeDisplaySchedulerClient> client_;
107 scoped_ptr<TestDisplayScheduler> scheduler_;
110 TEST_F(DisplaySchedulerTest, ResizeHasLateDeadlineUntilNewRootSurface) {
111 SurfaceId root_surface_id1(1);
112 SurfaceId root_surface_id2(2);
113 SurfaceId sid1(3);
114 base::TimeTicks late_deadline;
116 // Go trough an initial BeginFrame cycle with the root surface.
117 BeginFrameForTest();
118 scheduler_->SetNewRootSurface(root_surface_id1);
119 scheduler_->BeginFrameDeadlineForTest();
121 // Resize on the next begin frame cycle should cause the deadline to wait
122 // for a new root surface.
123 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
124 BeginFrameForTest();
125 scheduler_->SurfaceDamaged(sid1);
126 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
127 scheduler_->DisplayResized();
128 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
129 scheduler_->SetNewRootSurface(root_surface_id2);
130 EXPECT_GE(now_src().NowTicks(),
131 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
132 scheduler_->BeginFrameDeadlineForTest();
134 // Verify deadline goes back to normal after resize.
135 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
136 BeginFrameForTest();
137 scheduler_->SurfaceDamaged(sid1);
138 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
139 scheduler_->SurfaceDamaged(root_surface_id2);
140 EXPECT_GE(now_src().NowTicks(),
141 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
142 scheduler_->BeginFrameDeadlineForTest();
145 TEST_F(DisplaySchedulerTest, ResizeHasLateDeadlineUntilDamagedSurface) {
146 SurfaceId root_surface_id(1);
147 SurfaceId sid1(2);
148 base::TimeTicks late_deadline;
150 // Go trough an initial BeginFrame cycle with the root surface.
151 BeginFrameForTest();
152 scheduler_->SetNewRootSurface(root_surface_id);
153 scheduler_->BeginFrameDeadlineForTest();
155 // Resize on the next begin frame cycle should cause the deadline to wait
156 // for a new root surface.
157 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
158 BeginFrameForTest();
159 scheduler_->SurfaceDamaged(sid1);
160 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
161 scheduler_->DisplayResized();
162 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
163 scheduler_->SurfaceDamaged(root_surface_id);
164 EXPECT_GE(now_src().NowTicks(),
165 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
166 scheduler_->BeginFrameDeadlineForTest();
168 // Verify deadline goes back to normal after resize.
169 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
170 BeginFrameForTest();
171 scheduler_->SurfaceDamaged(sid1);
172 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
173 scheduler_->SurfaceDamaged(root_surface_id);
174 EXPECT_GE(now_src().NowTicks(),
175 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
176 scheduler_->BeginFrameDeadlineForTest();
179 TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
180 SurfaceId root_surface_id(0);
181 SurfaceId sid1(1);
182 SurfaceId sid2(2);
184 // Set the root surface
185 scheduler_->SetNewRootSurface(root_surface_id);
187 // Get scheduler to detect surface 1 as active by drawing
188 // two frames in a row with damage from surface 1.
189 BeginFrameForTest();
190 scheduler_->SurfaceDamaged(sid1);
191 scheduler_->BeginFrameDeadlineForTest();
192 BeginFrameForTest();
193 scheduler_->SurfaceDamaged(sid1);
194 scheduler_->BeginFrameDeadlineForTest();
196 // Damage only from surface 2 (inactive) does not trigger deadline early.
197 BeginFrameForTest();
198 scheduler_->SurfaceDamaged(sid2);
199 EXPECT_LT(now_src().NowTicks(),
200 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
202 // Damage from surface 1 triggers deadline early.
203 scheduler_->SurfaceDamaged(sid1);
204 EXPECT_GE(now_src().NowTicks(),
205 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
206 scheduler_->BeginFrameDeadlineForTest();
208 // Make both surface 1 and 2 active.
209 BeginFrameForTest();
210 scheduler_->SurfaceDamaged(sid2);
211 scheduler_->SurfaceDamaged(sid1);
212 scheduler_->BeginFrameDeadlineForTest();
214 // Deadline doesn't trigger early until surface 1 and 2 are both damaged.
215 BeginFrameForTest();
216 EXPECT_LT(now_src().NowTicks(),
217 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
218 scheduler_->SurfaceDamaged(sid1);
219 EXPECT_LT(now_src().NowTicks(),
220 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
221 scheduler_->SurfaceDamaged(sid2);
222 EXPECT_GE(now_src().NowTicks(),
223 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
224 scheduler_->BeginFrameDeadlineForTest();
226 // Make the system idle
227 BeginFrameForTest();
228 scheduler_->BeginFrameDeadlineForTest();
229 BeginFrameForTest();
230 scheduler_->BeginFrameDeadlineForTest();
232 // Deadline should trigger early if child surfaces are idle and
233 // we get damage on the root surface.
234 BeginFrameForTest();
235 EXPECT_LT(now_src().NowTicks(),
236 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
237 scheduler_->SurfaceDamaged(root_surface_id);
238 EXPECT_GE(now_src().NowTicks(),
239 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
240 scheduler_->BeginFrameDeadlineForTest();
243 TEST_F(DisplaySchedulerTest, OutputSurfaceLost) {
244 SurfaceId sid1(1);
246 // DrawAndSwap normally.
247 BeginFrameForTest();
248 EXPECT_LT(now_src().NowTicks(),
249 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
250 EXPECT_EQ(0, client_->draw_and_swap_count());
251 scheduler_->SurfaceDamaged(sid1);
252 scheduler_->BeginFrameDeadlineForTest();
253 EXPECT_EQ(1, client_->draw_and_swap_count());
255 // Deadline triggers immediately on OutputSurfaceLost.
256 BeginFrameForTest();
257 EXPECT_LT(now_src().NowTicks(),
258 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
259 scheduler_->OutputSurfaceLost();
260 EXPECT_GE(now_src().NowTicks(),
261 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
263 // Deadline does not DrawAndSwap after OutputSurfaceLost.
264 EXPECT_EQ(1, client_->draw_and_swap_count());
265 scheduler_->SurfaceDamaged(sid1);
266 scheduler_->BeginFrameDeadlineForTest();
267 EXPECT_EQ(1, client_->draw_and_swap_count());
270 TEST_F(DisplaySchedulerTest, ResizeCausesSwap) {
271 SurfaceId sid1(1);
273 // DrawAndSwap normally.
274 BeginFrameForTest();
275 EXPECT_LT(now_src().NowTicks(),
276 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
277 EXPECT_EQ(0, client_->draw_and_swap_count());
278 scheduler_->SurfaceDamaged(sid1);
279 scheduler_->BeginFrameDeadlineForTest();
280 EXPECT_EQ(1, client_->draw_and_swap_count());
282 scheduler_->DisplayResized();
283 BeginFrameForTest();
284 // DisplayResized should trigger a swap to happen.
285 scheduler_->BeginFrameDeadlineForTest();
286 EXPECT_EQ(2, client_->draw_and_swap_count());
289 TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) {
290 SurfaceId sid1(1);
291 base::TimeTicks late_deadline;
293 // DrawAndSwap normally.
294 BeginFrameForTest();
295 EXPECT_LT(now_src().NowTicks(),
296 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
297 EXPECT_EQ(0, client_->draw_and_swap_count());
298 scheduler_->SurfaceDamaged(sid1);
299 scheduler_->BeginFrameDeadlineForTest();
300 EXPECT_EQ(1, client_->draw_and_swap_count());
302 // Deadline triggers late while root resources are locked.
303 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
304 BeginFrameForTest();
305 scheduler_->SurfaceDamaged(sid1);
306 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
307 scheduler_->SetRootSurfaceResourcesLocked(true);
308 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
310 // Deadline does not DrawAndSwap while root resources are locked.
311 EXPECT_EQ(1, client_->draw_and_swap_count());
312 scheduler_->SurfaceDamaged(sid1);
313 scheduler_->BeginFrameDeadlineForTest();
314 EXPECT_EQ(1, client_->draw_and_swap_count());
316 // Deadline triggers normally when root resources are unlocked.
317 late_deadline = now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
318 BeginFrameForTest();
319 scheduler_->SurfaceDamaged(sid1);
320 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
321 scheduler_->SetRootSurfaceResourcesLocked(false);
322 EXPECT_EQ(base::TimeTicks(),
323 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
325 EXPECT_EQ(1, client_->draw_and_swap_count());
326 scheduler_->BeginFrameDeadlineForTest();
327 EXPECT_EQ(2, client_->draw_and_swap_count());
330 TEST_F(DisplaySchedulerTest, DidSwapBuffers) {
331 SurfaceId sid1(1);
332 SurfaceId sid2(2);
334 // Get scheduler to detect surface 1 and 2 as active.
335 BeginFrameForTest();
336 scheduler_->SurfaceDamaged(sid1);
337 scheduler_->SurfaceDamaged(sid2);
338 scheduler_->BeginFrameDeadlineForTest();
339 BeginFrameForTest();
340 scheduler_->SurfaceDamaged(sid1);
341 scheduler_->SurfaceDamaged(sid2);
342 scheduler_->BeginFrameDeadlineForTest();
344 // DrawAndSwap normally.
345 BeginFrameForTest();
346 EXPECT_LT(now_src().NowTicks(),
347 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
348 EXPECT_EQ(2, client_->draw_and_swap_count());
349 scheduler_->SurfaceDamaged(sid1);
350 scheduler_->SurfaceDamaged(sid2);
351 scheduler_->BeginFrameDeadlineForTest();
352 EXPECT_EQ(3, client_->draw_and_swap_count());
353 scheduler_->DidSwapBuffers();
355 // Deadline triggers late when swap throttled.
356 base::TimeTicks late_deadline =
357 now_src().NowTicks() + BeginFrameArgs::DefaultInterval();
358 BeginFrameForTest();
359 // Damage surface 1, but not surface 2 so we avoid triggering deadline
360 // early because all surfaces are ready.
361 scheduler_->SurfaceDamaged(sid1);
362 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
364 // Don't draw and swap in deadline while swap throttled.
365 EXPECT_EQ(3, client_->draw_and_swap_count());
366 scheduler_->BeginFrameDeadlineForTest();
367 EXPECT_EQ(3, client_->draw_and_swap_count());
369 // Deadline triggers normally once not swap throttled.
370 // Damage from previous BeginFrame should cary over, so don't damage again.
371 base::TimeTicks expected_deadline =
372 fake_begin_frame_source_.TestLastUsedBeginFrameArgs().deadline -
373 BeginFrameArgs::DefaultEstimatedParentDrawTime();
374 scheduler_->DidSwapBuffersComplete();
375 BeginFrameForTest();
376 EXPECT_EQ(expected_deadline,
377 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
378 // Still waiting for surface 2. Once it updates, deadline should trigger
379 // immediately again.
380 scheduler_->SurfaceDamaged(sid2);
381 EXPECT_EQ(scheduler_->DesiredBeginFrameDeadlineTimeForTest(),
382 base::TimeTicks());
383 // Draw and swap now that we aren't throttled.
384 EXPECT_EQ(3, client_->draw_and_swap_count());
385 scheduler_->BeginFrameDeadlineForTest();
386 EXPECT_EQ(4, client_->draw_and_swap_count());
389 // This test verfies that we try to reschedule the deadline
390 // after any event that may change what deadline we want.
391 TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) {
392 SurfaceId root_surface_id(1);
393 SurfaceId sid1(2);
394 int count = 1;
395 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
397 BeginFrameForTest();
398 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
400 scheduler_->BeginFrameDeadlineForTest();
401 scheduler_->DidSwapBuffers();
402 BeginFrameForTest();
403 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
405 scheduler_->DidSwapBuffersComplete();
406 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
408 scheduler_->DisplayResized();
409 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
411 scheduler_->SetNewRootSurface(root_surface_id);
412 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
414 scheduler_->SurfaceDamaged(sid1);
415 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
417 scheduler_->SetRootSurfaceResourcesLocked(true);
418 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
420 scheduler_->OutputSurfaceLost();
421 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
424 } // namespace
425 } // namespace cc