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

Unified Diff: cc/scheduler/scheduler.cc

Issue 23796002: cc: Implement deadine scheduling disabled by default (Closed) Base URL: http://git.chromium.org/chromium/src.git@schedReadback4
Patch Set: Only tie commit to BEGIN_FRAME_IDLE when deadline enabled Created 7 years, 3 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_settings.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/scheduler/scheduler.cc
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 14f6c7fe2f1d1d9eb9a1a7bddb078101631569e4..57273b8bba056117e886186f7bb68b04e2288117 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -4,6 +4,7 @@
#include "cc/scheduler/scheduler.h"
+#include <algorithm>
#include "base/auto_reset.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
@@ -21,12 +22,10 @@ Scheduler::Scheduler(SchedulerClient* client,
inside_process_scheduled_actions_(false),
inside_action_(SchedulerStateMachine::ACTION_NONE) {
DCHECK(client_);
- DCHECK(!state_machine_.BeginFrameNeededToDrawByImplThread());
+ DCHECK(!state_machine_.BeginFrameNeededByImplThread());
}
-Scheduler::~Scheduler() {
- client_->SetNeedsBeginFrameOnImplThread(false);
-}
+Scheduler::~Scheduler() {}
void Scheduler::SetCanStart() {
state_machine_.SetCanStart();
@@ -48,6 +47,12 @@ void Scheduler::NotifyReadyToActivate() {
ProcessScheduledActions();
}
+void Scheduler::ActivatePendingTree() {
+ client_->ScheduledActionActivatePendingTree();
+ if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
+ PostBeginFrameDeadline(base::TimeTicks());
+}
+
void Scheduler::SetNeedsCommit() {
state_machine_.SetNeedsCommit();
ProcessScheduledActions();
@@ -84,6 +89,9 @@ void Scheduler::FinishCommit() {
TRACE_EVENT0("cc", "Scheduler::FinishCommit");
state_machine_.FinishCommit();
ProcessScheduledActions();
+
+ if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly())
+ PostBeginFrameDeadline(base::TimeTicks());
}
void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) {
@@ -94,14 +102,17 @@ void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) {
void Scheduler::DidLoseOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface");
+ last_set_needs_begin_frame_ = false;
+ begin_frame_deadline_closure_.Cancel();
state_machine_.DidLoseOutputSurface();
ProcessScheduledActions();
}
void Scheduler::DidCreateAndInitializeOutputSurface() {
TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface");
+ DCHECK(!last_set_needs_begin_frame_);
+ DCHECK(begin_frame_deadline_closure_.IsCancelled());
state_machine_.DidCreateAndInitializeOutputSurface();
- last_set_needs_begin_frame_ = false;
ProcessScheduledActions();
}
@@ -112,12 +123,11 @@ base::TimeTicks Scheduler::AnticipatedDrawTime() {
last_begin_frame_args_.interval <= base::TimeDelta())
return base::TimeTicks();
- // TODO(brianderson): Express this in terms of the deadline.
base::TimeTicks now = base::TimeTicks::Now();
- int64 intervals = 1 + ((now - last_begin_frame_args_.frame_time) /
- last_begin_frame_args_.interval);
- return last_begin_frame_args_.frame_time +
- (last_begin_frame_args_.interval * intervals);
+ base::TimeTicks timebase = std::max(last_begin_frame_args_.frame_time,
+ last_begin_frame_args_.deadline);
+ int64 intervals = 1 + ((now - timebase) / last_begin_frame_args_.interval);
+ return timebase + (last_begin_frame_args_.interval * intervals);
}
base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
@@ -125,32 +135,30 @@ base::TimeTicks Scheduler::LastBeginFrameOnImplThreadTime() {
}
void Scheduler::SetupNextBeginFrameIfNeeded() {
- bool needs_begin_frame_to_draw =
- state_machine_.BeginFrameNeededToDrawByImplThread();
- // We want to avoid proactive begin frames with the synchronous compositor
- // because every SetNeedsBeginFrame will force a redraw.
- bool proactive_begin_frame_wanted =
- state_machine_.ProactiveBeginFrameWantedByImplThread() &&
- !settings_.using_synchronous_renderer_compositor &&
- settings_.throttle_frame_production;
- bool needs_begin_frame = needs_begin_frame_to_draw ||
- proactive_begin_frame_wanted;
+ bool needs_begin_frame =
+ state_machine_.BeginFrameNeededByImplThread();
+
+ bool at_end_of_deadline =
+ state_machine_.begin_frame_state() ==
+ SchedulerStateMachine::BEGIN_FRAME_STATE_INSIDE_DEADLINE;
bool should_call_set_needs_begin_frame =
// Always request the BeginFrame immediately if it wasn't needed before.
(needs_begin_frame && !last_set_needs_begin_frame_) ||
// We always need to explicitly request our next BeginFrame.
- state_machine_.inside_begin_frame();
+ at_end_of_deadline;
if (should_call_set_needs_begin_frame) {
client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame);
last_set_needs_begin_frame_ = needs_begin_frame;
}
- // Setup PollForAnticipatedDrawTriggers for cases where we want a proactive
- // BeginFrame but aren't requesting one.
- if (!needs_begin_frame &&
- state_machine_.ProactiveBeginFrameWantedByImplThread()) {
+ // Setup PollForAnticipatedDrawTriggers if we need to monitor state but
+ // aren't expecting any more BeginFrames. This should only be needed by the
+ // synchronous compositor when BeginFrameNeededByImplThread is false.
+ if (state_machine_.ShouldPollForAnticipatedDrawTriggers()) {
+ DCHECK(settings_.using_synchronous_renderer_compositor);
+ DCHECK(!needs_begin_frame);
if (poll_for_draw_triggers_closure_.IsCancelled()) {
poll_for_draw_triggers_closure_.Reset(
base::Bind(&Scheduler::PollForAnticipatedDrawTriggers,
@@ -167,11 +175,64 @@ void Scheduler::SetupNextBeginFrameIfNeeded() {
void Scheduler::BeginFrame(const BeginFrameArgs& args) {
TRACE_EVENT0("cc", "Scheduler::BeginFrame");
- DCHECK(!state_machine_.inside_begin_frame());
+ DCHECK(state_machine_.begin_frame_state() ==
+ SchedulerStateMachine::BEGIN_FRAME_STATE_IDLE);
last_begin_frame_args_ = args;
- state_machine_.DidEnterBeginFrame(args);
+ last_begin_frame_args_.deadline -= client_->DrawDurationEstimate();
+ state_machine_.OnBeginFrame(last_begin_frame_args_);
+ ProcessScheduledActions();
+ state_machine_.OnBeginFrameDeadlinePending();
+
+ if (settings_.using_synchronous_renderer_compositor) {
+ // The synchronous renderer compositor has to make its GL calls
+ // within this call to BeginFrame.
+ // TODO(brianderson): Have the OutputSurface initiate the deadline tasks
+ // so the sychronous renderer compoistor can take advantage of splitting
+ // up the BeginFrame and deadline as well.
+ OnBeginFrameDeadline();
+ } else if (!settings_.deadline_scheduling_enabled) {
+ // We emulate the old non-deadline scheduler here by posting the
+ // deadline task without any delay.
+ PostBeginFrameDeadline(base::TimeTicks());
+ } else if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly()) {
+ // We are ready to draw a new active tree immediately.
+ PostBeginFrameDeadline(base::TimeTicks());
+ } else if (state_machine_.needs_redraw()) {
+ // We have an animation or fast input path on the impl thread that wants
+ // to draw, so don't wait too long for a new active tree.
+ PostBeginFrameDeadline(last_begin_frame_args_.deadline);
+ } else {
+ // The impl thread doesn't have anything it wants to draw and we are just
+ // waiting for a new active tree, so post the deadline for the next
+ // expected BeginFrame start. This allows us to draw immediately when
+ // there is a new active tree, instead of waiting for the next BeginFrame.
+ // TODO(brianderson): Handle long deadlines (that are past the next frame's
+ // frame time) properly instead of using this hack.
+ PostBeginFrameDeadline(last_begin_frame_args_.frame_time +
+ last_begin_frame_args_.interval);
+ }
+}
+
+void Scheduler::PostBeginFrameDeadline(base::TimeTicks deadline) {
+ begin_frame_deadline_closure_.Cancel();
+ begin_frame_deadline_closure_.Reset(
+ base::Bind(&Scheduler::OnBeginFrameDeadline, weak_factory_.GetWeakPtr()));
+ client_->PostBeginFrameDeadline(begin_frame_deadline_closure_.callback(),
+ deadline);
+}
+
+void Scheduler::OnBeginFrameDeadline() {
+ TRACE_EVENT0("cc", "Scheduler::OnBeginFrameDeadline");
+ begin_frame_deadline_closure_.Cancel();
+ state_machine_.OnBeginFrameDeadline();
ProcessScheduledActions();
- state_machine_.DidLeaveBeginFrame();
+ // We only transition out of BEGIN_FRAME_STATE_INSIDE_DEADLINE when all
+ // actions that occur back-to-back in response to entering
+ // BEGIN_FRAME_STATE_INSIDE_DEADLINE have completed. This is important
+ // because sending the BeginFrame to the main thread will not occur if
+ // we transition to BEGIN_FRAME_STATE_IDLE too early.
+ state_machine_.OnBeginFrameIdle();
+ client_->DidBeginFrameDeadlineOnImplThread();
}
void Scheduler::PollForAnticipatedDrawTriggers() {
@@ -228,7 +289,7 @@ void Scheduler::ProcessScheduledActions() {
client_->ScheduledActionUpdateVisibleTiles();
break;
case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE:
- client_->ScheduledActionActivatePendingTree();
+ ActivatePendingTree();
break;
case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE:
DrawAndSwapIfPossible();
« no previous file with comments | « cc/scheduler/scheduler.h ('k') | cc/scheduler/scheduler_settings.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698