Index: cc/scheduler/scheduler.cc |
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc |
index 010cc990b4762316273d4c4a2b27fa645d791a57..b2a36e14301a3017cd2ef2f1297dad5ed517d958 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" |
@@ -17,11 +18,12 @@ Scheduler::Scheduler(SchedulerClient* client, |
weak_factory_(this), |
last_set_needs_begin_frame_(false), |
has_pending_begin_frame_(false), |
- safe_to_expect_begin_frame_(false), |
+ safe_to_expect_begin_frame_( |
+ !scheduler_settings.use_begin_frame_workaround_for_crbug_249806), |
state_machine_(scheduler_settings), |
inside_process_scheduled_actions_(false) { |
DCHECK(client_); |
- DCHECK(!state_machine_.BeginFrameNeededToDrawByImplThread()); |
+ DCHECK(!state_machine_.BeginFrameNeededByImplThread()); |
} |
Scheduler::~Scheduler() { |
@@ -43,19 +45,27 @@ void Scheduler::SetCanDraw(bool can_draw) { |
ProcessScheduledActions(); |
} |
-void Scheduler::SetHasPendingTree(bool has_pending_tree) { |
- state_machine_.SetHasPendingTree(has_pending_tree); |
+void Scheduler::NotifyReadyToActivate() { |
+ state_machine_.NotifyReadyToActivate(); |
ProcessScheduledActions(); |
} |
+void Scheduler::SetHasTrees(bool has_pending_tree, bool active_tree_is_null) { |
+ state_machine_.SetHasTrees(has_pending_tree, active_tree_is_null); |
+ ProcessScheduledActions(); |
+ |
+ if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly()) |
+ PostBeginFrameDeadline(base::TimeTicks()); |
+} |
+ |
void Scheduler::SetNeedsCommit() { |
state_machine_.SetNeedsCommit(); |
ProcessScheduledActions(); |
} |
-void Scheduler::SetNeedsForcedCommit() { |
+void Scheduler::SetNeedsForcedCommitForReadback() { |
state_machine_.SetNeedsCommit(); |
- state_machine_.SetNeedsForcedCommit(); |
+ state_machine_.SetNeedsForcedCommitForReadback(); |
ProcessScheduledActions(); |
} |
@@ -69,11 +79,6 @@ void Scheduler::DidSwapUseIncompleteTile() { |
ProcessScheduledActions(); |
} |
-void Scheduler::SetNeedsForcedRedraw() { |
- state_machine_.SetNeedsForcedRedraw(); |
- ProcessScheduledActions(); |
-} |
- |
void Scheduler::SetMainThreadNeedsLayerTextures() { |
state_machine_.SetMainThreadNeedsLayerTextures(); |
ProcessScheduledActions(); |
@@ -83,6 +88,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) { |
@@ -93,6 +101,8 @@ void Scheduler::BeginFrameAbortedByMainThread(bool did_handle) { |
void Scheduler::DidLoseOutputSurface() { |
TRACE_EVENT0("cc", "Scheduler::DidLoseOutputSurface"); |
+ begin_frame_deadline_closure_.Cancel(); |
+ has_pending_begin_frame_ = false; |
state_machine_.DidLoseOutputSurface(); |
ProcessScheduledActions(); |
} |
@@ -100,9 +110,11 @@ void Scheduler::DidLoseOutputSurface() { |
void Scheduler::DidCreateAndInitializeOutputSurface() { |
TRACE_EVENT0("cc", "Scheduler::DidCreateAndInitializeOutputSurface"); |
state_machine_.DidCreateAndInitializeOutputSurface(); |
+ begin_frame_deadline_closure_.Cancel(); |
has_pending_begin_frame_ = false; |
last_set_needs_begin_frame_ = false; |
- safe_to_expect_begin_frame_ = false; |
+ safe_to_expect_begin_frame_ = |
+ !settings_.use_begin_frame_workaround_for_crbug_249806; |
ProcessScheduledActions(); |
} |
@@ -113,12 +125,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() { |
@@ -128,41 +139,37 @@ 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; |
+ state_machine_.BeginFrameProactivelyNeededByImplThread(); |
+ |
+ // We want to avoid proactive begin frames with the synchronous |
+ // compositor because every SetNeedsBeginFrame will force a redraw. |
bool needs_begin_frame = needs_begin_frame_to_draw || |
proactive_begin_frame_wanted; |
- bool immediate_disables_needed = |
- settings_.using_synchronous_renderer_compositor; |
+ |
+ bool should_call_set_needs_begin_frame = |
+ // The synchronous renderer compositor needs immediate enables/disables. |
+ (settings_.using_synchronous_renderer_compositor && |
+ needs_begin_frame != last_set_needs_begin_frame_) || |
+ // Always request the BeginFrame immediately if it wasn't needed before. |
+ (needs_begin_frame && !last_set_needs_begin_frame_) || |
+ // Only disable the BeginFrame after a BeginFrame where we didn't swap. |
+ (!needs_begin_frame && last_set_needs_begin_frame_ && |
+ has_pending_begin_frame_ && !state_machine_.InsideBeginFrame()) || |
+ // We did not draw and swap this BeginFrame, |
+ // so we need to explicitly request another BeginFrame. |
+ (needs_begin_frame && has_pending_begin_frame_ && |
+ !state_machine_.InsideBeginFrame()); |
if (needs_begin_frame_to_draw) |
safe_to_expect_begin_frame_ = true; |
- // Determine if we need BeginFrame notifications. |
- // If we do, always request the BeginFrame immediately. |
- // If not, only disable on the next BeginFrame to avoid unnecessary toggles. |
- // The synchronous renderer compositor requires immediate disables though. |
- if ((needs_begin_frame || |
- state_machine_.inside_begin_frame() || |
- immediate_disables_needed) && |
- (needs_begin_frame != last_set_needs_begin_frame_)) { |
+ if (should_call_set_needs_begin_frame) { |
has_pending_begin_frame_ = false; |
client_->SetNeedsBeginFrameOnImplThread(needs_begin_frame); |
if (safe_to_expect_begin_frame_) |
last_set_needs_begin_frame_ = needs_begin_frame; |
} |
- |
- // Request another BeginFrame if we haven't drawn for now until we have |
- // deadlines implemented. |
- if (state_machine_.inside_begin_frame() && has_pending_begin_frame_) { |
- has_pending_begin_frame_ = false; |
- client_->SetNeedsBeginFrameOnImplThread(true); |
- return; |
- } |
} |
void Scheduler::BeginFrame(const BeginFrameArgs& args) { |
@@ -171,13 +178,36 @@ void Scheduler::BeginFrame(const BeginFrameArgs& args) { |
has_pending_begin_frame_ = true; |
safe_to_expect_begin_frame_ = true; |
last_begin_frame_args_ = args; |
- state_machine_.DidEnterBeginFrame(args); |
+ last_begin_frame_args_.AdjustDeadline(-client_->DrawDurationEstimate()); |
+ state_machine_.OnBeginFrame(last_begin_frame_args_); |
ProcessScheduledActions(); |
- state_machine_.DidLeaveBeginFrame(); |
+ |
+ if (settings_.using_synchronous_renderer_compositor) |
+ OnBeginFrameDeadline(); |
+ else if (state_machine_.ShouldTriggerBeginFrameDeadlineEarly()) |
+ PostBeginFrameDeadline(base::TimeTicks()); |
+ else |
+ PostBeginFrameDeadline(last_begin_frame_args_.deadline); |
+} |
+ |
+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(); |
+ client_->DidBeginFrameDeadlineOnImplThread(); |
} |
void Scheduler::DrawAndSwapIfPossible() { |
- ScheduledActionDrawAndSwapResult result = |
+ DrawSwapReadbackResult result = |
client_->ScheduledActionDrawAndSwapIfPossible(); |
state_machine_.DidDrawIfPossibleCompleted(result.did_draw); |
if (result.did_swap) |
@@ -185,7 +215,7 @@ void Scheduler::DrawAndSwapIfPossible() { |
} |
void Scheduler::DrawAndSwapForced() { |
- ScheduledActionDrawAndSwapResult result = |
+ DrawSwapReadbackResult result = |
client_->ScheduledActionDrawAndSwapForced(); |
if (result.did_swap) |
has_pending_begin_frame_ = false; |
@@ -199,8 +229,12 @@ void Scheduler::ProcessScheduledActions() { |
base::AutoReset<bool> mark_inside(&inside_process_scheduled_actions_, true); |
- SchedulerStateMachine::Action action = state_machine_.NextAction(); |
- while (action != SchedulerStateMachine::ACTION_NONE) { |
+ SchedulerStateMachine::Action action; |
+ do { |
+ action = state_machine_.NextAction(); |
+ TRACE_EVENT2("cc", "SchedulerStateMachine", |
+ "action", action, |
+ "state", state_machine_.ToString()); |
state_machine_.UpdateState(action); |
switch (action) { |
case SchedulerStateMachine::ACTION_NONE: |
@@ -214,15 +248,22 @@ void Scheduler::ProcessScheduledActions() { |
case SchedulerStateMachine::ACTION_UPDATE_VISIBLE_TILES: |
client_->ScheduledActionUpdateVisibleTiles(); |
break; |
- case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE_IF_NEEDED: |
- client_->ScheduledActionActivatePendingTreeIfNeeded(); |
+ case SchedulerStateMachine::ACTION_ACTIVATE_PENDING_TREE: |
+ client_->ScheduledActionActivatePendingTree(); |
break; |
- case SchedulerStateMachine::ACTION_DRAW_IF_POSSIBLE: |
+ case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE: |
DrawAndSwapIfPossible(); |
break; |
- case SchedulerStateMachine::ACTION_DRAW_FORCED: |
+ case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED: |
DrawAndSwapForced(); |
break; |
+ case SchedulerStateMachine::ACTION_DRAW_AND_SWAP_ABORT: |
+ // No action is actually performed, but this allows the state machine to |
+ // advance out of its waiting to draw state without actually drawing. |
+ break; |
+ case SchedulerStateMachine::ACTION_DRAW_AND_READBACK: |
+ client_->ScheduledActionDrawAndReadback(); |
+ break; |
case SchedulerStateMachine::ACTION_BEGIN_OUTPUT_SURFACE_CREATION: |
client_->ScheduledActionBeginOutputSurfaceCreation(); |
break; |
@@ -230,9 +271,9 @@ void Scheduler::ProcessScheduledActions() { |
client_->ScheduledActionAcquireLayerTexturesForMainThread(); |
break; |
} |
- action = state_machine_.NextAction(); |
- } |
+ } while (action != SchedulerStateMachine::ACTION_NONE); |
enne (OOO)
2013/08/02 19:41:25
This is a much-needed scheduler change.
|
+ state_machine_.AdvanceBeginFrameStateWhenNoActionsRemain(); |
SetupNextBeginFrameIfNeeded(); |
client_->DidAnticipatedDrawTimeChange(AnticipatedDrawTime()); |
} |