diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp index ed2ecbb508..9980ae0f2f 100644 --- a/graphics/allocator/2.0/default/Android.bp +++ b/graphics/allocator/2.0/default/Android.bp @@ -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 { diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h index 2f3022e440..8ca820026e 100644 --- a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h +++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h @@ -39,11 +39,11 @@ using mapper::V2_0::Error; namespace detail { -// AllocatorImpl implements IAllocator on top of AllocatorHal -template -class AllocatorImpl : public IALLOCATOR { +// AllocatorImpl implements V2_*::IAllocator on top of V2_*::hal::AllocatorHal +template +class AllocatorImpl : public Interface { public: - bool init(std::unique_ptr hal) { + bool init(std::unique_ptr hal) { mHal = std::move(hal); return true; } @@ -74,7 +74,7 @@ class AllocatorImpl : public IALLOCATOR { } protected: - std::unique_ptr mHal; + std::unique_ptr mHal; }; } // namespace detail diff --git a/graphics/allocator/2.0/utils/passthrough/Android.bp b/graphics/allocator/2.0/utils/passthrough/Android.bp index b95656572d..95b92cfb55 100644 --- a/graphics/allocator/2.0/utils/passthrough/Android.bp +++ b/graphics/allocator/2.0/utils/passthrough/Android.bp @@ -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\""], } diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp deleted file mode 100644 index 8edb7dc500..0000000000 --- a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp +++ /dev/null @@ -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 - -#include - -#include -#include -#include - -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* 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 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& 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(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 diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp deleted file mode 100644 index e343ecd294..0000000000 --- a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp +++ /dev/null @@ -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 - -#include - -#include -#include - -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 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 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* 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 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& 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(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | - BufferUsage::GPU_DATA_BUFFER); - - switch (usage & BufferUsage::CPU_WRITE_MASK) { - case static_cast(BufferUsage::CPU_WRITE_RARELY): - producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE; - break; - case static_cast(BufferUsage::CPU_WRITE_OFTEN): - producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN; - break; - default: - break; - } - - switch (usage & BufferUsage::CPU_READ_MASK) { - case static_cast(BufferUsage::CPU_READ_RARELY): - producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ; - break; - case static_cast(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(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(BufferUsage::CPU_READ_RARELY): - consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ; - break; - case static_cast(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(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 diff --git a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp deleted file mode 100644 index dae7a78ca5..0000000000 --- a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp +++ /dev/null @@ -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 - -#include -#include -#include -#include -#include -#include -#include - -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 GrallocLoader::createHal(const hw_module_t* module) { - int major = getModuleMajorApiVersion(module); - switch (major) { - case 1: { - auto hal = std::make_unique(); - return hal->initWithModule(module) ? std::move(hal) : nullptr; - } - case 0: { - auto hal = std::make_unique(); - 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) { - auto allocator = std::make_unique(); - return allocator->init(std::move(hal)) ? allocator.release() : nullptr; -} - -} // namespace passthrough -} // namespace V2_0 -} // namespace allocator -} // namespace graphics -} // namespace hardware -} // namespace android diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h index 8f433b0f56..6c179be722 100644 --- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h +++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h @@ -16,10 +16,16 @@ #pragma once -#include +#ifndef LOG_TAG +#warning "Gralloc0Hal.h included without LOG_TAG" +#endif -struct alloc_device_t; -struct hw_module_t; +#include // for strerror + +#include +#include +#include +#include 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 +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* outBuffers) override; + std::vector* outBuffers) override { + mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo; + if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) { + return Error::BAD_DESCRIPTOR; + } - void freeBuffers(const std::vector& buffers) override; + Error error = Error::NONE; + uint32_t stride = 0; + std::vector 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& 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(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; + } // namespace passthrough } // namespace V2_0 } // namespace allocator diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h index 3126e91506..53b5c14de7 100644 --- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h +++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h @@ -16,8 +16,16 @@ #pragma once +#ifndef LOG_TAG +#warning "Gralloc1Hal.h included without LOG_TAG" +#endif + +#include // for strerror + #include #include +#include +#include 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 +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 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* outBuffers) override; + std::vector* outBuffers) override { + mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo; + if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) { + return Error::BAD_DESCRIPTOR; + } - void freeBuffers(const std::vector& buffers) override; + gralloc1_buffer_descriptor_t desc; + Error error = createDescriptor(descriptorInfo, &desc); + if (error != Error::NONE) { + return error; + } + + uint32_t stride = 0; + std::vector 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& 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 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 - 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(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(BufferUsage::CPU_READ_MASK | + BufferUsage::CPU_WRITE_MASK | + BufferUsage::GPU_DATA_BUFFER); + + switch (usage & BufferUsage::CPU_WRITE_MASK) { + case static_cast(BufferUsage::CPU_WRITE_RARELY): + producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE; + break; + case static_cast(BufferUsage::CPU_WRITE_OFTEN): + producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN; + break; + default: + break; + } + + switch (usage & BufferUsage::CPU_READ_MASK) { + case static_cast(BufferUsage::CPU_READ_RARELY): + producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ; + break; + case static_cast(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(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(BufferUsage::CPU_READ_RARELY): + consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ; + break; + case static_cast(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(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; + } // namespace passthrough } // namespace V2_0 } // namespace allocator diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h index a0b9503c30..660099bb14 100644 --- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h +++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h @@ -16,11 +16,18 @@ #pragma once +#ifndef LOG_TAG +#warning "GrallocLoader.h included without LOG_TAG" +#endif + #include -#include - -struct hw_module_t; +#include +#include +#include +#include +#include +#include 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 createHal(const hw_module_t* module); + static std::unique_ptr createHal(const hw_module_t* module) { + int major = getModuleMajorApiVersion(module); + switch (major) { + case 1: { + auto hal = std::make_unique(); + return hal->initWithModule(module) ? std::move(hal) : nullptr; + } + case 0: { + auto hal = std::make_unique(); + 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); + static IAllocator* createAllocator(std::unique_ptr hal) { + auto allocator = std::make_unique(); + return allocator->init(std::move(hal)) ? allocator.release() : nullptr; + } }; } // namespace passthrough diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp index 677d966113..8874799d10 100644 --- a/graphics/mapper/2.0/default/Android.bp +++ b/graphics/mapper/2.0/default/Android.bp @@ -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\""], } diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp deleted file mode 100644 index 28f50161c7..0000000000 --- a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp +++ /dev/null @@ -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 - -namespace android { -namespace hardware { -namespace graphics { -namespace mapper { -namespace V2_0 { -namespace implementation { - -Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module) - : mModule(reinterpret_cast(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 diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.h b/graphics/mapper/2.0/default/Gralloc0Mapper.h deleted file mode 100644 index e792a69703..0000000000 --- a/graphics/mapper/2.0/default/Gralloc0Mapper.h +++ /dev/null @@ -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 - -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 diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp deleted file mode 100644 index c1e5adcd64..0000000000 --- a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp +++ /dev/null @@ -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 - -#include - -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 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 -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(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(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 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(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 diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.h b/graphics/mapper/2.0/default/Gralloc1Mapper.h deleted file mode 100644 index 452afdf820..0000000000 --- a/graphics/mapper/2.0/default/Gralloc1Mapper.h +++ /dev/null @@ -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 - -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 - 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 diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp deleted file mode 100644 index d16143da49..0000000000 --- a/graphics/mapper/2.0/default/GrallocMapper.cpp +++ /dev/null @@ -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 - -#include -#include - -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 lock(mMutex); - return mHandles.insert(bufferHandle).second; - } - - native_handle_t* pop(void* buffer) { - auto bufferHandle = static_cast(buffer); - - std::lock_guard lock(mMutex); - return mHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr; - } - - buffer_handle_t get(const void* buffer) { - auto bufferHandle = static_cast(buffer); - - std::lock_guard lock(mMutex); - return mHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr; - } - - private: - std::mutex mMutex; - std::unordered_set 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(0)); - - if (!descriptorInfo.width || !descriptorInfo.height || - !descriptorInfo.layerCount) { - return false; - } - - if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) { - return false; - } - - if (descriptorInfo.format == static_cast(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 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 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 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 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 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 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 diff --git a/graphics/mapper/2.0/default/GrallocMapper.h b/graphics/mapper/2.0/default/GrallocMapper.h deleted file mode 100644 index e876fe4494..0000000000 --- a/graphics/mapper/2.0/default/GrallocMapper.h +++ /dev/null @@ -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 -#include - -#include -#include - -namespace android { -namespace hardware { -namespace graphics { -namespace mapper { -namespace V2_0 { -namespace implementation { - -class GrallocMapper : public IMapper { - public: - // IMapper interface - Return createDescriptor(const BufferDescriptorInfo& descriptorInfo, - createDescriptor_cb hidl_cb) override; - Return importBuffer(const hidl_handle& rawHandle, - importBuffer_cb hidl_cb) override; - Return freeBuffer(void* buffer) override; - Return lock(void* buffer, uint64_t cpuUsage, - const IMapper::Rect& accessRegion, - const hidl_handle& acquireFence, - lock_cb hidl_cb) override; - Return lockYCbCr(void* buffer, uint64_t cpuUsage, - const IMapper::Rect& accessRegion, - const hidl_handle& acquireFence, - lockYCbCr_cb hidl_cb) override; - Return 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 diff --git a/graphics/mapper/2.0/default/passthrough.cpp b/graphics/mapper/2.0/default/passthrough.cpp new file mode 100644 index 0000000000..e18b88fb84 --- /dev/null +++ b/graphics/mapper/2.0/default/passthrough.cpp @@ -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 +#include + +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(); +} diff --git a/graphics/mapper/2.0/utils/OWNERS b/graphics/mapper/2.0/utils/OWNERS new file mode 100644 index 0000000000..3aa5fa1ffd --- /dev/null +++ b/graphics/mapper/2.0/utils/OWNERS @@ -0,0 +1,4 @@ +# Graphics team +jessehall@google.com +olv@google.com +stoza@google.com diff --git a/graphics/mapper/2.0/utils/hal/Android.bp b/graphics/mapper/2.0/utils/hal/Android.bp new file mode 100644 index 0000000000..5610a69aac --- /dev/null +++ b/graphics/mapper/2.0/utils/hal/Android.bp @@ -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"], +} diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h new file mode 100644 index 0000000000..5ad2a6564c --- /dev/null +++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h @@ -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 + +#include +#include +#include + +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 +class MapperImpl : public Interface { + public: + bool init(std::unique_ptr hal) { + mHal = std::move(hal); + return true; + } + + // IMapper 2.0 interface + + Return 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 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 freeBuffer(void* buffer) override { + native_handle_t* bufferHandle = removeImportedBuffer(buffer); + if (!bufferHandle) { + return Error::BAD_BUFFER; + } + + return mHal->freeBuffer(bufferHandle); + } + + Return 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 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 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(bufferHandle); + } + + virtual native_handle_t* removeImportedBuffer(void* buffer) { + return static_cast(buffer); + } + + virtual const native_handle_t* getImportedBuffer(void* buffer) const { + return static_cast(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 mHal; +}; + +} // namespace detail + +using Mapper = detail::MapperImpl; + +} // namespace hal +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h new file mode 100644 index 0000000000..ab2e5cf9b6 --- /dev/null +++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h @@ -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 +#include + +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 diff --git a/graphics/mapper/2.0/utils/passthrough/Android.bp b/graphics/mapper/2.0/utils/passthrough/Android.bp new file mode 100644 index 0000000000..4f700c867a --- /dev/null +++ b/graphics/mapper/2.0/utils/passthrough/Android.bp @@ -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"], +} diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h new file mode 100644 index 0000000000..7369ac7593 --- /dev/null +++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h @@ -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 + +#include +#include +#include +#include +#include + +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 +class Gralloc0HalImpl : public Hal { + public: + bool initWithModule(const hw_module_t* module) { + mModule = reinterpret_cast(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(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; + +} // namespace passthrough +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h new file mode 100644 index 0000000000..d9beb4f678 --- /dev/null +++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h @@ -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 + +#include + +#include +#include +#include +#include + +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 +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(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(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 flexPlanes(flex.num_planes); + flex.planes = flexPlanes.data(); + + const uint64_t consumerUsage = + cpuUsage & ~static_cast(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 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 + bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) { + auto pfn = mDevice->getFunction(mDevice, desc); + if (pfn) { + *outPfn = reinterpret_cast(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; + +} // namespace passthrough +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h similarity index 84% rename from graphics/mapper/2.0/default/GrallocBufferDescriptor.h rename to graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h index 9b5ab04562..4c477e12a5 100644 --- a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h +++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h @@ -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 @@ -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 diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h new file mode 100644 index 0000000000..e8b1b4b837 --- /dev/null +++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h @@ -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 +#include +#include + +#include +#include +#include +#include +#include +#include + +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 lock(mMutex); + return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr; + } + + native_handle_t* remove(void* buffer) { + auto bufferHandle = static_cast(buffer); + + std::lock_guard lock(mMutex); + return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr; + } + + const native_handle_t* get(void* buffer) { + auto bufferHandle = static_cast(buffer); + + std::lock_guard lock(mMutex); + return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr; + } + + private: + std::mutex mMutex; + std::unordered_set mBufferHandles; +}; + +// Inherit from V2_*::hal::Mapper and override imported buffer management functions +template +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 createHal(const hw_module_t* module) { + int major = getModuleMajorApiVersion(module); + switch (major) { + case 1: { + auto hal = std::make_unique(); + return hal->initWithModule(module) ? std::move(hal) : nullptr; + } + case 0: { + auto hal = std::make_unique(); + 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) { + auto mapper = std::make_unique>(); + return mapper->init(std::move(hal)) ? mapper.release() : nullptr; + } +}; + +} // namespace passthrough +} // namespace V2_0 +} // namespace mapper +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/graphics/mapper/2.0/utils/vts/Android.bp b/graphics/mapper/2.0/utils/vts/Android.bp new file mode 100644 index 0000000000..8bca152afa --- /dev/null +++ b/graphics/mapper/2.0/utils/vts/Android.bp @@ -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: ["."], +} diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp b/graphics/mapper/2.0/utils/vts/VtsHalGraphicsMapperTestUtils.cpp similarity index 69% rename from graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp rename to graphics/mapper/2.0/utils/vts/VtsHalGraphicsMapperTestUtils.cpp index 671c4b14ec..e3229caf2d 100644 --- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp +++ b/graphics/mapper/2.0/utils/vts/VtsHalGraphicsMapperTestUtils.cpp @@ -50,8 +50,7 @@ Gralloc::~Gralloc() { for (auto bufferHandle : mImportedBuffers) { auto buffer = const_cast(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 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 Gralloc::allocate( - const BufferDescriptor& descriptor, uint32_t count, bool import, - uint32_t* outStride) { +std::vector Gralloc::allocate(const BufferDescriptor& descriptor, + uint32_t count, bool import, + uint32_t* outStride) { std::vector 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 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 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(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(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(bufferHandle); NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0); @@ -234,24 +222,20 @@ int Gralloc::unlock(const native_handle_t* bufferHandle) { auto buffer = const_cast(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; } diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h b/graphics/mapper/2.0/utils/vts/VtsHalGraphicsMapperTestUtils.h similarity index 83% rename from graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h rename to graphics/mapper/2.0/utils/vts/VtsHalGraphicsMapperTestUtils.h index 9cf60a375a..1f7d88aefc 100644 --- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h +++ b/graphics/mapper/2.0/utils/vts/VtsHalGraphicsMapperTestUtils.h @@ -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 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 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 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: diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp index ac6cb47a68..8093b08676 100644 --- a/graphics/mapper/2.0/vts/functional/Android.bp +++ b/graphics/mapper/2.0/vts/functional/Android.bp @@ -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"], diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp index 1f9489851f..21ea66d7cd 100644 --- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp +++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp @@ -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()); + protected: + void SetUp() override { + ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique()); - mDummyDescriptorInfo.width = 64; - mDummyDescriptorInfo.height = 64; - mDummyDescriptorInfo.layerCount = 1; - mDummyDescriptorInfo.format = PixelFormat::RGBA_8888; - mDummyDescriptorInfo.usage = static_cast( - 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(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); + } - void TearDown() override {} + void TearDown() override {} - std::unique_ptr mGralloc; - IMapper::BufferDescriptorInfo mDummyDescriptorInfo{}; + std::unique_ptr 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 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(buffer); - }); + mGralloc->getMapper()->importBuffer(rawHandle, [&](const auto& tmpError, const auto& buffer) { + ASSERT_EQ(Error::NONE, tmpError); + importedHandle = static_cast(buffer); + }); // free the imported handle with another mapper std::unique_ptr 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(info.width), static_cast(info.height)}; int fence = -1; uint8_t* data; - ASSERT_NO_FATAL_FAILURE(data = static_cast(mGralloc->lock( - bufferHandle, info.usage, region, fence))); + ASSERT_NO_FATAL_FAILURE( + data = static_cast(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(mGralloc->lock( - bufferHandle, info.usage, region, fence))); + ASSERT_NO_FATAL_FAILURE( + data = static_cast(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(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(info.width), static_cast(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(layout.y); auto cbData = static_cast(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(layout.y); cbData = static_cast(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(mGralloc->allocate( - mDummyDescriptorInfo, false))); - mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError, - const auto&) { + ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast( + 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"; });