| 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;
|
|
|