1135 lines
45 KiB
C++
1135 lines
45 KiB
C++
/*
|
|
* Copyright 2019 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "Gralloc4"
|
|
|
|
#include <hidl/ServiceManagement.h>
|
|
#include <hwbinder/IPCThreadState.h>
|
|
#include <ui/Gralloc4.h>
|
|
|
|
#include <inttypes.h>
|
|
#include <log/log.h>
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wzero-length-array"
|
|
#include <sync/sync.h>
|
|
#pragma clang diagnostic pop
|
|
|
|
using aidl::android::hardware::graphics::common::ExtendableType;
|
|
using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
|
|
using aidl::android::hardware::graphics::common::StandardMetadataType;
|
|
using android::hardware::hidl_vec;
|
|
using android::hardware::graphics::allocator::V4_0::IAllocator;
|
|
using android::hardware::graphics::common::V1_2::BufferUsage;
|
|
using android::hardware::graphics::mapper::V4_0::BufferDescriptor;
|
|
using android::hardware::graphics::mapper::V4_0::Error;
|
|
using android::hardware::graphics::mapper::V4_0::IMapper;
|
|
using AidlDataspace = ::aidl::android::hardware::graphics::common::Dataspace;
|
|
using BufferDump = android::hardware::graphics::mapper::V4_0::IMapper::BufferDump;
|
|
using MetadataDump = android::hardware::graphics::mapper::V4_0::IMapper::MetadataDump;
|
|
using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
|
|
using MetadataTypeDescription =
|
|
android::hardware::graphics::mapper::V4_0::IMapper::MetadataTypeDescription;
|
|
|
|
namespace android {
|
|
|
|
namespace {
|
|
|
|
static constexpr Error kTransactionError = Error::NO_RESOURCES;
|
|
|
|
uint64_t getValidUsageBits() {
|
|
static const uint64_t validUsageBits = []() -> uint64_t {
|
|
uint64_t bits = 0;
|
|
for (const auto bit :
|
|
hardware::hidl_enum_range<hardware::graphics::common::V1_2::BufferUsage>()) {
|
|
bits = bits | bit;
|
|
}
|
|
return bits;
|
|
}();
|
|
return validUsageBits;
|
|
}
|
|
|
|
static inline IMapper::Rect sGralloc4Rect(const Rect& rect) {
|
|
IMapper::Rect outRect{};
|
|
outRect.left = rect.left;
|
|
outRect.top = rect.top;
|
|
outRect.width = rect.width();
|
|
outRect.height = rect.height();
|
|
return outRect;
|
|
}
|
|
static inline void sBufferDescriptorInfo(std::string name, uint32_t width, uint32_t height,
|
|
PixelFormat format, uint32_t layerCount, uint64_t usage,
|
|
IMapper::BufferDescriptorInfo* outDescriptorInfo) {
|
|
outDescriptorInfo->name = name;
|
|
outDescriptorInfo->width = width;
|
|
outDescriptorInfo->height = height;
|
|
outDescriptorInfo->layerCount = layerCount;
|
|
outDescriptorInfo->format = static_cast<hardware::graphics::common::V1_2::PixelFormat>(format);
|
|
outDescriptorInfo->usage = usage;
|
|
outDescriptorInfo->reservedSize = 0;
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
void Gralloc4Mapper::preload() {
|
|
android::hardware::preloadPassthroughService<IMapper>();
|
|
}
|
|
|
|
Gralloc4Mapper::Gralloc4Mapper() {
|
|
mMapper = IMapper::getService();
|
|
if (mMapper == nullptr) {
|
|
ALOGI("mapper 4.x is not supported");
|
|
return;
|
|
}
|
|
if (mMapper->isRemote()) {
|
|
LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
|
|
}
|
|
}
|
|
|
|
bool Gralloc4Mapper::isLoaded() const {
|
|
return mMapper != nullptr;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::validateBufferDescriptorInfo(
|
|
IMapper::BufferDescriptorInfo* descriptorInfo) const {
|
|
uint64_t validUsageBits = getValidUsageBits();
|
|
|
|
if (descriptorInfo->usage & ~validUsageBits) {
|
|
ALOGE("buffer descriptor contains invalid usage bits 0x%" PRIx64,
|
|
descriptorInfo->usage & ~validUsageBits);
|
|
return BAD_VALUE;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::createDescriptor(void* bufferDescriptorInfo,
|
|
void* outBufferDescriptor) const {
|
|
IMapper::BufferDescriptorInfo* descriptorInfo =
|
|
static_cast<IMapper::BufferDescriptorInfo*>(bufferDescriptorInfo);
|
|
BufferDescriptor* outDescriptor = static_cast<BufferDescriptor*>(outBufferDescriptor);
|
|
|
|
status_t status = validateBufferDescriptorInfo(descriptorInfo);
|
|
if (status != NO_ERROR) {
|
|
return status;
|
|
}
|
|
|
|
Error error;
|
|
auto hidl_cb = [&](const auto& tmpError, const auto& tmpDescriptor) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
*outDescriptor = tmpDescriptor;
|
|
};
|
|
|
|
hardware::Return<void> ret = mMapper->createDescriptor(*descriptorInfo, hidl_cb);
|
|
|
|
return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
|
|
buffer_handle_t* outBufferHandle) const {
|
|
Error error;
|
|
auto ret = mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
*outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
|
|
});
|
|
|
|
return static_cast<status_t>((ret.isOk()) ? error : kTransactionError);
|
|
}
|
|
|
|
void Gralloc4Mapper::freeBuffer(buffer_handle_t bufferHandle) const {
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
auto ret = mMapper->freeBuffer(buffer);
|
|
|
|
auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
|
|
ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d", buffer, error);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::validateBufferSize(buffer_handle_t bufferHandle, uint32_t width,
|
|
uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
uint32_t stride) const {
|
|
IMapper::BufferDescriptorInfo descriptorInfo;
|
|
sBufferDescriptorInfo("validateBufferSize", width, height, format, layerCount, usage,
|
|
&descriptorInfo);
|
|
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
auto ret = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
|
|
|
|
return static_cast<status_t>((ret.isOk()) ? static_cast<Error>(ret) : kTransactionError);
|
|
}
|
|
|
|
void Gralloc4Mapper::getTransportSize(buffer_handle_t bufferHandle, uint32_t* outNumFds,
|
|
uint32_t* outNumInts) const {
|
|
*outNumFds = uint32_t(bufferHandle->numFds);
|
|
*outNumInts = uint32_t(bufferHandle->numInts);
|
|
|
|
Error error;
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
auto ret = mMapper->getTransportSize(buffer,
|
|
[&](const auto& tmpError, const auto& tmpNumFds,
|
|
const auto& tmpNumInts) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
*outNumFds = tmpNumFds;
|
|
*outNumInts = tmpNumInts;
|
|
});
|
|
|
|
error = (ret.isOk()) ? error : kTransactionError;
|
|
|
|
ALOGE_IF(error != Error::NONE, "getTransportSize(%p) failed with %d", buffer, error);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
|
|
int acquireFence, void** outData, int32_t* outBytesPerPixel,
|
|
int32_t* outBytesPerStride) const {
|
|
std::vector<ui::PlaneLayout> planeLayouts;
|
|
status_t err = getPlaneLayouts(bufferHandle, &planeLayouts);
|
|
|
|
if (err == NO_ERROR && !planeLayouts.empty()) {
|
|
if (outBytesPerPixel) {
|
|
int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
|
|
for (const auto& planeLayout : planeLayouts) {
|
|
if (bitsPerPixel != planeLayout.sampleIncrementInBits) {
|
|
bitsPerPixel = -1;
|
|
}
|
|
}
|
|
if (bitsPerPixel >= 0 && bitsPerPixel % 8 == 0) {
|
|
*outBytesPerPixel = bitsPerPixel / 8;
|
|
} else {
|
|
*outBytesPerPixel = -1;
|
|
}
|
|
}
|
|
if (outBytesPerStride) {
|
|
int32_t bytesPerStride = planeLayouts.front().strideInBytes;
|
|
for (const auto& planeLayout : planeLayouts) {
|
|
if (bytesPerStride != planeLayout.strideInBytes) {
|
|
bytesPerStride = -1;
|
|
}
|
|
}
|
|
if (bytesPerStride >= 0) {
|
|
*outBytesPerStride = bytesPerStride;
|
|
} else {
|
|
*outBytesPerStride = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
|
|
IMapper::Rect accessRegion = sGralloc4Rect(bounds);
|
|
|
|
// put acquireFence in a hidl_handle
|
|
hardware::hidl_handle acquireFenceHandle;
|
|
NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
|
|
if (acquireFence >= 0) {
|
|
auto h = native_handle_init(acquireFenceStorage, 1, 0);
|
|
h->data[0] = acquireFence;
|
|
acquireFenceHandle = h;
|
|
}
|
|
|
|
Error error;
|
|
auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
|
|
[&](const auto& tmpError, const auto& tmpData) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
*outData = tmpData;
|
|
});
|
|
|
|
// we own acquireFence even on errors
|
|
if (acquireFence >= 0) {
|
|
close(acquireFence);
|
|
}
|
|
|
|
error = (ret.isOk()) ? error : kTransactionError;
|
|
|
|
ALOGW_IF(error != Error::NONE, "lock(%p, ...) failed: %d", bufferHandle, error);
|
|
|
|
return static_cast<status_t>(error);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage, const Rect& bounds,
|
|
int acquireFence, android_ycbcr* outYcbcr) const {
|
|
if (!outYcbcr) {
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
std::vector<ui::PlaneLayout> planeLayouts;
|
|
status_t error = getPlaneLayouts(bufferHandle, &planeLayouts);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
|
|
void* data = nullptr;
|
|
error = lock(bufferHandle, usage, bounds, acquireFence, &data, nullptr, nullptr);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
|
|
android_ycbcr ycbcr;
|
|
|
|
ycbcr.y = nullptr;
|
|
ycbcr.cb = nullptr;
|
|
ycbcr.cr = nullptr;
|
|
ycbcr.ystride = 0;
|
|
ycbcr.cstride = 0;
|
|
ycbcr.chroma_step = 0;
|
|
|
|
for (const auto& planeLayout : planeLayouts) {
|
|
for (const auto& planeLayoutComponent : planeLayout.components) {
|
|
if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
|
|
continue;
|
|
}
|
|
if (0 != planeLayoutComponent.offsetInBits % 8) {
|
|
unlock(bufferHandle);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
uint8_t* tmpData = static_cast<uint8_t*>(data) + planeLayout.offsetInBytes +
|
|
(planeLayoutComponent.offsetInBits / 8);
|
|
uint64_t sampleIncrementInBytes;
|
|
|
|
auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
|
|
switch (type) {
|
|
case PlaneLayoutComponentType::Y:
|
|
if ((ycbcr.y != nullptr) || (planeLayoutComponent.sizeInBits != 8) ||
|
|
(planeLayout.sampleIncrementInBits != 8)) {
|
|
unlock(bufferHandle);
|
|
return BAD_VALUE;
|
|
}
|
|
ycbcr.y = tmpData;
|
|
ycbcr.ystride = planeLayout.strideInBytes;
|
|
break;
|
|
|
|
case PlaneLayoutComponentType::CB:
|
|
case PlaneLayoutComponentType::CR:
|
|
if (planeLayout.sampleIncrementInBits % 8 != 0) {
|
|
unlock(bufferHandle);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
|
|
if ((sampleIncrementInBytes != 1) && (sampleIncrementInBytes != 2)) {
|
|
unlock(bufferHandle);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
if (ycbcr.cstride == 0 && ycbcr.chroma_step == 0) {
|
|
ycbcr.cstride = planeLayout.strideInBytes;
|
|
ycbcr.chroma_step = sampleIncrementInBytes;
|
|
} else {
|
|
if ((static_cast<int64_t>(ycbcr.cstride) != planeLayout.strideInBytes) ||
|
|
(ycbcr.chroma_step != sampleIncrementInBytes)) {
|
|
unlock(bufferHandle);
|
|
return BAD_VALUE;
|
|
}
|
|
}
|
|
|
|
if (type == PlaneLayoutComponentType::CB) {
|
|
if (ycbcr.cb != nullptr) {
|
|
unlock(bufferHandle);
|
|
return BAD_VALUE;
|
|
}
|
|
ycbcr.cb = tmpData;
|
|
} else {
|
|
if (ycbcr.cr != nullptr) {
|
|
unlock(bufferHandle);
|
|
return BAD_VALUE;
|
|
}
|
|
ycbcr.cr = tmpData;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
};
|
|
}
|
|
}
|
|
|
|
*outYcbcr = ycbcr;
|
|
return static_cast<status_t>(Error::NONE);
|
|
}
|
|
|
|
int Gralloc4Mapper::unlock(buffer_handle_t bufferHandle) const {
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
|
|
int releaseFence = -1;
|
|
Error error;
|
|
auto ret = mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
|
|
auto fenceHandle = tmpReleaseFence.getNativeHandle();
|
|
if (fenceHandle && fenceHandle->numFds == 1) {
|
|
int fd = dup(fenceHandle->data[0]);
|
|
if (fd >= 0) {
|
|
releaseFence = fd;
|
|
} else {
|
|
ALOGD("failed to dup unlock release fence");
|
|
sync_wait(fenceHandle->data[0], -1);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("unlock(%p) failed with %d", buffer, error);
|
|
}
|
|
|
|
return releaseFence;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::isSupported(uint32_t width, uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
bool* outSupported) const {
|
|
IMapper::BufferDescriptorInfo descriptorInfo;
|
|
sBufferDescriptorInfo("isSupported", width, height, format, layerCount, usage, &descriptorInfo);
|
|
|
|
Error error;
|
|
auto ret = mMapper->isSupported(descriptorInfo,
|
|
[&](const auto& tmpError, const auto& tmpSupported) {
|
|
error = tmpError;
|
|
if (error != Error::NONE) {
|
|
return;
|
|
}
|
|
if (outSupported) {
|
|
*outSupported = tmpSupported;
|
|
}
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("isSupported(%u, %u, %d, %u, ...) failed with %d", width, height, format, layerCount,
|
|
error);
|
|
}
|
|
|
|
return static_cast<status_t>(error);
|
|
}
|
|
|
|
template <class T>
|
|
status_t Gralloc4Mapper::get(buffer_handle_t bufferHandle, const MetadataType& metadataType,
|
|
DecodeFunction<T> decodeFunction, T* outMetadata) const {
|
|
if (!outMetadata) {
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
hidl_vec<uint8_t> vec;
|
|
Error error;
|
|
auto ret = mMapper->get(const_cast<native_handle_t*>(bufferHandle), metadataType,
|
|
[&](const auto& tmpError, const hidl_vec<uint8_t>& tmpVec) {
|
|
error = tmpError;
|
|
vec = tmpVec;
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("get(%s, %" PRIu64 ", ...) failed with %d", metadataType.name.c_str(),
|
|
metadataType.value, error);
|
|
return static_cast<status_t>(error);
|
|
}
|
|
|
|
return decodeFunction(vec, outMetadata);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getBufferId(buffer_handle_t bufferHandle, uint64_t* outBufferId) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_BufferId, gralloc4::decodeBufferId,
|
|
outBufferId);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getName(buffer_handle_t bufferHandle, std::string* outName) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Name, gralloc4::decodeName, outName);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getWidth(buffer_handle_t bufferHandle, uint64_t* outWidth) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Width, gralloc4::decodeWidth, outWidth);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getHeight(buffer_handle_t bufferHandle, uint64_t* outHeight) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Height, gralloc4::decodeHeight, outHeight);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getLayerCount(buffer_handle_t bufferHandle,
|
|
uint64_t* outLayerCount) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_LayerCount, gralloc4::decodeLayerCount,
|
|
outLayerCount);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getPixelFormatRequested(buffer_handle_t bufferHandle,
|
|
ui::PixelFormat* outPixelFormatRequested) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_PixelFormatRequested,
|
|
gralloc4::decodePixelFormatRequested, outPixelFormatRequested);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getPixelFormatFourCC(buffer_handle_t bufferHandle,
|
|
uint32_t* outPixelFormatFourCC) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_PixelFormatFourCC,
|
|
gralloc4::decodePixelFormatFourCC, outPixelFormatFourCC);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getPixelFormatModifier(buffer_handle_t bufferHandle,
|
|
uint64_t* outPixelFormatModifier) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_PixelFormatModifier,
|
|
gralloc4::decodePixelFormatModifier, outPixelFormatModifier);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getUsage(buffer_handle_t bufferHandle, uint64_t* outUsage) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Usage, gralloc4::decodeUsage, outUsage);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getAllocationSize(buffer_handle_t bufferHandle,
|
|
uint64_t* outAllocationSize) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_AllocationSize, gralloc4::decodeAllocationSize,
|
|
outAllocationSize);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getProtectedContent(buffer_handle_t bufferHandle,
|
|
uint64_t* outProtectedContent) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_ProtectedContent,
|
|
gralloc4::decodeProtectedContent, outProtectedContent);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getCompression(buffer_handle_t bufferHandle,
|
|
ExtendableType* outCompression) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Compression, gralloc4::decodeCompression,
|
|
outCompression);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getCompression(buffer_handle_t bufferHandle,
|
|
ui::Compression* outCompression) const {
|
|
if (!outCompression) {
|
|
return BAD_VALUE;
|
|
}
|
|
ExtendableType compression;
|
|
status_t error = getCompression(bufferHandle, &compression);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
if (!gralloc4::isStandardCompression(compression)) {
|
|
return BAD_TYPE;
|
|
}
|
|
*outCompression = gralloc4::getStandardCompressionValue(compression);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getInterlaced(buffer_handle_t bufferHandle,
|
|
ExtendableType* outInterlaced) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Interlaced, gralloc4::decodeInterlaced,
|
|
outInterlaced);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getInterlaced(buffer_handle_t bufferHandle,
|
|
ui::Interlaced* outInterlaced) const {
|
|
if (!outInterlaced) {
|
|
return BAD_VALUE;
|
|
}
|
|
ExtendableType interlaced;
|
|
status_t error = getInterlaced(bufferHandle, &interlaced);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
if (!gralloc4::isStandardInterlaced(interlaced)) {
|
|
return BAD_TYPE;
|
|
}
|
|
*outInterlaced = gralloc4::getStandardInterlacedValue(interlaced);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getChromaSiting(buffer_handle_t bufferHandle,
|
|
ExtendableType* outChromaSiting) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_ChromaSiting, gralloc4::decodeChromaSiting,
|
|
outChromaSiting);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getChromaSiting(buffer_handle_t bufferHandle,
|
|
ui::ChromaSiting* outChromaSiting) const {
|
|
if (!outChromaSiting) {
|
|
return BAD_VALUE;
|
|
}
|
|
ExtendableType chromaSiting;
|
|
status_t error = getChromaSiting(bufferHandle, &chromaSiting);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
if (!gralloc4::isStandardChromaSiting(chromaSiting)) {
|
|
return BAD_TYPE;
|
|
}
|
|
*outChromaSiting = gralloc4::getStandardChromaSitingValue(chromaSiting);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getPlaneLayouts(buffer_handle_t bufferHandle,
|
|
std::vector<ui::PlaneLayout>* outPlaneLayouts) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, gralloc4::decodePlaneLayouts,
|
|
outPlaneLayouts);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDataspace(buffer_handle_t bufferHandle,
|
|
ui::Dataspace* outDataspace) const {
|
|
if (!outDataspace) {
|
|
return BAD_VALUE;
|
|
}
|
|
AidlDataspace dataspace;
|
|
status_t error = get(bufferHandle, gralloc4::MetadataType_Dataspace, gralloc4::decodeDataspace,
|
|
&dataspace);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
// Gralloc4 uses stable AIDL dataspace but the rest of the system still uses HIDL dataspace
|
|
*outDataspace = static_cast<ui::Dataspace>(dataspace);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getBlendMode(buffer_handle_t bufferHandle,
|
|
ui::BlendMode* outBlendMode) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_BlendMode, gralloc4::decodeBlendMode,
|
|
outBlendMode);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getSmpte2086(buffer_handle_t bufferHandle,
|
|
std::optional<ui::Smpte2086>* outSmpte2086) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Smpte2086, gralloc4::decodeSmpte2086,
|
|
outSmpte2086);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getCta861_3(buffer_handle_t bufferHandle,
|
|
std::optional<ui::Cta861_3>* outCta861_3) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Cta861_3, gralloc4::decodeCta861_3,
|
|
outCta861_3);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getSmpte2094_40(
|
|
buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>>* outSmpte2094_40) const {
|
|
return get(bufferHandle, gralloc4::MetadataType_Smpte2094_40, gralloc4::decodeSmpte2094_40,
|
|
outSmpte2094_40);
|
|
}
|
|
|
|
template <class T>
|
|
status_t Gralloc4Mapper::getDefault(uint32_t width, uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
const MetadataType& metadataType,
|
|
DecodeFunction<T> decodeFunction, T* outMetadata) const {
|
|
if (!outMetadata) {
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
IMapper::BufferDescriptorInfo descriptorInfo;
|
|
sBufferDescriptorInfo("getDefault", width, height, format, layerCount, usage, &descriptorInfo);
|
|
|
|
hidl_vec<uint8_t> vec;
|
|
Error error;
|
|
auto ret = mMapper->getFromBufferDescriptorInfo(descriptorInfo, metadataType,
|
|
[&](const auto& tmpError,
|
|
const hidl_vec<uint8_t>& tmpVec) {
|
|
error = tmpError;
|
|
vec = tmpVec;
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("getDefault(%s, %" PRIu64 ", ...) failed with %d", metadataType.name.c_str(),
|
|
metadataType.value, error);
|
|
return static_cast<status_t>(error);
|
|
}
|
|
|
|
return decodeFunction(vec, outMetadata);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultPixelFormatFourCC(uint32_t width, uint32_t height,
|
|
PixelFormat format, uint32_t layerCount,
|
|
uint64_t usage,
|
|
uint32_t* outPixelFormatFourCC) const {
|
|
return getDefault(width, height, format, layerCount, usage,
|
|
gralloc4::MetadataType_PixelFormatFourCC, gralloc4::decodePixelFormatFourCC,
|
|
outPixelFormatFourCC);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultPixelFormatModifier(uint32_t width, uint32_t height,
|
|
PixelFormat format, uint32_t layerCount,
|
|
uint64_t usage,
|
|
uint64_t* outPixelFormatModifier) const {
|
|
return getDefault(width, height, format, layerCount, usage,
|
|
gralloc4::MetadataType_PixelFormatModifier,
|
|
gralloc4::decodePixelFormatModifier, outPixelFormatModifier);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultAllocationSize(uint32_t width, uint32_t height,
|
|
PixelFormat format, uint32_t layerCount,
|
|
uint64_t usage,
|
|
uint64_t* outAllocationSize) const {
|
|
return getDefault(width, height, format, layerCount, usage,
|
|
gralloc4::MetadataType_AllocationSize, gralloc4::decodeAllocationSize,
|
|
outAllocationSize);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultProtectedContent(uint32_t width, uint32_t height,
|
|
PixelFormat format, uint32_t layerCount,
|
|
uint64_t usage,
|
|
uint64_t* outProtectedContent) const {
|
|
return getDefault(width, height, format, layerCount, usage,
|
|
gralloc4::MetadataType_ProtectedContent, gralloc4::decodeProtectedContent,
|
|
outProtectedContent);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultCompression(uint32_t width, uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
ExtendableType* outCompression) const {
|
|
return getDefault(width, height, format, layerCount, usage, gralloc4::MetadataType_Compression,
|
|
gralloc4::decodeCompression, outCompression);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultCompression(uint32_t width, uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
ui::Compression* outCompression) const {
|
|
if (!outCompression) {
|
|
return BAD_VALUE;
|
|
}
|
|
ExtendableType compression;
|
|
status_t error = getDefaultCompression(width, height, format, layerCount, usage, &compression);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
if (!gralloc4::isStandardCompression(compression)) {
|
|
return BAD_TYPE;
|
|
}
|
|
*outCompression = gralloc4::getStandardCompressionValue(compression);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultInterlaced(uint32_t width, uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
ExtendableType* outInterlaced) const {
|
|
return getDefault(width, height, format, layerCount, usage, gralloc4::MetadataType_Interlaced,
|
|
gralloc4::decodeInterlaced, outInterlaced);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultInterlaced(uint32_t width, uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
ui::Interlaced* outInterlaced) const {
|
|
if (!outInterlaced) {
|
|
return BAD_VALUE;
|
|
}
|
|
ExtendableType interlaced;
|
|
status_t error = getDefaultInterlaced(width, height, format, layerCount, usage, &interlaced);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
if (!gralloc4::isStandardInterlaced(interlaced)) {
|
|
return BAD_TYPE;
|
|
}
|
|
*outInterlaced = gralloc4::getStandardInterlacedValue(interlaced);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultChromaSiting(uint32_t width, uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
ExtendableType* outChromaSiting) const {
|
|
return getDefault(width, height, format, layerCount, usage, gralloc4::MetadataType_ChromaSiting,
|
|
gralloc4::decodeChromaSiting, outChromaSiting);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultChromaSiting(uint32_t width, uint32_t height, PixelFormat format,
|
|
uint32_t layerCount, uint64_t usage,
|
|
ui::ChromaSiting* outChromaSiting) const {
|
|
if (!outChromaSiting) {
|
|
return BAD_VALUE;
|
|
}
|
|
ExtendableType chromaSiting;
|
|
status_t error =
|
|
getDefaultChromaSiting(width, height, format, layerCount, usage, &chromaSiting);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
if (!gralloc4::isStandardChromaSiting(chromaSiting)) {
|
|
return BAD_TYPE;
|
|
}
|
|
*outChromaSiting = gralloc4::getStandardChromaSitingValue(chromaSiting);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t Gralloc4Mapper::getDefaultPlaneLayouts(
|
|
uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount, uint64_t usage,
|
|
std::vector<ui::PlaneLayout>* outPlaneLayouts) const {
|
|
return getDefault(width, height, format, layerCount, usage, gralloc4::MetadataType_PlaneLayouts,
|
|
gralloc4::decodePlaneLayouts, outPlaneLayouts);
|
|
}
|
|
|
|
std::vector<MetadataTypeDescription> Gralloc4Mapper::listSupportedMetadataTypes() const {
|
|
hidl_vec<MetadataTypeDescription> descriptions;
|
|
Error error;
|
|
auto ret = mMapper->listSupportedMetadataTypes(
|
|
[&](const auto& tmpError, const auto& tmpDescriptions) {
|
|
error = tmpError;
|
|
descriptions = tmpDescriptions;
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("listSupportedMetadataType() failed with %d", error);
|
|
return {};
|
|
}
|
|
|
|
return static_cast<std::vector<MetadataTypeDescription>>(descriptions);
|
|
}
|
|
|
|
template <class T>
|
|
status_t Gralloc4Mapper::metadataDumpHelper(const BufferDump& bufferDump,
|
|
StandardMetadataType metadataType,
|
|
DecodeFunction<T> decodeFunction, T* outT) const {
|
|
const auto& metadataDump = bufferDump.metadataDump;
|
|
|
|
auto itr =
|
|
std::find_if(metadataDump.begin(), metadataDump.end(),
|
|
[&](const MetadataDump& tmpMetadataDump) {
|
|
if (!gralloc4::isStandardMetadataType(tmpMetadataDump.metadataType)) {
|
|
return false;
|
|
}
|
|
return metadataType ==
|
|
gralloc4::getStandardMetadataTypeValue(
|
|
tmpMetadataDump.metadataType);
|
|
});
|
|
if (itr == metadataDump.end()) {
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
return decodeFunction(itr->metadata, outT);
|
|
}
|
|
|
|
status_t Gralloc4Mapper::bufferDumpHelper(const BufferDump& bufferDump, std::ostringstream* outDump,
|
|
uint64_t* outAllocationSize, bool less) const {
|
|
uint64_t bufferId;
|
|
std::string name;
|
|
uint64_t width;
|
|
uint64_t height;
|
|
uint64_t layerCount;
|
|
ui::PixelFormat pixelFormatRequested;
|
|
uint32_t pixelFormatFourCC;
|
|
uint64_t pixelFormatModifier;
|
|
uint64_t usage;
|
|
AidlDataspace dataspace;
|
|
uint64_t allocationSize;
|
|
uint64_t protectedContent;
|
|
ExtendableType compression;
|
|
ExtendableType interlaced;
|
|
ExtendableType chromaSiting;
|
|
std::vector<ui::PlaneLayout> planeLayouts;
|
|
|
|
status_t error = metadataDumpHelper(bufferDump, StandardMetadataType::BUFFER_ID,
|
|
gralloc4::decodeBufferId, &bufferId);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::NAME, gralloc4::decodeName, &name);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::WIDTH, gralloc4::decodeWidth,
|
|
&width);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::HEIGHT, gralloc4::decodeHeight,
|
|
&height);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::LAYER_COUNT,
|
|
gralloc4::decodeLayerCount, &layerCount);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::PIXEL_FORMAT_REQUESTED,
|
|
gralloc4::decodePixelFormatRequested, &pixelFormatRequested);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::PIXEL_FORMAT_FOURCC,
|
|
gralloc4::decodePixelFormatFourCC, &pixelFormatFourCC);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::PIXEL_FORMAT_MODIFIER,
|
|
gralloc4::decodePixelFormatModifier, &pixelFormatModifier);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::USAGE, gralloc4::decodeUsage,
|
|
&usage);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::DATASPACE,
|
|
gralloc4::decodeDataspace, &dataspace);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::ALLOCATION_SIZE,
|
|
gralloc4::decodeAllocationSize, &allocationSize);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::PROTECTED_CONTENT,
|
|
gralloc4::decodeProtectedContent, &protectedContent);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::COMPRESSION,
|
|
gralloc4::decodeCompression, &compression);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::INTERLACED,
|
|
gralloc4::decodeInterlaced, &interlaced);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::CHROMA_SITING,
|
|
gralloc4::decodeChromaSiting, &chromaSiting);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
error = metadataDumpHelper(bufferDump, StandardMetadataType::PLANE_LAYOUTS,
|
|
gralloc4::decodePlaneLayouts, &planeLayouts);
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
|
|
if (outAllocationSize) {
|
|
*outAllocationSize = allocationSize;
|
|
}
|
|
double allocationSizeKiB = static_cast<double>(allocationSize) / 1024;
|
|
|
|
*outDump << "+ name:" << name << ", id:" << bufferId << ", size:" << allocationSizeKiB
|
|
<< "KiB, w/h:" << width << "x" << height << ", usage: 0x" << std::hex << usage
|
|
<< std::dec << ", req fmt:" << static_cast<int32_t>(pixelFormatRequested)
|
|
<< ", fourcc/mod:" << pixelFormatFourCC << "/" << pixelFormatModifier
|
|
<< ", dataspace: 0x" << std::hex << static_cast<uint32_t>(dataspace) << std::dec
|
|
<< ", compressed: ";
|
|
|
|
if (less) {
|
|
bool isCompressed = !gralloc4::isStandardCompression(compression) ||
|
|
(gralloc4::getStandardCompressionValue(compression) != ui::Compression::NONE);
|
|
*outDump << std::boolalpha << isCompressed << "\n";
|
|
} else {
|
|
*outDump << gralloc4::getCompressionName(compression) << "\n";
|
|
}
|
|
|
|
bool firstPlane = true;
|
|
for (const auto& planeLayout : planeLayouts) {
|
|
if (firstPlane) {
|
|
firstPlane = false;
|
|
*outDump << "\tplanes: ";
|
|
} else {
|
|
*outDump << "\t ";
|
|
}
|
|
|
|
for (size_t i = 0; i < planeLayout.components.size(); i++) {
|
|
const auto& planeLayoutComponent = planeLayout.components[i];
|
|
*outDump << gralloc4::getPlaneLayoutComponentTypeName(planeLayoutComponent.type);
|
|
if (i < planeLayout.components.size() - 1) {
|
|
*outDump << "/";
|
|
} else {
|
|
*outDump << ":\t";
|
|
}
|
|
}
|
|
*outDump << " w/h:" << planeLayout.widthInSamples << "x" << planeLayout.heightInSamples
|
|
<< ", stride:" << planeLayout.strideInBytes
|
|
<< " bytes, size:" << planeLayout.totalSizeInBytes;
|
|
if (!less) {
|
|
*outDump << ", inc:" << planeLayout.sampleIncrementInBits
|
|
<< " bits, subsampling w/h:" << planeLayout.horizontalSubsampling << "x"
|
|
<< planeLayout.verticalSubsampling;
|
|
}
|
|
*outDump << "\n";
|
|
}
|
|
|
|
if (!less) {
|
|
*outDump << "\tlayer cnt: " << layerCount << ", protected content: " << protectedContent
|
|
<< ", interlaced: " << gralloc4::getInterlacedName(interlaced)
|
|
<< ", chroma siting:" << gralloc4::getChromaSitingName(chromaSiting) << "\n";
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
std::string Gralloc4Mapper::dumpBuffer(buffer_handle_t bufferHandle, bool less) const {
|
|
auto buffer = const_cast<native_handle_t*>(bufferHandle);
|
|
|
|
BufferDump bufferDump;
|
|
Error error;
|
|
auto ret = mMapper->dumpBuffer(buffer, [&](const auto& tmpError, const auto& tmpBufferDump) {
|
|
error = tmpError;
|
|
bufferDump = tmpBufferDump;
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("dumpBuffer() failed with %d", error);
|
|
return "";
|
|
}
|
|
|
|
std::ostringstream stream;
|
|
stream.precision(2);
|
|
|
|
status_t err = bufferDumpHelper(bufferDump, &stream, nullptr, less);
|
|
if (err != NO_ERROR) {
|
|
ALOGE("bufferDumpHelper() failed with %d", err);
|
|
return "";
|
|
}
|
|
|
|
return stream.str();
|
|
}
|
|
|
|
std::string Gralloc4Mapper::dumpBuffers(bool less) const {
|
|
hidl_vec<BufferDump> bufferDumps;
|
|
Error error;
|
|
auto ret = mMapper->dumpBuffers([&](const auto& tmpError, const auto& tmpBufferDump) {
|
|
error = tmpError;
|
|
bufferDumps = tmpBufferDump;
|
|
});
|
|
|
|
if (!ret.isOk()) {
|
|
error = kTransactionError;
|
|
}
|
|
|
|
if (error != Error::NONE) {
|
|
ALOGE("dumpBuffer() failed with %d", error);
|
|
return "";
|
|
}
|
|
|
|
uint64_t totalAllocationSize = 0;
|
|
std::ostringstream stream;
|
|
stream.precision(2);
|
|
|
|
stream << "Imported gralloc buffers:\n";
|
|
|
|
for (const auto& bufferDump : bufferDumps) {
|
|
uint64_t allocationSize = 0;
|
|
status_t err = bufferDumpHelper(bufferDump, &stream, &allocationSize, less);
|
|
if (err != NO_ERROR) {
|
|
ALOGE("bufferDumpHelper() failed with %d", err);
|
|
return "";
|
|
}
|
|
totalAllocationSize += allocationSize;
|
|
}
|
|
|
|
double totalAllocationSizeKiB = static_cast<double>(totalAllocationSize) / 1024;
|
|
stream << "Total imported by gralloc: " << totalAllocationSizeKiB << "KiB\n";
|
|
return stream.str();
|
|
}
|
|
|
|
Gralloc4Allocator::Gralloc4Allocator(const Gralloc4Mapper& mapper) : mMapper(mapper) {
|
|
mAllocator = IAllocator::getService();
|
|
if (mAllocator == nullptr) {
|
|
ALOGW("allocator 4.x is not supported");
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool Gralloc4Allocator::isLoaded() const {
|
|
return mAllocator != nullptr;
|
|
}
|
|
|
|
std::string Gralloc4Allocator::dumpDebugInfo(bool less) const {
|
|
return mMapper.dumpBuffers(less);
|
|
}
|
|
|
|
status_t Gralloc4Allocator::allocate(std::string requestorName, uint32_t width, uint32_t height,
|
|
android::PixelFormat format, uint32_t layerCount,
|
|
uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
|
|
buffer_handle_t* outBufferHandles, bool importBuffers) const {
|
|
IMapper::BufferDescriptorInfo descriptorInfo;
|
|
sBufferDescriptorInfo(requestorName, width, height, format, layerCount, usage, &descriptorInfo);
|
|
|
|
BufferDescriptor descriptor;
|
|
status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
|
|
static_cast<void*>(&descriptor));
|
|
if (error != NO_ERROR) {
|
|
return error;
|
|
}
|
|
|
|
auto ret = mAllocator->allocate(descriptor, bufferCount,
|
|
[&](const auto& tmpError, const auto& tmpStride,
|
|
const auto& tmpBuffers) {
|
|
error = static_cast<status_t>(tmpError);
|
|
if (tmpError != Error::NONE) {
|
|
return;
|
|
}
|
|
|
|
if (importBuffers) {
|
|
for (uint32_t i = 0; i < bufferCount; i++) {
|
|
error = mMapper.importBuffer(tmpBuffers[i],
|
|
&outBufferHandles[i]);
|
|
if (error != NO_ERROR) {
|
|
for (uint32_t j = 0; j < i; j++) {
|
|
mMapper.freeBuffer(outBufferHandles[j]);
|
|
outBufferHandles[j] = nullptr;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
} else {
|
|
for (uint32_t i = 0; i < bufferCount; i++) {
|
|
outBufferHandles[i] = native_handle_clone(
|
|
tmpBuffers[i].getNativeHandle());
|
|
if (!outBufferHandles[i]) {
|
|
for (uint32_t j = 0; j < i; j++) {
|
|
auto buffer = const_cast<native_handle_t*>(
|
|
outBufferHandles[j]);
|
|
native_handle_close(buffer);
|
|
native_handle_delete(buffer);
|
|
outBufferHandles[j] = nullptr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*outStride = tmpStride;
|
|
});
|
|
|
|
// make sure the kernel driver sees BC_FREE_BUFFER and closes the fds now
|
|
hardware::IPCThreadState::self()->flushCommands();
|
|
|
|
return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
|
|
}
|
|
|
|
} // namespace android
|