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