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

Unified Diff: cc/surfaces/surface_manager.cc

Issue 2715973003: Refactor how temporary references are stored. (Closed)
Patch Set: Rebase. 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
« no previous file with comments | « cc/surfaces/surface_manager.h ('k') | cc/surfaces/surface_manager_ref_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/surfaces/surface_manager.cc
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index 776ac2a438d38fb498c29f20135eeebf17c03dc8..8bb0cba6eb9fcdde8d4b08bb471e7c1c6d402074 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 asterisk in front of them.
+ for (auto& map_entry : temporary_references_)
+ SurfaceReferencesToStringImpl(map_entry.first, "* ", &str);
+
return str.str();
}
#endif
@@ -143,98 +143,22 @@ const SurfaceId& SurfaceManager::GetRootSurfaceId() const {
return root_surface_id_;
}
-void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id,
- const SurfaceId& child_id) {
- 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);
-}
-
-void SurfaceManager::RemoveSurfaceReference(const SurfaceId& parent_id,
- const SurfaceId& child_id) {
- 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;
- }
-
- RemoveSurfaceReferenceImpl(parent_id, child_id);
-}
-
void SurfaceManager::AddSurfaceReferences(
const std::vector<SurfaceReference>& references) {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(using_surface_references());
for (const auto& reference : references)
- AddSurfaceReference(reference.parent_id(), reference.child_id());
+ AddSurfaceReferenceImpl(reference.parent_id(), reference.child_id());
}
void SurfaceManager::RemoveSurfaceReferences(
const std::vector<SurfaceReference>& references) {
DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(using_surface_references());
for (const auto& reference : references)
- RemoveSurfaceReference(reference.parent_id(), reference.child_id());
+ RemoveSurfaceReferenceImpl(reference.parent_id(), reference.child_id());
GarbageCollectSurfaces();
}
@@ -243,7 +167,7 @@ void SurfaceManager::GarbageCollectSurfaces() {
if (surfaces_to_destroy_.empty())
return;
- SurfaceIdSet reachable_surfaces = lifetime_type_ == LifetimeType::REFERENCES
+ SurfaceIdSet reachable_surfaces = using_surface_references()
? GetLiveSurfacesForReferences()
: GetLiveSurfacesForSequences();
@@ -267,13 +191,20 @@ void SurfaceManager::GarbageCollectSurfaces() {
}
SurfaceManager::SurfaceIdSet SurfaceManager::GetLiveSurfacesForReferences() {
- DCHECK_EQ(lifetime_type_, LifetimeType::REFERENCES);
+ DCHECK(using_surface_references());
SurfaceIdSet reachable_surfaces;
// 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 also reachable.
+ 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 +272,27 @@ 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) {
+ 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 << " to " << child_id;
+ return;
+ }
+
parent_to_child_refs_[parent_id].erase(child_id);
child_to_parent_refs_[child_id].erase(parent_id);
}
@@ -369,6 +315,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) {
@@ -586,11 +576,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_)
@@ -607,21 +594,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;
« no previous file with comments | « cc/surfaces/surface_manager.h ('k') | cc/surfaces/surface_manager_ref_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698