Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: cc/surfaces/display_scheduler_unittest.cc

Issue 1138563002: Add DisplayScheduler for Surfaces (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@rendererLatencyRecoveryHeuristic
Patch Set: rebase Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/surfaces/display_scheduler.cc ('k') | cc/surfaces/display_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include "cc/surfaces/display_scheduler.h"
6
7 #include "base/logging.h"
8 #include "base/test/null_task_runner.h"
9 #include "base/trace_event/trace_event.h"
10 #include "cc/output/begin_frame_args.h"
11 #include "cc/surfaces/display.h"
12 #include "cc/test/scheduler_test_common.h"
13 #include "cc/test/test_now_source.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace cc {
17 namespace {
18
19 class FakeDisplaySchedulerClient : public DisplaySchedulerClient {
20 public:
21 FakeDisplaySchedulerClient() : draw_and_swap_count_(0) {}
22
23 ~FakeDisplaySchedulerClient() override {}
24
25 bool DrawAndSwap() override {
26 draw_and_swap_count_++;
27 return true;
28 }
29
30 void Reset() { draw_and_swap_count_ = 0; }
31
32 int draw_and_swap_count() const { return draw_and_swap_count_; }
33
34 protected:
35 int draw_and_swap_count_;
36 };
37
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) {}
49
50 base::TimeTicks DesiredBeginFrameDeadlineTimeForTest() {
51 return DesiredBeginFrameDeadlineTime();
52 }
53
54 void BeginFrameDeadlineForTest() { OnBeginFrameDeadline(); }
55
56 void ScheduleBeginFrameDeadline() override {
57 scheduler_begin_frame_deadline_count_++;
58 DisplayScheduler::ScheduleBeginFrameDeadline();
59 }
60
61 int scheduler_begin_frame_deadline_count() {
62 return scheduler_begin_frame_deadline_count_;
63 }
64
65 protected:
66 int scheduler_begin_frame_deadline_count_;
67 };
68
69 class DisplaySchedulerTest : public testing::Test {
70 public:
71 DisplaySchedulerTest() {
72 const int max_pending_swaps = 1;
73 now_src_ = TestNowSource::Create();
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));
79 }
80
81 ~DisplaySchedulerTest() override {}
82
83 void SetUp() override { scheduler_->SetRootSurfaceResourcesLocked(false); }
84
85 void BeginFrameForTest() {
86 base::TimeTicks frame_time = now_src_->Now();
87 base::TimeDelta interval = BeginFrameArgs::DefaultInterval();
88 base::TimeTicks deadline = frame_time + interval -
89 BeginFrameArgs::DefaultEstimatedParentDrawTime();
90 fake_begin_frame_source_.TestOnBeginFrame(
91 BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, frame_time, deadline,
92 interval, BeginFrameArgs::NORMAL));
93 }
94
95 protected:
96 TestNowSource& now_src() { return *now_src_; }
97 FakeDisplaySchedulerClient& client() { return *client_; }
98 DisplayScheduler& scheduler() { return *scheduler_; }
99
100 scoped_refptr<TestNowSource> now_src_;
101 scoped_refptr<base::NullTaskRunner> null_task_runner_;
102
103 FakeBeginFrameSource fake_begin_frame_source_;
104 scoped_ptr<FakeDisplaySchedulerClient> client_;
105 scoped_ptr<TestDisplayScheduler> scheduler_;
106 };
107
108 TEST_F(DisplaySchedulerTest, EntireDisplayDamagedDrawsImmediately) {
109 SurfaceId root_surface_id(1);
110 BeginFrameForTest();
111 EXPECT_LT(now_src().Now(),
112 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
113 scheduler_->EntireDisplayDamaged(root_surface_id);
114 EXPECT_GE(now_src().Now(),
115 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
116 }
117
118 TEST_F(DisplaySchedulerTest, SurfaceDamaged) {
119 SurfaceId sid1(1);
120 SurfaceId sid2(2);
121
122 // Get scheduler to detect surface 1 as active by drawing
123 // two frames in a row with damage from surface 1.
124 BeginFrameForTest();
125 scheduler_->SurfaceDamaged(sid1);
126 scheduler_->BeginFrameDeadlineForTest();
127 BeginFrameForTest();
128 scheduler_->SurfaceDamaged(sid1);
129 scheduler_->BeginFrameDeadlineForTest();
130
131 // Damage only from surface 2 (inactive) does not trigger deadline early.
132 BeginFrameForTest();
133 scheduler_->SurfaceDamaged(sid2);
134 EXPECT_LT(now_src().Now(),
135 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
136
137 // Damage from surface 1 triggers deadline early.
138 scheduler_->SurfaceDamaged(sid1);
139 EXPECT_GE(now_src().Now(),
140 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
141 scheduler_->BeginFrameDeadlineForTest();
142
143 // Make both surface 1 and 2 active.
144 BeginFrameForTest();
145 scheduler_->SurfaceDamaged(sid2);
146 scheduler_->SurfaceDamaged(sid1);
147 scheduler_->BeginFrameDeadlineForTest();
148
149 // Deadline doesn't trigger early until surface 1 and 2 are both damaged.
150 BeginFrameForTest();
151 EXPECT_LT(now_src().Now(),
152 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
153 scheduler_->SurfaceDamaged(sid1);
154 EXPECT_LT(now_src().Now(),
155 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
156 scheduler_->SurfaceDamaged(sid2);
157 EXPECT_GE(now_src().Now(),
158 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
159 scheduler_->BeginFrameDeadlineForTest();
160 }
161
162 TEST_F(DisplaySchedulerTest, OutputSurfaceLost) {
163 SurfaceId sid1(1);
164
165 // DrawAndSwap normally.
166 BeginFrameForTest();
167 EXPECT_LT(now_src().Now(),
168 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
169 EXPECT_EQ(0, client_->draw_and_swap_count());
170 scheduler_->SurfaceDamaged(sid1);
171 scheduler_->BeginFrameDeadlineForTest();
172 EXPECT_EQ(1, client_->draw_and_swap_count());
173
174 // Deadline triggers immediately on OutputSurfaceLost.
175 BeginFrameForTest();
176 EXPECT_LT(now_src().Now(),
177 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
178 scheduler_->OutputSurfaceLost();
179 EXPECT_GE(now_src().Now(),
180 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
181
182 // Deadline does not DrawAndSwap after OutputSurfaceLost.
183 EXPECT_EQ(1, client_->draw_and_swap_count());
184 scheduler_->SurfaceDamaged(sid1);
185 scheduler_->BeginFrameDeadlineForTest();
186 EXPECT_EQ(1, client_->draw_and_swap_count());
187 }
188
189 TEST_F(DisplaySchedulerTest, RootSurfaceResourcesLocked) {
190 SurfaceId sid1(1);
191 base::TimeTicks late_deadline;
192
193 // DrawAndSwap normally.
194 BeginFrameForTest();
195 EXPECT_LT(now_src().Now(),
196 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
197 EXPECT_EQ(0, client_->draw_and_swap_count());
198 scheduler_->SurfaceDamaged(sid1);
199 scheduler_->BeginFrameDeadlineForTest();
200 EXPECT_EQ(1, client_->draw_and_swap_count());
201
202 // Deadline triggers late while root resources are locked.
203 late_deadline = now_src().Now() + BeginFrameArgs::DefaultInterval();
204 BeginFrameForTest();
205 scheduler_->SurfaceDamaged(sid1);
206 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
207 scheduler_->SetRootSurfaceResourcesLocked(true);
208 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
209
210 // Deadline does not DrawAndSwap while root resources are locked.
211 EXPECT_EQ(1, client_->draw_and_swap_count());
212 scheduler_->SurfaceDamaged(sid1);
213 scheduler_->BeginFrameDeadlineForTest();
214 EXPECT_EQ(1, client_->draw_and_swap_count());
215
216 // Deadline triggers normally when root resources are unlocked.
217 late_deadline = now_src().Now() + BeginFrameArgs::DefaultInterval();
218 BeginFrameForTest();
219 scheduler_->SurfaceDamaged(sid1);
220 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest());
221 scheduler_->SetRootSurfaceResourcesLocked(false);
222 EXPECT_EQ(base::TimeTicks(),
223 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
224
225 EXPECT_EQ(1, client_->draw_and_swap_count());
226 scheduler_->BeginFrameDeadlineForTest();
227 EXPECT_EQ(2, client_->draw_and_swap_count());
228 }
229
230 TEST_F(DisplaySchedulerTest, DidSwapBuffers) {
231 SurfaceId sid1(1);
232 SurfaceId sid2(2);
233 base::TimeTicks late_deadline;
234
235 // Get scheduler to detect surface 1 and 2 as active.
236 BeginFrameForTest();
237 scheduler_->SurfaceDamaged(sid1);
238 scheduler_->SurfaceDamaged(sid2);
239 scheduler_->BeginFrameDeadlineForTest();
240 BeginFrameForTest();
241 scheduler_->SurfaceDamaged(sid1);
242 scheduler_->SurfaceDamaged(sid2);
243 scheduler_->BeginFrameDeadlineForTest();
244
245 // DrawAndSwap normally.
246 BeginFrameForTest();
247 EXPECT_LT(now_src().Now(),
248 scheduler_->DesiredBeginFrameDeadlineTimeForTest());
249 EXPECT_EQ(2, client_->draw_and_swap_count());
250 scheduler_->SurfaceDamaged(sid1);
251 scheduler_->SurfaceDamaged(sid2);
252 scheduler_->BeginFrameDeadlineForTest();
253 EXPECT_EQ(3, client_->draw_and_swap_count());
254 scheduler_->DidSwapBuffers();
255
256 // Deadline triggers early when swap throttled.
257 BeginFrameForTest();
258 // Damage surface 1, but not surface 2 so we avoid triggering deadline
259 // early because all surfaces are ready.
260 scheduler_->SurfaceDamaged(sid1);
261 EXPECT_EQ(scheduler_->DesiredBeginFrameDeadlineTimeForTest(),
262 base::TimeTicks());
263
264 // Don't draw and swap in deadline while swap throttled.
265 EXPECT_EQ(3, client_->draw_and_swap_count());
266 scheduler_->BeginFrameDeadlineForTest();
267 EXPECT_EQ(3, client_->draw_and_swap_count());
268
269 // Deadline triggers normally once not swap throttled.
270 // Damage from previous BeginFrame should cary over, so don't damage again.
271 late_deadline = now_src().Now() + BeginFrameArgs::DefaultInterval();
272 scheduler_->DidSwapBuffersComplete();
273 BeginFrameForTest();
274 EXPECT_GT(scheduler_->DesiredBeginFrameDeadlineTimeForTest(),
275 now_src().Now());
276 EXPECT_LT(scheduler_->DesiredBeginFrameDeadlineTimeForTest(), late_deadline);
277 // Still waiting for surface 2. Once it updates, deadline should trigger
278 // immediately again.
279 scheduler_->SurfaceDamaged(sid2);
280 EXPECT_EQ(scheduler_->DesiredBeginFrameDeadlineTimeForTest(),
281 base::TimeTicks());
282 // Draw and swap now that we aren't throttled.
283 EXPECT_EQ(3, client_->draw_and_swap_count());
284 scheduler_->BeginFrameDeadlineForTest();
285 EXPECT_EQ(4, client_->draw_and_swap_count());
286 }
287
288 // This test verfies that we try to reschedule the deadline
289 // after any event that may change what deadline we want.
290 TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) {
291 SurfaceId root_surface_id(1);
292 SurfaceId sid1(2);
293 int count = 1;
294 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
295
296 BeginFrameForTest();
297 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
298
299 scheduler_->BeginFrameDeadlineForTest();
300 scheduler_->DidSwapBuffers();
301 BeginFrameForTest();
302 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
303
304 scheduler_->DidSwapBuffersComplete();
305 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
306
307 scheduler_->EntireDisplayDamaged(root_surface_id);
308 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
309
310 scheduler_->SurfaceDamaged(sid1);
311 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
312
313 scheduler_->SetRootSurfaceResourcesLocked(true);
314 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
315
316 scheduler_->OutputSurfaceLost();
317 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count());
318 }
319
320 } // namespace
321 } // namespace cc
OLDNEW
« no previous file with comments | « cc/surfaces/display_scheduler.cc ('k') | cc/surfaces/display_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698