| 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/surface_dependency_tracker.h" | 5 #include "cc/surfaces/surface_dependency_tracker.h" |
| 6 | 6 |
| 7 #include "cc/surfaces/surface.h" | 7 #include "cc/surfaces/surface.h" |
| 8 #include "cc/surfaces/surface_info.h" | 8 #include "cc/surfaces/surface_info.h" |
| 9 #include "cc/surfaces/surface_manager.h" | 9 #include "cc/surfaces/surface_manager.h" |
| 10 | 10 |
| 11 namespace cc { | 11 namespace cc { |
| 12 | 12 |
| 13 namespace { | 13 namespace { |
| 14 constexpr uint32_t kMaxBeginFrameCount = 4; | 14 constexpr uint32_t kMaxBeginFrameCount = 4; |
| 15 } | 15 } |
| 16 | 16 |
| 17 SurfaceDependencyTracker::SurfaceDependencyTracker( | 17 SurfaceDependencyTracker::SurfaceDependencyTracker( |
| 18 SurfaceManager* surface_manager, | 18 SurfaceManager* surface_manager, |
| 19 BeginFrameSource* begin_frame_source) | 19 BeginFrameSource* begin_frame_source) |
| 20 : surface_manager_(surface_manager), | 20 : surface_manager_(surface_manager), |
| 21 begin_frame_source_(begin_frame_source) { | 21 begin_frame_source_(begin_frame_source) { |
| 22 surface_manager_->AddObserver(this); | 22 surface_manager_->AddObserver(this); |
| 23 begin_frame_source_->AddObserver(this); | |
| 24 } | 23 } |
| 25 | 24 |
| 26 SurfaceDependencyTracker::~SurfaceDependencyTracker() { | 25 SurfaceDependencyTracker::~SurfaceDependencyTracker() { |
| 27 surface_manager_->RemoveObserver(this); | 26 surface_manager_->RemoveObserver(this); |
| 28 begin_frame_source_->RemoveObserver(this); | |
| 29 for (Surface* pending_surface : pending_surfaces_) | 27 for (Surface* pending_surface : pending_surfaces_) |
| 30 pending_surface->RemoveObserver(this); | 28 pending_surface->RemoveObserver(this); |
| 31 pending_surfaces_.clear(); | 29 pending_surfaces_.clear(); |
| 30 UpdateNeedsBeginFrames(); // Stop observing the BeginFrameSource. |
| 32 } | 31 } |
| 33 | 32 |
| 34 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) { | 33 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) { |
| 35 DCHECK(surface->HasPendingFrame()); | 34 DCHECK(surface->HasPendingFrame()); |
| 36 | 35 |
| 37 const CompositorFrame& pending_frame = surface->GetPendingFrame(); | 36 const CompositorFrame& pending_frame = surface->GetPendingFrame(); |
| 38 bool needs_begin_frame = | 37 bool needs_deadline = pending_frame.metadata.can_activate_before_dependencies; |
| 39 pending_frame.metadata.can_activate_before_dependencies; | |
| 40 | 38 |
| 41 // Referenced surface IDs that aren't currently known to the surface manager | 39 // Referenced surface IDs that aren't currently known to the surface manager |
| 42 // or do not have an active CompsotiorFrame block this frame. | 40 // or do not have an active CompsotiorFrame block this frame. |
| 43 for (const SurfaceId& surface_id : | 41 for (const SurfaceId& surface_id : |
| 44 pending_frame.metadata.referenced_surfaces) { | 42 pending_frame.metadata.referenced_surfaces) { |
| 45 Surface* surface_dependency = surface_manager_->GetSurfaceForId(surface_id); | 43 Surface* surface_dependency = surface_manager_->GetSurfaceForId(surface_id); |
| 46 if (!surface_dependency || !surface_dependency->HasActiveFrame()) | 44 if (!surface_dependency || !surface_dependency->HasActiveFrame()) |
| 47 blocked_surfaces_[surface_id].insert(surface); | 45 blocked_surfaces_[surface_id].insert(surface); |
| 48 } | 46 } |
| 49 | 47 |
| 50 if (!pending_surfaces_.count(surface)) { | 48 if (!pending_surfaces_.count(surface)) { |
| 51 surface->AddObserver(this); | 49 surface->AddObserver(this); |
| 52 pending_surfaces_.insert(surface); | 50 pending_surfaces_.insert(surface); |
| 53 } | 51 } |
| 54 | 52 |
| 55 if (needs_begin_frame && !frames_since_deadline_set_) | 53 if (needs_deadline && !frames_since_deadline_set_) |
| 56 frames_since_deadline_set_ = 0; | 54 frames_since_deadline_set_ = 0; |
| 55 |
| 56 // |pending_surfaces_| changed. |
| 57 UpdateNeedsBeginFrames(); |
| 58 } |
| 59 |
| 60 void SurfaceDependencyTracker::UpdateNeedsBeginFrames() { |
| 61 // We observe while there are pending surfaces, even if we don't have a |
| 62 // deadline set. This way, we can send BeginFrameAcks on behalf of the |
| 63 // pending CompositorFrames. |
| 64 bool needs_begin_frames = !pending_surfaces_.empty(); |
| 65 |
| 66 if (needs_begin_frames_ == needs_begin_frames) |
| 67 return; |
| 68 needs_begin_frames_ = needs_begin_frames; |
| 69 |
| 70 if (needs_begin_frames_) |
| 71 begin_frame_source_->AddObserver(this); |
| 72 else |
| 73 begin_frame_source_->RemoveObserver(this); |
| 57 } | 74 } |
| 58 | 75 |
| 59 void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) { | 76 void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) { |
| 77 // We only acknowledge the BeginFrame if and when all pending frames have |
| 78 // been activated. While there are pending frames, we will not acknowledge the |
| 79 // BeginFrame. This way, we indicate to the BeginFrameSource that we are still |
| 80 // waiting on blockers to resolve and that the |
| 81 // |latest_confirmed_sequence_number| of each pending frame is not integrated |
| 82 // into any display frame produced before their activation. |
| 83 // |
| 84 // While we are not acknowledging, the BeginFrameSource will use the sequence |
| 85 // number of the last BeginFrame that we did not receive as our |
| 86 // latest_confirmed_sequence_number. This may not be completely accurate (a |
| 87 // pending frame may include older updates), but it is as good as we can get, |
| 88 // since we cannot retroactively unconfirm BeginFrames that we didn't receive. |
| 89 |
| 60 // If no deadline is set then we have nothing to do. | 90 // If no deadline is set then we have nothing to do. |
| 61 if (!frames_since_deadline_set_) | 91 if (!frames_since_deadline_set_) |
| 62 return; | 92 return; |
| 63 | 93 |
| 94 if (args.source_id == last_begin_frame_args_.source_id && |
| 95 args.sequence_number == last_begin_frame_args_.sequence_number) { |
| 96 // We've seen this BeginFrame already. |
| 97 return; |
| 98 } |
| 99 |
| 64 // TODO(fsamuel, kylechar): We have a single global deadline here. We should | 100 // TODO(fsamuel, kylechar): We have a single global deadline here. We should |
| 65 // scope deadlines to surface subtrees. We cannot do that until | 101 // scope deadlines to surface subtrees. We cannot do that until |
| 66 // SurfaceReferences have been fully implemented | 102 // SurfaceReferences have been fully implemented |
| 67 // (see https://crbug.com/689719). | 103 // (see https://crbug.com/689719). |
| 68 last_begin_frame_args_ = args; | 104 last_begin_frame_args_ = args; |
| 69 // Nothing to do if we haven't hit a deadline yet. | 105 // Nothing to do if we haven't hit a deadline yet. |
| 70 if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount) | 106 if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount) |
| 71 return; | 107 return; |
| 72 | 108 |
| 73 // Activate all surfaces that respect the deadline. | 109 // Activate all surfaces that respect the deadline. |
| 74 PendingSurfaceSet pending_surfaces(pending_surfaces_); | 110 PendingSurfaceSet pending_surfaces(pending_surfaces_); |
| 75 for (Surface* pending_surface : pending_surfaces) | 111 for (Surface* pending_surface : pending_surfaces) |
| 76 pending_surface->ActivatePendingFrameForDeadline(); | 112 pending_surface->ActivatePendingFrameForDeadline(); |
| 77 | 113 |
| 78 frames_since_deadline_set_.reset(); | 114 frames_since_deadline_set_.reset(); |
| 79 } | 115 } |
| 80 | 116 |
| 81 const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const { | 117 const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const { |
| 82 return last_begin_frame_args_; | 118 // Return invalid args, so that we receive the same BeginFrame multiple times |
| 119 // if we start observing BeginFrames again during the same BeginFrame: Even if |
| 120 // we already received and acknowledged a BeginFrame before, we want to |
| 121 // acknowledge it again on behalf of any newly added pending surfaces. |
| 122 static BeginFrameArgs args; |
| 123 return args; |
| 83 } | 124 } |
| 84 | 125 |
| 85 void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {} | 126 void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {} |
| 86 | 127 |
| 128 void SurfaceDependencyTracker::AcknowledgeLastBeginFrame() { |
| 129 DCHECK(needs_begin_frames_); |
| 130 // TODO(eseckler): By not acking while a pending surface exist, we will |
| 131 // prevent early deadlines in DisplayScheduler, see https://crbug.com/707513. |
| 132 // Maybe there's a way to detect when it is unlikely/impossible for blockers |
| 133 // to resolve during the current BeginFrame. |
| 134 DCHECK(pending_surfaces_.empty()); |
| 135 |
| 136 // Some clients submit CompositorFrames without prior BeginFrames. |
| 137 if (!last_begin_frame_args_.IsValid()) |
| 138 return; |
| 139 |
| 140 begin_frame_source_->DidFinishFrame( |
| 141 this, BeginFrameAck(last_begin_frame_args_.source_id, |
| 142 last_begin_frame_args_.sequence_number, |
| 143 last_begin_frame_args_.sequence_number, true)); |
| 144 } |
| 145 |
| 87 void SurfaceDependencyTracker::OnReferencedSurfacesChanged( | 146 void SurfaceDependencyTracker::OnReferencedSurfacesChanged( |
| 88 Surface* surface, | 147 Surface* surface, |
| 89 const std::vector<SurfaceId>* active_referenced_surfaces, | 148 const std::vector<SurfaceId>* active_referenced_surfaces, |
| 90 const std::vector<SurfaceId>* pending_referenced_surfaces) {} | 149 const std::vector<SurfaceId>* pending_referenced_surfaces) {} |
| 91 | 150 |
| 92 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { | 151 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { |
| 93 // If the surface being destroyed doesn't have a pending frame then we have | 152 // If the surface being destroyed doesn't have a pending frame then we have |
| 94 // nothing to do here. | 153 // nothing to do here. |
| 95 if (!surface->HasPendingFrame()) | 154 if (!surface->HasPendingFrame()) |
| 96 return; | 155 return; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 110 if (pending_surface_it != pending_surface_set.end()) { | 169 if (pending_surface_it != pending_surface_set.end()) { |
| 111 pending_surface_set.erase(surface); | 170 pending_surface_set.erase(surface); |
| 112 if (pending_surface_set.empty()) | 171 if (pending_surface_set.empty()) |
| 113 blocked_surfaces_.erase(surface_id); | 172 blocked_surfaces_.erase(surface_id); |
| 114 } | 173 } |
| 115 } | 174 } |
| 116 | 175 |
| 117 if (blocked_surfaces_.empty()) | 176 if (blocked_surfaces_.empty()) |
| 118 frames_since_deadline_set_.reset(); | 177 frames_since_deadline_set_.reset(); |
| 119 | 178 |
| 120 pending_surfaces_.erase(surface); | 179 DCHECK(!pending_surfaces_.empty()); |
| 180 DCHECK(pending_surfaces_.erase(surface)); |
| 121 surface->RemoveObserver(this); | 181 surface->RemoveObserver(this); |
| 122 | 182 |
| 183 if (pending_surfaces_.empty()) |
| 184 AcknowledgeLastBeginFrame(); |
| 185 // |pending_surfaces_| changed. |
| 186 UpdateNeedsBeginFrames(); |
| 123 // Pretend that the discarded surface's SurfaceId is now available to unblock | 187 // Pretend that the discarded surface's SurfaceId is now available to unblock |
| 124 // dependencies because we now know the surface will never activate. | 188 // dependencies because we now know the surface will never activate. |
| 125 NotifySurfaceIdAvailable(surface->surface_id()); | 189 NotifySurfaceIdAvailable(surface->surface_id()); |
| 126 } | 190 } |
| 127 | 191 |
| 128 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { | 192 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { |
| 129 surface->RemoveObserver(this); | 193 surface->RemoveObserver(this); |
| 130 pending_surfaces_.erase(surface); | 194 DCHECK(!pending_surfaces_.empty()); |
| 195 DCHECK(pending_surfaces_.erase(surface)); |
| 196 |
| 197 if (pending_surfaces_.empty()) |
| 198 AcknowledgeLastBeginFrame(); |
| 199 // |pending_surfaces_| changed. |
| 200 UpdateNeedsBeginFrames(); |
| 131 NotifySurfaceIdAvailable(surface->surface_id()); | 201 NotifySurfaceIdAvailable(surface->surface_id()); |
| 132 } | 202 } |
| 133 | 203 |
| 134 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( | 204 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( |
| 135 Surface* surface, | 205 Surface* surface, |
| 136 const SurfaceDependencies& added_dependencies, | 206 const SurfaceDependencies& added_dependencies, |
| 137 const SurfaceDependencies& removed_dependencies) { | 207 const SurfaceDependencies& removed_dependencies) { |
| 138 // Update the |blocked_surfaces_| map with the changes in dependencies. | 208 // Update the |blocked_surfaces_| map with the changes in dependencies. |
| 139 for (const SurfaceId& surface_id : added_dependencies) | 209 for (const SurfaceId& surface_id : added_dependencies) |
| 140 blocked_surfaces_[surface_id].insert(surface); | 210 blocked_surfaces_[surface_id].insert(surface); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 // have a deadline. | 248 // have a deadline. |
| 179 if (blocked_surfaces_.empty()) | 249 if (blocked_surfaces_.empty()) |
| 180 frames_since_deadline_set_.reset(); | 250 frames_since_deadline_set_.reset(); |
| 181 | 251 |
| 182 // Tell each surface about the availability of its blocker. | 252 // Tell each surface about the availability of its blocker. |
| 183 for (Surface* blocked_pending_surface : blocked_pending_surface_set) | 253 for (Surface* blocked_pending_surface : blocked_pending_surface_set) |
| 184 blocked_pending_surface->NotifySurfaceIdAvailable(surface_id); | 254 blocked_pending_surface->NotifySurfaceIdAvailable(surface_id); |
| 185 } | 255 } |
| 186 | 256 |
| 187 } // namespace cc | 257 } // namespace cc |
| OLD | NEW |