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

Side by Side Diff: cc/surfaces/compositor_frame_sink_support.cc

Issue 2785103003: [cc] CompositorFrameSinkSupport: Defer BeginFrameAck of pending frames. (Closed)
Patch Set: address comments, some fixes, added tests. 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/surfaces/compositor_frame_sink_support.h" 5 #include "cc/surfaces/compositor_frame_sink_support.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "cc/output/compositor_frame.h" 10 #include "cc/output/compositor_frame.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 45
46 // For display root surfaces, the surface is no longer going to be visible 46 // For display root surfaces, the surface is no longer going to be visible
47 // so make it unreachable from the top-level root. 47 // so make it unreachable from the top-level root.
48 if (surface_manager_->using_surface_references() && is_root_ && 48 if (surface_manager_->using_surface_references() && is_root_ &&
49 reference_tracker_.current_surface_id().is_valid()) 49 reference_tracker_.current_surface_id().is_valid())
50 RemoveTopLevelRootReference(reference_tracker_.current_surface_id()); 50 RemoveTopLevelRootReference(reference_tracker_.current_surface_id());
51 51
52 // SurfaceFactory's destructor will attempt to return resources which will 52 // SurfaceFactory's destructor will attempt to return resources which will
53 // call back into here and access |client_| so we should destroy 53 // call back into here and access |client_| so we should destroy
54 // |surface_factory_|'s resources early on. 54 // |surface_factory_|'s resources early on.
55 surface_factory_.EvictSurface(); 55 EvictFrame();
56 surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_); 56 surface_manager_->UnregisterSurfaceFactoryClient(frame_sink_id_);
57 if (handles_frame_sink_id_invalidation_) 57 if (handles_frame_sink_id_invalidation_)
58 surface_manager_->InvalidateFrameSinkId(frame_sink_id_); 58 surface_manager_->InvalidateFrameSinkId(frame_sink_id_);
59 } 59 }
60 60
61 void CompositorFrameSinkSupport::EvictFrame() { 61 void CompositorFrameSinkSupport::EvictFrame() {
62 surface_factory_.EvictSurface(); 62 surface_factory_.EvictSurface();
63 } 63 }
64 64
65 void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) { 65 void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) {
66 needs_begin_frame_ = needs_begin_frame; 66 client_needs_begin_frame_ = needs_begin_frame;
67 bool was_observing = added_frame_observer_;
67 UpdateNeedsBeginFramesInternal(); 68 UpdateNeedsBeginFramesInternal();
69
70 // If we are observing because of a pending CompositorFrame, we may have
71 // previously received a BeginFrame that we should now forward to the client.
72 // BackToBackBeginFrameSource sends a new BeginFrame in a separate task
73 // provided we weren't observing before, so we special-case it here.
74 if (needs_begin_frame && !last_begin_frame_sent_to_client_ &&
75 (was_observing || begin_frame_source_->IsThrottled())) {
76 last_begin_frame_sent_to_client_ = true;
77 client_->OnBeginFrame(last_begin_frame_args_);
78 }
68 } 79 }
69 80
70 void CompositorFrameSinkSupport::BeginFrameDidNotSwap( 81 void CompositorFrameSinkSupport::BeginFrameDidNotSwap(
71 const BeginFrameAck& ack) { 82 const BeginFrameAck& ack) {
72 // TODO(eseckler): While a pending CompositorFrame exists (see TODO below), we
73 // should not acknowledge immediately. Instead, we should update the ack that
74 // will be sent to DisplayScheduler when the pending frame is activated.
75 DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, ack.sequence_number); 83 DCHECK_LE(BeginFrameArgs::kStartingFrameNumber, ack.sequence_number);
84
85 if (ack.sequence_number < BeginFrameArgs::kStartingFrameNumber) {
86 DLOG(ERROR) << "Received BeginFrameDidNotSwap with invalid BeginFrameAck.";
87 return;
88 }
76 // |has_damage| is not transmitted, but false by default. 89 // |has_damage| is not transmitted, but false by default.
77 DCHECK(!ack.has_damage); 90 DCHECK(!ack.has_damage);
78 if (begin_frame_source_) 91
79 begin_frame_source_->DidFinishFrame(this, ack); 92 // Client can continue to request BeginFrames after submitting a
93 // CompositorFrame, so we may end up with a pending frame here.
94 if (begin_frame_ack_for_pending_frame_) {
95 // We will acknowledge the BeginFrame once the pending frame activates.
96 begin_frame_ack_for_pending_frame_->source_id = ack.source_id;
brianderson 2017/03/31 19:21:27 Is it possible for the source_id to change? If no
Eric Seckler 2017/04/03 11:21:00 Considering headless use cases (dynamically replac
97 begin_frame_ack_for_pending_frame_->latest_confirmed_sequence_number =
98 ack.latest_confirmed_sequence_number;
99 return;
100 }
101
102 AcknowledgeBeginFrame(ack);
80 } 103 }
81 104
82 void CompositorFrameSinkSupport::SubmitCompositorFrame( 105 void CompositorFrameSinkSupport::SubmitCompositorFrame(
83 const LocalSurfaceId& local_surface_id, 106 const LocalSurfaceId& local_surface_id,
84 CompositorFrame frame) { 107 CompositorFrame frame) {
85 ++ack_pending_count_; 108 ++ack_pending_count_;
86 109
87 if (frame.metadata.begin_frame_ack.sequence_number < 110 if (frame.metadata.begin_frame_ack.sequence_number <
88 BeginFrameArgs::kStartingFrameNumber) { 111 BeginFrameArgs::kStartingFrameNumber) {
89 DLOG(ERROR) << "Received CompositorFrame with invalid BeginFrameAck."; 112 DLOG(ERROR) << "Received CompositorFrame with invalid BeginFrameAck.";
90 frame.metadata.begin_frame_ack.source_id = BeginFrameArgs::kManualSourceId; 113 frame.metadata.begin_frame_ack.source_id = BeginFrameArgs::kManualSourceId;
91 frame.metadata.begin_frame_ack.sequence_number = 114 frame.metadata.begin_frame_ack.sequence_number =
92 BeginFrameArgs::kStartingFrameNumber; 115 BeginFrameArgs::kStartingFrameNumber;
93 } 116 }
94 // |has_damage| is not transmitted. 117 // |has_damage| is not transmitted.
95 frame.metadata.begin_frame_ack.has_damage = true; 118 frame.metadata.begin_frame_ack.has_damage = true;
96 119
120 // The CompositorFrame submitted below might not be activated right away b/c
121 // of surface synchronization. We only forward the CompositorFrame's
122 // BeginFrameAck to DisplayScheduler once it is activated. While waiting for
123 // activation, we continue to observe BeginFrames. If the CompositorFrame is
124 // not activated before we receive the next BeginFrame, we will acknowledge
125 // the current one without updates. If there was a previous pending frame that
126 // didn't get activated, this overrides the pending BeginFrameAck.
127 begin_frame_ack_for_pending_frame_ = frame.metadata.begin_frame_ack;
128 surface_id_for_pending_frame_ = local_surface_id;
129 // Ensure that we continue observing BeginFrames while the frame is pending.
130 UpdateNeedsBeginFramesInternal();
131
97 surface_factory_.SubmitCompositorFrame( 132 surface_factory_.SubmitCompositorFrame(
98 local_surface_id, std::move(frame), 133 local_surface_id, std::move(frame),
99 base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck, 134 base::Bind(&CompositorFrameSinkSupport::DidReceiveCompositorFrameAck,
100 weak_factory_.GetWeakPtr())); 135 weak_factory_.GetWeakPtr()));
101
102 // TODO(eseckler): The CompositorFrame submitted below might not be activated
103 // right away b/c of surface synchronization. We should only send the
104 // BeginFrameAck to DisplayScheduler when it is activated. This also means
105 // that we need to stay an active BFO while a CompositorFrame is pending.
106 // See https://crbug.com/703079.
107 if (begin_frame_source_)
108 begin_frame_source_->DidFinishFrame(this, frame.metadata.begin_frame_ack);
109 } 136 }
110 137
111 void CompositorFrameSinkSupport::UpdateSurfaceReferences( 138 void CompositorFrameSinkSupport::UpdateSurfaceReferences(
112 const SurfaceId& last_surface_id, 139 const SurfaceId& last_surface_id,
113 const LocalSurfaceId& local_surface_id) { 140 const LocalSurfaceId& local_surface_id) {
114 const bool surface_id_changed = 141 const bool surface_id_changed =
115 last_surface_id.local_surface_id() != local_surface_id; 142 last_surface_id.local_surface_id() != local_surface_id;
116 143
117 // If this is a display root surface and the SurfaceId is changing, make the 144 // If this is a display root surface and the SurfaceId is changing, make the
118 // new SurfaceId reachable from the top-level root. 145 // new SurfaceId reachable from the top-level root.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 // We return the resources before sending an ack so they can be reused in 190 // We return the resources before sending an ack so they can be reused in
164 // making the next CompositorFrame. 191 // making the next CompositorFrame.
165 if (!surface_returned_resources_.empty()) { 192 if (!surface_returned_resources_.empty()) {
166 client_->ReclaimResources(surface_returned_resources_); 193 client_->ReclaimResources(surface_returned_resources_);
167 surface_returned_resources_.clear(); 194 surface_returned_resources_.clear();
168 } 195 }
169 client_->DidReceiveCompositorFrameAck(); 196 client_->DidReceiveCompositorFrameAck();
170 } 197 }
171 198
172 void CompositorFrameSinkSupport::ForceReclaimResources() { 199 void CompositorFrameSinkSupport::ForceReclaimResources() {
200 PendingFrameDiscarded();
173 surface_factory_.ClearSurface(); 201 surface_factory_.ClearSurface();
174 } 202 }
175 203
176 void CompositorFrameSinkSupport::ClaimTemporaryReference( 204 void CompositorFrameSinkSupport::ClaimTemporaryReference(
177 const SurfaceId& surface_id) { 205 const SurfaceId& surface_id) {
178 surface_manager_->AssignTemporaryReference(surface_id, frame_sink_id_); 206 surface_manager_->AssignTemporaryReference(surface_id, frame_sink_id_);
179 } 207 }
180 208
181 void CompositorFrameSinkSupport::ReferencedSurfacesChanged( 209 void CompositorFrameSinkSupport::ReferencedSurfacesChanged(
182 const LocalSurfaceId& local_surface_id, 210 const LocalSurfaceId& local_surface_id,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 UpdateNeedsBeginFramesInternal(); 250 UpdateNeedsBeginFramesInternal();
223 } 251 }
224 252
225 void CompositorFrameSinkSupport::WillDrawSurface( 253 void CompositorFrameSinkSupport::WillDrawSurface(
226 const LocalSurfaceId& local_surface_id, 254 const LocalSurfaceId& local_surface_id,
227 const gfx::Rect& damage_rect) { 255 const gfx::Rect& damage_rect) {
228 if (client_) 256 if (client_)
229 client_->WillDrawSurface(local_surface_id, damage_rect); 257 client_->WillDrawSurface(local_surface_id, damage_rect);
230 } 258 }
231 259
260 void CompositorFrameSinkSupport::PendingFrameActivated(
261 const LocalSurfaceId& local_surface_id) {
262 // |begin_frame_ack_for_pending_frame_| may not be set because ClearSurface()
263 // submits CompositorFrames we don't track.
264 if (!begin_frame_ack_for_pending_frame_)
265 return;
266 DCHECK_EQ(surface_id_for_pending_frame_, local_surface_id);
267
268 if (last_begin_frame_args_.IsValid()) {
brianderson 2017/03/31 19:21:27 Can you add a comment explaining why this block is
Eric Seckler 2017/04/03 11:21:00 Done.
269 if (last_begin_frame_args_.source_id !=
270 begin_frame_ack_for_pending_frame_->source_id) {
271 // BeginFrameSource has changed, we cannot confirm any sequence number.
272 begin_frame_ack_for_pending_frame_->source_id =
273 last_begin_frame_args_.source_id;
274 begin_frame_ack_for_pending_frame_->latest_confirmed_sequence_number =
275 BeginFrameArgs::kInvalidFrameNumber;
276 }
277
278 begin_frame_ack_for_pending_frame_->sequence_number =
279 last_begin_frame_args_.sequence_number;
280 }
281
282 DCHECK(begin_frame_ack_for_pending_frame_->has_damage);
283 AcknowledgeBeginFrame(*begin_frame_ack_for_pending_frame_);
284
285 begin_frame_ack_for_pending_frame_.reset();
286 // We may no longer need BeginFrames, since we no longer have a pending frame.
287 UpdateNeedsBeginFramesInternal();
288 }
289
290 void CompositorFrameSinkSupport::SurfaceDiscarded(
291 const LocalSurfaceId& local_surface_id) {
292 // Don't call PendingFrameDiscarded() if an older surface was discarded and a
293 // CompositorFrame may still be pending on the new surface.
294 if (local_surface_id != surface_id_for_pending_frame_)
295 return;
296
297 PendingFrameDiscarded();
298 }
299
300 void CompositorFrameSinkSupport::PendingFrameDiscarded() {
301 if (!begin_frame_ack_for_pending_frame_)
302 return;
303
304 begin_frame_ack_for_pending_frame_.reset();
305 AcknowledgeLastBeginFrameWithoutUpdates();
306 UpdateNeedsBeginFramesInternal();
307 }
308
232 void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) { 309 void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
233 UpdateNeedsBeginFramesInternal(); 310 UpdateNeedsBeginFramesInternal();
311
312 // If we are observing BeginFrames while a pending frame exists, we are
313 // deferring acknowledging until the pending frame activates. Thus, we may not
314 // have acknowledged the last BeginFrame yet. Do that now.
315 if (begin_frame_ack_for_pending_frame_)
316 AcknowledgeLastBeginFrameWithoutUpdates();
317
234 last_begin_frame_args_ = args; 318 last_begin_frame_args_ = args;
235 if (client_) 319 if (client_ && client_needs_begin_frame_) {
320 last_begin_frame_sent_to_client_ = true;
236 client_->OnBeginFrame(args); 321 client_->OnBeginFrame(args);
322 } else {
323 last_begin_frame_sent_to_client_ = false;
324 }
325 }
326
327 void CompositorFrameSinkSupport::AcknowledgeLastBeginFrameWithoutUpdates() {
brianderson 2017/03/31 19:21:27 It looks like this acknowledges the most recently
Eric Seckler 2017/04/03 11:21:00 Correct. In order to eventually acknowledge the ac
328 // Not all clients wait for a BeginFrame before submitting CompositorFrames.
329 if (!last_begin_frame_args_.IsValid())
330 return;
331
332 uint64_t confirmed_sequence_number = BeginFrameArgs::kInvalidFrameNumber;
333 if (last_begin_frame_args_.source_id ==
334 latest_confirmed_begin_frame_source_id_) {
335 confirmed_sequence_number = latest_confirmed_begin_frame_sequence_number_;
336 }
337 AcknowledgeBeginFrame(BeginFrameAck(last_begin_frame_args_.source_id,
338 last_begin_frame_args_.sequence_number,
339 confirmed_sequence_number, false));
340
341 // If we have a pending ack and the client doesn't currently need BeginFrames
342 // (thus is up-to-date), we should update the pending ack's
343 // latest_confirmed_frame_number now.
344 if (begin_frame_ack_for_pending_frame_ && !client_needs_begin_frame_) {
345 begin_frame_ack_for_pending_frame_->source_id =
346 last_begin_frame_args_.source_id;
347 begin_frame_ack_for_pending_frame_->latest_confirmed_sequence_number =
348 last_begin_frame_args_.sequence_number;
349 }
350 }
351
352 void CompositorFrameSinkSupport::AcknowledgeBeginFrame(
353 const BeginFrameAck& ack) {
354 latest_confirmed_begin_frame_source_id_ = ack.source_id;
355 latest_confirmed_begin_frame_sequence_number_ =
356 ack.latest_confirmed_sequence_number;
357 if (begin_frame_source_)
358 begin_frame_source_->DidFinishFrame(this, ack);
237 } 359 }
238 360
239 const BeginFrameArgs& CompositorFrameSinkSupport::LastUsedBeginFrameArgs() 361 const BeginFrameArgs& CompositorFrameSinkSupport::LastUsedBeginFrameArgs()
240 const { 362 const {
241 return last_begin_frame_args_; 363 return last_begin_frame_args_;
242 } 364 }
243 365
244 void CompositorFrameSinkSupport::OnBeginFrameSourcePausedChanged(bool paused) {} 366 void CompositorFrameSinkSupport::OnBeginFrameSourcePausedChanged(bool paused) {}
245 367
246 void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() { 368 void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() {
247 if (!begin_frame_source_) 369 if (!begin_frame_source_)
248 return; 370 return;
249 371
250 if (needs_begin_frame_ == added_frame_observer_) 372 // We continue observing BeginFrames while a frame is pending to be activated,
373 // so that we can eventually forward the corresponding BeginFrameAck to the
374 // source.
375 bool needs_begin_frame =
376 client_needs_begin_frame_ || begin_frame_ack_for_pending_frame_;
377
378 if (needs_begin_frame == added_frame_observer_)
251 return; 379 return;
252 380
253 added_frame_observer_ = needs_begin_frame_; 381 added_frame_observer_ = needs_begin_frame;
254 if (needs_begin_frame_) 382 if (added_frame_observer_)
255 begin_frame_source_->AddObserver(this); 383 begin_frame_source_->AddObserver(this);
256 else 384 else
257 begin_frame_source_->RemoveObserver(this); 385 begin_frame_source_->RemoveObserver(this);
258 } 386 }
259 387
260 void CompositorFrameSinkSupport::RequestCopyOfSurface( 388 void CompositorFrameSinkSupport::RequestCopyOfSurface(
261 std::unique_ptr<CopyOutputRequest> request) { 389 std::unique_ptr<CopyOutputRequest> request) {
262 surface_factory_.RequestCopyOfSurface(std::move(request)); 390 surface_factory_.RequestCopyOfSurface(std::move(request));
263 } 391 }
264 392
265 } // namespace cc 393 } // namespace cc
OLDNEW
« no previous file with comments | « cc/surfaces/compositor_frame_sink_support.h ('k') | cc/surfaces/compositor_frame_sink_support_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698