blob: 286c48ae74ab29eccc6a0afa017b21bd1ff2131a [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
Sungtak Leea4d13be2019-01-23 15:24:46 -0800162 static C2HandleGralloc* WrapAndMoveNativeHandle(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800163 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
Sungtak Leea4d13be2019-01-23 15:24:46 -0800184 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
Sungtak Lee08515812019-06-05 11:16:32 -0700204 static bool MigrateNativeHandle(
205 native_handle_t *handle,
206 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
207 if (handle == nullptr || !isValid(handle)) {
208 return false;
209 }
210 ExtraData *ed = getExtraData(handle);
211 if (!ed) return false;
212 ed->generation = generation;
213 ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
214 ed->igbp_id_hi = uint32_t(igbp_id >> 32);
215 ed->igbp_slot = igbp_slot;
216 return true;
217 }
218
219
Pawin Vongmasa36653902018-11-15 00:10:25 -0800220 static native_handle_t* UnwrapNativeHandle(
221 const C2Handle *const handle) {
222 const ExtraData *xd = getExtraData(handle);
223 if (xd == nullptr || xd->magic != MAGIC) {
224 return nullptr;
225 }
226 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
227 if (res != nullptr) {
228 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
229 }
230 return res;
231 }
232
233 static native_handle_t* UnwrapNativeHandle(
234 const C2Handle *const handle,
235 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
236 const ExtraData *xd = getExtraData(handle);
237 if (xd == nullptr || xd->magic != MAGIC) {
238 return nullptr;
239 }
240 *generation = xd->generation;
241 *igbp_id = unsigned(xd->igbp_id_lo) | uint64_t(unsigned(xd->igbp_id_hi)) << 32;
242 *igbp_slot = xd->igbp_slot;
243 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
244 if (res != nullptr) {
245 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
246 }
247 return res;
248 }
249
250 static const C2HandleGralloc* Import(
251 const C2Handle *const handle,
252 uint32_t *width, uint32_t *height, uint32_t *format,
253 uint64_t *usage, uint32_t *stride,
254 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
255 const ExtraData *xd = getExtraData(handle);
256 if (xd == nullptr) {
257 return nullptr;
258 }
259 *width = xd->width;
260 *height = xd->height;
261 *format = xd->format;
262 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
263 *stride = xd->stride;
264 *generation = xd->generation;
265 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
266 *igbp_slot = xd->igbp_slot;
267 return reinterpret_cast<const C2HandleGralloc *>(handle);
268 }
269};
270
271native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
272 return C2HandleGralloc::UnwrapNativeHandle(handle);
273}
274
275native_handle_t *UnwrapNativeCodec2GrallocHandle(
276 const C2Handle *const handle,
277 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
278 return C2HandleGralloc::UnwrapNativeHandle(handle, generation, igbp_id, igbp_slot);
279}
280
281C2Handle *WrapNativeCodec2GrallocHandle(
282 const native_handle_t *const handle,
283 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
284 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
285 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
286 generation, igbp_id, igbp_slot);
287}
288
Sungtak Lee08515812019-06-05 11:16:32 -0700289bool MigrateNativeCodec2GrallocHandle(
290 native_handle_t *handle,
291 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
292 return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
293}
294
295
Pawin Vongmasa36653902018-11-15 00:10:25 -0800296class C2AllocationGralloc : public C2GraphicAllocation {
297public:
298 virtual ~C2AllocationGralloc() override;
299
300 virtual c2_status_t map(
301 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
302 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
303 virtual c2_status_t unmap(
304 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
305 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
306 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
307 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
308
309 // internal methods
310 // |handle| will be moved.
311 C2AllocationGralloc(
312 const BufferDescriptorInfo &info,
313 const sp<IMapper> &mapper,
314 hidl_handle &hidlHandle,
315 const C2HandleGralloc *const handle,
316 C2Allocator::id_t allocatorId);
317 int dup() const;
318 c2_status_t status() const;
319
320private:
321 const BufferDescriptorInfo mInfo;
322 const sp<IMapper> mMapper;
323 const hidl_handle mHidlHandle;
324 const C2HandleGralloc *mHandle;
325 buffer_handle_t mBuffer;
326 const C2HandleGralloc *mLockedHandle;
327 bool mLocked;
328 C2Allocator::id_t mAllocatorId;
329 std::mutex mMappedLock;
330};
331
332C2AllocationGralloc::C2AllocationGralloc(
333 const BufferDescriptorInfo &info,
334 const sp<IMapper> &mapper,
335 hidl_handle &hidlHandle,
336 const C2HandleGralloc *const handle,
337 C2Allocator::id_t allocatorId)
338 : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
339 mInfo(info),
340 mMapper(mapper),
341 mHidlHandle(std::move(hidlHandle)),
342 mHandle(handle),
343 mBuffer(nullptr),
344 mLockedHandle(nullptr),
345 mLocked(false),
346 mAllocatorId(allocatorId) {
347}
348
349C2AllocationGralloc::~C2AllocationGralloc() {
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800350 if (mBuffer && mLocked) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800351 // implementation ignores addresss and rect
352 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
353 unmap(addr, C2Rect(), nullptr);
354 }
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800355 if (mBuffer) {
356 mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer));
357 }
358 if (mHandle) {
359 native_handle_delete(
360 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
361 }
Sungtak Lee2729dcf2019-01-18 13:15:07 -0800362 if (mLockedHandle) {
363 native_handle_delete(
364 const_cast<native_handle_t *>(
365 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
366 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800367}
368
369c2_status_t C2AllocationGralloc::map(
370 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
371 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
372 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
373 ALOGV("mapping buffer with usage %#llx => %#llx",
374 (long long)usage.expected, (long long)grallocUsage);
375
376 // TODO
377 (void) fence;
378
379 std::lock_guard<std::mutex> lock(mMappedLock);
380 if (mBuffer && mLocked) {
381 ALOGD("already mapped");
382 return C2_DUPLICATE;
383 }
384 if (!layout || !addr) {
385 ALOGD("wrong param");
386 return C2_BAD_VALUE;
387 }
388
389 c2_status_t err = C2_OK;
390 if (!mBuffer) {
391 mMapper->importBuffer(
392 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
393 err = maperr2error(maperr);
394 if (err == C2_OK) {
395 mBuffer = static_cast<buffer_handle_t>(buffer);
396 }
397 });
398 if (err != C2_OK) {
399 ALOGD("importBuffer failed: %d", err);
400 return err;
401 }
402 if (mBuffer == nullptr) {
403 ALOGD("importBuffer returned null buffer");
404 return C2_CORRUPTED;
405 }
406 uint32_t generation = 0;
407 uint64_t igbp_id = 0;
408 uint32_t igbp_slot = 0;
409 if (mHandle) {
410 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
411 }
Sungtak Leea4d13be2019-01-23 15:24:46 -0800412 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800413 mBuffer, mInfo.mapperInfo.width, mInfo.mapperInfo.height,
414 (uint32_t)mInfo.mapperInfo.format, mInfo.mapperInfo.usage, mInfo.stride,
415 generation, igbp_id, igbp_slot);
416 }
417
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700418 switch (mInfo.mapperInfo.format) {
419 case PixelFormat::RGBA_1010102: {
420 // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
421 // Surface. In all other cases it is RGBA. We don't know which case it is here, so
422 // default to YUV for now.
423 void *pointer = nullptr;
424 mMapper->lock(
425 const_cast<native_handle_t *>(mBuffer),
426 grallocUsage,
427 { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
428 // TODO: fence
429 hidl_handle(),
430 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
431 err = maperr2error(maperr);
432 if (err == C2_OK) {
433 pointer = mapPointer;
434 }
435 });
436 if (err != C2_OK) {
437 ALOGD("lock failed: %d", err);
438 return err;
439 }
440 // treat as 32-bit values
441 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
442 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
443 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
444 addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
445 layout->type = C2PlanarLayout::TYPE_YUVA;
446 layout->numPlanes = 4;
447 layout->rootPlanes = 1;
448 layout->planes[C2PlanarLayout::PLANE_Y] = {
449 C2PlaneInfo::CHANNEL_Y, // channel
450 4, // colInc
451 4 * (int32_t)mInfo.stride, // rowInc
452 1, // mColSampling
453 1, // mRowSampling
454 32, // allocatedDepth
455 10, // bitDepth
456 10, // rightShift
457 C2PlaneInfo::LITTLE_END, // endianness
458 C2PlanarLayout::PLANE_Y, // rootIx
459 0, // offset
460 };
461 layout->planes[C2PlanarLayout::PLANE_U] = {
462 C2PlaneInfo::CHANNEL_CB, // channel
463 4, // colInc
464 4 * (int32_t)mInfo.stride, // rowInc
465 1, // mColSampling
466 1, // mRowSampling
467 32, // allocatedDepth
468 10, // bitDepth
469 0, // rightShift
470 C2PlaneInfo::LITTLE_END, // endianness
471 C2PlanarLayout::PLANE_Y, // rootIx
472 0, // offset
473 };
474 layout->planes[C2PlanarLayout::PLANE_V] = {
475 C2PlaneInfo::CHANNEL_CR, // channel
476 4, // colInc
477 4 * (int32_t)mInfo.stride, // rowInc
478 1, // mColSampling
479 1, // mRowSampling
480 32, // allocatedDepth
481 10, // bitDepth
482 20, // rightShift
483 C2PlaneInfo::LITTLE_END, // endianness
484 C2PlanarLayout::PLANE_Y, // rootIx
485 0, // offset
486 };
487 layout->planes[C2PlanarLayout::PLANE_A] = {
488 C2PlaneInfo::CHANNEL_A, // channel
489 4, // colInc
490 4 * (int32_t)mInfo.stride, // rowInc
491 1, // mColSampling
492 1, // mRowSampling
493 32, // allocatedDepth
494 2, // bitDepth
495 30, // rightShift
496 C2PlaneInfo::LITTLE_END, // endianness
497 C2PlanarLayout::PLANE_Y, // rootIx
498 0, // offset
499 };
500 break;
501 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800502
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700503 case PixelFormat::RGBA_8888:
504 // TODO: alpha channel
505 // fall-through
506 case PixelFormat::RGBX_8888: {
507 void *pointer = nullptr;
508 mMapper->lock(
509 const_cast<native_handle_t *>(mBuffer),
510 grallocUsage,
511 { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
512 // TODO: fence
513 hidl_handle(),
514 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
515 err = maperr2error(maperr);
516 if (err == C2_OK) {
517 pointer = mapPointer;
518 }
519 });
520 if (err != C2_OK) {
521 ALOGD("lock failed: %d", err);
522 return err;
523 }
524 addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
525 addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
526 addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
527 layout->type = C2PlanarLayout::TYPE_RGB;
528 layout->numPlanes = 3;
529 layout->rootPlanes = 1;
530 layout->planes[C2PlanarLayout::PLANE_R] = {
531 C2PlaneInfo::CHANNEL_R, // channel
532 4, // colInc
533 4 * (int32_t)mInfo.stride, // rowInc
534 1, // mColSampling
535 1, // mRowSampling
536 8, // allocatedDepth
537 8, // bitDepth
538 0, // rightShift
539 C2PlaneInfo::NATIVE, // endianness
540 C2PlanarLayout::PLANE_R, // rootIx
541 0, // offset
542 };
543 layout->planes[C2PlanarLayout::PLANE_G] = {
544 C2PlaneInfo::CHANNEL_G, // channel
545 4, // colInc
546 4 * (int32_t)mInfo.stride, // rowInc
547 1, // mColSampling
548 1, // mRowSampling
549 8, // allocatedDepth
550 8, // bitDepth
551 0, // rightShift
552 C2PlaneInfo::NATIVE, // endianness
553 C2PlanarLayout::PLANE_R, // rootIx
554 1, // offset
555 };
556 layout->planes[C2PlanarLayout::PLANE_B] = {
557 C2PlaneInfo::CHANNEL_B, // channel
558 4, // colInc
559 4 * (int32_t)mInfo.stride, // rowInc
560 1, // mColSampling
561 1, // mRowSampling
562 8, // allocatedDepth
563 8, // bitDepth
564 0, // rightShift
565 C2PlaneInfo::NATIVE, // endianness
566 C2PlanarLayout::PLANE_R, // rootIx
567 2, // offset
568 };
569 break;
570 }
571
Pawin Vongmasa36653902018-11-15 00:10:25 -0800572 case PixelFormat::YCBCR_420_888:
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700573 // fall-through
574 case PixelFormat::YV12:
575 // fall-through
576 default: {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800577 YCbCrLayout ycbcrLayout;
578 mMapper->lockYCbCr(
579 const_cast<native_handle_t *>(mBuffer), grallocUsage,
580 { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height },
581 // TODO: fence
582 hidl_handle(),
583 [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
584 err = maperr2error(maperr);
585 if (err == C2_OK) {
586 ycbcrLayout = mapLayout;
587 }
588 });
589 if (err != C2_OK) {
590 ALOGD("lockYCbCr failed: %d", err);
591 return err;
592 }
593 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
594 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
595 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
596 layout->type = C2PlanarLayout::TYPE_YUV;
597 layout->numPlanes = 3;
598 layout->rootPlanes = 3;
599 layout->planes[C2PlanarLayout::PLANE_Y] = {
600 C2PlaneInfo::CHANNEL_Y, // channel
601 1, // colInc
602 (int32_t)ycbcrLayout.yStride, // rowInc
603 1, // mColSampling
604 1, // mRowSampling
605 8, // allocatedDepth
606 8, // bitDepth
607 0, // rightShift
608 C2PlaneInfo::NATIVE, // endianness
609 C2PlanarLayout::PLANE_Y, // rootIx
610 0, // offset
611 };
612 layout->planes[C2PlanarLayout::PLANE_U] = {
613 C2PlaneInfo::CHANNEL_CB, // channel
614 (int32_t)ycbcrLayout.chromaStep, // colInc
615 (int32_t)ycbcrLayout.cStride, // rowInc
616 2, // mColSampling
617 2, // mRowSampling
618 8, // allocatedDepth
619 8, // bitDepth
620 0, // rightShift
621 C2PlaneInfo::NATIVE, // endianness
622 C2PlanarLayout::PLANE_U, // rootIx
623 0, // offset
624 };
625 layout->planes[C2PlanarLayout::PLANE_V] = {
626 C2PlaneInfo::CHANNEL_CR, // channel
627 (int32_t)ycbcrLayout.chromaStep, // colInc
628 (int32_t)ycbcrLayout.cStride, // rowInc
629 2, // mColSampling
630 2, // mRowSampling
631 8, // allocatedDepth
632 8, // bitDepth
633 0, // rightShift
634 C2PlaneInfo::NATIVE, // endianness
635 C2PlanarLayout::PLANE_V, // rootIx
636 0, // offset
637 };
638 // handle interleaved formats
639 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
640 if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
641 layout->rootPlanes = 2;
642 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
643 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
644 } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
645 layout->rootPlanes = 2;
646 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
647 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
648 }
649 break;
650 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800651 }
652 mLocked = true;
653
654 return C2_OK;
655}
656
657c2_status_t C2AllocationGralloc::unmap(
658 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
659 // TODO: check addr and size, use fence
660 (void)addr;
661 (void)rect;
662
663 std::lock_guard<std::mutex> lock(mMappedLock);
664 c2_status_t err = C2_OK;
665 mMapper->unlock(
666 const_cast<native_handle_t *>(mBuffer),
667 [&err, &fence](const auto &maperr, const auto &releaseFence) {
668 // TODO
669 (void) fence;
670 (void) releaseFence;
671 err = maperr2error(maperr);
672 if (err == C2_OK) {
673 // TODO: fence
674 }
675 });
676 if (err == C2_OK) {
677 mLocked = false;
678 }
679 return err;
680}
681
682bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
683 return other && other->handle() == handle();
684}
685
686/* ===================================== GRALLOC ALLOCATOR ==================================== */
687class C2AllocatorGralloc::Impl {
688public:
689 Impl(id_t id, bool bufferQueue);
690
691 id_t getId() const {
692 return mTraits->id;
693 }
694
695 C2String getName() const {
696 return mTraits->name;
697 }
698
699 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
700 return mTraits;
701 }
702
703 c2_status_t newGraphicAllocation(
704 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
705 std::shared_ptr<C2GraphicAllocation> *allocation);
706
707 c2_status_t priorGraphicAllocation(
708 const C2Handle *handle,
709 std::shared_ptr<C2GraphicAllocation> *allocation);
710
711 c2_status_t status() const { return mInit; }
712
713private:
714 std::shared_ptr<C2Allocator::Traits> mTraits;
715 c2_status_t mInit;
716 sp<IAllocator> mAllocator;
717 sp<IMapper> mMapper;
718 const bool mBufferQueue;
719};
720
721void _UnwrapNativeCodec2GrallocMetadata(
722 const C2Handle *const handle,
723 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
724 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
725 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
726 generation, igbp_id, igbp_slot);
727}
728
729C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
730 : mInit(C2_OK), mBufferQueue(bufferQueue) {
731 // TODO: get this from allocator
732 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
733 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
734 mTraits = std::make_shared<C2Allocator::Traits>(traits);
735
736 // gralloc allocator is a singleton, so all objects share a global service
737 mAllocator = IAllocator::getService();
738 mMapper = IMapper::getService();
739 if (mAllocator == nullptr || mMapper == nullptr) {
740 mInit = C2_CORRUPTED;
741 }
742}
743
744c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
745 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
746 std::shared_ptr<C2GraphicAllocation> *allocation) {
747 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
748 ALOGV("allocating buffer with usage %#llx => %#llx",
749 (long long)usage.expected, (long long)grallocUsage);
750
751 BufferDescriptorInfo info = {
752 {
753 width,
754 height,
755 1u, // layerCount
756 (PixelFormat)format,
757 grallocUsage,
758 },
759 0u, // stride placeholder
760 };
761 c2_status_t err = C2_OK;
762 BufferDescriptor desc;
763 mMapper->createDescriptor(
764 info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
765 err = maperr2error(maperr);
766 if (err == C2_OK) {
767 desc = descriptor;
768 }
769 });
770 if (err != C2_OK) {
771 return err;
772 }
773
774 // IAllocator shares IMapper error codes.
775 hidl_handle buffer;
776 mAllocator->allocate(
777 desc,
778 1u,
779 [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
780 err = maperr2error(maperr);
781 if (err != C2_OK) {
782 return;
783 }
784 if (buffers.size() != 1u) {
785 err = C2_CORRUPTED;
786 return;
787 }
788 info.stride = stride;
Sungtak Leea4d13be2019-01-23 15:24:46 -0800789 buffer = buffers[0];
Pawin Vongmasa36653902018-11-15 00:10:25 -0800790 });
791 if (err != C2_OK) {
792 return err;
793 }
794
795
796 allocation->reset(new C2AllocationGralloc(
797 info, mMapper, buffer,
Sungtak Leea4d13be2019-01-23 15:24:46 -0800798 C2HandleGralloc::WrapAndMoveNativeHandle(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800799 buffer.getNativeHandle(),
800 info.mapperInfo.width, info.mapperInfo.height,
801 (uint32_t)info.mapperInfo.format, info.mapperInfo.usage, info.stride,
802 0, 0, mBufferQueue ? ~0 : 0),
803 mTraits->id));
804 return C2_OK;
805}
806
807c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
808 const C2Handle *handle,
809 std::shared_ptr<C2GraphicAllocation> *allocation) {
810 BufferDescriptorInfo info;
811 info.mapperInfo.layerCount = 1u;
812 uint32_t generation;
813 uint64_t igbp_id;
814 uint32_t igbp_slot;
815 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
816 handle,
817 &info.mapperInfo.width, &info.mapperInfo.height,
818 (uint32_t *)&info.mapperInfo.format, (uint64_t *)&info.mapperInfo.usage, &info.stride,
819 &generation, &igbp_id, &igbp_slot);
820 if (grallocHandle == nullptr) {
821 return C2_BAD_VALUE;
822 }
823
824 hidl_handle hidlHandle;
825 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
826
827 allocation->reset(new C2AllocationGralloc(info, mMapper, hidlHandle, grallocHandle, mTraits->id));
828 return C2_OK;
829}
830
831C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
832 : mImpl(new Impl(id, bufferQueue)) {}
833
834C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
835
836C2Allocator::id_t C2AllocatorGralloc::getId() const {
837 return mImpl->getId();
838}
839
840C2String C2AllocatorGralloc::getName() const {
841 return mImpl->getName();
842}
843
844std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
845 return mImpl->getTraits();
846}
847
848c2_status_t C2AllocatorGralloc::newGraphicAllocation(
849 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
850 std::shared_ptr<C2GraphicAllocation> *allocation) {
851 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
852}
853
854c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
855 const C2Handle *handle,
856 std::shared_ptr<C2GraphicAllocation> *allocation) {
857 return mImpl->priorGraphicAllocation(handle, allocation);
858}
859
860c2_status_t C2AllocatorGralloc::status() const {
861 return mImpl->status();
862}
863
864bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
865 return C2HandleGralloc::isValid(o);
866}
867
868} // namespace android