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