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

Unified Diff: cc/surfaces/compositor_frame_sink_support.cc

Issue 2785103003: [cc] CompositorFrameSinkSupport: Defer BeginFrameAck of pending frames. (Closed)
Patch Set: Created 3 years, 9 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/compositor_frame_sink_support.h ('k') | cc/surfaces/direct_compositor_frame_sink_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/surfaces/compositor_frame_sink_support.cc
diff --git a/cc/surfaces/compositor_frame_sink_support.cc b/cc/surfaces/compositor_frame_sink_support.cc
index 97c351f2f9acc2d5472b096bf2dcfbbf655ef8d6..b0f21866a1c5ff503954be2afd7ab3a86e948640 100644
--- a/cc/surfaces/compositor_frame_sink_support.cc
+++ b/cc/surfaces/compositor_frame_sink_support.cc
@@ -52,7 +52,7 @@ CompositorFrameSinkSupport::~CompositorFrameSinkSupport() {
// SurfaceFactory's destructor will attempt to return resources which will
// call back into here and access |client_| so we should destroy
// |surface_factory_|'s resources early on.
- surface_factory_.EvictSurface();
+ EvictFrame();
surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_);
if (handles_frame_sink_id_invalidation_)
surface_manager_->InvalidateFrameSinkId(frame_sink_id_);
@@ -60,23 +60,45 @@ CompositorFrameSinkSupport::~CompositorFrameSinkSupport() {
void CompositorFrameSinkSupport::EvictFrame() {
surface_factory_.EvictSurface();
+ PendingFrameDiscarded();
Fady Samuel 2017/03/30 12:41:56 There are other ways for frames to get discarded.
Eric Seckler 2017/03/30 14:20:50 In that particular case, I don't think we'd want t
}
void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) {
- needs_begin_frame_ = needs_begin_frame;
+ client_needs_begin_frame_ = needs_begin_frame;
+ bool was_observing = added_frame_observer_;
UpdateNeedsBeginFramesInternal();
+
+ // If we are observing because of a pending CompositorFrame, we may have
+ // previously received a BeginFrame that we should now forward to the client.
+ // BackToBackBeginFrameSource sends a new BeginFrame in a separate task
+ // provided we weren't observing before, so we special-case it here.
+ if (needs_begin_frame && !last_begin_frame_sent_to_client_ &&
+ (was_observing || begin_frame_source_->IsThrottled())) {
+ last_begin_frame_sent_to_client_ = true;
+ client_->OnBeginFrame(last_begin_frame_args_);
+ }
}
void CompositorFrameSinkSupport::BeginFrameDidNotSwap(
const BeginFrameAck& ack) {
- // TODO(eseckler): While a pending CompositorFrame exists (see TODO below), we
- // should not acknowledge immediately. Instead, we should update the ack that
- // will be sent to DisplayScheduler when the pending frame is activated.
DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, ack.sequence_number);
+
+ if (ack.sequence_number < BeginFrameArgs::kStartingFrameNumber) {
+ DLOG(ERROR) << "Received BeginFrameDidNotSwap with invalid BeginFrameAck.";
+ return;
+ }
// |has_damage| is not transmitted, but false by default.
DCHECK(!ack.has_damage);
- if (begin_frame_source_)
- begin_frame_source_->DidFinishFrame(this, ack);
+
+ if (has_pending_frame_) {
Fady Samuel 2017/03/30 12:41:56 How do we get here?
Eric Seckler 2017/03/30 14:20:50 A client may continue to receive further BeginFram
+ // We will acknowledge the BeginFrame once the pending frame activates.
+ begin_frame_ack_for_pending_frame_.source_id = ack.source_id;
+ begin_frame_ack_for_pending_frame_.latest_confirmed_sequence_number =
+ ack.latest_confirmed_sequence_number;
+ return;
+ }
+
+ AcknowledgeBeginFrame(ack);
}
void CompositorFrameSinkSupport::SubmitCompositorFrame(
@@ -94,18 +116,19 @@ void CompositorFrameSinkSupport::SubmitCompositorFrame(
// |has_damage| is not transmitted.
frame.metadata.begin_frame_ack.has_damage = true;
+ // The CompositorFrame submitted below might not be activated right away b/c
+ // of surface synchronization. We only send the BeginFrameAck to
+ // DisplayScheduler once it is activated.
Fady Samuel 2017/03/30 12:41:56 I'm confused. We send a AcknowledgeLastBeginFrameW
Eric Seckler 2017/03/30 14:20:50 Not right away. We only send the ack from Acknowle
+ has_pending_frame_ = true;
+ // If there was a previous pending frame that didn't get activated, this
+ // overrides the pending BeginFrameAck.
+ begin_frame_ack_for_pending_frame_ = frame.metadata.begin_frame_ack;
+ UpdateNeedsBeginFramesInternal();
+
surface_factory_.SubmitCompositorFrame(
local_surface_id, std::move(frame),
base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
weak_factory_.GetWeakPtr()));
-
- // TODO(eseckler): The CompositorFrame submitted below might not be activated
- // right away b/c of surface synchronization. We should only send the
- // BeginFrameAck to DisplayScheduler when it is activated. This also means
- // that we need to stay an active BFO while a CompositorFrame is pending.
- // See https://crbug.com/703079.
- if (begin_frame_source_)
- begin_frame_source_->DidFinishFrame(this, frame.metadata.begin_frame_ack);
}
void CompositorFrameSinkSupport::UpdateSurfaceReferences(
@@ -171,6 +194,7 @@ void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() {
void CompositorFrameSinkSupport::ForceReclaimResources() {
surface_factory_.ClearSurface();
+ PendingFrameDiscarded();
Fady Samuel 2017/03/30 12:41:56 There are other ways for a pending frame to get di
Eric Seckler 2017/03/30 14:20:50 Done. I'll have to keep this call to PendingFrameD
}
void CompositorFrameSinkSupport::ClaimTemporaryReference(
@@ -229,11 +253,81 @@ void CompositorFrameSinkSupport::WillDrawSurface(
client_->WillDrawSurface(local_surface_id, damage_rect);
}
+void CompositorFrameSinkSupport::PendingFrameActivated(
+ const LocalSurfaceId& local_surface_id) {
+ if (!has_pending_frame_)
Fady Samuel 2017/03/30 12:41:56 I'm confused about when this can happen? Should th
Eric Seckler 2017/03/30 14:20:50 Things like ClearSurface() submit CompositorFrames
+ return;
+
+ has_pending_frame_ = false;
+
+ if (last_begin_frame_args_.IsValid()) {
+ if (last_begin_frame_args_.source_id !=
+ begin_frame_ack_for_pending_frame_.source_id) {
+ // BeginFrameSource has changed, we cannot confirm any sequence number.
+ begin_frame_ack_for_pending_frame_.source_id =
+ last_begin_frame_args_.source_id;
+ begin_frame_ack_for_pending_frame_.latest_confirmed_sequence_number =
+ BeginFrameArgs::kInvalidFrameNumber;
+ }
+
+ begin_frame_ack_for_pending_frame_.sequence_number =
+ last_begin_frame_args_.sequence_number;
+ }
+
+ DCHECK(begin_frame_ack_for_pending_frame_.has_damage);
+ AcknowledgeBeginFrame(begin_frame_ack_for_pending_frame_);
+ UpdateNeedsBeginFramesInternal();
Fady Samuel 2017/03/30 12:41:56 A comment about how we are no longer waiting for a
Eric Seckler 2017/03/30 14:20:50 Done.
+}
+
+void CompositorFrameSinkSupport::PendingFrameDiscarded() {
+ if (!has_pending_frame_)
+ return;
+
+ has_pending_frame_ = false;
+ AcknowledgeLastBeginFrameWithoutUpdates();
+ UpdateNeedsBeginFramesInternal();
+}
+
void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
UpdateNeedsBeginFramesInternal();
+
+ // If we are observing BeginFrames while a pending frame exists, we are
+ // deferring acknowledging until the pending frame activates. Thus, we may not
+ // have acknowledged the last BeginFrame yet. Do that now.
+ if (has_pending_frame_)
+ AcknowledgeLastBeginFrameWithoutUpdates();
+
last_begin_frame_args_ = args;
- if (client_)
+ if (client_ && client_needs_begin_frame_) {
+ last_begin_frame_sent_to_client_ = true;
client_->OnBeginFrame(args);
+ } else {
+ last_begin_frame_sent_to_client_ = false;
+ }
+}
+
+void CompositorFrameSinkSupport::AcknowledgeLastBeginFrameWithoutUpdates() {
+ if (!last_begin_frame_args_.IsValid())
Fady Samuel 2017/03/30 12:41:55 Why would this happen?
Eric Seckler 2017/03/30 14:20:50 Well, not all clients wait for BeginFrames to subm
+ return;
+
+ uint64_t confirmed_sequence_number = BeginFrameArgs::kInvalidFrameNumber;
+ if (last_begin_frame_args_.source_id ==
+ latest_confirmed_begin_frame_source_id_) {
+ confirmed_sequence_number = latest_confirmed_begin_frame_sequence_number_;
+ }
+ AcknowledgeBeginFrame(BeginFrameAck(last_begin_frame_args_.source_id,
+ last_begin_frame_args_.sequence_number,
+ confirmed_sequence_number, false));
+}
+
+void CompositorFrameSinkSupport::AcknowledgeBeginFrame(
+ const BeginFrameAck& ack) {
+ latest_confirmed_begin_frame_source_id_ =
+ ack.latest_confirmed_sequence_number;
+ latest_confirmed_begin_frame_sequence_number_ =
+ ack.latest_confirmed_sequence_number;
+ if (begin_frame_source_)
+ begin_frame_source_->DidFinishFrame(this, ack);
}
const BeginFrameArgs& CompositorFrameSinkSupport::LastUsedBeginFrameArgs()
@@ -247,11 +341,16 @@ void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() {
if (!begin_frame_source_)
return;
- if (needs_begin_frame_ == added_frame_observer_)
+ // We continue observing BeginFrames while a frame is pending to be activated,
+ // so that we can eventually forward the corresponding BeginFrameAck to the
+ // source.
+ bool needs_begin_frame = client_needs_begin_frame_ || has_pending_frame_;
+
+ if (needs_begin_frame == added_frame_observer_)
return;
- added_frame_observer_ = needs_begin_frame_;
- if (needs_begin_frame_)
+ added_frame_observer_ = needs_begin_frame;
+ if (added_frame_observer_)
begin_frame_source_->AddObserver(this);
else
begin_frame_source_->RemoveObserver(this);
« no previous file with comments | « cc/surfaces/compositor_frame_sink_support.h ('k') | cc/surfaces/direct_compositor_frame_sink_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698