| 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), deadline_(this, begin_frame_source) {} |
| 21 begin_frame_source_(begin_frame_source) { | |
| 22 begin_frame_source_->AddObserver(this); | |
| 23 } | |
| 24 | 21 |
| 25 SurfaceDependencyTracker::~SurfaceDependencyTracker() { | 22 SurfaceDependencyTracker::~SurfaceDependencyTracker() { |
| 26 begin_frame_source_->RemoveObserver(this); | 23 deadline_.Cancel(); |
| 27 } | 24 } |
| 28 | 25 |
| 29 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) { | 26 void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) { |
| 30 DCHECK(surface->HasPendingFrame()); | 27 DCHECK(surface->HasPendingFrame()); |
| 31 | 28 |
| 32 const CompositorFrame& pending_frame = surface->GetPendingFrame(); | 29 const CompositorFrame& pending_frame = surface->GetPendingFrame(); |
| 33 bool needs_deadline = pending_frame.metadata.can_activate_before_dependencies; | 30 bool needs_deadline = pending_frame.metadata.can_activate_before_dependencies; |
| 34 | 31 |
| 35 auto late_it = late_surfaces_by_id_.find(surface->surface_id()); | 32 auto late_it = late_surfaces_by_id_.find(surface->surface_id()); |
| 36 if (needs_deadline && late_it != late_surfaces_by_id_.end()) { | 33 if (needs_deadline && late_it != late_surfaces_by_id_.end()) { |
| 37 late_surfaces_by_id_.erase(late_it); | 34 late_surfaces_by_id_.erase(late_it); |
| 38 surface->ActivatePendingFrameForDeadline(); | 35 surface->ActivatePendingFrameForDeadline(); |
| 39 return; | 36 return; |
| 40 } | 37 } |
| 41 | 38 |
| 42 // 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 |
| 43 // or do not have an active CompsotiorFrame block this frame. | 40 // or do not have an active CompsotiorFrame block this frame. |
| 44 for (const SurfaceId& surface_id : | 41 for (const SurfaceId& surface_id : |
| 45 pending_frame.metadata.activation_dependencies) { | 42 pending_frame.metadata.activation_dependencies) { |
| 46 Surface* surface_dependency = surface_manager_->GetSurfaceForId(surface_id); | 43 Surface* surface_dependency = surface_manager_->GetSurfaceForId(surface_id); |
| 47 if (!surface_dependency || !surface_dependency->HasActiveFrame()) | 44 if (!surface_dependency || !surface_dependency->HasActiveFrame()) |
| 48 blocked_surfaces_from_dependency_[surface_id].insert( | 45 blocked_surfaces_from_dependency_[surface_id].insert( |
| 49 surface->surface_id()); | 46 surface->surface_id()); |
| 50 } | 47 } |
| 51 | 48 |
| 52 blocked_surfaces_by_id_.insert(surface->surface_id()); | 49 blocked_surfaces_by_id_.insert(surface->surface_id()); |
| 53 | 50 |
| 54 if (needs_deadline && !frames_since_deadline_set_) | 51 if (needs_deadline && !deadline_.has_deadline()) |
| 55 frames_since_deadline_set_ = 0; | 52 deadline_.Set(kMaxBeginFrameCount); |
| 56 } | 53 } |
| 57 | 54 |
| 58 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { | 55 void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { |
| 59 blocked_surfaces_by_id_.erase(surface->surface_id()); | 56 blocked_surfaces_by_id_.erase(surface->surface_id()); |
| 60 NotifySurfaceIdAvailable(surface->surface_id()); | 57 NotifySurfaceIdAvailable(surface->surface_id()); |
| 61 } | 58 } |
| 62 | 59 |
| 63 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( | 60 void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( |
| 64 Surface* surface, | 61 Surface* surface, |
| 65 const base::flat_set<SurfaceId>& added_dependencies, | 62 const base::flat_set<SurfaceId>& added_dependencies, |
| 66 const base::flat_set<SurfaceId>& removed_dependencies) { | 63 const base::flat_set<SurfaceId>& removed_dependencies) { |
| 67 // Update the |blocked_surfaces_from_dependency_| map with the changes in | 64 // Update the |blocked_surfaces_from_dependency_| map with the changes in |
| 68 // dependencies. | 65 // dependencies. |
| 69 for (const SurfaceId& surface_id : added_dependencies) | 66 for (const SurfaceId& surface_id : added_dependencies) |
| 70 blocked_surfaces_from_dependency_[surface_id].insert(surface->surface_id()); | 67 blocked_surfaces_from_dependency_[surface_id].insert(surface->surface_id()); |
| 71 | 68 |
| 72 for (const SurfaceId& surface_id : removed_dependencies) { | 69 for (const SurfaceId& surface_id : removed_dependencies) { |
| 73 auto it = blocked_surfaces_from_dependency_.find(surface_id); | 70 auto it = blocked_surfaces_from_dependency_.find(surface_id); |
| 74 it->second.erase(surface->surface_id()); | 71 it->second.erase(surface->surface_id()); |
| 75 if (it->second.empty()) | 72 if (it->second.empty()) |
| 76 blocked_surfaces_from_dependency_.erase(it); | 73 blocked_surfaces_from_dependency_.erase(it); |
| 77 } | 74 } |
| 78 | 75 |
| 79 // If there are no more dependencies to resolve then we don't need to have a | 76 // If there are no more dependencies to resolve then we don't need to have a |
| 80 // deadline. | 77 // deadline. |
| 81 if (blocked_surfaces_from_dependency_.empty()) | 78 if (blocked_surfaces_from_dependency_.empty()) |
| 82 frames_since_deadline_set_.reset(); | 79 deadline_.Cancel(); |
| 83 } | 80 } |
| 84 | 81 |
| 85 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { | 82 void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { |
| 86 // If the surface being destroyed doesn't have a pending frame then we have | 83 // If the surface being destroyed doesn't have a pending frame then we have |
| 87 // nothing to do here. | 84 // nothing to do here. |
| 88 if (!surface->HasPendingFrame()) | 85 if (!surface->HasPendingFrame()) |
| 89 return; | 86 return; |
| 90 | 87 |
| 91 const CompositorFrame& pending_frame = surface->GetPendingFrame(); | 88 const CompositorFrame& pending_frame = surface->GetPendingFrame(); |
| 92 | 89 |
| 93 DCHECK(!pending_frame.metadata.activation_dependencies.empty()); | 90 DCHECK(!pending_frame.metadata.activation_dependencies.empty()); |
| 94 | 91 |
| 95 for (const SurfaceId& surface_id : | 92 for (const SurfaceId& surface_id : |
| 96 pending_frame.metadata.activation_dependencies) { | 93 pending_frame.metadata.activation_dependencies) { |
| 97 auto it = blocked_surfaces_from_dependency_.find(surface_id); | 94 auto it = blocked_surfaces_from_dependency_.find(surface_id); |
| 98 if (it == blocked_surfaces_from_dependency_.end()) | 95 if (it == blocked_surfaces_from_dependency_.end()) |
| 99 continue; | 96 continue; |
| 100 | 97 |
| 101 auto& blocked_surface_ids = it->second; | 98 auto& blocked_surface_ids = it->second; |
| 102 auto blocked_surface_ids_it = | 99 auto blocked_surface_ids_it = |
| 103 blocked_surface_ids.find(surface->surface_id()); | 100 blocked_surface_ids.find(surface->surface_id()); |
| 104 if (blocked_surface_ids_it != blocked_surface_ids.end()) { | 101 if (blocked_surface_ids_it != blocked_surface_ids.end()) { |
| 105 blocked_surface_ids.erase(surface->surface_id()); | 102 blocked_surface_ids.erase(surface->surface_id()); |
| 106 if (blocked_surface_ids.empty()) | 103 if (blocked_surface_ids.empty()) |
| 107 blocked_surfaces_from_dependency_.erase(surface_id); | 104 blocked_surfaces_from_dependency_.erase(surface_id); |
| 108 } | 105 } |
| 109 } | 106 } |
| 110 | 107 |
| 111 if (blocked_surfaces_from_dependency_.empty()) | 108 if (blocked_surfaces_from_dependency_.empty()) |
| 112 frames_since_deadline_set_.reset(); | 109 deadline_.Cancel(); |
| 113 | 110 |
| 114 blocked_surfaces_by_id_.erase(surface->surface_id()); | 111 blocked_surfaces_by_id_.erase(surface->surface_id()); |
| 115 | 112 |
| 116 // Pretend that the discarded surface's SurfaceId is now available to unblock | 113 // Pretend that the discarded surface's SurfaceId is now available to unblock |
| 117 // dependencies because we now know the surface will never activate. | 114 // dependencies because we now know the surface will never activate. |
| 118 NotifySurfaceIdAvailable(surface->surface_id()); | 115 NotifySurfaceIdAvailable(surface->surface_id()); |
| 119 } | 116 } |
| 120 | 117 |
| 121 void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) { | 118 void SurfaceDependencyTracker::OnDeadline() { |
| 122 // If no deadline is set then we have nothing to do. | |
| 123 if (!frames_since_deadline_set_) | |
| 124 return; | |
| 125 | |
| 126 // TODO(fsamuel, kylechar): We have a single global deadline here. We should | |
| 127 // scope deadlines to surface subtrees. We cannot do that until | |
| 128 // SurfaceReferences have been fully implemented | |
| 129 // (see https://crbug.com/689719). | |
| 130 last_begin_frame_args_ = args; | |
| 131 // Nothing to do if we haven't hit a deadline yet. | |
| 132 if (++(*frames_since_deadline_set_) != kMaxBeginFrameCount) | |
| 133 return; | |
| 134 | |
| 135 late_surfaces_by_id_.clear(); | 119 late_surfaces_by_id_.clear(); |
| 136 | 120 |
| 137 // Activate all surfaces that respect the deadline. | 121 // Activate all surfaces that respect the deadline. |
| 138 // Copy the set of blocked surfaces here because that set can mutate as we | 122 // Copy the set of blocked surfaces here because that set can mutate as we |
| 139 // activate CompositorFrames: an activation can trigger further activations | 123 // activate CompositorFrames: an activation can trigger further activations |
| 140 // which will remove elements from |blocked_surfaces_by_id_|. This | 124 // which will remove elements from |blocked_surfaces_by_id_|. This |
| 141 // invalidates the iterator. | 125 // invalidates the iterator. |
| 142 base::flat_set<SurfaceId> blocked_surfaces_by_id(blocked_surfaces_by_id_); | 126 base::flat_set<SurfaceId> blocked_surfaces_by_id(blocked_surfaces_by_id_); |
| 143 for (const SurfaceId& surface_id : blocked_surfaces_by_id) { | 127 for (const SurfaceId& surface_id : blocked_surfaces_by_id) { |
| 144 Surface* blocked_surface = surface_manager_->GetSurfaceForId(surface_id); | 128 Surface* blocked_surface = surface_manager_->GetSurfaceForId(surface_id); |
| 145 if (!blocked_surface) { | 129 if (!blocked_surface) { |
| 146 // A blocked surface may have been garbage collected during dependency | 130 // A blocked surface may have been garbage collected during dependency |
| 147 // resolution. | 131 // resolution. |
| 148 DCHECK(!blocked_surfaces_by_id_.count(surface_id)); | 132 DCHECK(!blocked_surfaces_by_id_.count(surface_id)); |
| 149 continue; | 133 continue; |
| 150 } | 134 } |
| 151 // Clear all tracked blockers for |blocked_surface|. | 135 // Clear all tracked blockers for |blocked_surface|. |
| 152 for (const SurfaceId& blocking_surface_id : | 136 for (const SurfaceId& blocking_surface_id : |
| 153 blocked_surface->blocking_surfaces()) { | 137 blocked_surface->blocking_surfaces()) { |
| 154 // If we are not activating this blocker now, then it's late. | 138 // If we are not activating this blocker now, then it's late. |
| 155 if (!blocked_surfaces_by_id.count(blocking_surface_id)) | 139 if (!blocked_surfaces_by_id.count(blocking_surface_id)) |
| 156 late_surfaces_by_id_.insert(blocking_surface_id); | 140 late_surfaces_by_id_.insert(blocking_surface_id); |
| 157 blocked_surfaces_from_dependency_[blocking_surface_id].erase(surface_id); | 141 blocked_surfaces_from_dependency_[blocking_surface_id].erase(surface_id); |
| 158 } | 142 } |
| 159 blocked_surface->ActivatePendingFrameForDeadline(); | 143 blocked_surface->ActivatePendingFrameForDeadline(); |
| 160 } | 144 } |
| 161 | |
| 162 frames_since_deadline_set_.reset(); | |
| 163 } | 145 } |
| 164 | 146 |
| 165 const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const { | |
| 166 return last_begin_frame_args_; | |
| 167 } | |
| 168 | |
| 169 void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {} | |
| 170 | |
| 171 void SurfaceDependencyTracker::NotifySurfaceIdAvailable( | 147 void SurfaceDependencyTracker::NotifySurfaceIdAvailable( |
| 172 const SurfaceId& surface_id) { | 148 const SurfaceId& surface_id) { |
| 173 auto it = blocked_surfaces_from_dependency_.find(surface_id); | 149 auto it = blocked_surfaces_from_dependency_.find(surface_id); |
| 174 if (it == blocked_surfaces_from_dependency_.end()) | 150 if (it == blocked_surfaces_from_dependency_.end()) |
| 175 return; | 151 return; |
| 176 | 152 |
| 177 // Unblock surfaces that depend on this |surface_id|. | 153 // Unblock surfaces that depend on this |surface_id|. |
| 178 base::flat_set<SurfaceId> blocked_surfaces_by_id(it->second); | 154 base::flat_set<SurfaceId> blocked_surfaces_by_id(it->second); |
| 179 blocked_surfaces_from_dependency_.erase(it); | 155 blocked_surfaces_from_dependency_.erase(it); |
| 180 // If there are no more blockers in the system, then we no longer need to | 156 // If there are no more blockers in the system, then we no longer need to |
| 181 // have a deadline. | 157 // have a deadline. |
| 182 if (blocked_surfaces_from_dependency_.empty()) | 158 if (blocked_surfaces_from_dependency_.empty()) |
| 183 frames_since_deadline_set_.reset(); | 159 deadline_.Cancel(); |
| 184 | 160 |
| 185 // Tell each surface about the availability of its blocker. | 161 // Tell each surface about the availability of its blocker. |
| 186 for (const SurfaceId& blocked_surface_by_id : blocked_surfaces_by_id) { | 162 for (const SurfaceId& blocked_surface_by_id : blocked_surfaces_by_id) { |
| 187 Surface* blocked_surface = | 163 Surface* blocked_surface = |
| 188 surface_manager_->GetSurfaceForId(blocked_surface_by_id); | 164 surface_manager_->GetSurfaceForId(blocked_surface_by_id); |
| 189 if (!blocked_surface) { | 165 if (!blocked_surface) { |
| 190 // A blocked surface may have been garbage collected during dependency | 166 // A blocked surface may have been garbage collected during dependency |
| 191 // resolution. | 167 // resolution. |
| 192 DCHECK(!blocked_surfaces_by_id_.count(blocked_surface_by_id)); | 168 DCHECK(!blocked_surfaces_by_id_.count(blocked_surface_by_id)); |
| 193 continue; | 169 continue; |
| 194 } | 170 } |
| 195 blocked_surface->NotifySurfaceIdAvailable(surface_id); | 171 blocked_surface->NotifySurfaceIdAvailable(surface_id); |
| 196 } | 172 } |
| 197 } | 173 } |
| 198 | 174 |
| 199 } // namespace cc | 175 } // namespace cc |
| OLD | NEW |