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 <cutils/native_handle.h> 24 #include <hardware/gralloc.h> 25 26 #include <C2AllocatorGralloc.h> 27 #include <C2Buffer.h> 28 #include <C2PlatformSupport.h> 29 30 namespace android { 31 32 namespace { 33 enum : uint64_t { 34 /** 35 * Usage mask that is passed through from gralloc to Codec 2.0 usage. 36 */ 37 PASSTHROUGH_USAGE_MASK = 38 ~(GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_PROTECTED) 39 }; 40 41 // verify that passthrough mask is within the platform mask 42 static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, ""); 43 } 44 45 C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) { 46 // gralloc does not support WRITE_PROTECTED 47 return C2MemoryUsage( 48 ((usage & GRALLOC_USAGE_SW_READ_MASK) ? C2MemoryUsage::CPU_READ : 0) | 49 ((usage & GRALLOC_USAGE_SW_WRITE_MASK) ? C2MemoryUsage::CPU_WRITE : 0) | 50 ((usage & GRALLOC_USAGE_PROTECTED) ? C2MemoryUsage::READ_PROTECTED : 0) | 51 (usage & PASSTHROUGH_USAGE_MASK)); 52 } 53 54 uint64_t C2AndroidMemoryUsage::asGrallocUsage() const { 55 // gralloc does not support WRITE_PROTECTED 56 return (((expected & C2MemoryUsage::CPU_READ) ? GRALLOC_USAGE_SW_READ_OFTEN : 0) | 57 ((expected & C2MemoryUsage::CPU_WRITE) ? GRALLOC_USAGE_SW_WRITE_OFTEN : 0) | 58 ((expected & C2MemoryUsage::READ_PROTECTED) ? GRALLOC_USAGE_PROTECTED : 0) | 59 (expected & PASSTHROUGH_USAGE_MASK)); 60 } 61 62 using ::android::hardware::graphics::allocator::V2_0::IAllocator; 63 using ::android::hardware::graphics::common::V1_0::BufferUsage; 64 using ::android::hardware::graphics::common::V1_0::PixelFormat; 65 using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor; 66 using ::android::hardware::graphics::mapper::V2_0::Error; 67 using ::android::hardware::graphics::mapper::V2_0::IMapper; 68 using ::android::hardware::graphics::mapper::V2_0::YCbCrLayout; 69 using ::android::hardware::hidl_handle; 70 using ::android::hardware::hidl_vec; 71 72 namespace { 73 74 struct BufferDescriptorInfo { 75 IMapper::BufferDescriptorInfo mapperInfo; 76 uint32_t stride; 77 }; 78 79 } 80 81 /* ===================================== GRALLOC ALLOCATION ==================================== */ 82 static c2_status_t maperr2error(Error maperr) { 83 switch (maperr) { 84 case Error::NONE: return C2_OK; 85 case Error::BAD_DESCRIPTOR: return C2_BAD_VALUE; 86 case Error::BAD_BUFFER: return C2_BAD_VALUE; 87 case Error::BAD_VALUE: return C2_BAD_VALUE; 88 case Error::NO_RESOURCES: return C2_NO_MEMORY; 89 case Error::UNSUPPORTED: return C2_CANNOT_DO; 90 } 91 return C2_CORRUPTED; 92 } 93 94 static 95 bool native_handle_is_invalid(const native_handle_t *const handle) { 96 // perform basic validation of a native handle 97 if (handle == nullptr) { 98 // null handle is considered valid 99 return false; 100 } 101 return ((size_t)handle->version != sizeof(native_handle_t) || 102 handle->numFds < 0 || 103 handle->numInts < 0 || 104 // for sanity assume handles must occupy less memory than INT_MAX bytes 105 handle->numFds > int((INT_MAX - handle->version) / sizeof(int)) - handle->numInts); 106 } 107 108 class C2HandleGralloc : public C2Handle { 109 private: 110 struct ExtraData { 111 uint32_t width; 112 uint32_t height; 113 uint32_t format; 114 uint32_t usage_lo; 115 uint32_t usage_hi; 116 uint32_t stride; 117 uint32_t igbp_id_lo; 118 uint32_t igbp_id_hi; 119 uint32_t igbp_slot; 120 uint32_t magic; 121 }; 122 123 enum { 124 NUM_INTS = sizeof(ExtraData) / sizeof(int), 125 }; 126 const static uint32_t MAGIC = '\xc2gr\x00'; 127 128 static 129 const ExtraData* getExtraData(const C2Handle *const handle) { 130 if (handle == nullptr 131 || native_handle_is_invalid(handle) 132 || handle->numInts < NUM_INTS) { 133 return nullptr; 134 } 135 return reinterpret_cast<const ExtraData*>( 136 &handle->data[handle->numFds + handle->numInts - NUM_INTS]); 137 } 138 139 static 140 ExtraData *getExtraData(C2Handle *const handle) { 141 return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle))); 142 } 143 144 public: 145 void getIgbpData(uint64_t *igbp_id, uint32_t *igbp_slot) const { 146 const ExtraData *ed = getExtraData(this); 147 *igbp_id = unsigned(ed->igbp_id_lo) | uint64_t(unsigned(ed->igbp_id_hi)) << 32; 148 *igbp_slot = ed->igbp_slot; 149 } 150 151 static bool isValid(const C2Handle *const o) { 152 if (o == nullptr) { // null handle is always valid 153 return true; 154 } 155 const ExtraData *xd = getExtraData(o); 156 // we cannot validate width/height/format/usage without accessing gralloc driver 157 return xd != nullptr && xd->magic == MAGIC; 158 } 159 160 static C2HandleGralloc* WrapNativeHandle( 161 const native_handle_t *const handle, 162 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, 163 uint32_t stride, uint64_t igbp_id = 0, uint32_t igbp_slot = 0) { 164 //CHECK(handle != nullptr); 165 if (native_handle_is_invalid(handle) || 166 handle->numInts > int((INT_MAX - handle->version) / sizeof(int)) - NUM_INTS - handle->numFds) { 167 return nullptr; 168 } 169 ExtraData xd = { 170 width, height, format, uint32_t(usage & 0xFFFFFFFF), uint32_t(usage >> 32), 171 stride, uint32_t(igbp_id & 0xFFFFFFFF), uint32_t(igbp_id >> 32), igbp_slot, MAGIC 172 }; 173 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts + NUM_INTS); 174 if (res != nullptr) { 175 memcpy(&res->data, &handle->data, sizeof(int) * (handle->numFds + handle->numInts)); 176 *getExtraData(res) = xd; 177 } 178 return reinterpret_cast<C2HandleGralloc *>(res); 179 } 180 181 static native_handle_t* UnwrapNativeHandle( 182 const C2Handle *const handle) { 183 const ExtraData *xd = getExtraData(handle); 184 if (xd == nullptr || xd->magic != MAGIC) { 185 return nullptr; 186 } 187 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS); 188 if (res != nullptr) { 189 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts)); 190 } 191 return res; 192 } 193 194 static native_handle_t* UnwrapNativeHandle( 195 const C2Handle *const handle, uint64_t *igbp_id, uint32_t *igbp_slot) { 196 const ExtraData *xd = getExtraData(handle); 197 if (xd == nullptr || xd->magic != MAGIC) { 198 return nullptr; 199 } 200 *igbp_id = unsigned(xd->igbp_id_lo) | uint64_t(unsigned(xd->igbp_id_hi)) << 32; 201 *igbp_slot = xd->igbp_slot; 202 native_handle_t *res = native_handle_create(handle->numFds, handle->numInts - NUM_INTS); 203 if (res != nullptr) { 204 memcpy(&res->data, &handle->data, sizeof(int) * (res->numFds + res->numInts)); 205 } 206 return res; 207 } 208 209 static const C2HandleGralloc* Import( 210 const C2Handle *const handle, 211 uint32_t *width, uint32_t *height, uint32_t *format, 212 uint64_t *usage, uint32_t *stride, 213 uint64_t *igbp_id, uint32_t *igbp_slot) { 214 const ExtraData *xd = getExtraData(handle); 215 if (xd == nullptr) { 216 return nullptr; 217 } 218 *width = xd->width; 219 *height = xd->height; 220 *format = xd->format; 221 *usage = xd->usage_lo | (uint64_t(xd->usage_hi) << 32); 222 *stride = xd->stride; 223 *igbp_id = xd->igbp_id_lo | (uint64_t(xd->igbp_id_hi) << 32); 224 *igbp_slot = xd->igbp_slot; 225 return reinterpret_cast<const C2HandleGralloc *>(handle); 226 } 227 }; 228 229 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) { 230 return C2HandleGralloc::UnwrapNativeHandle(handle); 231 } 232 233 native_handle_t *UnwrapNativeCodec2GrallocHandle( 234 const C2Handle *const handle, uint64_t *igbp_id, uint32_t *igbp_slot) { 235 return C2HandleGralloc::UnwrapNativeHandle(handle, igbp_id, igbp_slot); 236 } 237 238 C2Handle *WrapNativeCodec2GrallocHandle( 239 const native_handle_t *const handle, 240 uint32_t width, uint32_t height, uint32_t format, uint64_t usage, uint32_t stride, uint64_t igbp_id, uint32_t igbp_slot) { 241 return C2HandleGralloc::WrapNativeHandle(handle, width, height, format, usage, stride, igbp_id, igbp_slot); 242 } 243 244 class C2AllocationGralloc : public C2GraphicAllocation { 245 public: 246 virtual ~C2AllocationGralloc() override; 247 248 virtual c2_status_t map( 249 C2Rect rect, C2MemoryUsage usage, C2Fence *fence, 250 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) override; 251 virtual c2_status_t unmap( 252 uint8_t **addr /* nonnull */, C2Rect rect, C2Fence *fence /* nullable */) override; 253 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; } 254 virtual const C2Handle *handle() const override { return mLockedHandle ? : mHandle; } 255 virtual bool equals(const std::shared_ptr<const C2GraphicAllocation> &other) const override; 256 257 // internal methods 258 // |handle| will be moved. 259 C2AllocationGralloc( 260 const BufferDescriptorInfo &info, 261 const sp<IMapper> &mapper, 262 hidl_handle &hidlHandle, 263 const C2HandleGralloc *const handle, 264 C2Allocator::id_t allocatorId); 265 int dup() const; 266 c2_status_t status() const; 267 268 private: 269 const BufferDescriptorInfo mInfo; 270 const sp<IMapper> mMapper; 271 const hidl_handle mHidlHandle; 272 const C2HandleGralloc *mHandle; 273 buffer_handle_t mBuffer; 274 const C2HandleGralloc *mLockedHandle; 275 bool mLocked; 276 C2Allocator::id_t mAllocatorId; 277 }; 278 279 C2AllocationGralloc::C2AllocationGralloc( 280 const BufferDescriptorInfo &info, 281 const sp<IMapper> &mapper, 282 hidl_handle &hidlHandle, 283 const C2HandleGralloc *const handle, 284 C2Allocator::id_t allocatorId) 285 : C2GraphicAllocation(info.mapperInfo.width, info.mapperInfo.height), 286 mInfo(info), 287 mMapper(mapper), 288 mHidlHandle(std::move(hidlHandle)), 289 mHandle(handle), 290 mBuffer(nullptr), 291 mLockedHandle(nullptr), 292 mLocked(false), 293 mAllocatorId(allocatorId) { 294 } 295 296 C2AllocationGralloc::~C2AllocationGralloc() { 297 if (!mBuffer) { 298 return; 299 } 300 if (mLocked) { 301 // implementation ignores addresss and rect 302 uint8_t* addr[C2PlanarLayout::MAX_NUM_PLANES] = {}; 303 unmap(addr, C2Rect(), nullptr); 304 } 305 mMapper->freeBuffer(const_cast<native_handle_t *>(mBuffer)); 306 native_handle_delete(const_cast<native_handle_t*>( 307 reinterpret_cast<const native_handle_t*>(mHandle))); 308 } 309 310 c2_status_t C2AllocationGralloc::map( 311 C2Rect rect, C2MemoryUsage usage, C2Fence *fence, 312 C2PlanarLayout *layout /* nonnull */, uint8_t **addr /* nonnull */) { 313 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage(); 314 ALOGV("mapping buffer with usage %#llx => %#llx", 315 (long long)usage.expected, (long long)grallocUsage); 316 317 // TODO 318 (void) fence; 319 320 if (mBuffer && mLocked) { 321 ALOGD("already mapped"); 322 return C2_DUPLICATE; 323 } 324 if (!layout || !addr) { 325 ALOGD("wrong param"); 326 return C2_BAD_VALUE; 327 } 328 329 c2_status_t err = C2_OK; 330 if (!mBuffer) { 331 mMapper->importBuffer( 332 mHidlHandle, [&err, this](const auto &maperr, const auto &buffer) { 333 err = maperr2error(maperr); 334 if (err == C2_OK) { 335 mBuffer = static_cast<buffer_handle_t>(buffer); 336 } 337 }); 338 if (err != C2_OK) { 339 ALOGD("importBuffer failed: %d", err); 340 return err; 341 } 342 if (mBuffer == nullptr) { 343 ALOGD("importBuffer returned null buffer"); 344 return C2_CORRUPTED; 345 } 346 uint64_t igbp_id = 0; 347 uint32_t igbp_slot = 0; 348 if (mHandle) { 349 mHandle->getIgbpData(&igbp_id, &igbp_slot); 350 } 351 mLockedHandle = C2HandleGralloc::WrapNativeHandle( 352 mBuffer, mInfo.mapperInfo.width, mInfo.mapperInfo.height, 353 (uint32_t)mInfo.mapperInfo.format, mInfo.mapperInfo.usage, mInfo.stride, igbp_id, igbp_slot); 354 } 355 356 switch (mInfo.mapperInfo.format) { 357 case PixelFormat::YCBCR_420_888: 358 case PixelFormat::YV12: { 359 YCbCrLayout ycbcrLayout; 360 mMapper->lockYCbCr( 361 const_cast<native_handle_t *>(mBuffer), grallocUsage, 362 { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height }, 363 // TODO: fence 364 hidl_handle(), 365 [&err, &ycbcrLayout](const auto &maperr, const auto &mapLayout) { 366 err = maperr2error(maperr); 367 if (err == C2_OK) { 368 ycbcrLayout = mapLayout; 369 } 370 }); 371 if (err != C2_OK) { 372 ALOGD("lockYCbCr failed: %d", err); 373 return err; 374 } 375 addr[C2PlanarLayout::PLANE_Y] = (uint8_t *)ycbcrLayout.y; 376 addr[C2PlanarLayout::PLANE_U] = (uint8_t *)ycbcrLayout.cb; 377 addr[C2PlanarLayout::PLANE_V] = (uint8_t *)ycbcrLayout.cr; 378 layout->type = C2PlanarLayout::TYPE_YUV; 379 layout->numPlanes = 3; 380 layout->rootPlanes = 3; 381 layout->planes[C2PlanarLayout::PLANE_Y] = { 382 C2PlaneInfo::CHANNEL_Y, // channel 383 1, // colInc 384 (int32_t)ycbcrLayout.yStride, // rowInc 385 1, // mColSampling 386 1, // mRowSampling 387 8, // allocatedDepth 388 8, // bitDepth 389 0, // rightShift 390 C2PlaneInfo::NATIVE, // endianness 391 C2PlanarLayout::PLANE_Y, // rootIx 392 0, // offset 393 }; 394 layout->planes[C2PlanarLayout::PLANE_U] = { 395 C2PlaneInfo::CHANNEL_CB, // channel 396 (int32_t)ycbcrLayout.chromaStep, // colInc 397 (int32_t)ycbcrLayout.cStride, // rowInc 398 2, // mColSampling 399 2, // mRowSampling 400 8, // allocatedDepth 401 8, // bitDepth 402 0, // rightShift 403 C2PlaneInfo::NATIVE, // endianness 404 C2PlanarLayout::PLANE_U, // rootIx 405 0, // offset 406 }; 407 layout->planes[C2PlanarLayout::PLANE_V] = { 408 C2PlaneInfo::CHANNEL_CR, // channel 409 (int32_t)ycbcrLayout.chromaStep, // colInc 410 (int32_t)ycbcrLayout.cStride, // rowInc 411 2, // mColSampling 412 2, // mRowSampling 413 8, // allocatedDepth 414 8, // bitDepth 415 0, // rightShift 416 C2PlaneInfo::NATIVE, // endianness 417 C2PlanarLayout::PLANE_V, // rootIx 418 0, // offset 419 }; 420 // handle interleaved formats 421 intptr_t uvOffset = addr[C2PlanarLayout::PLANE_V] - addr[C2PlanarLayout::PLANE_U]; 422 if (uvOffset > 0 && uvOffset < (intptr_t)ycbcrLayout.chromaStep) { 423 layout->rootPlanes = 2; 424 layout->planes[C2PlanarLayout::PLANE_V].rootIx = C2PlanarLayout::PLANE_U; 425 layout->planes[C2PlanarLayout::PLANE_V].offset = uvOffset; 426 } else if (uvOffset < 0 && uvOffset > -(intptr_t)ycbcrLayout.chromaStep) { 427 layout->rootPlanes = 2; 428 layout->planes[C2PlanarLayout::PLANE_U].rootIx = C2PlanarLayout::PLANE_V; 429 layout->planes[C2PlanarLayout::PLANE_U].offset = -uvOffset; 430 } 431 break; 432 } 433 434 case PixelFormat::RGBA_8888: 435 // TODO: alpha channel 436 // fall-through 437 case PixelFormat::RGBX_8888: { 438 void *pointer = nullptr; 439 mMapper->lock( 440 const_cast<native_handle_t *>(mBuffer), 441 grallocUsage, 442 { (int32_t)rect.left, (int32_t)rect.top, (int32_t)rect.width, (int32_t)rect.height }, 443 // TODO: fence 444 hidl_handle(), 445 [&err, &pointer](const auto &maperr, const auto &mapPointer) { 446 err = maperr2error(maperr); 447 if (err == C2_OK) { 448 pointer = mapPointer; 449 } 450 }); 451 if (err != C2_OK) { 452 ALOGD("lock failed: %d", err); 453 return err; 454 } 455 addr[C2PlanarLayout::PLANE_R] = (uint8_t *)pointer; 456 addr[C2PlanarLayout::PLANE_G] = (uint8_t *)pointer + 1; 457 addr[C2PlanarLayout::PLANE_B] = (uint8_t *)pointer + 2; 458 layout->type = C2PlanarLayout::TYPE_RGB; 459 layout->numPlanes = 3; 460 layout->rootPlanes = 1; 461 layout->planes[C2PlanarLayout::PLANE_R] = { 462 C2PlaneInfo::CHANNEL_R, // channel 463 4, // colInc 464 4 * (int32_t)mInfo.stride, // rowInc 465 1, // mColSampling 466 1, // mRowSampling 467 8, // allocatedDepth 468 8, // bitDepth 469 0, // rightShift 470 C2PlaneInfo::NATIVE, // endianness 471 C2PlanarLayout::PLANE_R, // rootIx 472 0, // offset 473 }; 474 layout->planes[C2PlanarLayout::PLANE_G] = { 475 C2PlaneInfo::CHANNEL_G, // channel 476 4, // colInc 477 4 * (int32_t)mInfo.stride, // rowInc 478 1, // mColSampling 479 1, // mRowSampling 480 8, // allocatedDepth 481 8, // bitDepth 482 0, // rightShift 483 C2PlaneInfo::NATIVE, // endianness 484 C2PlanarLayout::PLANE_R, // rootIx 485 1, // offset 486 }; 487 layout->planes[C2PlanarLayout::PLANE_B] = { 488 C2PlaneInfo::CHANNEL_B, // channel 489 4, // colInc 490 4 * (int32_t)mInfo.stride, // rowInc 491 1, // mColSampling 492 1, // mRowSampling 493 8, // allocatedDepth 494 8, // bitDepth 495 0, // rightShift 496 C2PlaneInfo::NATIVE, // endianness 497 C2PlanarLayout::PLANE_R, // rootIx 498 2, // offset 499 }; 500 break; 501 } 502 default: { 503 ALOGD("unsupported pixel format: %d", mInfo.mapperInfo.format); 504 return C2_OMITTED; 505 } 506 } 507 mLocked = true; 508 509 return C2_OK; 510 } 511 512 c2_status_t C2AllocationGralloc::unmap( 513 uint8_t **addr, C2Rect rect, C2Fence *fence /* nullable */) { 514 // TODO: check addr and size, use fence 515 (void)addr; 516 (void)rect; 517 c2_status_t err = C2_OK; 518 mMapper->unlock( 519 const_cast<native_handle_t *>(mBuffer), 520 [&err, &fence](const auto &maperr, const auto &releaseFence) { 521 // TODO 522 (void) fence; 523 (void) releaseFence; 524 err = maperr2error(maperr); 525 if (err == C2_OK) { 526 // TODO: fence 527 } 528 }); 529 if (err == C2_OK) { 530 mLocked = false; 531 } 532 return err; 533 } 534 535 bool C2AllocationGralloc::equals(const std::shared_ptr<const C2GraphicAllocation> &other) const { 536 return other && other->handle() == handle(); 537 } 538 539 /* ===================================== GRALLOC ALLOCATOR ==================================== */ 540 class C2AllocatorGralloc::Impl { 541 public: 542 Impl(id_t id, bool bufferQueue); 543 544 id_t getId() const { 545 return mTraits->id; 546 } 547 548 C2String getName() const { 549 return mTraits->name; 550 } 551 552 std::shared_ptr<const C2Allocator::Traits> getTraits() const { 553 return mTraits; 554 } 555 556 c2_status_t newGraphicAllocation( 557 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage, 558 std::shared_ptr<C2GraphicAllocation> *allocation); 559 560 c2_status_t priorGraphicAllocation( 561 const C2Handle *handle, 562 std::shared_ptr<C2GraphicAllocation> *allocation); 563 564 c2_status_t status() const { return mInit; } 565 566 private: 567 std::shared_ptr<C2Allocator::Traits> mTraits; 568 c2_status_t mInit; 569 sp<IAllocator> mAllocator; 570 sp<IMapper> mMapper; 571 const bool mBufferQueue; 572 }; 573 574 void _UnwrapNativeCodec2GrallocMetadata( 575 const C2Handle *const handle, 576 uint32_t *width, uint32_t *height, uint32_t *format,uint64_t *usage, uint32_t *stride, 577 uint64_t *igbp_id, uint32_t *igbp_slot) { 578 (void)C2HandleGralloc::Import(handle, width, height, format, usage, stride, igbp_id, igbp_slot); 579 } 580 581 C2AllocatorGralloc::Impl::Impl(id_t id, bool bufferQueue) 582 : mInit(C2_OK), mBufferQueue(bufferQueue) { 583 // TODO: get this from allocator 584 C2MemoryUsage minUsage = { 0, 0 }, maxUsage = { ~(uint64_t)0, ~(uint64_t)0 }; 585 Traits traits = { "android.allocator.gralloc", id, C2Allocator::GRAPHIC, minUsage, maxUsage }; 586 mTraits = std::make_shared<C2Allocator::Traits>(traits); 587 588 // gralloc allocator is a singleton, so all objects share a global service 589 mAllocator = IAllocator::getService(); 590 mMapper = IMapper::getService(); 591 if (mAllocator == nullptr || mMapper == nullptr) { 592 mInit = C2_CORRUPTED; 593 } 594 } 595 596 c2_status_t C2AllocatorGralloc::Impl::newGraphicAllocation( 597 uint32_t width, uint32_t height, uint32_t format, const C2MemoryUsage &usage, 598 std::shared_ptr<C2GraphicAllocation> *allocation) { 599 uint64_t grallocUsage = static_cast<C2AndroidMemoryUsage>(usage).asGrallocUsage(); 600 ALOGV("allocating buffer with usage %#llx => %#llx", 601 (long long)usage.expected, (long long)grallocUsage); 602 603 BufferDescriptorInfo info = { 604 { 605 width, 606 height, 607 1u, // layerCount 608 (PixelFormat)format, 609 grallocUsage, 610 }, 611 0u, // stride placeholder 612 }; 613 c2_status_t err = C2_OK; 614 BufferDescriptor desc; 615 mMapper->createDescriptor( 616 info.mapperInfo, [&err, &desc](const auto &maperr, const auto &descriptor) { 617 err = maperr2error(maperr); 618 if (err == C2_OK) { 619 desc = descriptor; 620 } 621 }); 622 if (err != C2_OK) { 623 return err; 624 } 625 626 // IAllocator shares IMapper error codes. 627 hidl_handle buffer; 628 mAllocator->allocate( 629 desc, 630 1u, 631 [&err, &buffer, &info](const auto &maperr, const auto &stride, auto &buffers) { 632 err = maperr2error(maperr); 633 if (err != C2_OK) { 634 return; 635 } 636 if (buffers.size() != 1u) { 637 err = C2_CORRUPTED; 638 return; 639 } 640 info.stride = stride; 641 buffer = std::move(buffers[0]); 642 }); 643 if (err != C2_OK) { 644 return err; 645 } 646 647 648 allocation->reset(new C2AllocationGralloc( 649 info, mMapper, buffer, 650 C2HandleGralloc::WrapNativeHandle( 651 buffer.getNativeHandle(), 652 info.mapperInfo.width, info.mapperInfo.height, 653 (uint32_t)info.mapperInfo.format, info.mapperInfo.usage, info.stride, 654 0, mBufferQueue ? ~0 : 0), 655 mTraits->id)); 656 return C2_OK; 657 } 658 659 c2_status_t C2AllocatorGralloc::Impl::priorGraphicAllocation( 660 const C2Handle *handle, 661 std::shared_ptr<C2GraphicAllocation> *allocation) { 662 BufferDescriptorInfo info; 663 info.mapperInfo.layerCount = 1u; 664 uint64_t igbp_id; 665 uint32_t igbp_slot; 666 const C2HandleGralloc *grallocHandle = C2HandleGralloc::Import( 667 handle, 668 &info.mapperInfo.width, &info.mapperInfo.height, 669 (uint32_t *)&info.mapperInfo.format, (uint64_t *)&info.mapperInfo.usage, &info.stride, 670 &igbp_id, &igbp_slot); 671 if (grallocHandle == nullptr) { 672 return C2_BAD_VALUE; 673 } 674 675 hidl_handle hidlHandle; 676 hidlHandle.setTo(C2HandleGralloc::UnwrapNativeHandle(grallocHandle), true); 677 678 allocation->reset(new C2AllocationGralloc(info, mMapper, hidlHandle, grallocHandle, mTraits->id)); 679 return C2_OK; 680 } 681 682 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue) 683 : mImpl(new Impl(id, bufferQueue)) {} 684 685 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; } 686 687 C2Allocator::id_t C2AllocatorGralloc::getId() const { 688 return mImpl->getId(); 689 } 690 691 C2String C2AllocatorGralloc::getName() const { 692 return mImpl->getName(); 693 } 694 695 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const { 696 return mImpl->getTraits(); 697 } 698 699 c2_status_t C2AllocatorGralloc::newGraphicAllocation( 700 uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage, 701 std::shared_ptr<C2GraphicAllocation> *allocation) { 702 return mImpl->newGraphicAllocation(width, height, format, usage, allocation); 703 } 704 705 c2_status_t C2AllocatorGralloc::priorGraphicAllocation( 706 const C2Handle *handle, 707 std::shared_ptr<C2GraphicAllocation> *allocation) { 708 return mImpl->priorGraphicAllocation(handle, allocation); 709 } 710 711 c2_status_t C2AllocatorGralloc::status() const { 712 return mImpl->status(); 713 } 714 715 bool C2AllocatorGralloc::isValid(const C2Handle* const o) { 716 return C2HandleGralloc::isValid(o); 717 } 718 719 } // namespace android 720