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 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 56 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 ==================================== */ 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 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 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 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 163 ExtraData *getExtraData(C2Handle *const handle) { 164 return const_cast<ExtraData *>(getExtraData(const_cast<const C2Handle *const>(handle))); 165 } 166 167 public: 168 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 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 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 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 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 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 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 278 native_handle_t *UnwrapNativeCodec2GrallocHandle(const C2Handle *const handle) { 279 return C2HandleGralloc::UnwrapNativeHandle(handle); 280 } 281 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 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; 306 virtual C2Allocator::id_t getAllocatorId() const override { return mAllocatorId; } 307 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 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 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 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 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 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 864 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 873 id_t getId() const { 874 return mTraits->id; 875 } 876 877 C2String getName() const { 878 return mTraits->name; 879 } 880 881 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 893 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 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 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 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 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 1115 C2AllocatorGralloc::C2AllocatorGralloc(id_t id, bool bufferQueue) 1116 : mImpl(new Impl(id, bufferQueue)) {} 1117 1118 C2AllocatorGralloc::~C2AllocatorGralloc() { delete mImpl; } 1119 1120 C2Allocator::id_t C2AllocatorGralloc::getId() const { 1121 return mImpl->getId(); 1122 } 1123 1124 C2String C2AllocatorGralloc::getName() const { 1125 return mImpl->getName(); 1126 } 1127 1128 std::shared_ptr<const C2Allocator::Traits> C2AllocatorGralloc::getTraits() const { 1129 return mImpl->getTraits(); 1130 } 1131 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 1138 c2_status_t C2AllocatorGralloc::priorGraphicAllocation( 1139 const C2Handle *handle, 1140 std::shared_ptr<C2GraphicAllocation> *allocation) { 1141 return mImpl->priorGraphicAllocation(handle, allocation); 1142 } 1143 1144 c2_status_t C2AllocatorGralloc::status() const { 1145 return mImpl->status(); 1146 } 1147 1148 bool C2AllocatorGralloc::isValid(const C2Handle* const o) { 1149 return C2HandleGralloc::isValid(o); 1150 } 1151 1152 } // namespace android 1153