OLD | NEW |
(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_->SetResourcesLockedByBrowser(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 BeginFrameForTest(); |
| 110 EXPECT_LT(now_src().Now(), |
| 111 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 112 scheduler_->EntireDisplayDamaged(); |
| 113 EXPECT_GE(now_src().Now(), |
| 114 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 115 } |
| 116 |
| 117 TEST_F(DisplaySchedulerTest, SurfaceDamaged) { |
| 118 SurfaceId sid1(1); |
| 119 SurfaceId sid2(2); |
| 120 |
| 121 // Get scheduler to detect surface 1 as active by drawing |
| 122 // two frames in a row with damage from surface 1. |
| 123 BeginFrameForTest(); |
| 124 scheduler_->SurfaceDamaged(sid1); |
| 125 scheduler_->BeginFrameDeadlineForTest(); |
| 126 BeginFrameForTest(); |
| 127 scheduler_->SurfaceDamaged(sid1); |
| 128 scheduler_->BeginFrameDeadlineForTest(); |
| 129 |
| 130 // Damage only from surface 2 (inactive) does not trigger deadline early. |
| 131 BeginFrameForTest(); |
| 132 scheduler_->SurfaceDamaged(sid2); |
| 133 EXPECT_LT(now_src().Now(), |
| 134 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 135 |
| 136 // Damage from surface 1 triggers deadline early. |
| 137 scheduler_->SurfaceDamaged(sid1); |
| 138 EXPECT_GE(now_src().Now(), |
| 139 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 140 scheduler_->BeginFrameDeadlineForTest(); |
| 141 |
| 142 // Make both surface 1 and 2 active. |
| 143 BeginFrameForTest(); |
| 144 scheduler_->SurfaceDamaged(sid2); |
| 145 scheduler_->SurfaceDamaged(sid1); |
| 146 scheduler_->BeginFrameDeadlineForTest(); |
| 147 |
| 148 // Deadline doesn't trigger early until surface 1 and 2 are both damaged. |
| 149 BeginFrameForTest(); |
| 150 EXPECT_LT(now_src().Now(), |
| 151 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 152 scheduler_->SurfaceDamaged(sid1); |
| 153 EXPECT_LT(now_src().Now(), |
| 154 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 155 scheduler_->SurfaceDamaged(sid2); |
| 156 EXPECT_GE(now_src().Now(), |
| 157 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 158 scheduler_->BeginFrameDeadlineForTest(); |
| 159 } |
| 160 |
| 161 TEST_F(DisplaySchedulerTest, OutputSurfaceLost) { |
| 162 SurfaceId sid1(1); |
| 163 |
| 164 // DrawAndSwap normally. |
| 165 BeginFrameForTest(); |
| 166 EXPECT_LT(now_src().Now(), |
| 167 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 168 EXPECT_EQ(0, client_->draw_and_swap_count()); |
| 169 scheduler_->SurfaceDamaged(sid1); |
| 170 scheduler_->BeginFrameDeadlineForTest(); |
| 171 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 172 |
| 173 // Deadline triggers immediately on OutputSurfaceLost. |
| 174 BeginFrameForTest(); |
| 175 EXPECT_LT(now_src().Now(), |
| 176 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 177 scheduler_->OutputSurfaceLost(); |
| 178 EXPECT_GE(now_src().Now(), |
| 179 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 180 |
| 181 // Deadline does not DrawAndSwap after OutputSurfaceLost. |
| 182 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 183 scheduler_->SurfaceDamaged(sid1); |
| 184 scheduler_->BeginFrameDeadlineForTest(); |
| 185 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 186 } |
| 187 |
| 188 TEST_F(DisplaySchedulerTest, ResourcesLockedByBrowser) { |
| 189 SurfaceId sid1(1); |
| 190 base::TimeTicks late_deadline; |
| 191 |
| 192 // DrawAndSwap normally. |
| 193 BeginFrameForTest(); |
| 194 EXPECT_LT(now_src().Now(), |
| 195 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 196 EXPECT_EQ(0, client_->draw_and_swap_count()); |
| 197 scheduler_->SurfaceDamaged(sid1); |
| 198 scheduler_->BeginFrameDeadlineForTest(); |
| 199 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 200 |
| 201 // Deadline triggers late while ResourcesLockedByBrowser. |
| 202 late_deadline = now_src().Now() + BeginFrameArgs::DefaultInterval(); |
| 203 BeginFrameForTest(); |
| 204 scheduler_->SurfaceDamaged(sid1); |
| 205 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 206 scheduler_->SetResourcesLockedByBrowser(true); |
| 207 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 208 |
| 209 // Deadline does not DrawAndSwap while ResourcesLockedByBrowser. |
| 210 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 211 scheduler_->SurfaceDamaged(sid1); |
| 212 scheduler_->BeginFrameDeadlineForTest(); |
| 213 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 214 |
| 215 // Deadline triggers normally when ResourcesLockedByBrowser goes false. |
| 216 late_deadline = now_src().Now() + BeginFrameArgs::DefaultInterval(); |
| 217 BeginFrameForTest(); |
| 218 scheduler_->SurfaceDamaged(sid1); |
| 219 EXPECT_EQ(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 220 scheduler_->SetResourcesLockedByBrowser(false); |
| 221 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 222 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 223 scheduler_->BeginFrameDeadlineForTest(); |
| 224 EXPECT_EQ(2, client_->draw_and_swap_count()); |
| 225 } |
| 226 |
| 227 TEST_F(DisplaySchedulerTest, DidSwapBuffers) { |
| 228 SurfaceId sid1(1); |
| 229 base::TimeTicks late_deadline; |
| 230 |
| 231 // DrawAndSwap normally. |
| 232 BeginFrameForTest(); |
| 233 EXPECT_LT(now_src().Now(), |
| 234 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 235 EXPECT_EQ(0, client_->draw_and_swap_count()); |
| 236 scheduler_->SurfaceDamaged(sid1); |
| 237 scheduler_->BeginFrameDeadlineForTest(); |
| 238 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 239 scheduler_->DidSwapBuffers(); |
| 240 |
| 241 // Deadline triggers immediately while swap throttled. |
| 242 BeginFrameForTest(); |
| 243 scheduler_->SurfaceDamaged(sid1); |
| 244 EXPECT_EQ(base::TimeTicks(), |
| 245 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 246 |
| 247 // Don't draw and swap in deadline while swap throttled. |
| 248 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 249 scheduler_->BeginFrameDeadlineForTest(); |
| 250 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 251 |
| 252 // Then triggers normally once not swap throttled. |
| 253 // Damage from previous BeginFrame should cary over, so don't damage again. |
| 254 late_deadline = now_src().Now() + BeginFrameArgs::DefaultInterval(); |
| 255 BeginFrameForTest(); |
| 256 EXPECT_EQ(base::TimeTicks(), |
| 257 scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 258 scheduler_->DidSwapBuffersComplete(); |
| 259 EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |
| 260 |
| 261 // Draw and swap in deadline now that we aren't swap throttled. |
| 262 EXPECT_EQ(1, client_->draw_and_swap_count()); |
| 263 scheduler_->BeginFrameDeadlineForTest(); |
| 264 EXPECT_EQ(2, client_->draw_and_swap_count()); |
| 265 } |
| 266 |
| 267 // This test verfies that we try to reschedule the deadline |
| 268 // after any event that may change what deadline we want. |
| 269 TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) { |
| 270 SurfaceId sid1(1); |
| 271 int count = 1; |
| 272 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |
| 273 |
| 274 BeginFrameForTest(); |
| 275 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |
| 276 |
| 277 scheduler_->BeginFrameDeadlineForTest(); |
| 278 scheduler_->DidSwapBuffers(); |
| 279 BeginFrameForTest(); |
| 280 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |
| 281 |
| 282 scheduler_->DidSwapBuffersComplete(); |
| 283 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |
| 284 |
| 285 scheduler_->EntireDisplayDamaged(); |
| 286 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |
| 287 |
| 288 scheduler_->SurfaceDamaged(sid1); |
| 289 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |
| 290 |
| 291 scheduler_->SetResourcesLockedByBrowser(true); |
| 292 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |
| 293 |
| 294 scheduler_->OutputSurfaceLost(); |
| 295 EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |
| 296 } |
| 297 |
| 298 } // namespace |
| 299 } // namespace cc |
OLD | NEW |