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, 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, 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);
    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 
    486