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

Side by Side Diff: cc/surfaces/surface_manager.cc

Issue 2638833002: Moving temporary reference logic to SurfaceManager (Closed)
Patch Set: c Created 3 years, 11 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« 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