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 <drm/drm_fourcc.h>
27 #include <gralloctypes/Gralloc4.h>
28 #include <hardware/gralloc.h>
29 #include <ui/GraphicBufferAllocator.h>
30 #include <ui/GraphicBufferMapper.h>
31 #include <ui/Rect.h>
32
33 #include <C2AllocatorGralloc.h>
34 #include <C2Buffer.h>
35 #include <C2Debug.h>
36 #include <C2PlatformSupport.h>
37
38 using ::android::hardware::hidl_handle;
39 using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
40
41 namespace android {
42
43 namespace /* unnamed */ {
44 enum : uint64_t {
45 /**
46 * Usage mask that is passed through from gralloc to Codec 2.0 usage.
47 */
48 PASSTHROUGH_USAGE_MASK =
49 ~static_cast<uint64_t>(GRALLOC_USAGE_SW_READ_MASK |
50 GRALLOC_USAGE_SW_WRITE_MASK |
51 GRALLOC_USAGE_PROTECTED)
52 };
53
54 // verify that passthrough mask is within the platform mask
55 static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
56 } // unnamed
57
isAtLeastT()58 static bool isAtLeastT() {
59 return android_get_device_api_level() >= __ANDROID_API_T__;
60 }
61
FromGrallocUsage(uint64_t usage)62 C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
63 // gralloc does not support WRITE_PROTECTED
64 return C2MemoryUsage(
65 ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
66 ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
67 ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
68 (usage & PASSTHROUGH_USAGE_MASK));
69 }
70
asGrallocUsage() const71 uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
72 // gralloc does not support WRITE_PROTECTED
73 return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
74 ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
75 ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
76 (expected & PASSTHROUGH_USAGE_MASK));
77 }
78
79 namespace /* unnamed */ {
80
81 /* ===================================== GRALLOC ALLOCATION ==================================== */
native_handle_is_invalid(const native_handle_t * const handle)82 bool native_handle_is_invalid(const native_handle_t *const handle) {
83 // perform basic validation of a native handle
84 if (handle == nullptr) {
85 // null handle is considered valid
86 return false;
87 }
88 return ((size_t)handle->version != sizeof(native_handle_t) ||
89 handle->numFds < 0 ||
90 handle->numInts < 0 ||
91 // for sanity assume handles must occupy less memory than INT_MAX bytes
92 handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
93 }
94
95 class C2HandleGralloc : public C2Handle {
96 private:
97 struct ExtraData {
98 uint32_t width;
99 uint32_t height;
100 uint32_t format;
101 uint32_t usage_lo;
102 uint32_t usage_hi;
103 uint32_t stride;
104 uint32_t generation;
105 uint32_t igbp_id_lo;
106 uint32_t igbp_id_hi;
107 uint32_t igbp_slot;
108 uint32_t magic;
109 };
110
111 enum {
112 NUM_INTS = sizeof(ExtraData) / sizeof(int),
113 };
114 const static uint32_t MAGIC = '\xc2gr\x00';
115
116 static
GetExtraData(const C2Handle * const handle)117 const ExtraData* GetExtraData(const C2Handle *const handle) {
118 if (handle == nullptr
119 || native_handle_is_invalid(handle)
120 || handle->numInts < NUM_INTS) {
121 return nullptr;
122 }
123 return reinterpret_cast<const ExtraData*>(
124 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
125 }
126
127 static
GetExtraData(C2Handle * const handle)128 ExtraData *GetExtraData(C2Handle *const handle) {
129 return const_cast<ExtraData *>(GetExtraData(const_cast<const C2Handle *const>(handle)));
130 }
131
132 public:
getIgbpData(uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot) const133 void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
134 const ExtraData *ed = GetExtraData(this);
135 *generation = ed->generation;
136 *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
137 *igbp_slot = ed->igbp_slot;
138 }
139
IsValid(const C2Handle * const o)140 static bool IsValid(const C2Handle *const o) {
141 if (o == nullptr) { // null handle is always valid
142 return true;
143 }
144 const ExtraData *xd = GetExtraData(o);
145 // we cannot validate width/height/format/usage without accessing gralloc driver
146 return xd != nullptr && xd->magic == MAGIC;
147 }
148
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)149 static C2HandleGralloc* WrapAndMoveNativeHandle(
150 const native_handle_t *const handle,
151 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
152 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
153 //CHECK(handle != nullptr);
154 if (native_handle_is_invalid(handle) ||
155 handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
156 return nullptr;
157 }
158 ExtraData xd = {
159 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
160 stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
161 igbp_slot, MAGIC
162 };
163 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
164 if (res != nullptr) {
165 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
166 *GetExtraData(res) = xd;
167 }
168 return reinterpret_cast<C2HandleGralloc *>(res);
169 }
170
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)171 static C2HandleGralloc* WrapNativeHandle(
172 const native_handle_t *const handle,
173 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
174 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
175 if (handle == nullptr) {
176 return nullptr;
177 }
178 native_handle_t *clone = native_handle_clone(handle);
179 if (clone == nullptr) {
180 return nullptr;
181 }
182 C2HandleGralloc *res = WrapAndMoveNativeHandle(
183 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
184 if (res == nullptr) {
185 native_handle_close(clone);
186 }
187 native_handle_delete(clone);
188 return res;
189 }
190
getPixelFormat(const C2Handle * const handle)191 static uint32_t getPixelFormat(const C2Handle *const handle) {
192 if (handle == nullptr) {
193 return 0;
194 }
195 const ExtraData *xd = GetExtraData(handle);
196 return xd->format;
197 }
198
MigrateNativeHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)199 static bool MigrateNativeHandle(
200 native_handle_t *handle,
201 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
202 if (handle == nullptr || !IsValid(handle)) {
203 return false;
204 }
205 ExtraData *ed = GetExtraData(handle);
206 if (!ed) return false;
207 ed->generation = generation;
208 ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
209 ed->igbp_id_hi = uint32_t(igbp_id >> 32);
210 ed->igbp_slot = igbp_slot;
211 return true;
212 }
213
214
UnwrapNativeHandle(const C2Handle * const handle)215 static native_handle_t* UnwrapNativeHandle(
216 const C2Handle *const handle) {
217 const ExtraData *xd = GetExtraData(handle);
218 if (xd == nullptr || xd->magic != MAGIC) {
219 return nullptr;
220 }
221 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
222 if (res != nullptr) {
223 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
224 }
225 return res;
226 }
227
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)228 static const C2HandleGralloc* Import(
229 const C2Handle *const handle,
230 uint32_t *width, uint32_t *height, uint32_t *format,
231 uint64_t *usage, uint32_t *stride,
232 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
233 const ExtraData *xd = GetExtraData(handle);
234 if (xd == nullptr) {
235 return nullptr;
236 }
237 *width = xd->width;
238 *height = xd->height;
239 *format = xd->format;
240 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
241 *stride = xd->stride;
242 *generation = xd->generation;
243 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
244 *igbp_slot = xd->igbp_slot;
245 return reinterpret_cast<const C2HandleGralloc *>(handle);
246 }
247 };
248
249 class C2HandleAhwb : public C2Handle {
250 private:
251 // TODO: remove extradata and use AHardwareBuffer directly.
252 struct ExtraData {
253 uint32_t width;
254 uint32_t height;
255 uint32_t format;
256 uint32_t usage_lo;
257 uint32_t usage_hi;
258 uint32_t stride;
259 uint32_t origId_lo;
260 uint32_t origId_hi;
261 uint32_t magic;
262 };
263
264 enum {
265 NUM_INTS = sizeof(ExtraData) / sizeof(int),
266 };
267 const static uint32_t MAGIC = '\xc2hw\x00';
268
269 static
GetExtraData(const C2Handle * const handle)270 const ExtraData* GetExtraData(const C2Handle *const handle) {
271 if (handle == nullptr
272 || native_handle_is_invalid(handle)
273 || handle->numInts < NUM_INTS) {
274 return nullptr;
275 }
276 return reinterpret_cast<const ExtraData*>(
277 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
278 }
279
280 static
GetExtraData(C2Handle * const handle)281 ExtraData *GetExtraData(C2Handle *const handle) {
282 return const_cast<ExtraData *>(GetExtraData(const_cast<const C2Handle *const>(handle)));
283 }
284
285 public:
getOrigId(uint64_t * origId) const286 void getOrigId(uint64_t *origId) const {
287 const ExtraData *ed = GetExtraData(this);
288 *origId = unsigned(ed->origId_lo) | uint64_t(unsigned(ed->origId_hi)) << 32;
289 }
290
IsValid(const C2Handle * const o)291 static bool IsValid(const C2Handle *const o) {
292 if (o == nullptr) { // null handle is always valid
293 return true;
294 }
295 const ExtraData *xd = GetExtraData(o);
296 // we cannot validate width/height/format/usage without accessing gralloc driver
297 return xd != nullptr && xd->magic == MAGIC;
298 }
299
WrapAndMoveNativeHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint64_t origId)300 static C2HandleAhwb* WrapAndMoveNativeHandle(
301 const native_handle_t *const handle,
302 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
303 uint32_t stride, uint64_t origId) {
304 //CHECK(handle != nullptr);
305 if (native_handle_is_invalid(handle) || handle->numInts >
306 int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
307 return nullptr;
308 }
309 ExtraData xd = {
310 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
311 stride, uint32_t(origId & 0xFFFFFFFF), uint32_t(origId >> 32), MAGIC
312 };
313 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
314 if (res != nullptr) {
315 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
316 *GetExtraData(res) = xd;
317 }
318 return reinterpret_cast<C2HandleAhwb *>(res);
319 }
320
getPixelFormat(const C2Handle * const handle)321 static uint32_t getPixelFormat(const C2Handle *const handle) {
322 if (handle == nullptr) {
323 return 0;
324 }
325 const ExtraData *xd = GetExtraData(handle);
326 return xd->format;
327 }
328
WrapNativeHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint64_t origId)329 static C2HandleAhwb* WrapNativeHandle(
330 const native_handle_t *const handle,
331 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
332 uint32_t stride, uint64_t origId) {
333 if (handle == nullptr) {
334 return nullptr;
335 }
336 native_handle_t *clone = native_handle_clone(handle);
337 if (clone == nullptr) {
338 return nullptr;
339 }
340 C2HandleAhwb *res = WrapAndMoveNativeHandle(
341 clone, width, height, format, usage, stride, origId);
342 if (res == nullptr) {
343 native_handle_close(clone);
344 }
345 native_handle_delete(clone);
346 return res;
347 }
348
UnwrapNativeHandle(const C2Handle * const handle)349 static native_handle_t* UnwrapNativeHandle(
350 const C2Handle *const handle) {
351 const ExtraData *xd = GetExtraData(handle);
352 if (xd == nullptr || xd->magic != MAGIC) {
353 return nullptr;
354 }
355 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
356 if (res != nullptr) {
357 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
358 }
359 return res;
360 }
361
Import(const C2Handle * const handle,uint32_t * width,uint32_t * height,uint32_t * format,uint64_t * usage,uint32_t * stride,uint64_t * origId)362 static const C2HandleAhwb* Import(
363 const C2Handle *const handle,
364 uint32_t *width, uint32_t *height, uint32_t *format,
365 uint64_t *usage, uint32_t *stride,
366 uint64_t *origId) {
367 const ExtraData *xd = GetExtraData(handle);
368 if (xd == nullptr) {
369 return nullptr;
370 }
371 *width = xd->width;
372 *height = xd->height;
373 *format = xd->format;
374 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
375 *stride = xd->stride;
376 *origId = xd->origId_lo | (uint64_t(xd->origId_hi) << 32);
377 return reinterpret_cast<const C2HandleAhwb *>(handle);
378 }
379 };
380
381 static
Gralloc4Mapper_lock(native_handle_t * handle,uint64_t usage,const Rect & bounds,C2PlanarLayout * layout,uint8_t ** addr)382 c2_status_t Gralloc4Mapper_lock(native_handle_t *handle, uint64_t usage, const Rect& bounds,
383 C2PlanarLayout *layout, uint8_t **addr) {
384 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
385
386 std::vector<ui::PlaneLayout> planes;
387 // this method is only supported on Gralloc 4 or later
388 status_t err = mapper.getPlaneLayouts(handle, &planes);
389 if (err != NO_ERROR || planes.empty()) {
390 return C2_CANNOT_DO;
391 }
392
393 uint8_t *pointer = nullptr;
394 err = mapper.lock(handle, usage, bounds, (void **)&pointer);
395 if (err != NO_ERROR || pointer == nullptr) {
396 return C2_CORRUPTED;
397 }
398
399 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
400 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
401
402 layout->type = C2PlanarLayout::TYPE_YUV;
403 layout->numPlanes = 0;
404 layout->rootPlanes = 0;
405
406 for (const ui::PlaneLayout &plane : planes) {
407 layout->rootPlanes++;
408 uint32_t lastOffsetInBits = 0;
409 uint32_t rootIx = layout->numPlanes;
410
411 for (const PlaneLayoutComponent &component : plane.components) {
412 if (!gralloc4::isStandardPlaneLayoutComponentType(component.type)) {
413 mapper.unlock(handle);
414 return C2_CANNOT_DO;
415 }
416
417 uint32_t rightShiftBits = component.offsetInBits - lastOffsetInBits;
418 uint32_t allocatedDepthInBits = component.sizeInBits + rightShiftBits;
419 C2PlanarLayout::plane_index_t planeId;
420 C2PlaneInfo::channel_t channel;
421
422 switch (static_cast<PlaneLayoutComponentType>(component.type.value)) {
423 case PlaneLayoutComponentType::Y:
424 planeId = C2PlanarLayout::PLANE_Y;
425 channel = C2PlaneInfo::CHANNEL_Y;
426 break;
427 case PlaneLayoutComponentType::CB:
428 planeId = C2PlanarLayout::PLANE_U;
429 channel = C2PlaneInfo::CHANNEL_CB;
430 break;
431 case PlaneLayoutComponentType::CR:
432 planeId = C2PlanarLayout::PLANE_V;
433 channel = C2PlaneInfo::CHANNEL_CR;
434 break;
435 default:
436 mapper.unlock(handle);
437 return C2_CORRUPTED;
438 }
439
440 addr[planeId] = pointer + plane.offsetInBytes + (component.offsetInBits / 8);
441 layout->planes[planeId] = {
442 channel, // channel
443 static_cast<int32_t>(plane.sampleIncrementInBits / 8), // colInc
444 static_cast<int32_t>(plane.strideInBytes), // rowInc
445 static_cast<uint32_t>(plane.horizontalSubsampling), // mColSampling
446 static_cast<uint32_t>(plane.verticalSubsampling), // mRowSampling
447 allocatedDepthInBits, // allocatedDepth (bits)
448 static_cast<uint32_t>(component.sizeInBits), // bitDepth (bits)
449 rightShiftBits, // rightShift (bits)
450 C2PlaneInfo::NATIVE, // endianness
451 rootIx, // rootIx
452 static_cast<uint32_t>(component.offsetInBits / 8), // offset (bytes)
453 };
454
455 layout->numPlanes++;
456 lastOffsetInBits = component.offsetInBits + component.sizeInBits;
457 }
458 }
459 return C2_OK;
460 }
461
PopulatePlaneLayout(buffer_handle_t buffer,const Rect & rect,uint32_t format,uint64_t grallocUsage,uint32_t stride,C2PlanarLayout * layout,uint8_t ** addr)462 static c2_status_t PopulatePlaneLayout(
463 buffer_handle_t buffer,
464 const Rect &rect,
465 uint32_t format,
466 uint64_t grallocUsage,
467 uint32_t stride,
468 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
469 // 'NATIVE' on Android means LITTLE_ENDIAN
470 constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
471
472 // Try to resolve IMPLEMENTATION_DEFINED format to accurate format if
473 // possible.
474 uint32_t fourCc;
475 if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
476 !GraphicBufferMapper::get().getPixelFormatFourCC(buffer, &fourCc)) {
477 switch (fourCc) {
478 case DRM_FORMAT_XBGR8888:
479 format = static_cast<uint32_t>(PixelFormat4::RGBX_8888);
480 break;
481 case DRM_FORMAT_ABGR8888:
482 format = static_cast<uint32_t>(PixelFormat4::RGBA_8888);
483 break;
484 default:
485 break;
486 }
487 }
488
489 switch (format) {
490 case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
491 // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
492 // Surface. In all other cases it is RGBA. We don't know which case it is here, so
493 // default to YUV for now.
494 void *pointer = nullptr;
495 // TODO: fence
496 status_t err = GraphicBufferMapper::get().lock(
497 const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
498 if (err) {
499 ALOGE("failed transaction: lock(RGBA_1010102)");
500 return C2_CORRUPTED;
501 }
502 // treat as 32-bit values
503 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
504 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
505 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
506 addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
507 layout->type = C2PlanarLayout::TYPE_YUVA;
508 layout->numPlanes = 4;
509 layout->rootPlanes = 1;
510 layout->planes[C2PlanarLayout::PLANE_Y] = {
511 C2PlaneInfo::CHANNEL_Y, // channel
512 4, // colInc
513 static_cast<int32_t>(4 * stride), // rowInc
514 1, // mColSampling
515 1, // mRowSampling
516 32, // allocatedDepth
517 10, // bitDepth
518 10, // rightShift
519 C2PlaneInfo::LITTLE_END, // endianness
520 C2PlanarLayout::PLANE_Y, // rootIx
521 0, // offset
522 };
523 layout->planes[C2PlanarLayout::PLANE_U] = {
524 C2PlaneInfo::CHANNEL_CB, // channel
525 4, // colInc
526 static_cast<int32_t>(4 * stride), // rowInc
527 1, // mColSampling
528 1, // mRowSampling
529 32, // allocatedDepth
530 10, // bitDepth
531 0, // rightShift
532 C2PlaneInfo::LITTLE_END, // endianness
533 C2PlanarLayout::PLANE_Y, // rootIx
534 0, // offset
535 };
536 layout->planes[C2PlanarLayout::PLANE_V] = {
537 C2PlaneInfo::CHANNEL_CR, // channel
538 4, // colInc
539 static_cast<int32_t>(4 * stride), // rowInc
540 1, // mColSampling
541 1, // mRowSampling
542 32, // allocatedDepth
543 10, // bitDepth
544 20, // rightShift
545 C2PlaneInfo::LITTLE_END, // endianness
546 C2PlanarLayout::PLANE_Y, // rootIx
547 0, // offset
548 };
549 layout->planes[C2PlanarLayout::PLANE_A] = {
550 C2PlaneInfo::CHANNEL_A, // channel
551 4, // colInc
552 static_cast<int32_t>(4 * stride), // rowInc
553 1, // mColSampling
554 1, // mRowSampling
555 32, // allocatedDepth
556 2, // bitDepth
557 30, // rightShift
558 C2PlaneInfo::LITTLE_END, // endianness
559 C2PlanarLayout::PLANE_Y, // rootIx
560 0, // offset
561 };
562 break;
563 }
564
565 case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
566 // TODO: alpha channel
567 // fall-through
568 case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
569 void *pointer = nullptr;
570 // TODO: fence
571 status_t err = GraphicBufferMapper::get().lock(
572 const_cast<native_handle_t*>(buffer), grallocUsage, rect, &pointer);
573 if (err) {
574 ALOGE("failed transaction: lock(RGBA_8888)");
575 return C2_CORRUPTED;
576 }
577 addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
578 addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
579 addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
580 layout->type = C2PlanarLayout::TYPE_RGB;
581 layout->numPlanes = 3;
582 layout->rootPlanes = 1;
583 layout->planes[C2PlanarLayout::PLANE_R] = {
584 C2PlaneInfo::CHANNEL_R, // channel
585 4, // colInc
586 static_cast<int32_t>(4 * stride), // rowInc
587 1, // mColSampling
588 1, // mRowSampling
589 8, // allocatedDepth
590 8, // bitDepth
591 0, // rightShift
592 C2PlaneInfo::NATIVE, // endianness
593 C2PlanarLayout::PLANE_R, // rootIx
594 0, // offset
595 };
596 layout->planes[C2PlanarLayout::PLANE_G] = {
597 C2PlaneInfo::CHANNEL_G, // channel
598 4, // colInc
599 static_cast<int32_t>(4 * stride), // rowInc
600 1, // mColSampling
601 1, // mRowSampling
602 8, // allocatedDepth
603 8, // bitDepth
604 0, // rightShift
605 C2PlaneInfo::NATIVE, // endianness
606 C2PlanarLayout::PLANE_R, // rootIx
607 1, // offset
608 };
609 layout->planes[C2PlanarLayout::PLANE_B] = {
610 C2PlaneInfo::CHANNEL_B, // channel
611 4, // colInc
612 static_cast<int32_t>(4 * stride), // rowInc
613 1, // mColSampling
614 1, // mRowSampling
615 8, // allocatedDepth
616 8, // bitDepth
617 0, // rightShift
618 C2PlaneInfo::NATIVE, // endianness
619 C2PlanarLayout::PLANE_R, // rootIx
620 2, // offset
621 };
622 break;
623 }
624
625 case static_cast<uint32_t>(PixelFormat4::BLOB): {
626 void *pointer = nullptr;
627 // TODO: fence
628 status_t err = GraphicBufferMapper::get().lock(
629 const_cast<native_handle_t*>(buffer), grallocUsage, rect, &pointer);
630 if (err) {
631 ALOGE("failed transaction: lock(BLOB)");
632 return C2_CORRUPTED;
633 }
634 *addr = (uint8_t *)pointer;
635 break;
636 }
637
638 case static_cast<uint32_t>(PixelFormat4::YCBCR_422_SP):
639 // fall-through
640 case static_cast<uint32_t>(PixelFormat4::YCRCB_420_SP):
641 // fall-through
642 case static_cast<uint32_t>(PixelFormat4::YCBCR_422_I):
643 // fall-through
644 case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
645 // fall-through
646 case static_cast<uint32_t>(PixelFormat4::YV12): {
647 android_ycbcr ycbcrLayout;
648
649 status_t err = GraphicBufferMapper::get().lockYCbCr(
650 const_cast<native_handle_t*>(buffer), grallocUsage, rect, &ycbcrLayout);
651 if (err) {
652 ALOGE("failed transaction: lockYCbCr (err=%d)", err);
653 return C2_CORRUPTED;
654 }
655 if (!ycbcrLayout.y || !ycbcrLayout.cb || !ycbcrLayout.cr
656 || ycbcrLayout.ystride == 0
657 || ycbcrLayout.cstride == 0
658 || ycbcrLayout.chroma_step == 0) {
659 ALOGE("invalid layout: lockYCbCr (y=%s cb=%s cr=%s "
660 "ystride=%zu cstride=%zu chroma_step=%zu)",
661 ycbcrLayout.y ? "(non-null)" : "(null)",
662 ycbcrLayout.cb ? "(non-null)" : "(null)",
663 ycbcrLayout.cr ? "(non-null)" : "(null)",
664 ycbcrLayout.ystride, ycbcrLayout.cstride, ycbcrLayout.chroma_step);
665 return C2_CORRUPTED;
666 }
667
668 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
669 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
670 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
671 layout->type = C2PlanarLayout::TYPE_YUV;
672 layout->numPlanes = 3;
673 layout->rootPlanes = 3;
674 layout->planes[C2PlanarLayout::PLANE_Y] = {
675 C2PlaneInfo::CHANNEL_Y, // channel
676 1, // colInc
677 (int32_t)ycbcrLayout.ystride, // rowInc
678 1, // mColSampling
679 1, // mRowSampling
680 8, // allocatedDepth
681 8, // bitDepth
682 0, // rightShift
683 C2PlaneInfo::NATIVE, // endianness
684 C2PlanarLayout::PLANE_Y, // rootIx
685 0, // offset
686 };
687 layout->planes[C2PlanarLayout::PLANE_U] = {
688 C2PlaneInfo::CHANNEL_CB, // channel
689 (int32_t)ycbcrLayout.chroma_step, // colInc
690 (int32_t)ycbcrLayout.cstride, // rowInc
691 2, // mColSampling
692 2, // mRowSampling
693 8, // allocatedDepth
694 8, // bitDepth
695 0, // rightShift
696 C2PlaneInfo::NATIVE, // endianness
697 C2PlanarLayout::PLANE_U, // rootIx
698 0, // offset
699 };
700 layout->planes[C2PlanarLayout::PLANE_V] = {
701 C2PlaneInfo::CHANNEL_CR, // channel
702 (int32_t)ycbcrLayout.chroma_step, // colInc
703 (int32_t)ycbcrLayout.cstride, // rowInc
704 2, // mColSampling
705 2, // mRowSampling
706 8, // allocatedDepth
707 8, // bitDepth
708 0, // rightShift
709 C2PlaneInfo::NATIVE, // endianness
710 C2PlanarLayout::PLANE_V, // rootIx
711 0, // offset
712 };
713 break;
714 }
715
716 case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
717 // In Android T, P010 is relaxed to allow arbitrary stride for the Y and UV planes,
718 // try locking with the gralloc4 mapper first.
719 c2_status_t status = Gralloc4Mapper_lock(
720 const_cast<native_handle_t*>(buffer), grallocUsage, rect, layout, addr);
721 if (status == C2_OK) {
722 break;
723 }
724
725 void *pointer = nullptr;
726 status_t err = GraphicBufferMapper::get().lock(
727 const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
728 if (err) {
729 ALOGE("failed transaction: lock(YCBCR_P010)");
730 return C2_CORRUPTED;
731 }
732 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
733 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer + stride * 2 * rect.height();
734 addr[C2PlanarLayout::PLANE_V] = addr[C2PlanarLayout::PLANE_U] + 2;
735 layout->type = C2PlanarLayout::TYPE_YUV;
736 layout->numPlanes = 3;
737 layout->rootPlanes = 2;
738 layout->planes[C2PlanarLayout::PLANE_Y] = {
739 C2PlaneInfo::CHANNEL_Y, // channel
740 2, // colInc
741 static_cast<int32_t>(2 * stride), // rowInc
742 1, // mColSampling
743 1, // mRowSampling
744 16, // allocatedDepth
745 10, // bitDepth
746 6, // rightShift
747 kEndianness, // endianness
748 C2PlanarLayout::PLANE_Y, // rootIx
749 0, // offset
750 };
751 layout->planes[C2PlanarLayout::PLANE_U] = {
752 C2PlaneInfo::CHANNEL_CB, // channel
753 4, // colInc
754 static_cast<int32_t>(2 * stride), // rowInc
755 2, // mColSampling
756 2, // mRowSampling
757 16, // allocatedDepth
758 10, // bitDepth
759 6, // rightShift
760 kEndianness, // endianness
761 C2PlanarLayout::PLANE_U, // rootIx
762 0, // offset
763 };
764 layout->planes[C2PlanarLayout::PLANE_V] = {
765 C2PlaneInfo::CHANNEL_CR, // channel
766 4, // colInc
767 static_cast<int32_t>(2 * stride), // rowInc
768 2, // mColSampling
769 2, // mRowSampling
770 16, // allocatedDepth
771 10, // bitDepth
772 6, // rightShift
773 kEndianness, // endianness
774 C2PlanarLayout::PLANE_U, // rootIx
775 2, // offset
776 };
777 break;
778 }
779
780 default: {
781 // We don't know what it is, let's try to lock it with gralloc4
782 android_ycbcr ycbcrLayout;
783 if (isAtLeastT()) {
784 c2_status_t status = Gralloc4Mapper_lock(
785 const_cast<native_handle_t*>(buffer), grallocUsage, rect, layout, addr);
786 if (status == C2_OK) {
787 break;
788 }
789 }
790
791 // fallback to lockYCbCr
792 status_t err = GraphicBufferMapper::get().lockYCbCr(
793 const_cast<native_handle_t*>(buffer), grallocUsage, rect, &ycbcrLayout);
794 if (err == OK && ycbcrLayout.y && ycbcrLayout.cb && ycbcrLayout.cr
795 && ycbcrLayout.ystride > 0
796 && ycbcrLayout.cstride > 0
797 && ycbcrLayout.chroma_step > 0) {
798 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
799 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
800 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
801 layout->type = C2PlanarLayout::TYPE_YUV;
802 layout->numPlanes = 3;
803 layout->rootPlanes = 3;
804 layout->planes[C2PlanarLayout::PLANE_Y] = {
805 C2PlaneInfo::CHANNEL_Y, // channel
806 1, // colInc
807 (int32_t)ycbcrLayout.ystride, // rowInc
808 1, // mColSampling
809 1, // mRowSampling
810 8, // allocatedDepth
811 8, // bitDepth
812 0, // rightShift
813 C2PlaneInfo::NATIVE, // endianness
814 C2PlanarLayout::PLANE_Y, // rootIx
815 0, // offset
816 };
817 layout->planes[C2PlanarLayout::PLANE_U] = {
818 C2PlaneInfo::CHANNEL_CB, // channel
819 (int32_t)ycbcrLayout.chroma_step, // colInc
820 (int32_t)ycbcrLayout.cstride, // rowInc
821 2, // mColSampling
822 2, // mRowSampling
823 8, // allocatedDepth
824 8, // bitDepth
825 0, // rightShift
826 C2PlaneInfo::NATIVE, // endianness
827 C2PlanarLayout::PLANE_U, // rootIx
828 0, // offset
829 };
830 layout->planes[C2PlanarLayout::PLANE_V] = {
831 C2PlaneInfo::CHANNEL_CR, // channel
832 (int32_t)ycbcrLayout.chroma_step, // colInc
833 (int32_t)ycbcrLayout.cstride, // rowInc
834 2, // mColSampling
835 2, // mRowSampling
836 8, // allocatedDepth
837 8, // bitDepth
838 0, // rightShift
839 C2PlaneInfo::NATIVE, // endianness
840 C2PlanarLayout::PLANE_V, // rootIx
841 0, // offset
842 };
843 break;
844 }
845
846 // We really don't know what this is; lock the buffer and pass it through ---
847 // the client may know how to interpret it.
848
849 // unlock previous allocation if it was successful
850 if (err == OK) {
851 err = GraphicBufferMapper::get().unlock(buffer);
852 if (err) {
853 ALOGE("failed transaction: unlock");
854 return C2_CORRUPTED;
855 }
856 }
857
858 void *pointer = nullptr;
859 err = GraphicBufferMapper::get().lock(
860 const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
861 if (err) {
862 ALOGE("failed transaction: lock(??? %x)", format);
863 return C2_CORRUPTED;
864 }
865 addr[0] = (uint8_t *)pointer;
866 layout->type = C2PlanarLayout::TYPE_UNKNOWN;
867 layout->numPlanes = 1;
868 layout->rootPlanes = 1;
869 layout->planes[0] = {
870 // TODO: CHANNEL_UNKNOWN?
871 C2PlaneInfo::channel_t(0xFF), // channel
872 1, // colInc
873 int32_t(stride), // rowInc
874 1, // mColSampling
875 1, // mRowSampling
876 8, // allocatedDepth
877 8, // bitDepth
878 0, // rightShift
879 C2PlaneInfo::NATIVE, // endianness
880 0, // rootIx
881 0, // offset
882 };
883 break;
884 }
885 }
886 return C2_OK;
887 }
888
HandleInterleavedPlanes(C2PlanarLayout * layout,uint8_t ** addr)889 static void HandleInterleavedPlanes(
890 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
891 if (layout->type == C2PlanarLayout::TYPE_YUV && layout->rootPlanes == 3) {
892 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
893 intptr_t uvColInc = layout->planes[C2PlanarLayout::PLANE_U].colInc;
894 if (uvOffset > 0 && uvOffset < uvColInc) {
895 layout->rootPlanes = 2;
896 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
897 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
898 } else if (uvOffset < 0 && uvOffset > -uvColInc) {
899 layout->rootPlanes = 2;
900 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
901 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
902 }
903 }
904 }
905
906 } // unnamed namespace
907
908
UnwrapNativeCodec2GrallocHandle(const C2Handle * const handle)909 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
910 if (handle == nullptr) {
911 return nullptr;
912 }
913 if (C2AllocatorGralloc::CheckHandle(handle)) {
914 return C2HandleGralloc::UnwrapNativeHandle(handle);
915 }
916 if (C2AllocatorAhwb::CheckHandle(handle)) {
917 return C2HandleAhwb::UnwrapNativeHandle(handle);
918 }
919 ALOGE("tried to unwrap non c2 compatible handle");
920 return nullptr;
921 }
922
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)923 C2Handle *WrapNativeCodec2GrallocHandle(
924 const native_handle_t *const handle,
925 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
926 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
927 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
928 generation, igbp_id, igbp_slot);
929 }
930
ExtractFormatFromCodec2GrallocHandle(const C2Handle * const handle)931 uint32_t ExtractFormatFromCodec2GrallocHandle(const C2Handle *const handle) {
932 if (C2AllocatorGralloc::CheckHandle(handle)) {
933 return C2HandleGralloc::getPixelFormat(handle);
934 }
935 if (C2AllocatorAhwb::CheckHandle(handle)) {
936 return C2HandleAhwb::getPixelFormat(handle);
937 }
938 ALOGE("tried to extract pixelformat from non c2 compatible handle");
939 return 0;
940 }
941
ExtractMetadataFromCodec2GrallocHandle(const C2Handle * const handle,uint32_t * width,uint32_t * height,uint32_t * format,uint64_t * usage,uint32_t * stride)942 bool ExtractMetadataFromCodec2GrallocHandle(
943 const C2Handle *const handle,
944 uint32_t *width, uint32_t *height, uint32_t *format, uint64_t *usage, uint32_t *stride) {
945 if (handle == nullptr) {
946 ALOGE("ExtractMetadata from nullptr");
947 return false;
948 }
949 if (C2AllocatorGralloc::CheckHandle(handle)) {
950 uint32_t generation;
951 uint64_t igbp_id;
952 uint32_t igbp_slot;
953 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
954 &generation, &igbp_id, &igbp_slot);
955 return true;
956 }
957 if (C2AllocatorAhwb::CheckHandle(handle)) {
958 uint64_t origId;
959 (void)C2HandleAhwb::Import(handle, width, height, format, usage, stride, &origId);
960 return true;
961 }
962 ALOGE("ExtractMetadata from non compatible handle");
963 return false;
964 }
965
MigrateNativeCodec2GrallocHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)966 bool MigrateNativeCodec2GrallocHandle(
967 native_handle_t *handle,
968 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
969 return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
970 }
971
972
973
974 class C2AllocationGralloc : public C2GraphicAllocation {
975 public:
976 virtual ~C2AllocationGralloc() override;
977
978 virtual c2_status_t map(
979 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
980 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
981 virtual c2_status_t unmap(
982 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
getAllocatorId() const983 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
handle() const984 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
985 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
986
987 // internal methods
988 // |handle| will be moved.
989
990 C2AllocationGralloc(
991 uint32_t width, uint32_t height,
992 uint32_t format, uint32_t layerCount,
993 uint64_t grallocUsage, uint32_t stride,
994 hidl_handle &hidlHandle,
995 const C2HandleGralloc *const handle,
996 C2Allocator::id_t allocatorId);
997 int dup() const;
998 c2_status_t status() const;
999
1000 private:
1001 const uint32_t mWidth;
1002 const uint32_t mHeight;
1003 const uint32_t mFormat;
1004 const uint32_t mLayerCount;
1005 const uint64_t mGrallocUsage;
1006 const uint32_t mStride;
1007 const hidl_handle mHidlHandle;
1008 const C2HandleGralloc *mHandle;
1009 buffer_handle_t mBuffer;
1010 const C2HandleGralloc *mLockedHandle;
1011 bool mLocked;
1012 C2Allocator::id_t mAllocatorId;
1013 std::mutex mMappedLock;
1014 };
1015
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)1016 C2AllocationGralloc::C2AllocationGralloc(
1017 uint32_t width, uint32_t height,
1018 uint32_t format, uint32_t layerCount,
1019 uint64_t grallocUsage, uint32_t stride,
1020 hidl_handle &hidlHandle,
1021 const C2HandleGralloc *const handle,
1022 C2Allocator::id_t allocatorId)
1023 : C2GraphicAllocation(width, height),
1024 mWidth(width),
1025 mHeight(height),
1026 mFormat(format),
1027 mLayerCount(layerCount),
1028 mGrallocUsage(grallocUsage),
1029 mStride(stride),
1030 mHidlHandle(std::move(hidlHandle)),
1031 mHandle(handle),
1032 mBuffer(nullptr),
1033 mLockedHandle(nullptr),
1034 mLocked(false),
1035 mAllocatorId(allocatorId) {
1036 }
1037
~C2AllocationGralloc()1038 C2AllocationGralloc::~C2AllocationGralloc() {
1039 if (mBuffer && mLocked) {
1040 // implementation ignores address and rect
1041 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
1042 unmap(addr, C2Rect(), nullptr);
1043 }
1044 if (mBuffer) {
1045 status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
1046 if (err) {
1047 ALOGE("failed transaction: freeBuffer");
1048 }
1049 }
1050 if (mHandle) {
1051 native_handle_delete(
1052 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
1053 }
1054 if (mLockedHandle) {
1055 native_handle_delete(
1056 const_cast<native_handle_t *>(
1057 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
1058 }
1059 }
1060
map(C2Rect c2Rect,C2MemoryUsage usage,C2Fence * fence,C2PlanarLayout * layout,uint8_t ** addr)1061 c2_status_t C2AllocationGralloc::map(
1062 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
1063 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
1064 const Rect rect{(int32_t)c2Rect.left, (int32_t)c2Rect.top,
1065 (int32_t)(c2Rect.left + c2Rect.width) /* right */,
1066 (int32_t)(c2Rect.top + c2Rect.height) /* bottom */};
1067
1068 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
1069 ALOGV("mapping buffer with usage %#llx => %#llx",
1070 (long long)usage.expected, (long long)grallocUsage);
1071
1072 // TODO
1073 (void)fence;
1074
1075 std::lock_guard<std::mutex> lock(mMappedLock);
1076 if (mBuffer && mLocked) {
1077 ALOGD("already mapped");
1078 return C2_DUPLICATE;
1079 }
1080 if (!layout || !addr) {
1081 ALOGD("wrong param");
1082 return C2_BAD_VALUE;
1083 }
1084
1085 if (!mBuffer) {
1086 status_t err = GraphicBufferMapper::get().importBuffer(
1087 mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
1088 mFormat, mGrallocUsage, mStride, &mBuffer);
1089 if (err) {
1090 ALOGE("failed transaction: importBuffer");
1091 return C2_CORRUPTED;
1092 }
1093 if (mBuffer == nullptr) {
1094 ALOGD("importBuffer returned null buffer");
1095 return C2_CORRUPTED;
1096 }
1097 uint32_t generation = 0;
1098 uint64_t igbp_id = 0;
1099 uint32_t igbp_slot = 0;
1100 if (mHandle) {
1101 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
1102 }
1103
1104 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
1105 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
1106 mStride, generation, igbp_id, igbp_slot);
1107 }
1108
1109 c2_status_t ret = PopulatePlaneLayout(
1110 mBuffer, rect, mFormat, grallocUsage, mStride, layout, addr);
1111 if (ret != C2_OK) {
1112 return ret;
1113 }
1114 mLocked = true;
1115
1116 HandleInterleavedPlanes(layout, addr);
1117
1118 ALOGV("C2AllocationGralloc::map: layout: type=%d numPlanes=%d rootPlanes=%d",
1119 layout->type, layout->numPlanes, layout->rootPlanes);
1120 for (int i = 0; i < layout->numPlanes; ++i) {
1121 const C2PlaneInfo &plane = layout->planes[i];
1122 ALOGV("C2AllocationGralloc::map: plane[%d]: colInc=%d rowInc=%d rootIx=%u offset=%u",
1123 i, plane.colInc, plane.rowInc, plane.rootIx, plane.offset);
1124 }
1125
1126 return C2_OK;
1127 }
1128
unmap(uint8_t ** addr,C2Rect rect,C2Fence * fence)1129 c2_status_t C2AllocationGralloc::unmap(
1130 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
1131 // TODO: check addr and size, use fence
1132 (void)addr;
1133 (void)rect;
1134 (void)fence;
1135
1136 std::lock_guard<std::mutex> lock(mMappedLock);
1137 // TODO: fence
1138 status_t err = GraphicBufferMapper::get().unlock(mBuffer);
1139 if (err) {
1140 ALOGE("failed transaction: unlock");
1141 return C2_CORRUPTED;
1142 }
1143
1144 mLocked = false;
1145 return C2_OK;
1146 }
1147
equals(const std::shared_ptr<const C2GraphicAllocation> & other) const1148 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
1149 return other && other->handle() == handle();
1150 }
1151
1152 /* ===================================== GRALLOC ALLOCATOR ==================================== */
1153 class C2AllocatorGralloc::Impl {
1154 public:
1155 Impl(id_t id, bool bufferQueue);
1156
getId() const1157 id_t getId() const {
1158 return mTraits->id;
1159 }
1160
getName() const1161 C2String getName() const {
1162 return mTraits->name;
1163 }
1164
getTraits() const1165 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
1166 return mTraits;
1167 }
1168
1169 c2_status_t newGraphicAllocation(
1170 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1171 std::shared_ptr<C2GraphicAllocation> *allocation);
1172
1173 c2_status_t priorGraphicAllocation(
1174 const C2Handle *handle,
1175 std::shared_ptr<C2GraphicAllocation> *allocation);
1176
status() const1177 c2_status_t status() const { return mInit; }
1178
1179 private:
1180 std::shared_ptr<C2Allocator::Traits> mTraits;
1181 c2_status_t mInit;
1182 const bool mBufferQueue;
1183 };
1184
_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)1185 void _UnwrapNativeCodec2GrallocMetadata(
1186 const C2Handle *const handle,
1187 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
1188 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
1189 if (C2AllocatorGralloc::CheckHandle(handle)) {
1190 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
1191 generation, igbp_id, igbp_slot);
1192 return;
1193 }
1194 if (C2AllocatorAhwb::CheckHandle(handle)) {
1195 uint64_t origId;
1196 (void)C2HandleAhwb::Import(handle, width, height, format, usage, stride, &origId);
1197 return;
1198 }
1199 ALOGE("Tried to extract metadata from non c2 compatible handle");
1200 }
1201
Impl(id_t id,bool bufferQueue)1202 C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
1203 : mInit(C2_OK), mBufferQueue(bufferQueue) {
1204 // TODO: get this from allocator
1205 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
1206 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
1207 mTraits = std::make_shared<C2Allocator::Traits>(traits);
1208 }
1209
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,const C2MemoryUsage & usage,std::shared_ptr<C2GraphicAllocation> * allocation)1210 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
1211 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1212 std::shared_ptr<C2GraphicAllocation> *allocation) {
1213 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
1214 ALOGV("allocating buffer with usage %#llx => %#llx",
1215 (long long)usage.expected, (long long)grallocUsage);
1216
1217 buffer_handle_t buffer;
1218
1219 uint32_t stride = 0;
1220
1221 status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
1222 1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
1223 if (err) {
1224 ALOGE("failed transaction: allocate");
1225 return C2_CORRUPTED;
1226 }
1227
1228 hidl_handle hidlHandle;
1229 hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
1230
1231 allocation->reset(new C2AllocationGralloc(
1232 width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
1233 C2HandleGralloc::WrapAndMoveNativeHandle(
1234 hidlHandle, width, height,
1235 format, grallocUsage, stride,
1236 0, 0, mBufferQueue ? ~0 : 0),
1237 mTraits->id));
1238 return C2_OK;
1239 }
1240
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)1241 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
1242 const C2Handle *handle,
1243 std::shared_ptr<C2GraphicAllocation> *allocation) {
1244
1245 uint32_t generation;
1246 uint64_t igbp_id;
1247 uint32_t igbp_slot;
1248
1249 uint32_t width;
1250 uint32_t height;
1251 uint32_t format;
1252 uint32_t layerCount = 1;
1253 uint64_t grallocUsage;
1254 uint32_t stride;
1255
1256 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
1257 handle, &width, &height, &format, &grallocUsage, &stride,
1258 &generation, &igbp_id, &igbp_slot);
1259 if (grallocHandle == nullptr) {
1260 return C2_BAD_VALUE;
1261 }
1262
1263 hidl_handle hidlHandle;
1264 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
1265
1266 allocation->reset(new C2AllocationGralloc(
1267 width, height, format, layerCount,
1268 grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
1269 return C2_OK;
1270 }
1271
C2AllocatorGralloc(id_t id,bool bufferQueue)1272 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
1273 : mImpl(new Impl(id, bufferQueue)) {}
1274
~C2AllocatorGralloc()1275 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
1276
getId() const1277 C2Allocator::id_t C2AllocatorGralloc::getId() const {
1278 return mImpl->getId();
1279 }
1280
getName() const1281 C2String C2AllocatorGralloc::getName() const {
1282 return mImpl->getName();
1283 }
1284
getTraits() const1285 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
1286 return mImpl->getTraits();
1287 }
1288
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicAllocation> * allocation)1289 c2_status_t C2AllocatorGralloc::newGraphicAllocation(
1290 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
1291 std::shared_ptr<C2GraphicAllocation> *allocation) {
1292 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
1293 }
1294
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)1295 c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
1296 const C2Handle *handle,
1297 std::shared_ptr<C2GraphicAllocation> *allocation) {
1298 return mImpl->priorGraphicAllocation(handle, allocation);
1299 }
1300
status() const1301 c2_status_t C2AllocatorGralloc::status() const {
1302 return mImpl->status();
1303 }
1304
1305 // static
CheckHandle(const C2Handle * const o)1306 bool C2AllocatorGralloc::CheckHandle(const C2Handle* const o) {
1307 return C2HandleGralloc::IsValid(o);
1308 }
1309
1310
WrapNativeCodec2AhwbHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint64_t origId)1311 C2Handle *WrapNativeCodec2AhwbHandle(
1312 const native_handle_t *const handle,
1313 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
1314 uint64_t origId) {
1315 return C2HandleAhwb::WrapNativeHandle(handle, width, height, format, usage, stride,
1316 origId);
1317 }
1318
1319 class C2AllocationAhwb : public C2GraphicAllocation {
1320 public:
1321 virtual ~C2AllocationAhwb() override;
1322
1323 virtual c2_status_t map(
1324 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
1325 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
1326 virtual c2_status_t unmap(
1327 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
getAllocatorId() const1328 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
handle() const1329 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
1330 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
1331
1332 // internal methods
1333 // |handle| will be moved.
1334
1335 C2AllocationAhwb(
1336 uint32_t width, uint32_t height,
1337 uint32_t format, uint32_t layerCount,
1338 uint64_t grallocUsage, uint32_t stride,
1339 const C2HandleAhwb *const handle,
1340 C2Allocator::id_t allocatorId);
1341 int dup() const;
1342 c2_status_t status() const;
1343
1344 private:
1345 const uint32_t mWidth;
1346 const uint32_t mHeight;
1347 const uint32_t mFormat;
1348 const uint32_t mLayerCount;
1349 const uint64_t mGrallocUsage;
1350 const uint32_t mStride;
1351 const native_handle_t *mRawHandle;
1352 const C2HandleAhwb *mHandle;
1353 buffer_handle_t mBuffer;
1354 const C2HandleAhwb *mLockedHandle;
1355 bool mLocked;
1356 C2Allocator::id_t mAllocatorId;
1357 std::mutex mMappedLock;
1358 };
1359
C2AllocationAhwb(uint32_t width,uint32_t height,uint32_t format,uint32_t layerCount,uint64_t grallocUsage,uint32_t stride,const C2HandleAhwb * const handle,C2Allocator::id_t allocatorId)1360 C2AllocationAhwb::C2AllocationAhwb(
1361 uint32_t width, uint32_t height,
1362 uint32_t format, uint32_t layerCount,
1363 uint64_t grallocUsage, uint32_t stride,
1364 const C2HandleAhwb *const handle,
1365 C2Allocator::id_t allocatorId)
1366 : C2GraphicAllocation(width, height),
1367 mWidth(width),
1368 mHeight(height),
1369 mFormat(format),
1370 mLayerCount(layerCount),
1371 mGrallocUsage(grallocUsage),
1372 mStride(stride),
1373 mRawHandle(C2HandleAhwb::UnwrapNativeHandle(handle)),
1374 mHandle(handle),
1375 mBuffer(nullptr),
1376 mLockedHandle(nullptr),
1377 mLocked(false),
1378 mAllocatorId(allocatorId) {
1379 }
1380
~C2AllocationAhwb()1381 C2AllocationAhwb::~C2AllocationAhwb() {
1382 if (mBuffer && mLocked) {
1383 // implementation ignores address and rect
1384 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
1385 unmap(addr, C2Rect(), nullptr);
1386 }
1387 if (mBuffer) {
1388 status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
1389 if (err) {
1390 ALOGE("failed transaction: freeBuffer");
1391 }
1392 }
1393 if (mRawHandle) {
1394 native_handle_close(
1395 const_cast<native_handle_t *>(
1396 reinterpret_cast<const native_handle_t *>(mRawHandle)));
1397 native_handle_delete(
1398 const_cast<native_handle_t *>(
1399 reinterpret_cast<const native_handle_t *>(mRawHandle)));
1400 }
1401 if (mHandle) {
1402 native_handle_delete(
1403 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
1404 }
1405 if (mLockedHandle) {
1406 native_handle_delete(
1407 const_cast<native_handle_t *>(
1408 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
1409 }
1410 }
1411
map(C2Rect c2Rect,C2MemoryUsage usage,C2Fence * fence,C2PlanarLayout * layout,uint8_t ** addr)1412 c2_status_t C2AllocationAhwb::map(
1413 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
1414 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
1415 const Rect rect{(int32_t)c2Rect.left, (int32_t)c2Rect.top,
1416 (int32_t)(c2Rect.left + c2Rect.width) /* right */,
1417 (int32_t)(c2Rect.top + c2Rect.height) /* bottom */};
1418
1419 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
1420 ALOGV("mapping buffer with usage %#llx => %#llx",
1421 (long long)usage.expected, (long long)grallocUsage);
1422
1423 // TODO
1424 (void)fence;
1425
1426 std::lock_guard<std::mutex> lock(mMappedLock);
1427 if (mBuffer && mLocked) {
1428 ALOGD("already mapped");
1429 return C2_DUPLICATE;
1430 }
1431 if (!layout || !addr) {
1432 ALOGD("wrong param");
1433 return C2_BAD_VALUE;
1434 }
1435
1436 if (!mBuffer) {
1437 // TODO: libui/libgui dependency removal (b/214400477)
1438 status_t err = GraphicBufferMapper::get().importBuffer(
1439 mRawHandle, mWidth, mHeight, mLayerCount,
1440 mFormat, mGrallocUsage, mStride, &mBuffer);
1441 if (err) {
1442 ALOGE("failed transaction: importBuffer");
1443 return C2_CORRUPTED;
1444 }
1445 if (mBuffer == nullptr) {
1446 ALOGD("importBuffer returned null buffer");
1447 return C2_CORRUPTED;
1448 }
1449 uint64_t origId = 0;
1450 if (mHandle) {
1451 mHandle->getOrigId(&origId);
1452 }
1453
1454 mLockedHandle = C2HandleAhwb::WrapAndMoveNativeHandle(
1455 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
1456 mStride, origId);
1457 }
1458
1459 c2_status_t ret = PopulatePlaneLayout(
1460 mBuffer, rect, mFormat, grallocUsage, mStride, layout, addr);
1461 if (ret != C2_OK) {
1462 return ret;
1463 }
1464 mLocked = true;
1465
1466 HandleInterleavedPlanes(layout, addr);
1467
1468 ALOGV("C2AllocationGralloc::map: layout: type=%d numPlanes=%d rootPlanes=%d",
1469 layout->type, layout->numPlanes, layout->rootPlanes);
1470 for (int i = 0; i < layout->numPlanes; ++i) {
1471 const C2PlaneInfo &plane = layout->planes[i];
1472 ALOGV("C2AllocationGralloc::map: plane[%d]: colInc=%d rowInc=%d rootIx=%u offset=%u",
1473 i, plane.colInc, plane.rowInc, plane.rootIx, plane.offset);
1474 }
1475
1476 return C2_OK;
1477 }
1478
unmap(uint8_t ** addr,C2Rect rect,C2Fence * fence)1479 c2_status_t C2AllocationAhwb::unmap(
1480 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
1481 // TODO: check addr and size, use fence
1482 (void)addr;
1483 (void)rect;
1484 (void)fence;
1485
1486 std::lock_guard<std::mutex> lock(mMappedLock);
1487 // TODO: fence
1488 status_t err = GraphicBufferMapper::get().unlock(mBuffer);
1489 if (err) {
1490 ALOGE("failed transaction: unlock");
1491 return C2_CORRUPTED;
1492 }
1493
1494 mLocked = false;
1495 return C2_OK;
1496 }
1497
equals(const std::shared_ptr<const C2GraphicAllocation> & other) const1498 bool C2AllocationAhwb::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
1499 return other && other->handle() == handle();
1500 }
1501
1502 /* ===================================== AHARDWAREBUFFER ALLOCATOR ============================= */
1503 class C2AllocatorAhwb::Impl {
1504 public:
1505 Impl(id_t id);
1506
getId() const1507 id_t getId() const {
1508 return mTraits->id;
1509 }
1510
getName() const1511 C2String getName() const {
1512 return mTraits->name;
1513 }
1514
getTraits() const1515 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
1516 return mTraits;
1517 }
1518
1519 c2_status_t newGraphicAllocation(
1520 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1521 std::shared_ptr<C2GraphicAllocation> *allocation);
1522
1523 c2_status_t priorGraphicAllocation(
1524 const C2Handle *handle,
1525 std::shared_ptr<C2GraphicAllocation> *allocation);
1526
status() const1527 c2_status_t status() const { return mInit; }
1528
1529 private:
1530 std::shared_ptr<C2Allocator::Traits> mTraits;
1531 c2_status_t mInit;
1532 };
1533
Impl(id_t id)1534 C2AllocatorAhwb::Impl::Impl(id_t id)
1535 : mInit(C2_OK) {
1536 // TODO: get this from allocator
1537 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
1538 Traits traits = { "android.allocator.ahwb", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
1539 mTraits = std::make_shared<C2Allocator::Traits>(traits);
1540 }
1541
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,const C2MemoryUsage & usage,std::shared_ptr<C2GraphicAllocation> * allocation)1542 c2_status_t C2AllocatorAhwb::Impl::newGraphicAllocation(
1543 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1544 std::shared_ptr<C2GraphicAllocation> *allocation) {
1545 // TODO: for client side usage
1546 // HAL side Ahwb allocation should be done via IGBA currently.
1547 (void) width;
1548 (void) height;
1549 (void) format;
1550 (void) usage;
1551 (void) allocation;
1552 return C2_OMITTED;
1553 }
1554
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)1555 c2_status_t C2AllocatorAhwb::Impl::priorGraphicAllocation(
1556 const C2Handle *handle,
1557 std::shared_ptr<C2GraphicAllocation> *allocation) {
1558
1559 uint32_t width;
1560 uint32_t height;
1561 uint32_t format;
1562 uint32_t layerCount = 1;
1563 uint64_t grallocUsage;
1564 uint32_t stride;
1565 uint64_t origId;
1566
1567 const C2HandleAhwb *ahwbHandle = C2HandleAhwb::Import(
1568 handle, &width, &height, &format, &grallocUsage, &stride, &origId);
1569 if (ahwbHandle == nullptr) {
1570 return C2_BAD_VALUE;
1571 }
1572
1573 allocation->reset(new C2AllocationAhwb(
1574 width, height, format, layerCount,
1575 grallocUsage, stride, ahwbHandle, mTraits->id));
1576 return C2_OK;
1577 }
1578
C2AllocatorAhwb(id_t id)1579 C2AllocatorAhwb::C2AllocatorAhwb(id_t id)
1580 : mImpl(new Impl(id)) {}
1581
~C2AllocatorAhwb()1582 C2AllocatorAhwb::~C2AllocatorAhwb() { delete mImpl; }
1583
getId() const1584 C2Allocator::id_t C2AllocatorAhwb::getId() const {
1585 return mImpl->getId();
1586 }
1587
getName() const1588 C2String C2AllocatorAhwb::getName() const {
1589 return mImpl->getName();
1590 }
1591
getTraits() const1592 std::shared_ptr<const C2Allocator::Traits> C2AllocatorAhwb::getTraits() const {
1593 return mImpl->getTraits();
1594 }
1595
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicAllocation> * allocation)1596 c2_status_t C2AllocatorAhwb::newGraphicAllocation(
1597 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
1598 std::shared_ptr<C2GraphicAllocation> *allocation) {
1599 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
1600 }
1601
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)1602 c2_status_t C2AllocatorAhwb::priorGraphicAllocation(
1603 const C2Handle *handle,
1604 std::shared_ptr<C2GraphicAllocation> *allocation) {
1605 return mImpl->priorGraphicAllocation(handle, allocation);
1606 }
1607
status() const1608 c2_status_t C2AllocatorAhwb::status() const {
1609 return mImpl->status();
1610 }
1611
1612 // static
CheckHandle(const C2Handle * const o)1613 bool C2AllocatorAhwb::CheckHandle(const C2Handle* const o) {
1614 return C2HandleAhwb::IsValid(o);
1615 }
1616 } // namespace android
1617