Index: cc/surfaces/display_scheduler.cc |
diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc |
index 229bc6306ccb1ecf4af4056e074b35a56ac9f429..3728f043984473a5831743acb5937345861e5691 100644 |
--- a/cc/surfaces/display_scheduler.cc |
+++ b/cc/surfaces/display_scheduler.cc |
@@ -9,14 +9,15 @@ |
#include "base/auto_reset.h" |
#include "base/stl_util.h" |
#include "base/trace_event/trace_event.h" |
+#include "cc/output/begin_frame_args.h" |
#include "cc/output/output_surface.h" |
namespace cc { |
-DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source, |
- base::SingleThreadTaskRunner* task_runner, |
+DisplayScheduler::DisplayScheduler(base::SingleThreadTaskRunner* task_runner, |
int max_pending_swaps) |
- : begin_frame_source_(begin_frame_source), |
+ : client_(nullptr), |
+ begin_frame_source_(nullptr), |
task_runner_(task_runner), |
inside_surface_damaged_(false), |
visible_(false), |
@@ -44,6 +45,13 @@ void DisplayScheduler::SetClient(DisplaySchedulerClient* client) { |
client_ = client; |
} |
+void DisplayScheduler::SetBeginFrameSource( |
+ DisplayBeginFrameSource* begin_frame_source) { |
+ begin_frame_source_ = begin_frame_source; |
+ begin_frame_source_->SetClient(this); |
+ DCHECK(begin_frame_source_->GetTargetSource()); |
+} |
+ |
void DisplayScheduler::SetVisible(bool visible) { |
if (visible_ == visible) |
return; |
@@ -70,7 +78,7 @@ void DisplayScheduler::ForceImmediateSwapIfPossible() { |
bool in_begin = inside_begin_frame_deadline_interval_; |
AttemptDrawAndSwap(); |
if (in_begin) |
- begin_frame_source_->DidFinishFrame(this, 0); |
+ begin_frame_source_->GetTargetSource()->DidFinishFrame(this, 0); |
} |
void DisplayScheduler::DisplayResized() { |
@@ -108,9 +116,21 @@ void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) { |
} else { |
child_surface_ids_damaged_.insert(surface_id); |
- // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. |
- all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( |
- child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); |
+ if (BeginFrameForcesDamage()) { |
+ // Wait for all BeginFrameObservers to call DidFinishFrame() before |
+ // triggering an early deadline. We do this only if we know that the |
+ // BeginFrame should cause damage on all active surfaces, because BFOs |
+ // currently may not call DidFinishFrame() when the BeginFrame does not |
+ // cause any damage to their surface. |
+ // TODO(eseckler): Make this the default heuristic once we can guarantee |
+ // observers to call DidFinishFrame() for every frame. |
+ all_active_child_surfaces_ready_to_draw_ = |
+ begin_frame_source_->AllObserversFinishedFrame(); |
+ } else { |
+ // TODO(mithro): Use hints from SetNeedsBeginFrames and SwapAborts. |
+ all_active_child_surfaces_ready_to_draw_ = base::STLIncludes( |
+ child_surface_ids_damaged_, child_surface_ids_to_expect_damage_from_); |
+ } |
} |
StartObservingBeginFrames(); |
@@ -188,21 +208,33 @@ bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) { |
current_begin_frame_args_.deadline -= |
BeginFrameArgs::DefaultEstimatedParentDrawTime(); |
inside_begin_frame_deadline_interval_ = true; |
- ScheduleBeginFrameDeadline(); |
+ if (BeginFrameForcesDamage()) { |
+ // We know every surface that receives the BeginFrame will be damaged, so we |
+ // wait until all BeginFrameObservers have responded instead of waiting for |
+ // child_surface_ids_to_expect_damage_from_. |
+ expect_damage_from_root_surface_ = false; |
+ all_active_child_surfaces_ready_to_draw_ = |
+ begin_frame_source_->AllObserversFinishedFrame(); |
+ } |
+ |
+ ScheduleBeginFrameDeadline(); |
return true; |
} |
void DisplayScheduler::StartObservingBeginFrames() { |
if (!observing_begin_frame_source_ && ShouldDraw()) { |
- begin_frame_source_->AddObserver(this); |
+ // We don't want to wait for our own DidFinishFrame() when using |
+ // begin_frame_source_->AllObserversFinishedFrame(), so we add ourselves to |
+ // the target source directly. |
+ begin_frame_source_->GetTargetSource()->AddObserver(this); |
observing_begin_frame_source_ = true; |
} |
} |
void DisplayScheduler::StopObservingBeginFrames() { |
if (observing_begin_frame_source_) { |
- begin_frame_source_->RemoveObserver(this); |
+ begin_frame_source_->GetTargetSource()->RemoveObserver(this); |
observing_begin_frame_source_ = false; |
// A missed BeginFrame may be queued, so drop that too if we're going to |
@@ -217,6 +249,10 @@ bool DisplayScheduler::ShouldDraw() { |
return needs_draw_ && !output_surface_lost_ && visible_; |
} |
+bool DisplayScheduler::BeginFrameForcesDamage() const { |
+ return !current_begin_frame_args_.allow_latency_optimizations; |
+} |
+ |
void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) { |
// BeginFrameSources used with DisplayScheduler do not make use of this |
// feature. |
@@ -224,6 +260,24 @@ void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) { |
NOTIMPLEMENTED(); |
} |
+void DisplayScheduler::ObserverStatusChanged() { |
+ // If we're using the BeginFrameObservers to determine when all active |
+ // surfaces have been damaged, we may need to update the deadline. |
+ if (BeginFrameForcesDamage()) { |
+ all_active_child_surfaces_ready_to_draw_ = |
+ begin_frame_source_->AllObserversFinishedFrame(); |
+ ScheduleBeginFrameDeadline(); |
+ } |
+} |
+ |
+void DisplayScheduler::BeginFrameSourceSwapping(BeginFrameSource* new_source) { |
+ DCHECK(new_source); |
+ if (observing_begin_frame_source_) { |
+ begin_frame_source_->GetTargetSource()->RemoveObserver(this); |
+ new_source->AddObserver(this); |
+ } |
+} |
+ |
base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() { |
if (output_surface_lost_) { |
TRACE_EVENT_INSTANT0("cc", "Lost output surface", TRACE_EVENT_SCOPE_THREAD); |
@@ -236,7 +290,10 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() { |
current_begin_frame_args_.interval; |
} |
- if (!needs_draw_) { |
+ // Allow an immediate deadline even if there's no damage and we know that |
+ // no BeginFrameObservers are active. |
+ if (!needs_draw_ && |
+ !(BeginFrameForcesDamage() && all_active_child_surfaces_ready_to_draw_)) { |
TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD); |
return current_begin_frame_args_.frame_time + |
current_begin_frame_args_.interval; |
@@ -351,7 +408,7 @@ void DisplayScheduler::OnBeginFrameDeadline() { |
TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline"); |
AttemptDrawAndSwap(); |
- begin_frame_source_->DidFinishFrame(this, 0); |
+ begin_frame_source_->GetTargetSource()->DidFinishFrame(this, 0); |
} |
void DisplayScheduler::DidSwapBuffers() { |