Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / client / transfer_buffer_unittest.cc
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.
4
5 // Tests for the Command Buffer Helper.
6
7 #include "gpu/command_buffer/client/transfer_buffer.h"
8
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"
15
16 using ::testing::_;
17 using ::testing::AtMost;
18 using ::testing::Invoke;
19 using ::testing::Return;
20 using ::testing::SetArgPointee;
21 using ::testing::StrictMock;
22
23 namespace gpu {
24
25
26 class TransferBufferTest : public testing::Test {
27  protected:
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;
34
35   TransferBufferTest()
36       : transfer_buffer_id_(0) {
37   }
38
39   virtual void SetUp() OVERRIDE;
40   virtual void TearDown() OVERRIDE;
41
42   virtual void Initialize(unsigned int size_to_flush) {
43     ASSERT_TRUE(transfer_buffer_->Initialize(
44         kTransferBufferSize,
45         kStartingOffset,
46         kTransferBufferSize,
47         kTransferBufferSize,
48         kAlignment,
49         size_to_flush));
50   }
51
52   MockClientCommandBufferMockFlush* command_buffer() const {
53     return command_buffer_.get();
54   }
55
56   scoped_ptr<MockClientCommandBufferMockFlush> command_buffer_;
57   scoped_ptr<CommandBufferHelper> helper_;
58   scoped_ptr<TransferBuffer> transfer_buffer_;
59   int32 transfer_buffer_id_;
60 };
61
62 void TransferBufferTest::SetUp() {
63   command_buffer_.reset(new StrictMock<MockClientCommandBufferMockFlush>());
64   ASSERT_TRUE(command_buffer_->Initialize());
65
66   helper_.reset(new CommandBufferHelper(command_buffer()));
67   ASSERT_TRUE(helper_->Initialize(kCommandBufferSizeBytes));
68
69   transfer_buffer_id_ = command_buffer()->GetNextFreeTransferBufferId();
70
71   transfer_buffer_.reset(new TransferBuffer(helper_.get()));
72 }
73
74 void TransferBufferTest::TearDown() {
75   if (transfer_buffer_->HaveBuffer()) {
76     EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
77         .Times(1)
78         .RetiresOnSaturation();
79   }
80   // For command buffer.
81   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
82       .Times(1)
83       .RetiresOnSaturation();
84   EXPECT_CALL(*command_buffer(), OnFlush()).Times(AtMost(1));
85   transfer_buffer_.reset();
86 }
87
88 // GCC requires these declarations, but MSVC requires they not be present
89 #ifndef _MSC_VER
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;
95 #endif
96
97 TEST_F(TransferBufferTest, Basic) {
98   Initialize(0);
99   EXPECT_TRUE(transfer_buffer_->HaveBuffer());
100   EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
101   EXPECT_EQ(
102       kTransferBufferSize - kStartingOffset,
103       transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
104 }
105
106 TEST_F(TransferBufferTest, Free) {
107   Initialize(0);
108   EXPECT_TRUE(transfer_buffer_->HaveBuffer());
109   EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
110
111   // Free buffer.
112   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
113       .Times(1)
114       .RetiresOnSaturation();
115   transfer_buffer_->Free();
116   // See it's freed.
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());
121
122   // Free buffer.
123   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
124       .Times(1)
125       .RetiresOnSaturation();
126   transfer_buffer_->Free();
127   // See it's freed.
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());
132
133   // Free buffer.
134   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
135       .Times(1)
136       .RetiresOnSaturation();
137   transfer_buffer_->Free();
138   // See it's freed.
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);
146
147   // Free buffer.
148   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
149       .Times(1)
150       .RetiresOnSaturation();
151   transfer_buffer_->Free();
152   // See it's freed.
153   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
154   // See that it gets reallocated.
155   transfer_buffer_->GetResultOffset();
156   EXPECT_TRUE(transfer_buffer_->HaveBuffer());
157
158   EXPECT_EQ(
159       kTransferBufferSize - kStartingOffset,
160       transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
161
162   // Test freeing twice.
163   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
164       .Times(1)
165       .RetiresOnSaturation();
166   transfer_buffer_->Free();
167   transfer_buffer_->Free();
168 }
169
170 TEST_F(TransferBufferTest, TooLargeAllocation) {
171   Initialize(0);
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);
182 }
183
184 TEST_F(TransferBufferTest, MemoryAlignmentAfterZeroAllocation) {
185   Initialize(32u);
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);
193 }
194
195 TEST_F(TransferBufferTest, Flush) {
196   Initialize(16u);
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);
202     if (i % 2) {
203       EXPECT_CALL(*command_buffer(), Flush(_))
204           .Times(1)
205           .RetiresOnSaturation();
206     }
207     transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
208   }
209   for (int i = 0; i < 8; ++i) {
210     void* ptr = transfer_buffer_->Alloc(8u);
211     ASSERT_TRUE(ptr != NULL);
212     if (i % 2) {
213       EXPECT_CALL(*command_buffer(), Flush(_))
214           .Times(1)
215           .RetiresOnSaturation();
216     }
217     transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
218   }
219 }
220
221 class MockClientCommandBufferCanFail : public MockClientCommandBufferMockFlush {
222  public:
223   MockClientCommandBufferCanFail() {
224   }
225   virtual ~MockClientCommandBufferCanFail() {
226   }
227
228   MOCK_METHOD2(CreateTransferBuffer,
229                scoped_refptr<Buffer>(size_t size, int32* id));
230
231   scoped_refptr<gpu::Buffer> RealCreateTransferBuffer(size_t size, int32* id) {
232     return MockCommandBufferBase::CreateTransferBuffer(size, id);
233   }
234 };
235
236 class TransferBufferExpandContractTest : public testing::Test {
237  protected:
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;
246
247   TransferBufferExpandContractTest()
248       : transfer_buffer_id_(0) {
249   }
250
251   virtual void SetUp() OVERRIDE;
252   virtual void TearDown() OVERRIDE;
253
254   MockClientCommandBufferCanFail* command_buffer() const {
255     return command_buffer_.get();
256   }
257
258   scoped_ptr<MockClientCommandBufferCanFail> command_buffer_;
259   scoped_ptr<CommandBufferHelper> helper_;
260   scoped_ptr<TransferBuffer> transfer_buffer_;
261   int32 transfer_buffer_id_;
262 };
263
264 void TransferBufferExpandContractTest::SetUp() {
265   command_buffer_.reset(new StrictMock<MockClientCommandBufferCanFail>());
266   ASSERT_TRUE(command_buffer_->Initialize());
267
268   EXPECT_CALL(*command_buffer(),
269               CreateTransferBuffer(kCommandBufferSizeBytes, _))
270       .WillOnce(Invoke(
271           command_buffer(),
272           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
273       .RetiresOnSaturation();
274
275   helper_.reset(new CommandBufferHelper(command_buffer()));
276   ASSERT_TRUE(helper_->Initialize(kCommandBufferSizeBytes));
277
278   transfer_buffer_id_ = command_buffer()->GetNextFreeTransferBufferId();
279
280   EXPECT_CALL(*command_buffer(),
281               CreateTransferBuffer(kStartTransferBufferSize, _))
282       .WillOnce(Invoke(
283           command_buffer(),
284           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
285       .RetiresOnSaturation();
286
287   transfer_buffer_.reset(new TransferBuffer(helper_.get()));
288   ASSERT_TRUE(transfer_buffer_->Initialize(
289       kStartTransferBufferSize,
290       kStartingOffset,
291       kMinTransferBufferSize,
292       kMaxTransferBufferSize,
293       kAlignment,
294       0));
295 }
296
297 void TransferBufferExpandContractTest::TearDown() {
298   if (transfer_buffer_->HaveBuffer()) {
299     EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
300         .Times(1)
301         .RetiresOnSaturation();
302   }
303   // For command buffer.
304   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
305       .Times(1)
306       .RetiresOnSaturation();
307   transfer_buffer_.reset();
308 }
309
310 // GCC requires these declarations, but MSVC requires they not be present
311 #ifndef _MSC_VER
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;
319 #endif
320
321 TEST_F(TransferBufferExpandContractTest, Expand) {
322   // Check it starts at starting size.
323   EXPECT_EQ(
324       kStartTransferBufferSize - kStartingOffset,
325       transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
326
327   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
328       .Times(1)
329       .RetiresOnSaturation();
330   EXPECT_CALL(*command_buffer(),
331               CreateTransferBuffer(kStartTransferBufferSize * 2, _))
332       .WillOnce(Invoke(
333           command_buffer(),
334           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
335       .RetiresOnSaturation();
336
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);
345
346   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
347       .Times(1)
348       .RetiresOnSaturation();
349   EXPECT_CALL(*command_buffer(),
350               CreateTransferBuffer(kMaxTransferBufferSize, _))
351       .WillOnce(Invoke(
352           command_buffer(),
353           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
354       .RetiresOnSaturation();
355
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);
363
364   // Try next one more. Should not go past max.
365   size_allocated = 0;
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);
371 }
372
373 TEST_F(TransferBufferExpandContractTest, Contract) {
374   // Check it starts at starting size.
375   EXPECT_EQ(
376       kStartTransferBufferSize - kStartingOffset,
377       transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
378
379   // Free buffer.
380   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
381       .Times(1)
382       .RetiresOnSaturation();
383   transfer_buffer_->Free();
384   // See it's freed.
385   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
386
387   // Try to allocate again, fail first request
388   EXPECT_CALL(*command_buffer(),
389               CreateTransferBuffer(kStartTransferBufferSize, _))
390       .WillOnce(
391            DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
392       .RetiresOnSaturation();
393   EXPECT_CALL(*command_buffer(),
394               CreateTransferBuffer(kMinTransferBufferSize, _))
395       .WillOnce(Invoke(
396           command_buffer(),
397           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
398       .RetiresOnSaturation();
399
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);
408
409   // Free buffer.
410   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
411       .Times(1)
412       .RetiresOnSaturation();
413   transfer_buffer_->Free();
414   // See it's freed.
415   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
416
417   // Try to allocate again,
418   EXPECT_CALL(*command_buffer(),
419               CreateTransferBuffer(kMinTransferBufferSize, _))
420       .WillOnce(Invoke(
421           command_buffer(),
422           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
423       .RetiresOnSaturation();
424
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);
430 }
431
432 TEST_F(TransferBufferExpandContractTest, OutOfMemory) {
433   // Free buffer.
434   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
435       .Times(1)
436       .RetiresOnSaturation();
437   transfer_buffer_->Free();
438   // See it's freed.
439   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
440
441   // Try to allocate again, fail both requests.
442   EXPECT_CALL(*command_buffer(), CreateTransferBuffer(_, _))
443       .WillOnce(
444            DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
445       .WillOnce(
446            DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
447       .WillOnce(
448            DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
449       .RetiresOnSaturation();
450
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());
456 }
457
458 TEST_F(TransferBufferExpandContractTest, ReallocsToDefault) {
459   // Free buffer.
460   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
461       .Times(1)
462       .RetiresOnSaturation();
463   transfer_buffer_->Free();
464   // See it's freed.
465   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
466
467   // See that it gets reallocated.
468   EXPECT_CALL(*command_buffer(),
469               CreateTransferBuffer(kStartTransferBufferSize, _))
470       .WillOnce(Invoke(
471           command_buffer(),
472           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
473       .RetiresOnSaturation();
474   EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
475   EXPECT_TRUE(transfer_buffer_->HaveBuffer());
476
477   // Check it's the default size.
478   EXPECT_EQ(
479       kStartTransferBufferSize - kStartingOffset,
480       transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
481 }
482
483 }  // namespace gpu
484
485