1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2AllocatorGralloc"
19 #include <utils/Log.h>
20
21 #include <mutex>
22
23 #include <android/hardware/graphics/common/1.2/types.h>
24 #include <cutils/native_handle.h>
25 #include <hardware/gralloc.h>
26 #include <ui/GraphicBufferAllocator.h>
27 #include <ui/GraphicBufferMapper.h>
28
29 #include <C2AllocatorGralloc.h>
30 #include <C2Buffer.h>
31 #include <C2PlatformSupport.h>
32
33 using ::android::hardware::hidl_handle;
34 using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
35
36 namespace android {
37
38 namespace /* unnamed */ {
39 enum : uint64_t {
40 /**
41 * Usage mask that is passed through from gralloc to Codec 2.0 usage.
42 */
43 PASSTHROUGH_USAGE_MASK =
44 ~(GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_PROTECTED)
45 };
46
47 // verify that passthrough mask is within the platform mask
48 static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
49 } // unnamed
50
FromGrallocUsage(uint64_t usage)51 C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
52 // gralloc does not support WRITE_PROTECTED
53 return C2MemoryUsage(
54 ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
55 ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
56 ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
57 (usage & PASSTHROUGH_USAGE_MASK));
58 }
59
asGrallocUsage() const60 uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
61 // gralloc does not support WRITE_PROTECTED
62 return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
63 ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
64 ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
65 (expected & PASSTHROUGH_USAGE_MASK));
66 }
67
68 namespace /* unnamed */ {
69
70 /* ===================================== GRALLOC ALLOCATION ==================================== */
native_handle_is_invalid(const native_handle_t * const handle)71 bool native_handle_is_invalid(const native_handle_t *const handle) {
72 // perform basic validation of a native handle
73 if (handle == nullptr) {
74 // null handle is considered valid
75 return false;
76 }
77 return ((size_t)handle->version != sizeof(native_handle_t) ||
78 handle->numFds < 0 ||
79 handle->numInts < 0 ||
80 // for sanity assume handles must occupy less memory than INT_MAX bytes
81 handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
82 }
83
84 class C2HandleGralloc : public C2Handle {
85 private:
86 struct ExtraData {
87 uint32_t width;
88 uint32_t height;
89 uint32_t format;
90 uint32_t usage_lo;
91 uint32_t usage_hi;
92 uint32_t stride;
93 uint32_t generation;
94 uint32_t igbp_id_lo;
95 uint32_t igbp_id_hi;
96 uint32_t igbp_slot;
97 uint32_t magic;
98 };
99
100 enum {
101 NUM_INTS = sizeof(ExtraData) / sizeof(int),
102 };
103 const static uint32_t MAGIC = '\xc2gr\x00';
104
105 static
getExtraData(const C2Handle * const handle)106 const ExtraData* getExtraData(const C2Handle *const handle) {
107 if (handle == nullptr
108 || native_handle_is_invalid(handle)
109 || handle->numInts < NUM_INTS) {
110 return nullptr;
111 }
112 return reinterpret_cast<const ExtraData*>(
113 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
114 }
115
116 static
getExtraData(C2Handle * const handle)117 ExtraData *getExtraData(C2Handle *const handle) {
118 return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle)));
119 }
120
121 public:
getIgbpData(uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot) const122 void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
123 const ExtraData *ed = getExtraData(this);
124 *generation = ed->generation;
125 *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
126 *igbp_slot = ed->igbp_slot;
127 }
128
isValid(const C2Handle * const o)129 static bool isValid(const C2Handle *const o) {
130 if (o == nullptr) { // null handle is always valid
131 return true;
132 }
133 const ExtraData *xd = getExtraData(o);
134 // we cannot validate width/height/format/usage without accessing gralloc driver
135 return xd != nullptr && xd->magic == MAGIC;
136 }
137
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)138 static C2HandleGralloc* WrapAndMoveNativeHandle(
139 const native_handle_t *const handle,
140 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
141 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
142 //CHECK(handle != nullptr);
143 if (native_handle_is_invalid(handle) ||
144 handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
145 return nullptr;
146 }
147 ExtraData xd = {
148 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
149 stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
150 igbp_slot, MAGIC
151 };
152 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
153 if (res != nullptr) {
154 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
155 *getExtraData(res) = xd;
156 }
157 return reinterpret_cast<C2HandleGralloc *>(res);
158 }
159
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)160 static C2HandleGralloc* WrapNativeHandle(
161 const native_handle_t *const handle,
162 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
163 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
164 if (handle == nullptr) {
165 return nullptr;
166 }
167 native_handle_t *clone = native_handle_clone(handle);
168 if (clone == nullptr) {
169 return nullptr;
170 }
171 C2HandleGralloc *res = WrapAndMoveNativeHandle(
172 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
173 if (res == nullptr) {
174 native_handle_close(clone);
175 }
176 native_handle_delete(clone);
177 return res;
178 }
179
MigrateNativeHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)180 static bool MigrateNativeHandle(
181 native_handle_t *handle,
182 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
183 if (handle == nullptr || !isValid(handle)) {
184 return false;
185 }
186 ExtraData *ed = getExtraData(handle);
187 if (!ed) return false;
188 ed->generation = generation;
189 ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
190 ed->igbp_id_hi = uint32_t(igbp_id >> 32);
191 ed->igbp_slot = igbp_slot;
192 return true;
193 }
194
195
UnwrapNativeHandle(const C2Handle * const handle)196 static native_handle_t* UnwrapNativeHandle(
197 const C2Handle *const handle) {
198 const ExtraData *xd = getExtraData(handle);
199 if (xd == nullptr || xd->magic != MAGIC) {
200 return nullptr;
201 }
202 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
203 if (res != nullptr) {
204 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
205 }
206 return res;
207 }
208
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)209 static const C2HandleGralloc* Import(
210 const C2Handle *const handle,
211 uint32_t *width, uint32_t *height, uint32_t *format,
212 uint64_t *usage, uint32_t *stride,
213 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
214 const ExtraData *xd = getExtraData(handle);
215 if (xd == nullptr) {
216 return nullptr;
217 }
218 *width = xd->width;
219 *height = xd->height;
220 *format = xd->format;
221 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
222 *stride = xd->stride;
223 *generation = xd->generation;
224 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
225 *igbp_slot = xd->igbp_slot;
226 return reinterpret_cast<const C2HandleGralloc *>(handle);
227 }
228 };
229
230 } // unnamed namespace
231
UnwrapNativeCodec2GrallocHandle(const C2Handle * const handle)232 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
233 return C2HandleGralloc::UnwrapNativeHandle(handle);
234 }
235
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)236 C2Handle *WrapNativeCodec2GrallocHandle(
237 const native_handle_t *const handle,
238 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
239 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
240 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
241 generation, igbp_id, igbp_slot);
242 }
243
MigrateNativeCodec2GrallocHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)244 bool MigrateNativeCodec2GrallocHandle(
245 native_handle_t *handle,
246 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
247 return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
248 }
249
250
251 class C2AllocationGralloc : public C2GraphicAllocation {
252 public:
253 virtual ~C2AllocationGralloc() override;
254
255 virtual c2_status_t map(
256 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
257 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
258 virtual c2_status_t unmap(
259 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
getAllocatorId() const260 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
handle() const261 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
262 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
263
264 // internal methods
265 // |handle| will be moved.
266
267 C2AllocationGralloc(
268 uint32_t width, uint32_t height,
269 uint32_t format, uint32_t layerCount,
270 uint64_t grallocUsage, uint32_t stride,
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
277 private:
278 const uint32_t mWidth;
279 const uint32_t mHeight;
280 const uint32_t mFormat;
281 const uint32_t mLayerCount;
282 const uint64_t mGrallocUsage;
283 const uint32_t mStride;
284 const hidl_handle mHidlHandle;
285 const C2HandleGralloc *mHandle;
286 buffer_handle_t mBuffer;
287 const C2HandleGralloc *mLockedHandle;
288 bool mLocked;
289 C2Allocator::id_t mAllocatorId;
290 std::mutex mMappedLock;
291 };
292
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)293 C2AllocationGralloc::C2AllocationGralloc(
294 uint32_t width, uint32_t height,
295 uint32_t format, uint32_t layerCount,
296 uint64_t grallocUsage, uint32_t stride,
297 hidl_handle &hidlHandle,
298 const C2HandleGralloc *const handle,
299 C2Allocator::id_t allocatorId)
300 : C2GraphicAllocation(width, height),
301 mWidth(width),
302 mHeight(height),
303 mFormat(format),
304 mLayerCount(layerCount),
305 mGrallocUsage(grallocUsage),
306 mStride(stride),
307 mHidlHandle(std::move(hidlHandle)),
308 mHandle(handle),
309 mBuffer(nullptr),
310 mLockedHandle(nullptr),
311 mLocked(false),
312 mAllocatorId(allocatorId) {
313 }
314
~C2AllocationGralloc()315 C2AllocationGralloc::~C2AllocationGralloc() {
316 if (mBuffer && mLocked) {
317 // implementation ignores addresss and rect
318 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
319 unmap(addr, C2Rect(), nullptr);
320 }
321 if (mBuffer) {
322 status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
323 if (err) {
324 ALOGE("failed transaction: freeBuffer");
325 }
326 }
327 if (mHandle) {
328 native_handle_delete(
329 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
330 }
331 if (mLockedHandle) {
332 native_handle_delete(
333 const_cast<native_handle_t *>(
334 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
335 }
336 }
337
map(C2Rect rect,C2MemoryUsage usage,C2Fence * fence,C2PlanarLayout * layout,uint8_t ** addr)338 c2_status_t C2AllocationGralloc::map(
339 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
340 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
341 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
342 ALOGV("mapping buffer with usage %#llx => %#llx",
343 (long long)usage.expected, (long long)grallocUsage);
344
345 // TODO
346 (void)fence;
347
348 std::lock_guard<std::mutex> lock(mMappedLock);
349 if (mBuffer && mLocked) {
350 ALOGD("already mapped");
351 return C2_DUPLICATE;
352 }
353 if (!layout || !addr) {
354 ALOGD("wrong param");
355 return C2_BAD_VALUE;
356 }
357
358 if (!mBuffer) {
359 status_t err = GraphicBufferMapper::get().importBuffer(
360 mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
361 mFormat, mGrallocUsage, mStride, &mBuffer);
362 if (err) {
363 ALOGE("failed transaction: importBuffer");
364 return C2_CORRUPTED;
365 }
366 if (mBuffer == nullptr) {
367 ALOGD("importBuffer returned null buffer");
368 return C2_CORRUPTED;
369 }
370 uint32_t generation = 0;
371 uint64_t igbp_id = 0;
372 uint32_t igbp_slot = 0;
373 if (mHandle) {
374 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
375 }
376
377 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
378 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
379 mStride, generation, igbp_id, igbp_slot);
380 }
381 switch (mFormat) {
382 case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
383 // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
384 // Surface. In all other cases it is RGBA. We don't know which case it is here, so
385 // default to YUV for now.
386 void *pointer = nullptr;
387 // TODO: fence
388 status_t err = GraphicBufferMapper::get().lock(
389 const_cast<native_handle_t *>(mBuffer), grallocUsage,
390 { (int32_t)rect.left, (int32_t)rect.top,
391 (int32_t)rect.width, (int32_t)rect.height },
392 &pointer);
393 if (err) {
394 ALOGE("failed transaction: lock(RGBA_1010102)");
395 return C2_CORRUPTED;
396 }
397 // treat as 32-bit values
398 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
399 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
400 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
401 addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
402 layout->type = C2PlanarLayout::TYPE_YUVA;
403 layout->numPlanes = 4;
404 layout->rootPlanes = 1;
405 layout->planes[C2PlanarLayout::PLANE_Y] = {
406 C2PlaneInfo::CHANNEL_Y, // channel
407 4, // colInc
408 static_cast<int32_t>(4 * mStride), // rowInc
409 1, // mColSampling
410 1, // mRowSampling
411 32, // allocatedDepth
412 10, // bitDepth
413 10, // rightShift
414 C2PlaneInfo::LITTLE_END, // endianness
415 C2PlanarLayout::PLANE_Y, // rootIx
416 0, // offset
417 };
418 layout->planes[C2PlanarLayout::PLANE_U] = {
419 C2PlaneInfo::CHANNEL_CB, // channel
420 4, // colInc
421 static_cast<int32_t>(4 * mStride), // rowInc
422 1, // mColSampling
423 1, // mRowSampling
424 32, // allocatedDepth
425 10, // bitDepth
426 0, // rightShift
427 C2PlaneInfo::LITTLE_END, // endianness
428 C2PlanarLayout::PLANE_Y, // rootIx
429 0, // offset
430 };
431 layout->planes[C2PlanarLayout::PLANE_V] = {
432 C2PlaneInfo::CHANNEL_CR, // channel
433 4, // colInc
434 static_cast<int32_t>(4 * mStride), // rowInc
435 1, // mColSampling
436 1, // mRowSampling
437 32, // allocatedDepth
438 10, // bitDepth
439 20, // rightShift
440 C2PlaneInfo::LITTLE_END, // endianness
441 C2PlanarLayout::PLANE_Y, // rootIx
442 0, // offset
443 };
444 layout->planes[C2PlanarLayout::PLANE_A] = {
445 C2PlaneInfo::CHANNEL_A, // channel
446 4, // colInc
447 static_cast<int32_t>(4 * mStride), // rowInc
448 1, // mColSampling
449 1, // mRowSampling
450 32, // allocatedDepth
451 2, // bitDepth
452 30, // rightShift
453 C2PlaneInfo::LITTLE_END, // endianness
454 C2PlanarLayout::PLANE_Y, // rootIx
455 0, // offset
456 };
457 break;
458 }
459
460 case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
461 // TODO: alpha channel
462 // fall-through
463 case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
464 void *pointer = nullptr;
465 // TODO: fence
466 status_t err = GraphicBufferMapper::get().lock(
467 const_cast<native_handle_t*>(mBuffer), grallocUsage,
468 { (int32_t)rect.left, (int32_t)rect.top,
469 (int32_t)rect.width, (int32_t)rect.height },
470 &pointer);
471 if (err) {
472 ALOGE("failed transaction: lock(RGBA_8888)");
473 return C2_CORRUPTED;
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 static_cast<int32_t>(4 * mStride), // 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 static_cast<int32_t>(4 * mStride), // 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 static_cast<int32_t>(4 * mStride), // 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
523 case static_cast<uint32_t>(PixelFormat4::BLOB): {
524 void *pointer = nullptr;
525 // TODO: fence
526 status_t err = GraphicBufferMapper::get().lock(
527 const_cast<native_handle_t*>(mBuffer), grallocUsage,
528 { (int32_t)rect.left, (int32_t)rect.top,
529 (int32_t)rect.width, (int32_t)rect.height },
530 &pointer);
531 if (err) {
532 ALOGE("failed transaction: lock(BLOB)");
533 return C2_CORRUPTED;
534 }
535 *addr = (uint8_t *)pointer;
536 break;
537 }
538
539 case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
540 // fall-through
541 case static_cast<uint32_t>(PixelFormat4::YV12):
542 // fall-through
543 default: {
544 android_ycbcr ycbcrLayout;
545
546 status_t err = GraphicBufferMapper::get().lockYCbCr(
547 const_cast<native_handle_t*>(mBuffer), grallocUsage,
548 { (int32_t)rect.left, (int32_t)rect.top,
549 (int32_t)rect.width, (int32_t)rect.height },
550 &ycbcrLayout);
551 if (err) {
552 ALOGE("failed transaction: lockYCbCr");
553 return C2_CORRUPTED;
554 }
555
556 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
557 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
558 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
559 layout->type = C2PlanarLayout::TYPE_YUV;
560 layout->numPlanes = 3;
561 layout->rootPlanes = 3;
562 layout->planes[C2PlanarLayout::PLANE_Y] = {
563 C2PlaneInfo::CHANNEL_Y, // channel
564 1, // colInc
565 (int32_t)ycbcrLayout.ystride, // rowInc
566 1, // mColSampling
567 1, // mRowSampling
568 8, // allocatedDepth
569 8, // bitDepth
570 0, // rightShift
571 C2PlaneInfo::NATIVE, // endianness
572 C2PlanarLayout::PLANE_Y, // rootIx
573 0, // offset
574 };
575 layout->planes[C2PlanarLayout::PLANE_U] = {
576 C2PlaneInfo::CHANNEL_CB, // channel
577 (int32_t)ycbcrLayout.chroma_step, // colInc
578 (int32_t)ycbcrLayout.cstride, // rowInc
579 2, // mColSampling
580 2, // mRowSampling
581 8, // allocatedDepth
582 8, // bitDepth
583 0, // rightShift
584 C2PlaneInfo::NATIVE, // endianness
585 C2PlanarLayout::PLANE_U, // rootIx
586 0, // offset
587 };
588 layout->planes[C2PlanarLayout::PLANE_V] = {
589 C2PlaneInfo::CHANNEL_CR, // channel
590 (int32_t)ycbcrLayout.chroma_step, // colInc
591 (int32_t)ycbcrLayout.cstride, // rowInc
592 2, // mColSampling
593 2, // mRowSampling
594 8, // allocatedDepth
595 8, // bitDepth
596 0, // rightShift
597 C2PlaneInfo::NATIVE, // endianness
598 C2PlanarLayout::PLANE_V, // rootIx
599 0, // offset
600 };
601 // handle interleaved formats
602 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
603 if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chroma_step) {
604 layout->rootPlanes = 2;
605 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
606 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
607 } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chroma_step) {
608 layout->rootPlanes = 2;
609 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
610 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
611 }
612 break;
613 }
614 }
615 mLocked = true;
616
617 return C2_OK;
618 }
619
unmap(uint8_t ** addr,C2Rect rect,C2Fence * fence)620 c2_status_t C2AllocationGralloc::unmap(
621 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
622 // TODO: check addr and size, use fence
623 (void)addr;
624 (void)rect;
625 (void)fence;
626
627 std::lock_guard<std::mutex> lock(mMappedLock);
628 // TODO: fence
629 status_t err = GraphicBufferMapper::get().unlock(mBuffer);
630 if (err) {
631 ALOGE("failed transaction: unlock");
632 return C2_CORRUPTED;
633 }
634
635 mLocked = false;
636 return C2_OK;
637 }
638
equals(const std::shared_ptr<const C2GraphicAllocation> & other) const639 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
640 return other && other->handle() == handle();
641 }
642
643 /* ===================================== GRALLOC ALLOCATOR ==================================== */
644 class C2AllocatorGralloc::Impl {
645 public:
646 Impl(id_t id, bool bufferQueue);
647
getId() const648 id_t getId() const {
649 return mTraits->id;
650 }
651
getName() const652 C2String getName() const {
653 return mTraits->name;
654 }
655
getTraits() const656 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
657 return mTraits;
658 }
659
660 c2_status_t newGraphicAllocation(
661 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
662 std::shared_ptr<C2GraphicAllocation> *allocation);
663
664 c2_status_t priorGraphicAllocation(
665 const C2Handle *handle,
666 std::shared_ptr<C2GraphicAllocation> *allocation);
667
status() const668 c2_status_t status() const { return mInit; }
669
670 private:
671 std::shared_ptr<C2Allocator::Traits> mTraits;
672 c2_status_t mInit;
673 const bool mBufferQueue;
674 };
675
_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)676 void _UnwrapNativeCodec2GrallocMetadata(
677 const C2Handle *const handle,
678 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
679 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
680 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
681 generation, igbp_id, igbp_slot);
682 }
683
Impl(id_t id,bool bufferQueue)684 C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
685 : mInit(C2_OK), mBufferQueue(bufferQueue) {
686 // TODO: get this from allocator
687 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
688 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
689 mTraits = std::make_shared<C2Allocator::Traits>(traits);
690 }
691
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,const C2MemoryUsage & usage,std::shared_ptr<C2GraphicAllocation> * allocation)692 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
693 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
694 std::shared_ptr<C2GraphicAllocation> *allocation) {
695 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
696 ALOGV("allocating buffer with usage %#llx => %#llx",
697 (long long)usage.expected, (long long)grallocUsage);
698
699 buffer_handle_t buffer;
700
701 uint32_t stride = 0;
702
703 status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
704 1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
705 if (err) {
706 ALOGE("failed transaction: allocate");
707 return C2_CORRUPTED;
708 }
709
710 hidl_handle hidlHandle;
711 hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
712
713 allocation->reset(new C2AllocationGralloc(
714 width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
715 C2HandleGralloc::WrapAndMoveNativeHandle(
716 hidlHandle, width, height,
717 format, grallocUsage, stride,
718 0, 0, mBufferQueue ? ~0 : 0),
719 mTraits->id));
720 return C2_OK;
721 }
722
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)723 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
724 const C2Handle *handle,
725 std::shared_ptr<C2GraphicAllocation> *allocation) {
726
727 uint32_t generation;
728 uint64_t igbp_id;
729 uint32_t igbp_slot;
730
731 uint32_t width;
732 uint32_t height;
733 uint32_t format;
734 uint32_t layerCount = 1;
735 uint64_t grallocUsage;
736 uint32_t stride;
737
738 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
739 handle, &width, &height, &format, &grallocUsage, &stride,
740 &generation, &igbp_id, &igbp_slot);
741 if (grallocHandle == nullptr) {
742 return C2_BAD_VALUE;
743 }
744
745 hidl_handle hidlHandle;
746 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
747
748 allocation->reset(new C2AllocationGralloc(
749 width, height, format, layerCount,
750 grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
751 return C2_OK;
752 }
753
C2AllocatorGralloc(id_t id,bool bufferQueue)754 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
755 : mImpl(new Impl(id, bufferQueue)) {}
756
~C2AllocatorGralloc()757 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
758
getId() const759 C2Allocator::id_t C2AllocatorGralloc::getId() const {
760 return mImpl->getId();
761 }
762
getName() const763 C2String C2AllocatorGralloc::getName() const {
764 return mImpl->getName();
765 }
766
getTraits() const767 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
768 return mImpl->getTraits();
769 }
770
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicAllocation> * allocation)771 c2_status_t C2AllocatorGralloc::newGraphicAllocation(
772 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
773 std::shared_ptr<C2GraphicAllocation> *allocation) {
774 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
775 }
776
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)777 c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
778 const C2Handle *handle,
779 std::shared_ptr<C2GraphicAllocation> *allocation) {
780 return mImpl->priorGraphicAllocation(handle, allocation);
781 }
782
status() const783 c2_status_t C2AllocatorGralloc::status() const {
784 return mImpl->status();
785 }
786
isValid(const C2Handle * const o)787 bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
788 return C2HandleGralloc::isValid(o);
789 }
790
791 } // namespace android
792