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
27namespace android {
28
29class C2BufferUtilsTest : public ::testing::Test {
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
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
232class C2BufferTest : public ::testing::Test {
233public:
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
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
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
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
284    std::shared_ptr<C2BlockPool> makeLinearBlockPool() {
285        return std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
286    }
287
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
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
320    void unmapGraphic() {
321        ASSERT_TRUE(mGraphicAllocation);
322
323        // TODO: fence
324        ASSERT_EQ(C2_OK, mGraphicAllocation->unmap(mAddrGraphic, mMappedRect, nullptr));
325    }
326
327    std::shared_ptr<C2BlockPool> makeGraphicBlockPool() {
328        return std::make_shared<C2BasicGraphicBlockPool>(mGraphicAllocator);
329    }
330
331private:
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
344TEST_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
367TEST_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
429void 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
439bool 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
452TEST_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
505TEST_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
576class BufferData : public C2BufferData {
577public:
578    explicit BufferData(const std::vector<C2ConstLinearBlock> &blocks) : C2BufferData(blocks) {}
579    explicit BufferData(const std::vector<C2ConstGraphicBlock> &blocks) : C2BufferData(blocks) {}
580};
581
582class Buffer : public C2Buffer {
583public:
584    explicit Buffer(const std::vector<C2ConstLinearBlock> &blocks) : C2Buffer(blocks) {}
585    explicit Buffer(const std::vector<C2ConstGraphicBlock> &blocks) : C2Buffer(blocks) {}
586};
587
588TEST_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
659void DestroyCallback(const C2Buffer * /* buf */, void *arg) {
660    std::function<void(void)> *cb = (std::function<void(void)> *)arg;
661    (*cb)();
662}
663
664enum : uint32_t {
665    kParamIndexNumber1,
666    kParamIndexNumber2,
667};
668
669typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexNumber1> C2Number1Info;
670typedef C2GlobalParam<C2Info, C2Int32Value, kParamIndexNumber2> C2Number2Info;
671
672TEST_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
749TEST_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