| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_manager.h" | 5 #include "cc/surfaces/surface_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <queue> | 10 #include <queue> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "cc/surfaces/direct_surface_reference_factory.h" | 14 #include "cc/surfaces/direct_surface_reference_factory.h" |
| 15 #include "cc/surfaces/surface.h" | 15 #include "cc/surfaces/surface.h" |
| 16 #include "cc/surfaces/surface_factory_client.h" | 16 #include "cc/surfaces/surface_factory_client.h" |
| 17 #include "cc/surfaces/surface_id_allocator.h" | 17 #include "cc/surfaces/surface_id_allocator.h" |
| 18 #include "cc/surfaces/surface_info.h" |
| 18 | 19 |
| 19 #if DCHECK_IS_ON() | 20 #if DCHECK_IS_ON() |
| 20 #include <sstream> | 21 #include <sstream> |
| 21 #endif | 22 #endif |
| 22 | 23 |
| 23 namespace cc { | 24 namespace cc { |
| 24 | 25 |
| 25 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping() | 26 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping() |
| 26 : client(nullptr), source(nullptr) {} | 27 : client(nullptr), source(nullptr) {} |
| 27 | 28 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 38 root_surface_id_(FrameSinkId(0u, 0u), | 39 root_surface_id_(FrameSinkId(0u, 0u), |
| 39 LocalFrameId(1u, base::UnguessableToken::Create())), | 40 LocalFrameId(1u, base::UnguessableToken::Create())), |
| 40 weak_factory_(this) { | 41 weak_factory_(this) { |
| 41 thread_checker_.DetachFromThread(); | 42 thread_checker_.DetachFromThread(); |
| 42 reference_factory_ = | 43 reference_factory_ = |
| 43 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); | 44 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); |
| 44 } | 45 } |
| 45 | 46 |
| 46 SurfaceManager::~SurfaceManager() { | 47 SurfaceManager::~SurfaceManager() { |
| 47 DCHECK(thread_checker_.CalledOnValidThread()); | 48 DCHECK(thread_checker_.CalledOnValidThread()); |
| 49 |
| 50 if (lifetime_type_ == LifetimeType::REFERENCES) { |
| 51 // Remove all temporary references on shutdown. |
| 52 for (const auto& map_entry : temp_references_) { |
| 53 const FrameSinkId& frame_sink_id = map_entry.first; |
| 54 for (const auto& local_frame_id : map_entry.second) { |
| 55 RemoveSurfaceReferenceImpl(GetRootSurfaceId(), |
| 56 SurfaceId(frame_sink_id, local_frame_id)); |
| 57 } |
| 58 } |
| 59 GarbageCollectSurfaces(); |
| 60 } |
| 61 |
| 48 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); | 62 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); |
| 49 it != surfaces_to_destroy_.end(); | 63 it != surfaces_to_destroy_.end(); |
| 50 ++it) { | 64 ++it) { |
| 51 DeregisterSurface((*it)->surface_id()); | 65 DeregisterSurface((*it)->surface_id()); |
| 52 } | 66 } |
| 53 surfaces_to_destroy_.clear(); | 67 surfaces_to_destroy_.clear(); |
| 54 | 68 |
| 55 // All hierarchies, sources, and surface factory clients should be | 69 // All hierarchies, sources, and surface factory clients should be |
| 56 // unregistered prior to SurfaceManager destruction. | 70 // unregistered prior to SurfaceManager destruction. |
| 57 DCHECK_EQ(frame_sink_source_map_.size(), 0u); | 71 DCHECK_EQ(frame_sink_source_map_.size(), 0u); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 return root_surface_id_; | 134 return root_surface_id_; |
| 121 } | 135 } |
| 122 | 136 |
| 123 void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id, | 137 void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id, |
| 124 const SurfaceId& child_id) { | 138 const SurfaceId& child_id) { |
| 125 DCHECK(thread_checker_.CalledOnValidThread()); | 139 DCHECK(thread_checker_.CalledOnValidThread()); |
| 126 | 140 |
| 127 // Check some conditions that should never happen. We don't want to crash on | 141 // Check some conditions that should never happen. We don't want to crash on |
| 128 // bad input from a compromised client so just return early. | 142 // bad input from a compromised client so just return early. |
| 129 if (parent_id == child_id) { | 143 if (parent_id == child_id) { |
| 130 LOG(ERROR) << "Cannot add self reference for " << parent_id.ToString(); | 144 DLOG(ERROR) << "Cannot add self reference for " << parent_id.ToString(); |
| 131 return; | 145 return; |
| 132 } | 146 } |
| 133 if (parent_id != root_surface_id_ && surface_map_.count(parent_id) == 0) { | 147 if (parent_id != root_surface_id_ && surface_map_.count(parent_id) == 0) { |
| 134 LOG(ERROR) << "No surface in map for " << parent_id.ToString(); | 148 DLOG(ERROR) << "No surface in map for " << parent_id.ToString(); |
| 135 return; | 149 return; |
| 136 } | 150 } |
| 137 if (surface_map_.count(child_id) == 0) { | 151 if (surface_map_.count(child_id) == 0) { |
| 138 LOG(ERROR) << "No surface in map for " << child_id.ToString(); | 152 DLOG(ERROR) << "No surface in map for " << child_id.ToString(); |
| 139 return; | 153 return; |
| 140 } | 154 } |
| 141 | 155 |
| 156 // There could be a temporary reference to |child_id| which we should now |
| 157 // remove because a real reference is being added to it. To find out whether |
| 158 // or not a temporary reference exists, we need to first look up the |
| 159 // FrameSinkId of |child_id| in |temp_references_|, which returns a vector of |
| 160 // LocalFrameIds, and then search for the LocalFrameId of |child_id| in the |
| 161 // said vector. If there is no temporary reference, we can immediately add the |
| 162 // reference from |parent_id| and return. |
| 163 auto refs_iter = temp_references_.find(child_id.frame_sink_id()); |
| 164 if (refs_iter == temp_references_.end()) { |
| 165 AddSurfaceReferenceImpl(parent_id, child_id); |
| 166 return; |
| 167 } |
| 168 std::vector<LocalFrameId>& refs = refs_iter->second; |
| 169 auto temp_ref_iter = |
| 170 std::find(refs.begin(), refs.end(), child_id.local_frame_id()); |
| 171 if (temp_ref_iter == refs.end()) { |
| 172 AddSurfaceReferenceImpl(parent_id, child_id); |
| 173 return; |
| 174 } |
| 175 |
| 176 // Temporary references are implemented by holding a reference from the top |
| 177 // level root to the child. If |parent_id| is the top level root, we do |
| 178 // nothing because the reference already exists. Otherwise, remove the |
| 179 // temporary reference and add the reference. |
| 180 if (parent_id != GetRootSurfaceId()) { |
| 181 AddSurfaceReferenceImpl(parent_id, child_id); |
| 182 RemoveSurfaceReference(GetRootSurfaceId(), child_id); |
| 183 } |
| 184 |
| 185 // Remove temporary references for surfaces with the same FrameSinkId that |
| 186 // were created before |child_id|. The earlier surfaces were never embedded in |
| 187 // the parent and the parent is embedding a later surface, so we know the |
| 188 // parent doesn't need them anymore. |
| 189 for (auto iter = refs.begin(); iter != temp_ref_iter; ++iter) { |
| 190 SurfaceId id = SurfaceId(child_id.frame_sink_id(), *iter); |
| 191 RemoveSurfaceReference(GetRootSurfaceId(), id); |
| 192 } |
| 193 |
| 194 // Remove markers for temporary references up to |child_id|, as the temporary |
| 195 // references they correspond to were removed above. If |temp_ref_iter| points |
| 196 // at the last element in |refs| then we are removing all temporary references |
| 197 // for the FrameSinkId and can remove the map entry entirely. |
| 198 if (++temp_ref_iter == refs.end()) |
| 199 temp_references_.erase(child_id.frame_sink_id()); |
| 200 else |
| 201 refs.erase(refs.begin(), temp_ref_iter); |
| 202 } |
| 203 |
| 204 void SurfaceManager::AddSurfaceReferenceImpl(const SurfaceId& parent_id, |
| 205 const SurfaceId& child_id) { |
| 142 parent_to_child_refs_[parent_id].insert(child_id); | 206 parent_to_child_refs_[parent_id].insert(child_id); |
| 143 child_to_parent_refs_[child_id].insert(parent_id); | 207 child_to_parent_refs_[child_id].insert(parent_id); |
| 144 } | 208 } |
| 145 | 209 |
| 146 void SurfaceManager::RemoveSurfaceReference(const SurfaceId& parent_id, | 210 void SurfaceManager::RemoveSurfaceReference(const SurfaceId& parent_id, |
| 147 const SurfaceId& child_id) { | 211 const SurfaceId& child_id) { |
| 148 DCHECK(thread_checker_.CalledOnValidThread()); | 212 DCHECK(thread_checker_.CalledOnValidThread()); |
| 149 | 213 |
| 150 // Check if we have the reference that is requested to be removed. We don't | 214 // Check if we have the reference that is requested to be removed. We don't |
| 151 // want to crash on bad input from a compromised client so just return early. | 215 // want to crash on bad input from a compromised client so just return early. |
| 152 if (parent_to_child_refs_.count(parent_id) == 0 || | 216 if (parent_to_child_refs_.count(parent_id) == 0 || |
| 153 parent_to_child_refs_[parent_id].count(child_id) == 0) { | 217 parent_to_child_refs_[parent_id].count(child_id) == 0) { |
| 154 LOG(ERROR) << "No reference from " << parent_id.ToString() << " to " | 218 DLOG(ERROR) << "No reference from " << parent_id.ToString() << " to " |
| 155 << child_id.ToString(); | 219 << child_id.ToString(); |
| 156 return; | 220 return; |
| 157 } | 221 } |
| 158 | 222 |
| 159 RemoveSurfaceReferenceImpl(parent_id, child_id); | 223 RemoveSurfaceReferenceImpl(parent_id, child_id); |
| 160 GarbageCollectSurfaces(); | 224 GarbageCollectSurfaces(); |
| 161 } | 225 } |
| 162 | 226 |
| 163 size_t SurfaceManager::GetSurfaceReferenceCount( | 227 size_t SurfaceManager::GetSurfaceReferenceCount( |
| 164 const SurfaceId& surface_id) const { | 228 const SurfaceId& surface_id) const { |
| 165 auto iter = child_to_parent_refs_.find(surface_id); | 229 auto iter = child_to_parent_refs_.find(surface_id); |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id) { | 573 bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id) { |
| 510 CHECK(thread_checker_.CalledOnValidThread()); | 574 CHECK(thread_checker_.CalledOnValidThread()); |
| 511 bool changed = false; | 575 bool changed = false; |
| 512 for (auto& observer : observer_list_) | 576 for (auto& observer : observer_list_) |
| 513 observer.OnSurfaceDamaged(surface_id, &changed); | 577 observer.OnSurfaceDamaged(surface_id, &changed); |
| 514 return changed; | 578 return changed; |
| 515 } | 579 } |
| 516 | 580 |
| 517 void SurfaceManager::SurfaceCreated(const SurfaceInfo& surface_info) { | 581 void SurfaceManager::SurfaceCreated(const SurfaceInfo& surface_info) { |
| 518 CHECK(thread_checker_.CalledOnValidThread()); | 582 CHECK(thread_checker_.CalledOnValidThread()); |
| 583 |
| 584 if (lifetime_type_ == LifetimeType::REFERENCES) { |
| 585 // We can get into a situation where multiple CompositorFrames arrive for a |
| 586 // CompositorFrameSink before the client can add any references for the |
| 587 // frame. When the second frame with a new size arrives, the first will be |
| 588 // destroyed in SurfaceFactory and then if there are no references it will |
| 589 // be deleted during surface GC. A temporary reference, removed when a real |
| 590 // reference is received, is added to prevent this from happening. |
| 591 AddSurfaceReferenceImpl(GetRootSurfaceId(), surface_info.id()); |
| 592 temp_references_[surface_info.id().frame_sink_id()].push_back( |
| 593 surface_info.id().local_frame_id()); |
| 594 } |
| 595 |
| 519 for (auto& observer : observer_list_) | 596 for (auto& observer : observer_list_) |
| 520 observer.OnSurfaceCreated(surface_info); | 597 observer.OnSurfaceCreated(surface_info); |
| 521 } | 598 } |
| 522 | 599 |
| 523 #if DCHECK_IS_ON() | 600 #if DCHECK_IS_ON() |
| 524 void SurfaceManager::SurfaceReferencesToStringImpl(const SurfaceId& surface_id, | 601 void SurfaceManager::SurfaceReferencesToStringImpl(const SurfaceId& surface_id, |
| 525 std::string indent, | 602 std::string indent, |
| 526 std::stringstream* str) { | 603 std::stringstream* str) { |
| 527 *str << indent; | 604 *str << indent; |
| 528 | 605 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 549 std::vector<SurfaceId> children(iter->second.begin(), iter->second.end()); | 626 std::vector<SurfaceId> children(iter->second.begin(), iter->second.end()); |
| 550 std::sort(children.begin(), children.end()); | 627 std::sort(children.begin(), children.end()); |
| 551 | 628 |
| 552 for (const SurfaceId& child_id : children) | 629 for (const SurfaceId& child_id : children) |
| 553 SurfaceReferencesToStringImpl(child_id, indent + " ", str); | 630 SurfaceReferencesToStringImpl(child_id, indent + " ", str); |
| 554 } | 631 } |
| 555 } | 632 } |
| 556 #endif // DCHECK_IS_ON() | 633 #endif // DCHECK_IS_ON() |
| 557 | 634 |
| 558 } // namespace cc | 635 } // namespace cc |
| OLD | NEW |