| Index: content/renderer/scheduler/renderer_scheduler_impl.cc
|
| diff --git a/content/renderer/scheduler/renderer_scheduler_impl.cc b/content/renderer/scheduler/renderer_scheduler_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..43371178f17ee41cfacf042d0cb09e9adb8cbf95
|
| --- /dev/null
|
| +++ b/content/renderer/scheduler/renderer_scheduler_impl.cc
|
| @@ -0,0 +1,186 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/renderer/scheduler/renderer_scheduler_impl.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| +#include "cc/output/begin_frame_args.h"
|
| +#include "content/renderer/scheduler/renderer_scheduler_selector.h"
|
| +#include "ui/gfx/frame_time.h"
|
| +
|
| +namespace content {
|
| +
|
| +RendererSchedulerImpl::RendererSchedulerImpl()
|
| + : RendererSchedulerImpl(base::MessageLoopProxy::current()) {
|
| +}
|
| +
|
| +RendererSchedulerImpl::RendererSchedulerImpl(
|
| + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
|
| + : renderer_scheduler_selector_(new RendererSchedulerSelector()),
|
| + task_queue_manager_(
|
| + new TaskQueueManager(kTaskQueueCount,
|
| + main_task_runner,
|
| + renderer_scheduler_selector_.get())),
|
| + control_task_runner_(
|
| + task_queue_manager_->TaskRunnerForQueue(kControlTaskQueue)),
|
| + default_task_runner_(
|
| + task_queue_manager_->TaskRunnerForQueue(kDefaultTaskQueue)),
|
| + compositor_task_runner_(
|
| + task_queue_manager_->TaskRunnerForQueue(kCompositorTaskQueue)),
|
| + current_policy_(kNormalPriorityPolicy),
|
| + policy_may_need_update_(0),
|
| + weak_factory_(this) {
|
| + weak_renderer_scheduler_ptr_ = weak_factory_.GetWeakPtr();
|
| + idle_task_runner_ = make_scoped_refptr(new SingleThreadIdleTaskRunner(
|
| + task_queue_manager_->TaskRunnerForQueue(kIdleTaskQueue),
|
| + weak_factory_.GetWeakPtr()));
|
| + renderer_scheduler_selector_->SetQueuePriority(
|
| + kControlTaskQueue, RendererSchedulerSelector::kControlPriority);
|
| + renderer_scheduler_selector_->DisableQueue(kIdleTaskQueue);
|
| + task_queue_manager_->SetAutoPump(kIdleTaskQueue, false);
|
| +}
|
| +
|
| +RendererSchedulerImpl::~RendererSchedulerImpl() {
|
| +}
|
| +
|
| +void RendererSchedulerImpl::Shutdown() {
|
| + task_queue_manager_.reset();
|
| +}
|
| +
|
| +scoped_refptr<base::SingleThreadTaskRunner>
|
| +RendererSchedulerImpl::DefaultTaskRunner() {
|
| + return default_task_runner_;
|
| +}
|
| +
|
| +scoped_refptr<base::SingleThreadTaskRunner>
|
| +RendererSchedulerImpl::CompositorTaskRunner() {
|
| + return compositor_task_runner_;
|
| +}
|
| +
|
| +scoped_refptr<SingleThreadIdleTaskRunner>
|
| +RendererSchedulerImpl::IdleTaskRunner() {
|
| + return idle_task_runner_;
|
| +}
|
| +
|
| +void RendererSchedulerImpl::WillBeginFrame(const cc::BeginFrameArgs& args) {
|
| + main_thread_checker_.CalledOnValidThread();
|
| + if (!task_queue_manager_)
|
| + return;
|
| +
|
| + EndIdlePeriod();
|
| + estimated_next_frame_begin_ = args.frame_time + args.interval;
|
| +}
|
| +
|
| +void RendererSchedulerImpl::DidCommitFrameToCompositor() {
|
| + main_thread_checker_.CalledOnValidThread();
|
| + if (!task_queue_manager_)
|
| + return;
|
| +
|
| + if (Now() < estimated_next_frame_begin_) {
|
| + StartIdlePeriod();
|
| + }
|
| +}
|
| +
|
| +void RendererSchedulerImpl::DidReceiveInputEvent() {
|
| + if (!task_queue_manager_)
|
| + return;
|
| + base::AutoLock lock(incoming_signals_lock_);
|
| + if (last_input_time_.is_null()) {
|
| + // Update scheduler policy if should start a new compositor policy mode.
|
| + base::subtle::Release_Store(&policy_may_need_update_, 1);
|
| + PostUpdatePolicyOnControlRunner(base::TimeDelta());
|
| + }
|
| + last_input_time_ = Now();
|
| +}
|
| +
|
| +bool RendererSchedulerImpl::ShouldYieldForHighPriorityWork() {
|
| + main_thread_checker_.CalledOnValidThread();
|
| + if (!task_queue_manager_)
|
| + return false;
|
| +
|
| + return SchedulerPolicy() == kCompositorPriorityPolicy &&
|
| + !task_queue_manager_->IsQueueEmpty(kCompositorTaskQueue);
|
| +}
|
| +
|
| +base::TimeTicks RendererSchedulerImpl::CurrentIdleTaskDeadline() const {
|
| + main_thread_checker_.CalledOnValidThread();
|
| + return estimated_next_frame_begin_;
|
| +}
|
| +
|
| +RendererSchedulerImpl::Policy RendererSchedulerImpl::SchedulerPolicy() {
|
| + main_thread_checker_.CalledOnValidThread();
|
| + if (base::subtle::Acquire_Load(&policy_may_need_update_)) {
|
| + UpdatePolicy();
|
| + }
|
| + return current_policy_;
|
| +}
|
| +
|
| +void RendererSchedulerImpl::PostUpdatePolicyOnControlRunner(
|
| + base::TimeDelta delay) {
|
| + base::Closure closure = base::Bind(&RendererSchedulerImpl::UpdatePolicy,
|
| + weak_renderer_scheduler_ptr_);
|
| + if (delay > base::TimeDelta()) {
|
| + control_task_runner_->PostDelayedTask(FROM_HERE, closure, delay);
|
| + } else {
|
| + control_task_runner_->PostTask(FROM_HERE, closure);
|
| + }
|
| +}
|
| +
|
| +void RendererSchedulerImpl::UpdatePolicy() {
|
| + main_thread_checker_.CalledOnValidThread();
|
| + if (!task_queue_manager_)
|
| + return;
|
| +
|
| + base::AutoLock lock(incoming_signals_lock_);
|
| + base::subtle::Release_Store(&policy_may_need_update_, 0);
|
| +
|
| + Policy new_policy = kNormalPriorityPolicy;
|
| + if (!last_input_time_.is_null()) {
|
| + base::TimeDelta compositor_priority_duration =
|
| + base::TimeDelta::FromMilliseconds(kCompositorPriorityAfterTouchMillis);
|
| + base::TimeDelta remaining_compositor_priority_duration =
|
| + last_input_time_ + compositor_priority_duration - Now();
|
| + if (remaining_compositor_priority_duration > base::TimeDelta()) {
|
| + PostUpdatePolicyOnControlRunner(remaining_compositor_priority_duration);
|
| + new_policy = kCompositorPriorityPolicy;
|
| + } else {
|
| + // Null out last_input_time_ to ensure DidReceiveInputEvent will post an
|
| + // UpdatePolicy task when it's next called.
|
| + last_input_time_ = base::TimeTicks();
|
| + }
|
| + }
|
| +
|
| + if (new_policy == current_policy_) {
|
| + return;
|
| + }
|
| +
|
| + switch (new_policy) {
|
| + case kCompositorPriorityPolicy:
|
| + renderer_scheduler_selector_->SetQueuePriority(
|
| + kCompositorTaskQueue, RendererSchedulerSelector::kHighPriority);
|
| + break;
|
| + case kNormalPriorityPolicy:
|
| + renderer_scheduler_selector_->SetQueuePriority(
|
| + kCompositorTaskQueue, RendererSchedulerSelector::kNormalPriority);
|
| + break;
|
| + }
|
| + current_policy_ = new_policy;
|
| +}
|
| +
|
| +void RendererSchedulerImpl::StartIdlePeriod() {
|
| + renderer_scheduler_selector_->EnableQueue(
|
| + kIdleTaskQueue, RendererSchedulerSelector::kBestEffortPriority);
|
| + task_queue_manager_->PumpQueue(kIdleTaskQueue);
|
| +}
|
| +
|
| +void RendererSchedulerImpl::EndIdlePeriod() {
|
| + renderer_scheduler_selector_->DisableQueue(kIdleTaskQueue);
|
| +}
|
| +
|
| +base::TimeTicks RendererSchedulerImpl::Now() const {
|
| + return gfx::FrameTime::Now();
|
| +}
|
| +
|
| +} // namespace content
|
|
|