Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: content/renderer/scheduler/renderer_scheduler_impl.cc

Issue 664963002: content: Add RendererScheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update comments Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 "content/renderer/scheduler/renderer_scheduler_impl.h"
6
7 #include "base/bind.h"
8 #include "cc/output/begin_frame_args.h"
9 #include "content/renderer/scheduler/renderer_task_queue_selector.h"
10 #include "ui/gfx/frame_time.h"
11
12 namespace content {
13
14 RendererSchedulerImpl::RendererSchedulerImpl(
15 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
16 : renderer_task_queue_selector_(new RendererTaskQueueSelector()),
17 task_queue_manager_(
18 new TaskQueueManager(TASK_QUEUE_COUNT,
19 main_task_runner,
20 renderer_task_queue_selector_.get())),
21 control_task_runner_(
22 task_queue_manager_->TaskRunnerForQueue(CONTROL_TASK_QUEUE)),
23 default_task_runner_(
24 task_queue_manager_->TaskRunnerForQueue(DEFAULT_TASK_QUEUE)),
25 compositor_task_runner_(
26 task_queue_manager_->TaskRunnerForQueue(COMPOSITOR_TASK_QUEUE)),
27 current_policy_(NORMAL_PRIORITY_POLICY),
28 policy_may_need_update_(&incoming_signals_lock_),
29 weak_factory_(this) {
30 weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr();
31 update_policy_closure_ = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
32 weak_renderer_scheduler_ptr_);
33 end_idle_period_closure_ = base::Bind(&RendererSchedulerImpl::EndIdlePeriod,
34 weak_renderer_scheduler_ptr_);
35 idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner(
36 task_queue_manager_->TaskRunnerForQueue(IDLE_TASK_QUEUE),
37 base::Bind(&RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback,
38 weak_renderer_scheduler_ptr_)));
39 renderer_task_queue_selector_->SetQueuePriority(
40 CONTROL_TASK_QUEUE, RendererTaskQueueSelector::CONTROL_PRIORITY);
41 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE);
42 task_queue_manager_->SetAutoPump(IDLE_TASK_QUEUE, false);
43 }
44
45 RendererSchedulerImpl::~RendererSchedulerImpl() {
46 }
47
48 void RendererSchedulerImpl::Shutdown() {
49 main_thread_checker_.CalledOnValidThread();
50 task_queue_manager_.reset();
51 }
52
53 scoped_refptr<base::SingleThreadTaskRunner>
54 RendererSchedulerImpl::DefaultTaskRunner() {
55 main_thread_checker_.CalledOnValidThread();
56 return default_task_runner_;
57 }
58
59 scoped_refptr<base::SingleThreadTaskRunner>
60 RendererSchedulerImpl::CompositorTaskRunner() {
61 main_thread_checker_.CalledOnValidThread();
62 return compositor_task_runner_;
63 }
64
65 scoped_refptr<SingleThreadIdleTaskRunner>
66 RendererSchedulerImpl::IdleTaskRunner() {
67 main_thread_checker_.CalledOnValidThread();
68 return idle_task_runner_;
69 }
70
71 void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) {
72 main_thread_checker_.CalledOnValidThread();
73 if (!task_queue_manager_)
74 return;
75
76 EndIdlePeriod();
77 estimated_next_frame_begin_ = args.frame_time + args.interval;
78 }
79
80 void RendererSchedulerImpl::DidCommitFrameToCompositor() {
81 main_thread_checker_.CalledOnValidThread();
82 if (!task_queue_manager_)
83 return;
84
85 base::TimeTicks now(Now());
86 if (now < estimated_next_frame_begin_) {
87 StartIdlePeriod();
88 control_task_runner_->PostDelayedTask(FROM_HERE, end_idle_period_closure_,
89 estimated_next_frame_begin_ - now);
90 }
91 }
92
93 void RendererSchedulerImpl::DidReceiveInputEventOnCompositorThread() {
94 // TODO(rmcilroy): Decide whether only a subset of input events should trigger
95 // compositor priority policy - http://crbug.com/429814.
96 base::AutoLock lock(incoming_signals_lock_);
97 if (last_input_time_.is_null()) {
98 // Update scheduler policy if should start a new compositor policy mode.
99 policy_may_need_update_.SetLocked(true);
100 PostUpdatePolicyOnControlRunner(base::TimeDelta());
101 }
102 last_input_time_ = Now();
103 }
104
105 bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
106 main_thread_checker_.CalledOnValidThread();
107 if (!task_queue_manager_)
108 return false;
109
110 MaybeUpdatePolicy();
111 // We only yield if we are in the compositor priority and there is compositor
112 // work outstanding. Note: even though the control queue is higher priority
113 // we don't yield for it since these tasks are not user-provided work and they
114 // are only intended to run before the next task, not interrupt the tasks.
115 return SchedulerPolicy() == COMPOSITOR_PRIORITY_POLICY &&
116 !task_queue_manager_->IsQueueEmpty(COMPOSITOR_TASK_QUEUE);
117 }
118
119 void RendererSchedulerImpl::CurrentIdleTaskDeadlineCallback(
120 base::TimeTicks* deadline_out) const {
121 main_thread_checker_.CalledOnValidThread();
122 *deadline_out = estimated_next_frame_begin_;
123 }
124
125 RendererSchedulerImpl::Policy RendererSchedulerImpl::SchedulerPolicy() const {
126 main_thread_checker_.CalledOnValidThread();
127 return current_policy_;
128 }
129
130 void RendererSchedulerImpl::MaybeUpdatePolicy() {
131 main_thread_checker_.CalledOnValidThread();
132 if (policy_may_need_update_.IsSet()) {
133 UpdatePolicy();
134 }
135 }
136
137 void RendererSchedulerImpl::PostUpdatePolicyOnControlRunner(
138 base::TimeDelta delay) {
139 control_task_runner_->PostDelayedTask(FROM_HERE, update_policy_closure_,
140 delay);
141 }
142
143 void RendererSchedulerImpl::UpdatePolicy() {
144 main_thread_checker_.CalledOnValidThread();
145 if (!task_queue_manager_)
146 return;
147
148 base::AutoLock lock(incoming_signals_lock_);
149 policy_may_need_update_.SetLocked(false);
150
151 Policy new_policy = NORMAL_PRIORITY_POLICY;
152 if (!last_input_time_.is_null()) {
153 base::TimeDelta compositor_priority_duration =
154 base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis);
155 base::TimeTicks compositor_priority_end(last_input_time_ +
156 compositor_priority_duration);
157 base::TimeTicks now(Now());
158 if (compositor_priority_end > now) {
159 PostUpdatePolicyOnControlRunner(compositor_priority_end - now);
160 new_policy = COMPOSITOR_PRIORITY_POLICY;
161 } else {
162 // Null out last_input_time_ to ensure
163 // DidReceiveInputEventOnCompositorThread will post an
164 // UpdatePolicy task when it's next called.
165 last_input_time_ = base::TimeTicks();
166 }
167 }
168
169 if (new_policy == current_policy_)
170 return;
171
172 switch (new_policy) {
173 case COMPOSITOR_PRIORITY_POLICY:
174 renderer_task_queue_selector_->SetQueuePriority(
175 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::HIGH_PRIORITY);
176 break;
177 case NORMAL_PRIORITY_POLICY:
178 renderer_task_queue_selector_->SetQueuePriority(
179 COMPOSITOR_TASK_QUEUE, RendererTaskQueueSelector::NORMAL_PRIORITY);
180 break;
181 }
182 current_policy_ = new_policy;
183 }
184
185 void RendererSchedulerImpl::StartIdlePeriod() {
186 main_thread_checker_.CalledOnValidThread();
187 renderer_task_queue_selector_->EnableQueue(
188 IDLE_TASK_QUEUE, RendererTaskQueueSelector::BEST_EFFORT_PRIORITY);
189 task_queue_manager_->PumpQueue(IDLE_TASK_QUEUE);
190 }
191
192 void RendererSchedulerImpl::EndIdlePeriod() {
193 main_thread_checker_.CalledOnValidThread();
194 renderer_task_queue_selector_->DisableQueue(IDLE_TASK_QUEUE);
195 }
196
197 base::TimeTicks RendererSchedulerImpl::Now() const {
198 return gfx::FrameTime::Now();
199 }
200
201 RendererSchedulerImpl::PollableNeedsUpdateFlag::PollableNeedsUpdateFlag(
202 base::Lock* write_lock_)
203 : flag_(false), write_lock_(write_lock_) {
204 }
205
206 RendererSchedulerImpl::PollableNeedsUpdateFlag::~PollableNeedsUpdateFlag() {
207 }
208
209 void RendererSchedulerImpl::PollableNeedsUpdateFlag::SetLocked(bool value) {
210 write_lock_->AssertAcquired();
211 base::subtle::Release_Store(&flag_, value);
212 }
213
214 bool RendererSchedulerImpl::PollableNeedsUpdateFlag::IsSet() const {
215 thread_checker_.CalledOnValidThread();
216 return base::subtle::Acquire_Load(&flag_) != 0;
217 }
218 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/scheduler/renderer_scheduler_impl.h ('k') | content/renderer/scheduler/renderer_scheduler_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698