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
, static_cast<unsigned int>(-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());