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 
FromGrallocUsage(uint64_t usage)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 
asGrallocUsage() const54 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 ==================================== */
maperr2error(Error maperr)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
native_handle_is_invalid(const native_handle_t * const handle)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 generation;
118         uint32_t igbp_id_lo;
119         uint32_t igbp_id_hi;
120         uint32_t igbp_slot;
121         uint32_t magic;
122     };
123 
124     enum {
125         NUM_INTS = sizeof(ExtraData) / sizeof(int),
126     };
127     const static uint32_t MAGIC = '\xc2gr\x00';
128 
129     static
getExtraData(const C2Handle * const handle)130     const ExtraData* getExtraData(const C2Handle *const handle) {
131         if (handle == nullptr
132                 || native_handle_is_invalid(handle)
133                 || handle->numInts < NUM_INTS) {
134             return nullptr;
135         }
136         return reinterpret_cast<const ExtraData*>(
137                 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
138     }
139 
140     static
getExtraData(C2Handle * const handle)141     ExtraData *getExtraData(C2Handle *const handle) {
142         return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle)));
143     }
144 
145 public:
getIgbpData(uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot) const146     void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
147         const ExtraData *ed = getExtraData(this);
148         *generation = ed->generation;
149         *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
150         *igbp_slot = ed->igbp_slot;
151     }
152 
isValid(const C2Handle * const o)153     static bool isValid(const C2Handle *const o) {
154         if (o == nullptr) { // null handle is always valid
155             return true;
156         }
157         const ExtraData *xd = getExtraData(o);
158         // we cannot validate width/height/format/usage without accessing gralloc driver
159         return xd != nullptr && xd->magic == MAGIC;
160     }
161 
WrapAndMoveNativeHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id=0,uint32_t igbp_slot=0)162     static C2HandleGralloc* WrapAndMoveNativeHandle(
163             const native_handle_t *const handle,
164             uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
165             uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
166         //CHECK(handle != nullptr);
167         if (native_handle_is_invalid(handle) ||
168             handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
169             return nullptr;
170         }
171         ExtraData xd = {
172             width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
173             stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
174             igbp_slot, MAGIC
175         };
176         native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
177         if (res != nullptr) {
178             memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
179             *getExtraData(res) = xd;
180         }
181         return reinterpret_cast<C2HandleGralloc *>(res);
182     }
183 
WrapNativeHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id=0,uint32_t igbp_slot=0)184     static C2HandleGralloc* WrapNativeHandle(
185             const native_handle_t *const handle,
186             uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
187             uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
188         if (handle == nullptr) {
189             return nullptr;
190         }
191         native_handle_t *clone = native_handle_clone(handle);
192         if (clone == nullptr) {
193             return nullptr;
194         }
195         C2HandleGralloc *res = WrapAndMoveNativeHandle(
196                 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
197         if (res == nullptr) {
198             native_handle_close(clone);
199         }
200         native_handle_delete(clone);
201         return res;
202     }
203 
UnwrapNativeHandle(const C2Handle * const handle)204     static native_handle_t* UnwrapNativeHandle(
205             const C2Handle *const handle) {
206         const ExtraData *xd = getExtraData(handle);
207         if (xd == nullptr || xd->magic != MAGIC) {
208             return nullptr;
209         }
210         native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
211         if (res != nullptr) {
212             memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
213         }
214         return res;
215     }
216 
UnwrapNativeHandle(const C2Handle * const handle,uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot)217     static native_handle_t* UnwrapNativeHandle(
218             const C2Handle *const handle,
219             uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
220         const ExtraData *xd = getExtraData(handle);
221         if (xd == nullptr || xd->magic != MAGIC) {
222             return nullptr;
223         }
224         *generation = xd->generation;
225         *igbp_id = unsigned(xd->igbp_id_lo) | uint64_t(unsigned(xd->igbp_id_hi)) << 32;
226         *igbp_slot = xd->igbp_slot;
227         native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
228         if (res != nullptr) {
229             memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
230         }
231         return res;
232     }
233 
Import(const C2Handle * const handle,uint32_t * width,uint32_t * height,uint32_t * format,uint64_t * usage,uint32_t * stride,uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot)234     static const C2HandleGralloc* Import(
235             const C2Handle *const handle,
236             uint32_t *width, uint32_t *height, uint32_t *format,
237             uint64_t *usage, uint32_t *stride,
238             uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
239         const ExtraData *xd = getExtraData(handle);
240         if (xd == nullptr) {
241             return nullptr;
242         }
243         *width = xd->width;
244         *height = xd->height;
245         *format = xd->format;
246         *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
247         *stride = xd->stride;
248         *generation = xd->generation;
249         *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
250         *igbp_slot = xd->igbp_slot;
251         return reinterpret_cast<const C2HandleGralloc *>(handle);
252     }
253 };
254 
UnwrapNativeCodec2GrallocHandle(const C2Handle * const handle)255 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
256     return C2HandleGralloc::UnwrapNativeHandle(handle);
257 }
258 
UnwrapNativeCodec2GrallocHandle(const C2Handle * const handle,uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot)259 native_handle_t *UnwrapNativeCodec2GrallocHandle(
260         const C2Handle *const handle,
261         uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
262     return C2HandleGralloc::UnwrapNativeHandle(handle, generation, igbp_id, igbp_slot);
263 }
264 
WrapNativeCodec2GrallocHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)265 C2Handle *WrapNativeCodec2GrallocHandle(
266         const native_handle_t *const handle,
267         uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
268         uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
269     return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
270                                              generation, igbp_id, igbp_slot);
271 }
272 
273 class C2AllocationGralloc : public C2GraphicAllocation {
274 public:
275     virtual ~C2AllocationGralloc() override;
276 
277     virtual c2_status_t map(
278             C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
279             C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
280     virtual c2_status_t unmap(
281             uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
getAllocatorId() const282     virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
handle() const283     virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
284     virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
285 
286     // internal methods
287     // |handle| will be moved.
288     C2AllocationGralloc(
289               const BufferDescriptorInfo &info,
290               const sp<IMapper> &mapper,
291               hidl_handle &hidlHandle,
292               const C2HandleGralloc *const handle,
293               C2Allocator::id_t allocatorId);
294     int dup() const;
295     c2_status_t status() const;
296 
297 private:
298     const BufferDescriptorInfo mInfo;
299     const sp<IMapper> mMapper;
300     const hidl_handle mHidlHandle;
301     const C2HandleGralloc *mHandle;
302     buffer_handle_t mBuffer;
303     const C2HandleGralloc *mLockedHandle;
304     bool mLocked;
305     C2Allocator::id_t mAllocatorId;
306     std::mutex mMappedLock;
307 };
308 
C2AllocationGralloc(const BufferDescriptorInfo & info,const sp<IMapper> & mapper,hidl_handle & hidlHandle,const C2HandleGralloc * const handle,C2Allocator::id_t allocatorId)309 C2AllocationGralloc::C2AllocationGralloc(
310           const BufferDescriptorInfo &info,
311           const sp<IMapper> &mapper,
312           hidl_handle &hidlHandle,
313           const C2HandleGralloc *const handle,
314           C2Allocator::id_t allocatorId)
315     : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
316       mInfo(info),
317       mMapper(mapper),
318       mHidlHandle(std::move(hidlHandle)),
319       mHandle(handle),
320       mBuffer(nullptr),
321       mLockedHandle(nullptr),
322       mLocked(false),
323       mAllocatorId(allocatorId) {
324 }
325 
~C2AllocationGralloc()326 C2AllocationGralloc::~C2AllocationGralloc() {
327     if (mBuffer && mLocked) {
328         // implementation ignores addresss and rect
329         uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
330         unmap(addr, C2Rect(), nullptr);
331     }
332     if (mBuffer) {
333         mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
334     }
335     if (mHandle) {
336         native_handle_delete(
337                 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
338     }
339     if (mLockedHandle) {
340         native_handle_delete(
341                 const_cast<native_handle_t *>(
342                         reinterpret_cast<const native_handle_t *>(mLockedHandle)));
343     }
344 }
345 
map(C2Rect rect,C2MemoryUsage usage,C2Fence * fence,C2PlanarLayout * layout,uint8_t ** addr)346 c2_status_t C2AllocationGralloc::map(
347         C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
348         C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
349     uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
350     ALOGV("mapping buffer with usage %#llx => %#llx",
351           (long long)usage.expected, (long long)grallocUsage);
352 
353     // TODO
354     (void) fence;
355 
356     std::lock_guard<std::mutex> lock(mMappedLock);
357     if (mBuffer && mLocked) {
358         ALOGD("already mapped");
359         return C2_DUPLICATE;
360     }
361     if (!layout || !addr) {
362         ALOGD("wrong param");
363         return C2_BAD_VALUE;
364     }
365 
366     c2_status_t err = C2_OK;
367     if (!mBuffer) {
368         mMapper->importBuffer(
369                 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
370                     err = maperr2error(maperr);
371                     if (err == C2_OK) {
372                         mBuffer = static_cast<buffer_handle_t>(buffer);
373                     }
374                 });
375         if (err != C2_OK) {
376             ALOGD("importBuffer failed: %d", err);
377             return err;
378         }
379         if (mBuffer == nullptr) {
380             ALOGD("importBuffer returned null buffer");
381             return C2_CORRUPTED;
382         }
383         uint32_t generation = 0;
384         uint64_t igbp_id = 0;
385         uint32_t igbp_slot = 0;
386         if (mHandle) {
387             mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
388         }
389         mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
390                 mBuffer, mInfo.mapperInfo.width, mInfo.mapperInfo.height,
391                 (uint32_t)mInfo.mapperInfo.format, mInfo.mapperInfo.usage, mInfo.stride,
392                 generation, igbp_id, igbp_slot);
393     }
394 
395     // UGLY HACK: assume YCbCr 4:2:0 8-bit format (and lockable via lockYCbCr) if we don't
396     // recognize the format
397     PixelFormat format = mInfo.mapperInfo.format;
398     if (format != PixelFormat::RGBA_8888 && format != PixelFormat::RGBX_8888) {
399         format = PixelFormat::YCBCR_420_888;
400     }
401 
402     switch (format) {
403         case PixelFormat::YCBCR_420_888:
404         case PixelFormat::YV12: {
405             YCbCrLayout ycbcrLayout;
406             mMapper->lockYCbCr(
407                     const_cast<native_handle_t *>(mBuffer), grallocUsage,
408                     { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
409                     // TODO: fence
410                     hidl_handle(),
411                     [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
412                         err = maperr2error(maperr);
413                         if (err == C2_OK) {
414                             ycbcrLayout = mapLayout;
415                         }
416                     });
417             if (err != C2_OK) {
418                 ALOGD("lockYCbCr failed: %d", err);
419                 return err;
420             }
421             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
422             addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
423             addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
424             layout->type = C2PlanarLayout::TYPE_YUV;
425             layout->numPlanes = 3;
426             layout->rootPlanes = 3;
427             layout->planes[C2PlanarLayout::PLANE_Y] = {
428                 C2PlaneInfo::CHANNEL_Y,         // channel
429                 1,                              // colInc
430                 (int32_t)ycbcrLayout.yStride,   // rowInc
431                 1,                              // mColSampling
432                 1,                              // mRowSampling
433                 8,                              // allocatedDepth
434                 8,                              // bitDepth
435                 0,                              // rightShift
436                 C2PlaneInfo::NATIVE,            // endianness
437                 C2PlanarLayout::PLANE_Y,        // rootIx
438                 0,                              // offset
439             };
440             layout->planes[C2PlanarLayout::PLANE_U] = {
441                 C2PlaneInfo::CHANNEL_CB,          // channel
442                 (int32_t)ycbcrLayout.chromaStep,  // colInc
443                 (int32_t)ycbcrLayout.cStride,     // rowInc
444                 2,                                // mColSampling
445                 2,                                // mRowSampling
446                 8,                                // allocatedDepth
447                 8,                                // bitDepth
448                 0,                                // rightShift
449                 C2PlaneInfo::NATIVE,              // endianness
450                 C2PlanarLayout::PLANE_U,          // rootIx
451                 0,                                // offset
452             };
453             layout->planes[C2PlanarLayout::PLANE_V] = {
454                 C2PlaneInfo::CHANNEL_CR,          // channel
455                 (int32_t)ycbcrLayout.chromaStep,  // colInc
456                 (int32_t)ycbcrLayout.cStride,     // rowInc
457                 2,                                // mColSampling
458                 2,                                // mRowSampling
459                 8,                                // allocatedDepth
460                 8,                                // bitDepth
461                 0,                                // rightShift
462                 C2PlaneInfo::NATIVE,              // endianness
463                 C2PlanarLayout::PLANE_V,          // rootIx
464                 0,                                // offset
465             };
466             // handle interleaved formats
467             intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
468             if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
469                 layout->rootPlanes = 2;
470                 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
471                 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
472             } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
473                 layout->rootPlanes = 2;
474                 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
475                 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
476             }
477             break;
478         }
479 
480         case PixelFormat::RGBA_8888:
481             // TODO: alpha channel
482             // fall-through
483         case PixelFormat::RGBX_8888: {
484             void *pointer = nullptr;
485             mMapper->lock(
486                     const_cast<native_handle_t *>(mBuffer),
487                     grallocUsage,
488                     { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
489                     // TODO: fence
490                     hidl_handle(),
491                     [&err, &pointer](const auto &maperr, const auto &mapPointer) {
492                         err = maperr2error(maperr);
493                         if (err == C2_OK) {
494                             pointer = mapPointer;
495                         }
496                     });
497             if (err != C2_OK) {
498                 ALOGD("lock failed: %d", err);
499                 return err;
500             }
501             addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
502             addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
503             addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
504             layout->type = C2PlanarLayout::TYPE_RGB;
505             layout->numPlanes = 3;
506             layout->rootPlanes = 1;
507             layout->planes[C2PlanarLayout::PLANE_R] = {
508                 C2PlaneInfo::CHANNEL_R,         // channel
509                 4,                              // colInc
510                 4 * (int32_t)mInfo.stride,      // rowInc
511                 1,                              // mColSampling
512                 1,                              // mRowSampling
513                 8,                              // allocatedDepth
514                 8,                              // bitDepth
515                 0,                              // rightShift
516                 C2PlaneInfo::NATIVE,            // endianness
517                 C2PlanarLayout::PLANE_R,        // rootIx
518                 0,                              // offset
519             };
520             layout->planes[C2PlanarLayout::PLANE_G] = {
521                 C2PlaneInfo::CHANNEL_G,         // channel
522                 4,                              // colInc
523                 4 * (int32_t)mInfo.stride,      // rowInc
524                 1,                              // mColSampling
525                 1,                              // mRowSampling
526                 8,                              // allocatedDepth
527                 8,                              // bitDepth
528                 0,                              // rightShift
529                 C2PlaneInfo::NATIVE,            // endianness
530                 C2PlanarLayout::PLANE_R,        // rootIx
531                 1,                              // offset
532             };
533             layout->planes[C2PlanarLayout::PLANE_B] = {
534                 C2PlaneInfo::CHANNEL_B,         // channel
535                 4,                              // colInc
536                 4 * (int32_t)mInfo.stride,      // rowInc
537                 1,                              // mColSampling
538                 1,                              // mRowSampling
539                 8,                              // allocatedDepth
540                 8,                              // bitDepth
541                 0,                              // rightShift
542                 C2PlaneInfo::NATIVE,            // endianness
543                 C2PlanarLayout::PLANE_R,        // rootIx
544                 2,                              // offset
545             };
546             break;
547         }
548         default: {
549             ALOGD("unsupported pixel format: %d", mInfo.mapperInfo.format);
550             return C2_OMITTED;
551         }
552     }
553     mLocked = true;
554 
555     return C2_OK;
556 }
557 
unmap(uint8_t ** addr,C2Rect rect,C2Fence * fence)558 c2_status_t C2AllocationGralloc::unmap(
559         uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
560     // TODO: check addr and size, use fence
561     (void)addr;
562     (void)rect;
563 
564     std::lock_guard<std::mutex> lock(mMappedLock);
565     c2_status_t err = C2_OK;
566     mMapper->unlock(
567             const_cast<native_handle_t *>(mBuffer),
568             [&err, &fence](const auto &maperr, const auto &releaseFence) {
569                 // TODO
570                 (void) fence;
571                 (void) releaseFence;
572                 err = maperr2error(maperr);
573                 if (err == C2_OK) {
574                     // TODO: fence
575                 }
576             });
577     if (err == C2_OK) {
578         mLocked = false;
579     }
580     return err;
581 }
582 
equals(const std::shared_ptr<const C2GraphicAllocation> & other) const583 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
584     return other && other->handle() == handle();
585 }
586 
587 /* ===================================== GRALLOC ALLOCATOR ==================================== */
588 class C2AllocatorGralloc::Impl {
589 public:
590     Impl(id_t id, bool bufferQueue);
591 
getId() const592     id_t getId() const {
593         return mTraits->id;
594     }
595 
getName() const596     C2String getName() const {
597         return mTraits->name;
598     }
599 
getTraits() const600     std::shared_ptr<const C2Allocator::Traits> getTraits() const {
601         return mTraits;
602     }
603 
604     c2_status_t newGraphicAllocation(
605             uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
606             std::shared_ptr<C2GraphicAllocation> *allocation);
607 
608     c2_status_t priorGraphicAllocation(
609             const C2Handle *handle,
610             std::shared_ptr<C2GraphicAllocation> *allocation);
611 
status() const612     c2_status_t status() const { return mInit; }
613 
614 private:
615     std::shared_ptr<C2Allocator::Traits> mTraits;
616     c2_status_t mInit;
617     sp<IAllocator> mAllocator;
618     sp<IMapper> mMapper;
619     const bool mBufferQueue;
620 };
621 
_UnwrapNativeCodec2GrallocMetadata(const C2Handle * const handle,uint32_t * width,uint32_t * height,uint32_t * format,uint64_t * usage,uint32_t * stride,uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot)622 void _UnwrapNativeCodec2GrallocMetadata(
623         const C2Handle *const handle,
624         uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
625         uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
626     (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
627                                   generation, igbp_id, igbp_slot);
628 }
629 
Impl(id_t id,bool bufferQueue)630 C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
631     : mInit(C2_OK), mBufferQueue(bufferQueue) {
632     // TODO: get this from allocator
633     C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
634     Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
635     mTraits = std::make_shared<C2Allocator::Traits>(traits);
636 
637     // gralloc allocator is a singleton, so all objects share a global service
638     mAllocator = IAllocator::getService();
639     mMapper = IMapper::getService();
640     if (mAllocator == nullptr || mMapper == nullptr) {
641         mInit = C2_CORRUPTED;
642     }
643 }
644 
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,const C2MemoryUsage & usage,std::shared_ptr<C2GraphicAllocation> * allocation)645 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
646         uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
647         std::shared_ptr<C2GraphicAllocation> *allocation) {
648     uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
649     ALOGV("allocating buffer with usage %#llx => %#llx",
650           (long long)usage.expected, (long long)grallocUsage);
651 
652     BufferDescriptorInfo info = {
653         {
654             width,
655             height,
656             1u,  // layerCount
657             (PixelFormat)format,
658             grallocUsage,
659         },
660         0u,  // stride placeholder
661     };
662     c2_status_t err = C2_OK;
663     BufferDescriptor desc;
664     mMapper->createDescriptor(
665             info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
666                 err = maperr2error(maperr);
667                 if (err == C2_OK) {
668                     desc = descriptor;
669                 }
670             });
671     if (err != C2_OK) {
672         return err;
673     }
674 
675     // IAllocator shares IMapper error codes.
676     hidl_handle buffer;
677     mAllocator->allocate(
678             desc,
679             1u,
680             [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
681                 err = maperr2error(maperr);
682                 if (err != C2_OK) {
683                     return;
684                 }
685                 if (buffers.size() != 1u) {
686                     err = C2_CORRUPTED;
687                     return;
688                 }
689                 info.stride = stride;
690                 buffer = buffers[0];
691             });
692     if (err != C2_OK) {
693         return err;
694     }
695 
696 
697     allocation->reset(new C2AllocationGralloc(
698             info, mMapper, buffer,
699             C2HandleGralloc::WrapAndMoveNativeHandle(
700                     buffer.getNativeHandle(),
701                     info.mapperInfo.width, info.mapperInfo.height,
702                     (uint32_t)info.mapperInfo.format, info.mapperInfo.usage, info.stride,
703                     0, 0, mBufferQueue ? ~0 : 0),
704             mTraits->id));
705     return C2_OK;
706 }
707 
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)708 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
709         const C2Handle *handle,
710         std::shared_ptr<C2GraphicAllocation> *allocation) {
711     BufferDescriptorInfo info;
712     info.mapperInfo.layerCount = 1u;
713     uint32_t generation;
714     uint64_t igbp_id;
715     uint32_t igbp_slot;
716     const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
717             handle,
718             &info.mapperInfo.width, &info.mapperInfo.height,
719             (uint32_t *)&info.mapperInfo.format, (uint64_t *)&info.mapperInfo.usage, &info.stride,
720             &generation, &igbp_id, &igbp_slot);
721     if (grallocHandle == nullptr) {
722         return C2_BAD_VALUE;
723     }
724 
725     hidl_handle hidlHandle;
726     hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
727 
728     allocation->reset(new C2AllocationGralloc(info, mMapper, hidlHandle, grallocHandle, mTraits->id));
729     return C2_OK;
730 }
731 
C2AllocatorGralloc(id_t id,bool bufferQueue)732 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
733         : mImpl(new Impl(id, bufferQueue)) {}
734 
~C2AllocatorGralloc()735 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
736 
getId() const737 C2Allocator::id_t C2AllocatorGralloc::getId() const {
738     return mImpl->getId();
739 }
740 
getName() const741 C2String C2AllocatorGralloc::getName() const {
742     return mImpl->getName();
743 }
744 
getTraits() const745 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
746     return mImpl->getTraits();
747 }
748 
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicAllocation> * allocation)749 c2_status_t C2AllocatorGralloc::newGraphicAllocation(
750         uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
751         std::shared_ptr<C2GraphicAllocation> *allocation) {
752     return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
753 }
754 
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)755 c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
756         const C2Handle *handle,
757         std::shared_ptr<C2GraphicAllocation> *allocation) {
758     return mImpl->priorGraphicAllocation(handle, allocation);
759 }
760 
status() const761 c2_status_t C2AllocatorGralloc::status() const {
762     return mImpl->status();
763 }
764 
isValid(const C2Handle * const o)765 bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
766     return C2HandleGralloc::isValid(o);
767 }
768 
769 } // namespace android
770