OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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 // This file contains the tests for the RingBuffer class. |
| 6 |
| 7 #include "gpu/command_buffer/client/ring_buffer.h" |
| 8 #include "base/at_exit.h" |
| 9 #include "base/callback.h" |
| 10 #include "base/message_loop.h" |
| 11 #include "base/scoped_nsautorelease_pool.h" |
| 12 #include "gpu/command_buffer/client/cmd_buffer_helper.h" |
| 13 #include "gpu/command_buffer/service/cmd_buffer_engine.h" |
| 14 #include "gpu/command_buffer/service/mocks.h" |
| 15 #include "gpu/command_buffer/service/command_buffer_service.h" |
| 16 #include "gpu/command_buffer/service/gpu_processor.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 namespace gpu { |
| 20 |
| 21 using testing::Return; |
| 22 using testing::Mock; |
| 23 using testing::Truly; |
| 24 using testing::Sequence; |
| 25 using testing::DoAll; |
| 26 using testing::Invoke; |
| 27 using testing::_; |
| 28 |
| 29 class BaseRingBufferTest : public testing::Test { |
| 30 protected: |
| 31 static const unsigned int kBaseOffset = 128; |
| 32 static const unsigned int kBufferSize = 1024; |
| 33 |
| 34 virtual void SetUp() { |
| 35 api_mock_.reset(new AsyncAPIMock); |
| 36 // ignore noops in the mock - we don't want to inspect the internals of the |
| 37 // helper. |
| 38 EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, 0, _)) |
| 39 .WillRepeatedly(Return(error::kNoError)); |
| 40 // Forward the SetToken calls to the engine |
| 41 EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _)) |
| 42 .WillRepeatedly(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken), |
| 43 Return(error::kNoError))); |
| 44 |
| 45 command_buffer_.reset(new CommandBufferService); |
| 46 command_buffer_->Initialize(kBufferSize / sizeof(CommandBufferEntry)); |
| 47 Buffer ring_buffer = command_buffer_->GetRingBuffer(); |
| 48 |
| 49 parser_ = new CommandParser(ring_buffer.ptr, |
| 50 ring_buffer.size, |
| 51 0, |
| 52 ring_buffer.size, |
| 53 0, |
| 54 api_mock_.get()); |
| 55 |
| 56 gpu_processor_.reset(new GPUProcessor( |
| 57 command_buffer_.get(), NULL, parser_, INT_MAX)); |
| 58 command_buffer_->SetPutOffsetChangeCallback(NewCallback( |
| 59 gpu_processor_.get(), &GPUProcessor::ProcessCommands)); |
| 60 |
| 61 api_mock_->set_engine(gpu_processor_.get()); |
| 62 |
| 63 helper_.reset(new CommandBufferHelper(command_buffer_.get())); |
| 64 helper_->Initialize(); |
| 65 } |
| 66 |
| 67 int32 GetToken() { |
| 68 return command_buffer_->GetState().token; |
| 69 } |
| 70 |
| 71 virtual void TearDown() { |
| 72 helper_.release(); |
| 73 } |
| 74 |
| 75 base::ScopedNSAutoreleasePool autorelease_pool_; |
| 76 base::AtExitManager at_exit_manager_; |
| 77 MessageLoop message_loop_; |
| 78 scoped_ptr<AsyncAPIMock> api_mock_; |
| 79 scoped_ptr<CommandBufferService> command_buffer_; |
| 80 scoped_ptr<GPUProcessor> gpu_processor_; |
| 81 CommandParser* parser_; |
| 82 scoped_ptr<CommandBufferHelper> helper_; |
| 83 }; |
| 84 |
| 85 #ifndef COMPILER_MSVC |
| 86 const unsigned int BaseRingBufferTest::kBaseOffset; |
| 87 const unsigned int BaseRingBufferTest::kBufferSize; |
| 88 #endif |
| 89 |
| 90 // Test fixture for RingBuffer test - Creates a RingBuffer, using a |
| 91 // CommandBufferHelper with a mock AsyncAPIInterface for its interface (calling |
| 92 // it directly, not through the RPC mechanism), making sure Noops are ignored |
| 93 // and SetToken are properly forwarded to the engine. |
| 94 class RingBufferTest : public BaseRingBufferTest { |
| 95 protected: |
| 96 virtual void SetUp() { |
| 97 BaseRingBufferTest::SetUp(); |
| 98 allocator_.reset(new RingBuffer(kBaseOffset, kBufferSize, helper_.get())); |
| 99 } |
| 100 |
| 101 virtual void TearDown() { |
| 102 // If the GPUProcessor posts any tasks, this forces them to run. |
| 103 MessageLoop::current()->RunAllPending(); |
| 104 |
| 105 allocator_.release(); |
| 106 |
| 107 BaseRingBufferTest::TearDown(); |
| 108 } |
| 109 |
| 110 scoped_ptr<RingBuffer> allocator_; |
| 111 }; |
| 112 |
| 113 // Checks basic alloc and free. |
| 114 TEST_F(RingBufferTest, TestBasic) { |
| 115 const unsigned int kSize = 16; |
| 116 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize()); |
| 117 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSizeNoWaiting()); |
| 118 RingBuffer::Offset offset = allocator_->Alloc(kSize); |
| 119 EXPECT_GE(kBufferSize, offset - kBaseOffset + kSize); |
| 120 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeOrPendingSize()); |
| 121 EXPECT_EQ(kBufferSize - kSize, allocator_->GetLargestFreeSizeNoWaiting()); |
| 122 int32 token = helper_.get()->InsertToken(); |
| 123 allocator_->FreePendingToken(offset, token); |
| 124 } |
| 125 |
| 126 // Checks the free-pending-token mechanism. |
| 127 TEST_F(RingBufferTest, TestFreePendingToken) { |
| 128 const unsigned int kSize = 16; |
| 129 const unsigned int kAllocCount = kBufferSize / kSize; |
| 130 CHECK(kAllocCount * kSize == kBufferSize); |
| 131 |
| 132 // Allocate several buffers to fill in the memory. |
| 133 int32 tokens[kAllocCount]; |
| 134 for (unsigned int ii = 0; ii < kAllocCount; ++ii) { |
| 135 RingBuffer::Offset offset = allocator_->Alloc(kSize); |
| 136 EXPECT_GE(kBufferSize, offset - kBaseOffset + kSize); |
| 137 tokens[ii] = helper_.get()->InsertToken(); |
| 138 allocator_->FreePendingToken(offset, tokens[ii]); |
| 139 } |
| 140 |
| 141 EXPECT_EQ(kBufferSize - (kSize * kAllocCount), |
| 142 allocator_->GetLargestFreeSizeNoWaiting()); |
| 143 |
| 144 // This allocation will need to reclaim the space freed above, so that should |
| 145 // process the commands until a token is passed. |
| 146 RingBuffer::Offset offset1 = allocator_->Alloc(kSize); |
| 147 EXPECT_EQ(kBaseOffset, offset1); |
| 148 |
| 149 // Check that the token has indeed passed. |
| 150 EXPECT_LE(tokens[0], GetToken()); |
| 151 |
| 152 allocator_->FreePendingToken(offset1, helper_.get()->InsertToken()); |
| 153 } |
| 154 |
| 155 // Tests GetLargestFreeSizeNoWaiting |
| 156 TEST_F(RingBufferTest, TestGetLargestFreeSizeNoWaiting) { |
| 157 EXPECT_EQ(kBufferSize, allocator_->GetLargestFreeSizeNoWaiting()); |
| 158 |
| 159 RingBuffer::Offset offset = allocator_->Alloc(kBufferSize); |
| 160 EXPECT_EQ(0u, allocator_->GetLargestFreeSizeNoWaiting()); |
| 161 allocator_->FreePendingToken(offset, helper_.get()->InsertToken()); |
| 162 } |
| 163 |
| 164 // Test fixture for RingBufferWrapper test - Creates a |
| 165 // RingBufferWrapper, using a CommandBufferHelper with a mock |
| 166 // AsyncAPIInterface for its interface (calling it directly, not through the |
| 167 // RPC mechanism), making sure Noops are ignored and SetToken are properly |
| 168 // forwarded to the engine. |
| 169 class RingBufferWrapperTest : public BaseRingBufferTest { |
| 170 protected: |
| 171 virtual void SetUp() { |
| 172 BaseRingBufferTest::SetUp(); |
| 173 |
| 174 // Though allocating this buffer isn't strictly necessary, it makes |
| 175 // allocations point to valid addresses, so they could be used for |
| 176 // something. |
| 177 buffer_.reset(new int8[kBufferSize + kBaseOffset]); |
| 178 buffer_start_ = buffer_.get() + kBaseOffset; |
| 179 allocator_.reset(new RingBufferWrapper( |
| 180 kBaseOffset, kBufferSize, helper_.get(), buffer_start_)); |
| 181 } |
| 182 |
| 183 virtual void TearDown() { |
| 184 // If the GPUProcessor posts any tasks, this forces them to run. |
| 185 MessageLoop::current()->RunAllPending(); |
| 186 |
| 187 allocator_.release(); |
| 188 buffer_.release(); |
| 189 |
| 190 BaseRingBufferTest::TearDown(); |
| 191 } |
| 192 |
| 193 scoped_ptr<RingBufferWrapper> allocator_; |
| 194 scoped_array<int8> buffer_; |
| 195 int8* buffer_start_; |
| 196 }; |
| 197 |
| 198 // Checks basic alloc and free. |
| 199 TEST_F(RingBufferWrapperTest, TestBasic) { |
| 200 const unsigned int kSize = 16; |
| 201 void* pointer = allocator_->Alloc(kSize); |
| 202 ASSERT_TRUE(pointer); |
| 203 EXPECT_LE(buffer_start_, static_cast<int8*>(pointer)); |
| 204 EXPECT_GE(kBufferSize, static_cast<int8*>(pointer) - buffer_start_ + kSize); |
| 205 |
| 206 allocator_->FreePendingToken(pointer, helper_.get()->InsertToken()); |
| 207 |
| 208 int8* pointer_int8 = allocator_->AllocTyped<int8>(kSize); |
| 209 ASSERT_TRUE(pointer_int8); |
| 210 EXPECT_LE(buffer_start_, pointer_int8); |
| 211 EXPECT_GE(buffer_start_ + kBufferSize, pointer_int8 + kSize); |
| 212 allocator_->FreePendingToken(pointer_int8, helper_.get()->InsertToken()); |
| 213 |
| 214 unsigned int* pointer_uint = allocator_->AllocTyped<unsigned int>(kSize); |
| 215 ASSERT_TRUE(pointer_uint); |
| 216 EXPECT_LE(buffer_start_, reinterpret_cast<int8*>(pointer_uint)); |
| 217 EXPECT_GE(buffer_start_ + kBufferSize, |
| 218 reinterpret_cast<int8* >(pointer_uint + kSize)); |
| 219 |
| 220 // Check that it did allocate kSize * sizeof(unsigned int). We can't tell |
| 221 // directly, except from the remaining size. |
| 222 EXPECT_EQ(kBufferSize - kSize - kSize - kSize * sizeof(*pointer_uint), |
| 223 allocator_->GetLargestFreeSizeNoWaiting()); |
| 224 allocator_->FreePendingToken(pointer_uint, helper_.get()->InsertToken()); |
| 225 } |
| 226 |
| 227 // Checks the free-pending-token mechanism. |
| 228 TEST_F(RingBufferWrapperTest, TestFreePendingToken) { |
| 229 const unsigned int kSize = 16; |
| 230 const unsigned int kAllocCount = kBufferSize / kSize; |
| 231 CHECK(kAllocCount * kSize == kBufferSize); |
| 232 |
| 233 // Allocate several buffers to fill in the memory. |
| 234 int32 tokens[kAllocCount]; |
| 235 for (unsigned int ii = 0; ii < kAllocCount; ++ii) { |
| 236 void* pointer = allocator_->Alloc(kSize); |
| 237 EXPECT_TRUE(pointer != NULL); |
| 238 tokens[ii] = helper_.get()->InsertToken(); |
| 239 allocator_->FreePendingToken(pointer, helper_.get()->InsertToken()); |
| 240 } |
| 241 |
| 242 EXPECT_EQ(kBufferSize - (kSize * kAllocCount), |
| 243 allocator_->GetLargestFreeSizeNoWaiting()); |
| 244 |
| 245 // This allocation will need to reclaim the space freed above, so that should |
| 246 // process the commands until the token is passed. |
| 247 void* pointer1 = allocator_->Alloc(kSize); |
| 248 EXPECT_EQ(buffer_start_, static_cast<int8*>(pointer1)); |
| 249 |
| 250 // Check that the token has indeed passed. |
| 251 EXPECT_LE(tokens[0], GetToken()); |
| 252 |
| 253 allocator_->FreePendingToken(pointer1, helper_.get()->InsertToken()); |
| 254 } |
| 255 |
| 256 } // namespace gpu |
OLD | NEW |