Index: content/browser/renderer_host/software_frame_manager_unittest.cc |
diff --git a/content/browser/renderer_host/software_frame_manager_unittest.cc b/content/browser/renderer_host/software_frame_manager_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..964c2b977b6ce463b6951cbb8c1b85e6223d9434 |
--- /dev/null |
+++ b/content/browser/renderer_host/software_frame_manager_unittest.cc |
@@ -0,0 +1,246 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/browser/renderer_host/software_frame_manager.h" |
+ |
+#include <vector> |
+ |
+#include "base/sys_info.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace { |
+ |
+size_t MaxNumberOfSavedFrames() { |
+ static size_t max_number_of_saved_frames = std::min( |
+ 5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256)); |
+ return max_number_of_saved_frames; |
+} |
piman
2013/10/23 23:41:40
Ok, so, rather than duplicate the logic, which is
ccameron
2013/10/24 17:56:41
I'd duplicated this in preference to putting Softw
|
+ |
+} // namespace |
+ |
+namespace content { |
+ |
+class FakeSoftwareFrameManagerClient : public SoftwareFrameManagerClient { |
+ public: |
+ FakeSoftwareFrameManagerClient() |
+ : evicted_count_(0), weak_ptr_factory_(this) { |
+ software_frame_manager_.reset(new SoftwareFrameManager( |
+ weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ virtual ~FakeSoftwareFrameManagerClient() {} |
+ virtual void SoftwareFrameWasFreed( |
+ uint32 output_surface_id, unsigned frame_id) OVERRIDE { |
+ freed_frames_.push_back(std::make_pair(output_surface_id, frame_id)); |
+ } |
+ virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE { |
+ ++evicted_count_; |
+ } |
+ |
+ bool SwapToNewFrame(uint32 output_surface, unsigned frame_id) { |
+ cc::SoftwareFrameData frame; |
+ frame.id = frame_id; |
+ frame.size = gfx::Size(1, 1); |
+ frame.damage_rect = gfx::Rect(frame.size); |
+ frame.handle = base::SharedMemory::NULLHandle(); |
+ return software_frame_manager_->SwapToNewFrame( |
+ output_surface, &frame, 1.0, base::GetCurrentProcessHandle()); |
+ } |
+ |
+ std::vector<std::pair<uint32,unsigned> > freed_frames_; |
piman
2013/10/23 23:41:40
nit: private + accessors
ccameron
2013/10/24 17:56:41
Done.
|
+ size_t evicted_count_; |
+ |
+ scoped_ptr<SoftwareFrameManager> software_frame_manager_; |
+ base::WeakPtrFactory<FakeSoftwareFrameManagerClient> |
+ weak_ptr_factory_; |
piman
2013/10/23 23:41:40
nit: DISALLOW_COPY_AND_ASSIGN
ccameron
2013/10/24 17:56:41
Done.
|
+}; |
+ |
+class SoftwareFrameManagerTest : public testing::Test { |
+ public: |
+ void AllocateClients(size_t num_clients) { |
+ for (size_t i = 0; i < num_clients; ++i) |
+ clients_.push_back(new FakeSoftwareFrameManagerClient); |
+ } |
+ void FreeClients() { |
+ for (size_t i = 0; i < clients_.size(); ++i) |
+ delete clients_[i]; |
+ clients_.clear(); |
+ } |
+ |
+ std::vector<FakeSoftwareFrameManagerClient*> clients_; |
piman
2013/10/23 23:41:40
nit: private+accessors, DISALLOW_COPY_AND_ASSIGN
ccameron
2013/10/24 17:56:41
Made this protected instead (since all tests acces
|
+}; |
+ |
+TEST_F(SoftwareFrameManagerTest, DoNotEvictVisible) { |
+ // Create twice as many frames as are allowed. |
+ AllocateClients(2 * MaxNumberOfSavedFrames()); |
+ |
+ // Swap a visible frame to all clients_. Because they are all visible, |
+ // the should not be evicted. |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ bool swap_result = clients_[i]->SwapToNewFrame( |
+ static_cast<uint32>(i), 0); |
+ clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); |
+ EXPECT_TRUE(swap_result); |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); |
+ } |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); |
+ } |
+ |
+ // Swap another frame and make sure the original was freed (but not evicted). |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ bool swap_result = clients_[i]->SwapToNewFrame( |
+ static_cast<uint32>(i), 1); |
+ clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); |
+ EXPECT_TRUE(swap_result); |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(1u, clients_[i]->freed_frames_.size()); |
+ } |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(1u, clients_[i]->freed_frames_.size()); |
+ } |
+ |
+ // Mark the frames as nonvisible and make sure they start getting evicted. |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ clients_[i]->software_frame_manager_->SetVisibility(false); |
+ if (clients_.size() - i > MaxNumberOfSavedFrames()) { |
+ EXPECT_EQ(1u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(2u, clients_[i]->freed_frames_.size()); |
+ } else { |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(1u, clients_[i]->freed_frames_.size()); |
+ } |
+ } |
+ |
+ // Clean up. |
+ FreeClients(); |
+} |
+ |
+TEST_F(SoftwareFrameManagerTest, DoNotEvictDuringSwap) { |
+ // Create twice as many frames as are allowed. |
+ AllocateClients(2 * MaxNumberOfSavedFrames()); |
+ |
+ // Swap a visible frame to all clients_. Because they are all visible, |
+ // the should not be evicted. |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); |
+ clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); |
+ EXPECT_TRUE(swap_result); |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); |
+ } |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); |
+ } |
+ |
+ // Now create a test non-visible client, and swap a non-visible frame in. |
+ scoped_ptr<FakeSoftwareFrameManagerClient> test_client( |
+ new FakeSoftwareFrameManagerClient); |
+ test_client->software_frame_manager_->SetVisibility(false); |
+ { |
+ bool swap_result = test_client->SwapToNewFrame( |
+ static_cast<uint32>(500), 0); |
+ EXPECT_TRUE(swap_result); |
+ EXPECT_EQ(0u, test_client->evicted_count_); |
+ EXPECT_EQ(0u, test_client->freed_frames_.size()); |
+ test_client->software_frame_manager_->SwapToNewFrameComplete(false); |
+ EXPECT_EQ(1u, test_client->evicted_count_); |
+ EXPECT_EQ(1u, test_client->freed_frames_.size()); |
+ } |
+ |
+ // Clean up. |
+ FreeClients(); |
+} |
+ |
+TEST_F(SoftwareFrameManagerTest, Cleanup) { |
+ // Create twice as many frames as are allowed. |
+ AllocateClients(2 * MaxNumberOfSavedFrames()); |
+ |
+ // Swap a visible frame to all clients_. Because they are all visible, |
+ // the should not be evicted. |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); |
+ clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); |
+ EXPECT_TRUE(swap_result); |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); |
+ } |
+ |
+ // Destroy them. |
+ FreeClients(); |
+ |
+ // Create the maximum number of frames, all non-visible. They should not |
+ // be evicted, because the previous frames were cleaned up at destruction. |
+ AllocateClients(MaxNumberOfSavedFrames()); |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ cc::SoftwareFrameData frame; |
+ bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); |
+ clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); |
+ EXPECT_TRUE(swap_result); |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); |
+ } |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ EXPECT_EQ(0u, clients_[i]->evicted_count_); |
+ EXPECT_EQ(0u, clients_[i]->freed_frames_.size()); |
+ } |
+ |
+ // Clean up. |
+ FreeClients(); |
+} |
+ |
+TEST_F(SoftwareFrameManagerTest, EvictVersusFree) { |
+ // Create twice as many frames as are allowed and swap a visible frame to all |
+ // clients_. Because they are all visible, the should not be evicted. |
+ AllocateClients(2 * MaxNumberOfSavedFrames()); |
+ for (size_t i = 0; i < clients_.size(); ++i) { |
+ clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); |
+ clients_[i]->software_frame_manager_->SwapToNewFrameComplete(true); |
+ } |
+ |
+ // Create a test client with a frame that is not evicted. |
+ scoped_ptr<FakeSoftwareFrameManagerClient> test_client( |
+ new FakeSoftwareFrameManagerClient); |
+ bool swap_result = test_client->SwapToNewFrame(static_cast<uint32>(500), 0); |
+ EXPECT_TRUE(swap_result); |
+ test_client->software_frame_manager_->SwapToNewFrameComplete(true); |
+ EXPECT_EQ(0u, test_client->evicted_count_); |
+ EXPECT_EQ(0u, test_client->freed_frames_.size()); |
+ |
+ // Take out a reference on the current frame and make the memory manager |
+ // evict it. The frame will not be freed until this reference is released. |
+ cc::TextureMailbox mailbox; |
+ scoped_ptr<cc::SingleReleaseCallback> callback; |
+ test_client->software_frame_manager_->GetCurrentFrameMailbox( |
+ &mailbox, &callback); |
+ test_client->software_frame_manager_->SetVisibility(false); |
+ EXPECT_EQ(1u, test_client->evicted_count_); |
+ EXPECT_EQ(0u, test_client->freed_frames_.size()); |
+ |
+ // Swap a few frames. The frames will be freed as they are swapped out. |
+ for (size_t frame = 0; frame < 10; ++frame) { |
+ bool swap_result = test_client->SwapToNewFrame( |
+ static_cast<uint32>(500), 1 + static_cast<int>(frame)); |
+ EXPECT_TRUE(swap_result); |
+ test_client->software_frame_manager_->SwapToNewFrameComplete(true); |
+ EXPECT_EQ(frame, test_client->freed_frames_.size()); |
+ EXPECT_EQ(1u, test_client->evicted_count_); |
+ } |
+ |
+ // The reference to the frame that we didn't free is in the callback |
+ // object. It will go away when the callback is destroyed. |
+ EXPECT_EQ(9u, test_client->freed_frames_.size()); |
+ EXPECT_EQ(1u, test_client->evicted_count_); |
+ callback->Run(0, false); |
+ callback.reset(); |
+ EXPECT_EQ(10u, test_client->freed_frames_.size()); |
+ EXPECT_EQ(1u, test_client->evicted_count_); |
+ |
+ FreeClients(); |
+} |
+ |
+} // namespace content |