Home | History | Annotate | Download | only in scheduler
      1 // Copyright 2011 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/scheduler/frame_rate_controller.h"
      6 
      7 #include "base/test/test_simple_task_runner.h"
      8 #include "cc/test/scheduler_test_common.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 
     11 namespace cc {
     12 namespace {
     13 
     14 class FakeFrameRateControllerClient : public FrameRateControllerClient {
     15  public:
     16   FakeFrameRateControllerClient() { Reset(); }
     17 
     18   void Reset() { frame_count_ = 0; }
     19   bool BeganFrame() const { return frame_count_ > 0; }
     20   int frame_count() const { return frame_count_; }
     21 
     22   virtual void FrameRateControllerTick(
     23       bool throttled, const BeginFrameArgs& args) OVERRIDE {
     24     frame_count_ += throttled ? 0 : 1;
     25   }
     26 
     27  protected:
     28   int frame_count_;
     29 };
     30 
     31 TEST(FrameRateControllerTest, TestFrameThrottling_ImmediateAck) {
     32   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
     33       new base::TestSimpleTaskRunner;
     34   FakeFrameRateControllerClient client;
     35   base::TimeDelta interval = base::TimeDelta::FromMicroseconds(
     36       base::Time::kMicrosecondsPerSecond / 60);
     37   scoped_refptr<FakeDelayBasedTimeSource> time_source =
     38       FakeDelayBasedTimeSource::Create(interval, task_runner.get());
     39   FrameRateController controller(time_source);
     40 
     41   controller.SetClient(&client);
     42   controller.SetActive(true);
     43 
     44   base::TimeTicks elapsed;  // Muck around with time a bit
     45 
     46   // Trigger one frame, make sure the BeginFrame callback is called
     47   elapsed += task_runner->NextPendingTaskDelay();
     48   time_source->SetNow(elapsed);
     49   task_runner->RunPendingTasks();
     50   EXPECT_TRUE(client.BeganFrame());
     51   client.Reset();
     52 
     53   // Tell the controller we drew
     54   controller.DidSwapBuffers();
     55 
     56   // Tell the controller the frame ended 5ms later
     57   time_source->SetNow(time_source->Now() +
     58                       base::TimeDelta::FromMilliseconds(5));
     59   controller.DidSwapBuffersComplete();
     60 
     61   // Trigger another frame, make sure BeginFrame runs again
     62   elapsed += task_runner->NextPendingTaskDelay();
     63   // Sanity check that previous code didn't move time backward.
     64   EXPECT_GE(elapsed, time_source->Now());
     65   time_source->SetNow(elapsed);
     66   task_runner->RunPendingTasks();
     67   EXPECT_TRUE(client.BeganFrame());
     68 }
     69 
     70 TEST(FrameRateControllerTest, TestFrameThrottling_TwoFramesInFlight) {
     71   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
     72       new base::TestSimpleTaskRunner;
     73   FakeFrameRateControllerClient client;
     74   base::TimeDelta interval = base::TimeDelta::FromMicroseconds(
     75       base::Time::kMicrosecondsPerSecond / 60);
     76   scoped_refptr<FakeDelayBasedTimeSource> time_source =
     77       FakeDelayBasedTimeSource::Create(interval, task_runner.get());
     78   FrameRateController controller(time_source);
     79 
     80   controller.SetClient(&client);
     81   controller.SetActive(true);
     82   controller.SetMaxSwapsPending(2);
     83 
     84   base::TimeTicks elapsed;  // Muck around with time a bit
     85 
     86   // Trigger one frame, make sure the BeginFrame callback is called
     87   elapsed += task_runner->NextPendingTaskDelay();
     88   time_source->SetNow(elapsed);
     89   task_runner->RunPendingTasks();
     90   EXPECT_TRUE(client.BeganFrame());
     91   client.Reset();
     92 
     93   // Tell the controller we drew
     94   controller.DidSwapBuffers();
     95 
     96   // Trigger another frame, make sure BeginFrame callback runs again
     97   elapsed += task_runner->NextPendingTaskDelay();
     98   // Sanity check that previous code didn't move time backward.
     99   EXPECT_GE(elapsed, time_source->Now());
    100   time_source->SetNow(elapsed);
    101   task_runner->RunPendingTasks();
    102   EXPECT_TRUE(client.BeganFrame());
    103   client.Reset();
    104 
    105   // Tell the controller we drew, again.
    106   controller.DidSwapBuffers();
    107 
    108   // Trigger another frame. Since two frames are pending, we should not draw.
    109   elapsed += task_runner->NextPendingTaskDelay();
    110   // Sanity check that previous code didn't move time backward.
    111   EXPECT_GE(elapsed, time_source->Now());
    112   time_source->SetNow(elapsed);
    113   task_runner->RunPendingTasks();
    114   EXPECT_FALSE(client.BeganFrame());
    115 
    116   // Tell the controller the first frame ended 5ms later
    117   time_source->SetNow(time_source->Now() +
    118                       base::TimeDelta::FromMilliseconds(5));
    119   controller.DidSwapBuffersComplete();
    120 
    121   // Tick should not have been called
    122   EXPECT_FALSE(client.BeganFrame());
    123 
    124   // Trigger yet another frame. Since one frames is pending, another
    125   // BeginFrame callback should run.
    126   elapsed += task_runner->NextPendingTaskDelay();
    127   // Sanity check that previous code didn't move time backward.
    128   EXPECT_GE(elapsed, time_source->Now());
    129   time_source->SetNow(elapsed);
    130   task_runner->RunPendingTasks();
    131   EXPECT_TRUE(client.BeganFrame());
    132 }
    133 
    134 TEST(FrameRateControllerTest, TestFrameThrottling_Unthrottled) {
    135   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
    136       new base::TestSimpleTaskRunner;
    137   FakeFrameRateControllerClient client;
    138   FrameRateController controller(task_runner.get());
    139 
    140   controller.SetClient(&client);
    141   controller.SetMaxSwapsPending(2);
    142 
    143   // SetActive triggers 1st frame, make sure the BeginFrame callback
    144   // is called
    145   controller.SetActive(true);
    146   task_runner->RunPendingTasks();
    147   EXPECT_TRUE(client.BeganFrame());
    148   client.Reset();
    149 
    150   // Even if we don't call DidSwapBuffers, FrameRateController should
    151   // still attempt to tick multiple times until it does result in
    152   // a DidSwapBuffers.
    153   task_runner->RunPendingTasks();
    154   EXPECT_TRUE(client.BeganFrame());
    155   client.Reset();
    156 
    157   task_runner->RunPendingTasks();
    158   EXPECT_TRUE(client.BeganFrame());
    159   client.Reset();
    160 
    161   // DidSwapBuffers triggers 2nd frame, make sure the BeginFrame callback is
    162   // called
    163   controller.DidSwapBuffers();
    164   task_runner->RunPendingTasks();
    165   EXPECT_TRUE(client.BeganFrame());
    166   client.Reset();
    167 
    168   // DidSwapBuffers triggers 3rd frame (> max_frames_pending),
    169   // make sure the BeginFrame callback is NOT called
    170   controller.DidSwapBuffers();
    171   task_runner->RunPendingTasks();
    172   EXPECT_FALSE(client.BeganFrame());
    173   client.Reset();
    174 
    175   // Make sure there is no pending task since we can't do anything until we
    176   // receive a DidSwapBuffersComplete anyway.
    177   EXPECT_FALSE(task_runner->HasPendingTask());
    178 
    179   // DidSwapBuffersComplete triggers a frame, make sure the BeginFrame
    180   // callback is called
    181   controller.DidSwapBuffersComplete();
    182   task_runner->RunPendingTasks();
    183   EXPECT_TRUE(client.BeganFrame());
    184 }
    185 
    186 TEST(FrameRateControllerTest, TestFrameThrottling_NoDoubleTicking) {
    187   scoped_refptr<base::TestSimpleTaskRunner> task_runner =
    188       new base::TestSimpleTaskRunner;
    189   FakeFrameRateControllerClient client;
    190   FrameRateController controller(task_runner.get());
    191   controller.SetClient(&client);
    192 
    193   // SetActive triggers 1st frame and queues another tick task since the time
    194   // source isn't throttling.
    195   controller.SetActive(true);
    196   task_runner->RunPendingTasks();
    197   EXPECT_TRUE(client.BeganFrame());
    198   client.Reset();
    199   EXPECT_TRUE(task_runner->HasPendingTask());
    200 
    201   // Simulate a frame swap. This shouldn't queue a second tick task.
    202   controller.DidSwapBuffers();
    203   controller.DidSwapBuffersComplete();
    204 
    205   // The client should only be ticked once.
    206   task_runner->RunPendingTasks();
    207   EXPECT_EQ(1, client.frame_count());
    208 }
    209 
    210 }  // namespace
    211 }  // namespace cc
    212