1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2AllocatorGralloc"
19 #include <utils/Log.h>
20
21 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
22 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
23 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
24 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
25 #include <cutils/native_handle.h>
26 #include <hardware/gralloc.h>
27
28 #include <C2AllocatorGralloc.h>
29 #include <C2Buffer.h>
30 #include <C2PlatformSupport.h>
31
32 namespace android {
33
34 namespace /* unnamed */ {
35 enum : uint64_t {
36 /**
37 * Usage mask that is passed through from gralloc to Codec 2.0 usage.
38 */
39 PASSTHROUGH_USAGE_MASK =
40 ~(GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_PROTECTED)
41 };
42
43 // verify that passthrough mask is within the platform mask
44 static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
45 } // unnamed
46
FromGrallocUsage(uint64_t usage)47 C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
48 // gralloc does not support WRITE_PROTECTED
49 return C2MemoryUsage(
50 ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) |
51 ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) |
52 ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) |
53 (usage & PASSTHROUGH_USAGE_MASK));
54 }
55
asGrallocUsage() const56 uint64_t C2AndroidMemoryUsage::asGrallocUsage() const {
57 // gralloc does not support WRITE_PROTECTED
58 return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) |
59 ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) |
60 ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) |
61 (expected & PASSTHROUGH_USAGE_MASK));
62 }
63
64 using ::android::hardware::hidl_handle;
65 using ::android::hardware::hidl_vec;
66 using ::android::hardware::graphics::common::V1_0::BufferUsage;
67 using PixelFormat2 = ::android::hardware::graphics::common::V1_0::PixelFormat;
68 using PixelFormat3 = ::android::hardware::graphics::common::V1_2::PixelFormat;
69
70 using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
71 using BufferDescriptor2 = ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
72 using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
73 using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
74
75 using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
76 using BufferDescriptor3 = ::android::hardware::graphics::mapper::V3_0::BufferDescriptor;
77 using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
78 using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
79
80 namespace /* unnamed */ {
81
82 struct BufferDescriptorInfo2 {
83 IMapper2::BufferDescriptorInfo mapperInfo;
84 uint32_t stride;
85 };
86
87 struct BufferDescriptorInfo3 {
88 IMapper3::BufferDescriptorInfo mapperInfo;
89 uint32_t stride;
90 };
91
92 /* ===================================== GRALLOC ALLOCATION ==================================== */
maperr2error(Error2 maperr)93 c2_status_t maperr2error(Error2 maperr) {
94 switch (maperr) {
95 case Error2::NONE: return C2_OK;
96 case Error2::BAD_DESCRIPTOR: return C2_BAD_VALUE;
97 case Error2::BAD_BUFFER: return C2_BAD_VALUE;
98 case Error2::BAD_VALUE: return C2_BAD_VALUE;
99 case Error2::NO_RESOURCES: return C2_NO_MEMORY;
100 case Error2::UNSUPPORTED: return C2_CANNOT_DO;
101 }
102 return C2_CORRUPTED;
103 }
104
maperr2error(Error3 maperr)105 c2_status_t maperr2error(Error3 maperr) {
106 switch (maperr) {
107 case Error3::NONE: return C2_OK;
108 case Error3::BAD_DESCRIPTOR: return C2_BAD_VALUE;
109 case Error3::BAD_BUFFER: return C2_BAD_VALUE;
110 case Error3::BAD_VALUE: return C2_BAD_VALUE;
111 case Error3::NO_RESOURCES: return C2_NO_MEMORY;
112 case Error3::UNSUPPORTED: return C2_CANNOT_DO;
113 }
114 return C2_CORRUPTED;
115 }
116
native_handle_is_invalid(const native_handle_t * const handle)117 bool native_handle_is_invalid(const native_handle_t *const handle) {
118 // perform basic validation of a native handle
119 if (handle == nullptr) {
120 // null handle is considered valid
121 return false;
122 }
123 return ((size_t)handle->version != sizeof(native_handle_t) ||
124 handle->numFds < 0 ||
125 handle->numInts < 0 ||
126 // for sanity assume handles must occupy less memory than INT_MAX bytes
127 handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts);
128 }
129
130 class C2HandleGralloc : public C2Handle {
131 private:
132 struct ExtraData {
133 uint32_t width;
134 uint32_t height;
135 uint32_t format;
136 uint32_t usage_lo;
137 uint32_t usage_hi;
138 uint32_t stride;
139 uint32_t generation;
140 uint32_t igbp_id_lo;
141 uint32_t igbp_id_hi;
142 uint32_t igbp_slot;
143 uint32_t magic;
144 };
145
146 enum {
147 NUM_INTS = sizeof(ExtraData) / sizeof(int),
148 };
149 const static uint32_t MAGIC = '\xc2gr\x00';
150
151 static
getExtraData(const C2Handle * const handle)152 const ExtraData* getExtraData(const C2Handle *const handle) {
153 if (handle == nullptr
154 || native_handle_is_invalid(handle)
155 || handle->numInts < NUM_INTS) {
156 return nullptr;
157 }
158 return reinterpret_cast<const ExtraData*>(
159 &handle->data[handle->numFds + handle->numInts - NUM_INTS]);
160 }
161
162 static
getExtraData(C2Handle * const handle)163 ExtraData *getExtraData(C2Handle *const handle) {
164 return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle)));
165 }
166
167 public:
getIgbpData(uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot) const168 void getIgbpData(uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) const {
169 const ExtraData *ed = getExtraData(this);
170 *generation = ed->generation;
171 *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32;
172 *igbp_slot = ed->igbp_slot;
173 }
174
isValid(const C2Handle * const o)175 static bool isValid(const C2Handle *const o) {
176 if (o == nullptr) { // null handle is always valid
177 return true;
178 }
179 const ExtraData *xd = getExtraData(o);
180 // we cannot validate width/height/format/usage without accessing gralloc driver
181 return xd != nullptr && xd->magic == MAGIC;
182 }
183
WrapAndMoveNativeHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id=0,uint32_t igbp_slot=0)184 static C2HandleGralloc* WrapAndMoveNativeHandle(
185 const native_handle_t *const handle,
186 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
187 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
188 //CHECK(handle != nullptr);
189 if (native_handle_is_invalid(handle) ||
190 handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) {
191 return nullptr;
192 }
193 ExtraData xd = {
194 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32),
195 stride, generation, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32),
196 igbp_slot, MAGIC
197 };
198 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS);
199 if (res != nullptr) {
200 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts));
201 *getExtraData(res) = xd;
202 }
203 return reinterpret_cast<C2HandleGralloc *>(res);
204 }
205
WrapNativeHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id=0,uint32_t igbp_slot=0)206 static C2HandleGralloc* WrapNativeHandle(
207 const native_handle_t *const handle,
208 uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
209 uint32_t stride, uint32_t generation, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) {
210 if (handle == nullptr) {
211 return nullptr;
212 }
213 native_handle_t *clone = native_handle_clone(handle);
214 if (clone == nullptr) {
215 return nullptr;
216 }
217 C2HandleGralloc *res = WrapAndMoveNativeHandle(
218 clone, width, height, format, usage, stride, generation, igbp_id, igbp_slot);
219 if (res == nullptr) {
220 native_handle_close(clone);
221 }
222 native_handle_delete(clone);
223 return res;
224 }
225
MigrateNativeHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)226 static bool MigrateNativeHandle(
227 native_handle_t *handle,
228 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
229 if (handle == nullptr || !isValid(handle)) {
230 return false;
231 }
232 ExtraData *ed = getExtraData(handle);
233 if (!ed) return false;
234 ed->generation = generation;
235 ed->igbp_id_lo = uint32_t(igbp_id & 0xFFFFFFFF);
236 ed->igbp_id_hi = uint32_t(igbp_id >> 32);
237 ed->igbp_slot = igbp_slot;
238 return true;
239 }
240
241
UnwrapNativeHandle(const C2Handle * const handle)242 static native_handle_t* UnwrapNativeHandle(
243 const C2Handle *const handle) {
244 const ExtraData *xd = getExtraData(handle);
245 if (xd == nullptr || xd->magic != MAGIC) {
246 return nullptr;
247 }
248 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS);
249 if (res != nullptr) {
250 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts));
251 }
252 return res;
253 }
254
Import(const C2Handle * const handle,uint32_t * width,uint32_t * height,uint32_t * format,uint64_t * usage,uint32_t * stride,uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot)255 static const C2HandleGralloc* Import(
256 const C2Handle *const handle,
257 uint32_t *width, uint32_t *height, uint32_t *format,
258 uint64_t *usage, uint32_t *stride,
259 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
260 const ExtraData *xd = getExtraData(handle);
261 if (xd == nullptr) {
262 return nullptr;
263 }
264 *width = xd->width;
265 *height = xd->height;
266 *format = xd->format;
267 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32);
268 *stride = xd->stride;
269 *generation = xd->generation;
270 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32);
271 *igbp_slot = xd->igbp_slot;
272 return reinterpret_cast<const C2HandleGralloc *>(handle);
273 }
274 };
275
276 } // unnamed namespace
277
UnwrapNativeCodec2GrallocHandle(const C2Handle * const handle)278 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) {
279 return C2HandleGralloc::UnwrapNativeHandle(handle);
280 }
281
WrapNativeCodec2GrallocHandle(const native_handle_t * const handle,uint32_t width,uint32_t height,uint32_t format,uint64_t usage,uint32_t stride,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)282 C2Handle *WrapNativeCodec2GrallocHandle(
283 const native_handle_t *const handle,
284 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride,
285 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
286 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride,
287 generation, igbp_id, igbp_slot);
288 }
289
MigrateNativeCodec2GrallocHandle(native_handle_t * handle,uint32_t generation,uint64_t igbp_id,uint32_t igbp_slot)290 bool MigrateNativeCodec2GrallocHandle(
291 native_handle_t *handle,
292 uint32_t generation, uint64_t igbp_id, uint32_t igbp_slot) {
293 return C2HandleGralloc::MigrateNativeHandle(handle, generation, igbp_id, igbp_slot);
294 }
295
296
297 class C2AllocationGralloc : public C2GraphicAllocation {
298 public:
299 virtual ~C2AllocationGralloc() override;
300
301 virtual c2_status_t map(
302 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
303 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override;
304 virtual c2_status_t unmap(
305 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override;
getAllocatorId() const306 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; }
handle() const307 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; }
308 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override;
309
310 // internal methods
311 // |handle| will be moved.
312 C2AllocationGralloc(
313 const BufferDescriptorInfo2 &info,
314 const sp<IMapper2> &mapper,
315 hidl_handle &hidlHandle,
316 const C2HandleGralloc *const handle,
317 C2Allocator::id_t allocatorId);
318 C2AllocationGralloc(
319 const BufferDescriptorInfo3 &info,
320 const sp<IMapper3> &mapper,
321 hidl_handle &hidlHandle,
322 const C2HandleGralloc *const handle,
323 C2Allocator::id_t allocatorId);
324 int dup() const;
325 c2_status_t status() const;
326
327 private:
328 const BufferDescriptorInfo2 mInfo2{};
329 const sp<IMapper2> mMapper2{nullptr};
330 const BufferDescriptorInfo3 mInfo3{};
331 const sp<IMapper3> mMapper3{nullptr};
332 const hidl_handle mHidlHandle;
333 const C2HandleGralloc *mHandle;
334 buffer_handle_t mBuffer;
335 const C2HandleGralloc *mLockedHandle;
336 bool mLocked;
337 C2Allocator::id_t mAllocatorId;
338 std::mutex mMappedLock;
339 };
340
C2AllocationGralloc(const BufferDescriptorInfo2 & info,const sp<IMapper2> & mapper,hidl_handle & hidlHandle,const C2HandleGralloc * const handle,C2Allocator::id_t allocatorId)341 C2AllocationGralloc::C2AllocationGralloc(
342 const BufferDescriptorInfo2 &info,
343 const sp<IMapper2> &mapper,
344 hidl_handle &hidlHandle,
345 const C2HandleGralloc *const handle,
346 C2Allocator::id_t allocatorId)
347 : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
348 mInfo2(info),
349 mMapper2(mapper),
350 mHidlHandle(std::move(hidlHandle)),
351 mHandle(handle),
352 mBuffer(nullptr),
353 mLockedHandle(nullptr),
354 mLocked(false),
355 mAllocatorId(allocatorId) {
356 }
357
C2AllocationGralloc(const BufferDescriptorInfo3 & info,const sp<IMapper3> & mapper,hidl_handle & hidlHandle,const C2HandleGralloc * const handle,C2Allocator::id_t allocatorId)358 C2AllocationGralloc::C2AllocationGralloc(
359 const BufferDescriptorInfo3 &info,
360 const sp<IMapper3> &mapper,
361 hidl_handle &hidlHandle,
362 const C2HandleGralloc *const handle,
363 C2Allocator::id_t allocatorId)
364 : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height),
365 mInfo3(info),
366 mMapper3(mapper),
367 mHidlHandle(std::move(hidlHandle)),
368 mHandle(handle),
369 mBuffer(nullptr),
370 mLockedHandle(nullptr),
371 mLocked(false),
372 mAllocatorId(allocatorId) {
373 }
374
~C2AllocationGralloc()375 C2AllocationGralloc::~C2AllocationGralloc() {
376 if (mBuffer && mLocked) {
377 // implementation ignores addresss and rect
378 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {};
379 unmap(addr, C2Rect(), nullptr);
380 }
381 if (mBuffer) {
382 if (mMapper2) {
383 if (!mMapper2->freeBuffer(const_cast<native_handle_t *>(
384 mBuffer)).isOk()) {
385 ALOGE("failed transaction: freeBuffer");
386 }
387 } else {
388 if (!mMapper3->freeBuffer(const_cast<native_handle_t *>(
389 mBuffer)).isOk()) {
390 ALOGE("failed transaction: freeBuffer");
391 }
392 }
393 }
394 if (mHandle) {
395 native_handle_delete(
396 const_cast<native_handle_t *>(reinterpret_cast<const native_handle_t *>(mHandle)));
397 }
398 if (mLockedHandle) {
399 native_handle_delete(
400 const_cast<native_handle_t *>(
401 reinterpret_cast<const native_handle_t *>(mLockedHandle)));
402 }
403 }
404
map(C2Rect rect,C2MemoryUsage usage,C2Fence * fence,C2PlanarLayout * layout,uint8_t ** addr)405 c2_status_t C2AllocationGralloc::map(
406 C2Rect rect, C2MemoryUsage usage, C2Fence *fence,
407 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) {
408 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
409 ALOGV("mapping buffer with usage %#llx => %#llx",
410 (long long)usage.expected, (long long)grallocUsage);
411
412 // TODO
413 (void) fence;
414
415 std::lock_guard<std::mutex> lock(mMappedLock);
416 if (mBuffer && mLocked) {
417 ALOGD("already mapped");
418 return C2_DUPLICATE;
419 }
420 if (!layout || !addr) {
421 ALOGD("wrong param");
422 return C2_BAD_VALUE;
423 }
424
425 c2_status_t err = C2_OK;
426 if (!mBuffer) {
427 if (mMapper2) {
428 if (!mMapper2->importBuffer(
429 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
430 err = maperr2error(maperr);
431 if (err == C2_OK) {
432 mBuffer = static_cast<buffer_handle_t>(buffer);
433 }
434 }).isOk()) {
435 ALOGE("failed transaction: importBuffer");
436 return C2_CORRUPTED;
437 }
438 } else {
439 if (!mMapper3->importBuffer(
440 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) {
441 err = maperr2error(maperr);
442 if (err == C2_OK) {
443 mBuffer = static_cast<buffer_handle_t>(buffer);
444 }
445 }).isOk()) {
446 ALOGE("failed transaction: importBuffer (@3.0)");
447 return C2_CORRUPTED;
448 }
449 }
450 if (err != C2_OK) {
451 ALOGD("importBuffer failed: %d", err);
452 return err;
453 }
454 if (mBuffer == nullptr) {
455 ALOGD("importBuffer returned null buffer");
456 return C2_CORRUPTED;
457 }
458 uint32_t generation = 0;
459 uint64_t igbp_id = 0;
460 uint32_t igbp_slot = 0;
461 if (mHandle) {
462 mHandle->getIgbpData(&generation, &igbp_id, &igbp_slot);
463 }
464 if (mMapper2) {
465 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
466 mBuffer, mInfo2.mapperInfo.width, mInfo2.mapperInfo.height,
467 (uint32_t)mInfo2.mapperInfo.format, mInfo2.mapperInfo.usage,
468 mInfo2.stride, generation, igbp_id, igbp_slot);
469 } else {
470 mLockedHandle = C2HandleGralloc::WrapAndMoveNativeHandle(
471 mBuffer, mInfo3.mapperInfo.width, mInfo3.mapperInfo.height,
472 (uint32_t)mInfo3.mapperInfo.format, mInfo3.mapperInfo.usage,
473 mInfo3.stride, generation, igbp_id, igbp_slot);
474 }
475 }
476
477 PixelFormat3 format = mMapper2 ?
478 PixelFormat3(mInfo2.mapperInfo.format) :
479 PixelFormat3(mInfo3.mapperInfo.format);
480 switch (format) {
481 case PixelFormat3::RGBA_1010102: {
482 // TRICKY: this is used for media as YUV444 in the case when it is queued directly to a
483 // Surface. In all other cases it is RGBA. We don't know which case it is here, so
484 // default to YUV for now.
485 void *pointer = nullptr;
486 if (mMapper2) {
487 if (!mMapper2->lock(
488 const_cast<native_handle_t *>(mBuffer),
489 grallocUsage,
490 { (int32_t)rect.left, (int32_t)rect.top,
491 (int32_t)rect.width, (int32_t)rect.height },
492 // TODO: fence
493 hidl_handle(),
494 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
495 err = maperr2error(maperr);
496 if (err == C2_OK) {
497 pointer = mapPointer;
498 }
499 }).isOk()) {
500 ALOGE("failed transaction: lock(RGBA_1010102)");
501 return C2_CORRUPTED;
502 }
503 } else {
504 if (!mMapper3->lock(
505 const_cast<native_handle_t *>(mBuffer),
506 grallocUsage,
507 { (int32_t)rect.left, (int32_t)rect.top,
508 (int32_t)rect.width, (int32_t)rect.height },
509 // TODO: fence
510 hidl_handle(),
511 [&err, &pointer](const auto &maperr, const auto &mapPointer,
512 int32_t bytesPerPixel, int32_t bytesPerStride) {
513 err = maperr2error(maperr);
514 if (err == C2_OK) {
515 pointer = mapPointer;
516 }
517 (void)bytesPerPixel;
518 (void)bytesPerStride;
519 }).isOk()) {
520 ALOGE("failed transaction: lock(RGBA_1010102) (@3.0)");
521 return C2_CORRUPTED;
522 }
523 }
524 if (err != C2_OK) {
525 ALOGD("lock failed: %d", err);
526 return err;
527 }
528 // treat as 32-bit values
529 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)pointer;
530 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)pointer;
531 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)pointer;
532 addr[C2PlanarLayout::PLANE_A] = (uint8_t *)pointer;
533 layout->type = C2PlanarLayout::TYPE_YUVA;
534 layout->numPlanes = 4;
535 layout->rootPlanes = 1;
536 int32_t stride = mMapper2 ?
537 int32_t(mInfo2.stride) :
538 int32_t(mInfo3.stride);
539 layout->planes[C2PlanarLayout::PLANE_Y] = {
540 C2PlaneInfo::CHANNEL_Y, // channel
541 4, // colInc
542 4 * stride, // rowInc
543 1, // mColSampling
544 1, // mRowSampling
545 32, // allocatedDepth
546 10, // bitDepth
547 10, // rightShift
548 C2PlaneInfo::LITTLE_END, // endianness
549 C2PlanarLayout::PLANE_Y, // rootIx
550 0, // offset
551 };
552 layout->planes[C2PlanarLayout::PLANE_U] = {
553 C2PlaneInfo::CHANNEL_CB, // channel
554 4, // colInc
555 4 * stride, // rowInc
556 1, // mColSampling
557 1, // mRowSampling
558 32, // allocatedDepth
559 10, // bitDepth
560 0, // rightShift
561 C2PlaneInfo::LITTLE_END, // endianness
562 C2PlanarLayout::PLANE_Y, // rootIx
563 0, // offset
564 };
565 layout->planes[C2PlanarLayout::PLANE_V] = {
566 C2PlaneInfo::CHANNEL_CR, // channel
567 4, // colInc
568 4 * stride, // rowInc
569 1, // mColSampling
570 1, // mRowSampling
571 32, // allocatedDepth
572 10, // bitDepth
573 20, // rightShift
574 C2PlaneInfo::LITTLE_END, // endianness
575 C2PlanarLayout::PLANE_Y, // rootIx
576 0, // offset
577 };
578 layout->planes[C2PlanarLayout::PLANE_A] = {
579 C2PlaneInfo::CHANNEL_A, // channel
580 4, // colInc
581 4 * stride, // rowInc
582 1, // mColSampling
583 1, // mRowSampling
584 32, // allocatedDepth
585 2, // bitDepth
586 30, // rightShift
587 C2PlaneInfo::LITTLE_END, // endianness
588 C2PlanarLayout::PLANE_Y, // rootIx
589 0, // offset
590 };
591 break;
592 }
593
594 case PixelFormat3::RGBA_8888:
595 // TODO: alpha channel
596 // fall-through
597 case PixelFormat3::RGBX_8888: {
598 void *pointer = nullptr;
599 if (mMapper2) {
600 if (!mMapper2->lock(
601 const_cast<native_handle_t *>(mBuffer),
602 grallocUsage,
603 { (int32_t)rect.left, (int32_t)rect.top,
604 (int32_t)rect.width, (int32_t)rect.height },
605 // TODO: fence
606 hidl_handle(),
607 [&err, &pointer](const auto &maperr, const auto &mapPointer) {
608 err = maperr2error(maperr);
609 if (err == C2_OK) {
610 pointer = mapPointer;
611 }
612 }).isOk()) {
613 ALOGE("failed transaction: lock(RGBA_8888)");
614 return C2_CORRUPTED;
615 }
616 } else {
617 if (!mMapper3->lock(
618 const_cast<native_handle_t *>(mBuffer),
619 grallocUsage,
620 { (int32_t)rect.left, (int32_t)rect.top,
621 (int32_t)rect.width, (int32_t)rect.height },
622 // TODO: fence
623 hidl_handle(),
624 [&err, &pointer](const auto &maperr, const auto &mapPointer,
625 int32_t bytesPerPixel, int32_t bytesPerStride) {
626 err = maperr2error(maperr);
627 if (err == C2_OK) {
628 pointer = mapPointer;
629 }
630 (void)bytesPerPixel;
631 (void)bytesPerStride;
632 }).isOk()) {
633 ALOGE("failed transaction: lock(RGBA_8888) (@3.0)");
634 return C2_CORRUPTED;
635 }
636 }
637 if (err != C2_OK) {
638 ALOGD("lock failed: %d", err);
639 return err;
640 }
641 addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer;
642 addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1;
643 addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2;
644 layout->type = C2PlanarLayout::TYPE_RGB;
645 layout->numPlanes = 3;
646 layout->rootPlanes = 1;
647 int32_t stride = mMapper2 ?
648 int32_t(mInfo2.stride) :
649 int32_t(mInfo3.stride);
650 layout->planes[C2PlanarLayout::PLANE_R] = {
651 C2PlaneInfo::CHANNEL_R, // channel
652 4, // colInc
653 4 * stride, // rowInc
654 1, // mColSampling
655 1, // mRowSampling
656 8, // allocatedDepth
657 8, // bitDepth
658 0, // rightShift
659 C2PlaneInfo::NATIVE, // endianness
660 C2PlanarLayout::PLANE_R, // rootIx
661 0, // offset
662 };
663 layout->planes[C2PlanarLayout::PLANE_G] = {
664 C2PlaneInfo::CHANNEL_G, // channel
665 4, // colInc
666 4 * stride, // rowInc
667 1, // mColSampling
668 1, // mRowSampling
669 8, // allocatedDepth
670 8, // bitDepth
671 0, // rightShift
672 C2PlaneInfo::NATIVE, // endianness
673 C2PlanarLayout::PLANE_R, // rootIx
674 1, // offset
675 };
676 layout->planes[C2PlanarLayout::PLANE_B] = {
677 C2PlaneInfo::CHANNEL_B, // channel
678 4, // colInc
679 4 * stride, // rowInc
680 1, // mColSampling
681 1, // mRowSampling
682 8, // allocatedDepth
683 8, // bitDepth
684 0, // rightShift
685 C2PlaneInfo::NATIVE, // endianness
686 C2PlanarLayout::PLANE_R, // rootIx
687 2, // offset
688 };
689 break;
690 }
691
692 case PixelFormat3::YCBCR_420_888:
693 // fall-through
694 case PixelFormat3::YV12:
695 // fall-through
696 default: {
697 struct YCbCrLayout {
698 void* y;
699 void* cb;
700 void* cr;
701 uint32_t yStride;
702 uint32_t cStride;
703 uint32_t chromaStep;
704 };
705 YCbCrLayout ycbcrLayout;
706 if (mMapper2) {
707 if (!mMapper2->lockYCbCr(
708 const_cast<native_handle_t *>(mBuffer), grallocUsage,
709 { (int32_t)rect.left, (int32_t)rect.top,
710 (int32_t)rect.width, (int32_t)rect.height },
711 // TODO: fence
712 hidl_handle(),
713 [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
714 err = maperr2error(maperr);
715 if (err == C2_OK) {
716 ycbcrLayout = YCbCrLayout{
717 mapLayout.y,
718 mapLayout.cb,
719 mapLayout.cr,
720 mapLayout.yStride,
721 mapLayout.cStride,
722 mapLayout.chromaStep};
723 }
724 }).isOk()) {
725 ALOGE("failed transaction: lockYCbCr");
726 return C2_CORRUPTED;
727 }
728 } else {
729 if (!mMapper3->lockYCbCr(
730 const_cast<native_handle_t *>(mBuffer), grallocUsage,
731 { (int32_t)rect.left, (int32_t)rect.top,
732 (int32_t)rect.width, (int32_t)rect.height },
733 // TODO: fence
734 hidl_handle(),
735 [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) {
736 err = maperr2error(maperr);
737 if (err == C2_OK) {
738 ycbcrLayout = YCbCrLayout{
739 mapLayout.y,
740 mapLayout.cb,
741 mapLayout.cr,
742 mapLayout.yStride,
743 mapLayout.cStride,
744 mapLayout.chromaStep};
745 }
746 }).isOk()) {
747 ALOGE("failed transaction: lockYCbCr (@3.0)");
748 return C2_CORRUPTED;
749 }
750 }
751 if (err != C2_OK) {
752 ALOGD("lockYCbCr failed: %d", err);
753 return err;
754 }
755 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y;
756 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb;
757 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr;
758 layout->type = C2PlanarLayout::TYPE_YUV;
759 layout->numPlanes = 3;
760 layout->rootPlanes = 3;
761 layout->planes[C2PlanarLayout::PLANE_Y] = {
762 C2PlaneInfo::CHANNEL_Y, // channel
763 1, // colInc
764 (int32_t)ycbcrLayout.yStride, // rowInc
765 1, // mColSampling
766 1, // mRowSampling
767 8, // allocatedDepth
768 8, // bitDepth
769 0, // rightShift
770 C2PlaneInfo::NATIVE, // endianness
771 C2PlanarLayout::PLANE_Y, // rootIx
772 0, // offset
773 };
774 layout->planes[C2PlanarLayout::PLANE_U] = {
775 C2PlaneInfo::CHANNEL_CB, // channel
776 (int32_t)ycbcrLayout.chromaStep, // colInc
777 (int32_t)ycbcrLayout.cStride, // rowInc
778 2, // mColSampling
779 2, // mRowSampling
780 8, // allocatedDepth
781 8, // bitDepth
782 0, // rightShift
783 C2PlaneInfo::NATIVE, // endianness
784 C2PlanarLayout::PLANE_U, // rootIx
785 0, // offset
786 };
787 layout->planes[C2PlanarLayout::PLANE_V] = {
788 C2PlaneInfo::CHANNEL_CR, // channel
789 (int32_t)ycbcrLayout.chromaStep, // colInc
790 (int32_t)ycbcrLayout.cStride, // rowInc
791 2, // mColSampling
792 2, // mRowSampling
793 8, // allocatedDepth
794 8, // bitDepth
795 0, // rightShift
796 C2PlaneInfo::NATIVE, // endianness
797 C2PlanarLayout::PLANE_V, // rootIx
798 0, // offset
799 };
800 // handle interleaved formats
801 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U];
802 if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) {
803 layout->rootPlanes = 2;
804 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U;
805 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset;
806 } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) {
807 layout->rootPlanes = 2;
808 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V;
809 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset;
810 }
811 break;
812 }
813 }
814 mLocked = true;
815
816 return C2_OK;
817 }
818
unmap(uint8_t ** addr,C2Rect rect,C2Fence * fence)819 c2_status_t C2AllocationGralloc::unmap(
820 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) {
821 // TODO: check addr and size, use fence
822 (void)addr;
823 (void)rect;
824
825 std::lock_guard<std::mutex> lock(mMappedLock);
826 c2_status_t err = C2_OK;
827 if (mMapper2) {
828 if (!mMapper2->unlock(
829 const_cast<native_handle_t *>(mBuffer),
830 [&err, &fence](const auto &maperr, const auto &releaseFence) {
831 // TODO
832 (void) fence;
833 (void) releaseFence;
834 err = maperr2error(maperr);
835 if (err == C2_OK) {
836 // TODO: fence
837 }
838 }).isOk()) {
839 ALOGE("failed transaction: unlock");
840 return C2_CORRUPTED;
841 }
842 } else {
843 if (!mMapper3->unlock(
844 const_cast<native_handle_t *>(mBuffer),
845 [&err, &fence](const auto &maperr, const auto &releaseFence) {
846 // TODO
847 (void) fence;
848 (void) releaseFence;
849 err = maperr2error(maperr);
850 if (err == C2_OK) {
851 // TODO: fence
852 }
853 }).isOk()) {
854 ALOGE("failed transaction: unlock (@3.0)");
855 return C2_CORRUPTED;
856 }
857 }
858 if (err == C2_OK) {
859 mLocked = false;
860 }
861 return err;
862 }
863
equals(const std::shared_ptr<const C2GraphicAllocation> & other) const864 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const {
865 return other && other->handle() == handle();
866 }
867
868 /* ===================================== GRALLOC ALLOCATOR ==================================== */
869 class C2AllocatorGralloc::Impl {
870 public:
871 Impl(id_t id, bool bufferQueue);
872
getId() const873 id_t getId() const {
874 return mTraits->id;
875 }
876
getName() const877 C2String getName() const {
878 return mTraits->name;
879 }
880
getTraits() const881 std::shared_ptr<const C2Allocator::Traits> getTraits() const {
882 return mTraits;
883 }
884
885 c2_status_t newGraphicAllocation(
886 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
887 std::shared_ptr<C2GraphicAllocation> *allocation);
888
889 c2_status_t priorGraphicAllocation(
890 const C2Handle *handle,
891 std::shared_ptr<C2GraphicAllocation> *allocation);
892
status() const893 c2_status_t status() const { return mInit; }
894
895 private:
896 std::shared_ptr<C2Allocator::Traits> mTraits;
897 c2_status_t mInit;
898 sp<IAllocator2> mAllocator2;
899 sp<IMapper2> mMapper2;
900 sp<IAllocator3> mAllocator3;
901 sp<IMapper3> mMapper3;
902 const bool mBufferQueue;
903 };
904
_UnwrapNativeCodec2GrallocMetadata(const C2Handle * const handle,uint32_t * width,uint32_t * height,uint32_t * format,uint64_t * usage,uint32_t * stride,uint32_t * generation,uint64_t * igbp_id,uint32_t * igbp_slot)905 void _UnwrapNativeCodec2GrallocMetadata(
906 const C2Handle *const handle,
907 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride,
908 uint32_t *generation, uint64_t *igbp_id, uint32_t *igbp_slot) {
909 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride,
910 generation, igbp_id, igbp_slot);
911 }
912
Impl(id_t id,bool bufferQueue)913 C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue)
914 : mInit(C2_OK), mBufferQueue(bufferQueue) {
915 // TODO: get this from allocator
916 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 };
917 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage };
918 mTraits = std::make_shared<C2Allocator::Traits>(traits);
919
920 // gralloc allocator is a singleton, so all objects share a global service
921 mAllocator3 = IAllocator3::getService();
922 mMapper3 = IMapper3::getService();
923 if (!mAllocator3 || !mMapper3) {
924 mAllocator3 = nullptr;
925 mMapper3 = nullptr;
926 mAllocator2 = IAllocator2::getService();
927 mMapper2 = IMapper2::getService();
928 if (!mAllocator2 || !mMapper2) {
929 mAllocator2 = nullptr;
930 mMapper2 = nullptr;
931 mInit = C2_CORRUPTED;
932 }
933 }
934 }
935
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,const C2MemoryUsage & usage,std::shared_ptr<C2GraphicAllocation> * allocation)936 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation(
937 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage,
938 std::shared_ptr<C2GraphicAllocation> *allocation) {
939 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage();
940 ALOGV("allocating buffer with usage %#llx => %#llx",
941 (long long)usage.expected, (long long)grallocUsage);
942
943 c2_status_t err = C2_OK;
944 hidl_handle buffer{};
945
946 if (mMapper2) {
947 BufferDescriptorInfo2 info = {
948 {
949 width,
950 height,
951 1u, // layerCount
952 PixelFormat2(format),
953 grallocUsage,
954 },
955 0u, // stride placeholder
956 };
957 BufferDescriptor2 desc;
958 if (!mMapper2->createDescriptor(
959 info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
960 err = maperr2error(maperr);
961 if (err == C2_OK) {
962 desc = descriptor;
963 }
964 }).isOk()) {
965 ALOGE("failed transaction: createDescriptor");
966 return C2_CORRUPTED;
967 }
968 if (err != C2_OK) {
969 return err;
970 }
971
972 // IAllocator shares IMapper error codes.
973 if (!mAllocator2->allocate(
974 desc,
975 1u,
976 [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
977 err = maperr2error(maperr);
978 if (err != C2_OK) {
979 return;
980 }
981 if (buffers.size() != 1u) {
982 err = C2_CORRUPTED;
983 return;
984 }
985 info.stride = stride;
986 buffer = buffers[0];
987 }).isOk()) {
988 ALOGE("failed transaction: allocate");
989 return C2_CORRUPTED;
990 }
991 if (err != C2_OK) {
992 return err;
993 }
994 allocation->reset(new C2AllocationGralloc(
995 info, mMapper2, buffer,
996 C2HandleGralloc::WrapAndMoveNativeHandle(
997 buffer.getNativeHandle(),
998 width, height,
999 format, grallocUsage, info.stride,
1000 0, 0, mBufferQueue ? ~0 : 0),
1001 mTraits->id));
1002 return C2_OK;
1003 } else {
1004 BufferDescriptorInfo3 info = {
1005 {
1006 width,
1007 height,
1008 1u, // layerCount
1009 PixelFormat3(format),
1010 grallocUsage,
1011 },
1012 0u, // stride placeholder
1013 };
1014 BufferDescriptor3 desc;
1015 if (!mMapper3->createDescriptor(
1016 info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) {
1017 err = maperr2error(maperr);
1018 if (err == C2_OK) {
1019 desc = descriptor;
1020 }
1021 }).isOk()) {
1022 ALOGE("failed transaction: createDescriptor");
1023 return C2_CORRUPTED;
1024 }
1025 if (err != C2_OK) {
1026 return err;
1027 }
1028
1029 // IAllocator shares IMapper error codes.
1030 if (!mAllocator3->allocate(
1031 desc,
1032 1u,
1033 [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) {
1034 err = maperr2error(maperr);
1035 if (err != C2_OK) {
1036 return;
1037 }
1038 if (buffers.size() != 1u) {
1039 err = C2_CORRUPTED;
1040 return;
1041 }
1042 info.stride = stride;
1043 buffer = buffers[0];
1044 }).isOk()) {
1045 ALOGE("failed transaction: allocate");
1046 return C2_CORRUPTED;
1047 }
1048 if (err != C2_OK) {
1049 return err;
1050 }
1051 allocation->reset(new C2AllocationGralloc(
1052 info, mMapper3, buffer,
1053 C2HandleGralloc::WrapAndMoveNativeHandle(
1054 buffer.getNativeHandle(),
1055 width, height,
1056 format, grallocUsage, info.stride,
1057 0, 0, mBufferQueue ? ~0 : 0),
1058 mTraits->id));
1059 return C2_OK;
1060 }
1061 }
1062
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)1063 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation(
1064 const C2Handle *handle,
1065 std::shared_ptr<C2GraphicAllocation> *allocation) {
1066 if (mMapper2) {
1067 BufferDescriptorInfo2 info;
1068 info.mapperInfo.layerCount = 1u;
1069 uint32_t generation;
1070 uint64_t igbp_id;
1071 uint32_t igbp_slot;
1072 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
1073 handle,
1074 &info.mapperInfo.width, &info.mapperInfo.height,
1075 (uint32_t *)&info.mapperInfo.format,
1076 (uint64_t *)&info.mapperInfo.usage,
1077 &info.stride,
1078 &generation, &igbp_id, &igbp_slot);
1079 if (grallocHandle == nullptr) {
1080 return C2_BAD_VALUE;
1081 }
1082
1083 hidl_handle hidlHandle;
1084 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
1085
1086 allocation->reset(new C2AllocationGralloc(
1087 info, mMapper2, hidlHandle, grallocHandle, mTraits->id));
1088 return C2_OK;
1089 } else {
1090 BufferDescriptorInfo3 info;
1091 info.mapperInfo.layerCount = 1u;
1092 uint32_t generation;
1093 uint64_t igbp_id;
1094 uint32_t igbp_slot;
1095 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import(
1096 handle,
1097 &info.mapperInfo.width, &info.mapperInfo.height,
1098 (uint32_t *)&info.mapperInfo.format,
1099 (uint64_t *)&info.mapperInfo.usage,
1100 &info.stride,
1101 &generation, &igbp_id, &igbp_slot);
1102 if (grallocHandle == nullptr) {
1103 return C2_BAD_VALUE;
1104 }
1105
1106 hidl_handle hidlHandle;
1107 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true);
1108
1109 allocation->reset(new C2AllocationGralloc(
1110 info, mMapper3, hidlHandle, grallocHandle, mTraits->id));
1111 return C2_OK;
1112 }
1113 }
1114
C2AllocatorGralloc(id_t id,bool bufferQueue)1115 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue)
1116 : mImpl(new Impl(id, bufferQueue)) {}
1117
~C2AllocatorGralloc()1118 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; }
1119
getId() const1120 C2Allocator::id_t C2AllocatorGralloc::getId() const {
1121 return mImpl->getId();
1122 }
1123
getName() const1124 C2String C2AllocatorGralloc::getName() const {
1125 return mImpl->getName();
1126 }
1127
getTraits() const1128 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const {
1129 return mImpl->getTraits();
1130 }
1131
newGraphicAllocation(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicAllocation> * allocation)1132 c2_status_t C2AllocatorGralloc::newGraphicAllocation(
1133 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
1134 std::shared_ptr<C2GraphicAllocation> *allocation) {
1135 return mImpl->newGraphicAllocation(width, height, format, usage, allocation);
1136 }
1137
priorGraphicAllocation(const C2Handle * handle,std::shared_ptr<C2GraphicAllocation> * allocation)1138 c2_status_t C2AllocatorGralloc::priorGraphicAllocation(
1139 const C2Handle *handle,
1140 std::shared_ptr<C2GraphicAllocation> *allocation) {
1141 return mImpl->priorGraphicAllocation(handle, allocation);
1142 }
1143
status() const1144 c2_status_t C2AllocatorGralloc::status() const {
1145 return mImpl->status();
1146 }
1147
isValid(const C2Handle * const o)1148 bool C2AllocatorGralloc::isValid(const C2Handle* const o) {
1149 return C2HandleGralloc::isValid(o);
1150 }
1151
1152 } // namespace android
1153