From 3cacced179113a728649c8123d48e13f9ad9cbf7 Mon Sep 17 00:00:00 2001 From: Dominggoes Isakh Date: Fri, 23 Mar 2018 21:32:18 +0100 Subject: [PATCH] exynos4: android.hardware.graphics.allocator@2.0 for Exynos4 * Buffer got corrupt because of the mNumFlexPlanes member. Use fixed value of 4 instead and exclude the member. * Usage bits were not filtered properly Change-Id: I7ee9fa73f896c505403447ae118a76d9f53e00a8 --- Android.bp | 3 + exynos4/Android.bp | 3 + exynos4/hal/libgralloc_ump/Android.mk | 2 +- exynos4/interfaces/Android.bp | 3 + exynos4/interfaces/gralloc/Android.bp | 33 ++ exynos4/interfaces/gralloc/Gralloc.cpp | 57 ++ exynos4/interfaces/gralloc/Gralloc.h | 38 ++ .../interfaces/gralloc/Gralloc0Allocator.cpp | 144 +++++ .../interfaces/gralloc/Gralloc0Allocator.h | 59 ++ .../interfaces/gralloc/Gralloc1Allocator.cpp | 337 +++++++++++ .../interfaces/gralloc/Gralloc1Allocator.h | 89 +++ .../interfaces/gralloc/Gralloc1On0Adapter.cpp | 560 ++++++++++++++++++ .../interfaces/gralloc/Gralloc1On0Adapter.h | 456 ++++++++++++++ .../interfaces/gralloc/gralloc1-adapter.cpp | 32 + exynos4/interfaces/gralloc/gralloc1-adapter.h | 89 +++ 15 files changed, 1904 insertions(+), 1 deletion(-) create mode 100644 Android.bp create mode 100644 exynos4/Android.bp create mode 100644 exynos4/interfaces/Android.bp create mode 100644 exynos4/interfaces/gralloc/Android.bp create mode 100644 exynos4/interfaces/gralloc/Gralloc.cpp create mode 100644 exynos4/interfaces/gralloc/Gralloc.h create mode 100644 exynos4/interfaces/gralloc/Gralloc0Allocator.cpp create mode 100644 exynos4/interfaces/gralloc/Gralloc0Allocator.h create mode 100644 exynos4/interfaces/gralloc/Gralloc1Allocator.cpp create mode 100644 exynos4/interfaces/gralloc/Gralloc1Allocator.h create mode 100644 exynos4/interfaces/gralloc/Gralloc1On0Adapter.cpp create mode 100644 exynos4/interfaces/gralloc/Gralloc1On0Adapter.h create mode 100644 exynos4/interfaces/gralloc/gralloc1-adapter.cpp create mode 100644 exynos4/interfaces/gralloc/gralloc1-adapter.h diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000..6e395a7 --- /dev/null +++ b/Android.bp @@ -0,0 +1,3 @@ +subdirs = [ + "exynos4", +] diff --git a/exynos4/Android.bp b/exynos4/Android.bp new file mode 100644 index 0000000..107c53a --- /dev/null +++ b/exynos4/Android.bp @@ -0,0 +1,3 @@ +subdirs = [ + "interfaces", +] diff --git a/exynos4/hal/libgralloc_ump/Android.mk b/exynos4/hal/libgralloc_ump/Android.mk index c108eb4..0cd5ecb 100644 --- a/exynos4/hal/libgralloc_ump/Android.mk +++ b/exynos4/hal/libgralloc_ump/Android.mk @@ -49,7 +49,7 @@ LOCAL_CFLAGS += -DSAMSUNG_EXYNOS LOCAL_CFLAGS += -DSAMSUNG_EXYNOS_CACHE_UMP LOCAL_CFLAGS += -DUSE_PARTIAL_FLUSH -LOCAL_STATIC_LIBRARIES := libgralloc1-adapter +LOCAL_STATIC_LIBRARIES := libgralloc1-adapter-exynos4 LOCAL_SHARED_LIBRARIES += libsync ifeq ($(TARGET_SOC),exynos4210) diff --git a/exynos4/interfaces/Android.bp b/exynos4/interfaces/Android.bp new file mode 100644 index 0000000..8725443 --- /dev/null +++ b/exynos4/interfaces/Android.bp @@ -0,0 +1,3 @@ +subdirs = [ + "gralloc", +] diff --git a/exynos4/interfaces/gralloc/Android.bp b/exynos4/interfaces/gralloc/Android.bp new file mode 100644 index 0000000..c99c6e0 --- /dev/null +++ b/exynos4/interfaces/gralloc/Android.bp @@ -0,0 +1,33 @@ +cc_library_shared { + name: "android.hardware.graphics.allocator@2.0-impl-exynos4", + defaults: ["hidl_defaults"], + proprietary: true, + relative_install_path: "hw", + srcs: ["Gralloc.cpp", "Gralloc0Allocator.cpp", "Gralloc1Allocator.cpp"], + include_dirs: ["system/core/libgrallocusage/include"], + cppflags: ["-Wall", "-Wextra"], + shared_libs: [ + "android.hardware.graphics.allocator@2.0", + "libbase", + "libcutils", + "libhardware", + "libhidlbase", + "libhidltransport", + "liblog", + "libutils", + ], + header_libs: [ + "libgrallocmapperincludes", + ], + whole_static_libs: ["libgrallocusage"], +} + +cc_library_static { + name: "libgralloc1-adapter-exynos4", + defaults: ["hidl_defaults"], + srcs: ["gralloc1-adapter.cpp", "Gralloc1On0Adapter.cpp"], + include_dirs: ["system/core/libsync/include"], + cflags: ["-Wall", "-Wextra"], + export_include_dirs: ["."], + whole_static_libs: ["libgrallocusage"], +} diff --git a/exynos4/interfaces/gralloc/Gralloc.cpp b/exynos4/interfaces/gralloc/Gralloc.cpp new file mode 100644 index 0000000..273d3f5 --- /dev/null +++ b/exynos4/interfaces/gralloc/Gralloc.cpp @@ -0,0 +1,57 @@ +/* + * 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 "GrallocPassthrough" + +#include "Gralloc.h" +#include "Gralloc0Allocator.h" +#include "Gralloc1Allocator.h" + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +IAllocator* HIDL_FETCH_IAllocator(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 Gralloc1Allocator(module); + case 0: + return new Gralloc0Allocator(module); + default: + ALOGE("unknown gralloc module major version %d", major); + return nullptr; + } +} + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/exynos4/interfaces/gralloc/Gralloc.h b/exynos4/interfaces/gralloc/Gralloc.h new file mode 100644 index 0000000..c79eeaa --- /dev/null +++ b/exynos4/interfaces/gralloc/Gralloc.h @@ -0,0 +1,38 @@ +/* + * 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_ALLOCATOR_V2_0_GRALLOC_H +#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* name); + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H diff --git a/exynos4/interfaces/gralloc/Gralloc0Allocator.cpp b/exynos4/interfaces/gralloc/Gralloc0Allocator.cpp new file mode 100644 index 0000000..3b62bb3 --- /dev/null +++ b/exynos4/interfaces/gralloc/Gralloc0Allocator.cpp @@ -0,0 +1,144 @@ +/* + * 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 "Gralloc0Allocator" + +#include "Gralloc0Allocator.h" +#include "GrallocBufferDescriptor.h" + +#include + +#include + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::mapper::V2_0::implementation:: + grallocDecodeBufferDescriptor; + +Gralloc0Allocator::Gralloc0Allocator(const hw_module_t* module) { + int result = gralloc_open(module, &mDevice); + if (result) { + LOG_ALWAYS_FATAL("failed to open gralloc0 device: %s", + strerror(-result)); + } +} + +Gralloc0Allocator::~Gralloc0Allocator() { + gralloc_close(mDevice); +} + +Return Gralloc0Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) { + char buf[4096] = {}; + if (mDevice->dump) { + mDevice->dump(mDevice, buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + } + + hidl_cb(hidl_string(buf)); + + return Void(); +} + +Return Gralloc0Allocator::allocate(const BufferDescriptor& descriptor, + uint32_t count, allocate_cb hidl_cb) { + IMapper::BufferDescriptorInfo descriptorInfo; + if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) { + hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec()); + return Void(); + } + + 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++) { + buffer_handle_t tmpBuffer; + uint32_t tmpStride; + error = allocateOne(descriptorInfo, &tmpBuffer, &tmpStride); + if (error != Error::NONE) { + break; + } + + if (stride == 0) { + stride = tmpStride; + } else if (stride != tmpStride) { + // non-uniform strides + mDevice->free(mDevice, tmpBuffer); + stride = 0; + error = Error::UNSUPPORTED; + break; + } + + buffers.emplace_back(hidl_handle(tmpBuffer)); + } + + // return the buffers + hidl_vec hidl_buffers; + if (error == Error::NONE) { + hidl_buffers.setToExternal(buffers.data(), buffers.size()); + } + hidl_cb(error, stride, hidl_buffers); + + // free the buffers + for (const auto& buffer : buffers) { + mDevice->free(mDevice, buffer.getNativeHandle()); + } + + return Void(); +} + +Error Gralloc0Allocator::allocateOne(const IMapper::BufferDescriptorInfo& info, + buffer_handle_t* outBuffer, + uint32_t* outStride) { + if (info.layerCount > 1 || (info.usage >> 32) != 0) { + return Error::BAD_VALUE; + } + + buffer_handle_t buffer = nullptr; + int stride = 0; + int result = mDevice->alloc(mDevice, info.width, info.height, + static_cast(info.format), info.usage, + &buffer, &stride); + if (result) { + switch (result) { + case -EINVAL: + return Error::BAD_VALUE; + default: + return Error::NO_RESOURCES; + } + } + + *outBuffer = buffer; + *outStride = stride; + + return Error::NONE; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/exynos4/interfaces/gralloc/Gralloc0Allocator.h b/exynos4/interfaces/gralloc/Gralloc0Allocator.h new file mode 100644 index 0000000..0e90527 --- /dev/null +++ b/exynos4/interfaces/gralloc/Gralloc0Allocator.h @@ -0,0 +1,59 @@ +/* + * 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_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H +#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::mapper::V2_0::IMapper; +using android::hardware::graphics::mapper::V2_0::BufferDescriptor; +using android::hardware::graphics::mapper::V2_0::Error; + +class Gralloc0Allocator : public IAllocator { + public: + Gralloc0Allocator(const hw_module_t* module); + virtual ~Gralloc0Allocator(); + + // IAllocator interface + Return dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; + Return allocate(const BufferDescriptor& descriptor, uint32_t count, + allocate_cb hidl_cb) override; + + private: + Error allocateOne(const IMapper::BufferDescriptorInfo& info, + buffer_handle_t* outBuffer, uint32_t* outStride); + + alloc_device_t* mDevice; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H diff --git a/exynos4/interfaces/gralloc/Gralloc1Allocator.cpp b/exynos4/interfaces/gralloc/Gralloc1Allocator.cpp new file mode 100644 index 0000000..c0d1a78 --- /dev/null +++ b/exynos4/interfaces/gralloc/Gralloc1Allocator.cpp @@ -0,0 +1,337 @@ +/* + * 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 "Gralloc1Allocator" + +#include "Gralloc1Allocator.h" +#include "GrallocBufferDescriptor.h" + +#include + +#include + +#include + +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::common::V1_0::BufferUsage; +using android::hardware::graphics::mapper::V2_0::implementation:: + grallocDecodeBufferDescriptor; + +Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module) + : mDevice(nullptr), mCapabilities(), mDispatch() { + int result = gralloc1_open(module, &mDevice); + if (result) { + LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s", + strerror(-result)); + } + + initCapabilities(); + initDispatch(); +} + +Gralloc1Allocator::~Gralloc1Allocator() { + gralloc1_close(mDevice); +} + +void Gralloc1Allocator::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 +void Gralloc1Allocator::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 Gralloc1Allocator::initDispatch() { + 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); + if (mCapabilities.layeredBuffers) { + initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT, + &mDispatch.setLayerCount); + } + 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 Gralloc1Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) { + 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'; + + hidl_string reply; + reply.setToExternal(buf.data(), len); + hidl_cb(reply); + + return Void(); +} + +Return Gralloc1Allocator::allocate(const BufferDescriptor& descriptor, + uint32_t count, allocate_cb hidl_cb) { + IMapper::BufferDescriptorInfo descriptorInfo; + if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) { + hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec()); + return Void(); + } + + gralloc1_buffer_descriptor_t desc; + Error error = createDescriptor(descriptorInfo, &desc); + if (error != Error::NONE) { + hidl_cb(error, 0, hidl_vec()); + return Void(); + } + + uint32_t stride = 0; + std::vector buffers; + buffers.reserve(count); + + // allocate the buffers + for (uint32_t i = 0; i < count; i++) { + buffer_handle_t tmpBuffer; + uint32_t tmpStride; + error = allocateOne(desc, &tmpBuffer, &tmpStride); + if (error != Error::NONE) { + break; + } + + if (stride == 0) { + stride = tmpStride; + } else if (stride != tmpStride) { + // non-uniform strides + mDispatch.release(mDevice, tmpBuffer); + stride = 0; + error = Error::UNSUPPORTED; + break; + } + + buffers.emplace_back(hidl_handle(tmpBuffer)); + } + + mDispatch.destroyDescriptor(mDevice, desc); + + // return the buffers + hidl_vec hidl_buffers; + if (error == Error::NONE) { + hidl_buffers.setToExternal(buffers.data(), buffers.size()); + } + hidl_cb(error, stride, hidl_buffers); + + // free the buffers + for (const auto& buffer : buffers) { + mDispatch.release(mDevice, buffer.getNativeHandle()); + } + + return Void(); +} + +Error Gralloc1Allocator::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 Gralloc1Allocator::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 Gralloc1Allocator::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 Gralloc1Allocator::createDescriptor( + const 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; + } + } + uint64_t producerUsage = 0; + uint64_t consumerUsage = 0; + + android_convertGralloc0To1Usage(static_cast(info.usage), + &producerUsage, &consumerUsage); + + if (error == GRALLOC1_ERROR_NONE) { + error = mDispatch.setProducerUsage(mDevice, descriptor, + producerUsage); + } + if (error == GRALLOC1_ERROR_NONE) { + error = mDispatch.setConsumerUsage(mDevice, descriptor, + consumerUsage); + } + + if (error == GRALLOC1_ERROR_NONE) { + *outDescriptor = descriptor; + } else { + mDispatch.destroyDescriptor(mDevice, descriptor); + } + + return toError(error); +} + +Error Gralloc1Allocator::allocateOne(gralloc1_buffer_descriptor_t descriptor, + buffer_handle_t* outBuffer, + uint32_t* outStride) { + buffer_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 implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/exynos4/interfaces/gralloc/Gralloc1Allocator.h b/exynos4/interfaces/gralloc/Gralloc1Allocator.h new file mode 100644 index 0000000..7b5a966 --- /dev/null +++ b/exynos4/interfaces/gralloc/Gralloc1Allocator.h @@ -0,0 +1,89 @@ +/* + * 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_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H +#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H + +#include +#include +#include + +namespace android { +namespace hardware { +namespace graphics { +namespace allocator { +namespace V2_0 { +namespace implementation { + +using android::hardware::graphics::mapper::V2_0::IMapper; +using android::hardware::graphics::mapper::V2_0::BufferDescriptor; +using android::hardware::graphics::mapper::V2_0::Error; + +class Gralloc1Allocator : public IAllocator { + public: + Gralloc1Allocator(const hw_module_t* module); + virtual ~Gralloc1Allocator(); + + // IAllocator interface + Return dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; + Return allocate(const BufferDescriptor& descriptor, uint32_t count, + allocate_cb hidl_cb) override; + + private: + void initCapabilities(); + + template + void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn); + void initDispatch(); + + static Error toError(int32_t error); + static uint64_t toProducerUsage(uint64_t usage); + static uint64_t toConsumerUsage(uint64_t usage); + + Error createDescriptor(const IMapper::BufferDescriptorInfo& info, + gralloc1_buffer_descriptor_t* outDescriptor); + Error allocateOne(gralloc1_buffer_descriptor_t descriptor, + buffer_handle_t* outBuffer, uint32_t* outStride); + + gralloc1_device_t* mDevice; + + struct { + bool layeredBuffers; + } mCapabilities; + + struct { + GRALLOC1_PFN_DUMP dump; + GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor; + GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor; + GRALLOC1_PFN_SET_DIMENSIONS setDimensions; + GRALLOC1_PFN_SET_FORMAT setFormat; + GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount; + GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage; + GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage; + GRALLOC1_PFN_GET_STRIDE getStride; + GRALLOC1_PFN_ALLOCATE allocate; + GRALLOC1_PFN_RELEASE release; + } mDispatch; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace allocator +} // namespace graphics +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H diff --git a/exynos4/interfaces/gralloc/Gralloc1On0Adapter.cpp b/exynos4/interfaces/gralloc/Gralloc1On0Adapter.cpp new file mode 100644 index 0000000..d53a50c --- /dev/null +++ b/exynos4/interfaces/gralloc/Gralloc1On0Adapter.cpp @@ -0,0 +1,560 @@ +/* + * 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. + */ + +#undef LOG_TAG +#define LOG_TAG "Gralloc1On0Adapter" +//#define LOG_NDEBUG 0 + +#include "Gralloc1On0Adapter.h" +#include "gralloc1-adapter.h" + +#include + +#include + +#include +#include + +#include + +template +static gralloc1_function_pointer_t asFP(T function) +{ + static_assert(std::is_same::value, "Incompatible function pointer"); + return reinterpret_cast(function); +} + +namespace android { +namespace hardware { + +Gralloc1On0Adapter::Gralloc1On0Adapter(const hw_module_t* module) + : gralloc1_device_t(), + mModule(reinterpret_cast(module)), + mDevice(nullptr) +{ + ALOGV("Constructing"); + + int minor = 0; + mModule->perform(mModule, + GRALLOC1_ADAPTER_PERFORM_GET_REAL_MODULE_API_VERSION_MINOR, + &minor); + mMinorVersion = minor; + + common.tag = HARDWARE_DEVICE_TAG, + common.version = HARDWARE_DEVICE_API_VERSION(0, 0), + common.module = const_cast(module), + common.close = closeHook, + + getCapabilities = getCapabilitiesHook; + getFunction = getFunctionHook; + int error = ::gralloc_open(&(mModule->common), &mDevice); + if (error) { + ALOGE("Failed to open gralloc0 module: %d", error); + } + ALOGV("Opened gralloc0 device %p", mDevice); +} + +Gralloc1On0Adapter::~Gralloc1On0Adapter() +{ + ALOGV("Destructing"); + if (mDevice) { + ALOGV("Closing gralloc0 device %p", mDevice); + ::gralloc_close(mDevice); + } +} + +void Gralloc1On0Adapter::doGetCapabilities(uint32_t* outCount, + int32_t* /*outCapabilities*/) { + *outCount = 0; +} + +gralloc1_function_pointer_t Gralloc1On0Adapter::doGetFunction( + int32_t intDescriptor) +{ + constexpr auto lastDescriptor = + static_cast(GRALLOC1_LAST_FUNCTION); + if (intDescriptor < 0 || intDescriptor > lastDescriptor) { + ALOGE("Invalid function descriptor"); + return nullptr; + } + + auto descriptor = + static_cast(intDescriptor); + switch (descriptor) { + case GRALLOC1_FUNCTION_DUMP: + return asFP(dumpHook); + case GRALLOC1_FUNCTION_CREATE_DESCRIPTOR: + return asFP(createDescriptorHook); + case GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR: + return asFP(destroyDescriptorHook); + case GRALLOC1_FUNCTION_SET_CONSUMER_USAGE: + return asFP(setConsumerUsageHook); + case GRALLOC1_FUNCTION_SET_DIMENSIONS: + return asFP(setDimensionsHook); + case GRALLOC1_FUNCTION_SET_FORMAT: + return asFP(setFormatHook); + case GRALLOC1_FUNCTION_SET_LAYER_COUNT: + return asFP(setLayerCountHook); + case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE: + return asFP(setProducerUsageHook); + case GRALLOC1_FUNCTION_GET_BACKING_STORE: + return asFP( + bufferHook); + case GRALLOC1_FUNCTION_GET_CONSUMER_USAGE: + return asFP(getConsumerUsageHook); + case GRALLOC1_FUNCTION_GET_DIMENSIONS: + return asFP( + bufferHook); + case GRALLOC1_FUNCTION_GET_FORMAT: + return asFP( + bufferHook); + case GRALLOC1_FUNCTION_GET_LAYER_COUNT: + return asFP( + bufferHook); + case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE: + return asFP(getProducerUsageHook); + case GRALLOC1_FUNCTION_GET_STRIDE: + return asFP( + bufferHook); + case GRALLOC1_FUNCTION_ALLOCATE: + if (mDevice != nullptr) { + return asFP(allocateHook); + } else { + return nullptr; + } + case GRALLOC1_FUNCTION_RETAIN: + return asFP(retainHook); + case GRALLOC1_FUNCTION_RELEASE: + return asFP(releaseHook); + case GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES: + return asFP( + bufferHook); + case GRALLOC1_FUNCTION_LOCK: + return asFP( + lockHook); + case GRALLOC1_FUNCTION_LOCK_FLEX: + return asFP( + lockHook); + case GRALLOC1_FUNCTION_UNLOCK: + return asFP(unlockHook); + case GRALLOC1_FUNCTION_INVALID: + ALOGE("Invalid function descriptor"); + return nullptr; + } + + ALOGE("Unknown function descriptor: %d", intDescriptor); + return nullptr; +} + +void Gralloc1On0Adapter::dump(uint32_t* outSize, char* outBuffer) +{ + ALOGV("dump(%u (%p), %p", outSize ? *outSize : 0, outSize, outBuffer); + + if (!mDevice->dump) { + // dump is optional on gralloc0 implementations + *outSize = 0; + return; + } + + if (!outBuffer) { + constexpr int32_t BUFFER_LENGTH = 4096; + char buffer[BUFFER_LENGTH] = {}; + mDevice->dump(mDevice, buffer, BUFFER_LENGTH); + buffer[BUFFER_LENGTH - 1] = 0; // Ensure the buffer is null-terminated + size_t actualLength = std::strlen(buffer); + mCachedDump.resize(actualLength); + std::copy_n(buffer, actualLength, mCachedDump.begin()); + *outSize = static_cast(actualLength); + } else { + *outSize = std::min(*outSize, + static_cast(mCachedDump.size())); + outBuffer = std::copy_n(mCachedDump.cbegin(), *outSize, outBuffer); + } +} + +gralloc1_error_t Gralloc1On0Adapter::createDescriptor( + gralloc1_buffer_descriptor_t* outDescriptor) +{ + auto descriptorId = sNextBufferDescriptorId++; + std::lock_guard lock(mDescriptorMutex); + mDescriptors.emplace(descriptorId, std::make_shared()); + + ALOGV("Created descriptor %" PRIu64, descriptorId); + + *outDescriptor = descriptorId; + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::destroyDescriptor( + gralloc1_buffer_descriptor_t descriptor) +{ + ALOGV("Destroying descriptor %" PRIu64, descriptor); + + std::lock_guard lock(mDescriptorMutex); + if (mDescriptors.count(descriptor) == 0) { + return GRALLOC1_ERROR_BAD_DESCRIPTOR; + } + + mDescriptors.erase(descriptor); + return GRALLOC1_ERROR_NONE; +} + +Gralloc1On0Adapter::Buffer::Buffer(buffer_handle_t handle, + gralloc1_backing_store_t store, const Descriptor& descriptor, + uint32_t stride, uint32_t /* numFlexPlanes */, bool wasAllocated) + : mHandle(handle), + mReferenceCount(1), + mStore(store), + mDescriptor(descriptor), + mStride(stride), + mWasAllocated(wasAllocated) {} + +gralloc1_error_t Gralloc1On0Adapter::allocate( + gralloc1_buffer_descriptor_t id, + const std::shared_ptr& descriptor, + buffer_handle_t* outBufferHandle) +{ + ALOGV("allocate(%" PRIu64 ")", id); + + // If this function is being called, it's because we handed out its function + // pointer, which only occurs when mDevice has been loaded successfully and + // we are permitted to allocate + + int usage = android_convertGralloc1To0Usage( + descriptor->producerUsage, descriptor->consumerUsage); + buffer_handle_t handle = nullptr; + int stride = 0; + ALOGV("Calling alloc(%p, %u, %u, %i, %u)", mDevice, descriptor->width, + descriptor->height, descriptor->format, usage); + auto error = mDevice->alloc(mDevice, + static_cast(descriptor->width), + static_cast(descriptor->height), descriptor->format, + usage, &handle, &stride); + if (error != 0) { + ALOGE("gralloc0 allocation failed: %d (%s)", error, + strerror(-error)); + return GRALLOC1_ERROR_NO_RESOURCES; + } + + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_SET_USAGES, + handle, + static_cast(descriptor->producerUsage), + static_cast(descriptor->consumerUsage)); + + uint64_t backingStore = 0; + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_BACKING_STORE, + handle, &backingStore); + int numFlexPlanes = 0; + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_NUM_FLEX_PLANES, + handle, &numFlexPlanes); + + *outBufferHandle = handle; + auto buffer = std::make_shared(handle, backingStore, + *descriptor, stride, numFlexPlanes, true); + + std::lock_guard lock(mBufferMutex); + mBuffers.emplace(handle, std::move(buffer)); + + return GRALLOC1_ERROR_NONE; +} + +int32_t Gralloc1On0Adapter::allocateHook(gralloc1_device* device, + uint32_t numDescriptors, + const gralloc1_buffer_descriptor_t* descriptors, + buffer_handle_t* outBuffers) +{ + if (!outBuffers) { + return GRALLOC1_ERROR_UNDEFINED; + } + + auto adapter = getAdapter(device); + + gralloc1_error_t error = GRALLOC1_ERROR_NONE; + uint32_t i; + for (i = 0; i < numDescriptors; i++) { + auto descriptor = adapter->getDescriptor(descriptors[i]); + if (!descriptor) { + error = GRALLOC1_ERROR_BAD_DESCRIPTOR; + break; + } + + buffer_handle_t bufferHandle = nullptr; + error = adapter->allocate(descriptors[i], descriptor, &bufferHandle); + if (error != GRALLOC1_ERROR_NONE) { + break; + } + + outBuffers[i] = bufferHandle; + } + + if (error == GRALLOC1_ERROR_NONE) { + if (numDescriptors > 1) { + error = GRALLOC1_ERROR_NOT_SHARED; + } + } else { + for (uint32_t j = 0; j < i; j++) { + adapter->release(adapter->getBuffer(outBuffers[j])); + outBuffers[j] = nullptr; + } + } + + return error; +} + +gralloc1_error_t Gralloc1On0Adapter::retain( + const std::shared_ptr& buffer) +{ + std::lock_guard lock(mBufferMutex); + buffer->retain(); + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::release( + const std::shared_ptr& buffer) +{ + std::lock_guard lock(mBufferMutex); + if (!buffer->release()) { + return GRALLOC1_ERROR_NONE; + } + + buffer_handle_t handle = buffer->getHandle(); + if (buffer->wasAllocated()) { + ALOGV("Calling free(%p)", handle); + int result = mDevice->free(mDevice, handle); + if (result != 0) { + ALOGE("gralloc0 free failed: %d", result); + } + } else { + ALOGV("Calling unregisterBuffer(%p)", handle); + int result = mModule->unregisterBuffer(mModule, handle); + if (result != 0) { + ALOGE("gralloc0 unregister failed: %d", result); + } + } + + mBuffers.erase(handle); + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::retain(buffer_handle_t bufferHandle) +{ + ALOGV("retain(%p)", bufferHandle); + + std::lock_guard lock(mBufferMutex); + + if (mBuffers.count(bufferHandle) != 0) { + mBuffers[bufferHandle]->retain(); + return GRALLOC1_ERROR_NONE; + } + + ALOGV("Calling registerBuffer(%p)", bufferHandle); + int result = mModule->registerBuffer(mModule, bufferHandle); + if (result != 0) { + ALOGE("gralloc0 register failed: %d", result); + return GRALLOC1_ERROR_NO_RESOURCES; + } + + uint64_t backingStore = 0; + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_BACKING_STORE, + bufferHandle, &backingStore); + + int numFlexPlanes = 0; + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_NUM_FLEX_PLANES, + bufferHandle, &numFlexPlanes); + + int stride = 0; + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_STRIDE, + bufferHandle, &stride); + + int width = 0; + int height = 0; + int format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; + int producerUsage = 0; + int consumerUsage = 0; + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_DIMENSIONS, + bufferHandle, &width, &height); + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_FORMAT, + bufferHandle, &format); + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_PRODUCER_USAGE, + bufferHandle, &producerUsage); + mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_CONSUMER_USAGE, + bufferHandle, &consumerUsage); + + Descriptor descriptor; + descriptor.setDimensions(width, height); + descriptor.setFormat(format); + descriptor.setProducerUsage( + static_cast(producerUsage)); + descriptor.setConsumerUsage( + static_cast(consumerUsage)); + + auto buffer = std::make_shared(bufferHandle, backingStore, + descriptor, stride, numFlexPlanes, false); + mBuffers.emplace(bufferHandle, std::move(buffer)); + return GRALLOC1_ERROR_NONE; +} + +static void syncWaitForever(int fd, const char* logname) +{ + if (fd < 0) { + return; + } + + const int warningTimeout = 3500; + const int error = sync_wait(fd, warningTimeout); + if (error < 0 && errno == ETIME) { + ALOGE("%s: fence %d didn't signal in %u ms", logname, fd, + warningTimeout); + sync_wait(fd, -1); + } +} + +gralloc1_error_t Gralloc1On0Adapter::lock( + const std::shared_ptr& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, void** outData, + int acquireFence) +{ + if (mMinorVersion >= 3) { + int result = mModule->lockAsync(mModule, buffer->getHandle(), + android_convertGralloc1To0Usage(producerUsage, consumerUsage), + accessRegion.left, accessRegion.top, accessRegion.width, + accessRegion.height, outData, acquireFence); + if (result != 0) { + return GRALLOC1_ERROR_UNSUPPORTED; + } + } else { + syncWaitForever(acquireFence, "Gralloc1On0Adapter::lock"); + + int result = mModule->lock(mModule, buffer->getHandle(), + android_convertGralloc1To0Usage(producerUsage, consumerUsage), + accessRegion.left, accessRegion.top, accessRegion.width, + accessRegion.height, outData); + ALOGV("gralloc0 lock returned %d", result); + if (result != 0) { + return GRALLOC1_ERROR_UNSUPPORTED; + } else if (acquireFence >= 0) { + close(acquireFence); + } + } + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::lockFlex( + const std::shared_ptr& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, + struct android_flex_layout* outFlex, + int acquireFence) +{ + if (mMinorVersion >= 3) { + int result = mModule->perform(mModule, + GRALLOC1_ADAPTER_PERFORM_LOCK_FLEX, + buffer->getHandle(), + static_cast(producerUsage), + static_cast(consumerUsage), + accessRegion.left, + accessRegion.top, + accessRegion.width, + accessRegion.height, + outFlex, acquireFence); + if (result != 0) { + return GRALLOC1_ERROR_UNSUPPORTED; + } + } else { + syncWaitForever(acquireFence, "Gralloc1On0Adapter::lockFlex"); + + int result = mModule->perform(mModule, + GRALLOC1_ADAPTER_PERFORM_LOCK_FLEX, + buffer->getHandle(), + static_cast(producerUsage), + static_cast(consumerUsage), + accessRegion.left, + accessRegion.top, + accessRegion.width, + accessRegion.height, + outFlex, -1); + if (result != 0) { + return GRALLOC1_ERROR_UNSUPPORTED; + } else if (acquireFence >= 0) { + close(acquireFence); + } + } + + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::unlock( + const std::shared_ptr& buffer, + int* outReleaseFence) +{ + if (mMinorVersion >= 3) { + int fenceFd = -1; + int result = mModule->unlockAsync(mModule, buffer->getHandle(), + &fenceFd); + if (result != 0) { + close(fenceFd); + ALOGE("gralloc0 unlockAsync failed: %d", result); + } else { + *outReleaseFence = fenceFd; + } + } else { + int result = mModule->unlock(mModule, buffer->getHandle()); + if (result != 0) { + ALOGE("gralloc0 unlock failed: %d", result); + } else { + *outReleaseFence = -1; + } + } + return GRALLOC1_ERROR_NONE; +} + +std::shared_ptr +Gralloc1On0Adapter::getDescriptor(gralloc1_buffer_descriptor_t descriptorId) +{ + std::lock_guard lock(mDescriptorMutex); + if (mDescriptors.count(descriptorId) == 0) { + return nullptr; + } + + return mDescriptors[descriptorId]; +} + +std::shared_ptr Gralloc1On0Adapter::getBuffer( + buffer_handle_t bufferHandle) +{ + std::lock_guard lock(mBufferMutex); + if (mBuffers.count(bufferHandle) == 0) { + return nullptr; + } + + return mBuffers[bufferHandle]; +} + +std::atomic + Gralloc1On0Adapter::sNextBufferDescriptorId(1); + +} // namespace hardware +} // namespace android diff --git a/exynos4/interfaces/gralloc/Gralloc1On0Adapter.h b/exynos4/interfaces/gralloc/Gralloc1On0Adapter.h new file mode 100644 index 0000000..3900e46 --- /dev/null +++ b/exynos4/interfaces/gralloc/Gralloc1On0Adapter.h @@ -0,0 +1,456 @@ +/* + * 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_GRALLOC_1_ON_0_ADAPTER_H +#define ANDROID_HARDWARE_GRALLOC_1_ON_0_ADAPTER_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +struct gralloc_module_t; +struct alloc_device_t; + +namespace android { +namespace hardware { + +class Gralloc1On0Adapter : public gralloc1_device_t +{ +public: + Gralloc1On0Adapter(const hw_module_t* module); + ~Gralloc1On0Adapter(); + + gralloc1_device_t* getDevice() { + return static_cast(this); + } + +private: + static inline Gralloc1On0Adapter* getAdapter(gralloc1_device_t* device) { + return static_cast(device); + } + + static int closeHook(struct hw_device_t* device) { + delete getAdapter(reinterpret_cast(device)); + return 0; + } + + // getCapabilities + + void doGetCapabilities(uint32_t* outCount, + int32_t* /*gralloc1_capability_t*/ outCapabilities); + static void getCapabilitiesHook(gralloc1_device_t* device, + uint32_t* outCount, + int32_t* /*gralloc1_capability_t*/ outCapabilities) { + getAdapter(device)->doGetCapabilities(outCount, outCapabilities); + } + + // getFunction + + gralloc1_function_pointer_t doGetFunction( + int32_t /*gralloc1_function_descriptor_t*/ descriptor); + static gralloc1_function_pointer_t getFunctionHook( + gralloc1_device_t* device, + int32_t /*gralloc1_function_descriptor_t*/ descriptor) { + return getAdapter(device)->doGetFunction(descriptor); + } + + // dump + + void dump(uint32_t* outSize, char* outBuffer); + static void dumpHook(gralloc1_device_t* device, uint32_t* outSize, + char* outBuffer) { + return getAdapter(device)->dump(outSize, outBuffer); + } + std::string mCachedDump; + + // Buffer descriptor lifecycle functions + + struct Descriptor; + + gralloc1_error_t createDescriptor( + gralloc1_buffer_descriptor_t* outDescriptor); + static int32_t createDescriptorHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t* outDescriptor) { + auto error = getAdapter(device)->createDescriptor(outDescriptor); + return static_cast(error); + } + + gralloc1_error_t destroyDescriptor(gralloc1_buffer_descriptor_t descriptor); + static int32_t destroyDescriptorHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptor) { + auto error = getAdapter(device)->destroyDescriptor(descriptor); + return static_cast(error); + } + + // Buffer descriptor modification functions + + struct Descriptor : public std::enable_shared_from_this { + Descriptor() + : width(0), + height(0), + format(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), + layerCount(1), + producerUsage(GRALLOC1_PRODUCER_USAGE_NONE), + consumerUsage(GRALLOC1_CONSUMER_USAGE_NONE) {} + + gralloc1_error_t setDimensions(uint32_t w, uint32_t h) { + width = w; + height = h; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t setFormat(int32_t f) { + format = f; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t setLayerCount(uint32_t lc) { + layerCount = lc; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t setProducerUsage(gralloc1_producer_usage_t usage) { + producerUsage = usage; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t setConsumerUsage(gralloc1_consumer_usage_t usage) { + consumerUsage = usage; + return GRALLOC1_ERROR_NONE; + } + + uint32_t width; + uint32_t height; + int32_t format; + uint32_t layerCount; + gralloc1_producer_usage_t producerUsage; + gralloc1_consumer_usage_t consumerUsage; + }; + + template + static int32_t callDescriptorFunction(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, + gralloc1_error_t (Descriptor::*member)(Args...), Args... args) { + auto descriptor = getAdapter(device)->getDescriptor(descriptorId); + if (!descriptor) { + return static_cast(GRALLOC1_ERROR_BAD_DESCRIPTOR); + } + auto error = ((*descriptor).*member)(std::forward(args)...); + return static_cast(error); + } + + static int32_t setConsumerUsageHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) { + auto usage = static_cast(intUsage); + return callDescriptorFunction(device, descriptorId, + &Descriptor::setConsumerUsage, usage); + } + + static int32_t setDimensionsHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, uint32_t width, + uint32_t height) { + return callDescriptorFunction(device, descriptorId, + &Descriptor::setDimensions, width, height); + } + + static int32_t setFormatHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, int32_t format) { + return callDescriptorFunction(device, descriptorId, + &Descriptor::setFormat, format); + } + + static int32_t setLayerCountHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, uint32_t layerCount) { + return callDescriptorFunction(device, descriptorId, + &Descriptor::setLayerCount, layerCount); + } + + static int32_t setProducerUsageHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) { + auto usage = static_cast(intUsage); + return callDescriptorFunction(device, descriptorId, + &Descriptor::setProducerUsage, usage); + } + + // Buffer handle query functions + class Buffer { + public: + Buffer(buffer_handle_t handle, gralloc1_backing_store_t store, + const Descriptor& descriptor, uint32_t stride, + uint32_t numFlexPlanes, bool wasAllocated); + + buffer_handle_t getHandle() const { return mHandle; } + + void retain() { ++mReferenceCount; } + + // Returns true if the reference count has dropped to 0, indicating that + // the buffer needs to be released + bool release() { return --mReferenceCount == 0; } + + bool wasAllocated() const { return mWasAllocated; } + + gralloc1_error_t getBackingStore( + gralloc1_backing_store_t* outStore) const { + *outStore = mStore; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t getConsumerUsage( + gralloc1_consumer_usage_t* outUsage) const { + *outUsage = mDescriptor.consumerUsage; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t getDimensions(uint32_t* outWidth, + uint32_t* outHeight) const { + *outWidth = mDescriptor.width; + *outHeight = mDescriptor.height; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t getFormat(int32_t* outFormat) const { + *outFormat = mDescriptor.format; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t getLayerCount(uint32_t* outLayerCount) const { + *outLayerCount = mDescriptor.layerCount; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t getNumFlexPlanes(uint32_t* outNumPlanes) const { + *outNumPlanes = 4; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t getProducerUsage( + gralloc1_producer_usage_t* outUsage) const { + *outUsage = mDescriptor.producerUsage; + return GRALLOC1_ERROR_NONE; + } + + gralloc1_error_t getStride(uint32_t* outStride) const { + *outStride = mStride; + return GRALLOC1_ERROR_NONE; + } + + private: + + const buffer_handle_t mHandle; + size_t mReferenceCount; + + const gralloc1_backing_store_t mStore; + const Descriptor mDescriptor; + const uint32_t mStride; + + // Whether this buffer allocated in this process (as opposed to just + // being retained here), which determines whether to free or unregister + // the buffer when this Buffer is released + const bool mWasAllocated; + }; + + template + static int32_t callBufferFunction(gralloc1_device_t* device, + buffer_handle_t bufferHandle, + gralloc1_error_t (Buffer::*member)(Args...) const, Args... args) { + auto buffer = getAdapter(device)->getBuffer(bufferHandle); + if (!buffer) { + return static_cast(GRALLOC1_ERROR_BAD_HANDLE); + } + auto error = ((*buffer).*member)(std::forward(args)...); + return static_cast(error); + } + + template + static int32_t bufferHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle, Args... args) { + return Gralloc1On0Adapter::callBufferFunction(device, bufferHandle, + memFunc, std::forward(args)...); + } + + static int32_t getConsumerUsageHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle, uint64_t* outUsage) { + auto usage = GRALLOC1_CONSUMER_USAGE_NONE; + auto error = callBufferFunction(device, bufferHandle, + &Buffer::getConsumerUsage, &usage); + if (error == GRALLOC1_ERROR_NONE) { + *outUsage = static_cast(usage); + } + return error; + } + + static int32_t getProducerUsageHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle, uint64_t* outUsage) { + auto usage = GRALLOC1_PRODUCER_USAGE_NONE; + auto error = callBufferFunction(device, bufferHandle, + &Buffer::getProducerUsage, &usage); + if (error == GRALLOC1_ERROR_NONE) { + *outUsage = static_cast(usage); + } + return error; + } + + // Buffer management functions + + gralloc1_error_t allocate( + gralloc1_buffer_descriptor_t id, + const std::shared_ptr& descriptor, + buffer_handle_t* outBufferHandle); + static int32_t allocateHook(gralloc1_device* device, + uint32_t numDescriptors, + const gralloc1_buffer_descriptor_t* descriptors, + buffer_handle_t* outBuffers); + + gralloc1_error_t retain(const std::shared_ptr& buffer); + gralloc1_error_t retain(buffer_handle_t bufferHandle); + static int32_t retainHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle) + { + auto adapter = getAdapter(device); + return adapter->retain(bufferHandle); + } + + gralloc1_error_t release(const std::shared_ptr& buffer); + static int32_t releaseHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle) { + auto adapter = getAdapter(device); + + auto buffer = adapter->getBuffer(bufferHandle); + if (!buffer) { + return static_cast(GRALLOC1_ERROR_BAD_HANDLE); + } + + auto error = adapter->release(buffer); + return static_cast(error); + } + + // Buffer access functions + + gralloc1_error_t lock(const std::shared_ptr& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, void** outData, + int acquireFence); + gralloc1_error_t lockFlex(const std::shared_ptr& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, + struct android_flex_layout* outFlex, + int acquireFence); + + template &, gralloc1_producer_usage_t, + gralloc1_consumer_usage_t, const gralloc1_rect_t&, OUT*, + int)> + static int32_t lockHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle, + uint64_t /*gralloc1_producer_usage_t*/ uintProducerUsage, + uint64_t /*gralloc1_consumer_usage_t*/ uintConsumerUsage, + const gralloc1_rect_t* accessRegion, OUT* outData, + int32_t acquireFenceFd) { + auto adapter = getAdapter(device); + + // Exactly one of producer and consumer usage must be *_USAGE_NONE, + // but we can't check this until the upper levels of the framework + // correctly distinguish between producer and consumer usage + /* + bool hasProducerUsage = + uintProducerUsage != GRALLOC1_PRODUCER_USAGE_NONE; + bool hasConsumerUsage = + uintConsumerUsage != GRALLOC1_CONSUMER_USAGE_NONE; + if (hasProducerUsage && hasConsumerUsage || + !hasProducerUsage && !hasConsumerUsage) { + return static_cast(GRALLOC1_ERROR_BAD_VALUE); + } + */ + + auto producerUsage = + static_cast(uintProducerUsage); + auto consumerUsage = + static_cast(uintConsumerUsage); + + if (!outData) { + const auto producerCpuUsage = GRALLOC1_PRODUCER_USAGE_CPU_READ | + GRALLOC1_PRODUCER_USAGE_CPU_WRITE; + if ((producerUsage & producerCpuUsage) != 0) { + return static_cast(GRALLOC1_ERROR_BAD_VALUE); + } + if ((consumerUsage & GRALLOC1_CONSUMER_USAGE_CPU_READ) != 0) { + return static_cast(GRALLOC1_ERROR_BAD_VALUE); + } + } + + auto buffer = adapter->getBuffer(bufferHandle); + if (!buffer) { + return static_cast(GRALLOC1_ERROR_BAD_HANDLE); + } + + if (!accessRegion) { + ALOGE("accessRegion is null"); + return static_cast(GRALLOC1_ERROR_BAD_VALUE); + } + + auto error = ((*adapter).*member)(buffer, producerUsage, consumerUsage, + *accessRegion, outData, acquireFenceFd); + return static_cast(error); + } + + gralloc1_error_t unlock(const std::shared_ptr& buffer, + int* outReleaseFence); + static int32_t unlockHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle, int32_t* outReleaseFenceFd) { + auto adapter = getAdapter(device); + + auto buffer = adapter->getBuffer(bufferHandle); + if (!buffer) { + return static_cast(GRALLOC1_ERROR_BAD_HANDLE); + } + + int releaseFence = -1; + auto error = adapter->unlock(buffer, &releaseFence); + if (error == GRALLOC1_ERROR_NONE) { + *outReleaseFenceFd = releaseFence; + } + return static_cast(error); + } + + // Adapter internals + const gralloc_module_t* mModule; + uint8_t mMinorVersion; + alloc_device_t* mDevice; + + std::shared_ptr getDescriptor( + gralloc1_buffer_descriptor_t descriptorId); + std::shared_ptr getBuffer(buffer_handle_t bufferHandle); + + static std::atomic sNextBufferDescriptorId; + std::mutex mDescriptorMutex; + std::unordered_map> mDescriptors; + std::mutex mBufferMutex; + std::unordered_map> mBuffers; +}; + +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GRALLOC_1_ON_0_ADAPTER_H diff --git a/exynos4/interfaces/gralloc/gralloc1-adapter.cpp b/exynos4/interfaces/gralloc/gralloc1-adapter.cpp new file mode 100644 index 0000000..fcc59cd --- /dev/null +++ b/exynos4/interfaces/gralloc/gralloc1-adapter.cpp @@ -0,0 +1,32 @@ +/* + * 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 "Gralloc1On0Adapter.h" +#include "gralloc1-adapter.h" + +int gralloc1_adapter_device_open(const struct hw_module_t* module, + const char* id, struct hw_device_t** device) +{ + if (strcmp(id, GRALLOC_HARDWARE_MODULE_ID) != 0) { + ALOGE("unknown gralloc1 device id: %s", id); + return -EINVAL; + } + + auto adapter_device = new android::hardware::Gralloc1On0Adapter(module); + *device = &adapter_device->common; + + return 0; +} diff --git a/exynos4/interfaces/gralloc/gralloc1-adapter.h b/exynos4/interfaces/gralloc/gralloc1-adapter.h new file mode 100644 index 0000000..b912ef6 --- /dev/null +++ b/exynos4/interfaces/gralloc/gralloc1-adapter.h @@ -0,0 +1,89 @@ +/* + * 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_GRALLOC1_ADAPTER_H +#define ANDROID_HARDWARE_GRALLOC1_ADAPTER_H + +#include + +__BEGIN_DECLS + +#define GRALLOC1_ADAPTER_MODULE_API_VERSION_1_0 \ + HARDWARE_MODULE_API_VERSION(1, 0) + +enum { + GRALLOC1_ADAPTER_PERFORM_FIRST = 10000, + + // void getRealModuleApiVersionMinor(..., int* outMinorVersion); + GRALLOC1_ADAPTER_PERFORM_GET_REAL_MODULE_API_VERSION_MINOR = + GRALLOC1_ADAPTER_PERFORM_FIRST, + + // void setUsages(..., buffer_handle_t buffer, + // int producerUsage, + // int consumerUsage); + GRALLOC1_ADAPTER_PERFORM_SET_USAGES = + GRALLOC1_ADAPTER_PERFORM_FIRST + 1, + + // void getDimensions(..., buffer_handle_t buffer, + // int* outWidth, + // int* outHeight); + GRALLOC1_ADAPTER_PERFORM_GET_DIMENSIONS = + GRALLOC1_ADAPTER_PERFORM_FIRST + 2, + + // void getFormat(..., buffer_handle_t buffer, int* outFormat); + GRALLOC1_ADAPTER_PERFORM_GET_FORMAT = + GRALLOC1_ADAPTER_PERFORM_FIRST + 3, + + // void getProducerUsage(..., buffer_handle_t buffer, int* outUsage); + GRALLOC1_ADAPTER_PERFORM_GET_PRODUCER_USAGE = + GRALLOC1_ADAPTER_PERFORM_FIRST + 4, + + // void getConsumerUsage(..., buffer_handle_t buffer, int* outUsage); + GRALLOC1_ADAPTER_PERFORM_GET_CONSUMER_USAGE = + GRALLOC1_ADAPTER_PERFORM_FIRST + 5, + + // void getBackingStore(..., buffer_handle_t buffer, + // uint64_t* outBackingStore); + GRALLOC1_ADAPTER_PERFORM_GET_BACKING_STORE = + GRALLOC1_ADAPTER_PERFORM_FIRST + 6, + + // void getNumFlexPlanes(..., buffer_handle_t buffer, + // int* outNumFlexPlanes); + GRALLOC1_ADAPTER_PERFORM_GET_NUM_FLEX_PLANES = + GRALLOC1_ADAPTER_PERFORM_FIRST + 7, + + // void getStride(..., buffer_handle_t buffer, int* outStride); + GRALLOC1_ADAPTER_PERFORM_GET_STRIDE = + GRALLOC1_ADAPTER_PERFORM_FIRST + 8, + + // void lockFlex(..., buffer_handle_t buffer, + // int producerUsage, + // int consumerUsage, + // int left, + // int top, + // int width, + // int height, + // android_flex_layout* outLayout, + // int acquireFence); + GRALLOC1_ADAPTER_PERFORM_LOCK_FLEX = + GRALLOC1_ADAPTER_PERFORM_FIRST + 9, +}; + +int gralloc1_adapter_device_open(const struct hw_module_t* module, + const char* id, struct hw_device_t** device); + +__END_DECLS + +#endif /* ANDROID_HARDWARE_GRALLOC1_ADAPTER_H */