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

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 namespace cc { 20 namespace cc {
20 21
21 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping() 22 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping()
22 : client(nullptr), source(nullptr) {} 23 : client(nullptr), source(nullptr) {}
23 24
24 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping( 25 SurfaceManager::FrameSinkSourceMapping::FrameSinkSourceMapping(
25 const FrameSinkSourceMapping& other) = default; 26 const FrameSinkSourceMapping& other) = default;
26 27
27 SurfaceManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() { 28 SurfaceManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() {
28 DCHECK(is_empty()) << "client: " << client 29 DCHECK(is_empty()) << "client: " << client
29 << ", children: " << children.size(); 30 << ", children: " << children.size();
30 } 31 }
31 32
32 SurfaceManager::SurfaceManager(LifetimeType lifetime_type) 33 SurfaceManager::SurfaceManager(LifetimeType lifetime_type)
33 : lifetime_type_(lifetime_type), 34 : lifetime_type_(lifetime_type),
34 root_surface_id_(FrameSinkId(0u, 0u), 35 root_surface_id_(FrameSinkId(0u, 0u),
35 LocalFrameId(1u, base::UnguessableToken::Create())), 36 LocalFrameId(1u, base::UnguessableToken::Create())),
36 weak_factory_(this) { 37 weak_factory_(this) {
37 thread_checker_.DetachFromThread(); 38 thread_checker_.DetachFromThread();
38 reference_factory_ = 39 reference_factory_ =
39 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr()); 40 new DirectSurfaceReferenceFactory(weak_factory_.GetWeakPtr());
40 } 41 }
41 42
42 SurfaceManager::~SurfaceManager() { 43 SurfaceManager::~SurfaceManager() {
43 DCHECK(thread_checker_.CalledOnValidThread()); 44 DCHECK(thread_checker_.CalledOnValidThread());
45
46 if (lifetime_type_ == LifetimeType::REFERENCES) {
47 // Remove all temporary references on shutdown.
48 for (const auto& map_entry : temp_references_) {
49 const FrameSinkId& frame_sink_id = map_entry.first;
50 for (const auto& local_frame_id : map_entry.second) {
51 RemoveSurfaceReferenceImpl(GetRootSurfaceId(),
52 SurfaceId(frame_sink_id, local_frame_id));
53 }
54 }
55 GarbageCollectSurfaces();
56 }
57
44 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); 58 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin();
45 it != surfaces_to_destroy_.end(); 59 it != surfaces_to_destroy_.end();
46 ++it) { 60 ++it) {
47 DeregisterSurface((*it)->surface_id()); 61 DeregisterSurface((*it)->surface_id());
48 } 62 }
49 surfaces_to_destroy_.clear(); 63 surfaces_to_destroy_.clear();
50 64
51 // All hierarchies, sources, and surface factory clients should be 65 // All hierarchies, sources, and surface factory clients should be
52 // unregistered prior to SurfaceManager destruction. 66 // unregistered prior to SurfaceManager destruction.
53 DCHECK_EQ(frame_sink_source_map_.size(), 0u); 67 DCHECK_EQ(frame_sink_source_map_.size(), 0u);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 return root_surface_id_; 122 return root_surface_id_;
109 } 123 }
110 124
111 void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id, 125 void SurfaceManager::AddSurfaceReference(const SurfaceId& parent_id,
112 const SurfaceId& child_id) { 126 const SurfaceId& child_id) {
113 DCHECK(thread_checker_.CalledOnValidThread()); 127 DCHECK(thread_checker_.CalledOnValidThread());
114 128
115 // Check some conditions that should never happen. We don't want to crash on 129 // Check some conditions that should never happen. We don't want to crash on
116 // bad input from a compromised client so just return early. 130 // bad input from a compromised client so just return early.
117 if (parent_id == child_id) { 131 if (parent_id == child_id) {
118 LOG(ERROR) << "Cannot add self reference for " << parent_id.ToString(); 132 DLOG(ERROR) << "Cannot add self reference for " << parent_id.ToString();
119 return; 133 return;
120 } 134 }
121 if (parent_id != root_surface_id_ && surface_map_.count(parent_id) == 0) { 135 if (parent_id != root_surface_id_ && surface_map_.count(parent_id) == 0) {
122 LOG(ERROR) << "No surface in map for " << parent_id.ToString(); 136 DLOG(ERROR) << "No surface in map for " << parent_id.ToString();
123 return; 137 return;
124 } 138 }
125 if (surface_map_.count(child_id) == 0) { 139 if (surface_map_.count(child_id) == 0) {
126 LOG(ERROR) << "No surface in map for " << child_id.ToString(); 140 DLOG(ERROR) << "No surface in map for " << child_id.ToString();
127 return; 141 return;
128 } 142 }
129 143
144 // There could be a temporary reference to |child_id| which we should now
145 // remove because a real reference is being added to it. To find out whether
146 // or not a temporary reference exists, we need to first look up the
147 // FrameSinkId of |child_id| in |temp_references_|, which returns a vector of
148 // LocalFrameIds, and then search for the LocalFrameId of |child_id| in the
149 // said vector. If there is no temporary reference, we can immediately add the
150 // reference from |parent_id| and return.
151 auto refs_iter = temp_references_.find(child_id.frame_sink_id());
152 if (refs_iter == temp_references_.end()) {
153 AddSurfaceReferenceImpl(parent_id, child_id);
154 return;
155 }
156 std::vector<LocalFrameId>& refs = refs_iter->second;
157 auto temp_ref_iter =
158 std::find(refs.begin(), refs.end(), child_id.local_frame_id());
159 if (temp_ref_iter == refs.end()) {
160 AddSurfaceReferenceImpl(parent_id, child_id);
161 return;
162 }
163
164 // Temporary references are implemented by holding a reference from the top
165 // level root to the child. If |parent_id| is the top level root, we do
166 // nothing because the reference already exists.
danakj 2017/01/18 19:53:11 nit: don't linebreak after a period
Saman Sami 2017/01/18 19:55:43 Done.
167 // Otherwise remove the temporary reference and add the reference.
168 if (parent_id != GetRootSurfaceId()) {
169 AddSurfaceReferenceImpl(parent_id, child_id);
170 RemoveSurfaceReference(GetRootSurfaceId(), child_id);
171 }
172
173 // Remove temporary references for surfaces with the same FrameSinkId that
174 // were created before |child_id|. The earlier surfaces were never embedded in
175 // the parent and the parent is embedding a later surface, so we know the
176 // parent doesn't need them anymore.
177 for (auto iter = refs.begin(); iter != temp_ref_iter; ++iter) {
178 SurfaceId id = SurfaceId(child_id.frame_sink_id(), *iter);
179 RemoveSurfaceReference(GetRootSurfaceId(), id);
180 }
181
182 // Remove markers for temporary references up to |child_id|, as the temporary
183 // references they correspond to were removed above. If |temp_ref_iter| points
184 // at the last element in |refs| then we are removing all temporary references
185 // for the FrameSinkId and can remove the map entry entirely.
186 if (++temp_ref_iter == refs.end())
187 temp_references_.erase(child_id.frame_sink_id());
188 else
189 refs.erase(refs.begin(), temp_ref_iter);
190 }
191
192 void SurfaceManager::AddSurfaceReferenceImpl(const SurfaceId& parent_id,
193 const SurfaceId& child_id) {
130 parent_to_child_refs_[parent_id].insert(child_id); 194 parent_to_child_refs_[parent_id].insert(child_id);
131 child_to_parent_refs_[child_id].insert(parent_id); 195 child_to_parent_refs_[child_id].insert(parent_id);
132 } 196 }
133 197
134 void SurfaceManager::RemoveSurfaceReference(const SurfaceId& parent_id, 198 void SurfaceManager::RemoveSurfaceReference(const SurfaceId& parent_id,
135 const SurfaceId& child_id) { 199 const SurfaceId& child_id) {
136 DCHECK(thread_checker_.CalledOnValidThread()); 200 DCHECK(thread_checker_.CalledOnValidThread());
137 201
138 // Check if we have the reference that is requested to be removed. We don't 202 // Check if we have the reference that is requested to be removed. We don't
139 // want to crash on bad input from a compromised client so just return early. 203 // want to crash on bad input from a compromised client so just return early.
140 if (parent_to_child_refs_.count(parent_id) == 0 || 204 if (parent_to_child_refs_.count(parent_id) == 0 ||
141 parent_to_child_refs_[parent_id].count(child_id) == 0) { 205 parent_to_child_refs_[parent_id].count(child_id) == 0) {
142 LOG(ERROR) << "No reference from " << parent_id.ToString() << " to " 206 DLOG(ERROR) << "No reference from " << parent_id.ToString() << " to "
143 << child_id.ToString(); 207 << child_id.ToString();
144 return; 208 return;
145 } 209 }
146 210
147 RemoveSurfaceReferenceImpl(parent_id, child_id); 211 RemoveSurfaceReferenceImpl(parent_id, child_id);
148 GarbageCollectSurfaces(); 212 GarbageCollectSurfaces();
149 } 213 }
150 214
151 size_t SurfaceManager::GetSurfaceReferenceCount( 215 size_t SurfaceManager::GetSurfaceReferenceCount(
152 const SurfaceId& surface_id) const { 216 const SurfaceId& surface_id) const {
153 auto iter = child_to_parent_refs_.find(surface_id); 217 auto iter = child_to_parent_refs_.find(surface_id);
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id) { 561 bool SurfaceManager::SurfaceModified(const SurfaceId& surface_id) {
498 CHECK(thread_checker_.CalledOnValidThread()); 562 CHECK(thread_checker_.CalledOnValidThread());
499 bool changed = false; 563 bool changed = false;
500 for (auto& observer : observer_list_) 564 for (auto& observer : observer_list_)
501 observer.OnSurfaceDamaged(surface_id, &changed); 565 observer.OnSurfaceDamaged(surface_id, &changed);
502 return changed; 566 return changed;
503 } 567 }
504 568
505 void SurfaceManager::SurfaceCreated(const SurfaceInfo& surface_info) { 569 void SurfaceManager::SurfaceCreated(const SurfaceInfo& surface_info) {
506 CHECK(thread_checker_.CalledOnValidThread()); 570 CHECK(thread_checker_.CalledOnValidThread());
571
572 if (lifetime_type_ == LifetimeType::REFERENCES) {
573 // We can get into a situation where multiple CompositorFrames arrive for a
574 // CompositorFrameSink before the client can add any references for the
575 // frame. When the second frame with a new size arrives, the first will be
576 // destroyed in SurfaceFactory and then if there are no references it will
577 // be deleted during surface GC. A temporary reference, removed when a real
578 // reference is received, is added to prevent this from happening.
579 AddSurfaceReferenceImpl(GetRootSurfaceId(), surface_info.id());
580 temp_references_[surface_info.id().frame_sink_id()].push_back(
581 surface_info.id().local_frame_id());
582 }
583
507 for (auto& observer : observer_list_) 584 for (auto& observer : observer_list_)
508 observer.OnSurfaceCreated(surface_info); 585 observer.OnSurfaceCreated(surface_info);
509 } 586 }
510 587
511 } // namespace cc 588 } // 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