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

Unified Diff: cc/surfaces/surface_manager.cc

Issue 2716553004: Add temporary reference ownership to SurfaceManager. (Closed)
Patch Set: Cleanup. Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: cc/surfaces/surface_manager.cc
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index 981d7d74c095d66bcab633460cce9fe3562c159b..2dd5997f6e4000d0dd10da77c7fa40721a66a584 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -47,15 +47,11 @@ SurfaceManager::SurfaceManager(LifetimeType lifetime_type)
SurfaceManager::~SurfaceManager() {
DCHECK(thread_checker_.CalledOnValidThread());
- if (lifetime_type_ == LifetimeType::REFERENCES) {
+ if (using_surface_references()) {
// Remove all temporary references on shutdown.
- for (const auto& map_entry : temp_references_) {
- const FrameSinkId& frame_sink_id = map_entry.first;
- for (const auto& local_surface_id : map_entry.second) {
- RemoveSurfaceReferenceImpl(GetRootSurfaceId(),
- SurfaceId(frame_sink_id, local_surface_id));
- }
- }
+ temporary_references_.clear();
+ temporary_reference_ranges_.clear();
+
GarbageCollectSurfaces();
}
@@ -76,6 +72,10 @@ SurfaceManager::~SurfaceManager() {
std::string SurfaceManager::SurfaceReferencesToString() {
std::stringstream str;
SurfaceReferencesToStringImpl(root_surface_id_, "", &str);
+ // Temporary references will have an asterix in front of them.
Fady Samuel 2017/02/24 18:10:15 s/asterix/asterisk
kylechar 2017/02/24 19:57:29 Done.
+ for (auto& map_entry : temporary_references_)
+ SurfaceReferencesToStringImpl(map_entry.first, "* ", &str);
+
return str.str();
}
#endif
@@ -136,6 +136,20 @@ void SurfaceManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) {
void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) {
valid_frame_sink_ids_.erase(frame_sink_id);
+
+ if (using_surface_references()) {
+ // Remove any temporary references owned by |frame_sink_id|.
+ std::vector<SurfaceId> temp_refs_to_clear;
+ for (auto& map_entry : temporary_references_) {
+ base::Optional<FrameSinkId>& owner = map_entry.second;
+ if (owner.has_value() && owner.value() == frame_sink_id)
+ temp_refs_to_clear.push_back(map_entry.first);
+ }
+
+ for (auto& surface_id : temp_refs_to_clear)
+ RemoveTemporaryReference(surface_id, false);
+ }
+
GarbageCollectSurfaces();
}
@@ -143,107 +157,53 @@ const SurfaceId& SurfaceManager::GetRootSurfaceId() const {
return root_surface_id_;
}
-void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id,
- const SurfaceId& child_id) {
+void SurfaceManager::AddSurfaceReferences(
+ const std::vector<SurfaceReference>& references) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES);
- // Check some conditions that should never happen. We don't want to crash on
- // bad input from a compromised client so just return early.
- if (parent_id.frame_sink_id() == child_id.frame_sink_id()) {
- DLOG(ERROR) << "Cannot add self reference from " << parent_id << " to "
- << child_id;
- return;
- }
-
- // There could be a temporary reference to |child_id| which we should now
- // remove because a real reference is being added to it. To find out whether
- // or not a temporary reference exists, we need to first look up the
- // FrameSinkId of |child_id| in |temp_references_|, which returns a vector of
- // LocalSurfaceIds, and then search for the LocalSurfaceId of |child_id| in
- // the said vector. If there is no temporary reference, we can immediately add
- // the reference from |parent_id| and return.
- auto refs_iter = temp_references_.find(child_id.frame_sink_id());
- if (refs_iter == temp_references_.end()) {
- AddSurfaceReferenceImpl(parent_id, child_id);
- return;
- }
- std::vector<LocalSurfaceId>& refs = refs_iter->second;
- auto temp_ref_iter =
- std::find(refs.begin(), refs.end(), child_id.local_surface_id());
- if (temp_ref_iter == refs.end()) {
- AddSurfaceReferenceImpl(parent_id, child_id);
- return;
- }
-
- // Temporary references are implemented by holding a reference from the top
- // level root to the child. If |parent_id| is the top level root, we do
- // nothing because the reference already exists. Otherwise, remove the
- // temporary reference and add the reference.
- if (parent_id != GetRootSurfaceId()) {
- AddSurfaceReferenceImpl(parent_id, child_id);
- RemoveSurfaceReference(GetRootSurfaceId(), child_id);
- }
-
- // Remove temporary references for surfaces with the same FrameSinkId that
- // were created before |child_id|. The earlier surfaces were never embedded in
- // the parent and the parent is embedding a later surface, so we know the
- // parent doesn't need them anymore.
- for (auto iter = refs.begin(); iter != temp_ref_iter; ++iter) {
- SurfaceId id = SurfaceId(child_id.frame_sink_id(), *iter);
- RemoveSurfaceReference(GetRootSurfaceId(), id);
- }
-
- // Remove markers for temporary references up to |child_id|, as the temporary
- // references they correspond to were removed above. If |temp_ref_iter| points
- // at the last element in |refs| then we are removing all temporary references
- // for the FrameSinkId and can remove the map entry entirely.
- if (++temp_ref_iter == refs.end())
- temp_references_.erase(child_id.frame_sink_id());
- else
- refs.erase(refs.begin(), temp_ref_iter);
+ for (const auto& reference : references)
+ AddSurfaceReferenceImpl(reference.parent_id(), reference.child_id());
}
-void SurfaceManager::RemoveSurfaceReference(const SurfaceId& parent_id,
- const SurfaceId& child_id) {
+void SurfaceManager::RemoveSurfaceReferences(
+ const std::vector<SurfaceReference>& references) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES);
- // Check if we have the reference that is requested to be removed. We don't
- // want to crash on bad input from a compromised client so just return early.
- if (parent_to_child_refs_.count(parent_id) == 0 ||
- parent_to_child_refs_[parent_id].count(child_id) == 0) {
- DLOG(ERROR) << "No reference from " << parent_id.ToString() << " to "
- << child_id.ToString();
- return;
- }
+ for (const auto& reference : references)
+ RemoveSurfaceReferenceImpl(reference.parent_id(), reference.child_id());
- RemoveSurfaceReferenceImpl(parent_id, child_id);
+ GarbageCollectSurfaces();
}
-void SurfaceManager::AddSurfaceReferences(
- const std::vector<SurfaceReference>& references) {
+void SurfaceManager::AssignTemporaryReference(
+ const SurfaceId& surface_id,
+ const FrameSinkId& frame_sink_id) {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES);
- for (const auto& reference : references)
- AddSurfaceReference(reference.parent_id(), reference.child_id());
+ if (!HasTemporaryReference(surface_id))
+ return;
+
+ temporary_references_[surface_id] = frame_sink_id;
}
-void SurfaceManager::RemoveSurfaceReferences(
- const std::vector<SurfaceReference>& references) {
+void SurfaceManager::DropTemporaryReference(const SurfaceId& surface_id) {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES);
- for (const auto& reference : references)
- RemoveSurfaceReference(reference.parent_id(), reference.child_id());
+ if (!HasTemporaryReference(surface_id))
+ return;
- GarbageCollectSurfaces();
+ RemoveTemporaryReference(surface_id, false);
}
void SurfaceManager::GarbageCollectSurfaces() {
if (surfaces_to_destroy_.empty())
return;
- SurfaceIdSet reachable_surfaces = lifetime_type_ == LifetimeType::REFERENCES
+ SurfaceIdSet reachable_surfaces = using_surface_references()
? GetLiveSurfacesForReferences()
: GetLiveSurfacesForSequences();
@@ -274,6 +234,13 @@ SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() {
// Walk down from the root and mark each SurfaceId we encounter as reachable.
std::queue<SurfaceId> surface_queue;
surface_queue.push(root_surface_id_);
+
+ // All temporary references are reachable too.
+ for (auto& map_entry : temporary_references_) {
+ reachable_surfaces.insert(map_entry.first);
+ surface_queue.push(map_entry.first);
+ }
+
while (!surface_queue.empty()) {
const SurfaceId& surface_id = surface_queue.front();
auto iter = parent_to_child_refs_.find(surface_id);
@@ -341,12 +308,30 @@ SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForSequences() {
void SurfaceManager::AddSurfaceReferenceImpl(const SurfaceId& parent_id,
const SurfaceId& child_id) {
+ if (parent_id.frame_sink_id() == child_id.frame_sink_id()) {
+ DLOG(ERROR) << "Cannot add self reference from " << parent_id << " to "
+ << child_id;
+ return;
+ }
+
parent_to_child_refs_[parent_id].insert(child_id);
child_to_parent_refs_[child_id].insert(parent_id);
+
+ if (HasTemporaryReference(child_id))
+ RemoveTemporaryReference(child_id, true);
}
void SurfaceManager::RemoveSurfaceReferenceImpl(const SurfaceId& parent_id,
const SurfaceId& child_id) {
+ // Check if we have the reference that is requested to be removed. We don't
+ // want to crash on bad input from a compromised client so just return early.
+ if (parent_to_child_refs_.count(parent_id) == 0 ||
+ parent_to_child_refs_[parent_id].count(child_id) == 0) {
+ DLOG(ERROR) << "No reference from " << parent_id.ToString() << " to "
+ << child_id.ToString();
+ return;
+ }
+
parent_to_child_refs_[parent_id].erase(child_id);
child_to_parent_refs_[child_id].erase(parent_id);
}
@@ -369,6 +354,50 @@ void SurfaceManager::RemoveAllSurfaceReferences(const SurfaceId& surface_id) {
}
}
+bool SurfaceManager::HasTemporaryReference(const SurfaceId& surface_id) const {
+ return temporary_references_.count(surface_id) != 0;
+}
+
+void SurfaceManager::AddTemporaryReference(const SurfaceId& surface_id) {
+ DCHECK(!HasTemporaryReference(surface_id));
+
+ // Add an entry to |temporary_references_| with no owner for the temporary
+ // reference. Also add a range tracking entry so we know the order that
+ // surfaces were created for the FrameSinkId.
+ temporary_references_[surface_id] = base::Optional<FrameSinkId>();
+ temporary_reference_ranges_[surface_id.frame_sink_id()].push_back(
+ surface_id.local_surface_id());
+}
+
+void SurfaceManager::RemoveTemporaryReference(const SurfaceId& surface_id,
+ bool remove_range) {
+ DCHECK(HasTemporaryReference(surface_id));
+
+ const FrameSinkId& frame_sink_id = surface_id.frame_sink_id();
+ std::vector<LocalSurfaceId>& frame_sink_temp_refs =
+ temporary_reference_ranges_[frame_sink_id];
+
+ // Find the iterator to the range tracking entry for |surface_id|. Use that
+ // iterator and |remove_range| to find the right begin and end iterators for
+ // the temporary references we want to remove.
+ auto surface_id_iter =
+ std::find(frame_sink_temp_refs.begin(), frame_sink_temp_refs.end(),
+ surface_id.local_surface_id());
+ auto begin_iter =
+ remove_range ? frame_sink_temp_refs.begin() : surface_id_iter;
+ auto end_iter = surface_id_iter + 1;
+
+ // Remove temporary references and range tracking information.
+ for (auto iter = begin_iter; iter != end_iter; ++iter)
+ temporary_references_.erase(SurfaceId(frame_sink_id, *iter));
+ frame_sink_temp_refs.erase(begin_iter, end_iter);
+
+ // If last temporary reference is removed for |frame_sink_id| then cleanup
+ // range tracking map entry.
+ if (frame_sink_temp_refs.empty())
+ temporary_reference_ranges_.erase(frame_sink_id);
+}
+
void SurfaceManager::RegisterSurfaceFactoryClient(
const FrameSinkId& frame_sink_id,
SurfaceFactoryClient* client) {
@@ -589,11 +618,8 @@ void SurfaceManager::SurfaceCreated(const SurfaceInfo& surface_info) {
// use array notation into maps in tests (see https://crbug.com/691115).
bool has_real_reference =
it != child_to_parent_refs_.end() && !it->second.empty();
- if (!has_real_reference) {
- AddSurfaceReferenceImpl(GetRootSurfaceId(), surface_info.id());
- temp_references_[surface_info.id().frame_sink_id()].push_back(
- surface_info.id().local_surface_id());
- }
+ if (!has_real_reference)
+ AddTemporaryReference(surface_info.id());
}
for (auto& observer : observer_list_)
@@ -610,21 +636,24 @@ void SurfaceManager::SurfaceReferencesToStringImpl(const SurfaceId& surface_id,
Surface* surface = GetSurfaceForId(surface_id);
if (surface) {
*str << surface->surface_id().ToString();
- *str << (surface->destroyed() ? " destroyed " : " live ");
+ *str << (surface->destroyed() ? " destroyed" : " live");
if (surface->HasPendingFrame()) {
// This provides the surface size from the root render pass.
const CompositorFrame& frame = surface->GetPendingFrame();
- *str << "pending "
- << frame.render_pass_list.back()->output_rect.size().ToString()
- << " ";
+ if (!frame.render_pass_list.empty()) {
+ *str << " pending "
+ << frame.render_pass_list.back()->output_rect.size().ToString();
+ }
}
if (surface->HasActiveFrame()) {
// This provides the surface size from the root render pass.
const CompositorFrame& frame = surface->GetActiveFrame();
- *str << "active "
- << frame.render_pass_list.back()->output_rect.size().ToString();
+ if (!frame.render_pass_list.empty()) {
+ *str << " active "
+ << frame.render_pass_list.back()->output_rect.size().ToString();
+ }
}
} else {
*str << surface_id;

Powered by Google App Engine
This is Rietveld 408576698