1 /*
2 * Copyright 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18
19 #include <C2AllocatorIon.h>
20 #include <C2AllocatorGralloc.h>
21 #include <C2Buffer.h>
22 #include <C2BufferPriv.h>
23 #include <C2ParamDef.h>
24
25 #include <system/graphics.h>
26
27 namespace android {
28
29 class C2BufferUtilsTest : public ::testing::Test {
StaticSegmentTest()30 static void StaticSegmentTest() {
31 // constructor
32 static_assert(C2Segment(123u, 456u).offset == 123, "");
33 static_assert(C2Segment(123u, 456u).size == 456, "");
34
35 // empty
36 static_assert(!C2Segment(123u, 456u).isEmpty(), "");
37 static_assert(C2Segment(123u, 0u).isEmpty(), "");
38
39 // valid
40 static_assert(C2Segment(123u, 456u).isValid(), "");
41 static_assert(C2Segment(123u, ~123u).isValid(), "");
42 static_assert(!C2Segment(123u, 1 + ~123u).isValid(), "");
43
44 // bool()
45 static_assert(C2Segment(123u, 456u), "");
46 static_assert((bool)C2Segment(123u, ~123u), "");
47 static_assert(!bool(C2Segment(123u, 1 + ~123u)), "");
48 static_assert(!bool(C2Segment(123u, 0)), "");
49
50 // !
51 static_assert(!!C2Segment(123u, 456u), "");
52 static_assert(!!C2Segment(123u, ~123u), "");
53 static_assert(!C2Segment(123u, 1 + ~123u), "");
54 static_assert(!C2Segment(123u, 0), "");
55
56 // contains
57 static_assert(C2Segment(123u, ~123u).contains(C2Segment(123u, 0)), "");
58 static_assert(!C2Segment(123u, 1 + ~123u).contains(C2Segment(123u, 0)), "");
59 static_assert(C2Segment(123u, ~123u).contains(C2Segment(123u, ~123u)), "");
60 static_assert(!C2Segment(123u, ~123u).contains(C2Segment(123u, 1 + ~123u)), "");
61 static_assert(!C2Segment(123u, 1 + ~123u).contains(C2Segment(123u, 1 + ~123u)), "");
62 static_assert(!C2Segment(123u, ~123u).contains(C2Segment(122u, 2u)), "");
63 static_assert(C2Segment(123u, ~123u).contains(C2Segment(123u, 2u)), "");
64 static_assert(C2Segment(123u, 3u).contains(C2Segment(124u, 2u)), "");
65 static_assert(!C2Segment(123u, 3u).contains(C2Segment(125u, 2u)), "");
66
67 // ==
68 static_assert(C2Segment(123u, 456u) == C2Segment(123u, 456u), "");
69 static_assert(!(C2Segment(123u, 456u) == C2Segment(123u, 457u)), "");
70 static_assert(!(C2Segment(123u, 456u) == C2Segment(123u, 455u)), "");
71 static_assert(!(C2Segment(123u, 456u) == C2Segment(122u, 456u)), "");
72 static_assert(!(C2Segment(123u, 456u) == C2Segment(124u, 456u)), "");
73 static_assert(!(C2Segment(123u, 0u) == C2Segment(124u, 0u)), "");
74 static_assert(C2Segment(123u, 0u) == C2Segment(123u, 0u), "");
75 static_assert(C2Segment(123u, 1 + ~123u) == C2Segment(124u, 1 + ~124u), "");
76
77 // !=
78 static_assert(!(C2Segment(123u, 456u) != C2Segment(123u, 456u)), "");
79 static_assert(C2Segment(123u, 456u) != C2Segment(123u, 457u), "");
80 static_assert(C2Segment(123u, 456u) != C2Segment(123u, 455u), "");
81 static_assert(C2Segment(123u, 456u) != C2Segment(122u, 456u), "");
82 static_assert(C2Segment(123u, 456u) != C2Segment(124u, 456u), "");
83 static_assert(C2Segment(123u, 0u) != C2Segment(124u, 0u), "");
84 static_assert(!(C2Segment(123u, 0u) != C2Segment(123u, 0u)), "");
85 static_assert(!(C2Segment(123u, 1 + ~123u) != C2Segment(124u, 1 + ~124u)), "");
86
87 // <=
88 static_assert(C2Segment(123u, 456u) <= C2Segment(123u, 456u), "");
89 static_assert(C2Segment(123u, 456u) <= C2Segment(123u, 457u), "");
90 static_assert(C2Segment(123u, 456u) <= C2Segment(122u, 457u), "");
91 static_assert(!(C2Segment(123u, 457u) <= C2Segment(123u, 456u)), "");
92 static_assert(!(C2Segment(122u, 457u) <= C2Segment(123u, 456u)), "");
93 static_assert(!(C2Segment(123u, 457u) <= C2Segment(124u, 457u)), "");
94 static_assert(!(C2Segment(122u, 457u) <= C2Segment(123u, 457u)), "");
95 static_assert(!(C2Segment(122u, 0u) <= C2Segment(123u, 0u)), "");
96 static_assert(C2Segment(123u, 0u) <= C2Segment(122u, 1u), "");
97 static_assert(C2Segment(122u, 0u) <= C2Segment(122u, 1u), "");
98 static_assert(!(C2Segment(122u, ~122u) <= C2Segment(122u, 1 + ~122u)), "");
99 static_assert(!(C2Segment(122u, 1 + ~122u) <= C2Segment(122u, ~122u)), "");
100 static_assert(!(C2Segment(122u, 1 + ~122u) <= C2Segment(122u, 1 + ~122u)), "");
101
102 // <
103 static_assert(!(C2Segment(123u, 456u) < C2Segment(123u, 456u)), "");
104 static_assert(C2Segment(123u, 456u) < C2Segment(123u, 457u), "");
105 static_assert(C2Segment(123u, 456u) < C2Segment(122u, 457u), "");
106 static_assert(!(C2Segment(123u, 457u) < C2Segment(123u, 456u)), "");
107 static_assert(!(C2Segment(122u, 457u) < C2Segment(123u, 456u)), "");
108 static_assert(!(C2Segment(123u, 457u) < C2Segment(124u, 457u)), "");
109 static_assert(!(C2Segment(122u, 457u) < C2Segment(123u, 457u)), "");
110 static_assert(!(C2Segment(122u, 0u) < C2Segment(123u, 0u)), "");
111 static_assert(C2Segment(123u, 0u) < C2Segment(122u, 1u), "");
112 static_assert(C2Segment(122u, 0u) < C2Segment(122u, 1u), "");
113 static_assert(!(C2Segment(122u, ~122u) < C2Segment(122u, 1 + ~122u)), "");
114 static_assert(!(C2Segment(122u, 1 + ~122u) < C2Segment(122u, ~122u)), "");
115 static_assert(!(C2Segment(122u, 1 + ~122u) < C2Segment(122u, 1 + ~122u)), "");
116
117 // <=
118 static_assert(C2Segment(123u, 456u) >= C2Segment(123u, 456u), "");
119 static_assert(C2Segment(123u, 457u) >= C2Segment(123u, 456u), "");
120 static_assert(C2Segment(122u, 457u) >= C2Segment(123u, 456u), "");
121 static_assert(!(C2Segment(123u, 456u) >= C2Segment(123u, 457u)), "");
122 static_assert(!(C2Segment(123u, 456u) >= C2Segment(122u, 457u)), "");
123 static_assert(!(C2Segment(124u, 457u) >= C2Segment(123u, 457u)), "");
124 static_assert(!(C2Segment(123u, 457u) >= C2Segment(122u, 457u)), "");
125 static_assert(!(C2Segment(123u, 0u) >= C2Segment(122u, 0u)), "");
126 static_assert(C2Segment(122u, 1u) >= C2Segment(123u, 0u), "");
127 static_assert(C2Segment(122u, 1u) >= C2Segment(122u, 0u), "");
128 static_assert(!(C2Segment(122u, 1 + ~122u) >= C2Segment(122u, ~122u)), "");
129 static_assert(!(C2Segment(122u, ~122u) >= C2Segment(122u, 1 + ~122u)), "");
130 static_assert(!(C2Segment(122u, 1 + ~122u) >= C2Segment(122u, 1 + ~122u)), "");
131
132 // <
133 static_assert(!(C2Segment(123u, 456u) > C2Segment(123u, 456u)), "");
134 static_assert(C2Segment(123u, 457u) > C2Segment(123u, 456u), "");
135 static_assert(C2Segment(122u, 457u) > C2Segment(123u, 456u), "");
136 static_assert(!(C2Segment(123u, 456u) > C2Segment(123u, 457u)), "");
137 static_assert(!(C2Segment(123u, 456u) > C2Segment(122u, 457u)), "");
138 static_assert(!(C2Segment(124u, 457u) > C2Segment(123u, 457u)), "");
139 static_assert(!(C2Segment(123u, 457u) > C2Segment(122u, 457u)), "");
140 static_assert(!(C2Segment(123u, 0u) > C2Segment(122u, 0u)), "");
141 static_assert(C2Segment(122u, 1u) > C2Segment(123u, 0u), "");
142 static_assert(C2Segment(122u, 1u) > C2Segment(122u, 0u), "");
143 static_assert(!(C2Segment(122u, 1 + ~122u) > C2Segment(122u, ~122u)), "");
144 static_assert(!(C2Segment(122u, ~122u) > C2Segment(122u, 1 + ~122u)), "");
145 static_assert(!(C2Segment(122u, 1 + ~122u) > C2Segment(122u, 1 + ~122u)), "");
146
147 // end
148 static_assert(C2Segment(123u, 456u).end() == 579u, "");
149 static_assert(C2Segment(123u, 0u).end() == 123u, "");
150 static_assert(C2Segment(123u, ~123u).end() == 0xffffffffu, "");
151 static_assert(C2Segment(123u, 1 + ~123u).end() == 0u, "");
152
153 // intersect
154 static_assert(C2Segment(123u, 456u).intersect(C2Segment(123u, 456u)) == C2Segment(123u, 456u), "");
155 static_assert(C2Segment(123u, 456u).intersect(C2Segment(123u, 460u)) == C2Segment(123u, 456u), "");
156 static_assert(C2Segment(123u, 456u).intersect(C2Segment(124u, 460u)) == C2Segment(124u, 455u), "");
157 static_assert(C2Segment(123u, 456u).intersect(C2Segment(579u, 460u)) == C2Segment(579u, 0u), "");
158 static_assert(C2Segment(123u, 456u).intersect(C2Segment(589u, 460u)) == C2Segment(589u, ~9u /* -10 */), "");
159 static_assert(C2Segment(123u, 456u).intersect(C2Segment(123u, 455u)) == C2Segment(123u, 455u), "");
160 static_assert(C2Segment(123u, 456u).intersect(C2Segment(122u, 456u)) == C2Segment(123u, 455u), "");
161 static_assert(C2Segment(123u, 456u).intersect(C2Segment(0u, 123u)) == C2Segment(123u, 0u), "");
162 static_assert(C2Segment(123u, 456u).intersect(C2Segment(0u, 0u)) == C2Segment(123u, ~122u /* -123 */), "");
163
164 // normalize (change invalid segments to empty segments)
165 static_assert(C2Segment(123u, 456u).normalize() == C2Segment(123u, 456u), "");
166 static_assert(C2Segment(123u, ~123u).normalize() == C2Segment(123u, ~123u), "");
167 static_assert(C2Segment(123u, 1 + ~123u).normalize() == C2Segment(123u, 0u), "");
168
169 // note: normalize cannot be used to make this work
170 static_assert(C2Segment(123u, 456u).intersect(C2Segment(150u, ~150u)).normalize() == C2Segment(150u, 429u), "");
171 static_assert(C2Segment(123u, 456u).intersect(C2Segment(150u, 1 + ~150u)).normalize() != C2Segment(150u, 429u), "");
172 static_assert(C2Segment(123u, 456u).intersect(C2Segment(150u, 1 + ~150u)).normalize() == C2Segment(150u, 0u), "");
173
174 // saturate (change invalid segments to full segments up to max)
175 static_assert(C2Segment(123u, 456u).saturate() == C2Segment(123u, 456u), "");
176 static_assert(C2Segment(123u, ~123u).saturate() == C2Segment(123u, ~123u), "");
177 static_assert(C2Segment(123u, 1 + ~123u).saturate() == C2Segment(123u, ~123u), "");
178
179 // note: saturate can be used to make this work but only partially
180 static_assert(C2Segment(123u, 456u).intersect(C2Segment(150u, 1 + ~150u).saturate()).normalize() == C2Segment(150u, 429u), "");
181 static_assert(C2Segment(123u, 456u).intersect(C2Segment(0u, 100u).saturate()).normalize() == C2Segment(123u, 0u), "");
182 static_assert(C2Segment(123u, 456u).intersect(C2Segment(1000u, 100u).saturate()).normalize() != C2Segment(579u, 0u), "");
183 static_assert(C2Segment(123u, 456u).intersect(C2Segment(1000u, 100u).saturate()).normalize() == C2Segment(1000u, 0u), "");
184
185 }
186
StaticLinearRangeAndCapacityTest()187 static void StaticLinearRangeAndCapacityTest() {
188 class TestCapacity : public _C2LinearCapacityAspect {
189 using _C2LinearCapacityAspect::_C2LinearCapacityAspect;
190 friend class C2BufferUtilsTest;
191 };
192
193 class TestRange : public _C2LinearRangeAspect {
194 using _C2LinearRangeAspect::_C2LinearRangeAspect;
195 friend class C2BufferUtilsTest;
196 };
197
198 // _C2LinearCapacityAspect
199 static_assert(TestCapacity(0u).capacity() == 0u, "");
200 constexpr TestCapacity cap(123u);
201 static_assert(TestCapacity(&cap).capacity() == 123u, "");
202 static_assert(TestCapacity(nullptr).capacity() == 0u, "");
203
204 // _C2LinearCapacityRange
205 static_assert(TestRange(&cap).capacity() == 123u, "");
206 static_assert(TestRange(&cap).offset() == 0u, "");
207 static_assert(TestRange(&cap).size() == 123u, "");
208 static_assert(TestRange(&cap).endOffset() == 123u, "");
209
210 constexpr TestRange range(&cap, 50u, 100u);
211
212 static_assert(range.capacity() == 123u, "");
213 static_assert(range.offset() == 50u, "");
214 static_assert(range.size() == 73u, "");
215 static_assert(range.endOffset() == 123u, "");
216
217 static_assert(TestRange(&cap, 20u, 30u).capacity() == 123u, "");
218 static_assert(TestRange(&cap, 20u, 30u).offset() == 20u, "");
219 static_assert(TestRange(&cap, 20u, 30u).size() == 30u, "");
220 static_assert(TestRange(&cap, 20u, 30u).endOffset() == 50u, "");
221
222 static_assert(TestRange(&cap, 200u, 30u).capacity() == 123u, "");
223 static_assert(TestRange(&cap, 200u, 30u).offset() == 123u, "");
224 static_assert(TestRange(&cap, 200u, 30u).size() == 0u, "");
225 static_assert(TestRange(&cap, 200u, 30u).endOffset() == 123u, "");
226
227 }
228
229 };
230
231
232 class C2BufferTest : public ::testing::Test {
233 public:
C2BufferTest()234 C2BufferTest()
235 : mBlockPoolId(C2BlockPool::PLATFORM_START),
236 mLinearAllocator(std::make_shared<C2AllocatorIon>('i')),
237 mSize(0u),
238 mAddr(nullptr),
239 mGraphicAllocator(std::make_shared<C2AllocatorGralloc>('g')) {
240 }
241
242 ~C2BufferTest() = default;
243
allocateLinear(size_t capacity)244 void allocateLinear(size_t capacity) {
245 c2_status_t err = mLinearAllocator->newLinearAllocation(
246 capacity,
247 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
248 &mLinearAllocation);
249 if (err != C2_OK) {
250 mLinearAllocation.reset();
251 FAIL() << "C2Allocator::newLinearAllocation() failed: " << err;
252 }
253 }
254
mapLinear(size_t offset,size_t size,uint8_t ** addr)255 void mapLinear(size_t offset, size_t size, uint8_t **addr) {
256 ASSERT_TRUE(mLinearAllocation);
257 c2_status_t err = mLinearAllocation->map(
258 offset,
259 size,
260 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
261 // TODO: fence
262 nullptr,
263 &mAddr);
264 if (err != C2_OK) {
265 mAddr = nullptr;
266 FAIL() << "C2LinearAllocation::map() failed: " << err;
267 }
268 ASSERT_NE(nullptr, mAddr);
269 mSize = size;
270 *addr = (uint8_t *)mAddr;
271 }
272
unmapLinear()273 void unmapLinear() {
274 ASSERT_TRUE(mLinearAllocation);
275 ASSERT_NE(nullptr, mAddr);
276 ASSERT_NE(0u, mSize);
277
278 // TODO: fence
279 ASSERT_EQ(C2_OK, mLinearAllocation->unmap(mAddr, mSize, nullptr));
280 mSize = 0u;
281 mAddr = nullptr;
282 }
283
makeLinearBlockPool()284 std::shared_ptr<C2BlockPool> makeLinearBlockPool() {
285 return std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
286 }
287
allocateGraphic(uint32_t width,uint32_t height)288 void allocateGraphic(uint32_t width, uint32_t height) {
289 c2_status_t err = mGraphicAllocator->newGraphicAllocation(
290 width,
291 height,
292 HAL_PIXEL_FORMAT_YCBCR_420_888,
293 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
294 &mGraphicAllocation);
295 if (err != C2_OK) {
296 mGraphicAllocation.reset();
297 FAIL() << "C2Allocator::newGraphicAllocation() failed: " << err;
298 }
299 }
300
mapGraphic(C2Rect rect,C2PlanarLayout * layout,uint8_t ** addr)301 void mapGraphic(C2Rect rect, C2PlanarLayout *layout, uint8_t **addr) {
302 ASSERT_TRUE(mGraphicAllocation);
303 c2_status_t err = mGraphicAllocation->map(
304 rect,
305 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
306 // TODO: fence
307 nullptr,
308 layout,
309 addr);
310 if (err != C2_OK) {
311 addr[C2PlanarLayout::PLANE_Y] = nullptr;
312 addr[C2PlanarLayout::PLANE_U] = nullptr;
313 addr[C2PlanarLayout::PLANE_V] = nullptr;
314 FAIL() << "C2GraphicAllocation::map() failed: " << err;
315 }
316 mMappedRect = rect;
317 memcpy(mAddrGraphic, addr, sizeof(uint8_t*) * C2PlanarLayout::MAX_NUM_PLANES);
318 }
319
unmapGraphic()320 void unmapGraphic() {
321 ASSERT_TRUE(mGraphicAllocation);
322
323 // TODO: fence
324 ASSERT_EQ(C2_OK, mGraphicAllocation->unmap(mAddrGraphic, mMappedRect, nullptr));
325 }
326
makeGraphicBlockPool()327 std::shared_ptr<C2BlockPool> makeGraphicBlockPool() {
328 return std::make_shared<C2BasicGraphicBlockPool>(mGraphicAllocator);
329 }
330
331 private:
332 C2BlockPool::local_id_t mBlockPoolId;
333 std::shared_ptr<C2Allocator> mLinearAllocator;
334 std::shared_ptr<C2LinearAllocation> mLinearAllocation;
335 size_t mSize;
336 void *mAddr;
337 C2Rect mMappedRect;
338 uint8_t* mAddrGraphic[C2PlanarLayout::MAX_NUM_PLANES];
339
340 std::shared_ptr<C2Allocator> mGraphicAllocator;
341 std::shared_ptr<C2GraphicAllocation> mGraphicAllocation;
342 };
343
TEST_F(C2BufferTest,LinearAllocationTest)344 TEST_F(C2BufferTest, LinearAllocationTest) {
345 constexpr size_t kCapacity = 1024u * 1024u;
346
347 allocateLinear(kCapacity);
348
349 uint8_t *addr = nullptr;
350 mapLinear(0u, kCapacity, &addr);
351 ASSERT_NE(nullptr, addr);
352
353 for (size_t i = 0; i < kCapacity; ++i) {
354 addr[i] = i % 100u;
355 }
356
357 unmapLinear();
358 addr = nullptr;
359
360 mapLinear(kCapacity / 3, kCapacity / 3, &addr);
361 ASSERT_NE(nullptr, addr);
362 for (size_t i = 0; i < kCapacity / 3; ++i) {
363 ASSERT_EQ((i + kCapacity / 3) % 100, addr[i]) << " at i = " << i;
364 }
365 }
366
TEST_F(C2BufferTest,BlockPoolTest)367 TEST_F(C2BufferTest, BlockPoolTest) {
368 constexpr size_t kCapacity = 1024u * 1024u;
369
370 std::shared_ptr<C2BlockPool> blockPool(makeLinearBlockPool());
371
372 std::shared_ptr<C2LinearBlock> block;
373 ASSERT_EQ(C2_OK, blockPool->fetchLinearBlock(
374 kCapacity,
375 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
376 &block));
377 ASSERT_TRUE(block);
378
379 C2Acquirable<C2WriteView> writeViewHolder = block->map();
380 C2WriteView writeView = writeViewHolder.get();
381 ASSERT_EQ(C2_OK, writeView.error());
382 ASSERT_EQ(kCapacity, writeView.capacity());
383 ASSERT_EQ(0u, writeView.offset());
384 ASSERT_EQ(kCapacity, writeView.size());
385
386 uint8_t *data = writeView.data();
387 ASSERT_NE(nullptr, data);
388 for (size_t i = 0; i < writeView.size(); ++i) {
389 data[i] = i % 100u;
390 }
391
392 writeView.setOffset(kCapacity / 3);
393 data = writeView.data();
394 ASSERT_NE(nullptr, data);
395 for (size_t i = 0; i < writeView.size(); ++i) {
396 ASSERT_EQ((i + kCapacity / 3) % 100u, data[i]) << " at i = " << i
397 << "; data = " << static_cast<void *>(data);
398 }
399
400 C2Fence fence;
401 C2ConstLinearBlock constBlock = block->share(
402 kCapacity / 3, kCapacity / 3, fence);
403
404 C2Acquirable<C2ReadView> readViewHolder = constBlock.map();
405 C2ReadView readView = readViewHolder.get();
406 ASSERT_EQ(C2_OK, readView.error());
407 ASSERT_EQ(kCapacity / 3, readView.capacity());
408
409 // TODO: fence
410 const uint8_t *constData = readView.data();
411 ASSERT_NE(nullptr, constData);
412 for (size_t i = 0; i < readView.capacity(); ++i) {
413 ASSERT_EQ((i + kCapacity / 3) % 100u, constData[i]) << " at i = " << i
414 << "; data = " << static_cast<void *>(data)
415 << "; constData = " << static_cast<const void *>(constData);
416 }
417
418 readView = readView.subView(333u, 100u);
419 ASSERT_EQ(C2_OK, readView.error());
420 ASSERT_EQ(100u, readView.capacity());
421
422 constData = readView.data();
423 ASSERT_NE(nullptr, constData);
424 for (size_t i = 0; i < readView.capacity(); ++i) {
425 ASSERT_EQ((i + 333u + kCapacity / 3) % 100u, constData[i]) << " at i = " << i;
426 }
427 }
428
fillPlane(const C2Rect rect,const C2PlaneInfo info,uint8_t * addr,uint8_t value)429 void fillPlane(const C2Rect rect, const C2PlaneInfo info, uint8_t *addr, uint8_t value) {
430 for (uint32_t row = 0; row < rect.height / info.rowSampling; ++row) {
431 int32_t rowOffset = (row + rect.top / info.rowSampling) * info.rowInc;
432 for (uint32_t col = 0; col < rect.width / info.colSampling; ++col) {
433 int32_t colOffset = (col + rect.left / info.colSampling) * info.colInc;
434 addr[rowOffset + colOffset] = value;
435 }
436 }
437 }
438
verifyPlane(const C2Rect rect,const C2PlaneInfo info,const uint8_t * addr,uint8_t value)439 bool verifyPlane(const C2Rect rect, const C2PlaneInfo info, const uint8_t *addr, uint8_t value) {
440 for (uint32_t row = 0; row < rect.height / info.rowSampling; ++row) {
441 int32_t rowOffset = (row + rect.top / info.rowSampling) * info.rowInc;
442 for (uint32_t col = 0; col < rect.width / info.colSampling; ++col) {
443 int32_t colOffset = (col + rect.left / info.colSampling) * info.colInc;
444 if (addr[rowOffset + colOffset] != value) {
445 return false;
446 }
447 }
448 }
449 return true;
450 }
451
TEST_F(C2BufferTest,GraphicAllocationTest)452 TEST_F(C2BufferTest, GraphicAllocationTest) {
453 constexpr uint32_t kWidth = 320;
454 constexpr uint32_t kHeight = 240;
455
456 allocateGraphic(kWidth, kHeight);
457
458 uint8_t *addr[C2PlanarLayout::MAX_NUM_PLANES];
459 C2Rect rect(kWidth, kHeight);
460 C2PlanarLayout layout;
461 mapGraphic(rect, &layout, addr);
462 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_Y]);
463 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_U]);
464 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_V]);
465
466 uint8_t *y = addr[C2PlanarLayout::PLANE_Y];
467 C2PlaneInfo yInfo = layout.planes[C2PlanarLayout::PLANE_Y];
468 uint8_t *u = addr[C2PlanarLayout::PLANE_U];
469 C2PlaneInfo uInfo = layout.planes[C2PlanarLayout::PLANE_U];
470 uint8_t *v = addr[C2PlanarLayout::PLANE_V];
471 C2PlaneInfo vInfo = layout.planes[C2PlanarLayout::PLANE_V];
472
473 fillPlane(rect, yInfo, y, 0);
474 fillPlane(rect, uInfo, u, 0);
475 fillPlane(rect, vInfo, v, 0);
476 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), yInfo, y, 0x12);
477 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), uInfo, u, 0x34);
478 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), vInfo, v, 0x56);
479
480 unmapGraphic();
481
482 mapGraphic(rect, &layout, addr);
483 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_Y]);
484 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_U]);
485 ASSERT_NE(nullptr, addr[C2PlanarLayout::PLANE_V]);
486
487 y = addr[C2PlanarLayout::PLANE_Y];
488 yInfo = layout.planes[C2PlanarLayout::PLANE_Y];
489 u = addr[C2PlanarLayout::PLANE_U];
490 uInfo = layout.planes[C2PlanarLayout::PLANE_U];
491 v = addr[C2PlanarLayout::PLANE_V];
492 vInfo = layout.planes[C2PlanarLayout::PLANE_V];
493
494 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), yInfo, y, 0x12));
495 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), uInfo, u, 0x34));
496 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), vInfo, v, 0x56));
497 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, yInfo, y, 0));
498 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, uInfo, u, 0));
499 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, vInfo, v, 0));
500 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, yInfo, y, 0));
501 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, uInfo, u, 0));
502 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, vInfo, v, 0));
503 }
504
TEST_F(C2BufferTest,GraphicBlockPoolTest)505 TEST_F(C2BufferTest, GraphicBlockPoolTest) {
506 constexpr uint32_t kWidth = 320;
507 constexpr uint32_t kHeight = 240;
508
509 std::shared_ptr<C2BlockPool> blockPool(makeGraphicBlockPool());
510
511 std::shared_ptr<C2GraphicBlock> block;
512 ASSERT_EQ(C2_OK, blockPool->fetchGraphicBlock(
513 kWidth,
514 kHeight,
515 HAL_PIXEL_FORMAT_YCBCR_420_888,
516 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
517 &block));
518 ASSERT_TRUE(block);
519
520 C2Acquirable<C2GraphicView> graphicViewHolder = block->map();
521 C2GraphicView graphicView = graphicViewHolder.get();
522 ASSERT_EQ(C2_OK, graphicView.error());
523 ASSERT_EQ(kWidth, graphicView.width());
524 ASSERT_EQ(kHeight, graphicView.height());
525
526 uint8_t *const *data = graphicView.data();
527 C2PlanarLayout layout = graphicView.layout();
528 ASSERT_NE(nullptr, data);
529
530 uint8_t *y = data[C2PlanarLayout::PLANE_Y];
531 C2PlaneInfo yInfo = layout.planes[C2PlanarLayout::PLANE_Y];
532 uint8_t *u = data[C2PlanarLayout::PLANE_U];
533 C2PlaneInfo uInfo = layout.planes[C2PlanarLayout::PLANE_U];
534 uint8_t *v = data[C2PlanarLayout::PLANE_V];
535 C2PlaneInfo vInfo = layout.planes[C2PlanarLayout::PLANE_V];
536
537 fillPlane({ kWidth, kHeight }, yInfo, y, 0);
538 fillPlane({ kWidth, kHeight }, uInfo, u, 0);
539 fillPlane({ kWidth, kHeight }, vInfo, v, 0);
540 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), yInfo, y, 0x12);
541 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), uInfo, u, 0x34);
542 fillPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), vInfo, v, 0x56);
543
544 C2Fence fence;
545 C2ConstGraphicBlock constBlock = block->share(C2Rect(kWidth, kHeight), fence);
546 block.reset();
547
548 C2Acquirable<const C2GraphicView> constViewHolder = constBlock.map();
549 const C2GraphicView constGraphicView = constViewHolder.get();
550 ASSERT_EQ(C2_OK, constGraphicView.error());
551 ASSERT_EQ(kWidth, constGraphicView.width());
552 ASSERT_EQ(kHeight, constGraphicView.height());
553
554 const uint8_t *const *constData = constGraphicView.data();
555 layout = graphicView.layout();
556 ASSERT_NE(nullptr, constData);
557
558 const uint8_t *cy = constData[C2PlanarLayout::PLANE_Y];
559 yInfo = layout.planes[C2PlanarLayout::PLANE_Y];
560 const uint8_t *cu = constData[C2PlanarLayout::PLANE_U];
561 uInfo = layout.planes[C2PlanarLayout::PLANE_U];
562 const uint8_t *cv = constData[C2PlanarLayout::PLANE_V];
563 vInfo = layout.planes[C2PlanarLayout::PLANE_V];
564
565 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), yInfo, cy, 0x12));
566 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), uInfo, cu, 0x34));
567 ASSERT_TRUE(verifyPlane(C2Rect(kWidth / 2, kHeight / 2).at(kWidth / 4, kHeight / 4), vInfo, cv, 0x56));
568 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, yInfo, cy, 0));
569 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, uInfo, cu, 0));
570 ASSERT_TRUE(verifyPlane({ kWidth, kHeight / 4 }, vInfo, cv, 0));
571 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, yInfo, cy, 0));
572 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, uInfo, cu, 0));
573 ASSERT_TRUE(verifyPlane({ kWidth / 4, kHeight }, vInfo, cv, 0));
574 }
575
576 class BufferData : public C2BufferData {
577 public:
BufferData(const std::vector<C2ConstLinearBlock> & blocks)578 explicit BufferData(const std::vector<C2ConstLinearBlock> &blocks) : C2BufferData(blocks) {}
BufferData(const std::vector<C2ConstGraphicBlock> & blocks)579 explicit BufferData(const std::vector<C2ConstGraphicBlock> &blocks) : C2BufferData(blocks) {}
580 };
581
582 class Buffer : public C2Buffer {
583 public:
Buffer(const std::vector<C2ConstLinearBlock> & blocks)584 explicit Buffer(const std::vector<C2ConstLinearBlock> &blocks) : C2Buffer(blocks) {}
Buffer(const std::vector<C2ConstGraphicBlock> & blocks)585 explicit Buffer(const std::vector<C2ConstGraphicBlock> &blocks) : C2Buffer(blocks) {}
586 };
587
TEST_F(C2BufferTest,BufferDataTest)588 TEST_F(C2BufferTest, BufferDataTest) {
589 std::shared_ptr<C2BlockPool> linearBlockPool(makeLinearBlockPool());
590 std::shared_ptr<C2BlockPool> graphicBlockPool(makeGraphicBlockPool());
591
592 constexpr uint32_t kWidth1 = 320;
593 constexpr uint32_t kHeight1 = 240;
594 constexpr C2Rect kCrop1(kWidth1, kHeight1);
595 constexpr uint32_t kWidth2 = 176;
596 constexpr uint32_t kHeight2 = 144;
597 constexpr C2Rect kCrop2(kWidth2, kHeight2);
598 constexpr size_t kCapacity1 = 1024u;
599 constexpr size_t kCapacity2 = 2048u;
600
601 std::shared_ptr<C2LinearBlock> linearBlock1;
602 std::shared_ptr<C2LinearBlock> linearBlock2;
603 ASSERT_EQ(C2_OK, linearBlockPool->fetchLinearBlock(
604 kCapacity1,
605 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
606 &linearBlock1));
607 ASSERT_EQ(C2_OK, linearBlockPool->fetchLinearBlock(
608 kCapacity2,
609 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
610 &linearBlock2));
611 std::shared_ptr<C2GraphicBlock> graphicBlock1;
612 std::shared_ptr<C2GraphicBlock> graphicBlock2;
613 ASSERT_EQ(C2_OK, graphicBlockPool->fetchGraphicBlock(
614 kWidth1,
615 kHeight1,
616 HAL_PIXEL_FORMAT_YCBCR_420_888,
617 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
618 &graphicBlock1));
619 ASSERT_EQ(C2_OK, graphicBlockPool->fetchGraphicBlock(
620 kWidth2,
621 kHeight2,
622 HAL_PIXEL_FORMAT_YCBCR_420_888,
623 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
624 &graphicBlock2));
625
626 std::shared_ptr<C2BufferData> data(new BufferData({ linearBlock1->share(0, kCapacity1, C2Fence()) }));
627 EXPECT_EQ(C2BufferData::LINEAR, data->type());
628 ASSERT_EQ(1u, data->linearBlocks().size());
629 EXPECT_EQ(linearBlock1->handle(), data->linearBlocks().front().handle());
630 EXPECT_TRUE(data->graphicBlocks().empty());
631
632 data.reset(new BufferData({
633 linearBlock1->share(0, kCapacity1, C2Fence()),
634 linearBlock2->share(0, kCapacity2, C2Fence()),
635 }));
636 EXPECT_EQ(C2BufferData::LINEAR_CHUNKS, data->type());
637 ASSERT_EQ(2u, data->linearBlocks().size());
638 EXPECT_EQ(linearBlock1->handle(), data->linearBlocks().front().handle());
639 EXPECT_EQ(linearBlock2->handle(), data->linearBlocks().back().handle());
640 EXPECT_TRUE(data->graphicBlocks().empty());
641
642 data.reset(new BufferData({ graphicBlock1->share(kCrop1, C2Fence()) }));
643 EXPECT_EQ(C2BufferData::GRAPHIC, data->type());
644 ASSERT_EQ(1u, data->graphicBlocks().size());
645 EXPECT_EQ(graphicBlock1->handle(), data->graphicBlocks().front().handle());
646 EXPECT_TRUE(data->linearBlocks().empty());
647
648 data.reset(new BufferData({
649 graphicBlock1->share(kCrop1, C2Fence()),
650 graphicBlock2->share(kCrop2, C2Fence()),
651 }));
652 EXPECT_EQ(C2BufferData::GRAPHIC_CHUNKS, data->type());
653 ASSERT_EQ(2u, data->graphicBlocks().size());
654 EXPECT_EQ(graphicBlock1->handle(), data->graphicBlocks().front().handle());
655 EXPECT_EQ(graphicBlock2->handle(), data->graphicBlocks().back().handle());
656 EXPECT_TRUE(data->linearBlocks().empty());
657 }
658
DestroyCallback(const C2Buffer *,void * arg)659 void DestroyCallback(const C2Buffer * /* buf */, void *arg) {
660 std::function<void(void)> *cb = (std::function<void(void)> *)arg;
661 (*cb)();
662 }
663
664 enum : uint32_t {
665 kParamIndexNumber1,
666 kParamIndexNumber2,
667 };
668
669 typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexNumber1> C2Number1Info;
670 typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexNumber2> C2Number2Info;
671
TEST_F(C2BufferTest,BufferTest)672 TEST_F(C2BufferTest, BufferTest) {
673 std::shared_ptr<C2BlockPool> alloc(makeLinearBlockPool());
674 constexpr size_t kCapacity = 1024u;
675 std::shared_ptr<C2LinearBlock> block;
676
677 ASSERT_EQ(C2_OK, alloc->fetchLinearBlock(
678 kCapacity,
679 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
680 &block));
681
682 std::atomic_bool destroyed(false);
683 std::function<void(void)> arg = [&destroyed](){ destroyed = true; };
684
685 std::shared_ptr<C2Buffer> buffer(new Buffer( { block->share(0, kCapacity, C2Fence()) }));
686 ASSERT_EQ(C2_OK, buffer->registerOnDestroyNotify(&DestroyCallback, &arg));
687 EXPECT_FALSE(destroyed);
688 ASSERT_EQ(C2_DUPLICATE, buffer->registerOnDestroyNotify(&DestroyCallback, &arg));
689 buffer.reset();
690 EXPECT_TRUE(destroyed);
691
692 buffer.reset(new Buffer( { block->share(0, kCapacity, C2Fence()) }));
693 destroyed = false;
694 ASSERT_EQ(C2_OK, buffer->registerOnDestroyNotify(&DestroyCallback, &arg));
695 EXPECT_FALSE(destroyed);
696 ASSERT_EQ(C2_NOT_FOUND, buffer->unregisterOnDestroyNotify(&DestroyCallback, nullptr));
697 ASSERT_EQ(C2_OK, buffer->unregisterOnDestroyNotify(&DestroyCallback, &arg));
698 EXPECT_FALSE(destroyed);
699 ASSERT_EQ(C2_NOT_FOUND, buffer->unregisterOnDestroyNotify(&DestroyCallback, &arg));
700 buffer.reset();
701 EXPECT_FALSE(destroyed);
702
703 std::shared_ptr<C2Info> info1(new C2Number1Info(1));
704 std::shared_ptr<C2Info> info2(new C2Number2Info(2));
705 buffer.reset(new Buffer( { block->share(0, kCapacity, C2Fence()) }));
706 EXPECT_TRUE(buffer->info().empty());
707 EXPECT_FALSE(buffer->hasInfo(info1->type()));
708 EXPECT_FALSE(buffer->hasInfo(info2->type()));
709
710 ASSERT_EQ(C2_OK, buffer->setInfo(info1));
711 EXPECT_EQ(1u, buffer->info().size());
712 EXPECT_EQ(*info1, *buffer->info().front());
713 EXPECT_TRUE(buffer->hasInfo(info1->type()));
714 EXPECT_FALSE(buffer->hasInfo(info2->type()));
715
716 ASSERT_EQ(C2_OK, buffer->setInfo(info2));
717 EXPECT_EQ(2u, buffer->info().size());
718 EXPECT_TRUE(buffer->hasInfo(info1->type()));
719 EXPECT_TRUE(buffer->hasInfo(info2->type()));
720
721 std::shared_ptr<C2Info> removed = buffer->removeInfo(info1->type());
722 ASSERT_TRUE(removed);
723 EXPECT_EQ(*removed, *info1);
724 EXPECT_EQ(1u, buffer->info().size());
725 EXPECT_EQ(*info2, *buffer->info().front());
726 EXPECT_FALSE(buffer->hasInfo(info1->type()));
727 EXPECT_TRUE(buffer->hasInfo(info2->type()));
728
729 removed = buffer->removeInfo(info1->type());
730 ASSERT_FALSE(removed);
731 EXPECT_EQ(1u, buffer->info().size());
732 EXPECT_FALSE(buffer->hasInfo(info1->type()));
733 EXPECT_TRUE(buffer->hasInfo(info2->type()));
734
735 std::shared_ptr<C2Info> info3(new C2Number2Info(3));
736 ASSERT_EQ(C2_OK, buffer->setInfo(info3));
737 EXPECT_EQ(1u, buffer->info().size());
738 EXPECT_FALSE(buffer->hasInfo(info1->type()));
739 EXPECT_TRUE(buffer->hasInfo(info2->type()));
740
741 removed = buffer->removeInfo(info2->type());
742 ASSERT_TRUE(removed);
743 EXPECT_EQ(*info3, *removed);
744 EXPECT_TRUE(buffer->info().empty());
745 EXPECT_FALSE(buffer->hasInfo(info1->type()));
746 EXPECT_FALSE(buffer->hasInfo(info2->type()));
747 }
748
TEST_F(C2BufferTest,MultipleLinearMapTest)749 TEST_F(C2BufferTest, MultipleLinearMapTest) {
750 std::shared_ptr<C2BlockPool> pool(makeLinearBlockPool());
751 constexpr size_t kCapacity = 524288u;
752 for (int i = 0; i < 100; ++i) {
753 std::vector<C2WriteView> wViews;
754 std::vector<C2ReadView> rViews;
755 for (int j = 0; j < 16; ++j) {
756 std::shared_ptr<C2LinearBlock> block;
757 ASSERT_EQ(C2_OK, pool->fetchLinearBlock(
758 kCapacity,
759 { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
760 &block));
761 wViews.push_back(block->map().get());
762 C2ConstLinearBlock cBlock = block->share(0, kCapacity / 2, C2Fence());
763 rViews.push_back(cBlock.map().get());
764 }
765 }
766 }
767
768 } // namespace android
769