Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |