Merge changes from topic "gralloc-mapper-cleanup"

* changes:
  graphics: move libVtsHalGraphicsMapperTestUtils
  graphics: make mapper default impl a header library
  graphics: add mapper HAL support library
  graphics: make allocator passthrough library header-only
This commit is contained in:
Chia-I Wu
2018-02-01 20:53:26 +00:00
committed by Gerrit Code Review
31 changed files with 1685 additions and 1751 deletions

View File

@@ -4,11 +4,8 @@ cc_library_shared {
vendor: true,
relative_install_path: "hw",
srcs: ["passthrough.cpp"],
static_libs: [
"android.hardware.graphics.allocator@2.0-passthrough",
],
header_libs: [
"android.hardware.graphics.allocator@2.0-hal",
"android.hardware.graphics.allocator@2.0-passthrough",
],
shared_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -20,6 +17,7 @@ cc_library_shared {
"liblog",
"libutils",
],
cflags: ["-DLOG_TAG=\"AllocatorHal\""],
}
cc_binary {

View File

@@ -39,11 +39,11 @@ using mapper::V2_0::Error;
namespace detail {
// AllocatorImpl implements IAllocator on top of AllocatorHal
template <typename IALLOCATOR, typename ALLOCATOR_HAL>
class AllocatorImpl : public IALLOCATOR {
// AllocatorImpl implements V2_*::IAllocator on top of V2_*::hal::AllocatorHal
template <typename Interface, typename Hal>
class AllocatorImpl : public Interface {
public:
bool init(std::unique_ptr<ALLOCATOR_HAL> hal) {
bool init(std::unique_ptr<Hal> hal) {
mHal = std::move(hal);
return true;
}
@@ -74,7 +74,7 @@ class AllocatorImpl : public IALLOCATOR {
}
protected:
std::unique_ptr<ALLOCATOR_HAL> mHal;
std::unique_ptr<Hal> mHal;
};
} // namespace detail

View File

@@ -1,12 +1,7 @@
cc_library_static {
cc_library_headers {
name: "android.hardware.graphics.allocator@2.0-passthrough",
defaults: ["hidl_defaults"],
vendor: true,
srcs: [
"Gralloc0Hal.cpp",
"Gralloc1Hal.cpp",
"GrallocLoader.cpp",
],
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
@@ -19,11 +14,11 @@ cc_library_static {
],
header_libs: [
"android.hardware.graphics.allocator@2.0-hal",
"libgrallocmapperincludes",
"android.hardware.graphics.mapper@2.0-passthrough_headers",
],
export_header_lib_headers: [
"android.hardware.graphics.allocator@2.0-hal",
"android.hardware.graphics.mapper@2.0-passthrough_headers",
],
export_include_dirs: ["include"],
cflags: ["-DLOG_TAG=\"AllocatorHal\""],
}

View File

@@ -1,141 +0,0 @@
/*
* Copyright 2016 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.
*/
#include <allocator-passthrough/2.0/Gralloc0Hal.h>
#include <string.h>
#include <GrallocBufferDescriptor.h>
#include <hardware/gralloc.h>
#include <log/log.h>
namespace android {
namespace hardware {
namespace graphics {
namespace allocator {
namespace V2_0 {
namespace passthrough {
using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
Gralloc0Hal::~Gralloc0Hal() {
if (mDevice) {
gralloc_close(mDevice);
}
}
bool Gralloc0Hal::initWithModule(const hw_module_t* module) {
int result = gralloc_open(module, &mDevice);
if (result) {
ALOGE("failed to open gralloc0 device: %s", strerror(-result));
mDevice = nullptr;
return false;
}
return true;
}
std::string Gralloc0Hal::dumpDebugInfo() {
char buf[4096] = {};
if (mDevice->dump) {
mDevice->dump(mDevice, buf, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';
}
return buf;
}
Error Gralloc0Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
uint32_t* outStride,
std::vector<const native_handle_t*>* outBuffers) {
mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
return Error::BAD_DESCRIPTOR;
}
Error error = Error::NONE;
uint32_t stride = 0;
std::vector<const native_handle_t*> buffers;
buffers.reserve(count);
// allocate the buffers
for (uint32_t i = 0; i < count; i++) {
const native_handle_t* tmpBuffer;
uint32_t tmpStride;
error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
if (error != Error::NONE) {
break;
}
buffers.push_back(tmpBuffer);
if (stride == 0) {
stride = tmpStride;
} else if (stride != tmpStride) {
// non-uniform strides
error = Error::UNSUPPORTED;
break;
}
}
if (error != Error::NONE) {
freeBuffers(buffers);
return error;
}
*outStride = stride;
*outBuffers = std::move(buffers);
return Error::NONE;
}
void Gralloc0Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
for (auto buffer : buffers) {
int result = mDevice->free(mDevice, buffer);
if (result != 0) {
ALOGE("failed to free buffer %p: %d", buffer, result);
}
}
}
Error Gralloc0Hal::allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
const native_handle_t** outBuffer, uint32_t* outStride) {
if (info.layerCount > 1 || (info.usage >> 32) != 0) {
return Error::BAD_VALUE;
}
const native_handle_t* buffer = nullptr;
int stride = 0;
int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
info.usage, &buffer, &stride);
switch (result) {
case 0:
*outBuffer = buffer;
*outStride = stride;
return Error::NONE;
case -EINVAL:
return Error::BAD_VALUE;
default:
return Error::NO_RESOURCES;
}
}
} // namespace passthrough
} // namespace V2_0
} // namespace allocator
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -1,323 +0,0 @@
/*
* Copyright 2016 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.
*/
#include <allocator-passthrough/2.0/Gralloc1Hal.h>
#include <string.h>
#include <GrallocBufferDescriptor.h>
#include <log/log.h>
namespace android {
namespace hardware {
namespace graphics {
namespace allocator {
namespace V2_0 {
namespace passthrough {
using android::hardware::graphics::common::V1_0::BufferUsage;
using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
Gralloc1Hal::~Gralloc1Hal() {
if (mDevice) {
gralloc1_close(mDevice);
}
}
bool Gralloc1Hal::initWithModule(const hw_module_t* module) {
int result = gralloc1_open(module, &mDevice);
if (result) {
ALOGE("failed to open gralloc1 device: %s", strerror(-result));
mDevice = nullptr;
return false;
}
initCapabilities();
if (!initDispatch()) {
gralloc1_close(mDevice);
mDevice = nullptr;
return false;
}
return true;
}
void Gralloc1Hal::initCapabilities() {
uint32_t count = 0;
mDevice->getCapabilities(mDevice, &count, nullptr);
std::vector<int32_t> capabilities(count);
mDevice->getCapabilities(mDevice, &count, capabilities.data());
capabilities.resize(count);
for (auto capability : capabilities) {
if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
mCapabilities.layeredBuffers = true;
break;
}
}
}
gralloc1_function_pointer_t Gralloc1Hal::getDispatchFunction(
gralloc1_function_descriptor_t desc) const {
auto pfn = mDevice->getFunction(mDevice, desc);
if (!pfn) {
ALOGE("failed to get gralloc1 function %d", desc);
return nullptr;
}
return pfn;
}
bool Gralloc1Hal::initDispatch() {
if (!initDispatchFunction(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
!initDispatchFunction(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
!initDispatchFunction(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
!initDispatchFunction(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
!initDispatchFunction(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
!initDispatchFunction(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
!initDispatchFunction(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
!initDispatchFunction(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
!initDispatchFunction(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
!initDispatchFunction(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
return false;
}
if (mCapabilities.layeredBuffers) {
if (!initDispatchFunction(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
return false;
}
}
return true;
}
std::string Gralloc1Hal::dumpDebugInfo() {
uint32_t len = 0;
mDispatch.dump(mDevice, &len, nullptr);
std::vector<char> buf(len + 1);
mDispatch.dump(mDevice, &len, buf.data());
buf.resize(len + 1);
buf[len] = '\0';
return buf.data();
}
Error Gralloc1Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
uint32_t* outStride,
std::vector<const native_handle_t*>* outBuffers) {
mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
return Error::BAD_DESCRIPTOR;
}
gralloc1_buffer_descriptor_t desc;
Error error = createDescriptor(descriptorInfo, &desc);
if (error != Error::NONE) {
return error;
}
uint32_t stride = 0;
std::vector<const native_handle_t*> buffers;
buffers.reserve(count);
// allocate the buffers
for (uint32_t i = 0; i < count; i++) {
const native_handle_t* tmpBuffer;
uint32_t tmpStride;
error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
if (error != Error::NONE) {
break;
}
buffers.push_back(tmpBuffer);
if (stride == 0) {
stride = tmpStride;
} else if (stride != tmpStride) {
// non-uniform strides
error = Error::UNSUPPORTED;
break;
}
}
mDispatch.destroyDescriptor(mDevice, desc);
if (error != Error::NONE) {
freeBuffers(buffers);
return error;
}
*outStride = stride;
*outBuffers = std::move(buffers);
return Error::NONE;
}
void Gralloc1Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
for (auto buffer : buffers) {
int32_t error = mDispatch.release(mDevice, buffer);
if (error != GRALLOC1_ERROR_NONE) {
ALOGE("failed to free buffer %p: %d", buffer, error);
}
}
}
Error Gralloc1Hal::toError(int32_t error) {
switch (error) {
case GRALLOC1_ERROR_NONE:
return Error::NONE;
case GRALLOC1_ERROR_BAD_DESCRIPTOR:
return Error::BAD_DESCRIPTOR;
case GRALLOC1_ERROR_BAD_HANDLE:
return Error::BAD_BUFFER;
case GRALLOC1_ERROR_BAD_VALUE:
return Error::BAD_VALUE;
case GRALLOC1_ERROR_NOT_SHARED:
return Error::NONE; // this is fine
case GRALLOC1_ERROR_NO_RESOURCES:
return Error::NO_RESOURCES;
case GRALLOC1_ERROR_UNDEFINED:
case GRALLOC1_ERROR_UNSUPPORTED:
default:
return Error::UNSUPPORTED;
}
}
uint64_t Gralloc1Hal::toProducerUsage(uint64_t usage) {
// this is potentially broken as we have no idea which private flags
// should be filtered out
uint64_t producerUsage =
usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
BufferUsage::GPU_DATA_BUFFER);
switch (usage & BufferUsage::CPU_WRITE_MASK) {
case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
break;
case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
break;
default:
break;
}
switch (usage & BufferUsage::CPU_READ_MASK) {
case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
break;
case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
break;
default:
break;
}
// BufferUsage::GPU_DATA_BUFFER is always filtered out
return producerUsage;
}
uint64_t Gralloc1Hal::toConsumerUsage(uint64_t usage) {
// this is potentially broken as we have no idea which private flags
// should be filtered out
uint64_t consumerUsage =
usage &
~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
switch (usage & BufferUsage::CPU_READ_MASK) {
case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
break;
case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
break;
default:
break;
}
// BufferUsage::SENSOR_DIRECT_DATA is always filtered out
if (usage & BufferUsage::GPU_DATA_BUFFER) {
consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
}
return consumerUsage;
}
Error Gralloc1Hal::createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
gralloc1_buffer_descriptor_t* outDescriptor) {
gralloc1_buffer_descriptor_t descriptor;
int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
if (error == GRALLOC1_ERROR_NONE) {
error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
}
if (error == GRALLOC1_ERROR_NONE) {
error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
}
if (error == GRALLOC1_ERROR_NONE) {
if (mCapabilities.layeredBuffers) {
error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
} else if (info.layerCount > 1) {
error = GRALLOC1_ERROR_UNSUPPORTED;
}
}
if (error == GRALLOC1_ERROR_NONE) {
error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
}
if (error == GRALLOC1_ERROR_NONE) {
error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
}
if (error == GRALLOC1_ERROR_NONE) {
*outDescriptor = descriptor;
} else {
mDispatch.destroyDescriptor(mDevice, descriptor);
}
return toError(error);
}
Error Gralloc1Hal::allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
const native_handle_t** outBuffer, uint32_t* outStride) {
const native_handle_t* buffer = nullptr;
int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
return toError(error);
}
uint32_t stride = 0;
error = mDispatch.getStride(mDevice, buffer, &stride);
if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
mDispatch.release(mDevice, buffer);
return toError(error);
}
*outBuffer = buffer;
*outStride = stride;
return Error::NONE;
}
} // namespace passthrough
} // namespace V2_0
} // namespace allocator
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -1,76 +0,0 @@
/*
* Copyright 2017 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.
*/
#include <allocator-passthrough/2.0/GrallocLoader.h>
#include <allocator-hal/2.0/Allocator.h>
#include <allocator-hal/2.0/AllocatorHal.h>
#include <allocator-passthrough/2.0/Gralloc0Hal.h>
#include <allocator-passthrough/2.0/Gralloc1Hal.h>
#include <hardware/gralloc.h>
#include <hardware/hardware.h>
#include <log/log.h>
namespace android {
namespace hardware {
namespace graphics {
namespace allocator {
namespace V2_0 {
namespace passthrough {
const hw_module_t* GrallocLoader::loadModule() {
const hw_module_t* module;
int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (error) {
ALOGE("failed to get gralloc module");
return nullptr;
}
return module;
}
int GrallocLoader::getModuleMajorApiVersion(const hw_module_t* module) {
return (module->module_api_version >> 8) & 0xff;
}
std::unique_ptr<hal::AllocatorHal> GrallocLoader::createHal(const hw_module_t* module) {
int major = getModuleMajorApiVersion(module);
switch (major) {
case 1: {
auto hal = std::make_unique<Gralloc1Hal>();
return hal->initWithModule(module) ? std::move(hal) : nullptr;
}
case 0: {
auto hal = std::make_unique<Gralloc0Hal>();
return hal->initWithModule(module) ? std::move(hal) : nullptr;
}
default:
ALOGE("unknown gralloc module major version %d", major);
return nullptr;
}
}
IAllocator* GrallocLoader::createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
auto allocator = std::make_unique<hal::Allocator>();
return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
}
} // namespace passthrough
} // namespace V2_0
} // namespace allocator
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -16,10 +16,16 @@
#pragma once
#include <allocator-hal/2.0/AllocatorHal.h>
#ifndef LOG_TAG
#warning "Gralloc0Hal.h included without LOG_TAG"
#endif
struct alloc_device_t;
struct hw_module_t;
#include <cstring> // for strerror
#include <allocator-hal/2.0/AllocatorHal.h>
#include <hardware/gralloc.h>
#include <log/log.h>
#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
namespace android {
namespace hardware {
@@ -28,28 +34,125 @@ namespace allocator {
namespace V2_0 {
namespace passthrough {
namespace detail {
using mapper::V2_0::BufferDescriptor;
using mapper::V2_0::Error;
using mapper::V2_0::passthrough::grallocDecodeBufferDescriptor;
class Gralloc0Hal : public virtual hal::AllocatorHal {
// Gralloc0HalImpl implements V2_*::hal::AllocatorHal on top of gralloc0
template <typename Hal>
class Gralloc0HalImpl : public Hal {
public:
~Gralloc0Hal();
bool initWithModule(const hw_module_t* module);
~Gralloc0HalImpl() {
if (mDevice) {
gralloc_close(mDevice);
}
}
std::string dumpDebugInfo() override;
bool initWithModule(const hw_module_t* module) {
int result = gralloc_open(module, &mDevice);
if (result) {
ALOGE("failed to open gralloc0 device: %s", strerror(-result));
mDevice = nullptr;
return false;
}
return true;
}
std::string dumpDebugInfo() override {
char buf[4096] = {};
if (mDevice->dump) {
mDevice->dump(mDevice, buf, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';
}
return buf;
}
Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
std::vector<const native_handle_t*>* outBuffers) override;
std::vector<const native_handle_t*>* outBuffers) override {
mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
return Error::BAD_DESCRIPTOR;
}
void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
Error error = Error::NONE;
uint32_t stride = 0;
std::vector<const native_handle_t*> buffers;
buffers.reserve(count);
// allocate the buffers
for (uint32_t i = 0; i < count; i++) {
const native_handle_t* tmpBuffer;
uint32_t tmpStride;
error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
if (error != Error::NONE) {
break;
}
buffers.push_back(tmpBuffer);
if (stride == 0) {
stride = tmpStride;
} else if (stride != tmpStride) {
// non-uniform strides
error = Error::UNSUPPORTED;
break;
}
}
if (error != Error::NONE) {
freeBuffers(buffers);
return error;
}
*outStride = stride;
*outBuffers = std::move(buffers);
return Error::NONE;
}
void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
for (auto buffer : buffers) {
int result = mDevice->free(mDevice, buffer);
if (result != 0) {
ALOGE("failed to free buffer %p: %d", buffer, result);
}
}
}
protected:
Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
const native_handle_t** outBuffer, uint32_t* outStride);
const native_handle_t** outBuffer, uint32_t* outStride) {
if (info.layerCount > 1 || (info.usage >> 32) != 0) {
return Error::BAD_VALUE;
}
const native_handle_t* buffer = nullptr;
int stride = 0;
int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
info.usage, &buffer, &stride);
switch (result) {
case 0:
*outBuffer = buffer;
*outStride = stride;
return Error::NONE;
case -EINVAL:
return Error::BAD_VALUE;
default:
return Error::NO_RESOURCES;
}
}
alloc_device_t* mDevice = nullptr;
};
} // namespace detail
using Gralloc0Hal = detail::Gralloc0HalImpl<hal::AllocatorHal>;
} // namespace passthrough
} // namespace V2_0
} // namespace allocator

View File

@@ -16,8 +16,16 @@
#pragma once
#ifndef LOG_TAG
#warning "Gralloc1Hal.h included without LOG_TAG"
#endif
#include <cstring> // for strerror
#include <allocator-hal/2.0/AllocatorHal.h>
#include <hardware/gralloc1.h>
#include <log/log.h>
#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
namespace android {
namespace hardware {
@@ -26,46 +34,302 @@ namespace allocator {
namespace V2_0 {
namespace passthrough {
namespace detail {
using common::V1_0::BufferUsage;
using mapper::V2_0::BufferDescriptor;
using mapper::V2_0::Error;
using mapper::V2_0::passthrough::grallocDecodeBufferDescriptor;
class Gralloc1Hal : public virtual hal::AllocatorHal {
// Gralloc1HalImpl implements V2_*::hal::AllocatorHal on top of gralloc1
template <typename Hal>
class Gralloc1HalImpl : public Hal {
public:
~Gralloc1Hal();
bool initWithModule(const hw_module_t* module);
~Gralloc1HalImpl() {
if (mDevice) {
gralloc1_close(mDevice);
}
}
std::string dumpDebugInfo() override;
bool initWithModule(const hw_module_t* module) {
int result = gralloc1_open(module, &mDevice);
if (result) {
ALOGE("failed to open gralloc1 device: %s", strerror(-result));
mDevice = nullptr;
return false;
}
initCapabilities();
if (!initDispatch()) {
gralloc1_close(mDevice);
mDevice = nullptr;
return false;
}
return true;
}
std::string dumpDebugInfo() override {
uint32_t len = 0;
mDispatch.dump(mDevice, &len, nullptr);
std::vector<char> buf(len + 1);
mDispatch.dump(mDevice, &len, buf.data());
buf.resize(len + 1);
buf[len] = '\0';
return buf.data();
}
Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
std::vector<const native_handle_t*>* outBuffers) override;
std::vector<const native_handle_t*>* outBuffers) override {
mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
return Error::BAD_DESCRIPTOR;
}
void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
gralloc1_buffer_descriptor_t desc;
Error error = createDescriptor(descriptorInfo, &desc);
if (error != Error::NONE) {
return error;
}
uint32_t stride = 0;
std::vector<const native_handle_t*> buffers;
buffers.reserve(count);
// allocate the buffers
for (uint32_t i = 0; i < count; i++) {
const native_handle_t* tmpBuffer;
uint32_t tmpStride;
error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
if (error != Error::NONE) {
break;
}
buffers.push_back(tmpBuffer);
if (stride == 0) {
stride = tmpStride;
} else if (stride != tmpStride) {
// non-uniform strides
error = Error::UNSUPPORTED;
break;
}
}
mDispatch.destroyDescriptor(mDevice, desc);
if (error != Error::NONE) {
freeBuffers(buffers);
return error;
}
*outStride = stride;
*outBuffers = std::move(buffers);
return Error::NONE;
}
void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
for (auto buffer : buffers) {
int32_t error = mDispatch.release(mDevice, buffer);
if (error != GRALLOC1_ERROR_NONE) {
ALOGE("failed to free buffer %p: %d", buffer, error);
}
}
}
protected:
virtual void initCapabilities() {
uint32_t count = 0;
mDevice->getCapabilities(mDevice, &count, nullptr);
std::vector<int32_t> capabilities(count);
mDevice->getCapabilities(mDevice, &count, capabilities.data());
capabilities.resize(count);
for (auto capability : capabilities) {
if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
mCapabilities.layeredBuffers = true;
break;
}
}
}
template <typename T>
bool initDispatchFunction(gralloc1_function_descriptor_t desc, T* outPfn) {
auto pfn = getDispatchFunction(desc);
bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
auto pfn = mDevice->getFunction(mDevice, desc);
if (pfn) {
*outPfn = reinterpret_cast<T>(pfn);
return true;
} else {
ALOGE("failed to get gralloc1 function %d", desc);
return false;
}
}
gralloc1_function_pointer_t getDispatchFunction(gralloc1_function_descriptor_t desc) const;
virtual void initCapabilities();
virtual bool initDispatch();
virtual bool initDispatch() {
if (!initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
!initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
!initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
!initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
!initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
!initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
!initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
!initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
!initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
!initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
return false;
}
static Error toError(int32_t error);
static uint64_t toProducerUsage(uint64_t usage);
static uint64_t toConsumerUsage(uint64_t usage);
if (mCapabilities.layeredBuffers) {
if (!initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
return false;
}
}
return true;
}
static Error toError(int32_t error) {
switch (error) {
case GRALLOC1_ERROR_NONE:
return Error::NONE;
case GRALLOC1_ERROR_BAD_DESCRIPTOR:
return Error::BAD_DESCRIPTOR;
case GRALLOC1_ERROR_BAD_HANDLE:
return Error::BAD_BUFFER;
case GRALLOC1_ERROR_BAD_VALUE:
return Error::BAD_VALUE;
case GRALLOC1_ERROR_NOT_SHARED:
return Error::NONE; // this is fine
case GRALLOC1_ERROR_NO_RESOURCES:
return Error::NO_RESOURCES;
case GRALLOC1_ERROR_UNDEFINED:
case GRALLOC1_ERROR_UNSUPPORTED:
default:
return Error::UNSUPPORTED;
}
}
static uint64_t toProducerUsage(uint64_t usage) {
// this is potentially broken as we have no idea which private flags
// should be filtered out
uint64_t producerUsage = usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
BufferUsage::CPU_WRITE_MASK |
BufferUsage::GPU_DATA_BUFFER);
switch (usage & BufferUsage::CPU_WRITE_MASK) {
case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
break;
case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
break;
default:
break;
}
switch (usage & BufferUsage::CPU_READ_MASK) {
case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
break;
case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
break;
default:
break;
}
// BufferUsage::GPU_DATA_BUFFER is always filtered out
return producerUsage;
}
static uint64_t toConsumerUsage(uint64_t usage) {
// this is potentially broken as we have no idea which private flags
// should be filtered out
uint64_t consumerUsage =
usage &
~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
switch (usage & BufferUsage::CPU_READ_MASK) {
case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
break;
case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
break;
default:
break;
}
// BufferUsage::SENSOR_DIRECT_DATA is always filtered out
if (usage & BufferUsage::GPU_DATA_BUFFER) {
consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
}
return consumerUsage;
}
Error createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
gralloc1_buffer_descriptor_t* outDescriptor);
gralloc1_buffer_descriptor_t* outDescriptor) {
gralloc1_buffer_descriptor_t descriptor;
int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
if (error == GRALLOC1_ERROR_NONE) {
error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
}
if (error == GRALLOC1_ERROR_NONE) {
error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
}
if (error == GRALLOC1_ERROR_NONE) {
if (mCapabilities.layeredBuffers) {
error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
} else if (info.layerCount > 1) {
error = GRALLOC1_ERROR_UNSUPPORTED;
}
}
if (error == GRALLOC1_ERROR_NONE) {
error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
}
if (error == GRALLOC1_ERROR_NONE) {
error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
}
if (error == GRALLOC1_ERROR_NONE) {
*outDescriptor = descriptor;
} else {
mDispatch.destroyDescriptor(mDevice, descriptor);
}
return toError(error);
}
Error allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
const native_handle_t** outBuffer, uint32_t* outStride);
const native_handle_t** outBuffer, uint32_t* outStride) {
const native_handle_t* buffer = nullptr;
int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
return toError(error);
}
uint32_t stride = 0;
error = mDispatch.getStride(mDevice, buffer, &stride);
if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
mDispatch.release(mDevice, buffer);
return toError(error);
}
*outBuffer = buffer;
*outStride = stride;
return Error::NONE;
}
gralloc1_device_t* mDevice = nullptr;
@@ -88,6 +352,10 @@ class Gralloc1Hal : public virtual hal::AllocatorHal {
} mDispatch = {};
};
} // namespace detail
using Gralloc1Hal = detail::Gralloc1HalImpl<hal::AllocatorHal>;
} // namespace passthrough
} // namespace V2_0
} // namespace allocator

