blob: 3729f7bb1a3f86f00e8152eb5717eb67818fb56f [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
21#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
22#include <android/hardware/graphics/mapper/2.0/IMapper.h>
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070023#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
24#include <android/hardware/graphics/mapper/3.0/IMapper.h>
Marissa Wall8806edc2019-06-21 09:50:47 -070025#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
26#include <android/hardware/graphics/mapper/4.0/IMapper.h>
Pawin Vongmasa36653902018-11-15 00:10:25 -080027#include <cutils/native_handle.h>
28#include <hardware/gralloc.h>
29
30#include <C2AllocatorGralloc.h>
31#include <C2Buffer.h>
32#include <C2PlatformSupport.h>
33
34namespace android {
35
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070036namespace /* unnamed */ {
Pawin Vongmasa36653902018-11-15 00:10:25 -080037 enum : uint64_t {
38 /**
39 * Usage mask that is passed through from gralloc to Codec 2.0 usage.
40 */
41 PASSTHROUGH_USAGE_MASK =
42 ~(GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_PROTECTED)
43 };
44
45 // verify that passthrough mask is within the platform mask
46 static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070047} // unnamed
Pawin Vongmasa36653902018-11-15 00:10:25 -080048
49C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
50 // gralloc does not support WRITE_PROTECTED
51 return C2MemoryUsage(
52 ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
53 ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
54 ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
55 (usage & PASSTHROUGH_USAGE_MASK));
56}
57
58uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
59 // gralloc does not support WRITE_PROTECTED
60 return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
61 ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
62 ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
63 (expected & PASSTHROUGH_USAGE_MASK));
64}
65
Pawin Vongmasa36653902018-11-15 00:10:25 -080066using ::android::hardware::hidl_handle;
67using ::android::hardware::hidl_vec;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070068using ::android::hardware::graphics::common::V1_0::BufferUsage;
69using PixelFormat2 = ::android::hardware::graphics::common::V1_0::PixelFormat;
70using PixelFormat3 = ::android::hardware::graphics::common::V1_2::PixelFormat;
Marissa Wall8806edc2019-06-21 09:50:47 -070071using PixelFormat4 = ::android::hardware::graphics::common::V1_2::PixelFormat;
Pawin Vongmasa36653902018-11-15 00:10:25 -080072
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070073using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
74using BufferDescriptor2 = ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
75using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
76using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
Pawin Vongmasa36653902018-11-15 00:10:25 -080077
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070078using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
79using BufferDescriptor3 = ::android::hardware::graphics::mapper::V3_0::BufferDescriptor;
80using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
81using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
82
Marissa Wall8806edc2019-06-21 09:50:47 -070083using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
84using BufferDescriptor4 = ::android::hardware::graphics::mapper::V4_0::BufferDescriptor;
85using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
86using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
87
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070088namespace /* unnamed */ {
89
90struct BufferDescriptorInfo2 {
91 IMapper2::BufferDescriptorInfo mapperInfo;
Pawin Vongmasa36653902018-11-15 00:10:25 -080092 uint32_t stride;
93};
94
Pawin Vongmasad032f2d2019-05-15 08:42:44 -070095struct BufferDescriptorInfo3 {
96 IMapper3::BufferDescriptorInfo mapperInfo;
97 uint32_t stride;
98};
Pawin Vongmasa36653902018-11-15 00:10:25 -080099
Marissa Wall8806edc2019-06-21 09:50:47 -0700100struct BufferDescriptorInfo4 {
101 IMapper4::BufferDescriptorInfo mapperInfo;
102 uint32_t stride;
103};
104
Pawin Vongmasa36653902018-11-15 00:10:25 -0800105/* ===================================== GRALLOC ALLOCATION ==================================== */
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700106c2_status_t maperr2error(Error2 maperr) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800107 switch (maperr) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700108 case Error2::NONE: return C2_OK;
109 case Error2::BAD_DESCRIPTOR: return C2_BAD_VALUE;
110 case Error2::BAD_BUFFER: return C2_BAD_VALUE;
111 case Error2::BAD_VALUE: return C2_BAD_VALUE;
112 case Error2::NO_RESOURCES: return C2_NO_MEMORY;
113 case Error2::UNSUPPORTED: return C2_CANNOT_DO;
Pawin Vongmasa36653902018-11-15 00:10:25 -0800114 }
115 return C2_CORRUPTED;
116}
117
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700118c2_status_t maperr2error(Error3 maperr) {
119 switch (maperr) {
120 case Error3::NONE: return C2_OK;
121 case Error3::BAD_DESCRIPTOR: return C2_BAD_VALUE;
122 case Error3::BAD_BUFFER: return C2_BAD_VALUE;
123 case Error3::BAD_VALUE: return C2_BAD_VALUE;
124 case Error3::NO_RESOURCES: return C2_NO_MEMORY;
125 case Error3::UNSUPPORTED: return C2_CANNOT_DO;
126 }
127 return C2_CORRUPTED;
128}
129
Marissa Wall8806edc2019-06-21 09:50:47 -0700130c2_status_t maperr2error(Error4 maperr) {
131 switch (maperr) {
132 case Error4::NONE: return C2_OK;
133 case Error4::BAD_DESCRIPTOR: return C2_BAD_VALUE;
134 case Error4::BAD_BUFFER: return C2_BAD_VALUE;
135 case Error4::BAD_VALUE: return C2_BAD_VALUE;
136 case Error4::NO_RESOURCES: return C2_NO_MEMORY;
137 case Error4::UNSUPPORTED: return C2_CANNOT_DO;
138 }
139 return C2_CORRUPTED;
140}
141
Pawin Vongmasa36653902018-11-15 00:10:25 -0800142bool native_handle_is_invalid(const native_handle_t *const handle) {
143 // perform basic validation of a native handle
144 if (handle == nullptr) {
145 // null handle is considered valid
146 return false;
147 }
148 return ((size_t)handle->version != sizeof(native_handle_t) ||
149 handle->numFds < 0 ||
150 handle->numInts < 0 ||
151 // for sanity assume handles must occupy less memory than INT_MAX bytes
152 handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
153}
154
155class C2HandleGralloc : public C2Handle {
156private:
157 struct ExtraData {
158 uint32_t width;
159 uint32_t height;
160 uint32_t format;
161 uint32_t usage_lo;
162 uint32_t usage_hi;
163 uint32_t stride;
164 uint32_t generation;
165 uint32_t igbp_id_lo;
166 uint32_t igbp_id_hi;
167 uint32_t igbp_slot;
168 uint32_t magic;
169 };
170
171 enum {
172 NUM_INTS = sizeof(ExtraData) / sizeof(int),
173 };
174 const static uint32_t MAGIC = '\xc2gr\x00';
175
176 static
177 const ExtraData* getExtraData(const C2Handle *const handle) {
178 if (handle == nullptr
179 || native_handle_is_invalid(handle)
180 || handle->numInts < NUM_INTS) {
181 return nullptr;
182 }
183 return reinterpret_cast<const ExtraData*>(
184 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
185 }
186
187 static
188 ExtraData *getExtraData(C2Handle *const handle) {
189 return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle)));
190 }
191
192public:
193 void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
194 const ExtraData *ed = getExtraData(this);
195 *generation = ed->generation;
196 *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
197 *igbp_slot = ed->igbp_slot;
198 }
199
200 static bool isValid(const C2Handle *const o) {
201 if (o == nullptr) { // null handle is always valid
202 return true;
203 }
204 const ExtraData *xd = getExtraData(o);
205 // we cannot validate width/height/format/usage without accessing gralloc driver
206 return xd != nullptr && xd->magic == MAGIC;
207 }
208
Sungtak Leea4d13be2019-01-23 15:24:46 -0800209 static C2HandleGralloc* WrapAndMoveNativeHandle(
Pawin Vongmasa36653902018-11-15 00:10:25 -0800210 const native_handle_t *const handle,
211 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
212 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
213 //CHECK(handle != nullptr);
214 if (native_handle_is_invalid(handle) ||
215 handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
216 return nullptr;
217 }
218 ExtraData xd = {
219 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
220 stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
221 igbp_slot, MAGIC
222 };
223 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
224 if (res != nullptr) {
225 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
226 *getExtraData(res) = xd;
227 }
228 return reinterpret_cast<C2HandleGralloc *>(res);
229 }
230
Sungtak Leea4d13be2019-01-23 15:24:46 -0800231 static C2HandleGralloc* WrapNativeHandle(
232 const native_handle_t *const handle,
233 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
234 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
235 if (handle == nullptr) {
236 return nullptr;
237 }
238 native_handle_t *clone = native_handle_clone(handle);
239 if (clone == nullptr) {
240 return nullptr;
241 }
242 C2HandleGralloc *res = WrapAndMoveNativeHandle(
243 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
244 if (res == nullptr) {
245 native_handle_close(clone);
246 }
247 native_handle_delete(clone);
248 return res;
249 }
250
Sungtak Lee08515812019-06-05 11:16:32 -0700251 static bool MigrateNativeHandle(
252 native_handle_t *handle,
253 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
254 if (handle == nullptr || !isValid(handle)) {
255 return false;
256 }
257 ExtraData *ed = getExtraData(handle);
258 if (!ed) return false;
259 ed->generation = generation;
260 ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
261 ed->igbp_id_hi = uint32_t(igbp_id >> 32);
262 ed->igbp_slot = igbp_slot;
263 return true;
264 }
265
266
Pawin Vongmasa36653902018-11-15 00:10:25 -0800267 static native_handle_t* UnwrapNativeHandle(
268 const C2Handle *const handle) {
269 const ExtraData *xd = getExtraData(handle);
270 if (xd == nullptr || xd->magic != MAGIC) {
271 return nullptr;
272 }
273 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
274 if (res != nullptr) {
275 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
276 }
277 return res;
278 }
279
Pawin Vongmasa36653902018-11-15 00:10:25 -0800280 static const C2HandleGralloc* Import(
281 const C2Handle *const handle,
282 uint32_t *width, uint32_t *height, uint32_t *format,
283 uint64_t *usage, uint32_t *stride,
284 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
285 const ExtraData *xd = getExtraData(handle);
286 if (xd == nullptr) {
287 return nullptr;
288 }
289 *width = xd->width;
290 *height = xd->height;
291 *format = xd->format;
292 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
293 *stride = xd->stride;
294 *generation = xd->generation;
295 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
296 *igbp_slot = xd->igbp_slot;
297 return reinterpret_cast<const C2HandleGralloc *>(handle);
298 }
299};
300
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700301} // unnamed namespace
302
Pawin Vongmasa36653902018-11-15 00:10:25 -0800303native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
304 return C2HandleGralloc::UnwrapNativeHandle(handle);
305}
306
Pawin Vongmasa36653902018-11-15 00:10:25 -0800307C2Handle *WrapNativeCodec2GrallocHandle(
308 const native_handle_t *const handle,
309 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
310 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
311 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
312 generation, igbp_id, igbp_slot);
313}
314
Sungtak Lee08515812019-06-05 11:16:32 -0700315bool MigrateNativeCodec2GrallocHandle(
316 native_handle_t *handle,
317 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
318 return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
319}
320
321
Pawin Vongmasa36653902018-11-15 00:10:25 -0800322class C2AllocationGralloc : public C2GraphicAllocation {
323public:
324 virtual ~C2AllocationGralloc() override;
325
326 virtual c2_status_t map(
327 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
328 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
329 virtual c2_status_t unmap(
330 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
331 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
332 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
333 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
334
335 // internal methods
336 // |handle| will be moved.
337 C2AllocationGralloc(
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700338 const BufferDescriptorInfo2 &info,
339 const sp<IMapper2> &mapper,
340 hidl_handle &hidlHandle,
341 const C2HandleGralloc *const handle,
342 C2Allocator::id_t allocatorId);
343 C2AllocationGralloc(
344 const BufferDescriptorInfo3 &info,
345 const sp<IMapper3> &mapper,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800346 hidl_handle &hidlHandle,
347 const C2HandleGralloc *const handle,
348 C2Allocator::id_t allocatorId);
Marissa Wall8806edc2019-06-21 09:50:47 -0700349 C2AllocationGralloc(
350 const BufferDescriptorInfo4 &info,
351 const sp<IMapper4> &mapper,
352 hidl_handle &hidlHandle,
353 const C2HandleGralloc *const handle,
354 C2Allocator::id_t allocatorId);
Pawin Vongmasa36653902018-11-15 00:10:25 -0800355 int dup() const;
356 c2_status_t status() const;
357
358private:
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700359 const BufferDescriptorInfo2 mInfo2{};
360 const sp<IMapper2> mMapper2{nullptr};
361 const BufferDescriptorInfo3 mInfo3{};
362 const sp<IMapper3> mMapper3{nullptr};
Marissa Wall8806edc2019-06-21 09:50:47 -0700363 const BufferDescriptorInfo4 mInfo4{};
364 const sp<IMapper4> mMapper4{nullptr};
Pawin Vongmasa36653902018-11-15 00:10:25 -0800365 const hidl_handle mHidlHandle;
366 const C2HandleGralloc *mHandle;
367 buffer_handle_t mBuffer;
368 const C2HandleGralloc *mLockedHandle;
369 bool mLocked;
370 C2Allocator::id_t mAllocatorId;
371 std::mutex mMappedLock;
372};
373
374C2AllocationGralloc::C2AllocationGralloc(
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700375 const BufferDescriptorInfo2 &info,
376 const sp<IMapper2> &mapper,
Pawin Vongmasa36653902018-11-15 00:10:25 -0800377 hidl_handle &hidlHandle,
378 const C2HandleGralloc *const handle,
379 C2Allocator::id_t allocatorId)
380 : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700381 mInfo2(info),
382 mMapper2(mapper),
383 mHidlHandle(std::move(hidlHandle)),
384 mHandle(handle),
385 mBuffer(nullptr),
386 mLockedHandle(nullptr),
387 mLocked(false),
388 mAllocatorId(allocatorId) {
389}
390
391C2AllocationGralloc::C2AllocationGralloc(
392 const BufferDescriptorInfo3 &info,
393 const sp<IMapper3> &mapper,
394 hidl_handle &hidlHandle,
395 const C2HandleGralloc *const handle,
396 C2Allocator::id_t allocatorId)
397 : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
398 mInfo3(info),
399 mMapper3(mapper),
Pawin Vongmasa36653902018-11-15 00:10:25 -0800400 mHidlHandle(std::move(hidlHandle)),
401 mHandle(handle),
402 mBuffer(nullptr),
403 mLockedHandle(nullptr),
404 mLocked(false),
405 mAllocatorId(allocatorId) {
406}
407
Marissa Wall8806edc2019-06-21 09:50:47 -0700408C2AllocationGralloc::C2AllocationGralloc(
409 const BufferDescriptorInfo4 &info,
410 const sp<IMapper4> &mapper,
411 hidl_handle &hidlHandle,
412 const C2HandleGralloc *const handle,
413 C2Allocator::id_t allocatorId)
414 : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
415 mInfo4(info),
416 mMapper4(mapper),
417 mHidlHandle(std::move(hidlHandle)),
418 mHandle(handle),
419 mBuffer(nullptr),
420 mLockedHandle(nullptr),
421 mLocked(false),
422 mAllocatorId(allocatorId) {
423}
424
Pawin Vongmasa36653902018-11-15 00:10:25 -0800425C2AllocationGralloc::~C2AllocationGralloc() {
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800426 if (mBuffer && mLocked) {
Pawin Vongmasa36653902018-11-15 00:10:25 -0800427 // implementation ignores addresss and rect
428 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
429 unmap(addr, C2Rect(), nullptr);
430 }
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800431 if (mBuffer) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700432 if (mMapper2) {
433 if (!mMapper2->freeBuffer(const_cast<native_handle_t *>(
434 mBuffer)).isOk()) {
435 ALOGE("failed transaction: freeBuffer");
436 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700437 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700438 if (!mMapper3->freeBuffer(const_cast<native_handle_t *>(
439 mBuffer)).isOk()) {
440 ALOGE("failed transaction: freeBuffer");
441 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700442 } else {
443 if (!mMapper4->freeBuffer(const_cast<native_handle_t *>(
444 mBuffer)).isOk()) {
445 ALOGE("failed transaction: freeBuffer");
446 }
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700447 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700448
Yichi Chenfa94a3b2018-12-08 00:06:25 +0800449 }
450 if (mHandle) {
451 native_handle_delete(
452 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
453 }
Sungtak Lee2729dcf2019-01-18 13:15:07 -0800454 if (mLockedHandle) {
455 native_handle_delete(
456 const_cast<native_handle_t *>(
457 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
458 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800459}
460
461c2_status_t C2AllocationGralloc::map(
462 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
463 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
464 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
465 ALOGV("mapping buffer with usage %#llx => %#llx",
466 (long long)usage.expected, (long long)grallocUsage);
467
468 // TODO
469 (void) fence;
470
471 std::lock_guard<std::mutex> lock(mMappedLock);
472 if (mBuffer && mLocked) {
473 ALOGD("already mapped");
474 return C2_DUPLICATE;
475 }
476 if (!layout || !addr) {
477 ALOGD("wrong param");
478 return C2_BAD_VALUE;
479 }
480
481 c2_status_t err = C2_OK;
482 if (!mBuffer) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700483 if (mMapper2) {
484 if (!mMapper2->importBuffer(
485 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
486 err = maperr2error(maperr);
487 if (err == C2_OK) {
488 mBuffer = static_cast<buffer_handle_t>(buffer);
489 }
490 }).isOk()) {
491 ALOGE("failed transaction: importBuffer");
492 return C2_CORRUPTED;
493 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700494 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700495 if (!mMapper3->importBuffer(
496 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
497 err = maperr2error(maperr);
498 if (err == C2_OK) {
499 mBuffer = static_cast<buffer_handle_t>(buffer);
500 }
501 }).isOk()) {
502 ALOGE("failed transaction: importBuffer (@3.0)");
503 return C2_CORRUPTED;
504 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700505 } else {
506 if (!mMapper4->importBuffer(
507 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
508 err = maperr2error(maperr);
509 if (err == C2_OK) {
510 mBuffer = static_cast<buffer_handle_t>(buffer);
511 }
512 }).isOk()) {
513 ALOGE("failed transaction: importBuffer (@4.0)");
514 return C2_CORRUPTED;
515 }
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700516 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800517 if (err != C2_OK) {
518 ALOGD("importBuffer failed: %d", err);
519 return err;
520 }
521 if (mBuffer == nullptr) {
522 ALOGD("importBuffer returned null buffer");
523 return C2_CORRUPTED;
524 }
525 uint32_t generation = 0;
526 uint64_t igbp_id = 0;
527 uint32_t igbp_slot = 0;
528 if (mHandle) {
529 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
530 }
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700531 if (mMapper2) {
532 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
533 mBuffer, mInfo2.mapperInfo.width, mInfo2.mapperInfo.height,
534 (uint32_t)mInfo2.mapperInfo.format, mInfo2.mapperInfo.usage,
535 mInfo2.stride, generation, igbp_id, igbp_slot);
Marissa Wall8806edc2019-06-21 09:50:47 -0700536 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700537 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
538 mBuffer, mInfo3.mapperInfo.width, mInfo3.mapperInfo.height,
539 (uint32_t)mInfo3.mapperInfo.format, mInfo3.mapperInfo.usage,
540 mInfo3.stride, generation, igbp_id, igbp_slot);
Marissa Wall8806edc2019-06-21 09:50:47 -0700541 } else {
542 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
543 mBuffer, mInfo4.mapperInfo.width, mInfo4.mapperInfo.height,
544 (uint32_t)mInfo4.mapperInfo.format, mInfo4.mapperInfo.usage,
545 mInfo4.stride, generation, igbp_id, igbp_slot);
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700546 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800547 }
548
Marissa Wall8806edc2019-06-21 09:50:47 -0700549 PixelFormat4 format;
550 if (mMapper2) {
551 format = PixelFormat4(mInfo2.mapperInfo.format);
552 } else if (mMapper3) {
553 format = PixelFormat4(mInfo3.mapperInfo.format);
554 } else {
555 format = PixelFormat4(mInfo4.mapperInfo.format);
556 }
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700557 switch (format) {
Marissa Wall8806edc2019-06-21 09:50:47 -0700558 case PixelFormat4::RGBA_1010102: {
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700559 // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
560 // Surface. In all other cases it is RGBA. We don't know which case it is here, so
561 // default to YUV for now.
562 void *pointer = nullptr;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700563 if (mMapper2) {
564 if (!mMapper2->lock(
565 const_cast<native_handle_t *>(mBuffer),
566 grallocUsage,
567 { (int32_t)rect.left, (int32_t)rect.top,
568 (int32_t)rect.width, (int32_t)rect.height },
569 // TODO: fence
570 hidl_handle(),
571 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
572 err = maperr2error(maperr);
573 if (err == C2_OK) {
574 pointer = mapPointer;
575 }
576 }).isOk()) {
577 ALOGE("failed transaction: lock(RGBA_1010102)");
578 return C2_CORRUPTED;
579 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700580 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700581 if (!mMapper3->lock(
582 const_cast<native_handle_t *>(mBuffer),
583 grallocUsage,
584 { (int32_t)rect.left, (int32_t)rect.top,
585 (int32_t)rect.width, (int32_t)rect.height },
586 // TODO: fence
587 hidl_handle(),
588 [&err, &pointer](const auto &maperr, const auto &mapPointer,
589 int32_t bytesPerPixel, int32_t bytesPerStride) {
590 err = maperr2error(maperr);
591 if (err == C2_OK) {
592 pointer = mapPointer;
593 }
594 (void)bytesPerPixel;
595 (void)bytesPerStride;
596 }).isOk()) {
597 ALOGE("failed transaction: lock(RGBA_1010102) (@3.0)");
598 return C2_CORRUPTED;
599 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700600 } else {
601 if (!mMapper4->lock(
602 const_cast<native_handle_t *>(mBuffer),
603 grallocUsage,
604 { (int32_t)rect.left, (int32_t)rect.top,
605 (int32_t)rect.width, (int32_t)rect.height },
606 // TODO: fence
607 hidl_handle(),
Marissa Wall469b90a2019-11-06 10:12:43 -0800608 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
Marissa Wall8806edc2019-06-21 09:50:47 -0700609 err = maperr2error(maperr);
610 if (err == C2_OK) {
611 pointer = mapPointer;
612 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700613 }).isOk()) {
614 ALOGE("failed transaction: lock(RGBA_1010102) (@4.0)");
615 return C2_CORRUPTED;
616 }
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700617 }
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700618 if (err != C2_OK) {
619 ALOGD("lock failed: %d", err);
620 return err;
621 }
622 // treat as 32-bit values
623 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
624 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
625 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
626 addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
627 layout->type = C2PlanarLayout::TYPE_YUVA;
628 layout->numPlanes = 4;
629 layout->rootPlanes = 1;
Marissa Wall8806edc2019-06-21 09:50:47 -0700630 int32_t stride;
631 if (mMapper2) {
632 stride = int32_t(mInfo2.stride);
633 } if (mMapper3) {
634 stride = int32_t(mInfo3.stride);
635 } else {
636 stride = int32_t(mInfo4.stride);
637 }
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700638 layout->planes[C2PlanarLayout::PLANE_Y] = {
639 C2PlaneInfo::CHANNEL_Y, // channel
640 4, // colInc
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700641 4 * stride, // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700642 1, // mColSampling
643 1, // mRowSampling
644 32, // allocatedDepth
645 10, // bitDepth
646 10, // rightShift
647 C2PlaneInfo::LITTLE_END, // endianness
648 C2PlanarLayout::PLANE_Y, // rootIx
649 0, // offset
650 };
651 layout->planes[C2PlanarLayout::PLANE_U] = {
652 C2PlaneInfo::CHANNEL_CB, // channel
653 4, // colInc
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700654 4 * stride, // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700655 1, // mColSampling
656 1, // mRowSampling
657 32, // allocatedDepth
658 10, // bitDepth
659 0, // rightShift
660 C2PlaneInfo::LITTLE_END, // endianness
661 C2PlanarLayout::PLANE_Y, // rootIx
662 0, // offset
663 };
664 layout->planes[C2PlanarLayout::PLANE_V] = {
665 C2PlaneInfo::CHANNEL_CR, // channel
666 4, // colInc
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700667 4 * stride, // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700668 1, // mColSampling
669 1, // mRowSampling
670 32, // allocatedDepth
671 10, // bitDepth
672 20, // rightShift
673 C2PlaneInfo::LITTLE_END, // endianness
674 C2PlanarLayout::PLANE_Y, // rootIx
675 0, // offset
676 };
677 layout->planes[C2PlanarLayout::PLANE_A] = {
678 C2PlaneInfo::CHANNEL_A, // channel
679 4, // colInc
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700680 4 * stride, // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700681 1, // mColSampling
682 1, // mRowSampling
683 32, // allocatedDepth
684 2, // bitDepth
685 30, // rightShift
686 C2PlaneInfo::LITTLE_END, // endianness
687 C2PlanarLayout::PLANE_Y, // rootIx
688 0, // offset
689 };
690 break;
691 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800692
Marissa Wall8806edc2019-06-21 09:50:47 -0700693 case PixelFormat4::RGBA_8888:
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700694 // TODO: alpha channel
695 // fall-through
Marissa Wall8806edc2019-06-21 09:50:47 -0700696 case PixelFormat4::RGBX_8888: {
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700697 void *pointer = nullptr;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700698 if (mMapper2) {
699 if (!mMapper2->lock(
700 const_cast<native_handle_t *>(mBuffer),
701 grallocUsage,
702 { (int32_t)rect.left, (int32_t)rect.top,
703 (int32_t)rect.width, (int32_t)rect.height },
704 // TODO: fence
705 hidl_handle(),
706 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
707 err = maperr2error(maperr);
708 if (err == C2_OK) {
709 pointer = mapPointer;
710 }
711 }).isOk()) {
712 ALOGE("failed transaction: lock(RGBA_8888)");
713 return C2_CORRUPTED;
714 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700715 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700716 if (!mMapper3->lock(
717 const_cast<native_handle_t *>(mBuffer),
718 grallocUsage,
719 { (int32_t)rect.left, (int32_t)rect.top,
720 (int32_t)rect.width, (int32_t)rect.height },
721 // TODO: fence
722 hidl_handle(),
723 [&err, &pointer](const auto &maperr, const auto &mapPointer,
724 int32_t bytesPerPixel, int32_t bytesPerStride) {
725 err = maperr2error(maperr);
726 if (err == C2_OK) {
727 pointer = mapPointer;
728 }
729 (void)bytesPerPixel;
730 (void)bytesPerStride;
731 }).isOk()) {
732 ALOGE("failed transaction: lock(RGBA_8888) (@3.0)");
733 return C2_CORRUPTED;
734 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700735 } else {
736 if (!mMapper4->lock(
737 const_cast<native_handle_t *>(mBuffer),
738 grallocUsage,
739 { (int32_t)rect.left, (int32_t)rect.top,
740 (int32_t)rect.width, (int32_t)rect.height },
741 // TODO: fence
742 hidl_handle(),
Marissa Wall469b90a2019-11-06 10:12:43 -0800743 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
Marissa Wall8806edc2019-06-21 09:50:47 -0700744 err = maperr2error(maperr);
745 if (err == C2_OK) {
746 pointer = mapPointer;
747 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700748 }).isOk()) {
749 ALOGE("failed transaction: lock(RGBA_8888) (@4.0)");
750 return C2_CORRUPTED;
751 }
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700752 }
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700753 if (err != C2_OK) {
754 ALOGD("lock failed: %d", err);
755 return err;
756 }
757 addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
758 addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
759 addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
760 layout->type = C2PlanarLayout::TYPE_RGB;
761 layout->numPlanes = 3;
762 layout->rootPlanes = 1;
Marissa Wall8806edc2019-06-21 09:50:47 -0700763 int32_t stride;
764 if (mMapper2) {
765 stride = int32_t(mInfo2.stride);
766 } if (mMapper3) {
767 stride = int32_t(mInfo3.stride);
768 } else {
769 stride = int32_t(mInfo4.stride);
770 }
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700771 layout->planes[C2PlanarLayout::PLANE_R] = {
772 C2PlaneInfo::CHANNEL_R, // channel
773 4, // colInc
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700774 4 * stride, // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700775 1, // mColSampling
776 1, // mRowSampling
777 8, // allocatedDepth
778 8, // bitDepth
779 0, // rightShift
780 C2PlaneInfo::NATIVE, // endianness
781 C2PlanarLayout::PLANE_R, // rootIx
782 0, // offset
783 };
784 layout->planes[C2PlanarLayout::PLANE_G] = {
785 C2PlaneInfo::CHANNEL_G, // channel
786 4, // colInc
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700787 4 * stride, // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700788 1, // mColSampling
789 1, // mRowSampling
790 8, // allocatedDepth
791 8, // bitDepth
792 0, // rightShift
793 C2PlaneInfo::NATIVE, // endianness
794 C2PlanarLayout::PLANE_R, // rootIx
795 1, // offset
796 };
797 layout->planes[C2PlanarLayout::PLANE_B] = {
798 C2PlaneInfo::CHANNEL_B, // channel
799 4, // colInc
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700800 4 * stride, // rowInc
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700801 1, // mColSampling
802 1, // mRowSampling
803 8, // allocatedDepth
804 8, // bitDepth
805 0, // rightShift
806 C2PlaneInfo::NATIVE, // endianness
807 C2PlanarLayout::PLANE_R, // rootIx
808 2, // offset
809 };
810 break;
811 }
812
Marissa Wall8806edc2019-06-21 09:50:47 -0700813 case PixelFormat4::YCBCR_420_888:
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700814 // fall-through
Marissa Wall8806edc2019-06-21 09:50:47 -0700815 case PixelFormat4::YV12:
Lajos Molnar35d36cb2018-10-12 15:10:56 -0700816 // fall-through
817 default: {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700818 struct YCbCrLayout {
819 void* y;
820 void* cb;
821 void* cr;
822 uint32_t yStride;
823 uint32_t cStride;
824 uint32_t chromaStep;
825 };
Pawin Vongmasa36653902018-11-15 00:10:25 -0800826 YCbCrLayout ycbcrLayout;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700827 if (mMapper2) {
828 if (!mMapper2->lockYCbCr(
829 const_cast<native_handle_t *>(mBuffer), grallocUsage,
830 { (int32_t)rect.left, (int32_t)rect.top,
831 (int32_t)rect.width, (int32_t)rect.height },
832 // TODO: fence
833 hidl_handle(),
834 [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
835 err = maperr2error(maperr);
836 if (err == C2_OK) {
837 ycbcrLayout = YCbCrLayout{
838 mapLayout.y,
839 mapLayout.cb,
840 mapLayout.cr,
841 mapLayout.yStride,
842 mapLayout.cStride,
843 mapLayout.chromaStep};
844 }
845 }).isOk()) {
846 ALOGE("failed transaction: lockYCbCr");
847 return C2_CORRUPTED;
848 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700849 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700850 if (!mMapper3->lockYCbCr(
851 const_cast<native_handle_t *>(mBuffer), grallocUsage,
852 { (int32_t)rect.left, (int32_t)rect.top,
853 (int32_t)rect.width, (int32_t)rect.height },
854 // TODO: fence
855 hidl_handle(),
856 [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
857 err = maperr2error(maperr);
858 if (err == C2_OK) {
859 ycbcrLayout = YCbCrLayout{
860 mapLayout.y,
861 mapLayout.cb,
862 mapLayout.cr,
863 mapLayout.yStride,
864 mapLayout.cStride,
865 mapLayout.chromaStep};
866 }
867 }).isOk()) {
868 ALOGE("failed transaction: lockYCbCr (@3.0)");
869 return C2_CORRUPTED;
870 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700871 } else {
Marissa Wall469b90a2019-11-06 10:12:43 -0800872 // No device currently supports IMapper 4.0 so it is safe to just return an error
873 // code here.
874 //
875 // This will be supported by a combination of lock and BufferMetadata getters.
876 // We are going to refactor all the IAllocator/IMapper versioning code into a
877 // shared library. We will then add the IMapper 4.0 lockYCbCr support then.
878 ALOGE("failed transaction: lockYCbCr (@4.0)");
879 return C2_CORRUPTED;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700880 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800881 if (err != C2_OK) {
882 ALOGD("lockYCbCr failed: %d", err);
883 return err;
884 }
885 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
886 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
887 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
888 layout->type = C2PlanarLayout::TYPE_YUV;
889 layout->numPlanes = 3;
890 layout->rootPlanes = 3;
891 layout->planes[C2PlanarLayout::PLANE_Y] = {
892 C2PlaneInfo::CHANNEL_Y, // channel
893 1, // colInc
894 (int32_t)ycbcrLayout.yStride, // rowInc
895 1, // mColSampling
896 1, // mRowSampling
897 8, // allocatedDepth
898 8, // bitDepth
899 0, // rightShift
900 C2PlaneInfo::NATIVE, // endianness
901 C2PlanarLayout::PLANE_Y, // rootIx
902 0, // offset
903 };
904 layout->planes[C2PlanarLayout::PLANE_U] = {
905 C2PlaneInfo::CHANNEL_CB, // channel
906 (int32_t)ycbcrLayout.chromaStep, // colInc
907 (int32_t)ycbcrLayout.cStride, // rowInc
908 2, // mColSampling
909 2, // mRowSampling
910 8, // allocatedDepth
911 8, // bitDepth
912 0, // rightShift
913 C2PlaneInfo::NATIVE, // endianness
914 C2PlanarLayout::PLANE_U, // rootIx
915 0, // offset
916 };
917 layout->planes[C2PlanarLayout::PLANE_V] = {
918 C2PlaneInfo::CHANNEL_CR, // channel
919 (int32_t)ycbcrLayout.chromaStep, // colInc
920 (int32_t)ycbcrLayout.cStride, // rowInc
921 2, // mColSampling
922 2, // mRowSampling
923 8, // allocatedDepth
924 8, // bitDepth
925 0, // rightShift
926 C2PlaneInfo::NATIVE, // endianness
927 C2PlanarLayout::PLANE_V, // rootIx
928 0, // offset
929 };
930 // handle interleaved formats
931 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
932 if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
933 layout->rootPlanes = 2;
934 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
935 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
936 } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
937 layout->rootPlanes = 2;
938 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
939 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
940 }
941 break;
942 }
Pawin Vongmasa36653902018-11-15 00:10:25 -0800943 }
944 mLocked = true;
945
946 return C2_OK;
947}
948
949c2_status_t C2AllocationGralloc::unmap(
950 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
951 // TODO: check addr and size, use fence
952 (void)addr;
953 (void)rect;
954
955 std::lock_guard<std::mutex> lock(mMappedLock);
956 c2_status_t err = C2_OK;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700957 if (mMapper2) {
958 if (!mMapper2->unlock(
959 const_cast<native_handle_t *>(mBuffer),
960 [&err, &fence](const auto &maperr, const auto &releaseFence) {
961 // TODO
962 (void) fence;
963 (void) releaseFence;
964 err = maperr2error(maperr);
965 if (err == C2_OK) {
966 // TODO: fence
967 }
968 }).isOk()) {
969 ALOGE("failed transaction: unlock");
970 return C2_CORRUPTED;
971 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700972 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -0700973 if (!mMapper3->unlock(
974 const_cast<native_handle_t *>(mBuffer),
975 [&err, &fence](const auto &maperr, const auto &releaseFence) {
976 // TODO
977 (void) fence;
978 (void) releaseFence;
979 err = maperr2error(maperr);
980 if (err == C2_OK) {
981 // TODO: fence
982 }
983 }).isOk()) {
984 ALOGE("failed transaction: unlock (@3.0)");
985 return C2_CORRUPTED;
986 }
Marissa Wall8806edc2019-06-21 09:50:47 -0700987 } else {
988 if (!mMapper4->unlock(
989 const_cast<native_handle_t *>(mBuffer),
990 [&err, &fence](const auto &maperr, const auto &releaseFence) {
991 // TODO
992 (void) fence;
993 (void) releaseFence;
994 err = maperr2error(maperr);
995 if (err == C2_OK) {
996 // TODO: fence
997 }
998 }).isOk()) {
999 ALOGE("failed transaction: unlock (@4.0)");
1000 return C2_CORRUPTED;
1001 }
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001002 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001003 if (err == C2_OK) {
1004 mLocked = false;
1005 }
1006 return err;
1007}
1008
1009bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
1010 return other && other->handle() == handle();
1011}
1012
1013/* ===================================== GRALLOC ALLOCATOR ==================================== */
1014class C2AllocatorGralloc::Impl {
1015public:
1016 Impl(id_t id, bool bufferQueue);
1017
1018 id_t getId() const {
1019 return mTraits->id;
1020 }
1021
1022 C2String getName() const {
1023 return mTraits->name;
1024 }
1025
1026 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
1027 return mTraits;
1028 }
1029
1030 c2_status_t newGraphicAllocation(
1031 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1032 std::shared_ptr<C2GraphicAllocation> *allocation);
1033
1034 c2_status_t priorGraphicAllocation(
1035 const C2Handle *handle,
1036 std::shared_ptr<C2GraphicAllocation> *allocation);
1037
1038 c2_status_t status() const { return mInit; }
1039
1040private:
1041 std::shared_ptr<C2Allocator::Traits> mTraits;
1042 c2_status_t mInit;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001043 sp<IAllocator2> mAllocator2;
1044 sp<IMapper2> mMapper2;
1045 sp<IAllocator3> mAllocator3;
1046 sp<IMapper3> mMapper3;
Marissa Wall8806edc2019-06-21 09:50:47 -07001047 sp<IAllocator4> mAllocator4;
1048 sp<IMapper4> mMapper4;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001049 const bool mBufferQueue;
1050};
1051
1052void _UnwrapNativeCodec2GrallocMetadata(
1053 const C2Handle *const handle,
1054 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
1055 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
1056 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
1057 generation, igbp_id, igbp_slot);
1058}
1059
1060C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
1061 : mInit(C2_OK), mBufferQueue(bufferQueue) {
1062 // TODO: get this from allocator
1063 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
1064 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
1065 mTraits = std::make_shared<C2Allocator::Traits>(traits);
1066
1067 // gralloc allocator is a singleton, so all objects share a global service
Marissa Wall8806edc2019-06-21 09:50:47 -07001068 mAllocator4 = IAllocator4::getService();
1069 mMapper4 = IMapper4::getService();
1070 if (!mAllocator4 || !mMapper4) {
1071 mAllocator4 = nullptr;
1072 mMapper4 = nullptr;
1073 mAllocator3 = IAllocator3::getService();
1074 mMapper3 = IMapper3::getService();
1075 if (!mAllocator3 || !mMapper3) {
1076 mAllocator3 = nullptr;
1077 mMapper3 = nullptr;
1078 mAllocator2 = IAllocator2::getService();
1079 mMapper2 = IMapper2::getService();
1080 if (!mAllocator2 || !mMapper2) {
1081 mAllocator2 = nullptr;
1082 mMapper2 = nullptr;
1083 mInit = C2_CORRUPTED;
1084 }
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001085 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001086 }
1087}
1088
1089c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
1090 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
1091 std::shared_ptr<C2GraphicAllocation> *allocation) {
1092 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
1093 ALOGV("allocating buffer with usage %#llx => %#llx",
1094 (long long)usage.expected, (long long)grallocUsage);
1095
Pawin Vongmasa36653902018-11-15 00:10:25 -08001096 c2_status_t err = C2_OK;
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001097 hidl_handle buffer{};
1098
1099 if (mMapper2) {
1100 BufferDescriptorInfo2 info = {
1101 {
1102 width,
1103 height,
1104 1u, // layerCount
1105 PixelFormat2(format),
1106 grallocUsage,
1107 },
1108 0u, // stride placeholder
1109 };
1110 BufferDescriptor2 desc;
1111 if (!mMapper2->createDescriptor(
1112 info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
1113 err = maperr2error(maperr);
1114 if (err == C2_OK) {
1115 desc = descriptor;
1116 }
1117 }).isOk()) {
1118 ALOGE("failed transaction: createDescriptor");
1119 return C2_CORRUPTED;
1120 }
1121 if (err != C2_OK) {
1122 return err;
1123 }
1124
1125 // IAllocator shares IMapper error codes.
1126 if (!mAllocator2->allocate(
1127 desc,
1128 1u,
1129 [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
1130 err = maperr2error(maperr);
1131 if (err != C2_OK) {
1132 return;
1133 }
1134 if (buffers.size() != 1u) {
1135 err = C2_CORRUPTED;
1136 return;
1137 }
1138 info.stride = stride;
1139 buffer = buffers[0];
1140 }).isOk()) {
1141 ALOGE("failed transaction: allocate");
1142 return C2_CORRUPTED;
1143 }
1144 if (err != C2_OK) {
1145 return err;
1146 }
1147 allocation->reset(new C2AllocationGralloc(
1148 info, mMapper2, buffer,
1149 C2HandleGralloc::WrapAndMoveNativeHandle(
1150 buffer.getNativeHandle(),
1151 width, height,
1152 format, grallocUsage, info.stride,
1153 0, 0, mBufferQueue ? ~0 : 0),
1154 mTraits->id));
1155 return C2_OK;
Marissa Wall8806edc2019-06-21 09:50:47 -07001156 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001157 BufferDescriptorInfo3 info = {
1158 {
1159 width,
1160 height,
1161 1u, // layerCount
Marissa Wall8806edc2019-06-21 09:50:47 -07001162 PixelFormat4(format),
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001163 grallocUsage,
1164 },
1165 0u, // stride placeholder
1166 };
1167 BufferDescriptor3 desc;
1168 if (!mMapper3->createDescriptor(
1169 info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
1170 err = maperr2error(maperr);
1171 if (err == C2_OK) {
1172 desc = descriptor;
1173 }
1174 }).isOk()) {
1175 ALOGE("failed transaction: createDescriptor");
1176 return C2_CORRUPTED;
1177 }
1178 if (err != C2_OK) {
1179 return err;
1180 }
1181
1182 // IAllocator shares IMapper error codes.
1183 if (!mAllocator3->allocate(
1184 desc,
1185 1u,
1186 [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
1187 err = maperr2error(maperr);
1188 if (err != C2_OK) {
1189 return;
1190 }
1191 if (buffers.size() != 1u) {
1192 err = C2_CORRUPTED;
1193 return;
1194 }
1195 info.stride = stride;
1196 buffer = buffers[0];
1197 }).isOk()) {
1198 ALOGE("failed transaction: allocate");
1199 return C2_CORRUPTED;
1200 }
1201 if (err != C2_OK) {
1202 return err;
1203 }
1204 allocation->reset(new C2AllocationGralloc(
1205 info, mMapper3, buffer,
1206 C2HandleGralloc::WrapAndMoveNativeHandle(
1207 buffer.getNativeHandle(),
1208 width, height,
1209 format, grallocUsage, info.stride,
1210 0, 0, mBufferQueue ? ~0 : 0),
1211 mTraits->id));
1212 return C2_OK;
Marissa Wall8806edc2019-06-21 09:50:47 -07001213 } else {
1214 BufferDescriptorInfo4 info = {
1215 {
Marissa Wallc759fc52019-11-06 10:11:11 -08001216 "C2GrallocAllocation",
Marissa Wall8806edc2019-06-21 09:50:47 -07001217 width,
1218 height,
1219 1u, // layerCount
1220 PixelFormat4(format),
1221 grallocUsage,
1222 },
1223 0u, // stride placeholder
1224 };
1225 BufferDescriptor4 desc;
1226 if (!mMapper4->createDescriptor(
1227 info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
1228 err = maperr2error(maperr);
1229 if (err == C2_OK) {
1230 desc = descriptor;
1231 }
1232 }).isOk()) {
1233 ALOGE("failed transaction: createDescriptor");
1234 return C2_CORRUPTED;
1235 }
1236 if (err != C2_OK) {
1237 return err;
1238 }
1239
1240 // IAllocator shares IMapper error codes.
1241 if (!mAllocator4->allocate(
1242 desc,
1243 1u,
1244 [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
1245 err = maperr2error(maperr);
1246 if (err != C2_OK) {
1247 return;
1248 }
1249 if (buffers.size() != 1u) {
1250 err = C2_CORRUPTED;
1251 return;
1252 }
1253 info.stride = stride;
1254 buffer = buffers[0];
1255 }).isOk()) {
1256 ALOGE("failed transaction: allocate");
1257 return C2_CORRUPTED;
1258 }
1259 if (err != C2_OK) {
1260 return err;
1261 }
1262 allocation->reset(new C2AllocationGralloc(
1263 info, mMapper4, buffer,
1264 C2HandleGralloc::WrapAndMoveNativeHandle(
1265 buffer.getNativeHandle(),
1266 width, height,
1267 format, grallocUsage, info.stride,
1268 0, 0, mBufferQueue ? ~0 : 0),
1269 mTraits->id));
1270 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001271 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001272}
1273
1274c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
1275 const C2Handle *handle,
1276 std::shared_ptr<C2GraphicAllocation> *allocation) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001277 if (mMapper2) {
1278 BufferDescriptorInfo2 info;
1279 info.mapperInfo.layerCount = 1u;
1280 uint32_t generation;
1281 uint64_t igbp_id;
1282 uint32_t igbp_slot;
1283 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
1284 handle,
1285 &info.mapperInfo.width, &info.mapperInfo.height,
1286 (uint32_t *)&info.mapperInfo.format,
1287 (uint64_t *)&info.mapperInfo.usage,
1288 &info.stride,
1289 &generation, &igbp_id, &igbp_slot);
1290 if (grallocHandle == nullptr) {
1291 return C2_BAD_VALUE;
1292 }
1293
1294 hidl_handle hidlHandle;
1295 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
1296
1297 allocation->reset(new C2AllocationGralloc(
1298 info, mMapper2, hidlHandle, grallocHandle, mTraits->id));
1299 return C2_OK;
Marissa Wall8806edc2019-06-21 09:50:47 -07001300 } else if (mMapper3) {
Pawin Vongmasad032f2d2019-05-15 08:42:44 -07001301 BufferDescriptorInfo3 info;
1302 info.mapperInfo.layerCount = 1u;
1303 uint32_t generation;
1304 uint64_t igbp_id;
1305 uint32_t igbp_slot;
1306 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
1307 handle,
1308 &info.mapperInfo.width, &info.mapperInfo.height,
1309 (uint32_t *)&info.mapperInfo.format,
1310 (uint64_t *)&info.mapperInfo.usage,
1311 &info.stride,
1312 &generation, &igbp_id, &igbp_slot);
1313 if (grallocHandle == nullptr) {
1314 return C2_BAD_VALUE;
1315 }
1316
1317 hidl_handle hidlHandle;
1318 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
1319
1320 allocation->reset(new C2AllocationGralloc(
1321 info, mMapper3, hidlHandle, grallocHandle, mTraits->id));
1322 return C2_OK;
Marissa Wall8806edc2019-06-21 09:50:47 -07001323 } else {
1324 BufferDescriptorInfo4 info;
1325 info.mapperInfo.layerCount = 1u;
1326 uint32_t generation;
1327 uint64_t igbp_id;
1328 uint32_t igbp_slot;
1329 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
1330 handle,
1331 &info.mapperInfo.width, &info.mapperInfo.height,
1332 (uint32_t *)&info.mapperInfo.format,
1333 (uint64_t *)&info.mapperInfo.usage,
1334 &info.stride,
1335 &generation, &igbp_id, &igbp_slot);
1336 if (grallocHandle == nullptr) {
1337 return C2_BAD_VALUE;
1338 }
1339
1340 hidl_handle hidlHandle;
1341 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
1342
1343 allocation->reset(new C2AllocationGralloc(
1344 info, mMapper4, hidlHandle, grallocHandle, mTraits->id));
1345 return C2_OK;
Pawin Vongmasa36653902018-11-15 00:10:25 -08001346 }
Pawin Vongmasa36653902018-11-15 00:10:25 -08001347}
1348
1349C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
1350 : mImpl(new Impl(id, bufferQueue)) {}
1351
1352C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
1353
1354C2Allocator::id_t C2AllocatorGralloc::getId() const {
1355 return mImpl->getId();
1356}
1357
1358C2String C2AllocatorGralloc::getName() const {
1359 return mImpl->getName();
1360}
1361
1362std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
1363 return mImpl->getTraits();
1364}
1365
1366c2_status_t C2AllocatorGralloc::newGraphicAllocation(
1367 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
1368 std::shared_ptr<C2GraphicAllocation> *allocation) {
1369 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
1370}
1371
1372c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
1373 const C2Handle *handle,
1374 std::shared_ptr<C2GraphicAllocation> *allocation) {
1375 return mImpl->priorGraphicAllocation(handle, allocation);
1376}
1377
1378c2_status_t C2AllocatorGralloc::status() const {
1379 return mImpl->status();
1380}
1381
1382bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
1383 return C2HandleGralloc::isValid(o);
1384}
1385
1386} // namespace android