• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <ui/Rect.h>
29 
30 #include <C2AllocatorGralloc.h>
31 #include <C2Buffer.h>
32 #include <C2PlatformSupport.h>
33 
34 using ::android::hardware::hidl_handle;
35 using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
36 
37 namespace android {
38 
39 namespace /* unnamed */ {
40     enum : uint64_t {
41         /**
42          * Usage mask that is passed through from gralloc to Codec 2.0 usage.
43          */
44         PASSTHROUGH_USAGE_MASK =
45             ~static_cast<uint64_t>(GRALLOC_USAGE_SW_READ_MASK |
46                                    GRALLOC_USAGE_SW_WRITE_MASK |
47                                    GRALLOC_USAGE_PROTECTED)
48     };
49 
50     // verify that passthrough mask is within the platform mask
51     static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
52 } // unnamed
53 
FromGrallocUsage(uint64_t usage)54 C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
55     // gralloc does not support WRITE_PROTECTED
56     return C2MemoryUsage(
57             ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
58             ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
59             ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
60             (usage & PASSTHROUGH_USAGE_MASK));
61 }
62 
asGrallocUsage() const63 uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
64     // gralloc does not support WRITE_PROTECTED
65     return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
66             ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
67             ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
68             (expected & PASSTHROUGH_USAGE_MASK));
69 }
70 
71 namespace /* unnamed */ {
72 
73 /* ===================================== GRALLOC ALLOCATION ==================================== */
native_handle_is_invalid(const native_handle_t * const handle)74 bool native_handle_is_invalid(const native_handle_t *const handle) {
75     // perform basic validation of a native handle
76     if (handle == nullptr) {
77         // null handle is considered valid
78         return false;
79     }
80     return ((size_t)handle->version != sizeof(native_handle_t) ||
81             handle->numFds < 0 ||
82             handle->numInts < 0 ||
83             // for sanity assume handles must occupy less memory than INT_MAX bytes
84             handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
85 }
86 
87 class C2HandleGralloc : public C2Handle {
88 private:
89     struct ExtraData {
90         uint32_t width;
91         uint32_t height;
92         uint32_t format;
93         uint32_t usage_lo;
94         uint32_t usage_hi;
95         uint32_t stride;
96         uint32_t generation;
97         uint32_t igbp_id_lo;
98         uint32_t igbp_id_hi;
99         uint32_t igbp_slot;
100         uint32_t magic;
101     };
102 
103     enum {
104         NUM_INTS = sizeof(ExtraData) / sizeof(int),
105     };
106     const static uint32_t MAGIC = '\xc2gr\x00';
107 
108     static
GetExtraData(const C2Handle * const handle)109     const ExtraData* GetExtraData(const C2Handle *const handle) {
110         if (handle == nullptr
111                 || native_handle_is_invalid(handle)
112                 || handle->numInts < NUM_INTS) {
113             return nullptr;
114         }
115         return reinterpret_cast<const ExtraData*>(
116                 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
117     }
118 
119     static
GetExtraData(C2Handle * const handle)120     ExtraData *GetExtraData(C2Handle *const handle) {
121         return const_cast<ExtraData *>(GetExtraData(const_cast<const C2Handle *const>(handle)));
122     }
123 
124 public:
getIgbpData(uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot) const125     void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
126         const ExtraData *ed = GetExtraData(this);
127         *generation = ed->generation;
128         *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
129         *igbp_slot = ed->igbp_slot;
130     }
131 
IsValid(const C2Handle * const o)132     static bool IsValid(const C2Handle *const o) {
133         if (o == nullptr) { // null handle is always valid
134             return true;
135         }
136         const ExtraData *xd = GetExtraData(o);
137         // we cannot validate width/height/format/usage without accessing gralloc driver
138         return xd != nullptr && xd->magic == MAGIC;
139     }
140 
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)141     static C2HandleGralloc* WrapAndMoveNativeHandle(
142             const native_handle_t *const handle,
143             uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
144             uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
145         //CHECK(handle != nullptr);
146         if (native_handle_is_invalid(handle) ||
147             handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
148             return nullptr;
149         }
150         ExtraData xd = {
151             width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
152             stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
153             igbp_slot, MAGIC
154         };
155         native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
156         if (res != nullptr) {
157             memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
158             *GetExtraData(res) = xd;
159         }
160         return reinterpret_cast<C2HandleGralloc *>(res);
161     }
162 
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)163     static C2HandleGralloc* WrapNativeHandle(
164             const native_handle_t *const handle,
165             uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
166             uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
167         if (handle == nullptr) {
168             return nullptr;
169         }
170         native_handle_t *clone = native_handle_clone(handle);
171         if (clone == nullptr) {
172             return nullptr;
173         }
174         C2HandleGralloc *res = WrapAndMoveNativeHandle(
175                 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
176         if (res == nullptr) {
177             native_handle_close(clone);
178         }
179         native_handle_delete(clone);
180         return res;
181     }
182 
MigrateNativeHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)183     static bool MigrateNativeHandle(
184             native_handle_t *handle,
185             uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
186         if (handle == nullptr || !IsValid(handle)) {
187             return false;
188         }
189         ExtraData *ed = GetExtraData(handle);
190         if (!ed) return false;
191         ed->generation = generation;
192         ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
193         ed->igbp_id_hi = uint32_t(igbp_id >> 32);
194         ed->igbp_slot = igbp_slot;
195         return true;
196     }
197 
198 
UnwrapNativeHandle(const C2Handle * const handle)199     static native_handle_t* UnwrapNativeHandle(
200             const C2Handle *const handle) {
201         const ExtraData *xd = GetExtraData(handle);
202         if (xd == nullptr || xd->magic != MAGIC) {
203             return nullptr;
204         }
205         native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
206         if (res != nullptr) {
207             memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
208         }
209         return res;
210     }
211 
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)212     static const C2HandleGralloc* Import(
213             const C2Handle *const handle,
214             uint32_t *width, uint32_t *height, uint32_t *format,
215             uint64_t *usage, uint32_t *stride,
216             uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
217         const ExtraData *xd = GetExtraData(handle);
218         if (xd == nullptr) {
219             return nullptr;
220         }
221         *width = xd->width;
222         *height = xd->height;
223         *format = xd->format;
224         *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
225         *stride = xd->stride;
226         *generation = xd->generation;
227         *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
228         *igbp_slot = xd->igbp_slot;
229         return reinterpret_cast<const C2HandleGralloc *>(handle);
230     }
231 };
232 
233 } // unnamed namespace
234 
UnwrapNativeCodec2GrallocHandle(const C2Handle * const handle)235 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
236     return C2HandleGralloc::UnwrapNativeHandle(handle);
237 }
238 
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)239 C2Handle *WrapNativeCodec2GrallocHandle(
240         const native_handle_t *const handle,
241         uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
242         uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
243     return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
244                                              generation, igbp_id, igbp_slot);
245 }
246 
MigrateNativeCodec2GrallocHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)247 bool MigrateNativeCodec2GrallocHandle(
248         native_handle_t *handle,
249         uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
250     return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
251 }
252 
253 
254 class C2AllocationGralloc : public C2GraphicAllocation {
255 public:
256     virtual ~C2AllocationGralloc() override;
257 
258     virtual c2_status_t map(
259             C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
260             C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
261     virtual c2_status_t unmap(
262             uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
getAllocatorId() const263     virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
handle() const264     virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
265     virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
266 
267     // internal methods
268     // |handle| will be moved.
269 
270     C2AllocationGralloc(
271               uint32_t width, uint32_t height,
272               uint32_t format, uint32_t layerCount,
273               uint64_t grallocUsage, uint32_t stride,
274               hidl_handle &hidlHandle,
275               const C2HandleGralloc *const handle,
276               C2Allocator::id_t allocatorId);
277     int dup() const;
278     c2_status_t status() const;
279 
280 private:
281     const uint32_t mWidth;
282     const uint32_t mHeight;
283     const uint32_t mFormat;
284     const uint32_t mLayerCount;
285     const uint64_t mGrallocUsage;
286     const uint32_t mStride;
287     const hidl_handle mHidlHandle;
288     const C2HandleGralloc *mHandle;
289     buffer_handle_t mBuffer;
290     const C2HandleGralloc *mLockedHandle;
291     bool mLocked;
292     C2Allocator::id_t mAllocatorId;
293     std::mutex mMappedLock;
294 };
295 
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)296 C2AllocationGralloc::C2AllocationGralloc(
297           uint32_t width, uint32_t height,
298           uint32_t format, uint32_t layerCount,
299           uint64_t grallocUsage, uint32_t stride,
300           hidl_handle &hidlHandle,
301           const C2HandleGralloc *const handle,
302           C2Allocator::id_t allocatorId)
303     : C2GraphicAllocation(width, height),
304       mWidth(width),
305       mHeight(height),
306       mFormat(format),
307       mLayerCount(layerCount),
308       mGrallocUsage(grallocUsage),
309       mStride(stride),
310       mHidlHandle(std::move(hidlHandle)),
311       mHandle(handle),
312       mBuffer(nullptr),
313       mLockedHandle(nullptr),
314       mLocked(false),
315       mAllocatorId(allocatorId) {
316 }
317 
~C2AllocationGralloc()318 C2AllocationGralloc::~C2AllocationGralloc() {
319     if (mBuffer && mLocked) {
320         // implementation ignores addresss and rect
321         uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
322         unmap(addr, C2Rect(), nullptr);
323     }
324     if (mBuffer) {
325         status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
326         if (err) {
327             ALOGE("failed transaction: freeBuffer");
328         }
329     }
330     if (mHandle) {
331         native_handle_delete(
332                 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
333     }
334     if (mLockedHandle) {
335         native_handle_delete(
336                 const_cast<native_handle_t *>(
337                         reinterpret_cast<const native_handle_t *>(mLockedHandle)));
338     }
339 }
340 
map(C2Rect c2Rect,C2MemoryUsage usage,C2Fence * fence,C2PlanarLayout * layout,uint8_t ** addr)341 c2_status_t C2AllocationGralloc::map(
342         C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
343         C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
344     const Rect rect{(int32_t)c2Rect.left, (int32_t)c2Rect.top,
345                     (int32_t)(c2Rect.left + c2Rect.width) /* right */,
346                     (int32_t)(c2Rect.top + c2Rect.height) /* bottom */};
347 
348     uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
349     ALOGV("mapping buffer with usage %#llx => %#llx",
350           (long long)usage.expected, (long long)grallocUsage);
351 
352     // TODO
353     (void)fence;
354 
355     std::lock_guard<std::mutex> lock(mMappedLock);
356     if (mBuffer && mLocked) {
357         ALOGD("already mapped");
358         return C2_DUPLICATE;
359     }
360     if (!layout || !addr) {
361         ALOGD("wrong param");
362         return C2_BAD_VALUE;
363     }
364 
365     if (!mBuffer) {
366         status_t err = GraphicBufferMapper::get().importBuffer(
367                             mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
368                             mFormat, mGrallocUsage, mStride, &mBuffer);
369         if (err) {
370             ALOGE("failed transaction: importBuffer");
371             return C2_CORRUPTED;
372         }
373         if (mBuffer == nullptr) {
374             ALOGD("importBuffer returned null buffer");
375             return C2_CORRUPTED;
376         }
377         uint32_t generation = 0;
378         uint64_t igbp_id = 0;
379         uint32_t igbp_slot = 0;
380         if (mHandle) {
381             mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
382         }
383 
384         mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
385                 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
386                 mStride, generation, igbp_id, igbp_slot);
387     }
388     switch (mFormat) {
389         case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
390             // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
391             // Surface. In all other cases it is RGBA. We don't know which case it is here, so
392             // default to YUV for now.
393             void *pointer = nullptr;
394             // TODO: fence
395             status_t err = GraphicBufferMapper::get().lock(
396                     const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
397             if (err) {
398                 ALOGE("failed transaction: lock(RGBA_1010102)");
399                 return C2_CORRUPTED;
400             }
401             // treat as 32-bit values
402             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
403             addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
404             addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
405             addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
406             layout->type = C2PlanarLayout::TYPE_YUVA;
407             layout->numPlanes = 4;
408             layout->rootPlanes = 1;
409             layout->planes[C2PlanarLayout::PLANE_Y] = {
410                 C2PlaneInfo::CHANNEL_Y,         // channel
411                 4,                              // colInc
412                 static_cast<int32_t>(4 * mStride), // rowInc
413                 1,                              // mColSampling
414                 1,                              // mRowSampling
415                 32,                             // allocatedDepth
416                 10,                             // bitDepth
417                 10,                             // rightShift
418                 C2PlaneInfo::LITTLE_END,        // endianness
419                 C2PlanarLayout::PLANE_Y,        // rootIx
420                 0,                              // offset
421             };
422             layout->planes[C2PlanarLayout::PLANE_U] = {
423                 C2PlaneInfo::CHANNEL_CB,         // channel
424                 4,                              // colInc
425                 static_cast<int32_t>(4 * mStride), // rowInc
426                 1,                              // mColSampling
427                 1,                              // mRowSampling
428                 32,                             // allocatedDepth
429                 10,                             // bitDepth
430                 0,                              // rightShift
431                 C2PlaneInfo::LITTLE_END,        // endianness
432                 C2PlanarLayout::PLANE_Y,        // rootIx
433                 0,                              // offset
434             };
435             layout->planes[C2PlanarLayout::PLANE_V] = {
436                 C2PlaneInfo::CHANNEL_CR,         // channel
437                 4,                              // colInc
438                 static_cast<int32_t>(4 * mStride), // rowInc
439                 1,                              // mColSampling
440                 1,                              // mRowSampling
441                 32,                             // allocatedDepth
442                 10,                             // bitDepth
443                 20,                             // rightShift
444                 C2PlaneInfo::LITTLE_END,        // endianness
445                 C2PlanarLayout::PLANE_Y,        // rootIx
446                 0,                              // offset
447             };
448             layout->planes[C2PlanarLayout::PLANE_A] = {
449                 C2PlaneInfo::CHANNEL_A,         // channel
450                 4,                              // colInc
451                 static_cast<int32_t>(4 * mStride), // rowInc
452                 1,                              // mColSampling
453                 1,                              // mRowSampling
454                 32,                             // allocatedDepth
455                 2,                              // bitDepth
456                 30,                             // rightShift
457                 C2PlaneInfo::LITTLE_END,        // endianness
458                 C2PlanarLayout::PLANE_Y,        // rootIx
459                 0,                              // offset
460             };
461             break;
462         }
463 
464         case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
465             // TODO: alpha channel
466             // fall-through
467         case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
468             void *pointer = nullptr;
469             // TODO: fence
470             status_t err = GraphicBufferMapper::get().lock(
471                     const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
472             if (err) {
473                 ALOGE("failed transaction: lock(RGBA_8888)");
474                 return C2_CORRUPTED;
475             }
476             addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
477             addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
478             addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
479             layout->type = C2PlanarLayout::TYPE_RGB;
480             layout->numPlanes = 3;
481             layout->rootPlanes = 1;
482             layout->planes[C2PlanarLayout::PLANE_R] = {
483                 C2PlaneInfo::CHANNEL_R,         // channel
484                 4,                              // colInc
485                 static_cast<int32_t>(4 * mStride), // rowInc
486                 1,                              // mColSampling
487                 1,                              // mRowSampling
488                 8,                              // allocatedDepth
489                 8,                              // bitDepth
490                 0,                              // rightShift
491                 C2PlaneInfo::NATIVE,            // endianness
492                 C2PlanarLayout::PLANE_R,        // rootIx
493                 0,                              // offset
494             };
495             layout->planes[C2PlanarLayout::PLANE_G] = {
496                 C2PlaneInfo::CHANNEL_G,         // channel
497                 4,                              // colInc
498                 static_cast<int32_t>(4 * mStride), // rowInc
499                 1,                              // mColSampling
500                 1,                              // mRowSampling
501                 8,                              // allocatedDepth
502                 8,                              // bitDepth
503                 0,                              // rightShift
504                 C2PlaneInfo::NATIVE,            // endianness
505                 C2PlanarLayout::PLANE_R,        // rootIx
506                 1,                              // offset
507             };
508             layout->planes[C2PlanarLayout::PLANE_B] = {
509                 C2PlaneInfo::CHANNEL_B,         // channel
510                 4,                              // colInc
511                 static_cast<int32_t>(4 * mStride), // rowInc
512                 1,                              // mColSampling
513                 1,                              // mRowSampling
514                 8,                              // allocatedDepth
515                 8,                              // bitDepth
516                 0,                              // rightShift
517                 C2PlaneInfo::NATIVE,            // endianness
518                 C2PlanarLayout::PLANE_R,        // rootIx
519                 2,                              // offset
520             };
521             break;
522         }
523 
524         case static_cast<uint32_t>(PixelFormat4::BLOB): {
525             void *pointer = nullptr;
526             // TODO: fence
527             status_t err = GraphicBufferMapper::get().lock(
528                     const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &pointer);
529             if (err) {
530                 ALOGE("failed transaction: lock(BLOB)");
531                 return C2_CORRUPTED;
532             }
533             *addr = (uint8_t *)pointer;
534             break;
535         }
536 
537         case static_cast<uint32_t>(PixelFormat4::YCBCR_422_SP):
538             // fall-through
539         case static_cast<uint32_t>(PixelFormat4::YCRCB_420_SP):
540             // fall-through
541         case static_cast<uint32_t>(PixelFormat4::YCBCR_422_I):
542             // fall-through
543         case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
544             // fall-through
545         case static_cast<uint32_t>(PixelFormat4::YV12): {
546             android_ycbcr ycbcrLayout;
547 
548             status_t err = GraphicBufferMapper::get().lockYCbCr(
549                     const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
550             if (err) {
551                 ALOGE("failed transaction: lockYCbCr (err=%d)", err);
552                 return C2_CORRUPTED;
553             }
554             if (!ycbcrLayout.y || !ycbcrLayout.cb || !ycbcrLayout.cr
555                     || ycbcrLayout.ystride == 0
556                     || ycbcrLayout.cstride == 0
557                     || ycbcrLayout.chroma_step == 0) {
558                 ALOGE("invalid layout: lockYCbCr (y=%s cb=%s cr=%s "
559                         "ystride=%zu cstride=%zu chroma_step=%zu)",
560                         ycbcrLayout.y ? "(non-null)" : "(null)",
561                         ycbcrLayout.cb ? "(non-null)" : "(null)",
562                         ycbcrLayout.cr ? "(non-null)" : "(null)",
563                         ycbcrLayout.ystride, ycbcrLayout.cstride, ycbcrLayout.chroma_step);
564                 return C2_CORRUPTED;
565             }
566 
567             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
568             addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
569             addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
570             layout->type = C2PlanarLayout::TYPE_YUV;
571             layout->numPlanes = 3;
572             layout->rootPlanes = 3;
573             layout->planes[C2PlanarLayout::PLANE_Y] = {
574                 C2PlaneInfo::CHANNEL_Y,         // channel
575                 1,                              // colInc
576                 (int32_t)ycbcrLayout.ystride,   // rowInc
577                 1,                              // mColSampling
578                 1,                              // mRowSampling
579                 8,                              // allocatedDepth
580                 8,                              // bitDepth
581                 0,                              // rightShift
582                 C2PlaneInfo::NATIVE,            // endianness
583                 C2PlanarLayout::PLANE_Y,        // rootIx
584                 0,                              // offset
585             };
586             layout->planes[C2PlanarLayout::PLANE_U] = {
587                 C2PlaneInfo::CHANNEL_CB,          // channel
588                 (int32_t)ycbcrLayout.chroma_step, // colInc
589                 (int32_t)ycbcrLayout.cstride,     // rowInc
590                 2,                                // mColSampling
591                 2,                                // mRowSampling
592                 8,                                // allocatedDepth
593                 8,                                // bitDepth
594                 0,                                // rightShift
595                 C2PlaneInfo::NATIVE,              // endianness
596                 C2PlanarLayout::PLANE_U,          // rootIx
597                 0,                                // offset
598             };
599             layout->planes[C2PlanarLayout::PLANE_V] = {
600                 C2PlaneInfo::CHANNEL_CR,          // channel
601                 (int32_t)ycbcrLayout.chroma_step, // colInc
602                 (int32_t)ycbcrLayout.cstride,     // rowInc
603                 2,                                // mColSampling
604                 2,                                // mRowSampling
605                 8,                                // allocatedDepth
606                 8,                                // bitDepth
607                 0,                                // rightShift
608                 C2PlaneInfo::NATIVE,              // endianness
609                 C2PlanarLayout::PLANE_V,          // rootIx
610                 0,                                // offset
611             };
612             // handle interleaved formats
613             intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
614             if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
615                 layout->rootPlanes = 2;
616                 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
617                 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
618             } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
619                 layout->rootPlanes = 2;
620                 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
621                 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
622             }
623             break;
624         }
625 
626         case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
627             void *pointer = nullptr;
628             status_t err = GraphicBufferMapper::get().lock(
629                     const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
630             if (err) {
631                 ALOGE("failed transaction: lock(YCBCR_P010)");
632                 return C2_CORRUPTED;
633             }
634             addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
635             addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer + mStride * 2 * rect.height();
636             addr[C2PlanarLayout::PLANE_V] = addr[C2PlanarLayout::PLANE_U] + 2;
637             layout->type = C2PlanarLayout::TYPE_YUV;
638             layout->numPlanes = 3;
639             layout->rootPlanes = 2;
640             layout->planes[C2PlanarLayout::PLANE_Y] = {
641                 C2PlaneInfo::CHANNEL_Y,         // channel
642                 2,                              // colInc
643                 static_cast<int32_t>(2 * mStride), // rowInc
644                 1,                              // mColSampling
645                 1,                              // mRowSampling
646                 16,                             // allocatedDepth
647                 10,                             // bitDepth
648                 6,                              // rightShift
649                 C2PlaneInfo::LITTLE_END,        // endianness
650                 C2PlanarLayout::PLANE_Y,        // rootIx
651                 0,                              // offset
652             };
653             layout->planes[C2PlanarLayout::PLANE_U] = {
654                 C2PlaneInfo::CHANNEL_CB,        // channel
655                 4,                              // colInc
656                 static_cast<int32_t>(2 * mStride), // rowInc
657                 2,                              // mColSampling
658                 2,                              // mRowSampling
659                 16,                             // allocatedDepth
660                 10,                             // bitDepth
661                 6,                              // rightShift
662                 C2PlaneInfo::LITTLE_END,        // endianness
663                 C2PlanarLayout::PLANE_U,        // rootIx
664                 0,                              // offset
665             };
666             layout->planes[C2PlanarLayout::PLANE_V] = {
667                 C2PlaneInfo::CHANNEL_CR,        // channel
668                 4,                              // colInc
669                 static_cast<int32_t>(2 * mStride), // rowInc
670                 2,                              // mColSampling
671                 2,                              // mRowSampling
672                 16,                             // allocatedDepth
673                 10,                             // bitDepth
674                 6,                              // rightShift
675                 C2PlaneInfo::LITTLE_END,        // endianness
676                 C2PlanarLayout::PLANE_U,        // rootIx
677                 2,                              // offset
678             };
679             break;
680         }
681 
682         default: {
683             // We don't know what it is, but let's try to lock it.
684             android_ycbcr ycbcrLayout;
685 
686             status_t err = GraphicBufferMapper::get().lockYCbCr(
687                     const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, &ycbcrLayout);
688             if (err == OK && ycbcrLayout.y && ycbcrLayout.cb && ycbcrLayout.cr
689                     && ycbcrLayout.ystride > 0
690                     && ycbcrLayout.cstride > 0
691                     && ycbcrLayout.chroma_step > 0) {
692                 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
693                 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
694                 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
695                 layout->type = C2PlanarLayout::TYPE_YUV;
696                 layout->numPlanes = 3;
697                 layout->rootPlanes = 3;
698                 layout->planes[C2PlanarLayout::PLANE_Y] = {
699                     C2PlaneInfo::CHANNEL_Y,         // channel
700                     1,                              // colInc
701                     (int32_t)ycbcrLayout.ystride,   // rowInc
702                     1,                              // mColSampling
703                     1,                              // mRowSampling
704                     8,                              // allocatedDepth
705                     8,                              // bitDepth
706                     0,                              // rightShift
707                     C2PlaneInfo::NATIVE,            // endianness
708                     C2PlanarLayout::PLANE_Y,        // rootIx
709                     0,                              // offset
710                 };
711                 layout->planes[C2PlanarLayout::PLANE_U] = {
712                     C2PlaneInfo::CHANNEL_CB,          // channel
713                     (int32_t)ycbcrLayout.chroma_step, // colInc
714                     (int32_t)ycbcrLayout.cstride,     // rowInc
715                     2,                                // mColSampling
716                     2,                                // mRowSampling
717                     8,                                // allocatedDepth
718                     8,                                // bitDepth
719                     0,                                // rightShift
720                     C2PlaneInfo::NATIVE,              // endianness
721                     C2PlanarLayout::PLANE_U,          // rootIx
722                     0,                                // offset
723                 };
724                 layout->planes[C2PlanarLayout::PLANE_V] = {
725                     C2PlaneInfo::CHANNEL_CR,          // channel
726                     (int32_t)ycbcrLayout.chroma_step, // colInc
727                     (int32_t)ycbcrLayout.cstride,     // rowInc
728                     2,                                // mColSampling
729                     2,                                // mRowSampling
730                     8,                                // allocatedDepth
731                     8,                                // bitDepth
732                     0,                                // rightShift
733                     C2PlaneInfo::NATIVE,              // endianness
734                     C2PlanarLayout::PLANE_V,          // rootIx
735                     0,                                // offset
736                 };
737                 // handle interleaved formats
738                 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
739                 if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
740                     layout->rootPlanes = 2;
741                     layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
742                     layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
743                 } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
744                     layout->rootPlanes = 2;
745                     layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
746                     layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
747                 }
748                 break;
749             }
750 
751             // We really don't know what this is; lock the buffer and pass it through ---
752             // the client may know how to interpret it.
753 
754             // unlock previous allocation if it was successful
755             if (err == OK) {
756                 err = GraphicBufferMapper::get().unlock(mBuffer);
757                 if (err) {
758                     ALOGE("failed transaction: unlock");
759                     return C2_CORRUPTED;
760                 }
761             }
762 
763             void *pointer = nullptr;
764             err = GraphicBufferMapper::get().lock(
765                     const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
766             if (err) {
767                 ALOGE("failed transaction: lock(??? %x)", mFormat);
768                 return C2_CORRUPTED;
769             }
770             addr[0] = (uint8_t *)pointer;
771             layout->type = C2PlanarLayout::TYPE_UNKNOWN;
772             layout->numPlanes = 1;
773             layout->rootPlanes = 1;
774             layout->planes[0] = {
775                 // TODO: CHANNEL_UNKNOWN?
776                 C2PlaneInfo::channel_t(0xFF),   // channel
777                 1,                              // colInc
778                 int32_t(mStride),               // rowInc
779                 1,                              // mColSampling
780                 1,                              // mRowSampling
781                 8,                              // allocatedDepth
782                 8,                              // bitDepth
783                 0,                              // rightShift
784                 C2PlaneInfo::NATIVE,            // endianness
785                 0,                              // rootIx
786                 0,                              // offset
787             };
788             break;
789         }
790     }
791     mLocked = true;
792 
793     return C2_OK;
794 }
795 
unmap(uint8_t ** addr,C2Rect rect,C2Fence * fence)796 c2_status_t C2AllocationGralloc::unmap(
797         uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
798     // TODO: check addr and size, use fence
799     (void)addr;
800     (void)rect;
801     (void)fence;
802 
803     std::lock_guard<std::mutex> lock(mMappedLock);
804     // TODO: fence
805     status_t err = GraphicBufferMapper::get().unlock(mBuffer);
806     if (err) {
807         ALOGE("failed transaction: unlock");
808         return C2_CORRUPTED;
809     }
810 
811     mLocked = false;
812     return C2_OK;
813 }
814 
equals(const std::shared_ptr<const C2GraphicAllocation> & other) const815 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
816     return other && other->handle() == handle();
817 }
818 
819 /* ===================================== GRALLOC ALLOCATOR ==================================== */
820 class C2AllocatorGralloc::Impl {
821 public:
822     Impl(id_t id, bool bufferQueue);
823 
getId() const824     id_t getId() const {
825         return mTraits->id;
826     }
827 
getName() const828     C2String getName() const {
829         return mTraits->name;
830     }
831 
getTraits() const832     std::shared_ptr<const C2Allocator::Traits> getTraits() const {
833         return mTraits;
834     }
835 
836     c2_status_t newGraphicAllocation(
837             uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
838             std::shared_ptr<C2GraphicAllocation> *allocation);
839 
840     c2_status_t priorGraphicAllocation(
841             const C2Handle *handle,
842             std::shared_ptr<C2GraphicAllocation> *allocation);
843 
status() const844     c2_status_t status() const { return mInit; }
845 
846 private:
847     std::shared_ptr<C2Allocator::Traits> mTraits;
848     c2_status_t mInit;
849     const bool mBufferQueue;
850 };
851 
_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)852 void _UnwrapNativeCodec2GrallocMetadata(
853         const C2Handle *const handle,
854         uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
855         uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
856     (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
857                                   generation, igbp_id, igbp_slot);
858 }
859 
Impl(id_t id,bool bufferQueue)860 C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
861     : mInit(C2_OK), mBufferQueue(bufferQueue) {
862     // TODO: get this from allocator
863     C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
864     Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
865     mTraits = std::make_shared<C2Allocator::Traits>(traits);
866 }
867 
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,const C2MemoryUsage & usage,std::shared_ptr<C2GraphicAllocation> * allocation)868 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
869         uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
870         std::shared_ptr<C2GraphicAllocation> *allocation) {
871     uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
872     ALOGV("allocating buffer with usage %#llx => %#llx",
873           (long long)usage.expected, (long long)grallocUsage);
874 
875     buffer_handle_t buffer;
876 
877     uint32_t stride = 0;
878 
879     status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
880             1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
881     if (err) {
882         ALOGE("failed transaction: allocate");
883         return C2_CORRUPTED;
884     }
885 
886     hidl_handle hidlHandle;
887     hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
888 
889     allocation->reset(new C2AllocationGralloc(
890             width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
891             C2HandleGralloc::WrapAndMoveNativeHandle(
892                     hidlHandle, width, height,
893                     format, grallocUsage, stride,
894                     0, 0, mBufferQueue ? ~0 : 0),
895             mTraits->id));
896     return C2_OK;
897 }
898 
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)899 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
900         const C2Handle *handle,
901         std::shared_ptr<C2GraphicAllocation> *allocation) {
902 
903     uint32_t generation;
904     uint64_t igbp_id;
905     uint32_t igbp_slot;
906 
907     uint32_t width;
908     uint32_t height;
909     uint32_t format;
910     uint32_t layerCount = 1;
911     uint64_t grallocUsage;
912     uint32_t stride;
913 
914     const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
915             handle, &width, &height, &format, &grallocUsage, &stride,
916             &generation, &igbp_id, &igbp_slot);
917     if (grallocHandle == nullptr) {
918         return C2_BAD_VALUE;
919     }
920 
921     hidl_handle hidlHandle;
922     hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
923 
924     allocation->reset(new C2AllocationGralloc(
925             width, height, format, layerCount,
926             grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
927     return C2_OK;
928 }
929 
C2AllocatorGralloc(id_t id,bool bufferQueue)930 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
931         : mImpl(new Impl(id, bufferQueue)) {}
932 
~C2AllocatorGralloc()933 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
934 
getId() const935 C2Allocator::id_t C2AllocatorGralloc::getId() const {
936     return mImpl->getId();
937 }
938 
getName() const939 C2String C2AllocatorGralloc::getName() const {
940     return mImpl->getName();
941 }
942 
getTraits() const943 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
944     return mImpl->getTraits();
945 }
946 
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicAllocation> * allocation)947 c2_status_t C2AllocatorGralloc::newGraphicAllocation(
948         uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
949         std::shared_ptr<C2GraphicAllocation> *allocation) {
950     return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
951 }
952 
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)953 c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
954         const C2Handle *handle,
955         std::shared_ptr<C2GraphicAllocation> *allocation) {
956     return mImpl->priorGraphicAllocation(handle, allocation);
957 }
958 
status() const959 c2_status_t C2AllocatorGralloc::status() const {
960     return mImpl->status();
961 }
962 
963 // static
CheckHandle(const C2Handle * const o)964 bool C2AllocatorGralloc::CheckHandle(const C2Handle* const o) {
965     return C2HandleGralloc::IsValid(o);
966 }
967 
968 } // namespace android
969