View File

@@ -16,11 +16,18 @@
#pragma once
#ifndef LOG_TAG
#warning "GrallocLoader.h included without LOG_TAG"
#endif
#include <memory>
#include <allocator-hal/2.0/AllocatorHal.h>
struct hw_module_t;
#include <allocator-hal/2.0/Allocator.h>
#include <allocator-passthrough/2.0/Gralloc0Hal.h>
#include <allocator-passthrough/2.0/Gralloc1Hal.h>
#include <hardware/gralloc.h>
#include <hardware/hardware.h>
#include <log/log.h>
namespace android {
namespace hardware {
@@ -44,16 +51,45 @@ class GrallocLoader {
}
// load the gralloc module
static const hw_module_t* loadModule();
static const hw_module_t* loadModule() {
const hw_module_t* module;
int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (error) {
ALOGE("failed to get gralloc module");
return nullptr;
}
return module;
}
// return the major api version of the module
static int getModuleMajorApiVersion(const hw_module_t* module);
static int getModuleMajorApiVersion(const hw_module_t* module) {
return (module->module_api_version >> 8) & 0xff;
}
// create an AllocatorHal instance
static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module);
static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module) {
int major = getModuleMajorApiVersion(module);
switch (major) {
case 1: {
auto hal = std::make_unique<Gralloc1Hal>();
return hal->initWithModule(module) ? std::move(hal) : nullptr;
}
case 0: {
auto hal = std::make_unique<Gralloc0Hal>();
return hal->initWithModule(module) ? std::move(hal) : nullptr;
}
default:
ALOGE("unknown gralloc module major version %d", major);
return nullptr;
}
}
// create an IAllocator instance
static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal);
static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
auto allocator = std::make_unique<hal::Allocator>();
return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
}
};
} // namespace passthrough

View File

@@ -18,8 +18,10 @@ cc_library_shared {
defaults: ["hidl_defaults"],
vendor: true,
relative_install_path: "hw",
srcs: ["GrallocMapper.cpp", "Gralloc0Mapper.cpp", "Gralloc1Mapper.cpp"],
cppflags: ["-Wall", "-Wextra"],
srcs: ["passthrough.cpp"],
header_libs: [
"android.hardware.graphics.mapper@2.0-passthrough"
],
shared_libs: [
"android.hardware.graphics.mapper@2.0",
"libbase",
@@ -31,10 +33,5 @@ cc_library_shared {
"libsync",
"libutils",
],
}
cc_library_headers {
name: "libgrallocmapperincludes",
vendor: true,
export_include_dirs: ["."],
cflags: ["-DLOG_TAG=\"MapperHal\""],
}

View File

@@ -1,156 +0,0 @@
/*
* Copyright 2016 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 "Gralloc0Mapper"
#include "Gralloc0Mapper.h"
#include <log/log.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace implementation {
Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module)
: mModule(reinterpret_cast<const gralloc_module_t*>(module)),
mMinor(module->module_api_version & 0xff) {
mCapabilities.highUsageBits = false;
mCapabilities.layeredBuffers = false;
mCapabilities.unregisterImplyDelete = false;
}
Error Gralloc0Mapper::registerBuffer(buffer_handle_t bufferHandle) {
int result = mModule->registerBuffer(mModule, bufferHandle);
return result ? Error::BAD_BUFFER : Error::NONE;
}
void Gralloc0Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
mModule->unregisterBuffer(mModule, bufferHandle);
}
Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
void** outData) {
int result;
void* data = nullptr;
if (mMinor >= 3 && mModule->lockAsync) {
// Dup fenceFd as it is going to be owned by gralloc. Note that it is
// gralloc's responsibility to close it, even on locking errors.
if (fenceFd >= 0) {
fenceFd = dup(fenceFd);
if (fenceFd < 0) {
return Error::NO_RESOURCES;
}
}
result = mModule->lockAsync(mModule, bufferHandle, cpuUsage,
accessRegion.left, accessRegion.top,
accessRegion.width, accessRegion.height,
&data, fenceFd);
} else {
waitFenceFd(fenceFd, "Gralloc0Mapper::lock");
result = mModule->lock(mModule, bufferHandle, cpuUsage,
accessRegion.left, accessRegion.top,
accessRegion.width, accessRegion.height, &data);
}
if (result) {
return Error::BAD_VALUE;
} else {
*outData = data;
return Error::NONE;
}
}
Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
YCbCrLayout* outLayout) {
int result;
android_ycbcr ycbcr = {};
if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
// Dup fenceFd as it is going to be owned by gralloc. Note that it is
// gralloc's responsibility to close it, even on locking errors.
if (fenceFd >= 0) {
fenceFd = dup(fenceFd);
if (fenceFd < 0) {
return Error::NO_RESOURCES;
}
}
result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage,
accessRegion.left, accessRegion.top,
accessRegion.width,
accessRegion.height, &ycbcr, fenceFd);
} else {
waitFenceFd(fenceFd, "Gralloc0Mapper::lockYCbCr");
if (mModule->lock_ycbcr) {
result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage,
accessRegion.left, accessRegion.top,
accessRegion.width,
accessRegion.height, &ycbcr);
} else {
result = -EINVAL;
}
}
if (result) {
return Error::BAD_VALUE;
} else {
outLayout->y = ycbcr.y;
outLayout->cb = ycbcr.cb;
outLayout->cr = ycbcr.cr;
outLayout->yStride = ycbcr.ystride;
outLayout->cStride = ycbcr.cstride;
outLayout->chromaStep = ycbcr.chroma_step;
return Error::NONE;
}
}
Error Gralloc0Mapper::unlockBuffer(buffer_handle_t bufferHandle,
int* outFenceFd) {
int result;
int fenceFd = -1;
if (mMinor >= 3 && mModule->unlockAsync) {
result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
} else {
result = mModule->unlock(mModule, bufferHandle);
}
if (result) {
// we always own the fenceFd even when unlock failed
if (fenceFd >= 0) {
close(fenceFd);
}
return Error::BAD_VALUE;
} else {
*outFenceFd = fenceFd;
return Error::NONE;
}
}
} // namespace implementation
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -1,56 +0,0 @@
/*
* Copyright 2016 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.
*/
#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
#include "GrallocMapper.h"
#include <hardware/gralloc.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace implementation {
class Gralloc0Mapper : public GrallocMapper {
public:
Gralloc0Mapper(const hw_module_t* module);
private:
Error registerBuffer(buffer_handle_t bufferHandle) override;
void unregisterBuffer(buffer_handle_t bufferHandle) override;
Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
void** outData) override;
Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
YCbCrLayout* outLayout) override;
Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
const gralloc_module_t* mModule;
uint8_t mMinor;
};
} // namespace implementation
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H

View File

@@ -1,273 +0,0 @@
/*
* Copyright 2016 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 "Gralloc1Mapper"
#include "Gralloc1Mapper.h"
#include <vector>
#include <log/log.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace implementation {
using android::hardware::graphics::common::V1_0::BufferUsage;
Gralloc1Mapper::Gralloc1Mapper(const hw_module_t* module)
: mDevice(nullptr), mDispatch() {
int result = gralloc1_open(module, &mDevice);
if (result) {
LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
strerror(-result));
}
initCapabilities();
initDispatch();
}
Gralloc1Mapper::~Gralloc1Mapper() {
gralloc1_close(mDevice);
}
void Gralloc1Mapper::initCapabilities() {
mCapabilities.highUsageBits = true;
mCapabilities.layeredBuffers = false;
mCapabilities.unregisterImplyDelete = false;
uint32_t count = 0;
mDevice->getCapabilities(mDevice, &count, nullptr);
std::vector<int32_t> capabilities(count);
mDevice->getCapabilities(mDevice, &count, capabilities.data());
capabilities.resize(count);
for (auto capability : capabilities) {
switch (capability) {
case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
mCapabilities.layeredBuffers = true;
break;
case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
mCapabilities.unregisterImplyDelete = true;
break;
}
}
}
template <typename T>
void Gralloc1Mapper::initDispatch(gralloc1_function_descriptor_t desc,
T* outPfn) {
auto pfn = mDevice->getFunction(mDevice, desc);
if (!pfn) {
LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
}
*outPfn = reinterpret_cast<T>(pfn);
}
void Gralloc1Mapper::initDispatch() {
initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
&mDispatch.getNumFlexPlanes);
initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
}
Error Gralloc1Mapper::toError(int32_t error) {
switch (error) {
case GRALLOC1_ERROR_NONE:
return Error::NONE;
case GRALLOC1_ERROR_BAD_DESCRIPTOR:
return Error::BAD_DESCRIPTOR;
case GRALLOC1_ERROR_BAD_HANDLE:
return Error::BAD_BUFFER;
case GRALLOC1_ERROR_BAD_VALUE:
return Error::BAD_VALUE;
case GRALLOC1_ERROR_NOT_SHARED:
return Error::NONE; // this is fine
case GRALLOC1_ERROR_NO_RESOURCES:
return Error::NO_RESOURCES;
case GRALLOC1_ERROR_UNDEFINED:
case GRALLOC1_ERROR_UNSUPPORTED:
default:
return Error::UNSUPPORTED;
}
}
bool Gralloc1Mapper::toYCbCrLayout(const android_flex_layout& flex,
YCbCrLayout* outLayout) {
// must be YCbCr
if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
return false;
}
for (int i = 0; i < 3; i++) {
const auto& plane = flex.planes[i];
// must have 8-bit depth
if (plane.bits_per_component != 8 || plane.bits_used != 8) {
return false;
}
if (plane.component == FLEX_COMPONENT_Y) {
// Y must not be interleaved
if (plane.h_increment != 1) {
return false;
}
} else {
// Cb and Cr can be interleaved
if (plane.h_increment != 1 && plane.h_increment != 2) {
return false;
}
}
if (!plane.v_increment) {
return false;
}
}
if (flex.planes[0].component != FLEX_COMPONENT_Y ||
flex.planes[1].component != FLEX_COMPONENT_Cb ||
flex.planes[2].component != FLEX_COMPONENT_Cr) {
return false;
}
const auto& y = flex.planes[0];
const auto& cb = flex.planes[1];
const auto& cr = flex.planes[2];
if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
return false;
}
outLayout->y = y.top_left;
outLayout->cb = cb.top_left;
outLayout->cr = cr.top_left;
outLayout->yStride = y.v_increment;
outLayout->cStride = cb.v_increment;
outLayout->chromaStep = cb.h_increment;
return true;
}
gralloc1_rect_t Gralloc1Mapper::asGralloc1Rect(const IMapper::Rect& rect) {
return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
}
Error Gralloc1Mapper::registerBuffer(buffer_handle_t bufferHandle) {
return toError(mDispatch.retain(mDevice, bufferHandle));
}
void Gralloc1Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
mDispatch.release(mDevice, bufferHandle);
}
Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
void** outData) {
// Dup fenceFd as it is going to be owned by gralloc. Note that it is
// gralloc's responsibility to close it, even on locking errors.
if (fenceFd >= 0) {
fenceFd = dup(fenceFd);
if (fenceFd < 0) {
return Error::NO_RESOURCES;
}
}
const uint64_t consumerUsage =
cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
const auto accessRect = asGralloc1Rect(accessRegion);
void* data = nullptr;
int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage,
consumerUsage, &accessRect, &data, fenceFd);
if (error == GRALLOC1_ERROR_NONE) {
*outData = data;
}
return toError(error);
}
Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
YCbCrLayout* outLayout) {
// prepare flex layout
android_flex_layout flex = {};
int32_t error =
mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
if (error != GRALLOC1_ERROR_NONE) {
return toError(error);
}
std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
flex.planes = flexPlanes.data();
// Dup fenceFd as it is going to be owned by gralloc. Note that it is
// gralloc's responsibility to close it, even on locking errors.
if (fenceFd >= 0) {
fenceFd = dup(fenceFd);
if (fenceFd < 0) {
return Error::NO_RESOURCES;
}
}
const uint64_t consumerUsage =
cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
const auto accessRect = asGralloc1Rect(accessRegion);
error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage,
&accessRect, &flex, fenceFd);
if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
ALOGD("unable to convert android_flex_layout to YCbCrLayout");
// undo the lock
fenceFd = -1;
mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
if (fenceFd >= 0) {
close(fenceFd);
}
error = GRALLOC1_ERROR_BAD_HANDLE;
}
return toError(error);
}
Error Gralloc1Mapper::unlockBuffer(buffer_handle_t bufferHandle,
int* outFenceFd) {
int fenceFd = -1;
int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
if (error == GRALLOC1_ERROR_NONE) {
*outFenceFd = fenceFd;
} else if (fenceFd >= 0) {
// we always own the fenceFd even when unlock failed
close(fenceFd);
}
return toError(error);
}
} // namespace implementation
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -1,76 +0,0 @@
/*
* Copyright 2016 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.
*/
#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
#include "GrallocMapper.h"
#include <hardware/gralloc1.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace implementation {
class Gralloc1Mapper : public GrallocMapper {
public:
Gralloc1Mapper(const hw_module_t* module);
~Gralloc1Mapper();
private:
void initCapabilities();
template <typename T>
void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
void initDispatch();
static Error toError(int32_t error);
static bool toYCbCrLayout(const android_flex_layout& flex,
YCbCrLayout* outLayout);
static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
Error registerBuffer(buffer_handle_t bufferHandle) override;
void unregisterBuffer(buffer_handle_t bufferHandle) override;
Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
void** outData) override;
Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
YCbCrLayout* outLayout) override;
Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
gralloc1_device_t* mDevice;
struct {
GRALLOC1_PFN_RETAIN retain;
GRALLOC1_PFN_RELEASE release;
GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
GRALLOC1_PFN_LOCK lock;
GRALLOC1_PFN_LOCK_FLEX lockFlex;
GRALLOC1_PFN_UNLOCK unlock;
} mDispatch;
};
} // namespace implementation
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H

View File

@@ -1,321 +0,0 @@
/*
* Copyright 2016 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 "GrallocMapperPassthrough"
#include "GrallocMapper.h"
#include "Gralloc0Mapper.h"
#include "Gralloc1Mapper.h"
#include "GrallocBufferDescriptor.h"
#include <inttypes.h>
#include <log/log.h>
#include <sync/sync.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace implementation {
using android::hardware::graphics::common::V1_0::BufferUsage;
using android::hardware::graphics::common::V1_0::PixelFormat;
namespace {
class RegisteredHandlePool {
public:
bool add(buffer_handle_t bufferHandle) {
std::lock_guard<std::mutex> lock(mMutex);
return mHandles.insert(bufferHandle).second;
}
native_handle_t* pop(void* buffer) {
auto bufferHandle = static_cast<native_handle_t*>(buffer);
std::lock_guard<std::mutex> lock(mMutex);
return mHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
}
buffer_handle_t get(const void* buffer) {
auto bufferHandle = static_cast<buffer_handle_t>(buffer);
std::lock_guard<std::mutex> lock(mMutex);
return mHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
}
private:
std::mutex mMutex;
std::unordered_set<buffer_handle_t> mHandles;
};
// GraphicBufferMapper is expected to be valid (and leaked) during process
// termination. We need to make sure IMapper, and in turn, gRegisteredHandles
// are valid as well. Create the registered handle pool on the heap, and let
// it leak for simplicity.
//
// However, there is no way to make sure gralloc0/gralloc1 are valid. Any use
// of static/global object in gralloc0/gralloc1 that may have been destructed
// is potentially broken.
RegisteredHandlePool* gRegisteredHandles = new RegisteredHandlePool;
} // anonymous namespace
bool GrallocMapper::validateDescriptorInfo(
const BufferDescriptorInfo& descriptorInfo) const {
const uint64_t validUsageBits =
BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET |
BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET |
BufferUsage::PROTECTED | BufferUsage::COMPOSER_CURSOR |
BufferUsage::VIDEO_ENCODER | BufferUsage::CAMERA_OUTPUT |
BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
(mCapabilities.highUsageBits ? BufferUsage::VENDOR_MASK_HI
: static_cast<BufferUsage>(0));
if (!descriptorInfo.width || !descriptorInfo.height ||
!descriptorInfo.layerCount) {
return false;
}
if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
return false;
}
if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
return false;
}
if (descriptorInfo.usage & ~validUsageBits) {
// could not fail as gralloc may use the reserved bits...
ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
descriptorInfo.usage & ~validUsageBits);
}
return true;
}
Return<void> GrallocMapper::createDescriptor(
const BufferDescriptorInfo& descriptorInfo, createDescriptor_cb hidl_cb) {
if (validateDescriptorInfo(descriptorInfo)) {
hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo));
} else {
hidl_cb(Error::BAD_VALUE, BufferDescriptor());
}
return Void();
}
Return<void> GrallocMapper::importBuffer(const hidl_handle& rawHandle,
importBuffer_cb hidl_cb) {
// because of passthrough HALs, we must not generate an error when
// rawHandle has been imported
if (!rawHandle.getNativeHandle()) {
hidl_cb(Error::BAD_BUFFER, nullptr);
return Void();
}
native_handle_t* bufferHandle =
native_handle_clone(rawHandle.getNativeHandle());
if (!bufferHandle) {
hidl_cb(Error::NO_RESOURCES, nullptr);
return Void();
}
Error error = registerBuffer(bufferHandle);
if (error != Error::NONE) {
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
hidl_cb(error, nullptr);
return Void();
}
// The newly cloned handle is already registered? This can only happen
// when a handle previously registered was native_handle_delete'd instead
// of freeBuffer'd.
if (!gRegisteredHandles->add(bufferHandle)) {
ALOGE("handle %p has already been imported; potential fd leaking",
bufferHandle);
unregisterBuffer(bufferHandle);
if (!mCapabilities.unregisterImplyDelete) {
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
}
hidl_cb(Error::NO_RESOURCES, nullptr);
return Void();
}
hidl_cb(Error::NONE, bufferHandle);
return Void();
}
Return<Error> GrallocMapper::freeBuffer(void* buffer) {
native_handle_t* bufferHandle = gRegisteredHandles->pop(buffer);
if (!bufferHandle) {
return Error::BAD_BUFFER;
}
unregisterBuffer(bufferHandle);
if (!mCapabilities.unregisterImplyDelete) {
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
}
return Error::NONE;
}
void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) {
if (fenceFd < 0) {
return;
}
const int warningTimeout = 3500;
const int error = sync_wait(fenceFd, warningTimeout);
if (error < 0 && errno == ETIME) {
ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd,
warningTimeout);
sync_wait(fenceFd, -1);
}
}
bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle,
int* outFenceFd) {
auto handle = fenceHandle.getNativeHandle();
if (handle && handle->numFds > 1) {
ALOGE("invalid fence handle with %d fds", handle->numFds);
return false;
}
*outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
return true;
}
hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) {
native_handle_t* handle = nullptr;
if (fenceFd >= 0) {
handle = native_handle_init(handleStorage, 1, 0);
handle->data[0] = fenceFd;
}
return hidl_handle(handle);
}
Return<void> GrallocMapper::lock(void* buffer, uint64_t cpuUsage,
const IMapper::Rect& accessRegion,
const hidl_handle& acquireFence,
lock_cb hidl_cb) {
buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, nullptr);
return Void();
}
int fenceFd;
if (!getFenceFd(acquireFence, &fenceFd)) {
hidl_cb(Error::BAD_VALUE, nullptr);
return Void();
}
void* data = nullptr;
Error error =
lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
hidl_cb(error, data);
return Void();
}
Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage,
const IMapper::Rect& accessRegion,
const hidl_handle& acquireFence,
lockYCbCr_cb hidl_cb) {
YCbCrLayout layout = {};
buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, layout);
return Void();
}
int fenceFd;
if (!getFenceFd(acquireFence, &fenceFd)) {
hidl_cb(Error::BAD_VALUE, layout);
return Void();
}
Error error =
lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout);
hidl_cb(error, layout);
return Void();
}
Return<void> GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) {
buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, nullptr);
return Void();
}
int fenceFd;
Error error = unlockBuffer(bufferHandle, &fenceFd);
if (error == Error::NONE) {
NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
if (fenceFd >= 0) {
close(fenceFd);
}
} else {
hidl_cb(error, nullptr);
}
return Void();
}
IMapper* HIDL_FETCH_IMapper(const char* /* name */) {
const hw_module_t* module = nullptr;
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (err) {
ALOGE("failed to get gralloc module");
return nullptr;
}
uint8_t major = (module->module_api_version >> 8) & 0xff;
switch (major) {
case 1:
return new Gralloc1Mapper(module);
case 0:
return new Gralloc0Mapper(module);
default:
ALOGE("unknown gralloc module major version %d", major);
return nullptr;
}
}
} // namespace implementation
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -1,96 +0,0 @@
/*
* Copyright 2016 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.
*/
#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <cutils/native_handle.h>
#include <mutex>
#include <unordered_set>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace implementation {
class GrallocMapper : public IMapper {
public:
// IMapper interface
Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
createDescriptor_cb hidl_cb) override;
Return<void> importBuffer(const hidl_handle& rawHandle,
importBuffer_cb hidl_cb) override;
Return<Error> freeBuffer(void* buffer) override;
Return<void> lock(void* buffer, uint64_t cpuUsage,
const IMapper::Rect& accessRegion,
const hidl_handle& acquireFence,
lock_cb hidl_cb) override;
Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage,
const IMapper::Rect& accessRegion,
const hidl_handle& acquireFence,
lockYCbCr_cb hidl_cb) override;
Return<void> unlock(void* buffer, unlock_cb hidl_cb) override;
protected:
static void waitFenceFd(int fenceFd, const char* logname);
struct {
bool highUsageBits;
bool layeredBuffers;
bool unregisterImplyDelete;
} mCapabilities = {};
private:
virtual bool validateDescriptorInfo(
const BufferDescriptorInfo& descriptorInfo) const;
// Register a buffer. The handle is already cloned by the caller.
virtual Error registerBuffer(buffer_handle_t bufferHandle) = 0;
// Unregister a buffer. The handle is closed and deleted by the
// callee if and only if mCapabilities.unregisterImplyDelete is set.
virtual void unregisterBuffer(buffer_handle_t bufferHandle) = 0;
// Lock a buffer. The fence is owned by the caller.
virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
void** outData) = 0;
virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int fenceFd,
YCbCrLayout* outLayout) = 0;
// Unlock a buffer. The returned fence is owned by the caller.
virtual Error unlockBuffer(buffer_handle_t bufferHandle,
int* outFenceFd) = 0;
static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd);
static hidl_handle getFenceHandle(int fenceFd, char* handleStorage);
};
extern "C" IMapper* HIDL_FETCH_IMapper(const char* name);
} // namespace implementation
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2016 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.
*/
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <mapper-passthrough/2.0/GrallocLoader.h>
using android::hardware::graphics::mapper::V2_0::IMapper;
using android::hardware::graphics::mapper::V2_0::passthrough::GrallocLoader;
extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
return GrallocLoader::load();
}

View File

@@ -0,0 +1,4 @@
# Graphics team
jessehall@google.com
olv@google.com
stoza@google.com

View File

@@ -0,0 +1,27 @@
//
// Copyright (C) 2018 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.
cc_library_headers {
name: "android.hardware.graphics.mapper@2.0-hal",
defaults: ["hidl_defaults"],
vendor: true,
shared_libs: [
"android.hardware.graphics.mapper@2.0",
],
export_shared_lib_headers: [
"android.hardware.graphics.mapper@2.0",
],
export_include_dirs: ["include"],
}

View File

@@ -0,0 +1,210 @@
/*
* Copyright 2018 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.
*/
#pragma once
#ifndef LOG_TAG
#warning "Mapper.h included without LOG_TAG"
#endif
#include <memory>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <log/log.h>
#include <mapper-hal/2.0/MapperHal.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace hal {
namespace detail {
// MapperImpl implements V2_*::IMapper on top of V2_*::hal::MapperHal
template <typename Interface, typename Hal>
class MapperImpl : public Interface {
public:
bool init(std::unique_ptr<Hal> hal) {
mHal = std::move(hal);
return true;
}
// IMapper 2.0 interface
Return<void> createDescriptor(const V2_0::IMapper::BufferDescriptorInfo& descriptorInfo,
IMapper::createDescriptor_cb hidl_cb) override {
BufferDescriptor descriptor;
Error error = mHal->createDescriptor(descriptorInfo, &descriptor);
hidl_cb(error, descriptor);
return Void();
}
Return<void> importBuffer(const hidl_handle& rawHandle,
IMapper::importBuffer_cb hidl_cb) override {
if (!rawHandle.getNativeHandle()) {
hidl_cb(Error::BAD_BUFFER, nullptr);
return Void();
}
native_handle_t* bufferHandle = nullptr;
Error error = mHal->importBuffer(rawHandle.getNativeHandle(), &bufferHandle);
if (error != Error::NONE) {
hidl_cb(error, nullptr);
return Void();
}
void* buffer = addImportedBuffer(bufferHandle);
if (!buffer) {
mHal->freeBuffer(bufferHandle);
hidl_cb(Error::NO_RESOURCES, nullptr);
return Void();
}
hidl_cb(error, buffer);
return Void();
}
Return<Error> freeBuffer(void* buffer) override {
native_handle_t* bufferHandle = removeImportedBuffer(buffer);
if (!bufferHandle) {
return Error::BAD_BUFFER;
}
return mHal->freeBuffer(bufferHandle);
}
Return<void> lock(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
const hidl_handle& acquireFence, IMapper::lock_cb hidl_cb) override {
const native_handle_t* bufferHandle = getImportedBuffer(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, nullptr);
return Void();
}
base::unique_fd fenceFd;
Error error = getFenceFd(acquireFence, &fenceFd);
if (error != Error::NONE) {
hidl_cb(error, nullptr);
return Void();
}
void* data = nullptr;
error = mHal->lock(bufferHandle, cpuUsage, accessRegion, std::move(fenceFd), &data);
hidl_cb(error, data);
return Void();
}
Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
const hidl_handle& acquireFence,
IMapper::lockYCbCr_cb hidl_cb) override {
const native_handle_t* bufferHandle = getImportedBuffer(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, YCbCrLayout{});
return Void();
}
base::unique_fd fenceFd;
Error error = getFenceFd(acquireFence, &fenceFd);
if (error != Error::NONE) {
hidl_cb(error, YCbCrLayout{});
return Void();
}
YCbCrLayout layout{};
error = mHal->lockYCbCr(bufferHandle, cpuUsage, accessRegion, std::move(fenceFd), &layout);
hidl_cb(error, layout);
return Void();
}
Return<void> unlock(void* buffer, IMapper::unlock_cb hidl_cb) override {
const native_handle_t* bufferHandle = getImportedBuffer(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, nullptr);
return Void();
}
base::unique_fd fenceFd;
Error error = mHal->unlock(bufferHandle, &fenceFd);
if (error != Error::NONE) {
hidl_cb(error, nullptr);
return Void();
}
NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
return Void();
}
protected:
// these functions can be overriden to do true imported buffer management
virtual void* addImportedBuffer(native_handle_t* bufferHandle) {
return static_cast<void*>(bufferHandle);
}
virtual native_handle_t* removeImportedBuffer(void* buffer) {
return static_cast<native_handle_t*>(buffer);
}
virtual const native_handle_t* getImportedBuffer(void* buffer) const {
return static_cast<const native_handle_t*>(buffer);
}
// convert fenceFd to or from hidl_handle
static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) {
auto handle = fenceHandle.getNativeHandle();
if (handle && handle->numFds > 1) {
ALOGE("invalid fence handle with %d fds", handle->numFds);
return Error::BAD_VALUE;
}
int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
if (fenceFd >= 0) {
fenceFd = dup(fenceFd);
if (fenceFd < 0) {
return Error::NO_RESOURCES;
}
}
outFenceFd->reset(fenceFd);
return Error::NONE;
}
static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) {
native_handle_t* handle = nullptr;
if (fenceFd >= 0) {
handle = native_handle_init(handleStorage, 1, 0);
handle->data[0] = fenceFd;
}
return hidl_handle(handle);
}
std::unique_ptr<Hal> mHal;
};
} // namespace detail
using Mapper = detail::MapperImpl<IMapper, MapperHal>;
} // namespace hal
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2018 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.
*/
#pragma once
#include <android-base/unique_fd.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace hal {
class MapperHal {
public:
virtual ~MapperHal() = default;
// create a BufferDescriptor
virtual Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
BufferDescriptor* outDescriptor) = 0;
// import a raw handle owned by the caller
virtual Error importBuffer(const native_handle_t* rawHandle,
native_handle_t** outBufferHandle) = 0;
// free an imported buffer handle
virtual Error freeBuffer(native_handle_t* bufferHandle) = 0;
// lock a buffer
virtual Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
void** outData) = 0;
// lock a YCbCr buffer
virtual Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
YCbCrLayout* outLayout) = 0;
// unlock a buffer
virtual Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) = 0;
};
} // namespace hal
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,43 @@
//
// Copyright (C) 2016 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.
cc_library_headers {
name: "android.hardware.graphics.mapper@2.0-passthrough",
defaults: ["hidl_defaults"],
vendor: true,
shared_libs: [
"android.hardware.graphics.mapper@2.0",
"libhardware",
"libsync",
],
export_shared_lib_headers: [
"android.hardware.graphics.mapper@2.0",
"libhardware",
"libsync",
],
header_libs: [
"android.hardware.graphics.mapper@2.0-hal",
],
export_header_lib_headers: [
"android.hardware.graphics.mapper@2.0-hal",
],
export_include_dirs: ["include"],
}
cc_library_headers {
name: "android.hardware.graphics.mapper@2.0-passthrough_headers",
vendor: true,
export_include_dirs: ["include"],
}

View File

@@ -0,0 +1,214 @@
/*
* Copyright 2016 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.
*/
#pragma once
#ifndef LOG_TAG
#warning "Gralloc0Hal.h included without LOG_TAG"
#endif
#include <inttypes.h>
#include <hardware/gralloc.h>
#include <log/log.h>
#include <mapper-hal/2.0/MapperHal.h>
#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
#include <sync/sync.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace passthrough {
namespace detail {
using common::V1_0::BufferUsage;
// Gralloc0HalImpl implements V2_*::hal::MapperHal on top of gralloc0
template <typename Hal>
class Gralloc0HalImpl : public Hal {
public:
bool initWithModule(const hw_module_t* module) {
mModule = reinterpret_cast<const gralloc_module_t*>(module);
mMinor = module->module_api_version & 0xff;
return true;
}
Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
BufferDescriptor* outDescriptor) override {
if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
return Error::BAD_VALUE;
}
if (descriptorInfo.layerCount != 1) {
return Error::UNSUPPORTED;
}
if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
return Error::BAD_VALUE;
}
const uint64_t validUsageBits = getValidBufferUsageMask();
if (descriptorInfo.usage & ~validUsageBits) {
ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
descriptorInfo.usage & ~validUsageBits);
}
*outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
return Error::NONE;
}
Error importBuffer(const native_handle_t* rawHandle,
native_handle_t** outBufferHandle) override {
native_handle_t* bufferHandle = native_handle_clone(rawHandle);
if (!bufferHandle) {
return Error::NO_RESOURCES;
}
if (mModule->registerBuffer(mModule, bufferHandle)) {
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
return Error::BAD_BUFFER;
}
*outBufferHandle = bufferHandle;
return Error::NONE;
}
Error freeBuffer(native_handle_t* bufferHandle) override {
if (mModule->unregisterBuffer(mModule, bufferHandle)) {
return Error::BAD_BUFFER;
}
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
return Error::NONE;
}
Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
void** outData) override {
int result;
void* data = nullptr;
if (mMinor >= 3 && mModule->lockAsync) {
result = mModule->lockAsync(mModule, bufferHandle, cpuUsage, accessRegion.left,
accessRegion.top, accessRegion.width, accessRegion.height,
&data, fenceFd.release());
} else {
waitFenceFd(fenceFd, "Gralloc0Hal::lock");
result =
mModule->lock(mModule, bufferHandle, cpuUsage, accessRegion.left, accessRegion.top,
accessRegion.width, accessRegion.height, &data);
}
if (result) {
return Error::BAD_VALUE;
}
*outData = data;
return Error::NONE;
}
Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
YCbCrLayout* outLayout) override {
int result;
android_ycbcr ycbcr = {};
if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage, accessRegion.left,
accessRegion.top, accessRegion.width,
accessRegion.height, &ycbcr, fenceFd.release());
} else {
waitFenceFd(fenceFd, "Gralloc0Hal::lockYCbCr");
if (mModule->lock_ycbcr) {
result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage, accessRegion.left,
accessRegion.top, accessRegion.width,
accessRegion.height, &ycbcr);
} else {
result = -EINVAL;
}
}
if (result) {
return Error::BAD_VALUE;
}
outLayout->y = ycbcr.y;
outLayout->cb = ycbcr.cb;
outLayout->cr = ycbcr.cr;
outLayout->yStride = ycbcr.ystride;
outLayout->cStride = ycbcr.cstride;
outLayout->chromaStep = ycbcr.chroma_step;
return Error::NONE;
}
Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
int result;
int fenceFd = -1;
if (mMinor >= 3 && mModule->unlockAsync) {
result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
} else {
result = mModule->unlock(mModule, bufferHandle);
}
// we always own the fenceFd even when unlock failed
outFenceFd->reset(fenceFd);
return result ? Error::BAD_VALUE : Error::NONE;
}
protected:
virtual uint64_t getValidBufferUsageMask() const {
return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK;
}
static void waitFenceFd(const base::unique_fd& fenceFd, const char* logname) {
if (fenceFd < 0) {
return;
}
const int warningTimeout = 3500;
const int error = sync_wait(fenceFd, warningTimeout);
if (error < 0 && errno == ETIME) {
ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd.get(), warningTimeout);
sync_wait(fenceFd, -1);
}
}
const gralloc_module_t* mModule = nullptr;
uint8_t mMinor = 0;
};
} // namespace detail
using Gralloc0Hal = detail::Gralloc0HalImpl<hal::MapperHal>;
} // namespace passthrough
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,338 @@
/*
* Copyright 2016 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.
*/
#pragma once
#ifndef LOG_TAG
#warning "Gralloc1Hal.h included without LOG_TAG"
#endif
#include <inttypes.h>
#include <vector>
#include <hardware/gralloc1.h>
#include <log/log.h>
#include <mapper-hal/2.0/MapperHal.h>
#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace passthrough {
namespace detail {
using common::V1_0::BufferUsage;
// Gralloc1HalImpl implements V2_*::hal::MapperHal on top of gralloc1
template <typename Hal>
class Gralloc1HalImpl : public Hal {
public:
~Gralloc1HalImpl() {
if (mDevice) {
gralloc1_close(mDevice);
}
}
bool initWithModule(const hw_module_t* module) {
int result = gralloc1_open(module, &mDevice);
if (result) {
ALOGE("failed to open gralloc1 device: %s", strerror(-result));
mDevice = nullptr;
return false;
}
initCapabilities();
if (!initDispatch()) {
gralloc1_close(mDevice);
mDevice = nullptr;
return false;
}
return true;
}
Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
BufferDescriptor* outDescriptor) override {
if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
return Error::BAD_VALUE;
}
if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount != 1) {
return Error::UNSUPPORTED;
}
if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
return Error::BAD_VALUE;
}
const uint64_t validUsageBits = getValidBufferUsageMask();
if (descriptorInfo.usage & ~validUsageBits) {
ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
descriptorInfo.usage & ~validUsageBits);
}
*outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
return Error::NONE;
}
Error importBuffer(const native_handle_t* rawHandle,
native_handle_t** outBufferHandle) override {
native_handle_t* bufferHandle = native_handle_clone(rawHandle);
if (!bufferHandle) {
return Error::NO_RESOURCES;
}
int32_t error = mDispatch.retain(mDevice, bufferHandle);
if (error != GRALLOC1_ERROR_NONE) {
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
return toError(error);
}
*outBufferHandle = bufferHandle;
return Error::NONE;
}
Error freeBuffer(native_handle_t* bufferHandle) override {
int32_t error = mDispatch.release(mDevice, bufferHandle);
if (error == GRALLOC1_ERROR_NONE && !mCapabilities.releaseImplyDelete) {
native_handle_close(bufferHandle);
native_handle_delete(bufferHandle);
}
return toError(error);
}
Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
void** outData) override {
const uint64_t consumerUsage =
cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
const auto accessRect = asGralloc1Rect(accessRegion);
void* data = nullptr;
int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
&data, fenceFd.release());
if (error == GRALLOC1_ERROR_NONE) {
*outData = data;
}
return toError(error);
}
Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
YCbCrLayout* outLayout) override {
// prepare flex layout
android_flex_layout flex = {};
int32_t error = mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
if (error != GRALLOC1_ERROR_NONE) {
return toError(error);
}
std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
flex.planes = flexPlanes.data();
const uint64_t consumerUsage =
cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
const auto accessRect = asGralloc1Rect(accessRegion);
error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
&flex, fenceFd.release());
if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
ALOGD("unable to convert android_flex_layout to YCbCrLayout");
// undo the lock
unlock(bufferHandle, &fenceFd);
error = GRALLOC1_ERROR_BAD_HANDLE;
}
return toError(error);
}
Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
int fenceFd = -1;
int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
// we always own the fenceFd even when unlock failed
outFenceFd->reset(fenceFd);
return toError(error);
}
protected:
virtual void initCapabilities() {
uint32_t count = 0;
mDevice->getCapabilities(mDevice, &count, nullptr);
std::vector<int32_t> capabilities(count);
mDevice->getCapabilities(mDevice, &count, capabilities.data());
capabilities.resize(count);
for (auto capability : capabilities) {
switch (capability) {
case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
mCapabilities.layeredBuffers = true;
break;
case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
mCapabilities.releaseImplyDelete = true;
break;
}
}
}
template <typename T>
bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
auto pfn = mDevice->getFunction(mDevice, desc);
if (pfn) {
*outPfn = reinterpret_cast<T>(pfn);
return true;
} else {
ALOGE("failed to get gralloc1 function %d", desc);
return false;
}
}
virtual bool initDispatch() {
if (!initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain) ||
!initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release) ||
!initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES, &mDispatch.getNumFlexPlanes) ||
!initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock) ||
!initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex) ||
!initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock)) {
return false;
}
return true;
}
virtual uint64_t getValidBufferUsageMask() const {
return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
BufferUsage::VENDOR_MASK_HI;
}
static Error toError(int32_t error) {
switch (error) {
case GRALLOC1_ERROR_NONE:
return Error::NONE;
case GRALLOC1_ERROR_BAD_DESCRIPTOR:
return Error::BAD_DESCRIPTOR;
case GRALLOC1_ERROR_BAD_HANDLE:
return Error::BAD_BUFFER;
case GRALLOC1_ERROR_BAD_VALUE:
return Error::BAD_VALUE;
case GRALLOC1_ERROR_NOT_SHARED:
return Error::NONE; // this is fine
case GRALLOC1_ERROR_NO_RESOURCES:
return Error::NO_RESOURCES;
case GRALLOC1_ERROR_UNDEFINED:
case GRALLOC1_ERROR_UNSUPPORTED:
default:
return Error::UNSUPPORTED;
}
}
static bool toYCbCrLayout(const android_flex_layout& flex, YCbCrLayout* outLayout) {
// must be YCbCr
if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
return false;
}
for (int i = 0; i < 3; i++) {
const auto& plane = flex.planes[i];
// must have 8-bit depth
if (plane.bits_per_component != 8 || plane.bits_used != 8) {
return false;
}
if (plane.component == FLEX_COMPONENT_Y) {
// Y must not be interleaved
if (plane.h_increment != 1) {
return false;
}
} else {
// Cb and Cr can be interleaved
if (plane.h_increment != 1 && plane.h_increment != 2) {
return false;
}
}
if (!plane.v_increment) {
return false;
}
}
if (flex.planes[0].component != FLEX_COMPONENT_Y ||
flex.planes[1].component != FLEX_COMPONENT_Cb ||
flex.planes[2].component != FLEX_COMPONENT_Cr) {
return false;
}
const auto& y = flex.planes[0];
const auto& cb = flex.planes[1];
const auto& cr = flex.planes[2];
if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
return false;
}
outLayout->y = y.top_left;
outLayout->cb = cb.top_left;
outLayout->cr = cr.top_left;
outLayout->yStride = y.v_increment;
outLayout->cStride = cb.v_increment;
outLayout->chromaStep = cb.h_increment;
return true;
}
static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect) {
return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
}
gralloc1_device_t* mDevice = nullptr;
struct {
bool layeredBuffers;
bool releaseImplyDelete;
} mCapabilities = {};
struct {
GRALLOC1_PFN_RETAIN retain;
GRALLOC1_PFN_RELEASE release;
GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
GRALLOC1_PFN_LOCK lock;
GRALLOC1_PFN_LOCK_FLEX lockFlex;
GRALLOC1_PFN_UNLOCK unlock;
} mDispatch = {};
};
} // namespace detail
using Gralloc1Hal = detail::Gralloc1HalImpl<hal::MapperHal>;
} // namespace passthrough
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -14,8 +14,7 @@
* limitations under the License.
*/
#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
#pragma once
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
@@ -24,7 +23,7 @@ namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace implementation {
namespace passthrough {
using android::hardware::graphics::common::V1_0::PixelFormat;
@@ -50,9 +49,8 @@ inline BufferDescriptor grallocEncodeBufferDescriptor(
return descriptor;
}
inline bool grallocDecodeBufferDescriptor(
const BufferDescriptor& descriptor,
IMapper::BufferDescriptorInfo* outDescriptorInfo) {
inline bool grallocDecodeBufferDescriptor(const BufferDescriptor& descriptor,
IMapper::BufferDescriptorInfo* outDescriptorInfo) {
if (descriptor.size() != grallocBufferDescriptorSize ||
descriptor[0] != grallocBufferDescriptorMagicVersion) {
return false;
@@ -69,11 +67,9 @@ inline bool grallocDecodeBufferDescriptor(
return true;
}
} // namespace implementation
} // namespace passthrough
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android
#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H

View File

@@ -0,0 +1,161 @@
/*
* Copyright 2017 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.
*/
#pragma once
#ifndef LOG_TAG
#warning "GrallocLoader.h included without LOG_TAG"
#endif
#include <memory>
#include <mutex>
#include <unordered_set>
#include <hardware/gralloc.h>
#include <hardware/hardware.h>
#include <log/log.h>
#include <mapper-hal/2.0/Mapper.h>
#include <mapper-passthrough/2.0/Gralloc0Hal.h>
#include <mapper-passthrough/2.0/Gralloc1Hal.h>
namespace android {
namespace hardware {
namespace graphics {
namespace mapper {
namespace V2_0 {
namespace passthrough {
class GrallocImportedBufferPool {
public:
static GrallocImportedBufferPool& getInstance() {
// GraphicBufferMapper in framework is expected to be valid (and
// leaked) during process termination. We need to make sure IMapper,
// and in turn, GrallocImportedBufferPool is valid as well. Create
// imported buffer pool on the heap (and let it leak) for the purpose.
// Besides, all IMapper instances must share the same pool. Make it a
// singleton.
//
// However, there is no way to make sure gralloc0/gralloc1 are valid
// during process termination. Any use of static/global object in
// gralloc0/gralloc1 that may be destructed during process termination
// is potentially broken.
static GrallocImportedBufferPool* singleton = new GrallocImportedBufferPool;
return *singleton;
}
void* add(native_handle_t* bufferHandle) {
std::lock_guard<std::mutex> lock(mMutex);
return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr;
}
native_handle_t* remove(void* buffer) {
auto bufferHandle = static_cast<native_handle_t*>(buffer);
std::lock_guard<std::mutex> lock(mMutex);
return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
}
const native_handle_t* get(void* buffer) {
auto bufferHandle = static_cast<const native_handle_t*>(buffer);
std::lock_guard<std::mutex> lock(mMutex);
return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
}
private:
std::mutex mMutex;
std::unordered_set<const native_handle_t*> mBufferHandles;
};
// Inherit from V2_*::hal::Mapper and override imported buffer management functions
template <typename T>
class GrallocMapper : public T {
protected:
void* addImportedBuffer(native_handle_t* bufferHandle) override {
return GrallocImportedBufferPool::getInstance().add(bufferHandle);
}
native_handle_t* removeImportedBuffer(void* buffer) override {
return GrallocImportedBufferPool::getInstance().remove(buffer);
}
const native_handle_t* getImportedBuffer(void* buffer) const override {
return GrallocImportedBufferPool::getInstance().get(buffer);
}
};
class GrallocLoader {
public:
static IMapper* load() {
const hw_module_t* module = loadModule();
if (!module) {
return nullptr;
}
auto hal = createHal(module);
if (!hal) {
return nullptr;
}
return createMapper(std::move(hal));
}
// load the gralloc module
static const hw_module_t* loadModule() {
const hw_module_t* module;
int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
if (error) {
ALOGE("failed to get gralloc module");
return nullptr;
}
return module;
}
// return the major api version of the module
static int getModuleMajorApiVersion(const hw_module_t* module) {
return (module->module_api_version >> 8) & 0xff;
}
// create a MapperHal instance
static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) {
int major = getModuleMajorApiVersion(module);
switch (major) {
case 1: {
auto hal = std::make_unique<Gralloc1Hal>();
return hal->initWithModule(module) ? std::move(hal) : nullptr;
}
case 0: {
auto hal = std::make_unique<Gralloc0Hal>();
return hal->initWithModule(module) ? std::move(hal) : nullptr;
}
default:
ALOGE("unknown gralloc module major version %d", major);
return nullptr;
}
}
// create an IAllocator instance
static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) {
auto mapper = std::make_unique<GrallocMapper<hal::Mapper>>();
return mapper->init(std::move(hal)) ? mapper.release() : nullptr;
}
};
} // namespace passthrough
} // namespace V2_0
} // namespace mapper
} // namespace graphics
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,38 @@
//
// Copyright (C) 2016 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.
//
cc_library_static {
name: "libVtsHalGraphicsMapperTestUtils",
defaults: ["hidl_defaults"],
srcs: ["VtsHalGraphicsMapperTestUtils.cpp"],
cflags: [
"-O0",
"-g",
],
shared_libs: [
"libutils",
],
static_libs: [
"VtsHalHidlTargetTestBase",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
],
export_static_lib_headers: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
],
export_include_dirs: ["."],
}

View File

@@ -50,8 +50,7 @@ Gralloc::~Gralloc() {
for (auto bufferHandle : mImportedBuffers) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer))
<< "failed to free buffer " << buffer;
EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
}
mImportedBuffers.clear();
}
@@ -62,15 +61,13 @@ sp<IAllocator> Gralloc::getAllocator() const {
std::string Gralloc::dumpDebugInfo() {
std::string debugInfo;
mAllocator->dumpDebugInfo(
[&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
return debugInfo;
}
const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
const native_handle_t* bufferHandle =
native_handle_clone(rawHandle.getNativeHandle());
const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
EXPECT_NE(nullptr, bufferHandle);
if (bufferHandle) {
@@ -80,24 +77,22 @@ const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
return bufferHandle;
}
std::vector<const native_handle_t*> Gralloc::allocate(
const BufferDescriptor& descriptor, uint32_t count, bool import,
uint32_t* outStride) {
std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
uint32_t count, bool import,
uint32_t* outStride) {
std::vector<const native_handle_t*> bufferHandles;
bufferHandles.reserve(count);
mAllocator->allocate(
descriptor, count, [&](const auto& tmpError, const auto& tmpStride,
const auto& tmpBuffers) {
descriptor, count,
[&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
for (uint32_t i = 0; i < count; i++) {
if (import) {
ASSERT_NO_FATAL_FAILURE(
bufferHandles.push_back(importBuffer(tmpBuffers[i])));
ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(importBuffer(tmpBuffers[i])));
} else {
ASSERT_NO_FATAL_FAILURE(
bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
}
}
@@ -113,9 +108,8 @@ std::vector<const native_handle_t*> Gralloc::allocate(
return bufferHandles;
}
const native_handle_t* Gralloc::allocate(
const IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
uint32_t* outStride) {
const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
bool import, uint32_t* outStride) {
BufferDescriptor descriptor = createDescriptor(descriptorInfo);
if (::testing::Test::HasFatalFailure()) {
return nullptr;
@@ -133,26 +127,23 @@ sp<IMapper> Gralloc::getMapper() const {
return mMapper;
}
BufferDescriptor Gralloc::createDescriptor(
const IMapper::BufferDescriptorInfo& descriptorInfo) {
BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
BufferDescriptor descriptor;
mMapper->createDescriptor(
descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
descriptor = tmpDescriptor;
});
mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
descriptor = tmpDescriptor;
});
return descriptor;
}
const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
const native_handle_t* bufferHandle = nullptr;
mMapper->importBuffer(
rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to import buffer %p"
<< rawHandle.getNativeHandle();
bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
});
mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
ASSERT_EQ(Error::NONE, tmpError)
<< "failed to import buffer %p" << rawHandle.getNativeHandle();
bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
});
if (bufferHandle) {
mImportedBuffers.insert(bufferHandle);
@@ -189,8 +180,7 @@ void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
void* data = nullptr;
mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
[&](const auto& tmpError, const auto& tmpData) {
ASSERT_EQ(Error::NONE, tmpError)
<< "failed to lock buffer " << buffer;
ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
data = tmpData;
});
@@ -201,10 +191,8 @@ void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
return data;
}
YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle,
uint64_t cpuUsage,
const IMapper::Rect& accessRegion,
int acquireFence) {
YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int acquireFence) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
@@ -234,24 +222,20 @@ int Gralloc::unlock(const native_handle_t* bufferHandle) {
auto buffer = const_cast<native_handle_t*>(bufferHandle);
int releaseFence = -1;
mMapper->unlock(
buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer "
<< buffer;
mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " << buffer;
auto fenceHandle = tmpReleaseFence.getNativeHandle();
if (fenceHandle) {
ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle "
<< fenceHandle;
if (fenceHandle->numFds == 1) {
releaseFence = dup(fenceHandle->data[0]);
ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
} else {
ASSERT_EQ(0, fenceHandle->numFds)
<< " invalid fence handle " << fenceHandle;
}
auto fenceHandle = tmpReleaseFence.getNativeHandle();
if (fenceHandle) {
ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
if (fenceHandle->numFds == 1) {
releaseFence = dup(fenceHandle->data[0]);
ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
} else {
ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
}
});
}
});
return releaseFence;
}

