| OLD | NEW |
| 1 // Copyright 2011 The Chromium Authors. All rights reserved. | 1 // Copyright 2011 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/test/layer_tree_test.h" | 5 #include "cc/test/layer_tree_test.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 | 86 |
| 87 // Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks. | 87 // Adapts LayerTreeHostImpl for test. Runs real code, then invokes test hooks. |
| 88 class LayerTreeHostImplForTesting : public LayerTreeHostImpl { | 88 class LayerTreeHostImplForTesting : public LayerTreeHostImpl { |
| 89 public: | 89 public: |
| 90 static std::unique_ptr<LayerTreeHostImplForTesting> Create( | 90 static std::unique_ptr<LayerTreeHostImplForTesting> Create( |
| 91 TestHooks* test_hooks, | 91 TestHooks* test_hooks, |
| 92 const LayerTreeSettings& settings, | 92 const LayerTreeSettings& settings, |
| 93 LayerTreeHostImplClient* host_impl_client, | 93 LayerTreeHostImplClient* host_impl_client, |
| 94 TaskRunnerProvider* task_runner_provider, | 94 TaskRunnerProvider* task_runner_provider, |
| 95 TaskGraphRunner* task_graph_runner, | 95 TaskGraphRunner* task_graph_runner, |
| 96 RenderingStatsInstrumentation* stats_instrumentation) { | 96 RenderingStatsInstrumentation* stats_instrumentation, |
| 97 scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner) { |
| 97 return base::WrapUnique(new LayerTreeHostImplForTesting( | 98 return base::WrapUnique(new LayerTreeHostImplForTesting( |
| 98 test_hooks, settings, host_impl_client, task_runner_provider, | 99 test_hooks, settings, host_impl_client, task_runner_provider, |
| 99 task_graph_runner, stats_instrumentation)); | 100 task_graph_runner, stats_instrumentation, |
| 101 std::move(image_worker_task_runner))); |
| 100 } | 102 } |
| 101 | 103 |
| 102 protected: | 104 protected: |
| 103 LayerTreeHostImplForTesting( | 105 LayerTreeHostImplForTesting( |
| 104 TestHooks* test_hooks, | 106 TestHooks* test_hooks, |
| 105 const LayerTreeSettings& settings, | 107 const LayerTreeSettings& settings, |
| 106 LayerTreeHostImplClient* host_impl_client, | 108 LayerTreeHostImplClient* host_impl_client, |
| 107 TaskRunnerProvider* task_runner_provider, | 109 TaskRunnerProvider* task_runner_provider, |
| 108 TaskGraphRunner* task_graph_runner, | 110 TaskGraphRunner* task_graph_runner, |
| 109 RenderingStatsInstrumentation* stats_instrumentation) | 111 RenderingStatsInstrumentation* stats_instrumentation, |
| 112 scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner) |
| 110 : LayerTreeHostImpl(settings, | 113 : LayerTreeHostImpl(settings, |
| 111 host_impl_client, | 114 host_impl_client, |
| 112 task_runner_provider, | 115 task_runner_provider, |
| 113 stats_instrumentation, | 116 stats_instrumentation, |
| 114 task_graph_runner, | 117 task_graph_runner, |
| 115 AnimationHost::CreateForTesting(ThreadInstance::IMPL), | 118 AnimationHost::CreateForTesting(ThreadInstance::IMPL), |
| 116 0, | 119 0, |
| 117 nullptr), | 120 std::move(image_worker_task_runner)), |
| 118 test_hooks_(test_hooks), | 121 test_hooks_(test_hooks) {} |
| 119 block_notify_ready_to_activate_for_testing_(false), | |
| 120 notify_ready_to_activate_was_blocked_(false) {} | |
| 121 | 122 |
| 122 void CreateResourceAndRasterBufferProvider( | 123 void CreateResourceAndRasterBufferProvider( |
| 123 std::unique_ptr<RasterBufferProvider>* raster_buffer_provider, | 124 std::unique_ptr<RasterBufferProvider>* raster_buffer_provider, |
| 124 std::unique_ptr<ResourcePool>* resource_pool) override { | 125 std::unique_ptr<ResourcePool>* resource_pool) override { |
| 125 test_hooks_->CreateResourceAndRasterBufferProvider( | 126 test_hooks_->CreateResourceAndRasterBufferProvider( |
| 126 this, raster_buffer_provider, resource_pool); | 127 this, raster_buffer_provider, resource_pool); |
| 127 } | 128 } |
| 128 | 129 |
| 129 void WillBeginImplFrame(const BeginFrameArgs& args) override { | 130 void WillBeginImplFrame(const BeginFrameArgs& args) override { |
| 130 LayerTreeHostImpl::WillBeginImplFrame(args); | 131 LayerTreeHostImpl::WillBeginImplFrame(args); |
| 131 test_hooks_->WillBeginImplFrameOnThread(this, args); | 132 test_hooks_->WillBeginImplFrameOnThread(this, args); |
| 132 } | 133 } |
| 133 | 134 |
| 134 void DidFinishImplFrame() override { | 135 void DidFinishImplFrame() override { |
| 135 LayerTreeHostImpl::DidFinishImplFrame(); | 136 LayerTreeHostImpl::DidFinishImplFrame(); |
| 136 test_hooks_->DidFinishImplFrameOnThread(this); | 137 test_hooks_->DidFinishImplFrameOnThread(this); |
| 137 } | 138 } |
| 138 | 139 |
| 140 void DidSendBeginMainFrame() override { |
| 141 LayerTreeHostImpl::DidSendBeginMainFrame(); |
| 142 test_hooks_->DidSendBeginMainFrameOnThread(this); |
| 143 } |
| 144 |
| 139 void BeginMainFrameAborted( | 145 void BeginMainFrameAborted( |
| 140 CommitEarlyOutReason reason, | 146 CommitEarlyOutReason reason, |
| 141 std::vector<std::unique_ptr<SwapPromise>> swap_promises) override { | 147 std::vector<std::unique_ptr<SwapPromise>> swap_promises) override { |
| 142 LayerTreeHostImpl::BeginMainFrameAborted(reason, std::move(swap_promises)); | 148 LayerTreeHostImpl::BeginMainFrameAborted(reason, std::move(swap_promises)); |
| 143 test_hooks_->BeginMainFrameAbortedOnThread(this, reason); | 149 test_hooks_->BeginMainFrameAbortedOnThread(this, reason); |
| 144 } | 150 } |
| 145 | 151 |
| 146 void ReadyToCommit() override { | 152 void ReadyToCommit() override { |
| 147 LayerTreeHostImpl::ReadyToCommit(); | 153 LayerTreeHostImpl::ReadyToCommit(); |
| 148 test_hooks_->ReadyToCommitOnThread(this); | 154 test_hooks_->ReadyToCommitOnThread(this); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 block_notify_ready_to_activate_for_testing_ = block; | 207 block_notify_ready_to_activate_for_testing_ = block; |
| 202 if (!block && notify_ready_to_activate_was_blocked_) { | 208 if (!block && notify_ready_to_activate_was_blocked_) { |
| 203 task_runner_provider_->ImplThreadTaskRunner()->PostTask( | 209 task_runner_provider_->ImplThreadTaskRunner()->PostTask( |
| 204 FROM_HERE, | 210 FROM_HERE, |
| 205 base::Bind(&LayerTreeHostImplForTesting::NotifyReadyToActivate, | 211 base::Bind(&LayerTreeHostImplForTesting::NotifyReadyToActivate, |
| 206 base::Unretained(this))); | 212 base::Unretained(this))); |
| 207 notify_ready_to_activate_was_blocked_ = false; | 213 notify_ready_to_activate_was_blocked_ = false; |
| 208 } | 214 } |
| 209 } | 215 } |
| 210 | 216 |
| 217 void BlockImplSideInvalidationRequestsForTesting(bool block) override { |
| 218 block_impl_side_invalidation_ = block; |
| 219 if (!block_impl_side_invalidation_ && impl_side_invalidation_was_blocked_) { |
| 220 RequestImplSideInvalidation(); |
| 221 } |
| 222 } |
| 223 |
| 211 void ActivateSyncTree() override { | 224 void ActivateSyncTree() override { |
| 212 test_hooks_->WillActivateTreeOnThread(this); | 225 test_hooks_->WillActivateTreeOnThread(this); |
| 213 LayerTreeHostImpl::ActivateSyncTree(); | 226 LayerTreeHostImpl::ActivateSyncTree(); |
| 214 DCHECK(!pending_tree()); | 227 DCHECK(!pending_tree()); |
| 215 test_hooks_->DidActivateTreeOnThread(this); | 228 test_hooks_->DidActivateTreeOnThread(this); |
| 216 } | 229 } |
| 217 | 230 |
| 218 bool InitializeRenderer(CompositorFrameSink* compositor_frame_sink) override { | 231 bool InitializeRenderer(CompositorFrameSink* compositor_frame_sink) override { |
| 219 bool success = LayerTreeHostImpl::InitializeRenderer(compositor_frame_sink); | 232 bool success = LayerTreeHostImpl::InitializeRenderer(compositor_frame_sink); |
| 220 test_hooks_->InitializedRendererOnThread(this, success); | 233 test_hooks_->InitializedRendererOnThread(this, success); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 243 } | 256 } |
| 244 } | 257 } |
| 245 test_hooks_->UpdateAnimationState(this, has_unfinished_animation); | 258 test_hooks_->UpdateAnimationState(this, has_unfinished_animation); |
| 246 } | 259 } |
| 247 | 260 |
| 248 void NotifyTileStateChanged(const Tile* tile) override { | 261 void NotifyTileStateChanged(const Tile* tile) override { |
| 249 LayerTreeHostImpl::NotifyTileStateChanged(tile); | 262 LayerTreeHostImpl::NotifyTileStateChanged(tile); |
| 250 test_hooks_->NotifyTileStateChangedOnThread(this, tile); | 263 test_hooks_->NotifyTileStateChangedOnThread(this, tile); |
| 251 } | 264 } |
| 252 | 265 |
| 266 void InvalidateContentOnImplSide() override { |
| 267 LayerTreeHostImpl::InvalidateContentOnImplSide(); |
| 268 test_hooks_->DidInvalidateContentOnImplSide(this); |
| 269 } |
| 270 |
| 271 void RequestImplSideInvalidation() override { |
| 272 if (block_impl_side_invalidation_) { |
| 273 impl_side_invalidation_was_blocked_ = true; |
| 274 return; |
| 275 } |
| 276 |
| 277 impl_side_invalidation_was_blocked_ = false; |
| 278 LayerTreeHostImpl::RequestImplSideInvalidation(); |
| 279 test_hooks_->DidRequestImplSideInvalidation(this); |
| 280 } |
| 281 |
| 253 AnimationHost* animation_host() const { | 282 AnimationHost* animation_host() const { |
| 254 return static_cast<AnimationHost*>(mutator_host()); | 283 return static_cast<AnimationHost*>(mutator_host()); |
| 255 } | 284 } |
| 256 | 285 |
| 257 private: | 286 private: |
| 258 TestHooks* test_hooks_; | 287 TestHooks* test_hooks_; |
| 259 bool block_notify_ready_to_activate_for_testing_; | 288 bool block_notify_ready_to_activate_for_testing_ = false; |
| 260 bool notify_ready_to_activate_was_blocked_; | 289 bool notify_ready_to_activate_was_blocked_ = false; |
| 290 |
| 291 bool block_impl_side_invalidation_ = false; |
| 292 bool impl_side_invalidation_was_blocked_ = false; |
| 261 }; | 293 }; |
| 262 | 294 |
| 263 // Implementation of LayerTreeHost callback interface. | 295 // Implementation of LayerTreeHost callback interface. |
| 264 class LayerTreeHostClientForTesting : public LayerTreeHostClient, | 296 class LayerTreeHostClientForTesting : public LayerTreeHostClient, |
| 265 public LayerTreeHostSingleThreadClient { | 297 public LayerTreeHostSingleThreadClient { |
| 266 public: | 298 public: |
| 267 static std::unique_ptr<LayerTreeHostClientForTesting> Create( | 299 static std::unique_ptr<LayerTreeHostClientForTesting> Create( |
| 268 TestHooks* test_hooks) { | 300 TestHooks* test_hooks) { |
| 269 return base::WrapUnique(new LayerTreeHostClientForTesting(test_hooks)); | 301 return base::WrapUnique(new LayerTreeHostClientForTesting(test_hooks)); |
| 270 } | 302 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 public: | 367 public: |
| 336 static std::unique_ptr<LayerTreeHostForTesting> Create( | 368 static std::unique_ptr<LayerTreeHostForTesting> Create( |
| 337 TestHooks* test_hooks, | 369 TestHooks* test_hooks, |
| 338 CompositorMode mode, | 370 CompositorMode mode, |
| 339 LayerTreeHostClient* client, | 371 LayerTreeHostClient* client, |
| 340 LayerTreeHostSingleThreadClient* single_thread_client, | 372 LayerTreeHostSingleThreadClient* single_thread_client, |
| 341 TaskGraphRunner* task_graph_runner, | 373 TaskGraphRunner* task_graph_runner, |
| 342 const LayerTreeSettings& settings, | 374 const LayerTreeSettings& settings, |
| 343 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 375 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| 344 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, | 376 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner, |
| 377 scoped_refptr<base::SequencedTaskRunner> image_worker_task_runner, |
| 345 MutatorHost* mutator_host) { | 378 MutatorHost* mutator_host) { |
| 346 LayerTreeHost::InitParams params; | 379 LayerTreeHost::InitParams params; |
| 347 params.client = client; | 380 params.client = client; |
| 348 params.task_graph_runner = task_graph_runner; | 381 params.task_graph_runner = task_graph_runner; |
| 349 params.settings = &settings; | 382 params.settings = &settings; |
| 350 params.mutator_host = mutator_host; | 383 params.mutator_host = mutator_host; |
| 384 params.image_worker_task_runner = std::move(image_worker_task_runner); |
| 351 | 385 |
| 352 std::unique_ptr<LayerTreeHostForTesting> layer_tree_host( | 386 std::unique_ptr<LayerTreeHostForTesting> layer_tree_host( |
| 353 new LayerTreeHostForTesting(test_hooks, ¶ms, mode)); | 387 new LayerTreeHostForTesting(test_hooks, ¶ms, mode)); |
| 354 std::unique_ptr<TaskRunnerProvider> task_runner_provider = | 388 std::unique_ptr<TaskRunnerProvider> task_runner_provider = |
| 355 TaskRunnerProvider::Create(main_task_runner, impl_task_runner); | 389 TaskRunnerProvider::Create(main_task_runner, impl_task_runner); |
| 356 std::unique_ptr<Proxy> proxy; | 390 std::unique_ptr<Proxy> proxy; |
| 357 switch (mode) { | 391 switch (mode) { |
| 358 case CompositorMode::SINGLE_THREADED: | 392 case CompositorMode::SINGLE_THREADED: |
| 359 proxy = SingleThreadProxy::Create(layer_tree_host.get(), | 393 proxy = SingleThreadProxy::Create(layer_tree_host.get(), |
| 360 single_thread_client, | 394 single_thread_client, |
| 361 task_runner_provider.get()); | 395 task_runner_provider.get()); |
| 362 break; | 396 break; |
| 363 case CompositorMode::THREADED: | 397 case CompositorMode::THREADED: |
| 364 DCHECK(impl_task_runner.get()); | 398 DCHECK(impl_task_runner.get()); |
| 365 proxy = base::MakeUnique<ProxyMain>(layer_tree_host.get(), | 399 proxy = base::MakeUnique<ProxyMain>(layer_tree_host.get(), |
| 366 task_runner_provider.get()); | 400 task_runner_provider.get()); |
| 367 break; | 401 break; |
| 368 } | 402 } |
| 369 layer_tree_host->InitializeForTesting(std::move(task_runner_provider), | 403 layer_tree_host->InitializeForTesting(std::move(task_runner_provider), |
| 370 std::move(proxy)); | 404 std::move(proxy)); |
| 371 return layer_tree_host; | 405 return layer_tree_host; |
| 372 } | 406 } |
| 373 | 407 |
| 374 std::unique_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl( | 408 std::unique_ptr<LayerTreeHostImpl> CreateLayerTreeHostImpl( |
| 375 LayerTreeHostImplClient* host_impl_client) override { | 409 LayerTreeHostImplClient* host_impl_client) override { |
| 376 std::unique_ptr<LayerTreeHostImpl> host_impl = | 410 std::unique_ptr<LayerTreeHostImpl> host_impl = |
| 377 LayerTreeHostImplForTesting::Create( | 411 LayerTreeHostImplForTesting::Create( |
| 378 test_hooks_, GetSettings(), host_impl_client, | 412 test_hooks_, GetSettings(), host_impl_client, |
| 379 GetTaskRunnerProvider(), task_graph_runner(), | 413 GetTaskRunnerProvider(), task_graph_runner(), |
| 380 rendering_stats_instrumentation()); | 414 rendering_stats_instrumentation(), image_worker_task_runner_); |
| 381 input_handler_weak_ptr_ = host_impl->AsWeakPtr(); | 415 input_handler_weak_ptr_ = host_impl->AsWeakPtr(); |
| 382 return host_impl; | 416 return host_impl; |
| 383 } | 417 } |
| 384 | 418 |
| 385 void SetNeedsCommit() override { | 419 void SetNeedsCommit() override { |
| 386 if (!test_started_) | 420 if (!test_started_) |
| 387 return; | 421 return; |
| 388 LayerTreeHost::SetNeedsCommit(); | 422 LayerTreeHost::SetNeedsCommit(); |
| 389 } | 423 } |
| 390 | 424 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 | 622 |
| 589 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner = | 623 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner = |
| 590 base::ThreadTaskRunnerHandle::Get(); | 624 base::ThreadTaskRunnerHandle::Get(); |
| 591 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner = | 625 scoped_refptr<base::SingleThreadTaskRunner> impl_task_runner = |
| 592 impl_thread_ ? impl_thread_->task_runner() : nullptr; | 626 impl_thread_ ? impl_thread_->task_runner() : nullptr; |
| 593 | 627 |
| 594 animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN); | 628 animation_host_ = AnimationHost::CreateForTesting(ThreadInstance::MAIN); |
| 595 | 629 |
| 596 layer_tree_host_ = LayerTreeHostForTesting::Create( | 630 layer_tree_host_ = LayerTreeHostForTesting::Create( |
| 597 this, mode_, client_.get(), client_.get(), task_graph_runner_.get(), | 631 this, mode_, client_.get(), client_.get(), task_graph_runner_.get(), |
| 598 settings_, main_task_runner, impl_task_runner, animation_host_.get()); | 632 settings_, main_task_runner, impl_task_runner, |
| 633 image_worker_->task_runner(), animation_host_.get()); |
| 599 ASSERT_TRUE(layer_tree_host_); | 634 ASSERT_TRUE(layer_tree_host_); |
| 600 | 635 |
| 601 main_task_runner_ = | 636 main_task_runner_ = |
| 602 layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner(); | 637 layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner(); |
| 603 impl_task_runner_ = | 638 impl_task_runner_ = |
| 604 layer_tree_host_->GetTaskRunnerProvider()->ImplThreadTaskRunner(); | 639 layer_tree_host_->GetTaskRunnerProvider()->ImplThreadTaskRunner(); |
| 605 if (!impl_task_runner_) { | 640 if (!impl_task_runner_) { |
| 606 // For tests, if there's no impl thread, make things easier by just giving | 641 // For tests, if there's no impl thread, make things easier by just giving |
| 607 // the main thread task runner. | 642 // the main thread task runner. |
| 608 impl_task_runner_ = main_task_runner_; | 643 impl_task_runner_ = main_task_runner_; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 layer_tree_host_->SetNextCommitWaitsForActivation(); | 769 layer_tree_host_->SetNextCommitWaitsForActivation(); |
| 735 } | 770 } |
| 736 | 771 |
| 737 void LayerTreeTest::RunTest(CompositorMode mode) { | 772 void LayerTreeTest::RunTest(CompositorMode mode) { |
| 738 mode_ = mode; | 773 mode_ = mode; |
| 739 if (mode_ == CompositorMode::THREADED) { | 774 if (mode_ == CompositorMode::THREADED) { |
| 740 impl_thread_.reset(new base::Thread("Compositor")); | 775 impl_thread_.reset(new base::Thread("Compositor")); |
| 741 ASSERT_TRUE(impl_thread_->Start()); | 776 ASSERT_TRUE(impl_thread_->Start()); |
| 742 } | 777 } |
| 743 | 778 |
| 779 image_worker_ = base::MakeUnique<base::Thread>("ImageWorker"); |
| 780 ASSERT_TRUE(image_worker_->Start()); |
| 781 |
| 744 shared_bitmap_manager_.reset(new TestSharedBitmapManager); | 782 shared_bitmap_manager_.reset(new TestSharedBitmapManager); |
| 745 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager); | 783 gpu_memory_buffer_manager_.reset(new TestGpuMemoryBufferManager); |
| 746 task_graph_runner_.reset(new TestTaskGraphRunner); | 784 task_graph_runner_.reset(new TestTaskGraphRunner); |
| 747 | 785 |
| 748 // Spend less time waiting for BeginFrame because the output is | 786 // Spend less time waiting for BeginFrame because the output is |
| 749 // mocked out. | 787 // mocked out. |
| 750 settings_.renderer_settings.refresh_rate = 200.0; | 788 settings_.renderer_settings.refresh_rate = 200.0; |
| 751 settings_.background_animation_rate = 200.0; | 789 settings_.background_animation_rate = 200.0; |
| 752 // Disable latency recovery to make the scheduler more predictable in its | 790 // Disable latency recovery to make the scheduler more predictable in its |
| 753 // actions and less dependent on timings to make decisions. | 791 // actions and less dependent on timings to make decisions. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 DCHECK(task_runner_provider()->IsMainThread() || | 869 DCHECK(task_runner_provider()->IsMainThread() || |
| 832 task_runner_provider()->IsMainThreadBlocked()); | 870 task_runner_provider()->IsMainThreadBlocked()); |
| 833 return layer_tree_host_.get(); | 871 return layer_tree_host_.get(); |
| 834 } | 872 } |
| 835 | 873 |
| 836 Proxy* LayerTreeTest::proxy() { | 874 Proxy* LayerTreeTest::proxy() { |
| 837 return layer_tree_host() ? layer_tree_host()->proxy() : NULL; | 875 return layer_tree_host() ? layer_tree_host()->proxy() : NULL; |
| 838 } | 876 } |
| 839 | 877 |
| 840 } // namespace cc | 878 } // namespace cc |
| OLD | NEW |