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 <mutex>
22 
23 #include <android/hardware/graphics/common/1.2/types.h>
24 #include <cutils/native_handle.h>
25 #include <hardware/gralloc.h>
26 #include <ui/GraphicBufferAllocator.h>
27 #include <ui/GraphicBufferMapper.h>
28 
29 #include <C2AllocatorGralloc.h>
30 #include <C2Buffer.h>
31 #include <C2PlatformSupport.h>
32 
33 using ::android::hardware::hidl_handle;
34 using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
35 
36 namespace android {
37 
38 namespace /* unnamed */ {
39     enum : uint64_t {
40         /**
41          * Usage mask that is passed through from gralloc to Codec 2.0 usage.
42          */
43         PASSTHROUGH_USAGE_MASK =
44             ~(GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_PROTECTED)
45     };
46 
47     // verify that passthrough mask is within the platform mask
48     static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
49 } // unnamed
50 
FromGrallocUsage(uint64_t usage)51 C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
52     // gralloc does not support WRITE_PROTECTED
53     return C2MemoryUsage(
54             ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
55             ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
56             ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
57             (usage & PASSTHROUGH_USAGE_MASK));
58 }
59 
asGrallocUsage() const60 uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
61     // gralloc does not support WRITE_PROTECTED
62     return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
63             ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
64             ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
65             (expected & PASSTHROUGH_USAGE_MASK));
66 }
67 
68 namespace /* unnamed */ {
69 
70 /* ===================================== GRALLOC ALLOCATION ==================================== */
native_handle_is_invalid(const native_handle_t * const handle)71 bool native_handle_is_invalid(const native_handle_t *const handle) {
72     // perform basic validation of a native handle
73     if (handle == nullptr) {
74         // null handle is considered valid
75         return false;
76     }
77     return ((size_t)handle->version != sizeof(native_handle_t) ||
78             handle->numFds < 0 ||
79             handle->numInts < 0 ||
80             // for sanity assume handles must occupy less memory than INT_MAX bytes
81             handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
82 }
83 
84 class C2HandleGralloc : public C2Handle {
85 private:
86     struct ExtraData {
87         uint32_t width;
88         uint32_t height;
89         uint32_t format;
90         uint32_t usage_lo;
91         uint32_t usage_hi;
92         uint32_t stride;
93         uint32_t generation;
94         uint32_t igbp_id_lo;
95         uint32_t igbp_id_hi;
96         uint32_t igbp_slot;
97         uint32_t magic;
98     };
99 
100     enum {
101         NUM_INTS = sizeof(ExtraData) / sizeof(int),
102     };
103     const static uint32_t MAGIC = '\xc2gr\x00';
104 
105     static
getExtraData(const C2Handle * const handle)106     const ExtraData* getExtraData(const C2Handle *const handle) {
107         if (handle == nullptr
108                 || native_handle_is_invalid(handle)
109                 || handle->numInts < NUM_INTS) {
110             return nullptr;
111         }
112         return reinterpret_cast<const ExtraData*>(
113                 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
114     }
115 
116     static
getExtraData(C2Handle * const handle)117     ExtraData *getExtraData(C2Handle *const handle) {
118         return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle)));
119     }
120 
121 public:
getIgbpData(uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot) const122     void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
123         const ExtraData *ed = getExtraData(this);
124         *generation = ed->generation;
125         *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
126         *igbp_slot = ed->igbp_slot;
127     }
128 
isValid(const C2Handle * const o)129     static bool isValid(const C2Handle *const o) {
130         if (o == nullptr) { // null handle is always valid
131             return true;
132         }
133         const ExtraData *xd = getExtraData(o);
134         // we cannot validate width/height/format/usage without accessing gralloc driver
135         return xd != nullptr && xd->magic == MAGIC;
136     }
137 
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)138     static C2HandleGralloc* WrapAndMoveNativeHandle(
139             const native_handle_t *const handle,
140             uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
141             uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
142         //CHECK(handle != nullptr);
143         if (native_handle_is_invalid(handle) ||
144             handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
145             return nullptr;
146         }
147         ExtraData xd = {
148             width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
149             stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
150             igbp_slot, MAGIC
151         };
152         native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
153         if (res != nullptr) {
154             memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
155             *getExtraData(res) = xd;
156         }
157         return reinterpret_cast<C2HandleGralloc *>(res);
158     }
159 
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)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, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
164         if (handle == nullptr) {
165             return nullptr;
166         }
167         native_handle_t *clone = native_handle_clone(handle);
168         if (clone == nullptr) {
169             return nullptr;
170         }
171         C2HandleGralloc *res = WrapAndMoveNativeHandle(
172                 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
173         if (res == nullptr) {
174             native_handle_close(clone);
175         }
176         native_handle_delete(clone);
177         return res;
178     }
179 
MigrateNativeHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)180     static bool MigrateNativeHandle(
181             native_handle_t *handle,
182             uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
183         if (handle == nullptr || !isValid(handle)) {
184             return false;
185         }
186         ExtraData *ed = getExtraData(handle);
187         if (!ed) return false;
188         ed->generation = generation;
189         ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
190         ed->igbp_id_hi = uint32_t(igbp_id >> 32);
191         ed->igbp_slot = igbp_slot;
192         return true;
193     }
194 
195 
UnwrapNativeHandle(const C2Handle * const handle)196     static native_handle_t* UnwrapNativeHandle(
197             const C2Handle *const handle) {
198         const ExtraData *xd = getExtraData(handle);
199         if (xd == nullptr || xd->magic != MAGIC) {
200             return nullptr;
201         }
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 
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)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             uint32_t *generation, 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         *generation = xd->generation;
224         *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
225         *igbp_slot = xd->igbp_slot;
226         return reinterpret_cast<const C2HandleGralloc *>(handle);
227     }
228 };
229 
230 } // unnamed namespace
231 
UnwrapNativeCodec2GrallocHandle(const C2Handle * const handle)232 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
233     return C2HandleGralloc::UnwrapNativeHandle(handle);
234 }
235 
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)236 C2Handle *WrapNativeCodec2GrallocHandle(
237         const native_handle_t *const handle,
238         uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
239         uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
240     return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
241                                              generation, igbp_id, igbp_slot);
242 }
243 
MigrateNativeCodec2GrallocHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)244 bool MigrateNativeCodec2GrallocHandle(
245         native_handle_t *handle,
246         uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
247     return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
248 }
249 
250 
251 class C2AllocationGralloc : public C2GraphicAllocation {
252 public:
253     virtual ~C2AllocationGralloc() override;
254 
255     virtual c2_status_t map(
256             C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
257             C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
258     virtual c2_status_t unmap(
259             uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
getAllocatorId() const260     virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
handle() const261     virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
262     virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
263 
264     // internal methods
265     // |handle| will be moved.
266 
267     C2AllocationGralloc(
268               uint32_t width, uint32_t height,
269               uint32_t format, uint32_t layerCount,
270               uint64_t grallocUsage, uint32_t stride,
271               hidl_handle &hidlHandle,
272               const C2HandleGralloc *const handle,
273               C2Allocator::id_t allocatorId);
274     int dup() const;
275     c2_status_t status() const;
276 
277 private:
278     const uint32_t mWidth;
279     const uint32_t mHeight;
280     const uint32_t mFormat;
281     const uint32_t mLayerCount;
282     const uint64_t mGrallocUsage;
283     const uint32_t mStride;
284     const hidl_handle mHidlHandle;
285     const C2HandleGralloc *mHandle;
286     buffer_handle_t mBuffer;
287     const C2HandleGralloc *mLockedHandle;
288     bool mLocked;
289     C2Allocator::id_t mAllocatorId;
290     std::mutex mMappedLock;
291 };
292 
C2AllocationGralloc(uint32_t width,uint32_t height,uint32_t format,uint32_t layerCount,uint64_t grallocUsage,uint32_t stride,hidl_handle & hidlHandle,const C2HandleGralloc * const handle,C2Allocator::id_t allocatorId)293 C2AllocationGralloc::C2AllocationGralloc(
294           uint32_t width, uint32_t height,
295           uint32_t format, uint32_t layerCount,
296           uint64_t grallocUsage, uint32_t stride,
297           hidl_handle &hidlHandle,
298           const C2HandleGralloc *const handle,
299           C2Allocator::id_t allocatorId)
300     : C2GraphicAllocation(width, height),
301       mWidth(width),
302       mHeight(height),
303       mFormat(format),
304       mLayerCount(layerCount),
305       mGrallocUsage(grallocUsage),
306       mStride(stride),
307       mHidlHandle(std::move(hidlHandle)),
308       mHandle(handle),
309       mBuffer(nullptr),
310       mLockedHandle(nullptr),
311       mLocked(false),
312       mAllocatorId(allocatorId) {
313 }
314 
~C2AllocationGralloc()315 C2AllocationGralloc::~C2AllocationGralloc() {
316     if (mBuffer && mLocked) {
317         // implementation ignores addresss and rect
318         uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
319         unmap(addr, C2Rect(), nullptr);
320     }
321     if (mBuffer) {
322         status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
323         if (err) {
324             ALOGE("failed transaction: freeBuffer");
325         }
326     }
327     if (mHandle) {
328         native_handle_delete(
329                 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
330     }
331     if (mLockedHandle) {
332         native_handle_delete(
333                 const_cast<native_handle_t *>(
334                         reinterpret_cast<const native_handle_t *>(mLockedHandle)));
335     }
336 }
337 
map(C2Rect rect,C2MemoryUsage usage,C2Fence * fence,C2PlanarLayout * layout,uint8_t ** addr)338 c2_status_t C2AllocationGralloc::map(
339         C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
340         C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
341     uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
342     ALOGV("mapping buffer with usage %#llx => %#llx",
343           (long long)usage.expected, (long long)grallocUsage);
344 
345     // TODO
346     (void)fence;
347 
348     std::lock_guard<std::mutex> lock(mMappedLock);
349     if (mBuffer && mLocked) {
350         ALOGD("already mapped");
351         return C2_DUPLICATE;
352     }
353     if (!layout || !addr) {
354         ALOGD("wrong param");
355         return C2_BAD_VALUE;
356     }
357 
358     if (!mBuffer) {
359         status_t err = GraphicBufferMapper::get().importBuffer(
360                             mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
361                             mFormat, mGrallocUsage, mStride, &mBuffer);
362         if (err) {
363             ALOGE("failed transaction: importBuffer");
364             return C2_CORRUPTED;
365         }
366         if (mBuffer == nullptr) {
367             ALOGD("importBuffer returned null buffer");
368             return C2_CORRUPTED;
369         }
370         uint32_t generation = 0;
371         uint64_t igbp_id = 0;
372         uint32_t igbp_slot = 0;
373         if (mHandle) {
374             mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
375         }
376 
377         mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
378                 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
379                 mStride, generation, igbp_id, igbp_slot);
380     }
381     switch (mFormat) {
382         case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
383             // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
384             // Surface. In all other cases it is RGBA. We don't know which case it is here, so
385             // default to YUV for now.
386             void *pointer = nullptr;
387             // TODO: fence
388             status_t err = GraphicBufferMapper::get().lock(
389                                 const_cast<native_handle_t *>(mBuffer), grallocUsage,
390                                 { (int32_t)rect.left, (int32_t)rect.top,
391                                   (int32_t)rect.width, (int32_t)rect.height },
392                                 &pointer);
393             if (err) {
394                 ALOGE("failed transaction: lock(RGBA_1010102)");
395                 return C2_CORRUPTED;
396             }
397             // treat as 32-bit values
398             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
399             addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
400             addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
401             addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
402             layout->type = C2PlanarLayout::TYPE_YUVA;
403             layout->numPlanes = 4;
404             layout->rootPlanes = 1;
405             layout->planes[C2PlanarLayout::PLANE_Y] = {
406                 C2PlaneInfo::CHANNEL_Y,         // channel
407                 4,                              // colInc
408                 static_cast<int32_t>(4 * mStride), // rowInc
409                 1,                              // mColSampling
410                 1,                              // mRowSampling
411                 32,                             // allocatedDepth
412                 10,                             // bitDepth
413                 10,                             // rightShift
414                 C2PlaneInfo::LITTLE_END,        // endianness
415                 C2PlanarLayout::PLANE_Y,        // rootIx
416                 0,                              // offset
417             };
418             layout->planes[C2PlanarLayout::PLANE_U] = {
419                 C2PlaneInfo::CHANNEL_CB,         // channel
420                 4,                              // colInc
421                 static_cast<int32_t>(4 * mStride), // rowInc
422                 1,                              // mColSampling
423                 1,                              // mRowSampling
424                 32,                             // allocatedDepth
425                 10,                             // bitDepth
426                 0,                              // rightShift
427                 C2PlaneInfo::LITTLE_END,        // endianness
428                 C2PlanarLayout::PLANE_Y,        // rootIx
429                 0,                              // offset
430             };
431             layout->planes[C2PlanarLayout::PLANE_V] = {
432                 C2PlaneInfo::CHANNEL_CR,         // channel
433                 4,                              // colInc
434                 static_cast<int32_t>(4 * mStride), // rowInc
435                 1,                              // mColSampling
436                 1,                              // mRowSampling
437                 32,                             // allocatedDepth
438                 10,                             // bitDepth
439                 20,                             // rightShift
440                 C2PlaneInfo::LITTLE_END,        // endianness
441                 C2PlanarLayout::PLANE_Y,        // rootIx
442                 0,                              // offset
443             };
444             layout->planes[C2PlanarLayout::PLANE_A] = {
445                 C2PlaneInfo::CHANNEL_A,         // channel
446                 4,                              // colInc
447                 static_cast<int32_t>(4 * mStride), // rowInc
448                 1,                              // mColSampling
449                 1,                              // mRowSampling
450                 32,                             // allocatedDepth
451                 2,                              // bitDepth
452                 30,                             // rightShift
453                 C2PlaneInfo::LITTLE_END,        // endianness
454                 C2PlanarLayout::PLANE_Y,        // rootIx
455                 0,                              // offset
456             };
457             break;
458         }
459 
460         case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
461             // TODO: alpha channel
462             // fall-through
463         case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
464             void *pointer = nullptr;
465             // TODO: fence
466             status_t err = GraphicBufferMapper::get().lock(
467                                 const_cast<native_handle_t*>(mBuffer), grallocUsage,
468                                 { (int32_t)rect.left, (int32_t)rect.top,
469                                   (int32_t)rect.width, (int32_t)rect.height },
470                                 &pointer);
471             if (err) {
472                 ALOGE("failed transaction: lock(RGBA_8888)");
473                 return C2_CORRUPTED;
474             }
475             addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
476             addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
477             addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
478             layout->type = C2PlanarLayout::TYPE_RGB;
479             layout->numPlanes = 3;
480             layout->rootPlanes = 1;
481             layout->planes[C2PlanarLayout::PLANE_R] = {
482                 C2PlaneInfo::CHANNEL_R,         // channel
483                 4,                              // colInc
484                 static_cast<int32_t>(4 * mStride), // rowInc
485                 1,                              // mColSampling
486                 1,                              // mRowSampling
487                 8,                              // allocatedDepth
488                 8,                              // bitDepth
489                 0,                              // rightShift
490                 C2PlaneInfo::NATIVE,            // endianness
491                 C2PlanarLayout::PLANE_R,        // rootIx
492                 0,                              // offset
493             };
494             layout->planes[C2PlanarLayout::PLANE_G] = {
495                 C2PlaneInfo::CHANNEL_G,         // channel
496                 4,                              // colInc
497                 static_cast<int32_t>(4 * mStride), // rowInc
498                 1,                              // mColSampling
499                 1,                              // mRowSampling
500                 8,                              // allocatedDepth
501                 8,                              // bitDepth
502                 0,                              // rightShift
503                 C2PlaneInfo::NATIVE,            // endianness
504                 C2PlanarLayout::PLANE_R,        // rootIx
505                 1,                              // offset
506             };
507             layout->planes[C2PlanarLayout::PLANE_B] = {
508                 C2PlaneInfo::CHANNEL_B,         // channel
509                 4,                              // colInc
510                 static_cast<int32_t>(4 * mStride), // 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                 2,                              // offset
519             };
520             break;
521         }
522 
523         case static_cast<uint32_t>(PixelFormat4::BLOB): {
524             void *pointer = nullptr;
525             // TODO: fence
526             status_t err = GraphicBufferMapper::get().lock(
527                                 const_cast<native_handle_t*>(mBuffer), grallocUsage,
528                                 { (int32_t)rect.left, (int32_t)rect.top,
529                                   (int32_t)rect.width, (int32_t)rect.height },
530                                 &pointer);
531             if (err) {
532                 ALOGE("failed transaction: lock(BLOB)");
533                 return C2_CORRUPTED;
534             }
535             *addr = (uint8_t *)pointer;
536             break;
537         }
538 
539         case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
540             // fall-through
541         case static_cast<uint32_t>(PixelFormat4::YV12):
542             // fall-through
543         default: {
544             android_ycbcr ycbcrLayout;
545 
546             status_t err = GraphicBufferMapper::get().lockYCbCr(
547                         const_cast<native_handle_t*>(mBuffer), grallocUsage,
548                         { (int32_t)rect.left, (int32_t)rect.top,
549                           (int32_t)rect.width, (int32_t)rect.height },
550                         &ycbcrLayout);
551             if (err) {
552                 ALOGE("failed transaction: lockYCbCr");
553                 return C2_CORRUPTED;
554             }
555 
556             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
557             addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
558             addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
559             layout->type = C2PlanarLayout::TYPE_YUV;
560             layout->numPlanes = 3;
561             layout->rootPlanes = 3;
562             layout->planes[C2PlanarLayout::PLANE_Y] = {
563                 C2PlaneInfo::CHANNEL_Y,         // channel
564                 1,                              // colInc
565                 (int32_t)ycbcrLayout.ystride,   // rowInc
566                 1,                              // mColSampling
567                 1,                              // mRowSampling
568                 8,                              // allocatedDepth
569                 8,                              // bitDepth
570                 0,                              // rightShift
571                 C2PlaneInfo::NATIVE,            // endianness
572                 C2PlanarLayout::PLANE_Y,        // rootIx
573                 0,                              // offset
574             };
575             layout->planes[C2PlanarLayout::PLANE_U] = {
576                 C2PlaneInfo::CHANNEL_CB,          // channel
577                 (int32_t)ycbcrLayout.chroma_step, // colInc
578                 (int32_t)ycbcrLayout.cstride,     // rowInc
579                 2,                                // mColSampling
580                 2,                                // mRowSampling
581                 8,                                // allocatedDepth
582                 8,                                // bitDepth
583                 0,                                // rightShift
584                 C2PlaneInfo::NATIVE,              // endianness
585                 C2PlanarLayout::PLANE_U,          // rootIx
586                 0,                                // offset
587             };
588             layout->planes[C2PlanarLayout::PLANE_V] = {
589                 C2PlaneInfo::CHANNEL_CR,          // channel
590                 (int32_t)ycbcrLayout.chroma_step, // colInc
591                 (int32_t)ycbcrLayout.cstride,     // rowInc
592                 2,                                // mColSampling
593                 2,                                // mRowSampling
594                 8,                                // allocatedDepth
595                 8,                                // bitDepth
596                 0,                                // rightShift
597                 C2PlaneInfo::NATIVE,              // endianness
598                 C2PlanarLayout::PLANE_V,          // rootIx
599                 0,                                // offset
600             };
601             // handle interleaved formats
602             intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
603             if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
604                 layout->rootPlanes = 2;
605                 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
606                 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
607             } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
608                 layout->rootPlanes = 2;
609                 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
610                 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
611             }
612             break;
613         }
614     }
615     mLocked = true;
616 
617     return C2_OK;
618 }
619 
unmap(uint8_t ** addr,C2Rect rect,C2Fence * fence)620 c2_status_t C2AllocationGralloc::unmap(
621         uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
622     // TODO: check addr and size, use fence
623     (void)addr;
624     (void)rect;
625     (void)fence;
626 
627     std::lock_guard<std::mutex> lock(mMappedLock);
628     // TODO: fence
629     status_t err = GraphicBufferMapper::get().unlock(mBuffer);
630     if (err) {
631         ALOGE("failed transaction: unlock");
632         return C2_CORRUPTED;
633     }
634 
635     mLocked = false;
636     return C2_OK;
637 }
638 
equals(const std::shared_ptr<const C2GraphicAllocation> & other) const639 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
640     return other && other->handle() == handle();
641 }
642 
643 /* ===================================== GRALLOC ALLOCATOR ==================================== */
644 class C2AllocatorGralloc::Impl {
645 public:
646     Impl(id_t id, bool bufferQueue);
647 
getId() const648     id_t getId() const {
649         return mTraits->id;
650     }
651 
getName() const652     C2String getName() const {
653         return mTraits->name;
654     }
655 
getTraits() const656     std::shared_ptr<const C2Allocator::Traits> getTraits() const {
657         return mTraits;
658     }
659 
660     c2_status_t newGraphicAllocation(
661             uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
662             std::shared_ptr<C2GraphicAllocation> *allocation);
663 
664     c2_status_t priorGraphicAllocation(
665             const C2Handle *handle,
666             std::shared_ptr<C2GraphicAllocation> *allocation);
667 
status() const668     c2_status_t status() const { return mInit; }
669 
670 private:
671     std::shared_ptr<C2Allocator::Traits> mTraits;
672     c2_status_t mInit;
673     const bool mBufferQueue;
674 };
675 
_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)676 void _UnwrapNativeCodec2GrallocMetadata(
677         const C2Handle *const handle,
678         uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
679         uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
680     (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
681                                   generation, igbp_id, igbp_slot);
682 }
683 
Impl(id_t id,bool bufferQueue)684 C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
685     : mInit(C2_OK), mBufferQueue(bufferQueue) {
686     // TODO: get this from allocator
687     C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
688     Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
689     mTraits = std::make_shared<C2Allocator::Traits>(traits);
690 }
691 
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,const C2MemoryUsage & usage,std::shared_ptr<C2GraphicAllocation> * allocation)692 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
693         uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
694         std::shared_ptr<C2GraphicAllocation> *allocation) {
695     uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
696     ALOGV("allocating buffer with usage %#llx => %#llx",
697           (long long)usage.expected, (long long)grallocUsage);
698 
699     buffer_handle_t buffer;
700 
701     uint32_t stride = 0;
702 
703     status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
704             1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
705     if (err) {
706         ALOGE("failed transaction: allocate");
707         return C2_CORRUPTED;
708     }
709 
710     hidl_handle hidlHandle;
711     hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
712 
713     allocation->reset(new C2AllocationGralloc(
714             width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
715             C2HandleGralloc::WrapAndMoveNativeHandle(
716                     hidlHandle, width, height,
717                     format, grallocUsage, stride,
718                     0, 0, mBufferQueue ? ~0 : 0),
719             mTraits->id));
720     return C2_OK;
721 }
722 
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)723 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
724         const C2Handle *handle,
725         std::shared_ptr<C2GraphicAllocation> *allocation) {
726 
727     uint32_t generation;
728     uint64_t igbp_id;
729     uint32_t igbp_slot;
730 
731     uint32_t width;
732     uint32_t height;
733     uint32_t format;
734     uint32_t layerCount = 1;
735     uint64_t grallocUsage;
736     uint32_t stride;
737 
738     const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
739             handle, &width, &height, &format, &grallocUsage, &stride,
740             &generation, &igbp_id, &igbp_slot);
741     if (grallocHandle == nullptr) {
742         return C2_BAD_VALUE;
743     }
744 
745     hidl_handle hidlHandle;
746     hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
747 
748     allocation->reset(new C2AllocationGralloc(
749             width, height, format, layerCount,
750             grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
751     return C2_OK;
752 }
753 
C2AllocatorGralloc(id_t id,bool bufferQueue)754 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
755         : mImpl(new Impl(id, bufferQueue)) {}
756 
~C2AllocatorGralloc()757 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
758 
getId() const759 C2Allocator::id_t C2AllocatorGralloc::getId() const {
760     return mImpl->getId();
761 }
762 
getName() const763 C2String C2AllocatorGralloc::getName() const {
764     return mImpl->getName();
765 }
766 
getTraits() const767 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
768     return mImpl->getTraits();
769 }
770 
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicAllocation> * allocation)771 c2_status_t C2AllocatorGralloc::newGraphicAllocation(
772         uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
773         std::shared_ptr<C2GraphicAllocation> *allocation) {
774     return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
775 }
776 
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)777 c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
778         const C2Handle *handle,
779         std::shared_ptr<C2GraphicAllocation> *allocation) {
780     return mImpl->priorGraphicAllocation(handle, allocation);
781 }
782 
status() const783 c2_status_t C2AllocatorGralloc::status() const {
784     return mImpl->status();
785 }
786 
isValid(const C2Handle * const o)787 bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
788     return C2HandleGralloc::isValid(o);
789 }
790 
791 } // namespace android
792