View File

@@ -49,19 +49,16 @@ class Gralloc {
// is true, the returned buffers are also imported into the mapper.
//
// Either case, the returned buffers must be freed with freeBuffer.
std::vector<const native_handle_t*> allocate(
const BufferDescriptor& descriptor, uint32_t count, bool import = true,
uint32_t* outStride = nullptr);
const native_handle_t* allocate(
const IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
uint32_t* outStride = nullptr);
std::vector<const native_handle_t*> allocate(const BufferDescriptor& descriptor, uint32_t count,
bool import = true, uint32_t* outStride = nullptr);
const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
bool import = true, uint32_t* outStride = nullptr);
// IMapper methods
sp<IMapper> getMapper() const;
BufferDescriptor createDescriptor(
const IMapper::BufferDescriptorInfo& descriptorInfo);
BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
const native_handle_t* importBuffer(const hidl_handle& rawHandle);
void freeBuffer(const native_handle_t* bufferHandle);
@@ -71,9 +68,8 @@ class Gralloc {
// with each of these functions.
void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int acquireFence);
YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle,
uint64_t cpuUsage, const IMapper::Rect& accessRegion,
int acquireFence);
YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
const IMapper::Rect& accessRegion, int acquireFence);
int unlock(const native_handle_t* bufferHandle);
private:

