OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 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 <stddef.h> |
| 6 |
| 7 #include "cc/scheduler/begin_frame_source.h" |
| 8 #include "cc/surfaces/surface_factory_client.h" |
| 9 #include "cc/surfaces/surface_manager.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" |
| 11 |
| 12 namespace cc { |
| 13 |
| 14 class FakeSurfaceFactoryClient : public SurfaceFactoryClient { |
| 15 public: |
| 16 explicit FakeSurfaceFactoryClient(int id_namespace) |
| 17 : source_(nullptr), manager_(nullptr), id_namespace_(id_namespace) {} |
| 18 FakeSurfaceFactoryClient(int id_namespace, SurfaceManager* manager) |
| 19 : source_(nullptr), manager_(nullptr), id_namespace_(id_namespace) { |
| 20 DCHECK(manager); |
| 21 Register(manager); |
| 22 } |
| 23 |
| 24 ~FakeSurfaceFactoryClient() override { |
| 25 if (manager_) { |
| 26 Unregister(); |
| 27 } |
| 28 EXPECT_EQ(source_, nullptr); |
| 29 } |
| 30 |
| 31 BeginFrameSource* source() { return source_; } |
| 32 uint32_t id_namespace() { return id_namespace_; } |
| 33 |
| 34 void Register(SurfaceManager* manager) { |
| 35 EXPECT_EQ(manager_, nullptr); |
| 36 manager_ = manager; |
| 37 manager_->RegisterSurfaceFactoryClient(id_namespace_, this); |
| 38 } |
| 39 |
| 40 void Unregister() { |
| 41 EXPECT_NE(manager_, nullptr); |
| 42 manager_->UnregisterSurfaceFactoryClient(id_namespace_); |
| 43 manager_ = nullptr; |
| 44 } |
| 45 |
| 46 // SurfaceFactoryClient implementation. |
| 47 void ReturnResources(const ReturnedResourceArray& resources) override{}; |
| 48 void SetBeginFrameSource(BeginFrameSource* begin_frame_source) override { |
| 49 DCHECK(!source_ || !begin_frame_source); |
| 50 source_ = begin_frame_source; |
| 51 }; |
| 52 |
| 53 private: |
| 54 BeginFrameSource* source_; |
| 55 SurfaceManager* manager_; |
| 56 uint32_t id_namespace_; |
| 57 }; |
| 58 |
| 59 class EmptyBeginFrameSource : public BeginFrameSource { |
| 60 public: |
| 61 void DidFinishFrame(size_t remaining_frames) override{}; |
| 62 void AddObserver(BeginFrameObserver* obs) override{}; |
| 63 void RemoveObserver(BeginFrameObserver* obs) override{}; |
| 64 void SetClientReady() override {} |
| 65 void AsValueInto(base::trace_event::TracedValue* dict) const override{}; |
| 66 }; |
| 67 |
| 68 class SurfaceManagerTest : public testing::Test { |
| 69 public: |
| 70 // These tests don't care about namespace registration, so just preregister |
| 71 // a set of namespaces that tests can use freely without worrying if they're |
| 72 // valid or not. |
| 73 enum { MAX_NAMESPACE = 10 }; |
| 74 |
| 75 SurfaceManagerTest() { |
| 76 for (size_t i = 0; i < MAX_NAMESPACE; ++i) |
| 77 manager_.RegisterSurfaceIdNamespace(i); |
| 78 } |
| 79 |
| 80 ~SurfaceManagerTest() override { |
| 81 for (size_t i = 0; i < MAX_NAMESPACE; ++i) |
| 82 manager_.InvalidateSurfaceIdNamespace(i); |
| 83 } |
| 84 |
| 85 protected: |
| 86 SurfaceManager manager_; |
| 87 }; |
| 88 |
| 89 TEST_F(SurfaceManagerTest, SingleClients) { |
| 90 FakeSurfaceFactoryClient client(1); |
| 91 FakeSurfaceFactoryClient other_client(2); |
| 92 EmptyBeginFrameSource source; |
| 93 |
| 94 EXPECT_EQ(client.source(), nullptr); |
| 95 EXPECT_EQ(other_client.source(), nullptr); |
| 96 client.Register(&manager_); |
| 97 other_client.Register(&manager_); |
| 98 EXPECT_EQ(client.source(), nullptr); |
| 99 EXPECT_EQ(other_client.source(), nullptr); |
| 100 |
| 101 // Test setting unsetting BFS |
| 102 manager_.RegisterBeginFrameSource(&source, client.id_namespace()); |
| 103 EXPECT_EQ(client.source(), &source); |
| 104 EXPECT_EQ(other_client.source(), nullptr); |
| 105 manager_.UnregisterBeginFrameSource(&source); |
| 106 EXPECT_EQ(client.source(), nullptr); |
| 107 EXPECT_EQ(other_client.source(), nullptr); |
| 108 |
| 109 // Set BFS for other namespace |
| 110 manager_.RegisterBeginFrameSource(&source, other_client.id_namespace()); |
| 111 EXPECT_EQ(other_client.source(), &source); |
| 112 EXPECT_EQ(client.source(), nullptr); |
| 113 manager_.UnregisterBeginFrameSource(&source); |
| 114 EXPECT_EQ(client.source(), nullptr); |
| 115 EXPECT_EQ(other_client.source(), nullptr); |
| 116 |
| 117 // Re-set BFS for original |
| 118 manager_.RegisterBeginFrameSource(&source, client.id_namespace()); |
| 119 EXPECT_EQ(client.source(), &source); |
| 120 manager_.UnregisterBeginFrameSource(&source); |
| 121 EXPECT_EQ(client.source(), nullptr); |
| 122 } |
| 123 |
| 124 TEST_F(SurfaceManagerTest, MultipleDisplays) { |
| 125 EmptyBeginFrameSource root1_source; |
| 126 EmptyBeginFrameSource root2_source; |
| 127 |
| 128 // root1 -> A -> B |
| 129 // root2 -> C |
| 130 FakeSurfaceFactoryClient root1(1, &manager_); |
| 131 FakeSurfaceFactoryClient root2(2, &manager_); |
| 132 FakeSurfaceFactoryClient client_a(3, &manager_); |
| 133 FakeSurfaceFactoryClient client_b(4, &manager_); |
| 134 FakeSurfaceFactoryClient client_c(5, &manager_); |
| 135 |
| 136 manager_.RegisterBeginFrameSource(&root1_source, root1.id_namespace()); |
| 137 manager_.RegisterBeginFrameSource(&root2_source, root2.id_namespace()); |
| 138 EXPECT_EQ(root1.source(), &root1_source); |
| 139 EXPECT_EQ(root2.source(), &root2_source); |
| 140 |
| 141 // Set up initial hierarchy. |
| 142 manager_.RegisterSurfaceNamespaceHierarchy(root1.id_namespace(), |
| 143 client_a.id_namespace()); |
| 144 EXPECT_EQ(client_a.source(), root1.source()); |
| 145 manager_.RegisterSurfaceNamespaceHierarchy(client_a.id_namespace(), |
| 146 client_b.id_namespace()); |
| 147 EXPECT_EQ(client_b.source(), root1.source()); |
| 148 manager_.RegisterSurfaceNamespaceHierarchy(root2.id_namespace(), |
| 149 client_c.id_namespace()); |
| 150 EXPECT_EQ(client_c.source(), root2.source()); |
| 151 |
| 152 // Attach A into root2's subtree, like a window moving across displays. |
| 153 // root1 -> A -> B |
| 154 // root2 -> C -> A -> B |
| 155 manager_.RegisterSurfaceNamespaceHierarchy(client_c.id_namespace(), |
| 156 client_a.id_namespace()); |
| 157 // With the heuristic of just keeping existing BFS in the face of multiple, |
| 158 // no client sources should change. |
| 159 EXPECT_EQ(client_a.source(), root1.source()); |
| 160 EXPECT_EQ(client_b.source(), root1.source()); |
| 161 EXPECT_EQ(client_c.source(), root2.source()); |
| 162 |
| 163 // Detach A from root1. A and B should now be updated to root2. |
| 164 manager_.UnregisterSurfaceNamespaceHierarchy(root1.id_namespace(), |
| 165 client_a.id_namespace()); |
| 166 EXPECT_EQ(client_a.source(), root2.source()); |
| 167 EXPECT_EQ(client_b.source(), root2.source()); |
| 168 EXPECT_EQ(client_c.source(), root2.source()); |
| 169 |
| 170 // Detach root1 from BFS. root1 should now have no source. |
| 171 manager_.UnregisterBeginFrameSource(&root1_source); |
| 172 EXPECT_EQ(root1.source(), nullptr); |
| 173 EXPECT_NE(root2.source(), nullptr); |
| 174 |
| 175 // Detatch root2 from BFS. |
| 176 manager_.UnregisterBeginFrameSource(&root2_source); |
| 177 EXPECT_EQ(client_a.source(), nullptr); |
| 178 EXPECT_EQ(client_b.source(), nullptr); |
| 179 EXPECT_EQ(client_c.source(), nullptr); |
| 180 EXPECT_EQ(root2.source(), nullptr); |
| 181 |
| 182 // Cleanup hierarchy. |
| 183 manager_.UnregisterSurfaceNamespaceHierarchy(root2.id_namespace(), |
| 184 client_c.id_namespace()); |
| 185 manager_.UnregisterSurfaceNamespaceHierarchy(client_c.id_namespace(), |
| 186 client_a.id_namespace()); |
| 187 manager_.UnregisterSurfaceNamespaceHierarchy(client_a.id_namespace(), |
| 188 client_b.id_namespace()); |
| 189 } |
| 190 |
| 191 // In practice, registering and unregistering both parent/child relationships |
| 192 // and SurfaceFactoryClients can happen in any ordering with respect to |
| 193 // each other. These following tests verify that all the data structures |
| 194 // are properly set up and cleaned up under the four permutations of orderings |
| 195 // of this nesting. |
| 196 |
| 197 class SurfaceManagerOrderingTest : public SurfaceManagerTest { |
| 198 public: |
| 199 SurfaceManagerOrderingTest() |
| 200 : client_a_(1), |
| 201 client_b_(2), |
| 202 client_c_(3), |
| 203 hierarchy_registered_(false), |
| 204 clients_registered_(false), |
| 205 bfs_registered_(false) { |
| 206 AssertCorrectBFSState(); |
| 207 } |
| 208 |
| 209 ~SurfaceManagerOrderingTest() override { |
| 210 EXPECT_EQ(hierarchy_registered_, false); |
| 211 EXPECT_EQ(clients_registered_, false); |
| 212 EXPECT_EQ(bfs_registered_, false); |
| 213 AssertCorrectBFSState(); |
| 214 } |
| 215 |
| 216 void RegisterHierarchy() { |
| 217 DCHECK(!hierarchy_registered_); |
| 218 hierarchy_registered_ = true; |
| 219 manager_.RegisterSurfaceNamespaceHierarchy(client_a_.id_namespace(), |
| 220 client_b_.id_namespace()); |
| 221 manager_.RegisterSurfaceNamespaceHierarchy(client_b_.id_namespace(), |
| 222 client_c_.id_namespace()); |
| 223 AssertCorrectBFSState(); |
| 224 } |
| 225 void UnregisterHierarchy() { |
| 226 DCHECK(hierarchy_registered_); |
| 227 hierarchy_registered_ = false; |
| 228 manager_.UnregisterSurfaceNamespaceHierarchy(client_a_.id_namespace(), |
| 229 client_b_.id_namespace()); |
| 230 manager_.UnregisterSurfaceNamespaceHierarchy(client_b_.id_namespace(), |
| 231 client_c_.id_namespace()); |
| 232 AssertCorrectBFSState(); |
| 233 } |
| 234 |
| 235 void RegisterClients() { |
| 236 DCHECK(!clients_registered_); |
| 237 clients_registered_ = true; |
| 238 client_a_.Register(&manager_); |
| 239 client_b_.Register(&manager_); |
| 240 client_c_.Register(&manager_); |
| 241 AssertCorrectBFSState(); |
| 242 } |
| 243 |
| 244 void UnregisterClients() { |
| 245 DCHECK(clients_registered_); |
| 246 clients_registered_ = false; |
| 247 client_a_.Unregister(); |
| 248 client_b_.Unregister(); |
| 249 client_c_.Unregister(); |
| 250 AssertCorrectBFSState(); |
| 251 } |
| 252 |
| 253 void RegisterBFS() { |
| 254 DCHECK(!bfs_registered_); |
| 255 bfs_registered_ = true; |
| 256 manager_.RegisterBeginFrameSource(&source_, client_a_.id_namespace()); |
| 257 AssertCorrectBFSState(); |
| 258 } |
| 259 void UnregisterBFS() { |
| 260 DCHECK(bfs_registered_); |
| 261 bfs_registered_ = false; |
| 262 manager_.UnregisterBeginFrameSource(&source_); |
| 263 AssertCorrectBFSState(); |
| 264 } |
| 265 |
| 266 void AssertEmptyBFS() { |
| 267 EXPECT_EQ(client_a_.source(), nullptr); |
| 268 EXPECT_EQ(client_b_.source(), nullptr); |
| 269 EXPECT_EQ(client_c_.source(), nullptr); |
| 270 } |
| 271 |
| 272 void AssertAllValidBFS() { |
| 273 EXPECT_EQ(client_a_.source(), &source_); |
| 274 EXPECT_EQ(client_b_.source(), &source_); |
| 275 EXPECT_EQ(client_c_.source(), &source_); |
| 276 } |
| 277 |
| 278 protected: |
| 279 void AssertCorrectBFSState() { |
| 280 if (!clients_registered_ || !bfs_registered_) { |
| 281 AssertEmptyBFS(); |
| 282 return; |
| 283 } |
| 284 if (!hierarchy_registered_) { |
| 285 // A valid but not attached to anything. |
| 286 EXPECT_EQ(client_a_.source(), &source_); |
| 287 EXPECT_EQ(client_b_.source(), nullptr); |
| 288 EXPECT_EQ(client_c_.source(), nullptr); |
| 289 return; |
| 290 } |
| 291 |
| 292 AssertAllValidBFS(); |
| 293 } |
| 294 |
| 295 EmptyBeginFrameSource source_; |
| 296 // A -> B -> C hierarchy, with A always having the BFS. |
| 297 FakeSurfaceFactoryClient client_a_; |
| 298 FakeSurfaceFactoryClient client_b_; |
| 299 FakeSurfaceFactoryClient client_c_; |
| 300 |
| 301 bool hierarchy_registered_; |
| 302 bool clients_registered_; |
| 303 bool bfs_registered_; |
| 304 }; |
| 305 |
| 306 enum RegisterOrder { REGISTER_HIERARCHY_FIRST, REGISTER_CLIENTS_FIRST }; |
| 307 enum UnregisterOrder { UNREGISTER_HIERARCHY_FIRST, UNREGISTER_CLIENTS_FIRST }; |
| 308 enum BFSOrder { BFS_FIRST, BFS_SECOND, BFS_THIRD }; |
| 309 |
| 310 static const RegisterOrder kRegisterOrderList[] = {REGISTER_HIERARCHY_FIRST, |
| 311 REGISTER_CLIENTS_FIRST}; |
| 312 static const UnregisterOrder kUnregisterOrderList[] = { |
| 313 UNREGISTER_HIERARCHY_FIRST, UNREGISTER_CLIENTS_FIRST}; |
| 314 static const BFSOrder kBFSOrderList[] = {BFS_FIRST, BFS_SECOND, BFS_THIRD}; |
| 315 |
| 316 class SurfaceManagerOrderingParamTest |
| 317 : public SurfaceManagerOrderingTest, |
| 318 public ::testing::WithParamInterface< |
| 319 std::tr1::tuple<RegisterOrder, UnregisterOrder, BFSOrder>> {}; |
| 320 |
| 321 TEST_P(SurfaceManagerOrderingParamTest, Ordering) { |
| 322 // Test the four permutations of client/hierarchy setting/unsetting and test |
| 323 // each place the BFS can be added and removed. The BFS and the |
| 324 // client/hierarchy are less related, so BFS is tested independently instead |
| 325 // of every permutation of BFS setting and unsetting. |
| 326 // The register/unregister functions themselves test most of the state. |
| 327 RegisterOrder register_order = std::tr1::get<0>(GetParam()); |
| 328 UnregisterOrder unregister_order = std::tr1::get<1>(GetParam()); |
| 329 BFSOrder bfs_order = std::tr1::get<2>(GetParam()); |
| 330 |
| 331 // Attach everything up in the specified order. |
| 332 if (bfs_order == BFS_FIRST) |
| 333 RegisterBFS(); |
| 334 |
| 335 if (register_order == REGISTER_HIERARCHY_FIRST) |
| 336 RegisterHierarchy(); |
| 337 else |
| 338 RegisterClients(); |
| 339 |
| 340 if (bfs_order == BFS_SECOND) |
| 341 RegisterBFS(); |
| 342 |
| 343 if (register_order == REGISTER_HIERARCHY_FIRST) |
| 344 RegisterClients(); |
| 345 else |
| 346 RegisterHierarchy(); |
| 347 |
| 348 if (bfs_order == BFS_THIRD) |
| 349 RegisterBFS(); |
| 350 |
| 351 // Everything hooked up, so should be valid. |
| 352 AssertAllValidBFS(); |
| 353 |
| 354 // Detach everything in the specified order. |
| 355 if (bfs_order == BFS_THIRD) |
| 356 UnregisterBFS(); |
| 357 |
| 358 if (unregister_order == UNREGISTER_HIERARCHY_FIRST) |
| 359 UnregisterHierarchy(); |
| 360 else |
| 361 UnregisterClients(); |
| 362 |
| 363 if (bfs_order == BFS_SECOND) |
| 364 UnregisterBFS(); |
| 365 |
| 366 if (unregister_order == UNREGISTER_HIERARCHY_FIRST) |
| 367 UnregisterClients(); |
| 368 else |
| 369 UnregisterHierarchy(); |
| 370 |
| 371 if (bfs_order == BFS_FIRST) |
| 372 UnregisterBFS(); |
| 373 } |
| 374 |
| 375 INSTANTIATE_TEST_CASE_P( |
| 376 SurfaceManagerOrderingParamTestInstantiation, |
| 377 SurfaceManagerOrderingParamTest, |
| 378 ::testing::Combine(::testing::ValuesIn(kRegisterOrderList), |
| 379 ::testing::ValuesIn(kUnregisterOrderList), |
| 380 ::testing::ValuesIn(kBFSOrderList))); |
| 381 |
| 382 } // namespace cc |
OLD | NEW |