graphics: make allocator passthrough library header-only
android.hardware.graphics.allocator@2.0-passthrough should be a
header-only library to be fully reusable by vendor HALs.
This also allows us to switch from virtual inheritance to templates,
which is more straightforward. This changes nothing to the users
and we still have these relations
- AllocatorHal is an abstract class to be implemented by vendors or
the default implementations
- Gralloc[01]Hal are our default implementations
- Allocator implements HIDL IAllocator interface on top of
AllocatorHal
What we do not like about virtual inheritance is that, given
// abstract class B and D
class B {
virtual void foo() = 0;
virtual void bar() = 0;
};
class D : public virtual B {
// foo is superceded by fooEnhanced in D
void foo() { fooEnhanced(); }
virtual void fooEnhanced() = 0;
};
// an implementation of B
class BImpl : public virtual B {
void foo() {}
void bar() {}
};
// an implementation of D on top of BImpl
class DImpl : public virtual D, public virtual BImpl {
void fooEnhanced() {}
};
we get "no unique final overrider" becase both D and BImpl implement
foo. With non-virtual inheritance, on the other hand, we get "DImpl
is abstract" because foo is still pure virtual implemented in DImpl.
Templates solve the issue by allowing
namespace detail{
template<typename T>
class BImpl : public T { ... };
template<typename T>
class DImpl : public BImpl<T> { ... };
} // namespace detail
using BImpl = detail::BImpl<B>;
using DImpl = detail::DImpl<D>;
Test: boots
Change-Id: Iccb513e4fc751e9a687a1ed2d9fb2192c8324a50
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index ed2ecbb..9980ae0 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -4,11 +4,8 @@
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 @@
"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 2f3022e..8ca8200 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 @@
namespace detail {
-// AllocatorImpl implements IAllocator on top of AllocatorHal
-template <typename IALLOCATOR, typename ALLOCATOR_HAL>
-class AllocatorImpl : public IALLOCATOR {
+// AllocatorImpl implements V2_*::IAllocator on top of V2_*::hal::AllocatorHal
+template <typename Interface, typename Hal>
+class AllocatorImpl : public Interface {
public:
- bool init(std::unique_ptr<ALLOCATOR_HAL> hal) {
+ bool init(std::unique_ptr<Hal> hal) {
mHal = std::move(hal);
return true;
}
@@ -74,7 +74,7 @@
}
protected:
- std::unique_ptr<ALLOCATOR_HAL> mHal;
+ std::unique_ptr<Hal> mHal;
};
} // namespace detail
diff --git a/graphics/allocator/2.0/utils/passthrough/Android.bp b/graphics/allocator/2.0/utils/passthrough/Android.bp
index b956565..ff9280a 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",
@@ -23,7 +18,7 @@
],
export_header_lib_headers: [
"android.hardware.graphics.allocator@2.0-hal",
+ "libgrallocmapperincludes",
],
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 8edb7dc..0000000
--- 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 <allocator-passthrough/2.0/Gralloc0Hal.h>
-
-#include <string.h>
-
-#include <GrallocBufferDescriptor.h>
-#include <hardware/gralloc.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
-
-Gralloc0Hal::~Gralloc0Hal() {
- if (mDevice) {
- gralloc_close(mDevice);
- }
-}
-
-bool Gralloc0Hal::initWithModule(const hw_module_t* module) {
- int result = gralloc_open(module, &mDevice);
- if (result) {
- ALOGE("failed to open gralloc0 device: %s", strerror(-result));
- mDevice = nullptr;
- return false;
- }
-
- return true;
-}
-
-std::string Gralloc0Hal::dumpDebugInfo() {
- char buf[4096] = {};
- if (mDevice->dump) {
- mDevice->dump(mDevice, buf, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- }
-
- return buf;
-}
-
-Error Gralloc0Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
- uint32_t* outStride,
- std::vector<const native_handle_t*>* outBuffers) {
- mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
- if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
- return Error::BAD_DESCRIPTOR;
- }
-
- Error error = Error::NONE;
- uint32_t stride = 0;
- std::vector<const native_handle_t*> buffers;
- buffers.reserve(count);
-
- // allocate the buffers
- for (uint32_t i = 0; i < count; i++) {
- const native_handle_t* tmpBuffer;
- uint32_t tmpStride;
- error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
- if (error != Error::NONE) {
- break;
- }
-
- buffers.push_back(tmpBuffer);
-
- if (stride == 0) {
- stride = tmpStride;
- } else if (stride != tmpStride) {
- // non-uniform strides
- error = Error::UNSUPPORTED;
- break;
- }
- }
-
- if (error != Error::NONE) {
- freeBuffers(buffers);
- return error;
- }
-
- *outStride = stride;
- *outBuffers = std::move(buffers);
-
- return Error::NONE;
-}
-
-void Gralloc0Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
- for (auto buffer : buffers) {
- int result = mDevice->free(mDevice, buffer);
- if (result != 0) {
- ALOGE("failed to free buffer %p: %d", buffer, result);
- }
- }
-}
-
-Error Gralloc0Hal::allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
- const native_handle_t** outBuffer, uint32_t* outStride) {
- if (info.layerCount > 1 || (info.usage >> 32) != 0) {
- return Error::BAD_VALUE;
- }
-
- const native_handle_t* buffer = nullptr;
- int stride = 0;
- int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
- info.usage, &buffer, &stride);
- switch (result) {
- case 0:
- *outBuffer = buffer;
- *outStride = stride;
- return Error::NONE;
- case -EINVAL:
- return Error::BAD_VALUE;
- default:
- return Error::NO_RESOURCES;
- }
-}
-
-} // namespace passthrough
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
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 e343ecd..0000000
--- 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 <allocator-passthrough/2.0/Gralloc1Hal.h>
-
-#include <string.h>
-
-#include <GrallocBufferDescriptor.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
-
-Gralloc1Hal::~Gralloc1Hal() {
- if (mDevice) {
- gralloc1_close(mDevice);
- }
-}
-
-bool Gralloc1Hal::initWithModule(const hw_module_t* module) {
- int result = gralloc1_open(module, &mDevice);
- if (result) {
- ALOGE("failed to open gralloc1 device: %s", strerror(-result));
- mDevice = nullptr;
- return false;
- }
-
- initCapabilities();
- if (!initDispatch()) {
- gralloc1_close(mDevice);
- mDevice = nullptr;
- return false;
- }
-
- return true;
-}
-
-void Gralloc1Hal::initCapabilities() {
- uint32_t count = 0;
- mDevice->getCapabilities(mDevice, &count, nullptr);
-
- std::vector<int32_t> capabilities(count);
- mDevice->getCapabilities(mDevice, &count, capabilities.data());
- capabilities.resize(count);
-
- for (auto capability : capabilities) {
- if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
- mCapabilities.layeredBuffers = true;
- break;
- }
- }
-}
-
-gralloc1_function_pointer_t Gralloc1Hal::getDispatchFunction(
- gralloc1_function_descriptor_t desc) const {
- auto pfn = mDevice->getFunction(mDevice, desc);
- if (!pfn) {
- ALOGE("failed to get gralloc1 function %d", desc);
- return nullptr;
- }
- return pfn;
-}
-
-bool Gralloc1Hal::initDispatch() {
- if (!initDispatchFunction(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
- !initDispatchFunction(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
- return false;
- }
-
- if (mCapabilities.layeredBuffers) {
- if (!initDispatchFunction(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
- return false;
- }
- }
-
- return true;
-}
-
-std::string Gralloc1Hal::dumpDebugInfo() {
- uint32_t len = 0;
- mDispatch.dump(mDevice, &len, nullptr);
-
- std::vector<char> buf(len + 1);
- mDispatch.dump(mDevice, &len, buf.data());
- buf.resize(len + 1);
- buf[len] = '\0';
-
- return buf.data();
-}
-
-Error Gralloc1Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
- uint32_t* outStride,
- std::vector<const native_handle_t*>* outBuffers) {
- mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
- if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
- return Error::BAD_DESCRIPTOR;
- }
-
- gralloc1_buffer_descriptor_t desc;
- Error error = createDescriptor(descriptorInfo, &desc);
- if (error != Error::NONE) {
- return error;
- }
-
- uint32_t stride = 0;
- std::vector<const native_handle_t*> buffers;
- buffers.reserve(count);
-
- // allocate the buffers
- for (uint32_t i = 0; i < count; i++) {
- const native_handle_t* tmpBuffer;
- uint32_t tmpStride;
- error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
- if (error != Error::NONE) {
- break;
- }
-
- buffers.push_back(tmpBuffer);
-
- if (stride == 0) {
- stride = tmpStride;
- } else if (stride != tmpStride) {
- // non-uniform strides
- error = Error::UNSUPPORTED;
- break;
- }
- }
-
- mDispatch.destroyDescriptor(mDevice, desc);
-
- if (error != Error::NONE) {
- freeBuffers(buffers);
- return error;
- }
-
- *outStride = stride;
- *outBuffers = std::move(buffers);
-
- return Error::NONE;
-}
-
-void Gralloc1Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
- for (auto buffer : buffers) {
- int32_t error = mDispatch.release(mDevice, buffer);
- if (error != GRALLOC1_ERROR_NONE) {
- ALOGE("failed to free buffer %p: %d", buffer, error);
- }
- }
-}
-
-Error Gralloc1Hal::toError(int32_t error) {
- switch (error) {
- case GRALLOC1_ERROR_NONE:
- return Error::NONE;
- case GRALLOC1_ERROR_BAD_DESCRIPTOR:
- return Error::BAD_DESCRIPTOR;
- case GRALLOC1_ERROR_BAD_HANDLE:
- return Error::BAD_BUFFER;
- case GRALLOC1_ERROR_BAD_VALUE:
- return Error::BAD_VALUE;
- case GRALLOC1_ERROR_NOT_SHARED:
- return Error::NONE; // this is fine
- case GRALLOC1_ERROR_NO_RESOURCES:
- return Error::NO_RESOURCES;
- case GRALLOC1_ERROR_UNDEFINED:
- case GRALLOC1_ERROR_UNSUPPORTED:
- default:
- return Error::UNSUPPORTED;
- }
-}
-
-uint64_t Gralloc1Hal::toProducerUsage(uint64_t usage) {
- // this is potentially broken as we have no idea which private flags
- // should be filtered out
- uint64_t producerUsage =
- usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
- BufferUsage::GPU_DATA_BUFFER);
-
- switch (usage & BufferUsage::CPU_WRITE_MASK) {
- case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
- producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
- break;
- case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
- producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
- break;
- default:
- break;
- }
-
- switch (usage & BufferUsage::CPU_READ_MASK) {
- case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
- producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
- break;
- case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
- producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
- break;
- default:
- break;
- }
-
- // BufferUsage::GPU_DATA_BUFFER is always filtered out
-
- return producerUsage;
-}
-
-uint64_t Gralloc1Hal::toConsumerUsage(uint64_t usage) {
- // this is potentially broken as we have no idea which private flags
- // should be filtered out
- uint64_t consumerUsage =
- usage &
- ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
- BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
-
- switch (usage & BufferUsage::CPU_READ_MASK) {
- case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
- consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
- break;
- case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
- consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
- break;
- default:
- break;
- }
-
- // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
-
- if (usage & BufferUsage::GPU_DATA_BUFFER) {
- consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
- }
-
- return consumerUsage;
-}
-
-Error Gralloc1Hal::createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
- gralloc1_buffer_descriptor_t* outDescriptor) {
- gralloc1_buffer_descriptor_t descriptor;
-
- int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
-
- if (error == GRALLOC1_ERROR_NONE) {
- error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
- }
- if (error == GRALLOC1_ERROR_NONE) {
- error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
- }
- if (error == GRALLOC1_ERROR_NONE) {
- if (mCapabilities.layeredBuffers) {
- error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
- } else if (info.layerCount > 1) {
- error = GRALLOC1_ERROR_UNSUPPORTED;
- }
- }
- if (error == GRALLOC1_ERROR_NONE) {
- error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
- }
- if (error == GRALLOC1_ERROR_NONE) {
- error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
- }
-
- if (error == GRALLOC1_ERROR_NONE) {
- *outDescriptor = descriptor;
- } else {
- mDispatch.destroyDescriptor(mDevice, descriptor);
- }
-
- return toError(error);
-}
-
-Error Gralloc1Hal::allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
- const native_handle_t** outBuffer, uint32_t* outStride) {
- const native_handle_t* buffer = nullptr;
- int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
- if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
- return toError(error);
- }
-
- uint32_t stride = 0;
- error = mDispatch.getStride(mDevice, buffer, &stride);
- if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
- mDispatch.release(mDevice, buffer);
- return toError(error);
- }
-
- *outBuffer = buffer;
- *outStride = stride;
-
- return Error::NONE;
-}
-
-} // namespace passthrough
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
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 dae7a78..0000000
--- 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 <allocator-passthrough/2.0/GrallocLoader.h>
-
-#include <allocator-hal/2.0/Allocator.h>
-#include <allocator-hal/2.0/AllocatorHal.h>
-#include <allocator-passthrough/2.0/Gralloc0Hal.h>
-#include <allocator-passthrough/2.0/Gralloc1Hal.h>
-#include <hardware/gralloc.h>
-#include <hardware/hardware.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-const hw_module_t* GrallocLoader::loadModule() {
- const hw_module_t* module;
- int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
- if (error) {
- ALOGE("failed to get gralloc module");
- return nullptr;
- }
-
- return module;
-}
-
-int GrallocLoader::getModuleMajorApiVersion(const hw_module_t* module) {
- return (module->module_api_version >> 8) & 0xff;
-}
-
-std::unique_ptr<hal::AllocatorHal> GrallocLoader::createHal(const hw_module_t* module) {
- int major = getModuleMajorApiVersion(module);
- switch (major) {
- case 1: {
- auto hal = std::make_unique<Gralloc1Hal>();
- return hal->initWithModule(module) ? std::move(hal) : nullptr;
- }
- case 0: {
- auto hal = std::make_unique<Gralloc0Hal>();
- return hal->initWithModule(module) ? std::move(hal) : nullptr;
- }
- default:
- ALOGE("unknown gralloc module major version %d", major);
- return nullptr;
- }
-}
-
-IAllocator* GrallocLoader::createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
- auto allocator = std::make_unique<hal::Allocator>();
- return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
-}
-
-} // namespace passthrough
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
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 8f433b0..2665b40 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 <allocator-hal/2.0/AllocatorHal.h>
+#ifndef LOG_TAG
+#warning "Gralloc0Hal.h included without LOG_TAG"
+#endif
-struct alloc_device_t;
-struct hw_module_t;
+#include <cstring> // for strerror
+
+#include <GrallocBufferDescriptor.h>
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -28,28 +34,125 @@
namespace V2_0 {
namespace passthrough {
+namespace detail {
+
using mapper::V2_0::BufferDescriptor;
using mapper::V2_0::Error;
+using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
-class Gralloc0Hal : public virtual hal::AllocatorHal {
+// Gralloc0HalImpl implements V2_*::hal::AllocatorHal on top of gralloc0
+template <typename Hal>
+class Gralloc0HalImpl : public Hal {
public:
- ~Gralloc0Hal();
- bool initWithModule(const hw_module_t* module);
+ ~Gralloc0HalImpl() {
+ if (mDevice) {
+ gralloc_close(mDevice);
+ }
+ }
- std::string dumpDebugInfo() override;
+ bool initWithModule(const hw_module_t* module) {
+ int result = gralloc_open(module, &mDevice);
+ if (result) {
+ ALOGE("failed to open gralloc0 device: %s", strerror(-result));
+ mDevice = nullptr;
+ return false;
+ }
+
+ return true;
+ }
+
+ std::string dumpDebugInfo() override {
+ char buf[4096] = {};
+ if (mDevice->dump) {
+ mDevice->dump(mDevice, buf, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ }
+
+ return buf;
+ }
Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
- std::vector<const native_handle_t*>* outBuffers) override;
+ std::vector<const native_handle_t*>* outBuffers) override {
+ mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+ if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+ return Error::BAD_DESCRIPTOR;
+ }
- void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+ Error error = Error::NONE;
+ uint32_t stride = 0;
+ std::vector<const native_handle_t*> buffers;
+ buffers.reserve(count);
+
+ // allocate the buffers
+ for (uint32_t i = 0; i < count; i++) {
+ const native_handle_t* tmpBuffer;
+ uint32_t tmpStride;
+ error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
+ if (error != Error::NONE) {
+ break;
+ }
+
+ buffers.push_back(tmpBuffer);
+
+ if (stride == 0) {
+ stride = tmpStride;
+ } else if (stride != tmpStride) {
+ // non-uniform strides
+ error = Error::UNSUPPORTED;
+ break;
+ }
+ }
+
+ if (error != Error::NONE) {
+ freeBuffers(buffers);
+ return error;
+ }
+
+ *outStride = stride;
+ *outBuffers = std::move(buffers);
+
+ return Error::NONE;
+ }
+
+ void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
+ for (auto buffer : buffers) {
+ int result = mDevice->free(mDevice, buffer);
+ if (result != 0) {
+ ALOGE("failed to free buffer %p: %d", buffer, result);
+ }
+ }
+ }
protected:
Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
- const native_handle_t** outBuffer, uint32_t* outStride);
+ const native_handle_t** outBuffer, uint32_t* outStride) {
+ if (info.layerCount > 1 || (info.usage >> 32) != 0) {
+ return Error::BAD_VALUE;
+ }
+
+ const native_handle_t* buffer = nullptr;
+ int stride = 0;
+ int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
+ info.usage, &buffer, &stride);
+ switch (result) {
+ case 0:
+ *outBuffer = buffer;
+ *outStride = stride;
+ return Error::NONE;
+ case -EINVAL:
+ return Error::BAD_VALUE;
+ default:
+ return Error::NO_RESOURCES;
+ }
+ }
alloc_device_t* mDevice = nullptr;
};
+} // namespace detail
+
+using Gralloc0Hal = detail::Gralloc0HalImpl<hal::AllocatorHal>;
+
} // namespace passthrough
} // namespace V2_0
} // namespace allocator
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 3126e91..3979f0d 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 <cstring> // for strerror
+
+#include <GrallocBufferDescriptor.h>
#include <allocator-hal/2.0/AllocatorHal.h>
#include <hardware/gralloc1.h>
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -26,46 +34,302 @@
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::implementation::grallocDecodeBufferDescriptor;
-class Gralloc1Hal : public virtual hal::AllocatorHal {
+// Gralloc1HalImpl implements V2_*::hal::AllocatorHal on top of gralloc1
+template <typename Hal>
+class Gralloc1HalImpl : public Hal {
public:
- ~Gralloc1Hal();
- bool initWithModule(const hw_module_t* module);
+ ~Gralloc1HalImpl() {
+ if (mDevice) {
+ gralloc1_close(mDevice);
+ }
+ }
- std::string dumpDebugInfo() override;
+ bool initWithModule(const hw_module_t* module) {
+ int result = gralloc1_open(module, &mDevice);
+ if (result) {
+ ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+ mDevice = nullptr;
+ return false;
+ }
+
+ initCapabilities();
+ if (!initDispatch()) {
+ gralloc1_close(mDevice);
+ mDevice = nullptr;
+ return false;
+ }
+
+ return true;
+ }
+
+ std::string dumpDebugInfo() override {
+ uint32_t len = 0;
+ mDispatch.dump(mDevice, &len, nullptr);
+
+ std::vector<char> buf(len + 1);
+ mDispatch.dump(mDevice, &len, buf.data());
+ buf.resize(len + 1);
+ buf[len] = '\0';
+
+ return buf.data();
+ }
Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
- std::vector<const native_handle_t*>* outBuffers) override;
+ std::vector<const native_handle_t*>* outBuffers) override {
+ mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+ if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+ return Error::BAD_DESCRIPTOR;
+ }
- void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+ gralloc1_buffer_descriptor_t desc;
+ Error error = createDescriptor(descriptorInfo, &desc);
+ if (error != Error::NONE) {
+ return error;
+ }
+
+ uint32_t stride = 0;
+ std::vector<const native_handle_t*> buffers;
+ buffers.reserve(count);
+
+ // allocate the buffers
+ for (uint32_t i = 0; i < count; i++) {
+ const native_handle_t* tmpBuffer;
+ uint32_t tmpStride;
+ error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
+ if (error != Error::NONE) {
+ break;
+ }
+
+ buffers.push_back(tmpBuffer);
+
+ if (stride == 0) {
+ stride = tmpStride;
+ } else if (stride != tmpStride) {
+ // non-uniform strides
+ error = Error::UNSUPPORTED;
+ break;
+ }
+ }
+
+ mDispatch.destroyDescriptor(mDevice, desc);
+
+ if (error != Error::NONE) {
+ freeBuffers(buffers);
+ return error;
+ }
+
+ *outStride = stride;
+ *outBuffers = std::move(buffers);
+
+ return Error::NONE;
+ }
+
+ void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
+ for (auto buffer : buffers) {
+ int32_t error = mDispatch.release(mDevice, buffer);
+ if (error != GRALLOC1_ERROR_NONE) {
+ ALOGE("failed to free buffer %p: %d", buffer, error);
+ }
+ }
+ }
protected:
+ virtual void initCapabilities() {
+ uint32_t count = 0;
+ mDevice->getCapabilities(mDevice, &count, nullptr);
+
+ std::vector<int32_t> capabilities(count);
+ mDevice->getCapabilities(mDevice, &count, capabilities.data());
+ capabilities.resize(count);
+
+ for (auto capability : capabilities) {
+ if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
+ mCapabilities.layeredBuffers = true;
+ break;
+ }
+ }
+ }
+
template <typename T>
- bool initDispatchFunction(gralloc1_function_descriptor_t desc, T* outPfn) {
- auto pfn = getDispatchFunction(desc);
+ bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
+ auto pfn = mDevice->getFunction(mDevice, desc);
if (pfn) {
*outPfn = reinterpret_cast<T>(pfn);
return true;
} else {
+ ALOGE("failed to get gralloc1 function %d", desc);
return false;
}
}
- gralloc1_function_pointer_t getDispatchFunction(gralloc1_function_descriptor_t desc) const;
- virtual void initCapabilities();
- virtual bool initDispatch();
+ virtual bool initDispatch() {
+ if (!initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
+ !initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
+ !initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
+ !initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
+ !initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
+ !initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
+ !initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
+ !initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
+ !initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
+ !initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
+ return false;
+ }
- static Error toError(int32_t error);
- static uint64_t toProducerUsage(uint64_t usage);
- static uint64_t toConsumerUsage(uint64_t usage);
+ if (mCapabilities.layeredBuffers) {
+ if (!initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static Error toError(int32_t error) {
+ switch (error) {
+ case GRALLOC1_ERROR_NONE:
+ return Error::NONE;
+ case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+ return Error::BAD_DESCRIPTOR;
+ case GRALLOC1_ERROR_BAD_HANDLE:
+ return Error::BAD_BUFFER;
+ case GRALLOC1_ERROR_BAD_VALUE:
+ return Error::BAD_VALUE;
+ case GRALLOC1_ERROR_NOT_SHARED:
+ return Error::NONE; // this is fine
+ case GRALLOC1_ERROR_NO_RESOURCES:
+ return Error::NO_RESOURCES;
+ case GRALLOC1_ERROR_UNDEFINED:
+ case GRALLOC1_ERROR_UNSUPPORTED:
+ default:
+ return Error::UNSUPPORTED;
+ }
+ }
+
+ static uint64_t toProducerUsage(uint64_t usage) {
+ // this is potentially broken as we have no idea which private flags
+ // should be filtered out
+ uint64_t producerUsage = usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
+ BufferUsage::CPU_WRITE_MASK |
+ BufferUsage::GPU_DATA_BUFFER);
+
+ switch (usage & BufferUsage::CPU_WRITE_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ switch (usage & BufferUsage::CPU_READ_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ // BufferUsage::GPU_DATA_BUFFER is always filtered out
+
+ return producerUsage;
+ }
+
+ static uint64_t toConsumerUsage(uint64_t usage) {
+ // this is potentially broken as we have no idea which private flags
+ // should be filtered out
+ uint64_t consumerUsage =
+ usage &
+ ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+ BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
+
+ switch (usage & BufferUsage::CPU_READ_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+ consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+ consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
+
+ if (usage & BufferUsage::GPU_DATA_BUFFER) {
+ consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
+ }
+
+ return consumerUsage;
+ }
Error createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
- gralloc1_buffer_descriptor_t* outDescriptor);
+ gralloc1_buffer_descriptor_t* outDescriptor) {
+ gralloc1_buffer_descriptor_t descriptor;
+
+ int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
+
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ if (mCapabilities.layeredBuffers) {
+ error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
+ } else if (info.layerCount > 1) {
+ error = GRALLOC1_ERROR_UNSUPPORTED;
+ }
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
+ }
+
+ if (error == GRALLOC1_ERROR_NONE) {
+ *outDescriptor = descriptor;
+ } else {
+ mDispatch.destroyDescriptor(mDevice, descriptor);
+ }
+
+ return toError(error);
+ }
Error allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
- const native_handle_t** outBuffer, uint32_t* outStride);
+ const native_handle_t** outBuffer, uint32_t* outStride) {
+ const native_handle_t* buffer = nullptr;
+ int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
+ if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
+ return toError(error);
+ }
+
+ uint32_t stride = 0;
+ error = mDispatch.getStride(mDevice, buffer, &stride);
+ if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
+ mDispatch.release(mDevice, buffer);
+ return toError(error);
+ }
+
+ *outBuffer = buffer;
+ *outStride = stride;
+
+ return Error::NONE;
+ }
gralloc1_device_t* mDevice = nullptr;
@@ -88,6 +352,10 @@
} mDispatch = {};
};
+} // namespace detail
+
+using Gralloc1Hal = detail::Gralloc1HalImpl<hal::AllocatorHal>;
+
} // 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 a0b9503..660099b 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 <memory>
-#include <allocator-hal/2.0/AllocatorHal.h>
-
-struct hw_module_t;
+#include <allocator-hal/2.0/Allocator.h>
+#include <allocator-passthrough/2.0/Gralloc0Hal.h>
+#include <allocator-passthrough/2.0/Gralloc1Hal.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -44,16 +51,45 @@
}
// load the gralloc module
- static const hw_module_t* loadModule();
+ static const hw_module_t* loadModule() {
+ const hw_module_t* module;
+ int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+ if (error) {
+ ALOGE("failed to get gralloc module");
+ return nullptr;
+ }
+
+ return module;
+ }
// return the major api version of the module
- static int getModuleMajorApiVersion(const hw_module_t* module);
+ static int getModuleMajorApiVersion(const hw_module_t* module) {
+ return (module->module_api_version >> 8) & 0xff;
+ }
// create an AllocatorHal instance
- static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module);
+ static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module) {
+ int major = getModuleMajorApiVersion(module);
+ switch (major) {
+ case 1: {
+ auto hal = std::make_unique<Gralloc1Hal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+ case 0: {
+ auto hal = std::make_unique<Gralloc0Hal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+ default:
+ ALOGE("unknown gralloc module major version %d", major);
+ return nullptr;
+ }
+ }
// create an IAllocator instance
- static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal);
+ static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
+ auto allocator = std::make_unique<hal::Allocator>();
+ return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
+ }
};
} // namespace passthrough