View File

@@ -14,27 +14,6 @@
// limitations under the License.
//
cc_library_static {
name: "libVtsHalGraphicsMapperTestUtils",
defaults: ["hidl_defaults"],
srcs: ["VtsHalGraphicsMapperTestUtils.cpp"],
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
],
static_libs: [
"VtsHalHidlTargetTestBase",
],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
"-O0",
"-g",
],
export_include_dirs: ["."],
}
cc_test {
name: "VtsHalGraphicsMapperV2_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],

View File

@@ -33,22 +33,22 @@ using android::hardware::graphics::common::V1_0::BufferUsage;
using android::hardware::graphics::common::V1_0::PixelFormat;
class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
protected:
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
protected:
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
mDummyDescriptorInfo.width = 64;
mDummyDescriptorInfo.height = 64;
mDummyDescriptorInfo.layerCount = 1;
mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
mDummyDescriptorInfo.usage = static_cast<uint64_t>(
BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
}
mDummyDescriptorInfo.width = 64;
mDummyDescriptorInfo.height = 64;
mDummyDescriptorInfo.layerCount = 1;
mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
mDummyDescriptorInfo.usage =
static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
}
void TearDown() override {}
void TearDown() override {}
std::unique_ptr<Gralloc> mGralloc;
IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
std::unique_ptr<Gralloc> mGralloc;
IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
};
/**
@@ -63,18 +63,16 @@ TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
*/
TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
BufferDescriptor descriptor;
ASSERT_NO_FATAL_FAILURE(
descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
for (uint32_t count = 0; count < 5; count++) {
std::vector<const native_handle_t*> bufferHandles;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate(
descriptor, count, false, &stride));
ASSERT_NO_FATAL_FAILURE(bufferHandles =
mGralloc->allocate(descriptor, count, false, &stride));
if (count >= 1) {
EXPECT_LE(mDummyDescriptorInfo.width, stride)
<< "invalid buffer stride";
EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
}
for (auto bufferHandle : bufferHandles) {
@@ -89,10 +87,10 @@ TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
// this assumes any valid descriptor is non-empty
BufferDescriptor descriptor;
mGralloc->getAllocator()->allocate(
descriptor, 1, [&](const auto& tmpError, const auto&, const auto&) {
EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
});
mGralloc->getAllocator()->allocate(descriptor, 1,
[&](const auto& tmpError, const auto&, const auto&) {
EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
});
}
/**
@@ -122,11 +120,9 @@ TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
auto info = mDummyDescriptorInfo;
info.width = 0;
mGralloc->getMapper()->createDescriptor(
info, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_VALUE, tmpError)
<< "createDescriptor did not fail with BAD_VALUE";
});
mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE";
});
}
/**
@@ -134,8 +130,7 @@ TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
*/
TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
const native_handle_t* bufferHandle;
ASSERT_NO_FATAL_FAILURE(bufferHandle =
mGralloc->allocate(mDummyDescriptorInfo, true));
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
}
@@ -144,16 +139,13 @@ TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
*/
TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
const native_handle_t* clonedBufferHandle;
ASSERT_NO_FATAL_FAILURE(
clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
// A cloned handle is a raw handle. Check that we can import it multiple
// times.
const native_handle_t* importedBufferHandles[2];
ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] =
mGralloc->importBuffer(clonedBufferHandle));
ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] =
mGralloc->importBuffer(clonedBufferHandle));
ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] = mGralloc->importBuffer(clonedBufferHandle));
ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] = mGralloc->importBuffer(clonedBufferHandle));
ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
@@ -165,15 +157,13 @@ TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
*/
TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
const native_handle_t* rawHandle;
ASSERT_NO_FATAL_FAILURE(
rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
native_handle_t* importedHandle = nullptr;
mGralloc->getMapper()->importBuffer(
rawHandle, [&](const auto& tmpError, const auto& buffer) {
ASSERT_EQ(Error::NONE, tmpError);
importedHandle = static_cast<native_handle_t*>(buffer);
});
mGralloc->getMapper()->importBuffer(rawHandle, [&](const auto& tmpError, const auto& buffer) {
ASSERT_EQ(Error::NONE, tmpError);
importedHandle = static_cast<native_handle_t*>(buffer);
});
// free the imported handle with another mapper
std::unique_ptr<Gralloc> anotherGralloc;
@@ -203,15 +193,13 @@ TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
*/
TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
native_handle_t* invalidHandle = nullptr;
mGralloc->getMapper()->importBuffer(
invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "importBuffer with nullptr did not fail with BAD_BUFFER";
});
mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "importBuffer with nullptr did not fail with BAD_BUFFER";
});
invalidHandle = native_handle_create(0, 0);
mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError,
const auto&) {
mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "importBuffer with invalid handle did not fail with BAD_BUFFER";
});
@@ -224,8 +212,7 @@ TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
native_handle_t* invalidHandle = nullptr;
Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
EXPECT_EQ(Error::BAD_BUFFER, error)
<< "freeBuffer with nullptr did not fail with BAD_BUFFER";
EXPECT_EQ(Error::BAD_BUFFER, error) << "freeBuffer with nullptr did not fail with BAD_BUFFER";
invalidHandle = native_handle_create(0, 0);
error = mGralloc->getMapper()->freeBuffer(invalidHandle);
@@ -234,8 +221,7 @@ TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
native_handle_delete(invalidHandle);
const native_handle_t* clonedBufferHandle;
ASSERT_NO_FATAL_FAILURE(
clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
ASSERT_NO_FATAL_FAILURE(clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
error = mGralloc->getMapper()->freeBuffer(invalidHandle);
EXPECT_EQ(Error::BAD_BUFFER, error)
<< "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
@@ -251,16 +237,15 @@ TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
const native_handle_t* bufferHandle;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(bufferHandle =
mGralloc->allocate(info, true, &stride));
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
// lock buffer for writing
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
int fence = -1;
uint8_t* data;
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
bufferHandle, info.usage, region, fence)));
ASSERT_NO_FATAL_FAILURE(
data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
// RGBA_8888
size_t strideInBytes = stride * 4;
@@ -274,8 +259,8 @@ TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
// lock again for reading
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
bufferHandle, info.usage, region, fence)));
ASSERT_NO_FATAL_FAILURE(
data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
for (uint32_t y = 0; y < info.height; y++) {
for (size_t i = 0; i < writeInBytes; i++) {
EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
@@ -299,16 +284,14 @@ TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
const native_handle_t* bufferHandle;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(bufferHandle =
mGralloc->allocate(info, true, &stride));
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
// lock buffer for writing
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
int fence = -1;
YCbCrLayout layout;
ASSERT_NO_FATAL_FAILURE(
layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
auto yData = static_cast<uint8_t*>(layout.y);
auto cbData = static_cast<uint8_t*>(layout.cb);
@@ -328,8 +311,7 @@ TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
// lock again for reading
ASSERT_NO_FATAL_FAILURE(
layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
ASSERT_NO_FATAL_FAILURE(layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
yData = static_cast<uint8_t*>(layout.y);
cbData = static_cast<uint8_t*>(layout.cb);
@@ -357,25 +339,21 @@ TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
*/
TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
native_handle_t* invalidHandle = nullptr;
mGralloc->getMapper()->unlock(
invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with nullptr did not fail with BAD_BUFFER";
});
mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with nullptr did not fail with BAD_BUFFER";
});
invalidHandle = native_handle_create(0, 0);
mGralloc->getMapper()->unlock(
invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with invalid handle did not fail with BAD_BUFFER";
});
mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with invalid handle did not fail with BAD_BUFFER";
});
native_handle_delete(invalidHandle);
ASSERT_NO_FATAL_FAILURE(invalidHandle =
const_cast<native_handle_t*>(mGralloc->allocate(
mDummyDescriptorInfo, false)));
mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError,
const auto&) {
ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
mGralloc->allocate(mDummyDescriptorInfo, false)));
mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, const auto&) {
EXPECT_EQ(Error::BAD_BUFFER, tmpError)
<< "unlock with un-imported handle did not fail with BAD_BUFFER";
});