Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / cc / scheduler / frame_rate_controller.cc
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/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/single_thread_task_runner.h"
12 #include "cc/scheduler/delay_based_time_source.h"
13 #include "cc/scheduler/time_source.h"
14 #include "ui/gfx/frame_time.h"
15
16 namespace cc {
17
18 class FrameRateControllerTimeSourceAdapter : public TimeSourceClient {
19  public:
20   static scoped_ptr<FrameRateControllerTimeSourceAdapter> Create(
21       FrameRateController* frame_rate_controller) {
22     return make_scoped_ptr(
23         new FrameRateControllerTimeSourceAdapter(frame_rate_controller));
24   }
25   virtual ~FrameRateControllerTimeSourceAdapter() {}
26
27   virtual void OnTimerTick() OVERRIDE {
28     frame_rate_controller_->OnTimerTick();
29   }
30
31  private:
32   explicit FrameRateControllerTimeSourceAdapter(
33       FrameRateController* frame_rate_controller)
34       : frame_rate_controller_(frame_rate_controller) {}
35
36   FrameRateController* frame_rate_controller_;
37 };
38
39 FrameRateController::FrameRateController(scoped_refptr<TimeSource> timer)
40     : client_(NULL),
41       num_frames_pending_(0),
42       max_swaps_pending_(0),
43       interval_(BeginFrameArgs::DefaultInterval()),
44       time_source_(timer),
45       active_(false),
46       is_time_source_throttling_(true),
47       manual_tick_pending_(false),
48       task_runner_(NULL),
49       weak_factory_(this) {
50   time_source_client_adapter_ =
51       FrameRateControllerTimeSourceAdapter::Create(this);
52   time_source_->SetClient(time_source_client_adapter_.get());
53 }
54
55 FrameRateController::FrameRateController(
56     base::SingleThreadTaskRunner* task_runner)
57     : client_(NULL),
58       num_frames_pending_(0),
59       max_swaps_pending_(0),
60       interval_(BeginFrameArgs::DefaultInterval()),
61       active_(false),
62       is_time_source_throttling_(false),
63       manual_tick_pending_(false),
64       task_runner_(task_runner),
65       weak_factory_(this) {}
66
67 FrameRateController::~FrameRateController() {
68   if (is_time_source_throttling_)
69     time_source_->SetActive(false);
70 }
71
72 BeginFrameArgs FrameRateController::SetActive(bool active) {
73   if (active_ == active)
74     return BeginFrameArgs();
75   TRACE_EVENT1("cc", "FrameRateController::SetActive", "active", active);
76   active_ = active;
77
78   if (is_time_source_throttling_) {
79     base::TimeTicks missed_tick_time = time_source_->SetActive(active);
80     if (!missed_tick_time.is_null()) {
81       base::TimeTicks deadline = NextTickTime();
82       return  BeginFrameArgs::Create(
83           missed_tick_time, deadline + deadline_adjustment_, interval_);
84     }
85   } else {
86     if (active) {
87       PostManualTick();
88     } else {
89       weak_factory_.InvalidateWeakPtrs();
90       manual_tick_pending_ = false;
91     }
92   }
93
94   return BeginFrameArgs();
95 }
96
97 void FrameRateController::SetMaxSwapsPending(int max_swaps_pending) {
98   DCHECK_GE(max_swaps_pending, 0);
99   max_swaps_pending_ = max_swaps_pending;
100 }
101
102 void FrameRateController::SetTimebaseAndInterval(base::TimeTicks timebase,
103                                                  base::TimeDelta interval) {
104   interval_ = interval;
105   if (is_time_source_throttling_)
106     time_source_->SetTimebaseAndInterval(timebase, interval);
107 }
108
109 void FrameRateController::SetDeadlineAdjustment(base::TimeDelta delta) {
110   deadline_adjustment_ = delta;
111 }
112
113 void FrameRateController::OnTimerTick() {
114   TRACE_EVENT0("cc", "FrameRateController::OnTimerTick");
115   DCHECK(active_);
116
117   // Check if we have too many frames in flight.
118   bool throttled =
119       max_swaps_pending_ && num_frames_pending_ >= max_swaps_pending_;
120   TRACE_COUNTER_ID1("cc", "ThrottledCompositor", task_runner_, throttled);
121
122   if (client_) {
123     // TODO(brianderson): Use an adaptive parent compositor deadline.
124     base::TimeTicks frame_time = LastTickTime();
125     base::TimeTicks deadline = NextTickTime();
126     BeginFrameArgs args = BeginFrameArgs::Create(
127         frame_time, deadline + deadline_adjustment_, interval_);
128     client_->FrameRateControllerTick(throttled, args);
129   }
130
131   if (!is_time_source_throttling_ && !throttled)
132     PostManualTick();
133 }
134
135 void FrameRateController::PostManualTick() {
136   if (active_ && !manual_tick_pending_) {
137     manual_tick_pending_ = true;
138     task_runner_->PostTask(FROM_HERE,
139                            base::Bind(&FrameRateController::ManualTick,
140                                       weak_factory_.GetWeakPtr()));
141   }
142 }
143
144 void FrameRateController::ManualTick() {
145   manual_tick_pending_ = false;
146   OnTimerTick();
147 }
148
149 void FrameRateController::DidSwapBuffers() {
150   num_frames_pending_++;
151 }
152
153 void FrameRateController::DidSwapBuffersComplete() {
154   DCHECK_GT(num_frames_pending_, 0);
155   num_frames_pending_--;
156   if (!is_time_source_throttling_)
157     PostManualTick();
158 }
159
160 void FrameRateController::DidAbortAllPendingFrames() {
161   num_frames_pending_ = 0;
162 }
163
164 base::TimeTicks FrameRateController::NextTickTime() {
165   if (is_time_source_throttling_)
166     return time_source_->NextTickTime();
167
168   return base::TimeTicks();
169 }
170
171 base::TimeTicks FrameRateController::LastTickTime() {
172   if (is_time_source_throttling_)
173     return time_source_->LastTickTime();
174
175   return gfx::FrameTime::Now();
176 }
177
178 }  // namespace cc