blob: e04c637a1b4b40e81a1438ee6200b3ee8cfa96c5 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "C2AllocatorGralloc"
19#include <utils/Log.h>
20
Marissa Wall2a24a302019-11-25 11:19:18 -080021#include <mutex>
22
Praveen Chavan34493f12021-02-18 00:51:50 -080023#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
Marissa Wall2a24a302019-11-25 11:19:18 -080024#include <android/hardware/graphics/common/1.2/types.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080025#include <cutils/native_handle.h>
Tao Wu9d482892023-09-15 02:28:41 +000026#include <drm/drm_fourcc.h>
Praveen Chavan34493f12021-02-18 00:51:50 -080027#include <gralloctypes/Gralloc4.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080028#include <hardware/gralloc.h>
Marissa Wall2a24a302019-11-25 11:19:18 -080029#include <ui/GraphicBufferAllocator.h>
30#include <ui/GraphicBufferMapper.h>
Chih-Yu Huang486aa5d2020-10-13 16:22:58 +090031#include <ui/Rect.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080032
33#include <C2AllocatorGralloc.h>
34#include <C2Buffer.h>
Praveen Chavan34493f12021-02-18 00:51:50 -080035#include <C2Debug.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080036#include <C2PlatformSupport.h>
37
Marissa Wall2a24a302019-11-25 11:19:18 -080038using ::android::hardware::hidl_handle;
39using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
40
Pawin Vongmasa36653902018-11-15 00:10:25 -080041namespace android {
42
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070043namespace /* unnamed */ {
Pawin Vongmasa36653902018-11-15 00:10:25 -080044 enum : uint64_t {
45 /**
46 * Usage mask that is passed through from gralloc to Codec 2.0 usage.
47 */
48 PASSTHROUGH_USAGE_MASK =
Charlie Chen49d3fe72021-03-25 20:02:37 +080049 ~static_cast<uint64_t>(GRALLOC_USAGE_SW_READ_MASK |
50 GRALLOC_USAGE_SW_WRITE_MASK |
51 GRALLOC_USAGE_PROTECTED)
Pawin Vongmasa36653902018-11-15 00:10:25 -080052 };
53
54 // verify that passthrough mask is within the platform mask
55 static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070056} // unnamed
Pawin Vongmasa36653902018-11-15 00:10:25 -080057
Harish Mahendrakar7dc54f92022-06-30 20:36:23 -070058static bool isAtLeastT() {
59 return android_get_device_api_level() >= __ANDROID_API_T__;
60}
61
Pawin Vongmasa36653902018-11-15 00:10:25 -080062C2MemoryUsage 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
71uint64_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
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070079namespace /* unnamed */ {
80
Pawin Vongmasa36653902018-11-15 00:10:25 -080081/* ===================================== GRALLOC ALLOCATION ==================================== */
Pawin Vongmasa36653902018-11-15 00:10:25 -080082bool 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
95class C2HandleGralloc : public C2Handle {
96private:
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
John Stultz653ddd12020-09-19 05:26:24 +0000117 const ExtraData* GetExtraData(const C2Handle *const handle) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800118 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
John Stultz653ddd12020-09-19 05:26:24 +0000128 ExtraData *GetExtraData(C2Handle *const handle) {
129 return const_cast<ExtraData *>(GetExtraData(const_cast<const C2Handle *const>(handle)));
Pawin Vongmasa36653902018-11-15 00:10:25 -0800130 }
131
132public:
133 void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
John Stultz653ddd12020-09-19 05:26:24 +0000134 const ExtraData *ed = GetExtraData(this);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800135 *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
John Stultz653ddd12020-09-19 05:26:24 +0000140 static bool IsValid(const C2Handle *const o) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800141 if (o == nullptr) { // null handle is always valid
142 return true;
143 }
John Stultz653ddd12020-09-19 05:26:24 +0000144 const ExtraData *xd = GetExtraData(o);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800145 // we cannot validate width/height/format/usage without accessing gralloc driver
146 return xd != nullptr && xd->magic == MAGIC;
147 }
148
Sungtak Leea4d13be2019-01-23 15:24:46 -0800149 static C2HandleGralloc* WrapAndMoveNativeHandle(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800150 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));
John Stultz653ddd12020-09-19 05:26:24 +0000166 *GetExtraData(res) = xd;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800167 }
168 return reinterpret_cast<C2HandleGralloc *>(res);
169 }
170
Sungtak Leea4d13be2019-01-23 15:24:46 -0800171 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
Sungtak Lee08515812019-06-05 11:16:32 -0700191 static bool MigrateNativeHandle(
192 native_handle_t *handle,
193 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
John Stultz653ddd12020-09-19 05:26:24 +0000194 if (handle == nullptr || !IsValid(handle)) {
Sungtak Lee08515812019-06-05 11:16:32 -0700195 return false;
196 }
John Stultz653ddd12020-09-19 05:26:24 +0000197 ExtraData *ed = GetExtraData(handle);
Sungtak Lee08515812019-06-05 11:16:32 -0700198 if (!ed) return false;
199 ed->generation = generation;
200 ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
201 ed->igbp_id_hi = uint32_t(igbp_id >> 32);
202 ed->igbp_slot = igbp_slot;
203 return true;
204 }
205
206
Pawin Vongmasa36653902018-11-15 00:10:25 -0800207 static native_handle_t* UnwrapNativeHandle(
208 const C2Handle *const handle) {
John Stultz653ddd12020-09-19 05:26:24 +0000209 const ExtraData *xd = GetExtraData(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800210 if (xd == nullptr || xd->magic != MAGIC) {
211 return nullptr;
212 }
213 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
214 if (res != nullptr) {
215 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
216 }
217 return res;
218 }
219
Pawin Vongmasa36653902018-11-15 00:10:25 -0800220 static const C2HandleGralloc* Import(
221 const C2Handle *const handle,
222 uint32_t *width, uint32_t *height, uint32_t *format,
223 uint64_t *usage, uint32_t *stride,
224 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
John Stultz653ddd12020-09-19 05:26:24 +0000225 const ExtraData *xd = GetExtraData(handle);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800226 if (xd == nullptr) {
227 return nullptr;
228 }
229 *width = xd->width;
230 *height = xd->height;
231 *format = xd->format;
232 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
233 *stride = xd->stride;
234 *generation = xd->generation;
235 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
236 *igbp_slot = xd->igbp_slot;
237 return reinterpret_cast<const C2HandleGralloc *>(handle);
238 }
239};
240
Sungtak Lee1a67c9d2023-09-14 19:41:00 +0000241class C2HandleAhwb : public C2Handle {
242private:
243 // TODO: remove extradata and use AHardwareBuffer directly.
244 struct ExtraData {
245 uint32_t width;
246 uint32_t height;
247 uint32_t format;
248 uint32_t usage_lo;
249 uint32_t usage_hi;
250 uint32_t stride;
251 uint32_t origId_lo;
252 uint32_t origId_hi;
253 uint32_t magic;
254 };
255
256 enum {
257 NUM_INTS = sizeof(ExtraData) / sizeof(int),
258 };
259 const static uint32_t MAGIC = '\xc2hw\x00';
260
261 static
262 const ExtraData* GetExtraData(const C2Handle *const handle) {
263 if (handle == nullptr
264 || native_handle_is_invalid(handle)
265 || handle->numInts < NUM_INTS) {
266 return nullptr;
267 }
268 return reinterpret_cast<const ExtraData*>(
269 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
270 }
271
272 static
273 ExtraData *GetExtraData(C2Handle *const handle) {
274 return const_cast<ExtraData *>(GetExtraData(const_cast<const C2Handle *const>(handle)));
275 }
276
277public:
278 void getOrigId(uint64_t *origId) const {
279 const ExtraData *ed = GetExtraData(this);
280 *origId = unsigned(ed->origId_lo) | uint64_t(unsigned(ed->origId_hi)) << 32;
281 }
282
283 static bool IsValid(const C2Handle *const o) {
284 if (o == nullptr) { // null handle is always valid
285 return true;
286 }
287 const ExtraData *xd = GetExtraData(o);
288 // we cannot validate width/height/format/usage without accessing gralloc driver
289 return xd != nullptr && xd->magic == MAGIC;
290 }
291
292 static C2HandleAhwb* WrapAndMoveNativeHandle(
293 const native_handle_t *const handle,
294 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
295 uint32_t stride, uint64_t origId) {
296 //CHECK(handle != nullptr);
297 if (native_handle_is_invalid(handle) || handle->numInts >
298 int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
299 return nullptr;
300 }
301 ExtraData xd = {
302 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
303 stride, uint32_t(origId & 0xFFFFFFFF), uint32_t(origId >> 32), MAGIC
304 };
305 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
306 if (res != nullptr) {
307 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
308 *GetExtraData(res) = xd;
309 }
310 return reinterpret_cast<C2HandleAhwb *>(res);
311 }
312
313 static C2HandleAhwb* WrapNativeHandle(
314 const native_handle_t *const handle,
315 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
316 uint32_t stride, uint64_t origId) {
317 if (handle == nullptr) {
318 return nullptr;
319 }
320 native_handle_t *clone = native_handle_clone(handle);
321 if (clone == nullptr) {
322 return nullptr;
323 }
324 C2HandleAhwb *res = WrapAndMoveNativeHandle(
325 clone, width, height, format, usage, stride, origId);
326 if (res == nullptr) {
327 native_handle_close(clone);
328 }
329 native_handle_delete(clone);
330 return res;
331 }
332
333 static native_handle_t* UnwrapNativeHandle(
334 const C2Handle *const handle) {
335 const ExtraData *xd = GetExtraData(handle);
336 if (xd == nullptr || xd->magic != MAGIC) {
337 return nullptr;
338 }
339 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
340 if (res != nullptr) {
341 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
342 }
343 return res;
344 }
345
346 static const C2HandleAhwb* Import(
347 const C2Handle *const handle,
348 uint32_t *width, uint32_t *height, uint32_t *format,
349 uint64_t *usage, uint32_t *stride,
350 uint64_t *origId) {
351 const ExtraData *xd = GetExtraData(handle);
352 if (xd == nullptr) {
353 return nullptr;
354 }
355 *width = xd->width;
356 *height = xd->height;
357 *format = xd->format;
358 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
359 *stride = xd->stride;
360 *origId = xd->origId_lo | (uint64_t(xd->origId_hi) << 32);
361 return reinterpret_cast<const C2HandleAhwb *>(handle);
362 }
363};
364
Praveen Chavan34493f12021-02-18 00:51:50 -0800365static
366c2_status_t Gralloc4Mapper_lock(native_handle_t *handle, uint64_t usage, const Rect& bounds,
367 C2PlanarLayout *layout, uint8_t **addr) {
368 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
369
370 std::vector<ui::PlaneLayout> planes;
371 // this method is only supported on Gralloc 4 or later
372 status_t err = mapper.getPlaneLayouts(handle, &planes);
373 if (err != NO_ERROR || planes.empty()) {
374 return C2_CANNOT_DO;
375 }
376
377 uint8_t *pointer = nullptr;
378 err = mapper.lock(handle, usage, bounds, (void **)&pointer, nullptr, nullptr);
379 if (err != NO_ERROR || pointer == nullptr) {
380 return C2_CORRUPTED;
381 }
382
383 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
384 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
385
386 layout->type = C2PlanarLayout::TYPE_YUV;
387 layout->numPlanes = 0;
388 layout->rootPlanes = 0;
389
390 for (const ui::PlaneLayout &plane : planes) {
391 layout->rootPlanes++;
392 uint32_t lastOffsetInBits = 0;
Wonsik Kimf12bebc2022-03-24 16:25:03 -0700393 uint32_t rootIx = layout->numPlanes;
Praveen Chavan34493f12021-02-18 00:51:50 -0800394
395 for (const PlaneLayoutComponent &component : plane.components) {
396 if (!gralloc4::isStandardPlaneLayoutComponentType(component.type)) {
Praveen Chavan2c580d92022-02-24 12:23:46 -0800397 mapper.unlock(handle);
Praveen Chavan34493f12021-02-18 00:51:50 -0800398 return C2_CANNOT_DO;
399 }
400
401 uint32_t rightShiftBits = component.offsetInBits - lastOffsetInBits;
402 uint32_t allocatedDepthInBits = component.sizeInBits + rightShiftBits;
403 C2PlanarLayout::plane_index_t planeId;
404 C2PlaneInfo::channel_t channel;
405
406 switch (static_cast<PlaneLayoutComponentType>(component.type.value)) {
407 case PlaneLayoutComponentType::Y:
408 planeId = C2PlanarLayout::PLANE_Y;
409 channel = C2PlaneInfo::CHANNEL_Y;
410 break;
411 case PlaneLayoutComponentType::CB:
412 planeId = C2PlanarLayout::PLANE_U;
413 channel = C2PlaneInfo::CHANNEL_CB;
414 break;
415 case PlaneLayoutComponentType::CR:
416 planeId = C2PlanarLayout::PLANE_V;
417 channel = C2PlaneInfo::CHANNEL_CR;
418 break;
419 default:
Praveen Chavan2c580d92022-02-24 12:23:46 -0800420 mapper.unlock(handle);
Praveen Chavan34493f12021-02-18 00:51:50 -0800421 return C2_CORRUPTED;
422 }
423
424 addr[planeId] = pointer + plane.offsetInBytes + (component.offsetInBits / 8);
425 layout->planes[planeId] = {
426 channel, // channel
427 static_cast<int32_t>(plane.sampleIncrementInBits / 8), // colInc
428 static_cast<int32_t>(plane.strideInBytes), // rowInc
429 static_cast<uint32_t>(plane.horizontalSubsampling), // mColSampling
430 static_cast<uint32_t>(plane.verticalSubsampling), // mRowSampling
431 allocatedDepthInBits, // allocatedDepth (bits)
432 static_cast<uint32_t>(component.sizeInBits), // bitDepth (bits)
433 rightShiftBits, // rightShift (bits)
434 C2PlaneInfo::NATIVE, // endianness
435 rootIx, // rootIx
436 static_cast<uint32_t>(component.offsetInBits / 8), // offset (bytes)
437 };
438
439 layout->numPlanes++;
440 lastOffsetInBits = component.offsetInBits + component.sizeInBits;
Praveen Chavan34493f12021-02-18 00:51:50 -0800441 }
442 }
443 return C2_OK;
444}
445
Sungtak Lee25e33ee2023-09-15 08:06:37 +0000446static c2_status_t PopulatePlaneLayout(
447 buffer_handle_t buffer,
448 const Rect &rect,
449 uint32_t format,
450 uint64_t grallocUsage,
451 uint32_t stride,
452 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
453 // 'NATIVE' on Android means LITTLE_ENDIAN
454 constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
455
456 // Try to resolve IMPLEMENTATION_DEFINED format to accurate format if
457 // possible.
458 uint32_t fourCc;
459 if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
460 !GraphicBufferMapper::get().getPixelFormatFourCC(buffer, &fourCc)) {
461 switch (fourCc) {
462 case DRM_FORMAT_XBGR8888:
463 format = static_cast<uint32_t>(PixelFormat4::RGBX_8888);
464 break;
465 case DRM_FORMAT_ABGR8888:
466 format = static_cast<uint32_t>(PixelFormat4::RGBA_8888);
467 break;
468 default:
469 break;
470 }
471 }
472
473 switch (format) {
474 case static_cast<uint32_t>(PixelFormat4::RGBA_1010102): {
475 // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
476 // Surface. In all other cases it is RGBA. We don't know which case it is here, so
477 // default to YUV for now.
478 void *pointer = nullptr;
479 // TODO: fence
480 status_t err = GraphicBufferMapper::get().lock(
481 const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
482 if (err) {
483 ALOGE("failed transaction: lock(RGBA_1010102)");
484 return C2_CORRUPTED;
485 }
486 // treat as 32-bit values
487 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
488 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
489 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
490 addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
491 layout->type = C2PlanarLayout::TYPE_YUVA;
492 layout->numPlanes = 4;
493 layout->rootPlanes = 1;
494 layout->planes[C2PlanarLayout::PLANE_Y] = {
495 C2PlaneInfo::CHANNEL_Y, // channel
496 4, // colInc
497 static_cast<int32_t>(4 * stride), // rowInc
498 1, // mColSampling
499 1, // mRowSampling
500 32, // allocatedDepth
501 10, // bitDepth
502 10, // rightShift
503 C2PlaneInfo::LITTLE_END, // endianness
504 C2PlanarLayout::PLANE_Y, // rootIx
505 0, // offset
506 };
507 layout->planes[C2PlanarLayout::PLANE_U] = {
508 C2PlaneInfo::CHANNEL_CB, // channel
509 4, // colInc
510 static_cast<int32_t>(4 * stride), // rowInc
511 1, // mColSampling
512 1, // mRowSampling
513 32, // allocatedDepth
514 10, // bitDepth
515 0, // rightShift
516 C2PlaneInfo::LITTLE_END, // endianness
517 C2PlanarLayout::PLANE_Y, // rootIx
518 0, // offset
519 };
520 layout->planes[C2PlanarLayout::PLANE_V] = {
521 C2PlaneInfo::CHANNEL_CR, // channel
522 4, // colInc
523 static_cast<int32_t>(4 * stride), // rowInc
524 1, // mColSampling
525 1, // mRowSampling
526 32, // allocatedDepth
527 10, // bitDepth
528 20, // rightShift
529 C2PlaneInfo::LITTLE_END, // endianness
530 C2PlanarLayout::PLANE_Y, // rootIx
531 0, // offset
532 };
533 layout->planes[C2PlanarLayout::PLANE_A] = {
534 C2PlaneInfo::CHANNEL_A, // channel
535 4, // colInc
536 static_cast<int32_t>(4 * stride), // rowInc
537 1, // mColSampling
538 1, // mRowSampling
539 32, // allocatedDepth
540 2, // bitDepth
541 30, // rightShift
542 C2PlaneInfo::LITTLE_END, // endianness
543 C2PlanarLayout::PLANE_Y, // rootIx
544 0, // offset
545 };
546 break;
547 }
548
549 case static_cast<uint32_t>(PixelFormat4::RGBA_8888):
550 // TODO: alpha channel
551 // fall-through
552 case static_cast<uint32_t>(PixelFormat4::RGBX_8888): {
553 void *pointer = nullptr;
554 // TODO: fence
555 status_t err = GraphicBufferMapper::get().lock(
556 const_cast<native_handle_t*>(buffer), grallocUsage, rect, &pointer);
557 if (err) {
558 ALOGE("failed transaction: lock(RGBA_8888)");
559 return C2_CORRUPTED;
560 }
561 addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
562 addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
563 addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
564 layout->type = C2PlanarLayout::TYPE_RGB;
565 layout->numPlanes = 3;
566 layout->rootPlanes = 1;
567 layout->planes[C2PlanarLayout::PLANE_R] = {
568 C2PlaneInfo::CHANNEL_R, // channel
569 4, // colInc
570 static_cast<int32_t>(4 * stride), // rowInc
571 1, // mColSampling
572 1, // mRowSampling
573 8, // allocatedDepth
574 8, // bitDepth
575 0, // rightShift
576 C2PlaneInfo::NATIVE, // endianness
577 C2PlanarLayout::PLANE_R, // rootIx
578 0, // offset
579 };
580 layout->planes[C2PlanarLayout::PLANE_G] = {
581 C2PlaneInfo::CHANNEL_G, // channel
582 4, // colInc
583 static_cast<int32_t>(4 * stride), // rowInc
584 1, // mColSampling
585 1, // mRowSampling
586 8, // allocatedDepth
587 8, // bitDepth
588 0, // rightShift
589 C2PlaneInfo::NATIVE, // endianness
590 C2PlanarLayout::PLANE_R, // rootIx
591 1, // offset
592 };
593 layout->planes[C2PlanarLayout::PLANE_B] = {
594 C2PlaneInfo::CHANNEL_B, // channel
595 4, // colInc
596 static_cast<int32_t>(4 * stride), // rowInc
597 1, // mColSampling
598 1, // mRowSampling
599 8, // allocatedDepth
600 8, // bitDepth
601 0, // rightShift
602 C2PlaneInfo::NATIVE, // endianness
603 C2PlanarLayout::PLANE_R, // rootIx
604 2, // offset
605 };
606 break;
607 }
608
609 case static_cast<uint32_t>(PixelFormat4::BLOB): {
610 void *pointer = nullptr;
611 // TODO: fence
612 status_t err = GraphicBufferMapper::get().lock(
613 const_cast<native_handle_t*>(buffer), grallocUsage, rect, &pointer);
614 if (err) {
615 ALOGE("failed transaction: lock(BLOB)");
616 return C2_CORRUPTED;
617 }
618 *addr = (uint8_t *)pointer;
619 break;
620 }
621
622 case static_cast<uint32_t>(PixelFormat4::YCBCR_422_SP):
623 // fall-through
624 case static_cast<uint32_t>(PixelFormat4::YCRCB_420_SP):
625 // fall-through
626 case static_cast<uint32_t>(PixelFormat4::YCBCR_422_I):
627 // fall-through
628 case static_cast<uint32_t>(PixelFormat4::YCBCR_420_888):
629 // fall-through
630 case static_cast<uint32_t>(PixelFormat4::YV12): {
631 android_ycbcr ycbcrLayout;
632
633 status_t err = GraphicBufferMapper::get().lockYCbCr(
634 const_cast<native_handle_t*>(buffer), grallocUsage, rect, &ycbcrLayout);
635 if (err) {
636 ALOGE("failed transaction: lockYCbCr (err=%d)", err);
637 return C2_CORRUPTED;
638 }
639 if (!ycbcrLayout.y || !ycbcrLayout.cb || !ycbcrLayout.cr
640 || ycbcrLayout.ystride == 0
641 || ycbcrLayout.cstride == 0
642 || ycbcrLayout.chroma_step == 0) {
643 ALOGE("invalid layout: lockYCbCr (y=%s cb=%s cr=%s "
644 "ystride=%zu cstride=%zu chroma_step=%zu)",
645 ycbcrLayout.y ? "(non-null)" : "(null)",
646 ycbcrLayout.cb ? "(non-null)" : "(null)",
647 ycbcrLayout.cr ? "(non-null)" : "(null)",
648 ycbcrLayout.ystride, ycbcrLayout.cstride, ycbcrLayout.chroma_step);
649 return C2_CORRUPTED;
650 }
651
652 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
653 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
654 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
655 layout->type = C2PlanarLayout::TYPE_YUV;
656 layout->numPlanes = 3;
657 layout->rootPlanes = 3;
658 layout->planes[C2PlanarLayout::PLANE_Y] = {
659 C2PlaneInfo::CHANNEL_Y, // channel
660 1, // colInc
661 (int32_t)ycbcrLayout.ystride, // rowInc
662 1, // mColSampling
663 1, // mRowSampling
664 8, // allocatedDepth
665 8, // bitDepth
666 0, // rightShift
667 C2PlaneInfo::NATIVE, // endianness
668 C2PlanarLayout::PLANE_Y, // rootIx
669 0, // offset
670 };
671 layout->planes[C2PlanarLayout::PLANE_U] = {
672 C2PlaneInfo::CHANNEL_CB, // channel
673 (int32_t)ycbcrLayout.chroma_step, // colInc
674 (int32_t)ycbcrLayout.cstride, // rowInc
675 2, // mColSampling
676 2, // mRowSampling
677 8, // allocatedDepth
678 8, // bitDepth
679 0, // rightShift
680 C2PlaneInfo::NATIVE, // endianness
681 C2PlanarLayout::PLANE_U, // rootIx
682 0, // offset
683 };
684 layout->planes[C2PlanarLayout::PLANE_V] = {
685 C2PlaneInfo::CHANNEL_CR, // channel
686 (int32_t)ycbcrLayout.chroma_step, // colInc
687 (int32_t)ycbcrLayout.cstride, // rowInc
688 2, // mColSampling
689 2, // mRowSampling
690 8, // allocatedDepth
691 8, // bitDepth
692 0, // rightShift
693 C2PlaneInfo::NATIVE, // endianness
694 C2PlanarLayout::PLANE_V, // rootIx
695 0, // offset
696 };
697 break;
698 }
699
700 case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
701 // In Android T, P010 is relaxed to allow arbitrary stride for the Y and UV planes,
702 // try locking with the gralloc4 mapper first.
703 c2_status_t status = Gralloc4Mapper_lock(
704 const_cast<native_handle_t*>(buffer), grallocUsage, rect, layout, addr);
705 if (status == C2_OK) {
706 break;
707 }
708
709 void *pointer = nullptr;
710 status_t err = GraphicBufferMapper::get().lock(
711 const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
712 if (err) {
713 ALOGE("failed transaction: lock(YCBCR_P010)");
714 return C2_CORRUPTED;
715 }
716 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
717 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer + stride * 2 * rect.height();
718 addr[C2PlanarLayout::PLANE_V] = addr[C2PlanarLayout::PLANE_U] + 2;
719 layout->type = C2PlanarLayout::TYPE_YUV;
720 layout->numPlanes = 3;
721 layout->rootPlanes = 2;
722 layout->planes[C2PlanarLayout::PLANE_Y] = {
723 C2PlaneInfo::CHANNEL_Y, // channel
724 2, // colInc
725 static_cast<int32_t>(2 * stride), // rowInc
726 1, // mColSampling
727 1, // mRowSampling
728 16, // allocatedDepth
729 10, // bitDepth
730 6, // rightShift
731 kEndianness, // endianness
732 C2PlanarLayout::PLANE_Y, // rootIx
733 0, // offset
734 };
735 layout->planes[C2PlanarLayout::PLANE_U] = {
736 C2PlaneInfo::CHANNEL_CB, // channel
737 4, // colInc
738 static_cast<int32_t>(2 * stride), // rowInc
739 2, // mColSampling
740 2, // mRowSampling
741 16, // allocatedDepth
742 10, // bitDepth
743 6, // rightShift
744 kEndianness, // endianness
745 C2PlanarLayout::PLANE_U, // rootIx
746 0, // offset
747 };
748 layout->planes[C2PlanarLayout::PLANE_V] = {
749 C2PlaneInfo::CHANNEL_CR, // channel
750 4, // colInc
751 static_cast<int32_t>(2 * stride), // rowInc
752 2, // mColSampling
753 2, // mRowSampling
754 16, // allocatedDepth
755 10, // bitDepth
756 6, // rightShift
757 kEndianness, // endianness
758 C2PlanarLayout::PLANE_U, // rootIx
759 2, // offset
760 };
761 break;
762 }
763
764 default: {
765 // We don't know what it is, let's try to lock it with gralloc4
766 android_ycbcr ycbcrLayout;
767 if (isAtLeastT()) {
768 c2_status_t status = Gralloc4Mapper_lock(
769 const_cast<native_handle_t*>(buffer), grallocUsage, rect, layout, addr);
770 if (status == C2_OK) {
771 break;
772 }
773 }
774
775 // fallback to lockYCbCr
776 status_t err = GraphicBufferMapper::get().lockYCbCr(
777 const_cast<native_handle_t*>(buffer), grallocUsage, rect, &ycbcrLayout);
778 if (err == OK && ycbcrLayout.y && ycbcrLayout.cb && ycbcrLayout.cr
779 && ycbcrLayout.ystride > 0
780 && ycbcrLayout.cstride > 0
781 && ycbcrLayout.chroma_step > 0) {
782 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
783 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
784 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
785 layout->type = C2PlanarLayout::TYPE_YUV;
786 layout->numPlanes = 3;
787 layout->rootPlanes = 3;
788 layout->planes[C2PlanarLayout::PLANE_Y] = {
789 C2PlaneInfo::CHANNEL_Y, // channel
790 1, // colInc
791 (int32_t)ycbcrLayout.ystride, // rowInc
792 1, // mColSampling
793 1, // mRowSampling
794 8, // allocatedDepth
795 8, // bitDepth
796 0, // rightShift
797 C2PlaneInfo::NATIVE, // endianness
798 C2PlanarLayout::PLANE_Y, // rootIx
799 0, // offset
800 };
801 layout->planes[C2PlanarLayout::PLANE_U] = {
802 C2PlaneInfo::CHANNEL_CB, // channel
803 (int32_t)ycbcrLayout.chroma_step, // colInc
804 (int32_t)ycbcrLayout.cstride, // rowInc
805 2, // mColSampling
806 2, // mRowSampling
807 8, // allocatedDepth
808 8, // bitDepth
809 0, // rightShift
810 C2PlaneInfo::NATIVE, // endianness
811 C2PlanarLayout::PLANE_U, // rootIx
812 0, // offset
813 };
814 layout->planes[C2PlanarLayout::PLANE_V] = {
815 C2PlaneInfo::CHANNEL_CR, // channel
816 (int32_t)ycbcrLayout.chroma_step, // colInc
817 (int32_t)ycbcrLayout.cstride, // rowInc
818 2, // mColSampling
819 2, // mRowSampling
820 8, // allocatedDepth
821 8, // bitDepth
822 0, // rightShift
823 C2PlaneInfo::NATIVE, // endianness
824 C2PlanarLayout::PLANE_V, // rootIx
825 0, // offset
826 };
827 break;
828 }
829
830 // We really don't know what this is; lock the buffer and pass it through ---
831 // the client may know how to interpret it.
832
833 // unlock previous allocation if it was successful
834 if (err == OK) {
835 err = GraphicBufferMapper::get().unlock(buffer);
836 if (err) {
837 ALOGE("failed transaction: unlock");
838 return C2_CORRUPTED;
839 }
840 }
841
842 void *pointer = nullptr;
843 err = GraphicBufferMapper::get().lock(
844 const_cast<native_handle_t *>(buffer), grallocUsage, rect, &pointer);
845 if (err) {
846 ALOGE("failed transaction: lock(??? %x)", format);
847 return C2_CORRUPTED;
848 }
849 addr[0] = (uint8_t *)pointer;
850 layout->type = C2PlanarLayout::TYPE_UNKNOWN;
851 layout->numPlanes = 1;
852 layout->rootPlanes = 1;
853 layout->planes[0] = {
854 // TODO: CHANNEL_UNKNOWN?
855 C2PlaneInfo::channel_t(0xFF), // channel
856 1, // colInc
857 int32_t(stride), // rowInc
858 1, // mColSampling
859 1, // mRowSampling
860 8, // allocatedDepth
861 8, // bitDepth
862 0, // rightShift
863 C2PlaneInfo::NATIVE, // endianness
864 0, // rootIx
865 0, // offset
866 };
867 break;
868 }
869 }
870 return C2_OK;
871}
872
873static void HandleInterleavedPlanes(
874 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
875 if (layout->type == C2PlanarLayout::TYPE_YUV && layout->rootPlanes == 3) {
876 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
877 intptr_t uvColInc = layout->planes[C2PlanarLayout::PLANE_U].colInc;
878 if (uvOffset > 0 && uvOffset < uvColInc) {
879 layout->rootPlanes = 2;
880 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
881 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
882 } else if (uvOffset < 0 && uvOffset > -uvColInc) {
883 layout->rootPlanes = 2;
884 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
885 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
886 }
887 }
888}
889
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700890} // unnamed namespace
891
Praveen Chavan34493f12021-02-18 00:51:50 -0800892
Pawin Vongmasa36653902018-11-15 00:10:25 -0800893native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
894 return C2HandleGralloc::UnwrapNativeHandle(handle);
895}
896
Pawin Vongmasa36653902018-11-15 00:10:25 -0800897C2Handle *WrapNativeCodec2GrallocHandle(
898 const native_handle_t *const handle,
899 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
900 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
901 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
902 generation, igbp_id, igbp_slot);
903}
904
Sungtak Lee08515812019-06-05 11:16:32 -0700905bool MigrateNativeCodec2GrallocHandle(
906 native_handle_t *handle,
907 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
908 return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
909}
910
911
Sungtak Lee1a67c9d2023-09-14 19:41:00 +0000912
Pawin Vongmasa36653902018-11-15 00:10:25 -0800913class C2AllocationGralloc : public C2GraphicAllocation {
914public:
915 virtual ~C2AllocationGralloc() override;
916
917 virtual c2_status_t map(
Chih-Yu Huang486aa5d2020-10-13 16:22:58 +0900918 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800919 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
920 virtual c2_status_t unmap(
921 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
922 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
923 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
924 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
925
926 // internal methods
927 // |handle| will be moved.
Marissa Wall2a24a302019-11-25 11:19:18 -0800928
Pawin Vongmasa36653902018-11-15 00:10:25 -0800929 C2AllocationGralloc(
Marissa Wall2a24a302019-11-25 11:19:18 -0800930 uint32_t width, uint32_t height,
931 uint32_t format, uint32_t layerCount,
932 uint64_t grallocUsage, uint32_t stride,
Marissa Wall8806edc2019-06-21 09:50:47 -0700933 hidl_handle &hidlHandle,
934 const C2HandleGralloc *const handle,
935 C2Allocator::id_t allocatorId);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800936 int dup() const;
937 c2_status_t status() const;
938
939private:
Marissa Wall2a24a302019-11-25 11:19:18 -0800940 const uint32_t mWidth;
941 const uint32_t mHeight;
942 const uint32_t mFormat;
943 const uint32_t mLayerCount;
944 const uint64_t mGrallocUsage;
945 const uint32_t mStride;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800946 const hidl_handle mHidlHandle;
947 const C2HandleGralloc *mHandle;
948 buffer_handle_t mBuffer;
949 const C2HandleGralloc *mLockedHandle;
950 bool mLocked;
951 C2Allocator::id_t mAllocatorId;
952 std::mutex mMappedLock;
953};
954
955C2AllocationGralloc::C2AllocationGralloc(
Marissa Wall2a24a302019-11-25 11:19:18 -0800956 uint32_t width, uint32_t height,
957 uint32_t format, uint32_t layerCount,
958 uint64_t grallocUsage, uint32_t stride,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800959 hidl_handle &hidlHandle,
960 const C2HandleGralloc *const handle,
961 C2Allocator::id_t allocatorId)
Marissa Wall2a24a302019-11-25 11:19:18 -0800962 : C2GraphicAllocation(width, height),
963 mWidth(width),
964 mHeight(height),
965 mFormat(format),
966 mLayerCount(layerCount),
967 mGrallocUsage(grallocUsage),
968 mStride(stride),
Marissa Wall8806edc2019-06-21 09:50:47 -0700969 mHidlHandle(std::move(hidlHandle)),
970 mHandle(handle),
971 mBuffer(nullptr),
972 mLockedHandle(nullptr),
973 mLocked(false),
974 mAllocatorId(allocatorId) {
975}
976
Pawin Vongmasa36653902018-11-15 00:10:25 -0800977C2AllocationGralloc::~C2AllocationGralloc() {
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800978 if (mBuffer && mLocked) {
Sungtak Lee1a67c9d2023-09-14 19:41:00 +0000979 // implementation ignores address and rect
Pawin Vongmasa36653902018-11-15 00:10:25 -0800980 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
981 unmap(addr, C2Rect(), nullptr);
982 }
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800983 if (mBuffer) {
Marissa Wall2a24a302019-11-25 11:19:18 -0800984 status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
985 if (err) {
986 ALOGE("failed transaction: freeBuffer");
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700987 }
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800988 }
989 if (mHandle) {
990 native_handle_delete(
991 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
992 }
Sungtak Lee2729dcf2019-01-18 13:15:07 -0800993 if (mLockedHandle) {
994 native_handle_delete(
995 const_cast<native_handle_t *>(
996 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
997 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800998}
999
1000c2_status_t C2AllocationGralloc::map(
Chih-Yu Huang486aa5d2020-10-13 16:22:58 +09001001 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
Pawin Vongmasa36653902018-11-15 00:10:25 -08001002 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
Chih-Yu Huang486aa5d2020-10-13 16:22:58 +09001003 const Rect rect{(int32_t)c2Rect.left, (int32_t)c2Rect.top,
1004 (int32_t)(c2Rect.left + c2Rect.width) /* right */,
1005 (int32_t)(c2Rect.top + c2Rect.height) /* bottom */};
1006
Pawin Vongmasa36653902018-11-15 00:10:25 -08001007 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
1008 ALOGV("mapping buffer with usage %#llx => %#llx",
1009 (long long)usage.expected, (long long)grallocUsage);
1010
1011 // TODO
Marissa Wall2a24a302019-11-25 11:19:18 -08001012 (void)fence;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001013
1014 std::lock_guard<std::mutex> lock(mMappedLock);
1015 if (mBuffer && mLocked) {
1016 ALOGD("already mapped");
1017 return C2_DUPLICATE;
1018 }
1019 if (!layout || !addr) {
1020 ALOGD("wrong param");
1021 return C2_BAD_VALUE;
1022 }
1023
Pawin Vongmasa36653902018-11-15 00:10:25 -08001024 if (!mBuffer) {
Marissa Wall2a24a302019-11-25 11:19:18 -08001025 status_t err = GraphicBufferMapper::get().importBuffer(
1026 mHidlHandle.getNativeHandle(), mWidth, mHeight, mLayerCount,
1027 mFormat, mGrallocUsage, mStride, &mBuffer);
1028 if (err) {
1029 ALOGE("failed transaction: importBuffer");
1030 return C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001031 }
1032 if (mBuffer == nullptr) {
1033 ALOGD("importBuffer returned null buffer");
1034 return C2_CORRUPTED;
1035 }
1036 uint32_t generation = 0;
1037 uint64_t igbp_id = 0;
1038 uint32_t igbp_slot = 0;
1039 if (mHandle) {
1040 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
1041 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001042
Marissa Wall2a24a302019-11-25 11:19:18 -08001043 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
1044 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
1045 mStride, generation, igbp_id, igbp_slot);
Marissa Wall8806edc2019-06-21 09:50:47 -07001046 }
Praveen Chavan34493f12021-02-18 00:51:50 -08001047
Sungtak Lee25e33ee2023-09-15 08:06:37 +00001048 c2_status_t ret = PopulatePlaneLayout(
1049 mBuffer, rect, mFormat, grallocUsage, mStride, layout, addr);
1050 if (ret != C2_OK) {
1051 return ret;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001052 }
1053 mLocked = true;
1054
Sungtak Lee25e33ee2023-09-15 08:06:37 +00001055 HandleInterleavedPlanes(layout, addr);
Wonsik Kimf12bebc2022-03-24 16:25:03 -07001056
1057 ALOGV("C2AllocationGralloc::map: layout: type=%d numPlanes=%d rootPlanes=%d",
1058 layout->type, layout->numPlanes, layout->rootPlanes);
1059 for (int i = 0; i < layout->numPlanes; ++i) {
1060 const C2PlaneInfo &plane = layout->planes[i];
1061 ALOGV("C2AllocationGralloc::map: plane[%d]: colInc=%d rowInc=%d rootIx=%u offset=%u",
1062 i, plane.colInc, plane.rowInc, plane.rootIx, plane.offset);
1063 }
1064
Pawin Vongmasa36653902018-11-15 00:10:25 -08001065 return C2_OK;
1066}
1067
1068c2_status_t C2AllocationGralloc::unmap(
1069 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
1070 // TODO: check addr and size, use fence
1071 (void)addr;
1072 (void)rect;
Marissa Wall2a24a302019-11-25 11:19:18 -08001073 (void)fence;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001074
1075 std::lock_guard<std::mutex> lock(mMappedLock);
Marissa Wall2a24a302019-11-25 11:19:18 -08001076 // TODO: fence
1077 status_t err = GraphicBufferMapper::get().unlock(mBuffer);
1078 if (err) {
1079 ALOGE("failed transaction: unlock");
1080 return C2_CORRUPTED;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001081 }
Marissa Wall2a24a302019-11-25 11:19:18 -08001082
1083 mLocked = false;
1084 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001085}
1086
1087bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
1088 return other && other->handle() == handle();
1089}
1090
1091/* ===================================== GRALLOC ALLOCATOR ==================================== */
1092class C2AllocatorGralloc::Impl {
1093public:
1094 Impl(id_t id, bool bufferQueue);
1095
1096 id_t getId() const {
1097 return mTraits->id;
1098 }
1099
1100 C2String getName() const {
1101 return mTraits->name;
1102 }
1103
1104 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
1105 return mTraits;
1106 }
1107
1108 c2_status_t newGraphicAllocation(
1109 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1110 std::shared_ptr<C2GraphicAllocation> *allocation);
1111
1112 c2_status_t priorGraphicAllocation(
1113 const C2Handle *handle,
1114 std::shared_ptr<C2GraphicAllocation> *allocation);
1115
1116 c2_status_t status() const { return mInit; }
1117
1118private:
1119 std::shared_ptr<C2Allocator::Traits> mTraits;
1120 c2_status_t mInit;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001121 const bool mBufferQueue;
1122};
1123
1124void _UnwrapNativeCodec2GrallocMetadata(
1125 const C2Handle *const handle,
1126 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
1127 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
1128 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
1129 generation, igbp_id, igbp_slot);
1130}
1131
1132C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
1133 : mInit(C2_OK), mBufferQueue(bufferQueue) {
1134 // TODO: get this from allocator
1135 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
1136 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
1137 mTraits = std::make_shared<C2Allocator::Traits>(traits);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001138}
1139
1140c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
1141 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1142 std::shared_ptr<C2GraphicAllocation> *allocation) {
1143 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
1144 ALOGV("allocating buffer with usage %#llx => %#llx",
1145 (long long)usage.expected, (long long)grallocUsage);
1146
Marissa Wall2a24a302019-11-25 11:19:18 -08001147 buffer_handle_t buffer;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001148
Marissa Wall2a24a302019-11-25 11:19:18 -08001149 uint32_t stride = 0;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001150
Marissa Wall2a24a302019-11-25 11:19:18 -08001151 status_t err = GraphicBufferAllocator::get().allocateRawHandle(width, height, format,
1152 1u /* layer count */, grallocUsage, &buffer, &stride, "C2GrallocAllocation");
1153 if (err) {
1154 ALOGE("failed transaction: allocate");
1155 return C2_CORRUPTED;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001156 }
Marissa Wall2a24a302019-11-25 11:19:18 -08001157
1158 hidl_handle hidlHandle;
1159 hidlHandle.setTo(const_cast<native_handle_t*>(buffer), true);
1160
1161 allocation->reset(new C2AllocationGralloc(
1162 width, height, format, 1u /* layer count */, grallocUsage, stride, hidlHandle,
1163 C2HandleGralloc::WrapAndMoveNativeHandle(
1164 hidlHandle, width, height,
1165 format, grallocUsage, stride,
1166 0, 0, mBufferQueue ? ~0 : 0),
1167 mTraits->id));
1168 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001169}
1170
1171c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
1172 const C2Handle *handle,
1173 std::shared_ptr<C2GraphicAllocation> *allocation) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001174
Marissa Wall2a24a302019-11-25 11:19:18 -08001175 uint32_t generation;
1176 uint64_t igbp_id;
1177 uint32_t igbp_slot;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001178
Marissa Wall2a24a302019-11-25 11:19:18 -08001179 uint32_t width;
1180 uint32_t height;
1181 uint32_t format;
1182 uint32_t layerCount = 1;
1183 uint64_t grallocUsage;
1184 uint32_t stride;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001185
Marissa Wall2a24a302019-11-25 11:19:18 -08001186 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
1187 handle, &width, &height, &format, &grallocUsage, &stride,
1188 &generation, &igbp_id, &igbp_slot);
1189 if (grallocHandle == nullptr) {
1190 return C2_BAD_VALUE;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001191 }
Marissa Wall2a24a302019-11-25 11:19:18 -08001192
1193 hidl_handle hidlHandle;
1194 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
1195
1196 allocation->reset(new C2AllocationGralloc(
1197 width, height, format, layerCount,
1198 grallocUsage, stride, hidlHandle, grallocHandle, mTraits->id));
1199 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001200}
1201
1202C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
1203 : mImpl(new Impl(id, bufferQueue)) {}
1204
1205C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
1206
1207C2Allocator::id_t C2AllocatorGralloc::getId() const {
1208 return mImpl->getId();
1209}
1210
1211C2String C2AllocatorGralloc::getName() const {
1212 return mImpl->getName();
1213}
1214
1215std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
1216 return mImpl->getTraits();
1217}
1218
1219c2_status_t C2AllocatorGralloc::newGraphicAllocation(
1220 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
1221 std::shared_ptr<C2GraphicAllocation> *allocation) {
1222 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
1223}
1224
1225c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
1226 const C2Handle *handle,
1227 std::shared_ptr<C2GraphicAllocation> *allocation) {
1228 return mImpl->priorGraphicAllocation(handle, allocation);
1229}
1230
1231c2_status_t C2AllocatorGralloc::status() const {
1232 return mImpl->status();
1233}
1234
John Stultz653ddd12020-09-19 05:26:24 +00001235// static
1236bool C2AllocatorGralloc::CheckHandle(const C2Handle* const o) {
1237 return C2HandleGralloc::IsValid(o);
Pawin Vongmasa36653902018-11-15 00:10:25 -08001238}
1239
Sungtak Lee1a67c9d2023-09-14 19:41:00 +00001240
1241native_handle_t *UnwrapNativeCodec2AhwbHandle(const C2Handle *const handle) {
1242 return C2HandleAhwb::UnwrapNativeHandle(handle);
1243}
1244
1245C2Handle *WrapNativeCodec2AhwbHandle(
1246 const native_handle_t *const handle,
1247 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
1248 uint64_t origId) {
1249 return C2HandleAhwb::WrapNativeHandle(handle, width, height, format, usage, stride,
1250 origId);
1251}
1252
1253class C2AllocationAhwb : public C2GraphicAllocation {
1254public:
1255 virtual ~C2AllocationAhwb() override;
1256
1257 virtual c2_status_t map(
1258 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
1259 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
1260 virtual c2_status_t unmap(
1261 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
1262 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
1263 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
1264 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
1265
1266 // internal methods
1267 // |handle| will be moved.
1268
1269 C2AllocationAhwb(
1270 uint32_t width, uint32_t height,
1271 uint32_t format, uint32_t layerCount,
1272 uint64_t grallocUsage, uint32_t stride,
1273 const C2HandleAhwb *const handle,
1274 C2Allocator::id_t allocatorId);
1275 int dup() const;
1276 c2_status_t status() const;
1277
1278private:
1279 const uint32_t mWidth;
1280 const uint32_t mHeight;
1281 const uint32_t mFormat;
1282 const uint32_t mLayerCount;
1283 const uint64_t mGrallocUsage;
1284 const uint32_t mStride;
1285 const native_handle_t *mRawHandle;
1286 const C2HandleAhwb *mHandle;
1287 buffer_handle_t mBuffer;
1288 const C2HandleAhwb *mLockedHandle;
1289 bool mLocked;
1290 C2Allocator::id_t mAllocatorId;
1291 std::mutex mMappedLock;
1292};
1293
1294C2AllocationAhwb::C2AllocationAhwb(
1295 uint32_t width, uint32_t height,
1296 uint32_t format, uint32_t layerCount,
1297 uint64_t grallocUsage, uint32_t stride,
1298 const C2HandleAhwb *const handle,
1299 C2Allocator::id_t allocatorId)
1300 : C2GraphicAllocation(width, height),
1301 mWidth(width),
1302 mHeight(height),
1303 mFormat(format),
1304 mLayerCount(layerCount),
1305 mGrallocUsage(grallocUsage),
1306 mStride(stride),
1307 mRawHandle(C2HandleAhwb::UnwrapNativeHandle(handle)),
1308 mHandle(handle),
1309 mBuffer(nullptr),
1310 mLockedHandle(nullptr),
1311 mLocked(false),
1312 mAllocatorId(allocatorId) {
1313}
1314
1315C2AllocationAhwb::~C2AllocationAhwb() {
1316 if (mBuffer && mLocked) {
1317 // implementation ignores address and rect
1318 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
1319 unmap(addr, C2Rect(), nullptr);
1320 }
1321 if (mBuffer) {
1322 status_t err = GraphicBufferMapper::get().freeBuffer(mBuffer);
1323 if (err) {
1324 ALOGE("failed transaction: freeBuffer");
1325 }
1326 }
1327 if (mRawHandle) {
1328 native_handle_close(
1329 const_cast<native_handle_t *>(
1330 reinterpret_cast<const native_handle_t *>(mRawHandle)));
1331 native_handle_delete(
1332 const_cast<native_handle_t *>(
1333 reinterpret_cast<const native_handle_t *>(mRawHandle)));
1334 }
1335 if (mHandle) {
1336 native_handle_delete(
1337 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
1338 }
1339 if (mLockedHandle) {
1340 native_handle_delete(
1341 const_cast<native_handle_t *>(
1342 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
1343 }
1344}
1345
1346c2_status_t C2AllocationAhwb::map(
1347 C2Rect c2Rect, C2MemoryUsage usage, C2Fence *fence,
1348 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
1349 const Rect rect{(int32_t)c2Rect.left, (int32_t)c2Rect.top,
1350 (int32_t)(c2Rect.left + c2Rect.width) /* right */,
1351 (int32_t)(c2Rect.top + c2Rect.height) /* bottom */};
1352
1353 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
1354 ALOGV("mapping buffer with usage %#llx => %#llx",
1355 (long long)usage.expected, (long long)grallocUsage);
1356
1357 // TODO
1358 (void)fence;
1359
1360 std::lock_guard<std::mutex> lock(mMappedLock);
1361 if (mBuffer && mLocked) {
1362 ALOGD("already mapped");
1363 return C2_DUPLICATE;
1364 }
1365 if (!layout || !addr) {
1366 ALOGD("wrong param");
1367 return C2_BAD_VALUE;
1368 }
1369
1370 if (!mBuffer) {
1371 // TODO: libui/libgui dependency removal (b/214400477)
1372 status_t err = GraphicBufferMapper::get().importBuffer(
1373 mRawHandle, mWidth, mHeight, mLayerCount,
1374 mFormat, mGrallocUsage, mStride, &mBuffer);
1375 if (err) {
1376 ALOGE("failed transaction: importBuffer");
1377 return C2_CORRUPTED;
1378 }
1379 if (mBuffer == nullptr) {
1380 ALOGD("importBuffer returned null buffer");
1381 return C2_CORRUPTED;
1382 }
1383 uint64_t origId = 0;
1384 if (mHandle) {
1385 mHandle->getOrigId(&origId);
1386 }
1387
1388 mLockedHandle = C2HandleAhwb::WrapAndMoveNativeHandle(
1389 mBuffer, mWidth, mHeight, mFormat, mGrallocUsage,
1390 mStride, origId);
1391 }
1392
1393 c2_status_t ret = PopulatePlaneLayout(
1394 mBuffer, rect, mFormat, grallocUsage, mStride, layout, addr);
1395 if (ret != C2_OK) {
1396 return ret;
1397 }
1398 mLocked = true;
1399
1400 HandleInterleavedPlanes(layout, addr);
1401
1402 ALOGV("C2AllocationGralloc::map: layout: type=%d numPlanes=%d rootPlanes=%d",
1403 layout->type, layout->numPlanes, layout->rootPlanes);
1404 for (int i = 0; i < layout->numPlanes; ++i) {
1405 const C2PlaneInfo &plane = layout->planes[i];
1406 ALOGV("C2AllocationGralloc::map: plane[%d]: colInc=%d rowInc=%d rootIx=%u offset=%u",
1407 i, plane.colInc, plane.rowInc, plane.rootIx, plane.offset);
1408 }
1409
1410 return C2_OK;
1411}
1412
1413c2_status_t C2AllocationAhwb::unmap(
1414 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
1415 // TODO: check addr and size, use fence
1416 (void)addr;
1417 (void)rect;
1418 (void)fence;
1419
1420 std::lock_guard<std::mutex> lock(mMappedLock);
1421 // TODO: fence
1422 status_t err = GraphicBufferMapper::get().unlock(mBuffer);
1423 if (err) {
1424 ALOGE("failed transaction: unlock");
1425 return C2_CORRUPTED;
1426 }
1427
1428 mLocked = false;
1429 return C2_OK;
1430}
1431
1432bool C2AllocationAhwb::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
1433 return other && other->handle() == handle();
1434}
1435
1436/* ===================================== AHARDWAREBUFFER ALLOCATOR ============================= */
1437class C2AllocatorAhwb::Impl {
1438public:
1439 Impl(id_t id);
1440
1441 id_t getId() const {
1442 return mTraits->id;
1443 }
1444
1445 C2String getName() const {
1446 return mTraits->name;
1447 }
1448
1449 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
1450 return mTraits;
1451 }
1452
1453 c2_status_t newGraphicAllocation(
1454 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1455 std::shared_ptr<C2GraphicAllocation> *allocation);
1456
1457 c2_status_t priorGraphicAllocation(
1458 const C2Handle *handle,
1459 std::shared_ptr<C2GraphicAllocation> *allocation);
1460
1461 c2_status_t status() const { return mInit; }
1462
1463private:
1464 std::shared_ptr<C2Allocator::Traits> mTraits;
1465 c2_status_t mInit;
1466};
1467
1468void _UnwrapNativeCodec2AhwbMetadata(
1469 const C2Handle *const handle,
1470 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
1471 uint64_t *origId) {
1472 (void)C2HandleAhwb::Import(handle, width, height, format, usage, stride, origId);
1473}
1474
1475C2AllocatorAhwb::Impl::Impl(id_t id)
1476 : mInit(C2_OK) {
1477 // TODO: get this from allocator
1478 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
1479 Traits traits = { "android.allocator.ahwb", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
1480 mTraits = std::make_shared<C2Allocator::Traits>(traits);
1481}
1482
1483c2_status_t C2AllocatorAhwb::Impl::newGraphicAllocation(
1484 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1485 std::shared_ptr<C2GraphicAllocation> *allocation) {
1486 // TODO: for client side usage
1487 // HAL side Ahwb allocation should be done via IGBA currently.
1488 (void) width;
1489 (void) height;
1490 (void) format;
1491 (void) usage;
1492 (void) allocation;
1493 return C2_OMITTED;
1494}
1495
1496c2_status_t C2AllocatorAhwb::Impl::priorGraphicAllocation(
1497 const C2Handle *handle,
1498 std::shared_ptr<C2GraphicAllocation> *allocation) {
1499
1500 uint32_t width;
1501 uint32_t height;
1502 uint32_t format;
1503 uint32_t layerCount = 1;
1504 uint64_t grallocUsage;
1505 uint32_t stride;
1506 uint64_t origId;
1507
1508 const C2HandleAhwb *ahwbHandle = C2HandleAhwb::Import(
1509 handle, &width, &height, &format, &grallocUsage, &stride, &origId);
1510 if (ahwbHandle == nullptr) {
1511 return C2_BAD_VALUE;
1512 }
1513
1514 allocation->reset(new C2AllocationAhwb(
1515 width, height, format, layerCount,
1516 grallocUsage, stride, ahwbHandle, mTraits->id));
1517 return C2_OK;
1518}
1519
1520C2AllocatorAhwb::C2AllocatorAhwb(id_t id)
1521 : mImpl(new Impl(id)) {}
1522
1523C2AllocatorAhwb::~C2AllocatorAhwb() { delete mImpl; }
1524
1525C2Allocator::id_t C2AllocatorAhwb::getId() const {
1526 return mImpl->getId();
1527}
1528
1529C2String C2AllocatorAhwb::getName() const {
1530 return mImpl->getName();
1531}
1532
1533std::shared_ptr<const C2Allocator::Traits> C2AllocatorAhwb::getTraits() const {
1534 return mImpl->getTraits();
1535}
1536
1537c2_status_t C2AllocatorAhwb::newGraphicAllocation(
1538 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
1539 std::shared_ptr<C2GraphicAllocation> *allocation) {
1540 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
1541}
1542
1543c2_status_t C2AllocatorAhwb::priorGraphicAllocation(
1544 const C2Handle *handle,
1545 std::shared_ptr<C2GraphicAllocation> *allocation) {
1546 return mImpl->priorGraphicAllocation(handle, allocation);
1547}
1548
1549c2_status_t C2AllocatorAhwb::status() const {
1550 return mImpl->status();
1551}
1552
1553// static
1554bool C2AllocatorAhwb::CheckHandle(const C2Handle* const o) {
1555 return C2HandleAhwb::IsValid(o);
1556}
Pawin Vongmasa36653902018-11-15 00:10:25 -08001557} // namespace android