OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "cc/surfaces/framesink_manager.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 | |
10 #include <queue> | |
enne (OOO)
2017/03/20 18:28:53
Are all of these includes used?
| |
11 #include <utility> | |
12 | |
13 #include "base/logging.h" | |
14 #include "cc/surfaces/surface_factory_client.h" | |
15 | |
16 #if DCHECK_IS_ON() | |
enne (OOO)
2017/03/20 18:28:53
This doesn't appear used either.
| |
17 #include <sstream> | |
18 #endif | |
19 | |
20 namespace cc { | |
21 | |
22 FrameSinkManager::FrameSinkSourceMapping::FrameSinkSourceMapping() | |
23 : source(nullptr) {} | |
24 | |
25 FrameSinkManager::FrameSinkSourceMapping::FrameSinkSourceMapping( | |
26 const FrameSinkSourceMapping& other) = default; | |
27 | |
28 FrameSinkManager::FrameSinkSourceMapping::~FrameSinkSourceMapping() { | |
29 } | |
30 | |
31 FrameSinkManager::FrameSinkManager() { | |
32 } | |
33 | |
34 FrameSinkManager::~FrameSinkManager() { | |
35 | |
36 // All surface factory clients should be unregistered prior to SurfaceManager | |
37 // destruction. | |
38 DCHECK_EQ(clients_.size(), 0u); | |
39 DCHECK_EQ(registered_sources_.size(), 0u); | |
40 } | |
41 | |
42 void FrameSinkManager::RegisterFrameSinkId(const FrameSinkId& frame_sink_id) { | |
43 bool inserted = valid_frame_sink_ids_.insert(frame_sink_id).second; | |
44 DCHECK(inserted); | |
45 } | |
46 | |
47 void FrameSinkManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { | |
48 valid_frame_sink_ids_.erase(frame_sink_id); | |
49 } | |
50 | |
51 void FrameSinkManager::RegisterSurfaceFactoryClient( | |
52 const FrameSinkId& frame_sink_id, | |
53 SurfaceFactoryClient* client) { | |
54 DCHECK(client); | |
55 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | |
56 | |
57 clients_[frame_sink_id] = client; | |
58 | |
59 auto it = frame_sink_source_map_.find(frame_sink_id); | |
60 if (it != frame_sink_source_map_.end()) { | |
61 if (it->second.source) | |
62 client->SetBeginFrameSource(it->second.source); | |
63 } | |
64 } | |
65 | |
66 void FrameSinkManager::UnregisterSurfaceFactoryClient( | |
67 const FrameSinkId& frame_sink_id) { | |
68 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | |
69 auto client_iter = clients_.find(frame_sink_id); | |
70 DCHECK(client_iter != clients_.end()); | |
71 | |
72 auto source_iter = frame_sink_source_map_.find(frame_sink_id); | |
73 if (source_iter != frame_sink_source_map_.end()) { | |
74 if (source_iter->second.source) | |
75 client_iter->second->SetBeginFrameSource(nullptr); | |
76 if (!source_iter->second.has_children()) | |
77 frame_sink_source_map_.erase(source_iter); | |
78 } | |
79 clients_.erase(client_iter); | |
80 } | |
81 | |
82 void FrameSinkManager::RegisterBeginFrameSource( | |
83 BeginFrameSource* source, | |
84 const FrameSinkId& frame_sink_id) { | |
85 DCHECK(source); | |
86 DCHECK_EQ(registered_sources_.count(source), 0u); | |
87 DCHECK_EQ(valid_frame_sink_ids_.count(frame_sink_id), 1u); | |
88 | |
89 registered_sources_[source] = frame_sink_id; | |
90 RecursivelyAttachBeginFrameSource(frame_sink_id, source); | |
91 } | |
92 | |
93 void FrameSinkManager::UnregisterBeginFrameSource(BeginFrameSource* source) { | |
94 DCHECK(source); | |
95 DCHECK_EQ(registered_sources_.count(source), 1u); | |
96 | |
97 FrameSinkId frame_sink_id = registered_sources_[source]; | |
98 registered_sources_.erase(source); | |
99 | |
100 if (frame_sink_source_map_.count(frame_sink_id) == 0u) | |
101 return; | |
102 | |
103 // TODO(enne): these walks could be done in one step. | |
104 // Remove this begin frame source from its subtree. | |
105 RecursivelyDetachBeginFrameSource(frame_sink_id, source); | |
106 // Then flush every remaining registered source to fix any sources that | |
107 // became null because of the previous step but that have an alternative. | |
108 for (auto source_iter : registered_sources_) | |
109 RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); | |
110 } | |
111 | |
112 void FrameSinkManager::RecursivelyAttachBeginFrameSource( | |
113 const FrameSinkId& frame_sink_id, | |
114 BeginFrameSource* source) { | |
115 FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id]; | |
116 if (!mapping.source) { | |
117 mapping.source = source; | |
118 auto client_iter = clients_.find(frame_sink_id); | |
119 if (client_iter != clients_.end()) | |
120 client_iter->second->SetBeginFrameSource(source); | |
121 } | |
122 for (size_t i = 0; i < mapping.children.size(); ++i) | |
123 RecursivelyAttachBeginFrameSource(mapping.children[i], source); | |
124 } | |
125 | |
126 void FrameSinkManager::RecursivelyDetachBeginFrameSource( | |
127 const FrameSinkId& frame_sink_id, | |
128 BeginFrameSource* source) { | |
129 auto iter = frame_sink_source_map_.find(frame_sink_id); | |
130 if (iter == frame_sink_source_map_.end()) | |
131 return; | |
132 if (iter->second.source == source) { | |
133 iter->second.source = nullptr; | |
134 auto client_iter = clients_.find(frame_sink_id); | |
135 if (client_iter != clients_.end()) | |
136 client_iter->second->SetBeginFrameSource(nullptr); | |
137 } | |
138 | |
139 if (!iter->second.has_children() && !clients_.count(frame_sink_id)) { | |
140 frame_sink_source_map_.erase(iter); | |
141 return; | |
142 } | |
143 | |
144 std::vector<FrameSinkId>& children = iter->second.children; | |
145 for (size_t i = 0; i < children.size(); ++i) { | |
146 RecursivelyDetachBeginFrameSource(children[i], source); | |
147 } | |
148 } | |
149 | |
150 bool FrameSinkManager::ChildContains( | |
151 const FrameSinkId& child_frame_sink_id, | |
152 const FrameSinkId& search_frame_sink_id) const { | |
153 auto iter = frame_sink_source_map_.find(child_frame_sink_id); | |
154 if (iter == frame_sink_source_map_.end()) | |
155 return false; | |
156 | |
157 const std::vector<FrameSinkId>& children = iter->second.children; | |
158 for (size_t i = 0; i < children.size(); ++i) { | |
159 if (children[i] == search_frame_sink_id) | |
160 return true; | |
161 if (ChildContains(children[i], search_frame_sink_id)) | |
162 return true; | |
163 } | |
164 return false; | |
165 } | |
166 | |
167 void FrameSinkManager::RegisterFrameSinkHierarchy( | |
168 const FrameSinkId& parent_frame_sink_id, | |
169 const FrameSinkId& child_frame_sink_id) { | |
170 // If it's possible to reach the parent through the child's descendant chain, | |
171 // then this will create an infinite loop. Might as well just crash here. | |
172 CHECK(!ChildContains(child_frame_sink_id, parent_frame_sink_id)); | |
173 | |
174 std::vector<FrameSinkId>& children = | |
175 frame_sink_source_map_[parent_frame_sink_id].children; | |
176 for (size_t i = 0; i < children.size(); ++i) | |
177 DCHECK(children[i] != child_frame_sink_id); | |
178 children.push_back(child_frame_sink_id); | |
179 | |
180 // If the parent has no source, then attaching it to this child will | |
181 // not change any downstream sources. | |
182 BeginFrameSource* parent_source = | |
183 frame_sink_source_map_[parent_frame_sink_id].source; | |
184 if (!parent_source) | |
185 return; | |
186 | |
187 DCHECK_EQ(registered_sources_.count(parent_source), 1u); | |
188 RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source); | |
189 } | |
190 | |
191 void FrameSinkManager::UnregisterFrameSinkHierarchy( | |
192 const FrameSinkId& parent_frame_sink_id, | |
193 const FrameSinkId& child_frame_sink_id) { | |
194 // Deliberately do not check validity of either parent or child FrameSinkId | |
195 // here. They were valid during the registration, so were valid at some | |
196 // point in time. This makes it possible to invalidate parent and child | |
197 // FrameSinkIds independently of each other and not have an ordering | |
198 // dependency of unregistering the hierarchy first before either of them. | |
199 DCHECK_EQ(frame_sink_source_map_.count(parent_frame_sink_id), 1u); | |
200 | |
201 auto iter = frame_sink_source_map_.find(parent_frame_sink_id); | |
202 | |
203 std::vector<FrameSinkId>& children = iter->second.children; | |
204 bool found_child = false; | |
205 for (size_t i = 0; i < children.size(); ++i) { | |
206 if (children[i] == child_frame_sink_id) { | |
207 found_child = true; | |
208 children[i] = children.back(); | |
209 children.resize(children.size() - 1); | |
210 break; | |
211 } | |
212 } | |
213 DCHECK(found_child); | |
214 | |
215 // The SurfaceFactoryClient and hierarchy can be registered/unregistered | |
216 // in either order, so empty frame_sink_source_map entries need to be | |
217 // checked when removing either clients or relationships. | |
218 if (!iter->second.has_children() && !clients_.count(parent_frame_sink_id)) { | |
219 frame_sink_source_map_.erase(iter); | |
220 return; | |
221 } | |
222 | |
223 // If the parent does not have a begin frame source, then disconnecting it | |
224 // will not change any of its children. | |
225 BeginFrameSource* parent_source = iter->second.source; | |
226 if (!parent_source) | |
227 return; | |
228 | |
229 // TODO(enne): these walks could be done in one step. | |
230 RecursivelyDetachBeginFrameSource(child_frame_sink_id, parent_source); | |
231 for (auto source_iter : registered_sources_) | |
232 RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); | |
233 } | |
234 | |
235 } // namespace cc | |
OLD | NEW |