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 "base/logging.h" | 10 #include "base/logging.h" |
11 #include "cc/surfaces/surface.h" | 11 #include "cc/surfaces/surface.h" |
| 12 #include "cc/surfaces/surface_factory_client.h" |
12 #include "cc/surfaces/surface_id_allocator.h" | 13 #include "cc/surfaces/surface_id_allocator.h" |
13 | 14 |
14 namespace cc { | 15 namespace cc { |
15 | 16 |
| 17 SurfaceManager::ClientSourceMapping::ClientSourceMapping() |
| 18 : client(nullptr), source(nullptr) {} |
| 19 |
| 20 SurfaceManager::ClientSourceMapping::~ClientSourceMapping() { |
| 21 DCHECK(is_empty()) << "client: " << client |
| 22 << ", children: " << children.size(); |
| 23 } |
| 24 |
16 SurfaceManager::SurfaceManager() { | 25 SurfaceManager::SurfaceManager() { |
17 thread_checker_.DetachFromThread(); | 26 thread_checker_.DetachFromThread(); |
18 } | 27 } |
19 | 28 |
20 SurfaceManager::~SurfaceManager() { | 29 SurfaceManager::~SurfaceManager() { |
21 DCHECK(thread_checker_.CalledOnValidThread()); | 30 DCHECK(thread_checker_.CalledOnValidThread()); |
22 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); | 31 for (SurfaceDestroyList::iterator it = surfaces_to_destroy_.begin(); |
23 it != surfaces_to_destroy_.end(); | 32 it != surfaces_to_destroy_.end(); |
24 ++it) { | 33 ++it) { |
25 DeregisterSurface((*it)->surface_id()); | 34 DeregisterSurface((*it)->surface_id()); |
26 delete *it; | 35 delete *it; |
27 } | 36 } |
| 37 // All hierarchies, sources, and surface factory clients should be |
| 38 // unregistered prior to SurfaceManager destruction. |
| 39 DCHECK_EQ(namespace_client_map_.size(), 0u); |
| 40 DCHECK_EQ(registered_sources_.size(), 0u); |
28 } | 41 } |
29 | 42 |
30 void SurfaceManager::RegisterSurface(Surface* surface) { | 43 void SurfaceManager::RegisterSurface(Surface* surface) { |
31 DCHECK(thread_checker_.CalledOnValidThread()); | 44 DCHECK(thread_checker_.CalledOnValidThread()); |
32 DCHECK(surface); | 45 DCHECK(surface); |
33 DCHECK(!surface_map_.count(surface->surface_id())); | 46 DCHECK(!surface_map_.count(surface->surface_id())); |
34 surface_map_[surface->surface_id()] = surface; | 47 surface_map_[surface->surface_id()] = surface; |
35 } | 48 } |
36 | 49 |
37 void SurfaceManager::DeregisterSurface(SurfaceId surface_id) { | 50 void SurfaceManager::DeregisterSurface(SurfaceId surface_id) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 if (!live_surfaces_set.count((*dest_it)->surface_id())) { | 126 if (!live_surfaces_set.count((*dest_it)->surface_id())) { |
114 scoped_ptr<Surface> surf(*dest_it); | 127 scoped_ptr<Surface> surf(*dest_it); |
115 DeregisterSurface(surf->surface_id()); | 128 DeregisterSurface(surf->surface_id()); |
116 dest_it = surfaces_to_destroy_.erase(dest_it); | 129 dest_it = surfaces_to_destroy_.erase(dest_it); |
117 } else { | 130 } else { |
118 ++dest_it; | 131 ++dest_it; |
119 } | 132 } |
120 } | 133 } |
121 } | 134 } |
122 | 135 |
| 136 void SurfaceManager::RegisterSurfaceFactoryClient( |
| 137 uint32_t id_namespace, |
| 138 SurfaceFactoryClient* client) { |
| 139 DCHECK(client); |
| 140 DCHECK(!namespace_client_map_[id_namespace].client); |
| 141 DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u); |
| 142 |
| 143 auto iter = namespace_client_map_.find(id_namespace); |
| 144 if (iter == namespace_client_map_.end()) { |
| 145 auto insert_result = namespace_client_map_.insert( |
| 146 std::make_pair(id_namespace, ClientSourceMapping())); |
| 147 DCHECK(insert_result.second); |
| 148 iter = insert_result.first; |
| 149 } |
| 150 iter->second.client = client; |
| 151 |
| 152 // Propagate any previously set sources to the new client. |
| 153 if (iter->second.source) |
| 154 client->SetBeginFrameSource(iter->second.source); |
| 155 } |
| 156 |
| 157 void SurfaceManager::UnregisterSurfaceFactoryClient(uint32_t id_namespace) { |
| 158 DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u); |
| 159 DCHECK_EQ(namespace_client_map_.count(id_namespace), 1u); |
| 160 |
| 161 auto iter = namespace_client_map_.find(id_namespace); |
| 162 if (iter->second.source) |
| 163 iter->second.client->SetBeginFrameSource(nullptr); |
| 164 iter->second.client = nullptr; |
| 165 |
| 166 // The SurfaceFactoryClient and hierarchy can be registered/unregistered |
| 167 // in either order, so empty namespace_client_map entries need to be |
| 168 // checked when removing either clients or relationships. |
| 169 if (iter->second.is_empty()) |
| 170 namespace_client_map_.erase(iter); |
| 171 } |
| 172 |
| 173 void SurfaceManager::RegisterBeginFrameSource(BeginFrameSource* source, |
| 174 uint32_t id_namespace) { |
| 175 DCHECK(source); |
| 176 DCHECK_EQ(registered_sources_.count(source), 0u); |
| 177 DCHECK_EQ(valid_surface_id_namespaces_.count(id_namespace), 1u); |
| 178 |
| 179 registered_sources_[source] = id_namespace; |
| 180 RecursivelyAttachBeginFrameSource(id_namespace, source); |
| 181 } |
| 182 |
| 183 void SurfaceManager::UnregisterBeginFrameSource(BeginFrameSource* source) { |
| 184 DCHECK(source); |
| 185 DCHECK_EQ(registered_sources_.count(source), 1u); |
| 186 |
| 187 uint32_t id_namespace = registered_sources_[source]; |
| 188 registered_sources_.erase(source); |
| 189 |
| 190 if (namespace_client_map_.count(id_namespace) == 0u) |
| 191 return; |
| 192 |
| 193 // TODO(enne): these walks could be done in one step. |
| 194 // Remove this begin frame source from its subtree. |
| 195 RecursivelyDetachBeginFrameSource(id_namespace, source); |
| 196 // Then flush every remaining registered source to fix any sources that |
| 197 // became null because of the previous step but that have an alternative. |
| 198 for (auto source_iter : registered_sources_) |
| 199 RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); |
| 200 } |
| 201 |
| 202 void SurfaceManager::RecursivelyAttachBeginFrameSource( |
| 203 uint32_t id_namespace, |
| 204 BeginFrameSource* source) { |
| 205 ClientSourceMapping& mapping = namespace_client_map_[id_namespace]; |
| 206 if (!mapping.source) { |
| 207 mapping.source = source; |
| 208 if (mapping.client) |
| 209 mapping.client->SetBeginFrameSource(source); |
| 210 } |
| 211 for (size_t i = 0; i < mapping.children.size(); ++i) |
| 212 RecursivelyAttachBeginFrameSource(mapping.children[i], source); |
| 213 } |
| 214 |
| 215 void SurfaceManager::RecursivelyDetachBeginFrameSource( |
| 216 uint32_t id_namespace, |
| 217 BeginFrameSource* source) { |
| 218 auto iter = namespace_client_map_.find(id_namespace); |
| 219 if (iter == namespace_client_map_.end()) |
| 220 return; |
| 221 if (iter->second.source == source) { |
| 222 iter->second.source = nullptr; |
| 223 if (iter->second.client) |
| 224 iter->second.client->SetBeginFrameSource(nullptr); |
| 225 } |
| 226 |
| 227 if (iter->second.is_empty()) { |
| 228 namespace_client_map_.erase(iter); |
| 229 return; |
| 230 } |
| 231 |
| 232 std::vector<uint32_t>& children = iter->second.children; |
| 233 for (size_t i = 0; i < children.size(); ++i) { |
| 234 RecursivelyDetachBeginFrameSource(children[i], source); |
| 235 } |
| 236 } |
| 237 |
| 238 bool SurfaceManager::ChildContains(uint32_t child_namespace, |
| 239 uint32_t search_namespace) const { |
| 240 auto iter = namespace_client_map_.find(child_namespace); |
| 241 if (iter == namespace_client_map_.end()) |
| 242 return false; |
| 243 |
| 244 const std::vector<uint32_t>& children = iter->second.children; |
| 245 for (size_t i = 0; i < children.size(); ++i) { |
| 246 if (children[i] == search_namespace) |
| 247 return true; |
| 248 if (ChildContains(children[i], search_namespace)) |
| 249 return true; |
| 250 } |
| 251 return false; |
| 252 } |
| 253 |
| 254 void SurfaceManager::RegisterSurfaceNamespaceHierarchy( |
| 255 uint32_t parent_namespace, |
| 256 uint32_t child_namespace) { |
| 257 DCHECK_EQ(valid_surface_id_namespaces_.count(parent_namespace), 1u); |
| 258 DCHECK_EQ(valid_surface_id_namespaces_.count(child_namespace), 1u); |
| 259 |
| 260 // If it's possible to reach the parent through the child's descendant chain, |
| 261 // then this will create an infinite loop. Might as well just crash here. |
| 262 CHECK(!ChildContains(child_namespace, parent_namespace)); |
| 263 |
| 264 std::vector<uint32_t>& children = |
| 265 namespace_client_map_[parent_namespace].children; |
| 266 for (size_t i = 0; i < children.size(); ++i) |
| 267 DCHECK_NE(children[i], child_namespace); |
| 268 children.push_back(child_namespace); |
| 269 |
| 270 // If the parent has no source, then attaching it to this child will |
| 271 // not change any downstream sources. |
| 272 BeginFrameSource* parent_source = |
| 273 namespace_client_map_[parent_namespace].source; |
| 274 if (!parent_source) |
| 275 return; |
| 276 |
| 277 DCHECK_EQ(registered_sources_.count(parent_source), 1u); |
| 278 RecursivelyAttachBeginFrameSource(child_namespace, parent_source); |
| 279 } |
| 280 |
| 281 void SurfaceManager::UnregisterSurfaceNamespaceHierarchy( |
| 282 uint32_t parent_namespace, |
| 283 uint32_t child_namespace) { |
| 284 DCHECK_EQ(valid_surface_id_namespaces_.count(parent_namespace), 1u); |
| 285 DCHECK_EQ(valid_surface_id_namespaces_.count(child_namespace), 1u); |
| 286 DCHECK_EQ(namespace_client_map_.count(parent_namespace), 1u); |
| 287 |
| 288 auto iter = namespace_client_map_.find(parent_namespace); |
| 289 |
| 290 std::vector<uint32_t>& children = iter->second.children; |
| 291 bool found_child = false; |
| 292 for (size_t i = 0; i < children.size(); ++i) { |
| 293 if (children[i] == child_namespace) { |
| 294 found_child = true; |
| 295 children[i] = children[children.size() - 1]; |
| 296 children.resize(children.size() - 1); |
| 297 break; |
| 298 } |
| 299 } |
| 300 DCHECK(found_child); |
| 301 |
| 302 // The SurfaceFactoryClient and hierarchy can be registered/unregistered |
| 303 // in either order, so empty namespace_client_map entries need to be |
| 304 // checked when removing either clients or relationships. |
| 305 if (iter->second.is_empty()) { |
| 306 namespace_client_map_.erase(iter); |
| 307 return; |
| 308 } |
| 309 |
| 310 // If the parent does not have a begin frame source, then disconnecting it |
| 311 // will not change any of its children. |
| 312 BeginFrameSource* parent_source = iter->second.source; |
| 313 if (!parent_source) |
| 314 return; |
| 315 |
| 316 // TODO(enne): these walks could be done in one step. |
| 317 RecursivelyDetachBeginFrameSource(child_namespace, parent_source); |
| 318 for (auto source_iter : registered_sources_) |
| 319 RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first); |
| 320 } |
| 321 |
123 Surface* SurfaceManager::GetSurfaceForId(SurfaceId surface_id) { | 322 Surface* SurfaceManager::GetSurfaceForId(SurfaceId surface_id) { |
124 DCHECK(thread_checker_.CalledOnValidThread()); | 323 DCHECK(thread_checker_.CalledOnValidThread()); |
125 SurfaceMap::iterator it = surface_map_.find(surface_id); | 324 SurfaceMap::iterator it = surface_map_.find(surface_id); |
126 if (it == surface_map_.end()) | 325 if (it == surface_map_.end()) |
127 return NULL; | 326 return NULL; |
128 return it->second; | 327 return it->second; |
129 } | 328 } |
130 | 329 |
131 bool SurfaceManager::SurfaceModified(SurfaceId surface_id) { | 330 bool SurfaceManager::SurfaceModified(SurfaceId surface_id) { |
132 DCHECK(thread_checker_.CalledOnValidThread()); | 331 CHECK(thread_checker_.CalledOnValidThread()); |
133 bool changed = false; | 332 bool changed = false; |
134 FOR_EACH_OBSERVER(SurfaceDamageObserver, observer_list_, | 333 FOR_EACH_OBSERVER(SurfaceDamageObserver, observer_list_, |
135 OnSurfaceDamaged(surface_id, &changed)); | 334 OnSurfaceDamaged(surface_id, &changed)); |
136 return changed; | 335 return changed; |
137 } | 336 } |
138 | 337 |
139 } // namespace cc | 338 } // namespace cc |
OLD | NEW |