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