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 void SetUp() override
;
40 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 EXPECT_CALL(*command_buffer(), Flush(_
)).Times(AtMost(1));
86 transfer_buffer_
.reset();
89 // GCC requires these declarations, but MSVC requires they not be present
91 const int32
TransferBufferTest::kNumCommandEntries
;
92 const int32
TransferBufferTest::kCommandBufferSizeBytes
;
93 const unsigned int TransferBufferTest::kStartingOffset
;
94 const unsigned int TransferBufferTest::kAlignment
;
95 const size_t TransferBufferTest::kTransferBufferSize
;
98 TEST_F(TransferBufferTest
, Basic
) {
100 EXPECT_TRUE(transfer_buffer_
->HaveBuffer());
101 EXPECT_EQ(transfer_buffer_id_
, transfer_buffer_
->GetShmId());
103 kTransferBufferSize
- kStartingOffset
,
104 transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
107 TEST_F(TransferBufferTest
, Free
) {
109 EXPECT_TRUE(transfer_buffer_
->HaveBuffer());
110 EXPECT_EQ(transfer_buffer_id_
, transfer_buffer_
->GetShmId());
113 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
115 .RetiresOnSaturation();
116 transfer_buffer_
->Free();
118 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
119 // See that it gets reallocated.
120 EXPECT_EQ(transfer_buffer_id_
, transfer_buffer_
->GetShmId());
121 EXPECT_TRUE(transfer_buffer_
->HaveBuffer());
124 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
126 .RetiresOnSaturation();
127 transfer_buffer_
->Free();
129 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
130 // See that it gets reallocated.
131 EXPECT_TRUE(transfer_buffer_
->GetResultBuffer() != NULL
);
132 EXPECT_TRUE(transfer_buffer_
->HaveBuffer());
135 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
137 .RetiresOnSaturation();
138 transfer_buffer_
->Free();
140 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
141 // See that it gets reallocated.
142 unsigned int size
= 0;
143 void* data
= transfer_buffer_
->AllocUpTo(1, &size
);
144 EXPECT_TRUE(data
!= NULL
);
145 EXPECT_TRUE(transfer_buffer_
->HaveBuffer());
146 transfer_buffer_
->FreePendingToken(data
, 1);
149 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
151 .RetiresOnSaturation();
152 transfer_buffer_
->Free();
154 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
155 // See that it gets reallocated.
156 transfer_buffer_
->GetResultOffset();
157 EXPECT_TRUE(transfer_buffer_
->HaveBuffer());
160 kTransferBufferSize
- kStartingOffset
,
161 transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
163 // Test freeing twice.
164 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
166 .RetiresOnSaturation();
167 transfer_buffer_
->Free();
168 transfer_buffer_
->Free();
171 TEST_F(TransferBufferTest
, TooLargeAllocation
) {
173 // Check that we can't allocate large than max size.
174 void* ptr
= transfer_buffer_
->Alloc(kTransferBufferSize
+ 1);
175 EXPECT_TRUE(ptr
== NULL
);
176 // Check we if we try to allocate larger than max we get max.
177 unsigned int size_allocated
= 0;
178 ptr
= transfer_buffer_
->AllocUpTo(
179 kTransferBufferSize
+ 1, &size_allocated
);
180 ASSERT_TRUE(ptr
!= NULL
);
181 EXPECT_EQ(kTransferBufferSize
- kStartingOffset
, size_allocated
);
182 transfer_buffer_
->FreePendingToken(ptr
, 1);
185 TEST_F(TransferBufferTest
, MemoryAlignmentAfterZeroAllocation
) {
187 void* ptr
= transfer_buffer_
->Alloc(0);
188 EXPECT_EQ((reinterpret_cast<uintptr_t>(ptr
) & (kAlignment
- 1)), 0u);
189 transfer_buffer_
->FreePendingToken(ptr
, static_cast<unsigned int>(-1));
190 // Check that the pointer is aligned on the following allocation.
191 ptr
= transfer_buffer_
->Alloc(4);
192 EXPECT_EQ((reinterpret_cast<uintptr_t>(ptr
) & (kAlignment
- 1)), 0u);
193 transfer_buffer_
->FreePendingToken(ptr
, 1);
196 TEST_F(TransferBufferTest
, Flush
) {
198 unsigned int size_allocated
= 0;
199 for (int i
= 0; i
< 8; ++i
) {
200 void* ptr
= transfer_buffer_
->AllocUpTo(8u, &size_allocated
);
201 ASSERT_TRUE(ptr
!= NULL
);
202 EXPECT_EQ(8u, size_allocated
);
204 EXPECT_CALL(*command_buffer(), Flush(_
))
206 .RetiresOnSaturation();
208 transfer_buffer_
->FreePendingToken(ptr
, helper_
->InsertToken());
210 for (int i
= 0; i
< 8; ++i
) {
211 void* ptr
= transfer_buffer_
->Alloc(8u);
212 ASSERT_TRUE(ptr
!= NULL
);
214 EXPECT_CALL(*command_buffer(), Flush(_
))
216 .RetiresOnSaturation();
218 transfer_buffer_
->FreePendingToken(ptr
, helper_
->InsertToken());
222 class MockClientCommandBufferCanFail
: public MockClientCommandBufferMockFlush
{
224 MockClientCommandBufferCanFail() {
226 virtual ~MockClientCommandBufferCanFail() {
229 MOCK_METHOD2(CreateTransferBuffer
,
230 scoped_refptr
<Buffer
>(size_t size
, int32
* id
));
232 scoped_refptr
<gpu::Buffer
> RealCreateTransferBuffer(size_t size
, int32
* id
) {
233 return MockCommandBufferBase::CreateTransferBuffer(size
, id
);
237 class TransferBufferExpandContractTest
: public testing::Test
{
239 static const int32 kNumCommandEntries
= 400;
240 static const int32 kCommandBufferSizeBytes
=
241 kNumCommandEntries
* sizeof(CommandBufferEntry
);
242 static const unsigned int kStartingOffset
= 64;
243 static const unsigned int kAlignment
= 4;
244 static const size_t kStartTransferBufferSize
= 256;
245 static const size_t kMaxTransferBufferSize
= 1024;
246 static const size_t kMinTransferBufferSize
= 128;
248 TransferBufferExpandContractTest()
249 : transfer_buffer_id_(0) {
252 void SetUp() override
;
253 void TearDown() override
;
255 MockClientCommandBufferCanFail
* command_buffer() const {
256 return command_buffer_
.get();
259 scoped_ptr
<MockClientCommandBufferCanFail
> command_buffer_
;
260 scoped_ptr
<CommandBufferHelper
> helper_
;
261 scoped_ptr
<TransferBuffer
> transfer_buffer_
;
262 int32 transfer_buffer_id_
;
265 void TransferBufferExpandContractTest::SetUp() {
266 command_buffer_
.reset(new StrictMock
<MockClientCommandBufferCanFail
>());
267 ASSERT_TRUE(command_buffer_
->Initialize());
269 EXPECT_CALL(*command_buffer(),
270 CreateTransferBuffer(kCommandBufferSizeBytes
, _
))
273 &MockClientCommandBufferCanFail::RealCreateTransferBuffer
))
274 .RetiresOnSaturation();
276 helper_
.reset(new CommandBufferHelper(command_buffer()));
277 ASSERT_TRUE(helper_
->Initialize(kCommandBufferSizeBytes
));
279 transfer_buffer_id_
= command_buffer()->GetNextFreeTransferBufferId();
281 EXPECT_CALL(*command_buffer(),
282 CreateTransferBuffer(kStartTransferBufferSize
, _
))
285 &MockClientCommandBufferCanFail::RealCreateTransferBuffer
))
286 .RetiresOnSaturation();
288 transfer_buffer_
.reset(new TransferBuffer(helper_
.get()));
289 ASSERT_TRUE(transfer_buffer_
->Initialize(
290 kStartTransferBufferSize
,
292 kMinTransferBufferSize
,
293 kMaxTransferBufferSize
,
298 void TransferBufferExpandContractTest::TearDown() {
299 if (transfer_buffer_
->HaveBuffer()) {
300 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
302 .RetiresOnSaturation();
304 // For command buffer.
305 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
307 .RetiresOnSaturation();
308 transfer_buffer_
.reset();
311 // GCC requires these declarations, but MSVC requires they not be present
313 const int32
TransferBufferExpandContractTest::kNumCommandEntries
;
314 const int32
TransferBufferExpandContractTest::kCommandBufferSizeBytes
;
315 const unsigned int TransferBufferExpandContractTest::kStartingOffset
;
316 const unsigned int TransferBufferExpandContractTest::kAlignment
;
317 const size_t TransferBufferExpandContractTest::kStartTransferBufferSize
;
318 const size_t TransferBufferExpandContractTest::kMaxTransferBufferSize
;
319 const size_t TransferBufferExpandContractTest::kMinTransferBufferSize
;
322 TEST_F(TransferBufferExpandContractTest
, Expand
) {
323 // Check it starts at starting size.
325 kStartTransferBufferSize
- kStartingOffset
,
326 transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
328 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
330 .RetiresOnSaturation();
331 EXPECT_CALL(*command_buffer(),
332 CreateTransferBuffer(kStartTransferBufferSize
* 2, _
))
335 &MockClientCommandBufferCanFail::RealCreateTransferBuffer
))
336 .RetiresOnSaturation();
338 // Try next power of 2.
339 const size_t kSize1
= 512 - kStartingOffset
;
340 unsigned int size_allocated
= 0;
341 void* ptr
= transfer_buffer_
->AllocUpTo(kSize1
, &size_allocated
);
342 ASSERT_TRUE(ptr
!= NULL
);
343 EXPECT_EQ(kSize1
, size_allocated
);
344 EXPECT_EQ(kSize1
, transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
345 transfer_buffer_
->FreePendingToken(ptr
, 1);
347 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
349 .RetiresOnSaturation();
350 EXPECT_CALL(*command_buffer(),
351 CreateTransferBuffer(kMaxTransferBufferSize
, _
))
354 &MockClientCommandBufferCanFail::RealCreateTransferBuffer
))
355 .RetiresOnSaturation();
357 // Try next power of 2.
358 const size_t kSize2
= 1024 - kStartingOffset
;
359 ptr
= transfer_buffer_
->AllocUpTo(kSize2
, &size_allocated
);
360 ASSERT_TRUE(ptr
!= NULL
);
361 EXPECT_EQ(kSize2
, size_allocated
);
362 EXPECT_EQ(kSize2
, transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
363 transfer_buffer_
->FreePendingToken(ptr
, 1);
365 // Try next one more. Should not go past max.
367 const size_t kSize3
= kSize2
+ 1;
368 ptr
= transfer_buffer_
->AllocUpTo(kSize3
, &size_allocated
);
369 EXPECT_EQ(kSize2
, size_allocated
);
370 EXPECT_EQ(kSize2
, transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
371 transfer_buffer_
->FreePendingToken(ptr
, 1);
374 TEST_F(TransferBufferExpandContractTest
, Contract
) {
375 // Check it starts at starting size.
377 kStartTransferBufferSize
- kStartingOffset
,
378 transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
381 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
383 .RetiresOnSaturation();
384 transfer_buffer_
->Free();
386 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
388 // Try to allocate again, fail first request
389 EXPECT_CALL(*command_buffer(),
390 CreateTransferBuffer(kStartTransferBufferSize
, _
))
392 DoAll(SetArgPointee
<1>(-1), Return(scoped_refptr
<gpu::Buffer
>())))
393 .RetiresOnSaturation();
394 EXPECT_CALL(*command_buffer(),
395 CreateTransferBuffer(kMinTransferBufferSize
, _
))
398 &MockClientCommandBufferCanFail::RealCreateTransferBuffer
))
399 .RetiresOnSaturation();
401 const size_t kSize1
= 256 - kStartingOffset
;
402 const size_t kSize2
= 128 - kStartingOffset
;
403 unsigned int size_allocated
= 0;
404 void* ptr
= transfer_buffer_
->AllocUpTo(kSize1
, &size_allocated
);
405 ASSERT_TRUE(ptr
!= NULL
);
406 EXPECT_EQ(kSize2
, size_allocated
);
407 EXPECT_EQ(kSize2
, transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
408 transfer_buffer_
->FreePendingToken(ptr
, 1);
411 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
413 .RetiresOnSaturation();
414 transfer_buffer_
->Free();
416 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
418 // Try to allocate again,
419 EXPECT_CALL(*command_buffer(),
420 CreateTransferBuffer(kMinTransferBufferSize
, _
))
423 &MockClientCommandBufferCanFail::RealCreateTransferBuffer
))
424 .RetiresOnSaturation();
426 ptr
= transfer_buffer_
->AllocUpTo(kSize1
, &size_allocated
);
427 ASSERT_TRUE(ptr
!= NULL
);
428 EXPECT_EQ(kSize2
, size_allocated
);
429 EXPECT_EQ(kSize2
, transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());
430 transfer_buffer_
->FreePendingToken(ptr
, 1);
433 TEST_F(TransferBufferExpandContractTest
, OutOfMemory
) {
435 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
437 .RetiresOnSaturation();
438 transfer_buffer_
->Free();
440 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
442 // Try to allocate again, fail both requests.
443 EXPECT_CALL(*command_buffer(), CreateTransferBuffer(_
, _
))
445 DoAll(SetArgPointee
<1>(-1), Return(scoped_refptr
<gpu::Buffer
>())))
447 DoAll(SetArgPointee
<1>(-1), Return(scoped_refptr
<gpu::Buffer
>())))
449 DoAll(SetArgPointee
<1>(-1), Return(scoped_refptr
<gpu::Buffer
>())))
450 .RetiresOnSaturation();
452 const size_t kSize1
= 512 - kStartingOffset
;
453 unsigned int size_allocated
= 0;
454 void* ptr
= transfer_buffer_
->AllocUpTo(kSize1
, &size_allocated
);
455 ASSERT_TRUE(ptr
== NULL
);
456 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
459 TEST_F(TransferBufferExpandContractTest
, ReallocsToDefault
) {
461 EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_
))
463 .RetiresOnSaturation();
464 transfer_buffer_
->Free();
466 EXPECT_FALSE(transfer_buffer_
->HaveBuffer());
468 // See that it gets reallocated.
469 EXPECT_CALL(*command_buffer(),
470 CreateTransferBuffer(kStartTransferBufferSize
, _
))
473 &MockClientCommandBufferCanFail::RealCreateTransferBuffer
))
474 .RetiresOnSaturation();
475 EXPECT_EQ(transfer_buffer_id_
, transfer_buffer_
->GetShmId());
476 EXPECT_TRUE(transfer_buffer_
->HaveBuffer());
478 // Check it's the default size.
480 kStartTransferBufferSize
- kStartingOffset
,
481 transfer_buffer_
->GetCurrentMaxAllocationWithoutRealloc());