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.
5 #include "cc/scheduler/frame_rate_controller.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"
18 class FrameRateControllerTimeSourceAdapter
: public TimeSourceClient
{
20 static scoped_ptr
<FrameRateControllerTimeSourceAdapter
> Create(
21 FrameRateController
* frame_rate_controller
) {
22 return make_scoped_ptr(
23 new FrameRateControllerTimeSourceAdapter(frame_rate_controller
));
25 virtual ~FrameRateControllerTimeSourceAdapter() {}
27 virtual void OnTimerTick() OVERRIDE
{
28 frame_rate_controller_
->OnTimerTick();
32 explicit FrameRateControllerTimeSourceAdapter(
33 FrameRateController
* frame_rate_controller
)
34 : frame_rate_controller_(frame_rate_controller
) {}
36 FrameRateController
* frame_rate_controller_
;
39 FrameRateController::FrameRateController(scoped_refptr
<TimeSource
> timer
)
41 num_frames_pending_(0),
42 max_swaps_pending_(0),
43 interval_(BeginFrameArgs::DefaultInterval()),
46 is_time_source_throttling_(true),
49 time_source_client_adapter_
=
50 FrameRateControllerTimeSourceAdapter::Create(this);
51 time_source_
->SetClient(time_source_client_adapter_
.get());
54 FrameRateController::FrameRateController(
55 base::SingleThreadTaskRunner
* task_runner
)
57 num_frames_pending_(0),
58 max_swaps_pending_(0),
59 interval_(BeginFrameArgs::DefaultInterval()),
61 is_time_source_throttling_(false),
62 task_runner_(task_runner
),
63 weak_factory_(this) {}
65 FrameRateController::~FrameRateController() {
66 if (is_time_source_throttling_
)
67 time_source_
->SetActive(false);
70 BeginFrameArgs
FrameRateController::SetActive(bool active
) {
71 if (active_
== active
)
72 return BeginFrameArgs();
73 TRACE_EVENT1("cc", "FrameRateController::SetActive", "active", active
);
76 if (is_time_source_throttling_
) {
77 base::TimeTicks missed_tick_time
= time_source_
->SetActive(active
);
78 if (!missed_tick_time
.is_null()) {
79 base::TimeTicks deadline
= NextTickTime();
80 return BeginFrameArgs::Create(
81 missed_tick_time
, deadline
+ deadline_adjustment_
, interval_
);
87 weak_factory_
.InvalidateWeakPtrs();
90 return BeginFrameArgs();
93 void FrameRateController::SetMaxSwapsPending(int max_swaps_pending
) {
94 DCHECK_GE(max_swaps_pending
, 0);
95 max_swaps_pending_
= max_swaps_pending
;
98 void FrameRateController::SetTimebaseAndInterval(base::TimeTicks timebase
,
99 base::TimeDelta interval
) {
100 interval_
= interval
;
101 if (is_time_source_throttling_
)
102 time_source_
->SetTimebaseAndInterval(timebase
, interval
);
105 void FrameRateController::SetDeadlineAdjustment(base::TimeDelta delta
) {
106 deadline_adjustment_
= delta
;
109 void FrameRateController::OnTimerTick() {
110 TRACE_EVENT0("cc", "FrameRateController::OnTimerTick");
113 // Check if we have too many frames in flight.
115 max_swaps_pending_
&& num_frames_pending_
>= max_swaps_pending_
;
116 TRACE_COUNTER_ID1("cc", "ThrottledCompositor", task_runner_
, throttled
);
119 // TODO(brianderson): Use an adaptive parent compositor deadline.
120 base::TimeTicks frame_time
= LastTickTime();
121 base::TimeTicks deadline
= NextTickTime();
122 BeginFrameArgs args
= BeginFrameArgs::Create(
123 frame_time
, deadline
+ deadline_adjustment_
, interval_
);
124 client_
->FrameRateControllerTick(throttled
, args
);
127 if (!is_time_source_throttling_
&& !throttled
)
131 void FrameRateController::PostManualTick() {
133 task_runner_
->PostTask(FROM_HERE
,
134 base::Bind(&FrameRateController::ManualTick
,
135 weak_factory_
.GetWeakPtr()));
139 void FrameRateController::ManualTick() {
143 void FrameRateController::DidSwapBuffers() {
144 num_frames_pending_
++;
147 void FrameRateController::DidSwapBuffersComplete() {
148 DCHECK_GT(num_frames_pending_
, 0);
149 num_frames_pending_
--;
150 if (!is_time_source_throttling_
)
154 void FrameRateController::DidAbortAllPendingFrames() {
155 num_frames_pending_
= 0;
158 base::TimeTicks
FrameRateController::NextTickTime() {
159 if (is_time_source_throttling_
)
160 return time_source_
->NextTickTime();
162 return base::TimeTicks();
165 base::TimeTicks
FrameRateController::LastTickTime() {
166 if (is_time_source_throttling_
)
167 return time_source_
->LastTickTime();
169 return gfx::FrameTime::Now();