1 // Copyright (c) 2012 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.
5 // Tests for the Command Buffer Helper.
7 #include "gpu/command_buffer/client/transfer_buffer.h"
9 #include "base/compiler_specific.h"
10 #include "gpu/command_buffer/client/client_test_helper.h"
11 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
12 #include "gpu/command_buffer/common/command_buffer.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "testing/gmock/include/gmock/gmock.h"
17 using ::testing::AtMost;
18 using ::testing::Invoke;
19 using ::testing::Return;
20 using ::testing::SetArgPointee;
21 using ::testing::StrictMock;
26 class TransferBufferTest : public testing::Test {
28 static const int32 kNumCommandEntries = 400;
29 static const int32 kCommandBufferSizeBytes =
30 kNumCommandEntries * sizeof(CommandBufferEntry);
31 static const unsigned int kStartingOffset = 64;
32 static const unsigned int kAlignment = 4;
33 static const size_t kTransferBufferSize = 256;
36 : transfer_buffer_id_(0) {
39 virtual void SetUp() OVERRIDE;
40 virtual void TearDown() OVERRIDE;
42 virtual void Initialize(unsigned int size_to_flush) {
43 ASSERT_TRUE(transfer_buffer_->Initialize(
52 MockClientCommandBufferMockFlush* command_buffer() const {
53 return command_buffer_.get();
56 scoped_ptr<MockClientCommandBufferMockFlush> command_buffer_;
57 scoped_ptr<CommandBufferHelper> helper_;
58 scoped_ptr<TransferBuffer> transfer_buffer_;
59 int32 transfer_buffer_id_;
62 void TransferBufferTest::SetUp() {
63 command_buffer_.reset(new StrictMock<MockClientCommandBufferMockFlush>());
64 ASSERT_TRUE(command_buffer_->Initialize());
66 helper_.reset(new CommandBufferHelper(command_buffer()));
67 ASSERT_TRUE(helper_->Initialize(kCommandBufferSizeBytes));
69 transfer_buffer_id_ = command_buffer()->GetNextFreeTransferBufferId();
71 transfer_buffer_.reset(new TransferBuffer(helper_.get()));
74 void TransferBufferTest::TearDown() {
75 if (transfer_buffer_->HaveBuffer()) {
76 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
78 .RetiresOnSaturation();
80 // For command buffer.
81 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
83 .RetiresOnSaturation();
84 EXPECT_CALL(*command_buffer(), OnFlush()).Times(AtMost(1));
85 transfer_buffer_.reset();
88 // GCC requires these declarations, but MSVC requires they not be present
90 const int32 TransferBufferTest::kNumCommandEntries;
91 const int32 TransferBufferTest::kCommandBufferSizeBytes;
92 const unsigned int TransferBufferTest::kStartingOffset;
93 const unsigned int TransferBufferTest::kAlignment;
94 const size_t TransferBufferTest::kTransferBufferSize;
97 TEST_F(TransferBufferTest, Basic) {
99 EXPECT_TRUE(transfer_buffer_->HaveBuffer());
100 EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
102 kTransferBufferSize - kStartingOffset,
103 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
106 TEST_F(TransferBufferTest, Free) {
108 EXPECT_TRUE(transfer_buffer_->HaveBuffer());
109 EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
112 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
114 .RetiresOnSaturation();
115 transfer_buffer_->Free();
117 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
118 // See that it gets reallocated.
119 EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
120 EXPECT_TRUE(transfer_buffer_->HaveBuffer());
123 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
125 .RetiresOnSaturation();
126 transfer_buffer_->Free();
128 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
129 // See that it gets reallocated.
130 EXPECT_TRUE(transfer_buffer_->GetResultBuffer() != NULL);
131 EXPECT_TRUE(transfer_buffer_->HaveBuffer());
134 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
136 .RetiresOnSaturation();
137 transfer_buffer_->Free();
139 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
140 // See that it gets reallocated.
141 unsigned int size = 0;
142 void* data = transfer_buffer_->AllocUpTo(1, &size);
143 EXPECT_TRUE(data != NULL);
144 EXPECT_TRUE(transfer_buffer_->HaveBuffer());
145 transfer_buffer_->FreePendingToken(data, 1);
148 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
150 .RetiresOnSaturation();
151 transfer_buffer_->Free();
153 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
154 // See that it gets reallocated.
155 transfer_buffer_->GetResultOffset();
156 EXPECT_TRUE(transfer_buffer_->HaveBuffer());
159 kTransferBufferSize - kStartingOffset,
160 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
162 // Test freeing twice.
163 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
165 .RetiresOnSaturation();
166 transfer_buffer_->Free();
167 transfer_buffer_->Free();
170 TEST_F(TransferBufferTest, TooLargeAllocation) {
172 // Check that we can't allocate large than max size.
173 void* ptr = transfer_buffer_->Alloc(kTransferBufferSize + 1);
174 EXPECT_TRUE(ptr == NULL);
175 // Check we if we try to allocate larger than max we get max.
176 unsigned int size_allocated = 0;
177 ptr = transfer_buffer_->AllocUpTo(
178 kTransferBufferSize + 1, &size_allocated);
179 ASSERT_TRUE(ptr != NULL);
180 EXPECT_EQ(kTransferBufferSize - kStartingOffset, size_allocated);
181 transfer_buffer_->FreePendingToken(ptr, 1);
184 TEST_F(TransferBufferTest, MemoryAlignmentAfterZeroAllocation) {
186 void* ptr = transfer_buffer_->Alloc(0);
187 EXPECT_EQ((reinterpret_cast<uintptr_t>(ptr) & (kAlignment - 1)), 0u);
188 transfer_buffer_->FreePendingToken(ptr, -1);
189 // Check that the pointer is aligned on the following allocation.
190 ptr = transfer_buffer_->Alloc(4);
191 EXPECT_EQ((reinterpret_cast<uintptr_t>(ptr) & (kAlignment - 1)), 0u);
192 transfer_buffer_->FreePendingToken(ptr, 1);
195 TEST_F(TransferBufferTest, Flush) {
197 unsigned int size_allocated = 0;
198 for (int i = 0; i < 8; ++i) {
199 void* ptr = transfer_buffer_->AllocUpTo(8u, &size_allocated);
200 ASSERT_TRUE(ptr != NULL);
201 EXPECT_EQ(8u, size_allocated);
203 EXPECT_CALL(*command_buffer(), Flush(_))
205 .RetiresOnSaturation();
207 transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
209 for (int i = 0; i < 8; ++i) {
210 void* ptr = transfer_buffer_->Alloc(8u);
211 ASSERT_TRUE(ptr != NULL);
213 EXPECT_CALL(*command_buffer(), Flush(_))
215 .RetiresOnSaturation();
217 transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
221 class MockClientCommandBufferCanFail : public MockClientCommandBufferMockFlush {
223 MockClientCommandBufferCanFail() {
225 virtual ~MockClientCommandBufferCanFail() {
228 MOCK_METHOD2(CreateTransferBuffer,
229 scoped_refptr<Buffer>(size_t size, int32* id));
231 scoped_refptr<gpu::Buffer> RealCreateTransferBuffer(size_t size, int32* id) {
232 return MockCommandBufferBase::CreateTransferBuffer(size, id);
236 class TransferBufferExpandContractTest : public testing::Test {
238 static const int32 kNumCommandEntries = 400;
239 static const int32 kCommandBufferSizeBytes =
240 kNumCommandEntries * sizeof(CommandBufferEntry);
241 static const unsigned int kStartingOffset = 64;
242 static const unsigned int kAlignment = 4;
243 static const size_t kStartTransferBufferSize = 256;
244 static const size_t kMaxTransferBufferSize = 1024;
245 static const size_t kMinTransferBufferSize = 128;
247 TransferBufferExpandContractTest()
248 : transfer_buffer_id_(0) {
251 virtual void SetUp() OVERRIDE;
252 virtual void TearDown() OVERRIDE;
254 MockClientCommandBufferCanFail* command_buffer() const {
255 return command_buffer_.get();
258 scoped_ptr<MockClientCommandBufferCanFail> command_buffer_;
259 scoped_ptr<CommandBufferHelper> helper_;
260 scoped_ptr<TransferBuffer> transfer_buffer_;
261 int32 transfer_buffer_id_;
264 void TransferBufferExpandContractTest::SetUp() {
265 command_buffer_.reset(new StrictMock<MockClientCommandBufferCanFail>());
266 ASSERT_TRUE(command_buffer_->Initialize());
268 EXPECT_CALL(*command_buffer(),
269 CreateTransferBuffer(kCommandBufferSizeBytes, _))
272 &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
273 .RetiresOnSaturation();
275 helper_.reset(new CommandBufferHelper(command_buffer()));
276 ASSERT_TRUE(helper_->Initialize(kCommandBufferSizeBytes));
278 transfer_buffer_id_ = command_buffer()->GetNextFreeTransferBufferId();
280 EXPECT_CALL(*command_buffer(),
281 CreateTransferBuffer(kStartTransferBufferSize, _))
284 &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
285 .RetiresOnSaturation();
287 transfer_buffer_.reset(new TransferBuffer(helper_.get()));
288 ASSERT_TRUE(transfer_buffer_->Initialize(
289 kStartTransferBufferSize,
291 kMinTransferBufferSize,
292 kMaxTransferBufferSize,
297 void TransferBufferExpandContractTest::TearDown() {
298 if (transfer_buffer_->HaveBuffer()) {
299 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
301 .RetiresOnSaturation();
303 // For command buffer.
304 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
306 .RetiresOnSaturation();
307 transfer_buffer_.reset();
310 // GCC requires these declarations, but MSVC requires they not be present
312 const int32 TransferBufferExpandContractTest::kNumCommandEntries;
313 const int32 TransferBufferExpandContractTest::kCommandBufferSizeBytes;
314 const unsigned int TransferBufferExpandContractTest::kStartingOffset;
315 const unsigned int TransferBufferExpandContractTest::kAlignment;
316 const size_t TransferBufferExpandContractTest::kStartTransferBufferSize;
317 const size_t TransferBufferExpandContractTest::kMaxTransferBufferSize;
318 const size_t TransferBufferExpandContractTest::kMinTransferBufferSize;
321 TEST_F(TransferBufferExpandContractTest, Expand) {
322 // Check it starts at starting size.
324 kStartTransferBufferSize - kStartingOffset,
325 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
327 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
329 .RetiresOnSaturation();
330 EXPECT_CALL(*command_buffer(),
331 CreateTransferBuffer(kStartTransferBufferSize * 2, _))
334 &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
335 .RetiresOnSaturation();
337 // Try next power of 2.
338 const size_t kSize1 = 512 - kStartingOffset;
339 unsigned int size_allocated = 0;
340 void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated);
341 ASSERT_TRUE(ptr != NULL);
342 EXPECT_EQ(kSize1, size_allocated);
343 EXPECT_EQ(kSize1, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
344 transfer_buffer_->FreePendingToken(ptr, 1);
346 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
348 .RetiresOnSaturation();
349 EXPECT_CALL(*command_buffer(),
350 CreateTransferBuffer(kMaxTransferBufferSize, _))
353 &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
354 .RetiresOnSaturation();
356 // Try next power of 2.
357 const size_t kSize2 = 1024 - kStartingOffset;
358 ptr = transfer_buffer_->AllocUpTo(kSize2, &size_allocated);
359 ASSERT_TRUE(ptr != NULL);
360 EXPECT_EQ(kSize2, size_allocated);
361 EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
362 transfer_buffer_->FreePendingToken(ptr, 1);
364 // Try next one more. Should not go past max.
366 const size_t kSize3 = kSize2 + 1;
367 ptr = transfer_buffer_->AllocUpTo(kSize3, &size_allocated);
368 EXPECT_EQ(kSize2, size_allocated);
369 EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
370 transfer_buffer_->FreePendingToken(ptr, 1);
373 TEST_F(TransferBufferExpandContractTest, Contract) {
374 // Check it starts at starting size.
376 kStartTransferBufferSize - kStartingOffset,
377 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
380 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
382 .RetiresOnSaturation();
383 transfer_buffer_->Free();
385 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
387 // Try to allocate again, fail first request
388 EXPECT_CALL(*command_buffer(),
389 CreateTransferBuffer(kStartTransferBufferSize, _))
391 DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
392 .RetiresOnSaturation();
393 EXPECT_CALL(*command_buffer(),
394 CreateTransferBuffer(kMinTransferBufferSize, _))
397 &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
398 .RetiresOnSaturation();
400 const size_t kSize1 = 256 - kStartingOffset;
401 const size_t kSize2 = 128 - kStartingOffset;
402 unsigned int size_allocated = 0;
403 void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated);
404 ASSERT_TRUE(ptr != NULL);
405 EXPECT_EQ(kSize2, size_allocated);
406 EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
407 transfer_buffer_->FreePendingToken(ptr, 1);
410 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
412 .RetiresOnSaturation();
413 transfer_buffer_->Free();
415 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
417 // Try to allocate again,
418 EXPECT_CALL(*command_buffer(),
419 CreateTransferBuffer(kMinTransferBufferSize, _))
422 &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
423 .RetiresOnSaturation();
425 ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated);
426 ASSERT_TRUE(ptr != NULL);
427 EXPECT_EQ(kSize2, size_allocated);
428 EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
429 transfer_buffer_->FreePendingToken(ptr, 1);
432 TEST_F(TransferBufferExpandContractTest, OutOfMemory) {
434 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
436 .RetiresOnSaturation();
437 transfer_buffer_->Free();
439 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
441 // Try to allocate again, fail both requests.
442 EXPECT_CALL(*command_buffer(), CreateTransferBuffer(_, _))
444 DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
446 DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
448 DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
449 .RetiresOnSaturation();
451 const size_t kSize1 = 512 - kStartingOffset;
452 unsigned int size_allocated = 0;
453 void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated);
454 ASSERT_TRUE(ptr == NULL);
455 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
458 TEST_F(TransferBufferExpandContractTest, ReallocsToDefault) {
460 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
462 .RetiresOnSaturation();
463 transfer_buffer_->Free();
465 EXPECT_FALSE(transfer_buffer_->HaveBuffer());
467 // See that it gets reallocated.
468 EXPECT_CALL(*command_buffer(),
469 CreateTransferBuffer(kStartTransferBufferSize, _))
472 &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
473 .RetiresOnSaturation();
474 EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
475 EXPECT_TRUE(transfer_buffer_->HaveBuffer());
477 // Check it's the default size.
479 kStartTransferBufferSize - kStartingOffset,
480 transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());