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