1/*
2 * Copyright (C) 2016 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//#define LOG_NDEBUG 0
18#define LOG_TAG "C2AllocatorGralloc"
19#include <utils/Log.h>
20
21#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
22#include <android/hardware/graphics/mapper/2.0/IMapper.h>
23#include <cutils/native_handle.h>
24#include <hardware/gralloc.h>
25
26#include <C2AllocatorGralloc.h>
27#include <C2Buffer.h>
28#include <C2PlatformSupport.h>
29
30namespace android {
31
32namespace {
33    enum : uint64_t {
34        /**
35         * Usage mask that is passed through from gralloc to Codec 2.0 usage.
36         */
37        PASSTHROUGH_USAGE_MASK =
38            ~(GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_PROTECTED)
39    };
40
41    // verify that passthrough mask is within the platform mask
42    static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
43}
44
45C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
46    // gralloc does not support WRITE_PROTECTED
47    return C2MemoryUsage(
48            ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
49            ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
50            ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
51            (usage & PASSTHROUGH_USAGE_MASK));
52}
53
54uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
55    // gralloc does not support WRITE_PROTECTED
56    return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
57            ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
58            ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
59            (expected & PASSTHROUGH_USAGE_MASK));
60}
61
62using ::android::hardware::graphics::allocator::V2_0::IAllocator;
63using ::android::hardware::graphics::common::V1_0::BufferUsage;
64using ::android::hardware::graphics::common::V1_0::PixelFormat;
65using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
66using ::android::hardware::graphics::mapper::V2_0::Error;
67using ::android::hardware::graphics::mapper::V2_0::IMapper;
68using ::android::hardware::graphics::mapper::V2_0::YCbCrLayout;
69using ::android::hardware::hidl_handle;
70using ::android::hardware::hidl_vec;
71
72namespace {
73
74struct BufferDescriptorInfo {
75    IMapper::BufferDescriptorInfo mapperInfo;
76    uint32_t stride;
77};
78
79}
80
81/* ===================================== GRALLOC ALLOCATION ==================================== */
82static c2_status_t maperr2error(Error maperr) {
83    switch (maperr) {
84        case Error::NONE:           return C2_OK;
85        case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE;
86        case Error::BAD_BUFFER:     return C2_BAD_VALUE;
87        case Error::BAD_VALUE:      return C2_BAD_VALUE;
88        case Error::NO_RESOURCES:   return C2_NO_MEMORY;
89        case Error::UNSUPPORTED:    return C2_CANNOT_DO;
90    }
91    return C2_CORRUPTED;
92}
93
94static
95bool native_handle_is_invalid(const native_handle_t *const handle) {
96    // perform basic validation of a native handle
97    if (handle == nullptr) {
98        // null handle is considered valid
99        return false;
100    }
101    return ((size_t)handle->version != sizeof(native_handle_t) ||
102            handle->numFds < 0 ||
103            handle->numInts < 0 ||
104            // for sanity assume handles must occupy less memory than INT_MAX bytes
105            handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
106}
107
108class C2HandleGralloc : public C2Handle {
109private:
110    struct ExtraData {
111        uint32_t width;
112        uint32_t height;
113        uint32_t format;
114        uint32_t usage_lo;
115        uint32_t usage_hi;
116        uint32_t stride;
117        uint32_t igbp_id_lo;
118        uint32_t igbp_id_hi;
119        uint32_t igbp_slot;
120        uint32_t magic;
121    };
122
123    enum {
124        NUM_INTS = sizeof(ExtraData) / sizeof(int),
125    };
126    const static uint32_t MAGIC = '\xc2gr\x00';
127
128    static
129    const ExtraData* getExtraData(const C2Handle *const handle) {
130        if (handle == nullptr
131                || native_handle_is_invalid(handle)
132                || handle->numInts < NUM_INTS) {
133            return nullptr;
134        }
135        return reinterpret_cast<const ExtraData*>(
136                &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
137    }
138
139    static
140    ExtraData *getExtraData(C2Handle *const handle) {
141        return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle)));
142    }
143
144public:
145    void getIgbpData(uint64_t *igbp_id, uint32_t *igbp_slot) const {
146        const ExtraData *ed = getExtraData(this);
147        *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
148        *igbp_slot = ed->igbp_slot;
149    }
150
151    static bool isValid(const C2Handle *const o) {
152        if (o == nullptr) { // null handle is always valid
153            return true;
154        }
155        const ExtraData *xd = getExtraData(o);
156        // we cannot validate width/height/format/usage without accessing gralloc driver
157        return xd != nullptr && xd->magic == MAGIC;
158    }
159
160    static C2HandleGralloc* WrapNativeHandle(
161            const native_handle_t *const handle,
162            uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
163            uint32_t stride, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
164        //CHECK(handle != nullptr);
165        if (native_handle_is_invalid(handle) ||
166            handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
167            return nullptr;
168        }
169        ExtraData xd = {
170            width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
171            stride, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32), igbp_slot, MAGIC
172        };
173        native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
174        if (res != nullptr) {
175            memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
176            *getExtraData(res) = xd;
177        }
178        return reinterpret_cast<C2HandleGralloc *>(res);
179    }
180
181    static native_handle_t* UnwrapNativeHandle(
182            const C2Handle *const handle) {
183        const ExtraData *xd = getExtraData(handle);
184        if (xd == nullptr || xd->magic != MAGIC) {
185            return nullptr;
186        }
187        native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
188        if (res != nullptr) {
189            memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
190        }
191        return res;
192    }
193
194    static native_handle_t* UnwrapNativeHandle(
195            const C2Handle *const handle, uint64_t *igbp_id, uint32_t *igbp_slot) {
196        const ExtraData *xd = getExtraData(handle);
197        if (xd == nullptr || xd->magic != MAGIC) {
198            return nullptr;
199        }
200        *igbp_id = unsigned(xd->igbp_id_lo) | uint64_t(unsigned(xd->igbp_id_hi)) << 32;
201        *igbp_slot = xd->igbp_slot;
202        native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
203        if (res != nullptr) {
204            memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
205        }
206        return res;
207    }
208
209    static const C2HandleGralloc* Import(
210            const C2Handle *const handle,
211            uint32_t *width, uint32_t *height, uint32_t *format,
212            uint64_t *usage, uint32_t *stride,
213            uint64_t *igbp_id, uint32_t *igbp_slot) {
214        const ExtraData *xd = getExtraData(handle);
215        if (xd == nullptr) {
216            return nullptr;
217        }
218        *width = xd->width;
219        *height = xd->height;
220        *format = xd->format;
221        *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
222        *stride = xd->stride;
223        *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
224        *igbp_slot = xd->igbp_slot;
225        return reinterpret_cast<const C2HandleGralloc *>(handle);
226    }
227};
228
229native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
230    return C2HandleGralloc::UnwrapNativeHandle(handle);
231}
232
233native_handle_t *UnwrapNativeCodec2GrallocHandle(
234        const C2Handle *const handle, uint64_t *igbp_id, uint32_t *igbp_slot) {
235    return C2HandleGralloc::UnwrapNativeHandle(handle, igbp_id, igbp_slot);
236}
237
238C2Handle *WrapNativeCodec2GrallocHandle(
239        const native_handle_t *const handle,
240        uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride, uint64_t igbp_id, uint32_t igbp_slot) {
241    return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride, igbp_id, igbp_slot);
242}
243
244class C2AllocationGralloc : public C2GraphicAllocation {
245public:
246    virtual ~C2AllocationGralloc() override;
247
248    virtual c2_status_t map(
249            C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
250            C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
251    virtual c2_status_t unmap(
252            uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
253    virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
254    virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
255    virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
256
257    // internal methods
258    // |handle| will be moved.
259    C2AllocationGralloc(
260              const BufferDescriptorInfo &info,
261              const sp<IMapper> &mapper,
262              hidl_handle &hidlHandle,
263              const C2HandleGralloc *const handle,
264              C2Allocator::id_t allocatorId);
265    int dup() const;
266    c2_status_t status() const;
267
268private:
269    const BufferDescriptorInfo mInfo;
270    const sp<IMapper> mMapper;
271    const hidl_handle mHidlHandle;
272    const C2HandleGralloc *mHandle;
273    buffer_handle_t mBuffer;
274    const C2HandleGralloc *mLockedHandle;
275    bool mLocked;
276    C2Allocator::id_t mAllocatorId;
277};
278
279C2AllocationGralloc::C2AllocationGralloc(
280          const BufferDescriptorInfo &info,
281          const sp<IMapper> &mapper,
282          hidl_handle &hidlHandle,
283          const C2HandleGralloc *const handle,
284          C2Allocator::id_t allocatorId)
285    : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
286      mInfo(info),
287      mMapper(mapper),
288      mHidlHandle(std::move(hidlHandle)),
289      mHandle(handle),
290      mBuffer(nullptr),
291      mLockedHandle(nullptr),
292      mLocked(false),
293      mAllocatorId(allocatorId) {
294}
295
296C2AllocationGralloc::~C2AllocationGralloc() {
297    if (!mBuffer) {
298        return;
299    }
300    if (mLocked) {
301        // implementation ignores addresss and rect
302        uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
303        unmap(addr, C2Rect(), nullptr);
304    }
305    mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
306    native_handle_delete(const_cast<native_handle_t*>(
307            reinterpret_cast<const native_handle_t*>(mHandle)));
308}
309
310c2_status_t C2AllocationGralloc::map(
311        C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
312        C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
313    uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
314    ALOGV("mapping buffer with usage %#llx => %#llx",
315          (long long)usage.expected, (long long)grallocUsage);
316
317    // TODO
318    (void) fence;
319
320    if (mBuffer && mLocked) {
321        ALOGD("already mapped");
322        return C2_DUPLICATE;
323    }
324    if (!layout || !addr) {
325        ALOGD("wrong param");
326        return C2_BAD_VALUE;
327    }
328
329    c2_status_t err = C2_OK;
330    if (!mBuffer) {
331        mMapper->importBuffer(
332                mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
333                    err = maperr2error(maperr);
334                    if (err == C2_OK) {
335                        mBuffer = static_cast<buffer_handle_t>(buffer);
336                    }
337                });
338        if (err != C2_OK) {
339            ALOGD("importBuffer failed: %d", err);
340            return err;
341        }
342        if (mBuffer == nullptr) {
343            ALOGD("importBuffer returned null buffer");
344            return C2_CORRUPTED;
345        }
346        uint64_t igbp_id = 0;
347        uint32_t igbp_slot = 0;
348        if (mHandle) {
349            mHandle->getIgbpData(&igbp_id, &igbp_slot);
350        }
351        mLockedHandle = C2HandleGralloc::WrapNativeHandle(
352                mBuffer, mInfo.mapperInfo.width, mInfo.mapperInfo.height,
353                (uint32_t)mInfo.mapperInfo.format, mInfo.mapperInfo.usage, mInfo.stride, igbp_id, igbp_slot);
354    }
355
356    switch (mInfo.mapperInfo.format) {
357        case PixelFormat::YCBCR_420_888:
358        case PixelFormat::YV12: {
359            YCbCrLayout ycbcrLayout;
360            mMapper->lockYCbCr(
361                    const_cast<native_handle_t *>(mBuffer), grallocUsage,
362                    { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
363                    // TODO: fence
364                    hidl_handle(),
365                    [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
366                        err = maperr2error(maperr);
367                        if (err == C2_OK) {
368                            ycbcrLayout = mapLayout;
369                        }
370                    });
371            if (err != C2_OK) {
372                ALOGD("lockYCbCr failed: %d", err);
373                return err;
374            }
375            addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
376            addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
377            addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
378            layout->type = C2PlanarLayout::TYPE_YUV;
379            layout->numPlanes = 3;
380            layout->rootPlanes = 3;
381            layout->planes[C2PlanarLayout::PLANE_Y] = {
382                C2PlaneInfo::CHANNEL_Y,         // channel
383                1,                              // colInc
384                (int32_t)ycbcrLayout.yStride,   // rowInc
385                1,                              // mColSampling
386                1,                              // mRowSampling
387                8,                              // allocatedDepth
388                8,                              // bitDepth
389                0,                              // rightShift
390                C2PlaneInfo::NATIVE,            // endianness
391                C2PlanarLayout::PLANE_Y,        // rootIx
392                0,                              // offset
393            };
394            layout->planes[C2PlanarLayout::PLANE_U] = {
395                C2PlaneInfo::CHANNEL_CB,          // channel
396                (int32_t)ycbcrLayout.chromaStep,  // colInc
397                (int32_t)ycbcrLayout.cStride,     // rowInc
398                2,                                // mColSampling
399                2,                                // mRowSampling
400                8,                                // allocatedDepth
401                8,                                // bitDepth
402                0,                                // rightShift
403                C2PlaneInfo::NATIVE,              // endianness
404                C2PlanarLayout::PLANE_U,          // rootIx
405                0,                                // offset
406            };
407            layout->planes[C2PlanarLayout::PLANE_V] = {
408                C2PlaneInfo::CHANNEL_CR,          // channel
409                (int32_t)ycbcrLayout.chromaStep,  // colInc
410                (int32_t)ycbcrLayout.cStride,     // rowInc
411                2,                                // mColSampling
412                2,                                // mRowSampling
413                8,                                // allocatedDepth
414                8,                                // bitDepth
415                0,                                // rightShift
416                C2PlaneInfo::NATIVE,              // endianness
417                C2PlanarLayout::PLANE_V,          // rootIx
418                0,                                // offset
419            };
420            // handle interleaved formats
421            intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
422            if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
423                layout->rootPlanes = 2;
424                layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
425                layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
426            } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
427                layout->rootPlanes = 2;
428                layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
429                layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
430            }
431            break;
432        }
433
434        case PixelFormat::RGBA_8888:
435            // TODO: alpha channel
436            // fall-through
437        case PixelFormat::RGBX_8888: {
438            void *pointer = nullptr;
439            mMapper->lock(
440                    const_cast<native_handle_t *>(mBuffer),
441                    grallocUsage,
442                    { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
443                    // TODO: fence
444                    hidl_handle(),
445                    [&err, &pointer](const auto &maperr, const auto &mapPointer) {
446                        err = maperr2error(maperr);
447                        if (err == C2_OK) {
448                            pointer = mapPointer;
449                        }
450                    });
451            if (err != C2_OK) {
452                ALOGD("lock failed: %d", err);
453                return err;
454            }
455            addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
456            addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
457            addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
458            layout->type = C2PlanarLayout::TYPE_RGB;
459            layout->numPlanes = 3;
460            layout->rootPlanes = 1;
461            layout->planes[C2PlanarLayout::PLANE_R] = {
462                C2PlaneInfo::CHANNEL_R,         // channel
463                4,                              // colInc
464                4 * (int32_t)mInfo.stride,      // rowInc
465                1,                              // mColSampling
466                1,                              // mRowSampling
467                8,                              // allocatedDepth
468                8,                              // bitDepth
469                0,                              // rightShift
470                C2PlaneInfo::NATIVE,            // endianness
471                C2PlanarLayout::PLANE_R,        // rootIx
472                0,                              // offset
473            };
474            layout->planes[C2PlanarLayout::PLANE_G] = {
475                C2PlaneInfo::CHANNEL_G,         // channel
476                4,                              // colInc
477                4 * (int32_t)mInfo.stride,      // rowInc
478                1,                              // mColSampling
479                1,                              // mRowSampling
480                8,                              // allocatedDepth
481                8,                              // bitDepth
482                0,                              // rightShift
483                C2PlaneInfo::NATIVE,            // endianness
484                C2PlanarLayout::PLANE_R,        // rootIx
485                1,                              // offset
486            };
487            layout->planes[C2PlanarLayout::PLANE_B] = {
488                C2PlaneInfo::CHANNEL_B,         // channel
489                4,                              // colInc
490                4 * (int32_t)mInfo.stride,      // rowInc
491                1,                              // mColSampling
492                1,                              // mRowSampling
493                8,                              // allocatedDepth
494                8,                              // bitDepth
495                0,                              // rightShift
496                C2PlaneInfo::NATIVE,            // endianness
497                C2PlanarLayout::PLANE_R,        // rootIx
498                2,                              // offset
499            };
500            break;
501        }
502        default: {
503            ALOGD("unsupported pixel format: %d", mInfo.mapperInfo.format);
504            return C2_OMITTED;
505        }
506    }
507    mLocked = true;
508
509    return C2_OK;
510}
511
512c2_status_t C2AllocationGralloc::unmap(
513        uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
514    // TODO: check addr and size, use fence
515    (void)addr;
516    (void)rect;
517    c2_status_t err = C2_OK;
518    mMapper->unlock(
519            const_cast<native_handle_t *>(mBuffer),
520            [&err, &fence](const auto &maperr, const auto &releaseFence) {
521                // TODO
522                (void) fence;
523                (void) releaseFence;
524                err = maperr2error(maperr);
525                if (err == C2_OK) {
526                    // TODO: fence
527                }
528            });
529    if (err == C2_OK) {
530        mLocked = false;
531    }
532    return err;
533}
534
535bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
536    return other && other->handle() == handle();
537}
538
539/* ===================================== GRALLOC ALLOCATOR ==================================== */
540class C2AllocatorGralloc::Impl {
541public:
542    Impl(id_t id, bool bufferQueue);
543
544    id_t getId() const {
545        return mTraits->id;
546    }
547
548    C2String getName() const {
549        return mTraits->name;
550    }
551
552    std::shared_ptr<const C2Allocator::Traits> getTraits() const {
553        return mTraits;
554    }
555
556    c2_status_t newGraphicAllocation(
557            uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
558            std::shared_ptr<C2GraphicAllocation> *allocation);
559
560    c2_status_t priorGraphicAllocation(
561            const C2Handle *handle,
562            std::shared_ptr<C2GraphicAllocation> *allocation);
563
564    c2_status_t status() const { return mInit; }
565
566private:
567    std::shared_ptr<C2Allocator::Traits> mTraits;
568    c2_status_t mInit;
569    sp<IAllocator> mAllocator;
570    sp<IMapper> mMapper;
571    const bool mBufferQueue;
572};
573
574void _UnwrapNativeCodec2GrallocMetadata(
575        const C2Handle *const handle,
576        uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
577        uint64_t *igbp_id, uint32_t *igbp_slot) {
578    (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride, igbp_id, igbp_slot);
579}
580
581C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
582    : mInit(C2_OK), mBufferQueue(bufferQueue) {
583    // TODO: get this from allocator
584    C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
585    Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
586    mTraits = std::make_shared<C2Allocator::Traits>(traits);
587
588    // gralloc allocator is a singleton, so all objects share a global service
589    mAllocator = IAllocator::getService();
590    mMapper = IMapper::getService();
591    if (mAllocator == nullptr || mMapper == nullptr) {
592        mInit = C2_CORRUPTED;
593    }
594}
595
596c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
597        uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
598        std::shared_ptr<C2GraphicAllocation> *allocation) {
599    uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
600    ALOGV("allocating buffer with usage %#llx => %#llx",
601          (long long)usage.expected, (long long)grallocUsage);
602
603    BufferDescriptorInfo info = {
604        {
605            width,
606            height,
607            1u,  // layerCount
608            (PixelFormat)format,
609            grallocUsage,
610        },
611        0u,  // stride placeholder
612    };
613    c2_status_t err = C2_OK;
614    BufferDescriptor desc;
615    mMapper->createDescriptor(
616            info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
617                err = maperr2error(maperr);
618                if (err == C2_OK) {
619                    desc = descriptor;
620                }
621            });
622    if (err != C2_OK) {
623        return err;
624    }
625
626    // IAllocator shares IMapper error codes.
627    hidl_handle buffer;
628    mAllocator->allocate(
629            desc,
630            1u,
631            [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
632                err = maperr2error(maperr);
633                if (err != C2_OK) {
634                    return;
635                }
636                if (buffers.size() != 1u) {
637                    err = C2_CORRUPTED;
638                    return;
639                }
640                info.stride = stride;
641                buffer = std::move(buffers[0]);
642            });
643    if (err != C2_OK) {
644        return err;
645    }
646
647
648    allocation->reset(new C2AllocationGralloc(
649            info, mMapper, buffer,
650            C2HandleGralloc::WrapNativeHandle(
651                    buffer.getNativeHandle(),
652                    info.mapperInfo.width, info.mapperInfo.height,
653                    (uint32_t)info.mapperInfo.format, info.mapperInfo.usage, info.stride,
654                    0, mBufferQueue ? ~0 : 0),
655            mTraits->id));
656    return C2_OK;
657}
658
659c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
660        const C2Handle *handle,
661        std::shared_ptr<C2GraphicAllocation> *allocation) {
662    BufferDescriptorInfo info;
663    info.mapperInfo.layerCount = 1u;
664    uint64_t igbp_id;
665    uint32_t igbp_slot;
666    const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
667            handle,
668            &info.mapperInfo.width, &info.mapperInfo.height,
669            (uint32_t *)&info.mapperInfo.format, (uint64_t *)&info.mapperInfo.usage, &info.stride,
670            &igbp_id, &igbp_slot);
671    if (grallocHandle == nullptr) {
672        return C2_BAD_VALUE;
673    }
674
675    hidl_handle hidlHandle;
676    hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
677
678    allocation->reset(new C2AllocationGralloc(info, mMapper, hidlHandle, grallocHandle, mTraits->id));
679    return C2_OK;
680}
681
682C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
683        : mImpl(new Impl(id, bufferQueue)) {}
684
685C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
686
687C2Allocator::id_t C2AllocatorGralloc::getId() const {
688    return mImpl->getId();
689}
690
691C2String C2AllocatorGralloc::getName() const {
692    return mImpl->getName();
693}
694
695std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
696    return mImpl->getTraits();
697}
698
699c2_status_t C2AllocatorGralloc::newGraphicAllocation(
700        uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
701        std::shared_ptr<C2GraphicAllocation> *allocation) {
702    return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
703}
704
705c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
706        const C2Handle *handle,
707        std::shared_ptr<C2GraphicAllocation> *allocation) {
708    return mImpl->priorGraphicAllocation(handle, allocation);
709}
710
711c2_status_t C2AllocatorGralloc::status() const {
712    return mImpl->status();
713}
714
715bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
716    return C2HandleGralloc::isValid(o);
717}
718
719} // namespace android
720