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