| 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 late while swap throttled. |  | 
| 242   late_deadline = now_src().Now() + BeginFrameArgs::DefaultInterval(); |  | 
| 243   BeginFrameForTest(); |  | 
| 244   scheduler_->SurfaceDamaged(sid1); |  | 
| 245   EXPECT_EQ(late_deadline, 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 when 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(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |  | 
| 257   scheduler_->DidSwapBuffersComplete(); |  | 
| 258   EXPECT_GT(late_deadline, scheduler_->DesiredBeginFrameDeadlineTimeForTest()); |  | 
| 259 |  | 
| 260   // Draw and swap in deadline now that we aren't swap throttled. |  | 
| 261   EXPECT_EQ(1, client_->draw_and_swap_count()); |  | 
| 262   scheduler_->BeginFrameDeadlineForTest(); |  | 
| 263   EXPECT_EQ(2, client_->draw_and_swap_count()); |  | 
| 264 } |  | 
| 265 |  | 
| 266 // This test verfies that we try to reschedule the deadline |  | 
| 267 // after any event that may change what deadline we want. |  | 
| 268 TEST_F(DisplaySchedulerTest, ScheduleBeginFrameDeadline) { |  | 
| 269   SurfaceId sid1(1); |  | 
| 270   int count = 1; |  | 
| 271   EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |  | 
| 272 |  | 
| 273   BeginFrameForTest(); |  | 
| 274   EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |  | 
| 275 |  | 
| 276   scheduler_->BeginFrameDeadlineForTest(); |  | 
| 277   scheduler_->DidSwapBuffers(); |  | 
| 278   BeginFrameForTest(); |  | 
| 279   EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |  | 
| 280 |  | 
| 281   scheduler_->DidSwapBuffersComplete(); |  | 
| 282   EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |  | 
| 283 |  | 
| 284   scheduler_->EntireDisplayDamaged(); |  | 
| 285   EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |  | 
| 286 |  | 
| 287   scheduler_->SurfaceDamaged(sid1); |  | 
| 288   EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |  | 
| 289 |  | 
| 290   scheduler_->SetResourcesLockedByBrowser(true); |  | 
| 291   EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |  | 
| 292 |  | 
| 293   scheduler_->OutputSurfaceLost(); |  | 
| 294   EXPECT_EQ(count++, scheduler_->scheduler_begin_frame_deadline_count()); |  | 
| 295 } |  | 
| 296 |  | 
| 297 }  // namespace |  | 
| 298 }  // namespace cc |  | 
| OLD | NEW | 
|---|