You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
491 lines
17 KiB
491 lines
17 KiB
/*
|
|
* Copyright 2020 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "cros_gralloc/gralloc3/CrosGralloc3Mapper.h"
|
|
|
|
#include <cutils/native_handle.h>
|
|
|
|
#include "cros_gralloc/cros_gralloc_helpers.h"
|
|
#include "cros_gralloc/gralloc3/CrosGralloc3Utils.h"
|
|
|
|
#include "helpers.h"
|
|
|
|
using android::hardware::hidl_handle;
|
|
using android::hardware::hidl_vec;
|
|
using android::hardware::Return;
|
|
using android::hardware::Void;
|
|
using android::hardware::graphics::common::V1_2::BufferUsage;
|
|
using android::hardware::graphics::common::V1_2::PixelFormat;
|
|
using android::hardware::graphics::mapper::V3_0::Error;
|
|
using android::hardware::graphics::mapper::V3_0::IMapper;
|
|
using android::hardware::graphics::mapper::V3_0::YCbCrLayout;
|
|
|
|
CrosGralloc3Mapper::CrosGralloc3Mapper() : mDriver(std::make_unique<cros_gralloc_driver>()) {
|
|
if (mDriver->init()) {
|
|
drv_log("Failed to initialize driver.\n");
|
|
mDriver = nullptr;
|
|
}
|
|
}
|
|
|
|
Return<void> CrosGralloc3Mapper::createDescriptor(const BufferDescriptorInfo& description,
|
|
createDescriptor_cb hidlCb) {
|
|
hidl_vec<uint32_t> descriptor;
|
|
|
|
if (description.width == 0) {
|
|
drv_log("Failed to createDescriptor. Bad width: %d.\n", description.width);
|
|
hidlCb(Error::BAD_VALUE, descriptor);
|
|
return Void();
|
|
}
|
|
|
|
if (description.height == 0) {
|
|
drv_log("Failed to createDescriptor. Bad height: %d.\n", description.height);
|
|
hidlCb(Error::BAD_VALUE, descriptor);
|
|
return Void();
|
|
}
|
|
|
|
if (description.layerCount == 0) {
|
|
drv_log("Failed to createDescriptor. Bad layer count: %d.\n", description.layerCount);
|
|
hidlCb(Error::BAD_VALUE, descriptor);
|
|
return Void();
|
|
}
|
|
|
|
auto descriptor_opt = encodeBufferDescriptorInfo(description);
|
|
if (!descriptor_opt) {
|
|
drv_log("Failed to createDescriptor. Failed to encodeBufferDescriptorInfo\n");
|
|
hidlCb(Error::BAD_VALUE, descriptor);
|
|
return Void();
|
|
}
|
|
|
|
descriptor = *descriptor_opt;
|
|
hidlCb(Error::NONE, descriptor);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> CrosGralloc3Mapper::importBuffer(const hidl_handle& handle, importBuffer_cb hidlCb) {
|
|
if (!mDriver) {
|
|
drv_log("Failed to import buffer. Driver is uninitialized.\n");
|
|
hidlCb(Error::NO_RESOURCES, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
const native_handle_t* bufferHandle = handle.getNativeHandle();
|
|
if (!bufferHandle || bufferHandle->numFds == 0) {
|
|
drv_log("Failed to importBuffer. Bad handle.\n");
|
|
hidlCb(Error::BAD_BUFFER, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle);
|
|
if (!importedBufferHandle) {
|
|
drv_log("Failed to importBuffer. Handle clone failed.\n");
|
|
hidlCb(Error::NO_RESOURCES, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
int ret = mDriver->retain(importedBufferHandle);
|
|
if (ret) {
|
|
native_handle_close(importedBufferHandle);
|
|
native_handle_delete(importedBufferHandle);
|
|
hidlCb(Error::NO_RESOURCES, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
hidlCb(Error::NONE, importedBufferHandle);
|
|
return Void();
|
|
}
|
|
|
|
Return<Error> CrosGralloc3Mapper::freeBuffer(void* rawHandle) {
|
|
if (!mDriver) {
|
|
drv_log("Failed to freeBuffer. Driver is uninitialized.\n");
|
|
return Error::NO_RESOURCES;
|
|
}
|
|
|
|
native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
|
|
if (!bufferHandle) {
|
|
drv_log("Failed to freeBuffer. Empty handle.\n");
|
|
return Error::BAD_BUFFER;
|
|
}
|
|
|
|
int ret = mDriver->release(bufferHandle);
|
|
if (ret) {
|
|
drv_log("Failed to freeBuffer.\n");
|
|
return Error::BAD_BUFFER;
|
|
}
|
|
|
|
native_handle_close(bufferHandle);
|
|
native_handle_delete(bufferHandle);
|
|
return Error::NONE;
|
|
}
|
|
|
|
Return<Error> CrosGralloc3Mapper::validateBufferSize(void* rawHandle,
|
|
const BufferDescriptorInfo& descriptor,
|
|
uint32_t stride) {
|
|
if (!mDriver) {
|
|
drv_log("Failed to validateBufferSize. Driver is uninitialized.\n");
|
|
return Error::NO_RESOURCES;
|
|
}
|
|
|
|
native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
|
|
if (!bufferHandle) {
|
|
drv_log("Failed to validateBufferSize. Empty handle.\n");
|
|
return Error::BAD_BUFFER;
|
|
}
|
|
|
|
cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
|
|
if (!crosHandle) {
|
|
drv_log("Failed to validateBufferSize. Invalid handle.\n");
|
|
return Error::BAD_BUFFER;
|
|
}
|
|
|
|
PixelFormat crosHandleFormat = static_cast<PixelFormat>(crosHandle->droid_format);
|
|
if (descriptor.format != crosHandleFormat) {
|
|
drv_log("Failed to validateBufferSize. Format mismatch.\n");
|
|
return Error::BAD_BUFFER;
|
|
}
|
|
|
|
if (descriptor.width != crosHandle->width) {
|
|
drv_log("Failed to validateBufferSize. Width mismatch (%d vs %d).\n", descriptor.width,
|
|
crosHandle->width);
|
|
return Error::BAD_VALUE;
|
|
}
|
|
|
|
if (descriptor.height != crosHandle->height) {
|
|
drv_log("Failed to validateBufferSize. Height mismatch (%d vs %d).\n", descriptor.height,
|
|
crosHandle->height);
|
|
return Error::BAD_VALUE;
|
|
}
|
|
|
|
if (stride != crosHandle->pixel_stride) {
|
|
drv_log("Failed to validateBufferSize. Stride mismatch (%d vs %d).\n", stride,
|
|
crosHandle->pixel_stride);
|
|
return Error::BAD_VALUE;
|
|
}
|
|
|
|
return Error::NONE;
|
|
}
|
|
|
|
Return<void> CrosGralloc3Mapper::getTransportSize(void* rawHandle, getTransportSize_cb hidlCb) {
|
|
if (!mDriver) {
|
|
drv_log("Failed to getTransportSize. Driver is uninitialized.\n");
|
|
hidlCb(Error::BAD_BUFFER, 0, 0);
|
|
return Void();
|
|
}
|
|
|
|
native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle);
|
|
if (!bufferHandle) {
|
|
drv_log("Failed to getTransportSize. Bad handle.\n");
|
|
hidlCb(Error::BAD_BUFFER, 0, 0);
|
|
return Void();
|
|
}
|
|
|
|
// No local process data is currently stored on the native handle.
|
|
hidlCb(Error::NONE, bufferHandle->numFds, bufferHandle->numInts);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> CrosGralloc3Mapper::lock(void* rawHandle, uint64_t cpuUsage, const Rect& accessRegion,
|
|
const hidl_handle& acquireFence, lock_cb hidlCb) {
|
|
if (!mDriver) {
|
|
drv_log("Failed to lock. Driver is uninitialized.\n");
|
|
hidlCb(Error::NO_RESOURCES, nullptr, 0, 0);
|
|
return Void();
|
|
}
|
|
|
|
buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
|
|
if (!bufferHandle) {
|
|
drv_log("Failed to lock. Empty handle.\n");
|
|
hidlCb(Error::BAD_BUFFER, nullptr, 0, 0);
|
|
return Void();
|
|
}
|
|
|
|
cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
|
|
if (crosHandle == nullptr) {
|
|
drv_log("Failed to lock. Invalid handle.\n");
|
|
hidlCb(Error::BAD_BUFFER, nullptr, 0, 0);
|
|
return Void();
|
|
}
|
|
|
|
LockResult result = lockInternal(crosHandle, cpuUsage, accessRegion, acquireFence);
|
|
if (result.error != Error::NONE) {
|
|
drv_log("Failed to lock. Failed to lockInternal.\n");
|
|
hidlCb(result.error, nullptr, 0, 0);
|
|
return Void();
|
|
}
|
|
|
|
int32_t bytesPerPixel = drv_bytes_per_pixel_from_format(crosHandle->format, 0);
|
|
int32_t bytesPerStride = static_cast<int32_t>(crosHandle->strides[0]);
|
|
|
|
hidlCb(Error::NONE, result.mapped[0], bytesPerPixel, bytesPerStride);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> CrosGralloc3Mapper::lockYCbCr(void* rawHandle, uint64_t cpuUsage,
|
|
const Rect& accessRegion,
|
|
const android::hardware::hidl_handle& acquireFence,
|
|
lockYCbCr_cb hidlCb) {
|
|
YCbCrLayout ycbcr = {};
|
|
|
|
if (!mDriver) {
|
|
drv_log("Failed to lock. Driver is uninitialized.\n");
|
|
hidlCb(Error::NO_RESOURCES, ycbcr);
|
|
return Void();
|
|
}
|
|
|
|
buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
|
|
if (!bufferHandle) {
|
|
drv_log("Failed to lockYCbCr. Empty handle.\n");
|
|
hidlCb(Error::BAD_BUFFER, ycbcr);
|
|
return Void();
|
|
}
|
|
|
|
cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle);
|
|
if (crosHandle == nullptr) {
|
|
drv_log("Failed to lockYCbCr. Invalid handle.\n");
|
|
hidlCb(Error::BAD_BUFFER, ycbcr);
|
|
return Void();
|
|
}
|
|
|
|
LockResult result = lockInternal(crosHandle, cpuUsage, accessRegion, acquireFence);
|
|
if (result.error != Error::NONE) {
|
|
drv_log("Failed to lockYCbCr. Failed to lockInternal.\n");
|
|
hidlCb(result.error, ycbcr);
|
|
return Void();
|
|
}
|
|
|
|
switch (crosHandle->format) {
|
|
case DRM_FORMAT_NV12: {
|
|
ycbcr.y = result.mapped[0] + crosHandle->offsets[0];
|
|
ycbcr.cb = result.mapped[0] + crosHandle->offsets[1];
|
|
ycbcr.cr = result.mapped[0] + crosHandle->offsets[1] + 1;
|
|
ycbcr.yStride = crosHandle->strides[0];
|
|
ycbcr.cStride = crosHandle->strides[1];
|
|
ycbcr.chromaStep = 2;
|
|
break;
|
|
}
|
|
case DRM_FORMAT_NV21: {
|
|
ycbcr.y = result.mapped[0] + crosHandle->offsets[0];
|
|
ycbcr.cb = result.mapped[0] + crosHandle->offsets[1] + 1;
|
|
ycbcr.cr = result.mapped[0] + crosHandle->offsets[1];
|
|
ycbcr.yStride = crosHandle->strides[0];
|
|
ycbcr.cStride = crosHandle->strides[1];
|
|
ycbcr.chromaStep = 2;
|
|
break;
|
|
}
|
|
case DRM_FORMAT_YVU420: {
|
|
ycbcr.y = result.mapped[0] + crosHandle->offsets[0];
|
|
ycbcr.cb = result.mapped[0] + crosHandle->offsets[1];
|
|
ycbcr.cr = result.mapped[0] + crosHandle->offsets[2];
|
|
ycbcr.yStride = crosHandle->strides[0];
|
|
ycbcr.cStride = crosHandle->strides[1];
|
|
ycbcr.chromaStep = 1;
|
|
break;
|
|
}
|
|
case DRM_FORMAT_YVU420_ANDROID: {
|
|
ycbcr.y = result.mapped[0] + crosHandle->offsets[0];
|
|
ycbcr.cb = result.mapped[0] + crosHandle->offsets[2];
|
|
ycbcr.cr = result.mapped[0] + crosHandle->offsets[1];
|
|
ycbcr.yStride = crosHandle->strides[0];
|
|
ycbcr.cStride = crosHandle->strides[1];
|
|
ycbcr.chromaStep = 1;
|
|
break;
|
|
}
|
|
default: {
|
|
std::string format = get_drm_format_string(crosHandle->format);
|
|
drv_log("Failed to lockYCbCr. Unhandled format: %s\n", format.c_str());
|
|
hidlCb(Error::BAD_BUFFER, ycbcr);
|
|
return Void();
|
|
}
|
|
}
|
|
|
|
hidlCb(Error::NONE, ycbcr);
|
|
return Void();
|
|
}
|
|
|
|
CrosGralloc3Mapper::LockResult CrosGralloc3Mapper::lockInternal(
|
|
cros_gralloc_handle_t crosHandle, uint64_t cpuUsage, const Rect& region,
|
|
const android::hardware::hidl_handle& acquireFence) {
|
|
LockResult result = {};
|
|
|
|
if (!mDriver) {
|
|
drv_log("Failed to lock. Driver is uninitialized.\n");
|
|
result.error = Error::NO_RESOURCES;
|
|
return result;
|
|
}
|
|
|
|
if (cpuUsage == 0) {
|
|
drv_log("Failed to lock. Bad cpu usage: %" PRIu64 ".\n", cpuUsage);
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
uint32_t mapUsage = 0;
|
|
int ret = convertToMapUsage(cpuUsage, &mapUsage);
|
|
if (ret) {
|
|
drv_log("Failed to lock. Convert usage failed.\n");
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
if (region.left < 0) {
|
|
drv_log("Failed to lock. Invalid region: negative left value %d.\n", region.left);
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
if (region.top < 0) {
|
|
drv_log("Failed to lock. Invalid region: negative top value %d.\n", region.top);
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
if (region.width < 0) {
|
|
drv_log("Failed to lock. Invalid region: negative width value %d.\n", region.width);
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
if (region.height < 0) {
|
|
drv_log("Failed to lock. Invalid region: negative height value %d.\n", region.height);
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
if (region.width > crosHandle->width) {
|
|
drv_log("Failed to lock. Invalid region: width greater than buffer width (%d vs %d).\n",
|
|
region.width, crosHandle->width);
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
if (region.height > crosHandle->height) {
|
|
drv_log("Failed to lock. Invalid region: height greater than buffer height (%d vs %d).\n",
|
|
region.height, crosHandle->height);
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
struct rectangle rect = {static_cast<uint32_t>(region.left), static_cast<uint32_t>(region.top),
|
|
static_cast<uint32_t>(region.width),
|
|
static_cast<uint32_t>(region.height)};
|
|
|
|
// An access region of all zeros means the entire buffer.
|
|
if (rect.x == 0 && rect.y == 0 && rect.width == 0 && rect.height == 0) {
|
|
rect.width = crosHandle->width;
|
|
rect.height = crosHandle->height;
|
|
}
|
|
|
|
int acquireFenceFd = -1;
|
|
ret = convertToFenceFd(acquireFence, &acquireFenceFd);
|
|
if (ret) {
|
|
drv_log("Failed to lock. Bad acquire fence.\n");
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(crosHandle);
|
|
ret = mDriver->lock(bufferHandle, acquireFenceFd, false, &rect, mapUsage, result.mapped);
|
|
if (ret) {
|
|
result.error = Error::BAD_VALUE;
|
|
return result;
|
|
}
|
|
|
|
result.error = Error::NONE;
|
|
return result;
|
|
}
|
|
|
|
Return<void> CrosGralloc3Mapper::unlock(void* rawHandle, unlock_cb hidlCb) {
|
|
if (!mDriver) {
|
|
drv_log("Failed to unlock. Driver is uninitialized.\n");
|
|
hidlCb(Error::BAD_BUFFER, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle);
|
|
if (!bufferHandle) {
|
|
drv_log("Failed to unlock. Empty handle.\n");
|
|
hidlCb(Error::BAD_BUFFER, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
int releaseFenceFd = -1;
|
|
int ret = mDriver->unlock(bufferHandle, &releaseFenceFd);
|
|
if (ret) {
|
|
drv_log("Failed to unlock.\n");
|
|
hidlCb(Error::BAD_BUFFER, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
hidl_handle releaseFenceHandle;
|
|
ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle);
|
|
if (ret) {
|
|
drv_log("Failed to unlock. Failed to convert release fence to handle.\n");
|
|
hidlCb(Error::BAD_BUFFER, nullptr);
|
|
return Void();
|
|
}
|
|
|
|
hidlCb(Error::NONE, releaseFenceHandle);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> CrosGralloc3Mapper::isSupported(const BufferDescriptorInfo& descriptor,
|
|
isSupported_cb hidlCb) {
|
|
if (!mDriver) {
|
|
drv_log("Failed to isSupported. Driver is uninitialized.\n");
|
|
hidlCb(Error::BAD_VALUE, false);
|
|
return Void();
|
|
}
|
|
|
|
struct cros_gralloc_buffer_descriptor crosDescriptor;
|
|
if (convertToCrosDescriptor(descriptor, &crosDescriptor)) {
|
|
hidlCb(Error::NONE, false);
|
|
return Void();
|
|
}
|
|
|
|
bool supported = mDriver->is_supported(&crosDescriptor);
|
|
if (!supported) {
|
|
crosDescriptor.use_flags &= ~BO_USE_SCANOUT;
|
|
supported = mDriver->is_supported(&crosDescriptor);
|
|
}
|
|
|
|
hidlCb(Error::NONE, supported);
|
|
return Void();
|
|
}
|
|
|
|
int CrosGralloc3Mapper::getResolvedDrmFormat(PixelFormat pixelFormat, uint64_t bufferUsage,
|
|
uint32_t* outDrmFormat) {
|
|
uint32_t drmFormat;
|
|
if (convertToDrmFormat(pixelFormat, &drmFormat)) {
|
|
std::string pixelFormatString = getPixelFormatString(pixelFormat);
|
|
drv_log("Failed to getResolvedDrmFormat. Failed to convert format %s\n",
|
|
pixelFormatString.c_str());
|
|
return -EINVAL;
|
|
}
|
|
|
|
uint64_t usage;
|
|
if (convertToBufferUsage(bufferUsage, &usage)) {
|
|
std::string usageString = getUsageString(bufferUsage);
|
|
drv_log("Failed to getResolvedDrmFormat. Failed to convert usage %s\n",
|
|
usageString.c_str());
|
|
return -EINVAL;
|
|
}
|
|
|
|
uint32_t resolvedDrmFormat = mDriver->get_resolved_drm_format(drmFormat, usage);
|
|
if (resolvedDrmFormat == DRM_FORMAT_INVALID) {
|
|
std::string drmFormatString = get_drm_format_string(drmFormat);
|
|
drv_log("Failed to getResolvedDrmFormat. Failed to resolve drm format %s\n",
|
|
drmFormatString.c_str());
|
|
return -EINVAL;
|
|
}
|
|
|
|
*outDrmFormat = resolvedDrmFormat;
|
|
|
|
return 0;
|
|
}
|
|
|
|
android::hardware::graphics::mapper::V3_0::IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
|
|
return static_cast<android::hardware::graphics::mapper::V3_0::IMapper*>(new CrosGralloc3Mapper);
|
|
}
|