Home | History | Annotate | Download | only in client
      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, Flush) {
    185   Initialize(16u);
    186   unsigned int size_allocated = 0;
    187   for (int i = 0; i < 8; ++i) {
    188     void* ptr = transfer_buffer_->AllocUpTo(8u, &size_allocated);
    189     ASSERT_TRUE(ptr != NULL);
    190     EXPECT_EQ(8u, size_allocated);
    191     if (i % 2) {
    192       EXPECT_CALL(*command_buffer(), Flush(_))
    193           .Times(1)
    194           .RetiresOnSaturation();
    195     }
    196     transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
    197   }
    198   for (int i = 0; i < 8; ++i) {
    199     void* ptr = transfer_buffer_->Alloc(8u);
    200     ASSERT_TRUE(ptr != NULL);
    201     if (i % 2) {
    202       EXPECT_CALL(*command_buffer(), Flush(_))
    203           .Times(1)
    204           .RetiresOnSaturation();
    205     }
    206     transfer_buffer_->FreePendingToken(ptr, helper_->InsertToken());
    207   }
    208 }
    209 
    210 class MockClientCommandBufferCanFail : public MockClientCommandBufferMockFlush {
    211  public:
    212   MockClientCommandBufferCanFail() {
    213   }
    214   virtual ~MockClientCommandBufferCanFail() {
    215   }
    216 
    217   MOCK_METHOD2(CreateTransferBuffer, Buffer(size_t size, int32* id));
    218 
    219   Buffer RealCreateTransferBuffer(size_t size, int32* id) {
    220     return MockCommandBufferBase::CreateTransferBuffer(size, id);
    221   }
    222 };
    223 
    224 class TransferBufferExpandContractTest : public testing::Test {
    225  protected:
    226   static const int32 kNumCommandEntries = 400;
    227   static const int32 kCommandBufferSizeBytes =
    228       kNumCommandEntries * sizeof(CommandBufferEntry);
    229   static const unsigned int kStartingOffset = 64;
    230   static const unsigned int kAlignment = 4;
    231   static const size_t kStartTransferBufferSize = 256;
    232   static const size_t kMaxTransferBufferSize = 1024;
    233   static const size_t kMinTransferBufferSize = 128;
    234 
    235   TransferBufferExpandContractTest()
    236       : transfer_buffer_id_(0) {
    237   }
    238 
    239   virtual void SetUp() OVERRIDE;
    240   virtual void TearDown() OVERRIDE;
    241 
    242   MockClientCommandBufferCanFail* command_buffer() const {
    243     return command_buffer_.get();
    244   }
    245 
    246   scoped_ptr<MockClientCommandBufferCanFail> command_buffer_;
    247   scoped_ptr<CommandBufferHelper> helper_;
    248   scoped_ptr<TransferBuffer> transfer_buffer_;
    249   int32 transfer_buffer_id_;
    250 };
    251 
    252 void TransferBufferExpandContractTest::SetUp() {
    253   command_buffer_.reset(new StrictMock<MockClientCommandBufferCanFail>());
    254   ASSERT_TRUE(command_buffer_->Initialize());
    255 
    256   EXPECT_CALL(*command_buffer(),
    257               CreateTransferBuffer(kCommandBufferSizeBytes, _))
    258       .WillOnce(Invoke(
    259           command_buffer(),
    260           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
    261       .RetiresOnSaturation();
    262 
    263   helper_.reset(new CommandBufferHelper(command_buffer()));
    264   ASSERT_TRUE(helper_->Initialize(kCommandBufferSizeBytes));
    265 
    266   transfer_buffer_id_ = command_buffer()->GetNextFreeTransferBufferId();
    267 
    268   EXPECT_CALL(*command_buffer(),
    269               CreateTransferBuffer(kStartTransferBufferSize, _))
    270       .WillOnce(Invoke(
    271           command_buffer(),
    272           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
    273       .RetiresOnSaturation();
    274 
    275   transfer_buffer_.reset(new TransferBuffer(helper_.get()));
    276   ASSERT_TRUE(transfer_buffer_->Initialize(
    277       kStartTransferBufferSize,
    278       kStartingOffset,
    279       kMinTransferBufferSize,
    280       kMaxTransferBufferSize,
    281       kAlignment,
    282       0));
    283 }
    284 
    285 void TransferBufferExpandContractTest::TearDown() {
    286   if (transfer_buffer_->HaveBuffer()) {
    287     EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
    288         .Times(1)
    289         .RetiresOnSaturation();
    290   }
    291   // For command buffer.
    292   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
    293       .Times(1)
    294       .RetiresOnSaturation();
    295   transfer_buffer_.reset();
    296 }
    297 
    298 // GCC requires these declarations, but MSVC requires they not be present
    299 #ifndef _MSC_VER
    300 const int32 TransferBufferExpandContractTest::kNumCommandEntries;
    301 const int32 TransferBufferExpandContractTest::kCommandBufferSizeBytes;
    302 const unsigned int TransferBufferExpandContractTest::kStartingOffset;
    303 const unsigned int TransferBufferExpandContractTest::kAlignment;
    304 const size_t TransferBufferExpandContractTest::kStartTransferBufferSize;
    305 const size_t TransferBufferExpandContractTest::kMaxTransferBufferSize;
    306 const size_t TransferBufferExpandContractTest::kMinTransferBufferSize;
    307 #endif
    308 
    309 TEST_F(TransferBufferExpandContractTest, Expand) {
    310   // Check it starts at starting size.
    311   EXPECT_EQ(
    312       kStartTransferBufferSize - kStartingOffset,
    313       transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
    314 
    315   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
    316       .Times(1)
    317       .RetiresOnSaturation();
    318   EXPECT_CALL(*command_buffer(),
    319               CreateTransferBuffer(kStartTransferBufferSize * 2, _))
    320       .WillOnce(Invoke(
    321           command_buffer(),
    322           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
    323       .RetiresOnSaturation();
    324 
    325   // Try next power of 2.
    326   const size_t kSize1 = 512 - kStartingOffset;
    327   unsigned int size_allocated = 0;
    328   void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated);
    329   ASSERT_TRUE(ptr != NULL);
    330   EXPECT_EQ(kSize1, size_allocated);
    331   EXPECT_EQ(kSize1, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
    332   transfer_buffer_->FreePendingToken(ptr, 1);
    333 
    334   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
    335       .Times(1)
    336       .RetiresOnSaturation();
    337   EXPECT_CALL(*command_buffer(),
    338               CreateTransferBuffer(kMaxTransferBufferSize, _))
    339       .WillOnce(Invoke(
    340           command_buffer(),
    341           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
    342       .RetiresOnSaturation();
    343 
    344   // Try next power of 2.
    345   const size_t kSize2 = 1024 - kStartingOffset;
    346   ptr = transfer_buffer_->AllocUpTo(kSize2, &size_allocated);
    347   ASSERT_TRUE(ptr != NULL);
    348   EXPECT_EQ(kSize2, size_allocated);
    349   EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
    350   transfer_buffer_->FreePendingToken(ptr, 1);
    351 
    352   // Try next one more. Should not go past max.
    353   size_allocated = 0;
    354   const size_t kSize3 = kSize2 + 1;
    355   ptr = transfer_buffer_->AllocUpTo(kSize3, &size_allocated);
    356   EXPECT_EQ(kSize2, size_allocated);
    357   EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
    358   transfer_buffer_->FreePendingToken(ptr, 1);
    359 }
    360 
    361 TEST_F(TransferBufferExpandContractTest, Contract) {
    362   // Check it starts at starting size.
    363   EXPECT_EQ(
    364       kStartTransferBufferSize - kStartingOffset,
    365       transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
    366 
    367   // Free buffer.
    368   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
    369       .Times(1)
    370       .RetiresOnSaturation();
    371   transfer_buffer_->Free();
    372   // See it's freed.
    373   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
    374 
    375   // Try to allocate again, fail first request
    376   EXPECT_CALL(*command_buffer(),
    377               CreateTransferBuffer(kStartTransferBufferSize, _))
    378       .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
    379       .RetiresOnSaturation();
    380   EXPECT_CALL(*command_buffer(),
    381               CreateTransferBuffer(kMinTransferBufferSize, _))
    382       .WillOnce(Invoke(
    383           command_buffer(),
    384           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
    385       .RetiresOnSaturation();
    386 
    387   const size_t kSize1 = 256 - kStartingOffset;
    388   const size_t kSize2 = 128 - kStartingOffset;
    389   unsigned int size_allocated = 0;
    390   void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated);
    391   ASSERT_TRUE(ptr != NULL);
    392   EXPECT_EQ(kSize2, size_allocated);
    393   EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
    394   transfer_buffer_->FreePendingToken(ptr, 1);
    395 
    396   // Free buffer.
    397   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
    398       .Times(1)
    399       .RetiresOnSaturation();
    400   transfer_buffer_->Free();
    401   // See it's freed.
    402   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
    403 
    404   // Try to allocate again,
    405   EXPECT_CALL(*command_buffer(),
    406               CreateTransferBuffer(kMinTransferBufferSize, _))
    407       .WillOnce(Invoke(
    408           command_buffer(),
    409           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
    410       .RetiresOnSaturation();
    411 
    412   ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated);
    413   ASSERT_TRUE(ptr != NULL);
    414   EXPECT_EQ(kSize2, size_allocated);
    415   EXPECT_EQ(kSize2, transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
    416   transfer_buffer_->FreePendingToken(ptr, 1);
    417 }
    418 
    419 TEST_F(TransferBufferExpandContractTest, OutOfMemory) {
    420   // Free buffer.
    421   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
    422       .Times(1)
    423       .RetiresOnSaturation();
    424   transfer_buffer_->Free();
    425   // See it's freed.
    426   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
    427 
    428   // Try to allocate again, fail both requests.
    429   EXPECT_CALL(*command_buffer(), CreateTransferBuffer(_, _))
    430       .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
    431       .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
    432       .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
    433       .RetiresOnSaturation();
    434 
    435   const size_t kSize1 = 512 - kStartingOffset;
    436   unsigned int size_allocated = 0;
    437   void* ptr = transfer_buffer_->AllocUpTo(kSize1, &size_allocated);
    438   ASSERT_TRUE(ptr == NULL);
    439   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
    440 }
    441 
    442 TEST_F(TransferBufferExpandContractTest, ReallocsToDefault) {
    443   // Free buffer.
    444   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
    445       .Times(1)
    446       .RetiresOnSaturation();
    447   transfer_buffer_->Free();
    448   // See it's freed.
    449   EXPECT_FALSE(transfer_buffer_->HaveBuffer());
    450 
    451   // See that it gets reallocated.
    452   EXPECT_CALL(*command_buffer(),
    453               CreateTransferBuffer(kStartTransferBufferSize, _))
    454       .WillOnce(Invoke(
    455           command_buffer(),
    456           &MockClientCommandBufferCanFail::RealCreateTransferBuffer))
    457       .RetiresOnSaturation();
    458   EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId());
    459   EXPECT_TRUE(transfer_buffer_->HaveBuffer());
    460 
    461   // Check it's the default size.
    462   EXPECT_EQ(
    463       kStartTransferBufferSize - kStartingOffset,
    464       transfer_buffer_->GetCurrentMaxAllocationWithoutRealloc());
    465 }
    466 
    467 }  // namespace gpu
    468 
    469 
    470