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