OLD | NEW |
---|---|
(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.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/message_loop/message_loop_proxy.h" | |
9 #include "cc/output/begin_frame_args.h" | |
10 #include "content/renderer/scheduler/renderer_scheduler_selector.h" | |
11 #include "ui/gfx/frame_time.h" | |
12 | |
13 namespace content { | |
14 | |
15 RendererScheduler::RendererScheduler() | |
16 : renderer_scheduler_selector_(new RendererSchedulerSelector()), | |
17 task_queue_manager_(kTaskQueueCount, | |
18 base::MessageLoopProxy::current(), | |
19 renderer_scheduler_selector_.get()), | |
20 control_task_runner_( | |
21 task_queue_manager_.TaskRunnerForQueue(kControlTaskQueue)) { | |
22 renderer_scheduler_selector_->SetQueuePriority( | |
23 kControlTaskQueue, RendererSchedulerSelector::kControlPriority); | |
24 renderer_scheduler_selector_->DisableQueue(kIdleTaskQueue); | |
25 task_queue_manager_.SetAutoPump(kIdleTaskQueue, false); | |
26 } | |
27 | |
28 RendererScheduler::~RendererScheduler() { | |
29 } | |
30 | |
31 scoped_refptr<base::SingleThreadTaskRunner> | |
32 RendererScheduler::DefaultTaskRunner() { | |
33 return task_queue_manager_.TaskRunnerForQueue(kDefaultTaskQueue); | |
34 } | |
35 | |
36 scoped_refptr<base::SingleThreadTaskRunner> | |
37 RendererScheduler::CompositorTaskRunner() { | |
38 return task_queue_manager_.TaskRunnerForQueue(kCompositorTaskQueue); | |
39 } | |
40 | |
41 scoped_refptr<base::SingleThreadTaskRunner> | |
42 RendererScheduler::IdleTaskRunner() { | |
43 return task_queue_manager_.TaskRunnerForQueue(kIdleTaskQueue); | |
44 } | |
45 | |
46 void RendererScheduler::WillBeginFrame(const cc::BeginFrameArgs& args) { | |
47 main_thread_checker_.CalledOnValidThread(); | |
48 EndIdlePeriod(); | |
49 estimated_next_frame_begin_ = args.frame_time + args.interval; | |
50 } | |
51 | |
52 void RendererScheduler::DidCommitFrameToCompositor() { | |
53 main_thread_checker_.CalledOnValidThread(); | |
54 if (gfx::FrameTime::Now() < estimated_next_frame_begin_) { | |
55 StartIdlePeriod(); | |
56 } | |
57 } | |
58 | |
59 void RendererScheduler::DidReceiveInputEvent() { | |
60 base::AutoLock lock(incoming_signals_lock_); | |
61 if (last_input_time_.is_null()) { | |
62 // Update scheduler policy if should start a new compositor policy mode. | |
63 base::subtle::NoBarrier_Store(&policy_may_need_update_, 1); | |
64 control_task_runner_->PostTask( | |
65 FROM_HERE, | |
66 base::Bind(&RendererScheduler::UpdatePolicy, base::Unretained(this))); | |
67 } | |
68 last_input_time_ = base::TimeTicks::Now(); | |
69 } | |
70 | |
71 bool RendererScheduler::ShouldYieldForHighPriorityWork() { | |
72 main_thread_checker_.CalledOnValidThread(); | |
73 return SchedulerPolicy() == kCompositorPriorityPolicy && | |
74 task_queue_manager_.PollQueue(kCompositorTaskQueue); | |
alexclarke
2014/10/22 15:59:42
I think this should be:
!task_queue_manag
rmcilroy
2014/10/23 14:54:49
Hadn't synced Sami's new changes yet - done now.
| |
75 } | |
76 | |
77 base::TimeTicks RendererScheduler::CurrentFrameDeadlineForIdleTasks() const { | |
78 main_thread_checker_.CalledOnValidThread(); | |
79 return estimated_next_frame_begin_; | |
80 } | |
81 | |
82 RendererScheduler::Policy RendererScheduler::SchedulerPolicy() { | |
83 main_thread_checker_.CalledOnValidThread(); | |
84 if (base::subtle::NoBarrier_Load(&policy_may_need_update_)) { | |
85 UpdatePolicy(); | |
86 } | |
87 return current_policy_; | |
88 } | |
89 | |
90 void RendererScheduler::UpdatePolicy() { | |
91 main_thread_checker_.CalledOnValidThread(); | |
92 base::AutoLock lock(incoming_signals_lock_); | |
93 | |
94 Policy new_policy = kNormalPriorityPolicy; | |
95 if (!last_input_time_.is_null()) { | |
96 base::TimeDelta compositor_priority_time = | |
97 base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis); | |
98 base::TimeDelta remaining_compositor_priority_time = | |
99 base::TimeTicks::Now() - (last_input_time_ + compositor_priority_time); | |
100 if (remaining_compositor_priority_time > base::TimeDelta()) { | |
101 new_policy = kCompositorPriorityPolicy; | |
102 control_task_runner_->PostDelayedTask( | |
103 FROM_HERE, | |
104 base::Bind(&RendererScheduler::UpdatePolicy, base::Unretained(this)), | |
105 remaining_compositor_priority_time); | |
106 } else { | |
107 // Null out last_input_time_ to ensure DidReceiveInputEvent will post an | |
108 // UpdatePolicy task when it's next called. | |
109 last_input_time_ = base::TimeTicks(); | |
110 } | |
111 } | |
112 | |
113 if (new_policy != current_policy_) { | |
114 return; | |
alexclarke
2014/10/22 10:06:37
Shouldn't we clear the dirty flag here too?
rmcilroy
2014/10/23 14:54:49
Yes good point - moved this to the top of the func
| |
115 } | |
116 | |
117 switch (new_policy) { | |
118 case kCompositorPriorityPolicy: | |
119 renderer_scheduler_selector_->SetQueuePriority( | |
120 kCompositorTaskQueue, RendererSchedulerSelector::kHighPriority); | |
121 break; | |
122 case kNormalPriorityPolicy: | |
123 renderer_scheduler_selector_->SetQueuePriority( | |
124 kCompositorTaskQueue, RendererSchedulerSelector::kNormalPriority); | |
125 break; | |
126 } | |
127 current_policy_ = new_policy; | |
128 base::subtle::NoBarrier_Store(&policy_may_need_update_, 0); | |
Sami
2014/10/22 14:49:24
Thinking out loud: these can be barrier-less safel
rmcilroy
2014/10/23 14:54:49
Yes, they aren't guarding anything, and actually w
| |
129 } | |
130 | |
131 void RendererScheduler::StartIdlePeriod() { | |
132 renderer_scheduler_selector_->EnableQueue( | |
133 kIdleTaskQueue, RendererSchedulerSelector::kBestEffortPriority); | |
134 task_queue_manager_.PumpQueue(kIdleTaskQueue); | |
135 } | |
136 | |
137 void RendererScheduler::EndIdlePeriod() { | |
138 renderer_scheduler_selector_->DisableQueue(kIdleTaskQueue); | |
139 } | |
140 | |
141 } // namespace content | |
OLD | NEW |