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

Unified Diff: cc/surfaces/display_scheduler.cc

Issue 2527283003: cc: Introduce BeginFrame sequence numbers and acknowledgements.
Patch Set: Address Brian's comments. Created 4 years 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/surfaces/display_scheduler.h ('k') | cc/surfaces/display_scheduler_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/surfaces/display_scheduler.cc
diff --git a/cc/surfaces/display_scheduler.cc b/cc/surfaces/display_scheduler.cc
index 229bc6306ccb1ecf4af4056e074b35a56ac9f429..11a6d04f53e48224f337d4cfe6e03dd58ce1f1cc 100644
--- a/cc/surfaces/display_scheduler.cc
+++ b/cc/surfaces/display_scheduler.cc
@@ -13,10 +13,10 @@
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),
@@ -25,12 +25,9 @@ DisplayScheduler::DisplayScheduler(BeginFrameSource* begin_frame_source,
inside_begin_frame_deadline_interval_(false),
needs_draw_(false),
expecting_root_surface_damage_because_of_resize_(false),
- all_active_child_surfaces_ready_to_draw_(false),
pending_swaps_(0),
max_pending_swaps_(max_pending_swaps),
- observing_begin_frame_source_(false),
- root_surface_damaged_(false),
- expect_damage_from_root_surface_(false),
+ observing_begin_frames_(false),
weak_ptr_factory_(this) {
begin_frame_deadline_closure_ = base::Bind(
&DisplayScheduler::OnBeginFrameDeadline, weak_ptr_factory_.GetWeakPtr());
@@ -44,6 +41,12 @@ 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);
+}
+
void DisplayScheduler::SetVisible(bool visible) {
if (visible_ == visible)
return;
@@ -68,14 +71,13 @@ void DisplayScheduler::SetRootSurfaceResourcesLocked(bool locked) {
void DisplayScheduler::ForceImmediateSwapIfPossible() {
TRACE_EVENT0("cc", "DisplayScheduler::ForceImmediateSwapIfPossible");
bool in_begin = inside_begin_frame_deadline_interval_;
- AttemptDrawAndSwap();
+ bool did_draw = AttemptDrawAndSwap();
if (in_begin)
- begin_frame_source_->DidFinishFrame(this, 0);
+ begin_frame_source_->FinishClientFrame(did_draw, needs_draw_);
}
void DisplayScheduler::DisplayResized() {
expecting_root_surface_damage_because_of_resize_ = true;
- expect_damage_from_root_surface_ = true;
needs_draw_ = true;
ScheduleBeginFrameDeadline();
}
@@ -102,16 +104,8 @@ void DisplayScheduler::SurfaceDamaged(const SurfaceId& surface_id) {
needs_draw_ = true;
- if (surface_id == root_surface_id_) {
- root_surface_damaged_ = true;
+ if (surface_id == root_surface_id_)
expecting_root_surface_damage_because_of_resize_ = false;
- } 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_);
- }
StartObservingBeginFrames();
ScheduleBeginFrameDeadline();
@@ -123,35 +117,27 @@ void DisplayScheduler::OutputSurfaceLost() {
ScheduleBeginFrameDeadline();
}
-void DisplayScheduler::DrawAndSwap() {
+bool DisplayScheduler::DrawAndSwap() {
TRACE_EVENT0("cc", "DisplayScheduler::DrawAndSwap");
DCHECK_LT(pending_swaps_, max_pending_swaps_);
DCHECK(!output_surface_lost_);
bool success = client_->DrawAndSwap();
if (!success)
- return;
-
- child_surface_ids_to_expect_damage_from_ =
- base::STLSetIntersection<std::vector<SurfaceId>>(
- child_surface_ids_damaged_, child_surface_ids_damaged_prev_);
-
- child_surface_ids_damaged_prev_.swap(child_surface_ids_damaged_);
- child_surface_ids_damaged_.clear();
+ return false;
needs_draw_ = false;
- all_active_child_surfaces_ready_to_draw_ =
- child_surface_ids_to_expect_damage_from_.empty();
-
- expect_damage_from_root_surface_ = root_surface_damaged_;
- root_surface_damaged_ = false;
+ return true;
}
-bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
+void DisplayScheduler::OnBeginFrame(const BeginFrameArgs& args) {
base::TimeTicks now = base::TimeTicks::Now();
TRACE_EVENT2("cc", "DisplayScheduler::BeginFrame", "args", args.AsValue(),
"now", now);
+ // We always use the args, even if we post a missing_begin_frame_task.
+ last_used_begin_frame_args_ = args;
+
if (inside_surface_damaged_) {
// Repost this so that we don't run a missed BeginFrame on the same
// callstack. Otherwise we end up running unexpected scheduler actions
@@ -160,12 +146,12 @@ bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
DCHECK_EQ(args.type, BeginFrameArgs::MISSED);
DCHECK(missed_begin_frame_task_.IsCancelled());
missed_begin_frame_task_.Reset(base::Bind(
- base::IgnoreResult(&DisplayScheduler::OnBeginFrameDerivedImpl),
+ base::IgnoreResult(&DisplayScheduler::OnBeginFrame),
// The CancelableCallback will not run after it is destroyed, which
// happens when |this| is destroyed.
base::Unretained(this), args));
task_runner_->PostTask(FROM_HERE, missed_begin_frame_task_.callback());
- return true;
+ return;
}
// Save the |BeginFrameArgs| as the callback (missed_begin_frame_task_) can be
@@ -189,21 +175,24 @@ bool DisplayScheduler::OnBeginFrameDerivedImpl(const BeginFrameArgs& args) {
BeginFrameArgs::DefaultEstimatedParentDrawTime();
inside_begin_frame_deadline_interval_ = true;
ScheduleBeginFrameDeadline();
+}
- return true;
+const BeginFrameArgs& DisplayScheduler::LastUsedBeginFrameArgs() const {
+ return last_used_begin_frame_args_;
}
void DisplayScheduler::StartObservingBeginFrames() {
- if (!observing_begin_frame_source_ && ShouldDraw()) {
- begin_frame_source_->AddObserver(this);
- observing_begin_frame_source_ = true;
+ if (!observing_begin_frames_ &&
+ (ShouldDraw() || begin_frame_source_->HasObservers())) {
+ begin_frame_source_->SetClientNeedsBeginFrames(true);
+ observing_begin_frames_ = true;
}
}
void DisplayScheduler::StopObservingBeginFrames() {
- if (observing_begin_frame_source_) {
- begin_frame_source_->RemoveObserver(this);
- observing_begin_frame_source_ = false;
+ if (observing_begin_frames_) {
+ begin_frame_source_->SetClientNeedsBeginFrames(false);
+ observing_begin_frames_ = false;
// A missed BeginFrame may be queued, so drop that too if we're going to
// stop listening.
@@ -217,11 +206,12 @@ bool DisplayScheduler::ShouldDraw() {
return needs_draw_ && !output_surface_lost_ && visible_;
}
-void DisplayScheduler::OnBeginFrameSourcePausedChanged(bool paused) {
- // BeginFrameSources used with DisplayScheduler do not make use of this
- // feature.
- if (paused)
- NOTIMPLEMENTED();
+void DisplayScheduler::BeginFrameObserverStatusChanged() {
+ // We proactively start observing if any observer requests BeginFrames to
+ // ensure that we call FinishClientFrame() for all of the source's frames.
+ StartObservingBeginFrames();
+ // Schedules an immediate deadline if all observers have responded.
+ ScheduleBeginFrameDeadline();
}
base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
@@ -236,7 +226,10 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
current_begin_frame_args_.interval;
}
- if (!needs_draw_) {
+ bool observers_finished_frame =
+ begin_frame_source_->AllObserversFinishedFrame();
+
+ if (!needs_draw_ && !observers_finished_frame) {
TRACE_EVENT_INSTANT0("cc", "No damage yet", TRACE_EVENT_SCOPE_THREAD);
return current_begin_frame_args_.frame_time +
current_begin_frame_args_.interval;
@@ -249,10 +242,8 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
current_begin_frame_args_.interval;
}
- bool root_ready_to_draw =
- !expect_damage_from_root_surface_ || root_surface_damaged_;
-
- if (all_active_child_surfaces_ready_to_draw_ && root_ready_to_draw) {
+ if (observers_finished_frame &&
+ !expecting_root_surface_damage_because_of_resize_) {
TRACE_EVENT_INSTANT0("cc", "All active surfaces ready",
TRACE_EVENT_SCOPE_THREAD);
return base::TimeTicks();
@@ -266,27 +257,6 @@ base::TimeTicks DisplayScheduler::DesiredBeginFrameDeadlineTime() {
current_begin_frame_args_.interval;
}
- // Use an earlier deadline if we are only waiting for the root surface
- // in case our expect_damage_from_root_surface heuristic is incorrect.
- // TODO(mithro): Replace this with SetNeedsBeginFrame and SwapAbort
- // logic.
- if (all_active_child_surfaces_ready_to_draw_ &&
- expect_damage_from_root_surface_) {
- TRACE_EVENT_INSTANT0("cc", "Waiting for damage from root surface",
- TRACE_EVENT_SCOPE_THREAD);
- // This adjusts the deadline by DefaultEstimatedParentDrawTime for
- // a second time. The first one represented the Surfaces draw to display
- // latency. This one represents root surface commit+raster+draw latency.
- // We treat the root surface differently since it lives on the same thread
- // as Surfaces and waiting for it too long may push out the Surfaces draw.
- // If we also assume the root surface is fast to start a commit after the
- // beginning of a frame, it'll have a chance to lock its resources, which
- // will cause us to wait for it to unlock its resources above.
- // TODO(mithro): Replace hard coded estimates.
- return current_begin_frame_args_.deadline -
- BeginFrameArgs::DefaultEstimatedParentDrawTime();
- }
-
TRACE_EVENT_INSTANT0("cc", "More damage expected soon",
TRACE_EVENT_SCOPE_THREAD);
return current_begin_frame_args_.deadline;
@@ -327,31 +297,32 @@ void DisplayScheduler::ScheduleBeginFrameDeadline() {
"desired_deadline", desired_deadline);
}
-void DisplayScheduler::AttemptDrawAndSwap() {
+bool DisplayScheduler::AttemptDrawAndSwap() {
inside_begin_frame_deadline_interval_ = false;
begin_frame_deadline_task_.Cancel();
begin_frame_deadline_task_time_ = base::TimeTicks();
if (ShouldDraw()) {
if (pending_swaps_ < max_pending_swaps_ && !root_surface_resources_locked_)
- DrawAndSwap();
- } else {
+ return DrawAndSwap();
+ } else if (!begin_frame_source_->HasObservers()) {
// We are going idle, so reset expectations.
- child_surface_ids_to_expect_damage_from_.clear();
- child_surface_ids_damaged_prev_.clear();
- child_surface_ids_damaged_.clear();
- all_active_child_surfaces_ready_to_draw_ = true;
- expect_damage_from_root_surface_ = false;
+ // TODO(eseckler): Should we avoid going idle if
+ // expecting_root_surface_damage_because_of_resize_ is true?
+ expecting_root_surface_damage_because_of_resize_ = false;
StopObservingBeginFrames();
}
+
+ return false;
}
void DisplayScheduler::OnBeginFrameDeadline() {
TRACE_EVENT0("cc", "DisplayScheduler::OnBeginFrameDeadline");
+ DCHECK(inside_begin_frame_deadline_interval_);
- AttemptDrawAndSwap();
- begin_frame_source_->DidFinishFrame(this, 0);
+ bool did_draw = AttemptDrawAndSwap();
+ begin_frame_source_->FinishClientFrame(did_draw, needs_draw_);
}
void DisplayScheduler::DidSwapBuffers() {
« no previous file with comments | « cc/surfaces/display_scheduler.h ('k') | cc/surfaces/display_scheduler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698