buffer_hub_queue-test.cpp revision 1db8a5d7e3b0565b976e77859e28d77f6a451a2b
1#include <base/logging.h> 2#include <private/dvr/buffer_hub_client.h> 3#include <private/dvr/buffer_hub_queue_client.h> 4 5#include <gtest/gtest.h> 6 7#include <vector> 8 9namespace android { 10namespace dvr { 11 12using pdx::LocalHandle; 13 14namespace { 15 16constexpr int kBufferWidth = 100; 17constexpr int kBufferHeight = 1; 18constexpr int kBufferFormat = HAL_PIXEL_FORMAT_BLOB; 19constexpr int kBufferUsage = GRALLOC_USAGE_SW_READ_RARELY; 20constexpr int kBufferSliceCount = 1; // number of slices in each buffer 21 22class BufferHubQueueTest : public ::testing::Test { 23 public: 24 template <typename Meta> 25 bool CreateQueues(int usage_set_mask = 0, int usage_clear_mask = 0, 26 int usage_deny_set_mask = 0, 27 int usage_deny_clear_mask = 0) { 28 producer_queue_ = 29 ProducerQueue::Create<Meta>(usage_set_mask, usage_clear_mask, 30 usage_deny_set_mask, usage_deny_clear_mask); 31 if (!producer_queue_) 32 return false; 33 34 consumer_queue_ = producer_queue_->CreateConsumerQueue(); 35 if (!consumer_queue_) 36 return false; 37 38 return true; 39 } 40 41 void AllocateBuffer() { 42 // Create producer buffer. 43 size_t slot; 44 int ret = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight, 45 kBufferFormat, kBufferUsage, 46 kBufferSliceCount, &slot); 47 ASSERT_EQ(ret, 0); 48 } 49 50 protected: 51 std::unique_ptr<ProducerQueue> producer_queue_; 52 std::unique_ptr<ConsumerQueue> consumer_queue_; 53}; 54 55TEST_F(BufferHubQueueTest, TestDequeue) { 56 const size_t nb_dequeue_times = 16; 57 58 ASSERT_TRUE(CreateQueues<size_t>()); 59 60 // Allocate only one buffer. 61 AllocateBuffer(); 62 63 // But dequeue multiple times. 64 for (size_t i = 0; i < nb_dequeue_times; i++) { 65 size_t slot; 66 LocalHandle fence; 67 auto p1 = producer_queue_->Dequeue(0, &slot, &fence); 68 ASSERT_NE(nullptr, p1); 69 size_t mi = i; 70 ASSERT_EQ(p1->Post(LocalHandle(), &mi, sizeof(mi)), 0); 71 size_t mo; 72 auto c1 = consumer_queue_->Dequeue(100, &slot, &mo, &fence); 73 ASSERT_NE(nullptr, c1); 74 ASSERT_EQ(mi, mo); 75 c1->Release(LocalHandle()); 76 } 77} 78 79TEST_F(BufferHubQueueTest, TestProducerConsumer) { 80 const size_t nb_buffer = 16; 81 size_t slot; 82 uint64_t seq; 83 84 ASSERT_TRUE(CreateQueues<uint64_t>()); 85 86 for (size_t i = 0; i < nb_buffer; i++) { 87 AllocateBuffer(); 88 89 // Producer queue has all the available buffers on initialize. 90 ASSERT_EQ(producer_queue_->count(), i + 1); 91 ASSERT_EQ(producer_queue_->capacity(), i + 1); 92 93 // Consumer queue has no avaiable buffer on initialize. 94 ASSERT_EQ(consumer_queue_->count(), 0U); 95 // Consumer queue does not import buffers until a dequeue is issued. 96 ASSERT_EQ(consumer_queue_->capacity(), i); 97 // Dequeue returns nullptr since no buffer is ready to consumer, but 98 // this implicitly triggers buffer import and bump up |capacity|. 99 LocalHandle fence; 100 auto consumer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence); 101 ASSERT_EQ(nullptr, consumer_null); 102 ASSERT_EQ(consumer_queue_->capacity(), i + 1); 103 } 104 105 for (size_t i = 0; i < nb_buffer; i++) { 106 LocalHandle fence; 107 // First time, there is no buffer available to dequeue. 108 auto buffer_null = consumer_queue_->Dequeue(0, &slot, &seq, &fence); 109 ASSERT_EQ(nullptr, buffer_null); 110 111 // Make sure Producer buffer is Post()'ed so that it's ready to Accquire 112 // in the consumer's Dequeue() function. 113 auto producer = producer_queue_->Dequeue(0, &slot, &fence); 114 ASSERT_NE(nullptr, producer); 115 116 uint64_t seq_in = static_cast<uint64_t>(i); 117 ASSERT_EQ(producer->Post({}, &seq_in, sizeof(seq_in)), 0); 118 119 // Second time, the just |Post()|'ed buffer should be dequeued. 120 uint64_t seq_out = 0; 121 auto consumer = consumer_queue_->Dequeue(0, &slot, &seq_out, &fence); 122 ASSERT_NE(nullptr, consumer); 123 ASSERT_EQ(seq_in, seq_out); 124 } 125} 126 127struct TestMetadata { 128 char a; 129 int32_t b; 130 int64_t c; 131}; 132 133TEST_F(BufferHubQueueTest, TestMetadata) { 134 ASSERT_TRUE(CreateQueues<TestMetadata>()); 135 AllocateBuffer(); 136 137 std::vector<TestMetadata> ms = { 138 {'0', 0, 0}, {'1', 10, 3333}, {'@', 123, 1000000000}}; 139 140 for (auto mi : ms) { 141 size_t slot; 142 LocalHandle fence; 143 auto p1 = producer_queue_->Dequeue(0, &slot, &fence); 144 ASSERT_NE(nullptr, p1); 145 ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0); 146 TestMetadata mo; 147 auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence); 148 ASSERT_EQ(mi.a, mo.a); 149 ASSERT_EQ(mi.b, mo.b); 150 ASSERT_EQ(mi.c, mo.c); 151 c1->Release(LocalHandle(-1)); 152 } 153} 154 155TEST_F(BufferHubQueueTest, TestMetadataMismatch) { 156 ASSERT_TRUE(CreateQueues<int64_t>()); 157 AllocateBuffer(); 158 159 int64_t mi = 3; 160 size_t slot; 161 LocalHandle fence; 162 auto p1 = producer_queue_->Dequeue(0, &slot, &fence); 163 ASSERT_NE(nullptr, p1); 164 ASSERT_EQ(p1->Post(LocalHandle(-1), &mi, sizeof(mi)), 0); 165 166 int32_t mo; 167 // Acquire a buffer with mismatched metadata is not OK. 168 auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence); 169 ASSERT_EQ(nullptr, c1); 170} 171 172TEST_F(BufferHubQueueTest, TestEnqueue) { 173 ASSERT_TRUE(CreateQueues<int64_t>()); 174 AllocateBuffer(); 175 176 size_t slot; 177 LocalHandle fence; 178 auto p1 = producer_queue_->Dequeue(0, &slot, &fence); 179 ASSERT_NE(nullptr, p1); 180 181 int64_t mo; 182 producer_queue_->Enqueue(p1, slot); 183 auto c1 = consumer_queue_->Dequeue(0, &slot, &mo, &fence); 184 ASSERT_EQ(nullptr, c1); 185} 186 187TEST_F(BufferHubQueueTest, TestAllocateBuffer) { 188 ASSERT_TRUE(CreateQueues<int64_t>()); 189 190 size_t s1; 191 AllocateBuffer(); 192 LocalHandle fence; 193 auto p1 = producer_queue_->Dequeue(0, &s1, &fence); 194 ASSERT_NE(nullptr, p1); 195 196 // producer queue is exhausted 197 size_t s2; 198 auto p2_null = producer_queue_->Dequeue(0, &s2, &fence); 199 ASSERT_EQ(nullptr, p2_null); 200 201 // dynamically add buffer. 202 AllocateBuffer(); 203 ASSERT_EQ(producer_queue_->count(), 1U); 204 ASSERT_EQ(producer_queue_->capacity(), 2U); 205 206 // now we can dequeue again 207 auto p2 = producer_queue_->Dequeue(0, &s2, &fence); 208 ASSERT_NE(nullptr, p2); 209 ASSERT_EQ(producer_queue_->count(), 0U); 210 // p1 and p2 should have different slot number 211 ASSERT_NE(s1, s2); 212 213 // Consumer queue does not import buffers until |Dequeue| or |ImportBuffers| 214 // are called. So far consumer_queue_ should be empty. 215 ASSERT_EQ(consumer_queue_->count(), 0U); 216 217 int64_t seq = 1; 218 ASSERT_EQ(p1->Post(LocalHandle(), seq), 0); 219 size_t cs1, cs2; 220 auto c1 = consumer_queue_->Dequeue(0, &cs1, &seq, &fence); 221 ASSERT_NE(nullptr, c1); 222 ASSERT_EQ(consumer_queue_->count(), 0U); 223 ASSERT_EQ(consumer_queue_->capacity(), 2U); 224 ASSERT_EQ(cs1, s1); 225 226 ASSERT_EQ(p2->Post(LocalHandle(), seq), 0); 227 auto c2 = consumer_queue_->Dequeue(0, &cs2, &seq, &fence); 228 ASSERT_NE(nullptr, c2); 229 ASSERT_EQ(cs2, s2); 230} 231 232TEST_F(BufferHubQueueTest, TestUsageSetMask) { 233 const int set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN; 234 ASSERT_TRUE(CreateQueues<int64_t>(set_mask, 0, 0, 0)); 235 236 // When allocation, leave out |set_mask| from usage bits on purpose. 237 size_t slot; 238 int ret = producer_queue_->AllocateBuffer( 239 kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage & ~set_mask, 240 kBufferSliceCount, &slot); 241 ASSERT_EQ(ret, 0); 242 243 LocalHandle fence; 244 auto p1 = producer_queue_->Dequeue(0, &slot, &fence); 245 ASSERT_EQ(p1->usage() & set_mask, set_mask); 246} 247 248TEST_F(BufferHubQueueTest, TestUsageClearMask) { 249 const int clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN; 250 ASSERT_TRUE(CreateQueues<int64_t>(0, clear_mask, 0, 0)); 251 252 // When allocation, add |clear_mask| into usage bits on purpose. 253 size_t slot; 254 int ret = producer_queue_->AllocateBuffer( 255 kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage | clear_mask, 256 kBufferSliceCount, &slot); 257 ASSERT_EQ(ret, 0); 258 259 LocalHandle fence; 260 auto p1 = producer_queue_->Dequeue(0, &slot, &fence); 261 ASSERT_EQ(p1->usage() & clear_mask, 0); 262} 263 264TEST_F(BufferHubQueueTest, TestUsageDenySetMask) { 265 const int deny_set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN; 266 ASSERT_TRUE(CreateQueues<int64_t>(0, 0, deny_set_mask, 0)); 267 268 // Now that |deny_set_mask| is illegal, allocation without those bits should 269 // be able to succeed. 270 size_t slot; 271 int ret = producer_queue_->AllocateBuffer( 272 kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage & ~deny_set_mask, 273 kBufferSliceCount, &slot); 274 ASSERT_EQ(ret, 0); 275 276 // While allocation with those bits should fail. 277 ret = producer_queue_->AllocateBuffer( 278 kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage | deny_set_mask, 279 kBufferSliceCount, &slot); 280 ASSERT_EQ(ret, -EINVAL); 281} 282 283TEST_F(BufferHubQueueTest, TestUsageDenyClearMask) { 284 const int deny_clear_mask = GRALLOC_USAGE_SW_WRITE_OFTEN; 285 ASSERT_TRUE(CreateQueues<int64_t>(0, 0, 0, deny_clear_mask)); 286 287 // Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are 288 // mandatory), allocation with those bits should be able to succeed. 289 size_t slot; 290 int ret = producer_queue_->AllocateBuffer( 291 kBufferWidth, kBufferHeight, kBufferFormat, 292 kBufferUsage | deny_clear_mask, kBufferSliceCount, &slot); 293 ASSERT_EQ(ret, 0); 294 295 // While allocation without those bits should fail. 296 ret = producer_queue_->AllocateBuffer( 297 kBufferWidth, kBufferHeight, kBufferFormat, 298 kBufferUsage & ~deny_clear_mask, kBufferSliceCount, &slot); 299 ASSERT_EQ(ret, -EINVAL); 300} 301 302} // namespace 303 304} // namespace dvr 305} // namespace android 306