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

Unified Diff: cc/surfaces/surface_dependency_tracker.cc

Issue 2789163002: [cc] Acknowledge BeginFrames in SurfaceDependencyTracker. (Closed)
Patch Set: fix nits Created 3 years, 8 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/surfaces/surface_dependency_tracker.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/surfaces/surface_dependency_tracker.cc
diff --git a/cc/surfaces/surface_dependency_tracker.cc b/cc/surfaces/surface_dependency_tracker.cc
index 6cfeae8ec2b04abb49551738b222ebd5d5e1d58d..386d99a1a9110a4d7179f6e700707446656bdca9 100644
--- a/cc/surfaces/surface_dependency_tracker.cc
+++ b/cc/surfaces/surface_dependency_tracker.cc
@@ -20,23 +20,21 @@ SurfaceDependencyTracker::SurfaceDependencyTracker(
: surface_manager_(surface_manager),
begin_frame_source_(begin_frame_source) {
surface_manager_->AddObserver(this);
- begin_frame_source_->AddObserver(this);
}
SurfaceDependencyTracker::~SurfaceDependencyTracker() {
surface_manager_->RemoveObserver(this);
- begin_frame_source_->RemoveObserver(this);
for (Surface* pending_surface : pending_surfaces_)
pending_surface->RemoveObserver(this);
pending_surfaces_.clear();
+ UpdateNeedsBeginFrames(); // Stop observing the BeginFrameSource.
}
void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
DCHECK(surface->HasPendingFrame());
const CompositorFrame& pending_frame = surface->GetPendingFrame();
- bool needs_begin_frame =
- pending_frame.metadata.can_activate_before_dependencies;
+ bool needs_deadline = pending_frame.metadata.can_activate_before_dependencies;
// Referenced surface IDs that aren't currently known to the surface manager
// or do not have an active CompsotiorFrame block this frame.
@@ -52,15 +50,53 @@ void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
pending_surfaces_.insert(surface);
}
- if (needs_begin_frame && !frames_since_deadline_set_)
+ if (needs_deadline && !frames_since_deadline_set_)
frames_since_deadline_set_ = 0;
+
+ // |pending_surfaces_| changed.
+ UpdateNeedsBeginFrames();
+}
+
+void SurfaceDependencyTracker::UpdateNeedsBeginFrames() {
+ // We observe while there are pending surfaces, even if we don't have a
+ // deadline set. This way, we can send BeginFrameAcks on behalf of the
+ // pending CompositorFrames.
+ bool needs_begin_frames = !pending_surfaces_.empty();
+
+ if (needs_begin_frames_ == needs_begin_frames)
+ return;
+ needs_begin_frames_ = needs_begin_frames;
+
+ if (needs_begin_frames_)
+ begin_frame_source_->AddObserver(this);
+ else
+ begin_frame_source_->RemoveObserver(this);
}
void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) {
+ // We only acknowledge the BeginFrame if and when all pending frames have
+ // been activated. While there are pending frames, we will not acknowledge the
+ // BeginFrame. This way, we indicate to the BeginFrameSource that we are still
+ // waiting on blockers to resolve and that the
+ // |latest_confirmed_sequence_number| of each pending frame is not integrated
+ // into any display frame produced before their activation.
+ //
+ // While we are not acknowledging, the BeginFrameSource will use the sequence
+ // number of the last BeginFrame that we did not receive as our
+ // latest_confirmed_sequence_number. This may not be completely accurate (a
+ // pending frame may include older updates), but it is as good as we can get,
+ // since we cannot retroactively unconfirm BeginFrames that we didn't receive.
+
// If no deadline is set then we have nothing to do.
if (!frames_since_deadline_set_)
return;
+ if (args.source_id == last_begin_frame_args_.source_id &&
+ args.sequence_number == last_begin_frame_args_.sequence_number) {
+ // We've seen this BeginFrame already.
+ return;
+ }
+
// TODO(fsamuel, kylechar): We have a single global deadline here. We should
// scope deadlines to surface subtrees. We cannot do that until
// SurfaceReferences have been fully implemented
@@ -79,11 +115,34 @@ void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) {
}
const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const {
- return last_begin_frame_args_;
+ // Return invalid args, so that we receive the same BeginFrame multiple times
+ // if we start observing BeginFrames again during the same BeginFrame: Even if
+ // we already received and acknowledged a BeginFrame before, we want to
+ // acknowledge it again on behalf of any newly added pending surfaces.
+ static BeginFrameArgs args;
+ return args;
}
void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {}
+void SurfaceDependencyTracker::AcknowledgeLastBeginFrame() {
+ DCHECK(needs_begin_frames_);
+ // TODO(eseckler): By not acking while a pending surface exist, we will
+ // prevent early deadlines in DisplayScheduler, see https://crbug.com/707513.
+ // Maybe there's a way to detect when it is unlikely/impossible for blockers
+ // to resolve during the current BeginFrame.
+ DCHECK(pending_surfaces_.empty());
+
+ // Some clients submit CompositorFrames without prior BeginFrames.
+ if (!last_begin_frame_args_.IsValid())
+ return;
+
+ begin_frame_source_->DidFinishFrame(
+ this, BeginFrameAck(last_begin_frame_args_.source_id,
+ last_begin_frame_args_.sequence_number,
+ last_begin_frame_args_.sequence_number, true));
+}
+
void SurfaceDependencyTracker::OnReferencedSurfacesChanged(
Surface* surface,
const std::vector<SurfaceId>* active_referenced_surfaces,
@@ -117,9 +176,14 @@ void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) {
if (blocked_surfaces_.empty())
frames_since_deadline_set_.reset();
- pending_surfaces_.erase(surface);
+ DCHECK(!pending_surfaces_.empty());
+ DCHECK(pending_surfaces_.erase(surface));
surface->RemoveObserver(this);
+ if (pending_surfaces_.empty())
+ AcknowledgeLastBeginFrame();
+ // |pending_surfaces_| changed.
+ UpdateNeedsBeginFrames();
// Pretend that the discarded surface's SurfaceId is now available to unblock
// dependencies because we now know the surface will never activate.
NotifySurfaceIdAvailable(surface->surface_id());
@@ -127,7 +191,13 @@ void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) {
void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) {
surface->RemoveObserver(this);
- pending_surfaces_.erase(surface);
+ DCHECK(!pending_surfaces_.empty());
+ DCHECK(pending_surfaces_.erase(surface));
+
+ if (pending_surfaces_.empty())
+ AcknowledgeLastBeginFrame();
+ // |pending_surfaces_| changed.
+ UpdateNeedsBeginFrames();
NotifySurfaceIdAvailable(surface->surface_id());
}
« no previous file with comments | « cc/surfaces/surface_dependency_tracker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698