OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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 "content/browser/renderer_host/software_frame_manager.h" |
| 6 |
| 7 #include <vector> |
| 8 |
| 9 #include "base/sys_info.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" |
| 11 |
| 12 namespace content { |
| 13 |
| 14 class FakeSoftwareFrameManagerClient : public SoftwareFrameManagerClient { |
| 15 public: |
| 16 FakeSoftwareFrameManagerClient() |
| 17 : evicted_count_(0), weak_ptr_factory_(this) { |
| 18 software_frame_manager_.reset(new SoftwareFrameManager( |
| 19 weak_ptr_factory_.GetWeakPtr())); |
| 20 } |
| 21 virtual ~FakeSoftwareFrameManagerClient() {} |
| 22 virtual void SoftwareFrameWasFreed( |
| 23 uint32 output_surface_id, unsigned frame_id) OVERRIDE { |
| 24 freed_frames_.push_back(std::make_pair(output_surface_id, frame_id)); |
| 25 } |
| 26 virtual void ReleaseReferencesToSoftwareFrame() OVERRIDE { |
| 27 ++evicted_count_; |
| 28 } |
| 29 |
| 30 bool SwapToNewFrame(uint32 output_surface, unsigned frame_id) { |
| 31 cc::SoftwareFrameData frame; |
| 32 frame.id = frame_id; |
| 33 frame.size = gfx::Size(1, 1); |
| 34 frame.damage_rect = gfx::Rect(frame.size); |
| 35 frame.handle = base::SharedMemory::NULLHandle(); |
| 36 return software_frame_manager_->SwapToNewFrame( |
| 37 output_surface, &frame, 1.0, base::GetCurrentProcessHandle()); |
| 38 } |
| 39 |
| 40 SoftwareFrameManager* software_frame_manager() { |
| 41 return software_frame_manager_.get(); |
| 42 } |
| 43 size_t freed_frame_count() const { return freed_frames_.size(); } |
| 44 size_t evicted_frame_count() const { return evicted_count_; } |
| 45 |
| 46 private: |
| 47 std::vector<std::pair<uint32,unsigned> > freed_frames_; |
| 48 size_t evicted_count_; |
| 49 |
| 50 scoped_ptr<SoftwareFrameManager> software_frame_manager_; |
| 51 base::WeakPtrFactory<FakeSoftwareFrameManagerClient> |
| 52 weak_ptr_factory_; |
| 53 |
| 54 DISALLOW_COPY_AND_ASSIGN(FakeSoftwareFrameManagerClient); |
| 55 }; |
| 56 |
| 57 class SoftwareFrameManagerTest : public testing::Test { |
| 58 public: |
| 59 SoftwareFrameManagerTest() {} |
| 60 void AllocateClients(size_t num_clients) { |
| 61 for (size_t i = 0; i < num_clients; ++i) |
| 62 clients_.push_back(new FakeSoftwareFrameManagerClient); |
| 63 } |
| 64 void FreeClients() { |
| 65 for (size_t i = 0; i < clients_.size(); ++i) |
| 66 delete clients_[i]; |
| 67 clients_.clear(); |
| 68 } |
| 69 size_t MaxNumberOfSavedFrames() const { |
| 70 size_t result = SoftwareFrameMemoryManager::GetInstance()-> |
| 71 max_number_of_saved_frames(); |
| 72 return result; |
| 73 } |
| 74 |
| 75 protected: |
| 76 std::vector<FakeSoftwareFrameManagerClient*> clients_; |
| 77 |
| 78 private: |
| 79 DISALLOW_COPY_AND_ASSIGN(SoftwareFrameManagerTest); |
| 80 }; |
| 81 |
| 82 TEST_F(SoftwareFrameManagerTest, DoNotEvictVisible) { |
| 83 // Create twice as many frames as are allowed. |
| 84 AllocateClients(2 * MaxNumberOfSavedFrames()); |
| 85 |
| 86 // Swap a visible frame to all clients_. Because they are all visible, |
| 87 // the should not be evicted. |
| 88 for (size_t i = 0; i < clients_.size(); ++i) { |
| 89 bool swap_result = clients_[i]->SwapToNewFrame( |
| 90 static_cast<uint32>(i), 0); |
| 91 clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true); |
| 92 EXPECT_TRUE(swap_result); |
| 93 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 94 EXPECT_EQ(0u, clients_[i]->freed_frame_count()); |
| 95 } |
| 96 for (size_t i = 0; i < clients_.size(); ++i) { |
| 97 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 98 EXPECT_EQ(0u, clients_[i]->freed_frame_count()); |
| 99 } |
| 100 |
| 101 // Swap another frame and make sure the original was freed (but not evicted). |
| 102 for (size_t i = 0; i < clients_.size(); ++i) { |
| 103 bool swap_result = clients_[i]->SwapToNewFrame( |
| 104 static_cast<uint32>(i), 1); |
| 105 clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true); |
| 106 EXPECT_TRUE(swap_result); |
| 107 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 108 EXPECT_EQ(1u, clients_[i]->freed_frame_count()); |
| 109 } |
| 110 for (size_t i = 0; i < clients_.size(); ++i) { |
| 111 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 112 EXPECT_EQ(1u, clients_[i]->freed_frame_count()); |
| 113 } |
| 114 |
| 115 // Mark the frames as nonvisible and make sure they start getting evicted. |
| 116 for (size_t i = 0; i < clients_.size(); ++i) { |
| 117 clients_[i]->software_frame_manager()->SetVisibility(false); |
| 118 if (clients_.size() - i > MaxNumberOfSavedFrames()) { |
| 119 EXPECT_EQ(1u, clients_[i]->evicted_frame_count()); |
| 120 EXPECT_EQ(2u, clients_[i]->freed_frame_count()); |
| 121 } else { |
| 122 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 123 EXPECT_EQ(1u, clients_[i]->freed_frame_count()); |
| 124 } |
| 125 } |
| 126 |
| 127 // Clean up. |
| 128 FreeClients(); |
| 129 } |
| 130 |
| 131 TEST_F(SoftwareFrameManagerTest, DoNotEvictDuringSwap) { |
| 132 // Create twice as many frames as are allowed. |
| 133 AllocateClients(2 * MaxNumberOfSavedFrames()); |
| 134 |
| 135 // Swap a visible frame to all clients_. Because they are all visible, |
| 136 // the should not be evicted. |
| 137 for (size_t i = 0; i < clients_.size(); ++i) { |
| 138 bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); |
| 139 clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true); |
| 140 EXPECT_TRUE(swap_result); |
| 141 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 142 EXPECT_EQ(0u, clients_[i]->freed_frame_count()); |
| 143 } |
| 144 for (size_t i = 0; i < clients_.size(); ++i) { |
| 145 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 146 EXPECT_EQ(0u, clients_[i]->freed_frame_count()); |
| 147 } |
| 148 |
| 149 // Now create a test non-visible client, and swap a non-visible frame in. |
| 150 scoped_ptr<FakeSoftwareFrameManagerClient> test_client( |
| 151 new FakeSoftwareFrameManagerClient); |
| 152 test_client->software_frame_manager()->SetVisibility(false); |
| 153 { |
| 154 bool swap_result = test_client->SwapToNewFrame( |
| 155 static_cast<uint32>(500), 0); |
| 156 EXPECT_TRUE(swap_result); |
| 157 EXPECT_EQ(0u, test_client->evicted_frame_count()); |
| 158 EXPECT_EQ(0u, test_client->freed_frame_count()); |
| 159 test_client->software_frame_manager()->SwapToNewFrameComplete(false); |
| 160 EXPECT_EQ(1u, test_client->evicted_frame_count()); |
| 161 EXPECT_EQ(1u, test_client->freed_frame_count()); |
| 162 } |
| 163 |
| 164 // Clean up. |
| 165 FreeClients(); |
| 166 } |
| 167 |
| 168 TEST_F(SoftwareFrameManagerTest, Cleanup) { |
| 169 // Create twice as many frames as are allowed. |
| 170 AllocateClients(2 * MaxNumberOfSavedFrames()); |
| 171 |
| 172 // Swap a visible frame to all clients_. Because they are all visible, |
| 173 // the should not be evicted. |
| 174 for (size_t i = 0; i < clients_.size(); ++i) { |
| 175 bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); |
| 176 clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true); |
| 177 EXPECT_TRUE(swap_result); |
| 178 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 179 EXPECT_EQ(0u, clients_[i]->freed_frame_count()); |
| 180 } |
| 181 |
| 182 // Destroy them. |
| 183 FreeClients(); |
| 184 |
| 185 // Create the maximum number of frames, all non-visible. They should not |
| 186 // be evicted, because the previous frames were cleaned up at destruction. |
| 187 AllocateClients(MaxNumberOfSavedFrames()); |
| 188 for (size_t i = 0; i < clients_.size(); ++i) { |
| 189 cc::SoftwareFrameData frame; |
| 190 bool swap_result = clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); |
| 191 clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true); |
| 192 EXPECT_TRUE(swap_result); |
| 193 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 194 EXPECT_EQ(0u, clients_[i]->freed_frame_count()); |
| 195 } |
| 196 for (size_t i = 0; i < clients_.size(); ++i) { |
| 197 EXPECT_EQ(0u, clients_[i]->evicted_frame_count()); |
| 198 EXPECT_EQ(0u, clients_[i]->freed_frame_count()); |
| 199 } |
| 200 |
| 201 // Clean up. |
| 202 FreeClients(); |
| 203 } |
| 204 |
| 205 TEST_F(SoftwareFrameManagerTest, EvictVersusFree) { |
| 206 // Create twice as many frames as are allowed and swap a visible frame to all |
| 207 // clients_. Because they are all visible, the should not be evicted. |
| 208 AllocateClients(2 * MaxNumberOfSavedFrames()); |
| 209 for (size_t i = 0; i < clients_.size(); ++i) { |
| 210 clients_[i]->SwapToNewFrame(static_cast<uint32>(i), 0); |
| 211 clients_[i]->software_frame_manager()->SwapToNewFrameComplete(true); |
| 212 } |
| 213 |
| 214 // Create a test client with a frame that is not evicted. |
| 215 scoped_ptr<FakeSoftwareFrameManagerClient> test_client( |
| 216 new FakeSoftwareFrameManagerClient); |
| 217 bool swap_result = test_client->SwapToNewFrame(static_cast<uint32>(500), 0); |
| 218 EXPECT_TRUE(swap_result); |
| 219 test_client->software_frame_manager()->SwapToNewFrameComplete(true); |
| 220 EXPECT_EQ(0u, test_client->evicted_frame_count()); |
| 221 EXPECT_EQ(0u, test_client->freed_frame_count()); |
| 222 |
| 223 // Take out a reference on the current frame and make the memory manager |
| 224 // evict it. The frame will not be freed until this reference is released. |
| 225 cc::TextureMailbox mailbox; |
| 226 scoped_ptr<cc::SingleReleaseCallback> callback; |
| 227 test_client->software_frame_manager()->GetCurrentFrameMailbox( |
| 228 &mailbox, &callback); |
| 229 test_client->software_frame_manager()->SetVisibility(false); |
| 230 EXPECT_EQ(1u, test_client->evicted_frame_count()); |
| 231 EXPECT_EQ(0u, test_client->freed_frame_count()); |
| 232 |
| 233 // Swap a few frames. The frames will be freed as they are swapped out. |
| 234 for (size_t frame = 0; frame < 10; ++frame) { |
| 235 bool swap_result = test_client->SwapToNewFrame( |
| 236 static_cast<uint32>(500), 1 + static_cast<int>(frame)); |
| 237 EXPECT_TRUE(swap_result); |
| 238 test_client->software_frame_manager()->SwapToNewFrameComplete(true); |
| 239 EXPECT_EQ(frame, test_client->freed_frame_count()); |
| 240 EXPECT_EQ(1u, test_client->evicted_frame_count()); |
| 241 } |
| 242 |
| 243 // The reference to the frame that we didn't free is in the callback |
| 244 // object. It will go away when the callback is destroyed. |
| 245 EXPECT_EQ(9u, test_client->freed_frame_count()); |
| 246 EXPECT_EQ(1u, test_client->evicted_frame_count()); |
| 247 callback->Run(0, false); |
| 248 callback.reset(); |
| 249 EXPECT_EQ(10u, test_client->freed_frame_count()); |
| 250 EXPECT_EQ(1u, test_client->evicted_frame_count()); |
| 251 |
| 252 FreeClients(); |
| 253 } |
| 254 |
| 255 } // namespace content |
OLD | NEW |