Home | History | Annotate | Download | only in vndk
      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 
     30 namespace android {
     31 
     32 namespace {
     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 
     45 C2MemoryUsage 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 
     54 uint64_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 
     62 using ::android::hardware::graphics::allocator::V2_0::IAllocator;
     63 using ::android::hardware::graphics::common::V1_0::BufferUsage;
     64 using ::android::hardware::graphics::common::V1_0::PixelFormat;
     65 using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
     66 using ::android::hardware::graphics::mapper::V2_0::Error;
     67 using ::android::hardware::graphics::mapper::V2_0::IMapper;
     68 using ::android::hardware::graphics::mapper::V2_0::YCbCrLayout;
     69 using ::android::hardware::hidl_handle;
     70 using ::android::hardware::hidl_vec;
     71 
     72 namespace {
     73 
     74 struct BufferDescriptorInfo {
     75     IMapper::BufferDescriptorInfo mapperInfo;
     76     uint32_t stride;
     77 };
     78 
     79 }
     80 
     81 /* ===================================== GRALLOC ALLOCATION ==================================== */
     82 static 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 
     94 static
     95 bool 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 
    108 class C2HandleGralloc : public C2Handle {
    109 private:
    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 
    144 public:
    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 
    229 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
    230     return C2HandleGralloc::UnwrapNativeHandle(handle);
    231 }
    232 
    233 native_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 
    238 C2Handle *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 
    244 class C2AllocationGralloc : public C2GraphicAllocation {
    245 public:
    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 
    268 private:
    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 
    279 C2AllocationGralloc::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 
    296 C2AllocationGralloc::~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 
    310 c2_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 
    512 c2_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 
    535 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
    536     return other && other->handle() == handle();
    537 }
    538 
    539 /* ===================================== GRALLOC ALLOCATOR ==================================== */
    540 class C2AllocatorGralloc::Impl {
    541 public:
    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 
    566 private:
    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 
    574 void _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 
    581 C2AllocatorGralloc::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 
    596 c2_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 
    659 c2_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 
    682 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
    683         : mImpl(new Impl(id, bufferQueue)) {}
    684 
    685 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
    686 
    687 C2Allocator::id_t C2AllocatorGralloc::getId() const {
    688     return mImpl->getId();
    689 }
    690 
    691 C2String C2AllocatorGralloc::getName() const {
    692     return mImpl->getName();
    693 }
    694 
    695 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
    696     return mImpl->getTraits();
    697 }
    698 
    699 c2_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 
    705 c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
    706         const C2Handle *handle,
    707         std::shared_ptr<C2GraphicAllocation> *allocation) {
    708     return mImpl->priorGraphicAllocation(handle, allocation);
    709 }
    710 
    711 c2_status_t C2AllocatorGralloc::status() const {
    712     return mImpl->status();
    713 }
    714 
    715 bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
    716     return C2HandleGralloc::isValid(o);
    717 }
    718 
    719 } // namespace android
    720