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