| 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() {
|
|
|