blob: 22e8d8476c8ff2ee3e9eadc313068efdec2392b9 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
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
30namespace android {
31
32namespace {
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
45C2MemoryUsage 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
54uint64_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
62using ::android::hardware::graphics::allocator::V2_0::IAllocator;
63using ::android::hardware::graphics::common::V1_0::BufferUsage;
64using ::android::hardware::graphics::common::V1_0::PixelFormat;
65using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
66using ::android::hardware::graphics::mapper::V2_0::Error;
67using ::android::hardware::graphics::mapper::V2_0::IMapper;
68using ::android::hardware::graphics::mapper::V2_0::YCbCrLayout;
69using ::android::hardware::hidl_handle;
70using ::android::hardware::hidl_vec;
71
72namespace {
73
74struct BufferDescriptorInfo {
75 IMapper::BufferDescriptorInfo mapperInfo;
76 uint32_t stride;
77};
78
79}
80
81/* ===================================== GRALLOC ALLOCATION ==================================== */
82static 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
94static
95bool 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
108class C2HandleGralloc : public C2Handle {
109private:
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
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
141 ExtraData *getExtraData(C2Handle *const handle) {
142 return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle)));
143 }
144
145public:
146 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
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
162 static C2HandleGralloc* WrapNativeHandle(
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
184 static native_handle_t* UnwrapNativeHandle(
185 const C2Handle *const handle) {
186 const ExtraData *xd = getExtraData(handle);
187 if (xd == nullptr || xd->magic != MAGIC) {
188 return nullptr;
189 }
190 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
191 if (res != nullptr) {
192 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
193 }
194 return res;
195 }
196
197 static native_handle_t* UnwrapNativeHandle(
198 const C2Handle *const handle,
199 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
200 const ExtraData *xd = getExtraData(handle);
201 if (xd == nullptr || xd->magic != MAGIC) {
202 return nullptr;
203 }
204 *generation = xd->generation;
205 *igbp_id = unsigned(xd->igbp_id_lo) | uint64_t(unsigned(xd->igbp_id_hi)) << 32;
206 *igbp_slot = xd->igbp_slot;
207 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
208 if (res != nullptr) {
209 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
210 }
211 return res;
212 }
213
214 static const C2HandleGralloc* Import(
215 const C2Handle *const handle,
216 uint32_t *width, uint32_t *height, uint32_t *format,
217 uint64_t *usage, uint32_t *stride,
218 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
219 const ExtraData *xd = getExtraData(handle);
220 if (xd == nullptr) {
221 return nullptr;
222 }
223 *width = xd->width;
224 *height = xd->height;
225 *format = xd->format;
226 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
227 *stride = xd->stride;
228 *generation = xd->generation;
229 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
230 *igbp_slot = xd->igbp_slot;
231 return reinterpret_cast<const C2HandleGralloc *>(handle);
232 }
233};
234
235native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
236 return C2HandleGralloc::UnwrapNativeHandle(handle);
237}
238
239native_handle_t *UnwrapNativeCodec2GrallocHandle(
240 const C2Handle *const handle,
241 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
242 return C2HandleGralloc::UnwrapNativeHandle(handle, generation, igbp_id, igbp_slot);
243}
244
245C2Handle *WrapNativeCodec2GrallocHandle(
246 const native_handle_t *const handle,
247 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
248 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
249 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
250 generation, igbp_id, igbp_slot);
251}
252
253class C2AllocationGralloc : public C2GraphicAllocation {
254public:
255 virtual ~C2AllocationGralloc() override;
256
257 virtual c2_status_t map(
258 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
259 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
260 virtual c2_status_t unmap(
261 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
262 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
263 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
264 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
265
266 // internal methods
267 // |handle| will be moved.
268 C2AllocationGralloc(
269 const BufferDescriptorInfo &info,
270 const sp<IMapper> &mapper,
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
277private:
278 const BufferDescriptorInfo mInfo;
279 const sp<IMapper> mMapper;
280 const hidl_handle mHidlHandle;
281 const C2HandleGralloc *mHandle;
282 buffer_handle_t mBuffer;
283 const C2HandleGralloc *mLockedHandle;
284 bool mLocked;
285 C2Allocator::id_t mAllocatorId;
286 std::mutex mMappedLock;
287};
288
289C2AllocationGralloc::C2AllocationGralloc(
290 const BufferDescriptorInfo &info,
291 const sp<IMapper> &mapper,
292 hidl_handle &hidlHandle,
293 const C2HandleGralloc *const handle,
294 C2Allocator::id_t allocatorId)
295 : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
296 mInfo(info),
297 mMapper(mapper),
298 mHidlHandle(std::move(hidlHandle)),
299 mHandle(handle),
300 mBuffer(nullptr),
301 mLockedHandle(nullptr),
302 mLocked(false),
303 mAllocatorId(allocatorId) {
304}
305
306C2AllocationGralloc::~C2AllocationGralloc() {
307 if (!mBuffer) {
308 return;
309 }
310 if (mLocked) {
311 // implementation ignores addresss and rect
312 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
313 unmap(addr, C2Rect(), nullptr);
314 }
315 mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
316 native_handle_delete(const_cast<native_handle_t*>(
317 reinterpret_cast<const native_handle_t*>(mHandle)));
318}
319
320c2_status_t C2AllocationGralloc::map(
321 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
322 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
323 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
324 ALOGV("mapping buffer with usage %#llx => %#llx",
325 (long long)usage.expected, (long long)grallocUsage);
326
327 // TODO
328 (void) fence;
329
330 std::lock_guard<std::mutex> lock(mMappedLock);
331 if (mBuffer && mLocked) {
332 ALOGD("already mapped");
333 return C2_DUPLICATE;
334 }
335 if (!layout || !addr) {
336 ALOGD("wrong param");
337 return C2_BAD_VALUE;
338 }
339
340 c2_status_t err = C2_OK;
341 if (!mBuffer) {
342 mMapper->importBuffer(
343 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
344 err = maperr2error(maperr);
345 if (err == C2_OK) {
346 mBuffer = static_cast<buffer_handle_t>(buffer);
347 }
348 });
349 if (err != C2_OK) {
350 ALOGD("importBuffer failed: %d", err);
351 return err;
352 }
353 if (mBuffer == nullptr) {
354 ALOGD("importBuffer returned null buffer");
355 return C2_CORRUPTED;
356 }
357 uint32_t generation = 0;
358 uint64_t igbp_id = 0;
359 uint32_t igbp_slot = 0;
360 if (mHandle) {
361 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
362 }
363 mLockedHandle = C2HandleGralloc::WrapNativeHandle(
364 mBuffer, mInfo.mapperInfo.width, mInfo.mapperInfo.height,
365 (uint32_t)mInfo.mapperInfo.format, mInfo.mapperInfo.usage, mInfo.stride,
366 generation, igbp_id, igbp_slot);
367 }
368
369 // UGLY HACK: assume YCbCr 4:2:0 8-bit format (and lockable via lockYCbCr) if we don't
370 // recognize the format
371 PixelFormat format = mInfo.mapperInfo.format;
372 if (format != PixelFormat::RGBA_8888 && format != PixelFormat::RGBX_8888) {
373 format = PixelFormat::YCBCR_420_888;
374 }
375
376 switch (format) {
377 case PixelFormat::YCBCR_420_888:
378 case PixelFormat::YV12: {
379 YCbCrLayout ycbcrLayout;
380 mMapper->lockYCbCr(
381 const_cast<native_handle_t *>(mBuffer), grallocUsage,
382 { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
383 // TODO: fence
384 hidl_handle(),
385 [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
386 err = maperr2error(maperr);
387 if (err == C2_OK) {
388 ycbcrLayout = mapLayout;
389 }
390 });
391 if (err != C2_OK) {
392 ALOGD("lockYCbCr failed: %d", err);
393 return err;
394 }
395 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
396 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
397 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
398 layout->type = C2PlanarLayout::TYPE_YUV;
399 layout->numPlanes = 3;
400 layout->rootPlanes = 3;
401 layout->planes[C2PlanarLayout::PLANE_Y] = {
402 C2PlaneInfo::CHANNEL_Y, // channel
403 1, // colInc
404 (int32_t)ycbcrLayout.yStride, // rowInc
405 1, // mColSampling
406 1, // mRowSampling
407 8, // allocatedDepth
408 8, // bitDepth
409 0, // rightShift
410 C2PlaneInfo::NATIVE, // endianness
411 C2PlanarLayout::PLANE_Y, // rootIx
412 0, // offset
413 };
414 layout->planes[C2PlanarLayout::PLANE_U] = {
415 C2PlaneInfo::CHANNEL_CB, // channel
416 (int32_t)ycbcrLayout.chromaStep, // colInc
417 (int32_t)ycbcrLayout.cStride, // rowInc
418 2, // mColSampling
419 2, // mRowSampling
420 8, // allocatedDepth
421 8, // bitDepth
422 0, // rightShift
423 C2PlaneInfo::NATIVE, // endianness
424 C2PlanarLayout::PLANE_U, // rootIx
425 0, // offset
426 };
427 layout->planes[C2PlanarLayout::PLANE_V] = {
428 C2PlaneInfo::CHANNEL_CR, // channel
429 (int32_t)ycbcrLayout.chromaStep, // colInc
430 (int32_t)ycbcrLayout.cStride, // rowInc
431 2, // mColSampling
432 2, // mRowSampling
433 8, // allocatedDepth
434 8, // bitDepth
435 0, // rightShift
436 C2PlaneInfo::NATIVE, // endianness
437 C2PlanarLayout::PLANE_V, // rootIx
438 0, // offset
439 };
440 // handle interleaved formats
441 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
442 if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
443 layout->rootPlanes = 2;
444 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
445 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
446 } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
447 layout->rootPlanes = 2;
448 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
449 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
450 }
451 break;
452 }
453
454 case PixelFormat::RGBA_8888:
455 // TODO: alpha channel
456 // fall-through
457 case PixelFormat::RGBX_8888: {
458 void *pointer = nullptr;
459 mMapper->lock(
460 const_cast<native_handle_t *>(mBuffer),
461 grallocUsage,
462 { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
463 // TODO: fence
464 hidl_handle(),
465 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
466 err = maperr2error(maperr);
467 if (err == C2_OK) {
468 pointer = mapPointer;
469 }
470 });
471 if (err != C2_OK) {
472 ALOGD("lock failed: %d", err);
473 return err;
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 4 * (int32_t)mInfo.stride, // 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 4 * (int32_t)mInfo.stride, // 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 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 2, // offset
519 };
520 break;
521 }
522 default: {
523 ALOGD("unsupported pixel format: %d", mInfo.mapperInfo.format);
524 return C2_OMITTED;
525 }
526 }
527 mLocked = true;
528
529 return C2_OK;
530}
531
532c2_status_t C2AllocationGralloc::unmap(
533 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
534 // TODO: check addr and size, use fence
535 (void)addr;
536 (void)rect;
537
538 std::lock_guard<std::mutex> lock(mMappedLock);
539 c2_status_t err = C2_OK;
540 mMapper->unlock(
541 const_cast<native_handle_t *>(mBuffer),
542 [&err, &fence](const auto &maperr, const auto &releaseFence) {
543 // TODO
544 (void) fence;
545 (void) releaseFence;
546 err = maperr2error(maperr);
547 if (err == C2_OK) {
548 // TODO: fence
549 }
550 });
551 if (err == C2_OK) {
552 mLocked = false;
553 }
554 return err;
555}
556
557bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
558 return other && other->handle() == handle();
559}
560
561/* ===================================== GRALLOC ALLOCATOR ==================================== */
562class C2AllocatorGralloc::Impl {
563public:
564 Impl(id_t id, bool bufferQueue);
565
566 id_t getId() const {
567 return mTraits->id;
568 }
569
570 C2String getName() const {
571 return mTraits->name;
572 }
573
574 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
575 return mTraits;
576 }
577
578 c2_status_t newGraphicAllocation(
579 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
580 std::shared_ptr<C2GraphicAllocation> *allocation);
581
582 c2_status_t priorGraphicAllocation(
583 const C2Handle *handle,
584 std::shared_ptr<C2GraphicAllocation> *allocation);
585
586 c2_status_t status() const { return mInit; }
587
588private:
589 std::shared_ptr<C2Allocator::Traits> mTraits;
590 c2_status_t mInit;
591 sp<IAllocator> mAllocator;
592 sp<IMapper> mMapper;
593 const bool mBufferQueue;
594};
595
596void _UnwrapNativeCodec2GrallocMetadata(
597 const C2Handle *const handle,
598 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
599 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
600 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
601 generation, igbp_id, igbp_slot);
602}
603
604C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
605 : mInit(C2_OK), mBufferQueue(bufferQueue) {
606 // TODO: get this from allocator
607 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
608 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
609 mTraits = std::make_shared<C2Allocator::Traits>(traits);
610
611 // gralloc allocator is a singleton, so all objects share a global service
612 mAllocator = IAllocator::getService();
613 mMapper = IMapper::getService();
614 if (mAllocator == nullptr || mMapper == nullptr) {
615 mInit = C2_CORRUPTED;
616 }
617}
618
619c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
620 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
621 std::shared_ptr<C2GraphicAllocation> *allocation) {
622 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
623 ALOGV("allocating buffer with usage %#llx => %#llx",
624 (long long)usage.expected, (long long)grallocUsage);
625
626 BufferDescriptorInfo info = {
627 {
628 width,
629 height,
630 1u, // layerCount
631 (PixelFormat)format,
632 grallocUsage,
633 },
634 0u, // stride placeholder
635 };
636 c2_status_t err = C2_OK;
637 BufferDescriptor desc;
638 mMapper->createDescriptor(
639 info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
640 err = maperr2error(maperr);
641 if (err == C2_OK) {
642 desc = descriptor;
643 }
644 });
645 if (err != C2_OK) {
646 return err;
647 }
648
649 // IAllocator shares IMapper error codes.
650 hidl_handle buffer;
651 mAllocator->allocate(
652 desc,
653 1u,
654 [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
655 err = maperr2error(maperr);
656 if (err != C2_OK) {
657 return;
658 }
659 if (buffers.size() != 1u) {
660 err = C2_CORRUPTED;
661 return;
662 }
663 info.stride = stride;
664 buffer = std::move(buffers[0]);
665 });
666 if (err != C2_OK) {
667 return err;
668 }
669
670
671 allocation->reset(new C2AllocationGralloc(
672 info, mMapper, buffer,
673 C2HandleGralloc::WrapNativeHandle(
674 buffer.getNativeHandle(),
675 info.mapperInfo.width, info.mapperInfo.height,
676 (uint32_t)info.mapperInfo.format, info.mapperInfo.usage, info.stride,
677 0, 0, mBufferQueue ? ~0 : 0),
678 mTraits->id));
679 return C2_OK;
680}
681
682c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
683 const C2Handle *handle,
684 std::shared_ptr<C2GraphicAllocation> *allocation) {
685 BufferDescriptorInfo info;
686 info.mapperInfo.layerCount = 1u;
687 uint32_t generation;
688 uint64_t igbp_id;
689 uint32_t igbp_slot;
690 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
691 handle,
692 &info.mapperInfo.width, &info.mapperInfo.height,
693 (uint32_t *)&info.mapperInfo.format, (uint64_t *)&info.mapperInfo.usage, &info.stride,
694 &generation, &igbp_id, &igbp_slot);
695 if (grallocHandle == nullptr) {
696 return C2_BAD_VALUE;
697 }
698
699 hidl_handle hidlHandle;
700 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
701
702 allocation->reset(new C2AllocationGralloc(info, mMapper, hidlHandle, grallocHandle, mTraits->id));
703 return C2_OK;
704}
705
706C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
707 : mImpl(new Impl(id, bufferQueue)) {}
708
709C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
710
711C2Allocator::id_t C2AllocatorGralloc::getId() const {
712 return mImpl->getId();
713}
714
715C2String C2AllocatorGralloc::getName() const {
716 return mImpl->getName();
717}
718
719std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
720 return mImpl->getTraits();
721}
722
723c2_status_t C2AllocatorGralloc::newGraphicAllocation(
724 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
725 std::shared_ptr<C2GraphicAllocation> *allocation) {
726 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
727}
728
729c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
730 const C2Handle *handle,
731 std::shared_ptr<C2GraphicAllocation> *allocation) {
732 return mImpl->priorGraphicAllocation(handle, allocation);
733}
734
735c2_status_t C2AllocatorGralloc::status() const {
736 return mImpl->status();
737}
738
739bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
740 return C2HandleGralloc::isValid(o);
741}
742
743} // namespace android