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/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 UpdateNeedsBeginFrames(); // |pending_surfaces_| changed. | |
| 57 } | |
| 58 | |
| 59 void SurfaceDependencyTracker::UpdateNeedsBeginFrames() { | |
| 60 // We observe while there are pending surfaces, even if we don't have a | |
| 61 // deadline set. This way, we can send BeginFrameAcks on behalf of the | |
| 62 // pending CompositorFrames. | |
| 63 bool needs_begin_frames = !pending_surfaces_.empty(); | |
| 64 | |
| 65 if (needs_begin_frames_ == needs_begin_frames) | |
| 66 return; | |
| 67 needs_begin_frames_ = needs_begin_frames; | |
| 68 | |
| 69 if (needs_begin_frames_) | |
| 70 begin_frame_source_->AddObserver(this); | |
| 71 else | |
| 72 begin_frame_source_->RemoveObserver(this); | |
| 57 } | 73 } |
| 58 | 74 |
| 59 void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) { | 75 void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) { |
| 76 // We only acknowledge the BeginFrame if and when all pending frames have | |
| 77 // been activated. While there are pending frames, we will not acknowledge the | |
| 78 // BeginFrame. This way, we indicate to the BeginFrameSource that we are still | |
| 79 // waiting on blockers to resolve and that the | |
| 80 // |latest_confirmed_sequence_number| of each pending frame is not integrated | |
| 81 // into any display frame produced before their activation. | |
| 82 // | |
| 83 // While we are not acknowledging, the BeginFrameSource will use the sequence | |
| 84 // number of the last BeginFrame that we did not receive as our | |
| 85 // latest_confirmed_sequence_number. This may not be completely accurate (a | |
| 86 // pending frame may include older updates), but it is as good as we can get, | |
| 87 // since we cannot retroactively unconfirm BeginFrames that we didn't receive. | |
| 88 | |
| 60 // If no deadline is set then we have nothing to do. | 89 // If no deadline is set then we have nothing to do. |
| 61 if (!frames_since_deadline_set_) | 90 if (!frames_since_deadline_set_) |
| 62 return; | 91 return; |
| 63 | 92 |
| 93 if (args.source_id == last_begin_frame_args_.source_id && | |
| 94 args.sequence_number == last_begin_frame_args_.sequence_number) { | |
| 95 // We've seen this BeginFrame already. | |
| 96 return; | |
| 97 } | |
| 98 | |
| 64 // TODO(fsamuel, kylechar): We have a single global deadline here. We should | 99 // TODO(fsamuel, kylechar): We have a single global deadline here. We should |
| 65 // scope deadlines to surface subtrees. We cannot do that until | 100 // scope deadlines to surface subtrees. We cannot do that until |
| 66 // SurfaceReferences have been fully implemented | 101 // SurfaceReferences have been fully implemented |
| 67 // (see https://crbug.com/689719). | 102 // (see https://crbug.com/689719). |
| 68 last_begin_frame_args_ = args; | 103 last_begin_frame_args_ = args; |
| 69 // Nothing to do if we haven't hit a deadline yet. | 104 // Nothing to do if we haven't hit a deadline yet. |
| 70 if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount) | 105 if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount) |
| 71 return; | 106 return; |
| 72 | 107 |
| 73 // Activate all surfaces that respect the deadline. | 108 // Activate all surfaces that respect the deadline. |
| 74 PendingSurfaceSet pending_surfaces(pending_surfaces_); | 109 PendingSurfaceSet pending_surfaces(pending_surfaces_); |
| 75 for (Surface* pending_surface : pending_surfaces) | 110 for (Surface* pending_surface : pending_surfaces) |
| 76 pending_surface->ActivatePendingFrameForDeadline(); | 111 pending_surface->ActivatePendingFrameForDeadline(); |
| 77 | 112 |
| 78 frames_since_deadline_set_.reset(); | 113 frames_since_deadline_set_.reset(); |
| 79 } | 114 } |
| 80 | 115 |
| 81 const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const { | 116 const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const { |
| 82 return last_begin_frame_args_; | 117 // Return invalid args, so that we receive the same BeginFrame multiple times |
| 118 // if we start observing BeginFrames again during the same BeginFrame: Even if | |
| 119 // we already received and acknowledged a BeginFrame before, we want to | |
| 120 // acknowledge it again on behalf of any newly added pending surfaces. | |
|
brianderson
2017/04/04 00:29:19
I'm not familiar with SurfaceDependencyTracker. Wh
Eric Seckler
2017/04/04 08:36:45
I was erring on the side of caution, i.e. not assu
| |
| 121 static BeginFrameArgs args; | |
|
Fady Samuel
2017/04/03 19:03:02
This seems kinda icky... What's wrong with always
Eric Seckler
2017/04/04 08:36:45
If we always observe, we have the problem that we
| |
| 122 return args; | |
| 83 } | 123 } |
| 84 | 124 |
| 85 void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {} | 125 void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {} |
| 86 | 126 |
| 127 void SurfaceDependencyTracker::AcknowledgeLastBeginFrame() { | |
| 128 DCHECK(needs_begin_frames_); | |
| 129 DCHECK(pending_surfaces_.empty()); | |
|
Fady Samuel
2017/04/03 19:03:02
This makes me kind of sad...but maybe it's OK for
Eric Seckler
2017/04/04 08:36:45
Yeah. Added one. FWIW, I'm going to try out tracki
| |
| 130 | |
| 131 // Some clients submit CompositorFrames without prior BeginFrames. | |
| 132 if (!last_begin_frame_args_.IsValid()) | |
| 133 return; | |
| 134 | |
| 135 begin_frame_source_->DidFinishFrame( | |
| 136 this, BeginFrameAck(last_begin_frame_args_.source_id, | |
| 137 last_begin_frame_args_.sequence_number, | |
| 138 last_begin_frame_args_.sequence_number, true)); | |
| 139 } | |
| 140 | |
| 87 void SurfaceDependencyTracker::OnReferencedSurfacesChanged( | 141 void SurfaceDependencyTracker::OnReferencedSurfacesChanged( |
| 88 Surface* surface, | 142 Surface* surface, |
| 89 const std::vector<SurfaceId>* active_referenced_surfaces, | 143 const std::vector<SurfaceId>* active_referenced_surfaces, |
| 90 const std::vector<SurfaceId>* pending_referenced_surfaces) {} | 144 const std::vector<SurfaceId>* pending_referenced_surfaces) {} |
| 91 | 145 |
| 92 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { | 146 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { |
| 93 // If the surface being destroyed doesn't have a pending frame then we have | 147 // If the surface being destroyed doesn't have a pending frame then we have |
| 94 // nothing to do here. | 148 // nothing to do here. |
| 95 if (!surface->HasPendingFrame()) | 149 if (!surface->HasPendingFrame()) |
| 96 return; | 150 return; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 110 if (pending_surface_it != pending_surface_set.end()) { | 164 if (pending_surface_it != pending_surface_set.end()) { |
| 111 pending_surface_set.erase(surface); | 165 pending_surface_set.erase(surface); |
| 112 if (pending_surface_set.empty()) | 166 if (pending_surface_set.empty()) |
| 113 blocked_surfaces_.erase(surface_id); | 167 blocked_surfaces_.erase(surface_id); |
| 114 } | 168 } |
| 115 } | 169 } |
| 116 | 170 |
| 117 if (blocked_surfaces_.empty()) | 171 if (blocked_surfaces_.empty()) |
| 118 frames_since_deadline_set_.reset(); | 172 frames_since_deadline_set_.reset(); |
| 119 | 173 |
| 120 pending_surfaces_.erase(surface); | 174 DCHECK(!pending_surfaces_.empty()); |
| 175 DCHECK(pending_surfaces_.erase(surface)); | |
| 121 surface->RemoveObserver(this); | 176 surface->RemoveObserver(this); |
| 122 | 177 |
| 178 if (pending_surfaces_.empty()) | |
| 179 AcknowledgeLastBeginFrame(); | |
| 180 UpdateNeedsBeginFrames(); // |pending_surfaces_| changed. | |
|
Fady Samuel
2017/04/03 19:03:02
nit: put this comment above.
| |
| 181 | |
| 123 // Pretend that the discarded surface's SurfaceId is now available to unblock | 182 // Pretend that the discarded surface's SurfaceId is now available to unblock |
| 124 // dependencies because we now know the surface will never activate. | 183 // dependencies because we now know the surface will never activate. |
| 125 NotifySurfaceIdAvailable(surface->surface_id()); | 184 NotifySurfaceIdAvailable(surface->surface_id()); |
| 126 } | 185 } |
| 127 | 186 |
| 128 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { | 187 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { |
| 129 surface->RemoveObserver(this); | 188 surface->RemoveObserver(this); |
| 130 pending_surfaces_.erase(surface); | 189 DCHECK(!pending_surfaces_.empty()); |
| 190 DCHECK(pending_surfaces_.erase(surface)); | |
| 191 | |
| 192 if (pending_surfaces_.empty()) | |
| 193 AcknowledgeLastBeginFrame(); | |
| 194 UpdateNeedsBeginFrames(); // |pending_surfaces_| changed. | |
|
Fady Samuel
2017/04/03 19:03:02
nit: put this comment above.
| |
| 195 | |
|
Fady Samuel
2017/04/03 19:03:02
nit: remove.
| |
| 131 NotifySurfaceIdAvailable(surface->surface_id()); | 196 NotifySurfaceIdAvailable(surface->surface_id()); |
| 132 } | 197 } |
| 133 | 198 |
| 134 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( | 199 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( |
| 135 Surface* surface, | 200 Surface* surface, |
| 136 const SurfaceDependencies& added_dependencies, | 201 const SurfaceDependencies& added_dependencies, |
| 137 const SurfaceDependencies& removed_dependencies) { | 202 const SurfaceDependencies& removed_dependencies) { |
| 138 // Update the |blocked_surfaces_| map with the changes in dependencies. | 203 // Update the |blocked_surfaces_| map with the changes in dependencies. |
| 139 for (const SurfaceId& surface_id : added_dependencies) | 204 for (const SurfaceId& surface_id : added_dependencies) |
| 140 blocked_surfaces_[surface_id].insert(surface); | 205 blocked_surfaces_[surface_id].insert(surface); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 // have a deadline. | 243 // have a deadline. |
| 179 if (blocked_surfaces_.empty()) | 244 if (blocked_surfaces_.empty()) |
| 180 frames_since_deadline_set_.reset(); | 245 frames_since_deadline_set_.reset(); |
| 181 | 246 |
| 182 // Tell each surface about the availability of its blocker. | 247 // Tell each surface about the availability of its blocker. |
| 183 for (Surface* blocked_pending_surface : blocked_pending_surface_set) | 248 for (Surface* blocked_pending_surface : blocked_pending_surface_set) |
| 184 blocked_pending_surface->NotifySurfaceIdAvailable(surface_id); | 249 blocked_pending_surface->NotifySurfaceIdAvailable(surface_id); |
| 185 } | 250 } |
| 186 | 251 |
| 187 } // namespace cc | 252 } // namespace cc |
| OLD | NEW |