diff options
author | 2016-01-11 15:21:07 -0800 | |
---|---|---|
committer | 2016-06-13 13:29:16 -0700 | |
commit | 1e2a2a0ee81401072d9fc0f842c7ec1a915c5a07 (patch) | |
tree | 835daa55e93d7192b12cdeeb81368a864d4155fc | |
parent | 75e6dde051bd382869cdb74052a09264a00a0209 (diff) |
libui: Add Gralloc1On0Adapter
Adds an adapter which provides the gralloc1 interface on top of a
gralloc 0.x device.
Bug: 28401203
Change-Id: I0eeafc998b56e2e2fc39de6fad41e3ed2e19658a
-rw-r--r-- | include/ui/Gralloc1On0Adapter.h | 478 | ||||
-rw-r--r-- | libs/ui/Android.mk | 3 | ||||
-rw-r--r-- | libs/ui/Gralloc1On0Adapter.cpp | 469 |
3 files changed, 949 insertions, 1 deletions
diff --git a/include/ui/Gralloc1On0Adapter.h b/include/ui/Gralloc1On0Adapter.h new file mode 100644 index 0000000000..edcfb65e91 --- /dev/null +++ b/include/ui/Gralloc1On0Adapter.h @@ -0,0 +1,478 @@ +/* + * 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_UI_GRALLOC_1_ON_0_ADAPTER_H +#define ANDROID_UI_GRALLOC_1_ON_0_ADAPTER_H + +#include <ui/Fence.h> +#include <ui/GraphicBuffer.h> + +#include <hardware/gralloc1.h> + +#include <string> +#include <unordered_map> +#include <vector> + +struct gralloc_module_t; + +// This is not an "official" capability (i.e., it is not found in gralloc1.h), +// but we will use it to detect that we are running through the adapter, which +// is capable of collaborating with GraphicBuffer such that queries on a +// buffer_handle_t succeed +static const auto GRALLOC1_CAPABILITY_ON_ADAPTER = + static_cast<gralloc1_capability_t>(GRALLOC1_LAST_CAPABILITY + 1); + +static const auto GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER = + static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 1); +static const auto GRALLOC1_FUNCTION_ALLOCATE_WITH_ID = + static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 2); +static const auto GRALLOC1_FUNCTION_LOCK_YCBCR = + static_cast<gralloc1_function_descriptor_t>(GRALLOC1_LAST_FUNCTION + 3); +static const auto GRALLOC1_LAST_ADAPTER_FUNCTION = GRALLOC1_FUNCTION_LOCK_YCBCR; + +typedef gralloc1_error_t (*GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER)( + gralloc1_device_t* device, const android::GraphicBuffer* buffer); +typedef gralloc1_error_t (*GRALLOC1_PFN_ALLOCATE_WITH_ID)( + gralloc1_device_t* device, gralloc1_buffer_descriptor_t descriptor, + gralloc1_backing_store_t id, buffer_handle_t* outBuffer); +typedef int32_t /*gralloc1_error_t*/ (*GRALLOC1_PFN_LOCK_YCBCR)( + gralloc1_device_t* device, buffer_handle_t buffer, + uint64_t /*gralloc1_producer_usage_t*/ producerUsage, + uint64_t /*gralloc1_consumer_usage_t*/ consumerUsage, + const gralloc1_rect_t* accessRegion, struct android_ycbcr* outYCbCr, + int32_t acquireFence); + +namespace android { + +class Gralloc1On0Adapter : public gralloc1_device_t +{ +public: + Gralloc1On0Adapter(const hw_module_t* module); + ~Gralloc1On0Adapter(); + + gralloc1_device_t* getDevice() { + return static_cast<gralloc1_device_t*>(this); + } + +private: + static inline Gralloc1On0Adapter* getAdapter(gralloc1_device_t* device) { + return static_cast<Gralloc1On0Adapter*>(device); + } + + // 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 + + class 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<int32_t>(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<int32_t>(error); + } + + // Buffer descriptor modification functions + + struct Descriptor : public std::enable_shared_from_this<Descriptor> { + Descriptor(Gralloc1On0Adapter* adapter, + gralloc1_buffer_descriptor_t id) + : adapter(adapter), + id(id), + width(0), + height(0), + format(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), + 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 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; + } + + Gralloc1On0Adapter* const adapter; + const gralloc1_buffer_descriptor_t id; + + uint32_t width; + uint32_t height; + int32_t format; + gralloc1_producer_usage_t producerUsage; + gralloc1_consumer_usage_t consumerUsage; + }; + + template <typename ...Args> + 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<int32_t>(GRALLOC1_ERROR_BAD_DESCRIPTOR); + } + auto error = ((*descriptor).*member)(std::forward<Args>(args)...); + return static_cast<int32_t>(error); + } + + static int32_t setConsumerUsageHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) { + auto usage = static_cast<gralloc1_consumer_usage_t>(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 setProducerUsageHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) { + auto usage = static_cast<gralloc1_producer_usage_t>(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, + 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 getNumFlexPlanes(uint32_t* outNumPlanes) const { + // TODO: This is conservative, and we could do better by examining + // the format, but it won't hurt anything for now + *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; + + // Since we're adapting to gralloc0, there will always be a 1:1 + // correspondence between buffer handles and backing stores, and the + // backing store ID will be the same as the GraphicBuffer unique ID + 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 <typename ...Args> + 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<int32_t>(GRALLOC1_ERROR_BAD_HANDLE); + } + auto error = ((*buffer).*member)(std::forward<Args>(args)...); + return static_cast<int32_t>(error); + } + + template <typename MF, MF memFunc, typename ...Args> + static int32_t bufferHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle, Args... args) { + return Gralloc1On0Adapter::callBufferFunction(device, bufferHandle, + memFunc, std::forward<Args>(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<uint64_t>(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<uint64_t>(usage); + } + return error; + } + + // Buffer management functions + + // We don't provide GRALLOC1_FUNCTION_ALLOCATE, since this should always be + // called through GRALLOC1_FUNCTION_ALLOCATE_WITH_ID + gralloc1_error_t allocate( + const std::shared_ptr<Descriptor>& descriptor, + gralloc1_backing_store_t id, + buffer_handle_t* outBufferHandle); + static gralloc1_error_t allocateWithIdHook(gralloc1_device_t* device, + gralloc1_buffer_descriptor_t descriptors, + gralloc1_backing_store_t id, buffer_handle_t* outBuffer); + + gralloc1_error_t retain(const std::shared_ptr<Buffer>& buffer); + gralloc1_error_t release(const std::shared_ptr<Buffer>& buffer); + + // Member function pointer 'member' will either be retain or release + template <gralloc1_error_t (Gralloc1On0Adapter::*member)( + const std::shared_ptr<Buffer>& buffer)> + static int32_t managementHook(gralloc1_device_t* device, + buffer_handle_t bufferHandle) { + auto adapter = getAdapter(device); + + auto buffer = adapter->getBuffer(bufferHandle); + if (!buffer) { + return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE); + } + + auto error = ((*adapter).*member)(buffer); + return static_cast<int32_t>(error); + } + + gralloc1_error_t retain(const GraphicBuffer* buffer); + static gralloc1_error_t retainGraphicBufferHook(gralloc1_device_t* device, + const GraphicBuffer* buffer) { + auto adapter = getAdapter(device); + return adapter->retain(buffer); + } + + // Buffer access functions + + gralloc1_error_t lock(const std::shared_ptr<Buffer>& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, void** outData, + const sp<Fence>& acquireFence); + gralloc1_error_t lockFlex(const std::shared_ptr<Buffer>& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, + struct android_flex_layout* outFlex, + const sp<Fence>& acquireFence); + gralloc1_error_t lockYCbCr(const std::shared_ptr<Buffer>& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, + struct android_ycbcr* outFlex, + const sp<Fence>& acquireFence); + + template <typename OUT, gralloc1_error_t (Gralloc1On0Adapter::*member)( + const std::shared_ptr<Buffer>&, gralloc1_producer_usage_t, + gralloc1_consumer_usage_t, const gralloc1_rect_t&, OUT*, + const sp<Fence>&)> + 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<int32_t>(GRALLOC1_ERROR_BAD_VALUE); + } + */ + + auto producerUsage = + static_cast<gralloc1_producer_usage_t>(uintProducerUsage); + auto consumerUsage = + static_cast<gralloc1_consumer_usage_t>(uintConsumerUsage); + + if (!outData) { + const auto producerCpuUsage = GRALLOC1_PRODUCER_USAGE_CPU_READ | + GRALLOC1_PRODUCER_USAGE_CPU_WRITE; + if (producerUsage & producerCpuUsage != 0) { + return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE); + } + if (consumerUsage & GRALLOC1_CONSUMER_USAGE_CPU_READ != 0) { + return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE); + } + } + + auto buffer = adapter->getBuffer(bufferHandle); + if (!buffer) { + return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE); + } + + if (!accessRegion) { + ALOGE("accessRegion is null"); + return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE); + } + + sp<Fence> acquireFence{new Fence(acquireFenceFd)}; + auto error = ((*adapter).*member)(buffer, producerUsage, consumerUsage, + *accessRegion, outData, acquireFence); + return static_cast<int32_t>(error); + } + + gralloc1_error_t unlock(const std::shared_ptr<Buffer>& buffer, + sp<Fence>* 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<int32_t>(GRALLOC1_ERROR_BAD_HANDLE); + } + + sp<Fence> releaseFence = Fence::NO_FENCE; + auto error = adapter->unlock(buffer, &releaseFence); + if (error == GRALLOC1_ERROR_NONE) { + *outReleaseFenceFd = releaseFence->dup(); + } + return static_cast<int32_t>(error); + } + + // Adapter internals + const gralloc_module_t* mModule; + uint8_t mMinorVersion; + alloc_device_t* mDevice; + + std::shared_ptr<Descriptor> getDescriptor( + gralloc1_buffer_descriptor_t descriptorId); + std::shared_ptr<Buffer> getBuffer(buffer_handle_t bufferHandle); + + static std::atomic<gralloc1_buffer_descriptor_t> sNextBufferDescriptorId; + std::unordered_map<gralloc1_buffer_descriptor_t, + std::shared_ptr<Descriptor>> mDescriptors; + std::unordered_map<buffer_handle_t, std::shared_ptr<Buffer>> mBuffers; +}; + +} // namespace android + +#endif diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk index ee6c093bcf..85ad36d5b8 100644 --- a/libs/ui/Android.mk +++ b/libs/ui/Android.mk @@ -17,7 +17,7 @@ include $(CLEAR_VARS) LOCAL_CLANG := true LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror -LOCAL_SANITIZE := integer +# LOCAL_SANITIZE := integer # The static constructors and destructors in this library have not been noted to # introduce significant overheads @@ -37,6 +37,7 @@ LOCAL_CPPFLAGS += -Wno-padded LOCAL_SRC_FILES := \ Fence.cpp \ FrameStats.cpp \ + Gralloc1On0Adapter.cpp \ GraphicBuffer.cpp \ GraphicBufferAllocator.cpp \ GraphicBufferMapper.cpp \ diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp new file mode 100644 index 0000000000..6e69df1621 --- /dev/null +++ b/libs/ui/Gralloc1On0Adapter.cpp @@ -0,0 +1,469 @@ +/* + * 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 <hardware/gralloc.h> + +#include <ui/Gralloc1On0Adapter.h> + +#include <utils/Log.h> + +#include <inttypes.h> + +template <typename PFN, typename T> +static gralloc1_function_pointer_t asFP(T function) +{ + static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer"); + return reinterpret_cast<gralloc1_function_pointer_t>(function); +} + +namespace android { + +Gralloc1On0Adapter::Gralloc1On0Adapter(const hw_module_t* module) + : mModule(reinterpret_cast<const gralloc_module_t*>(module)), + mMinorVersion(mModule->common.module_api_version & 0xFF), + mDevice(nullptr) +{ + ALOGV("Constructing"); + 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) +{ + if (outCapabilities == nullptr) { + *outCount = 1; + return; + } + if (*outCount >= 1) { + *outCapabilities = GRALLOC1_CAPABILITY_ON_ADAPTER; + *outCount = 1; + } +} + +gralloc1_function_pointer_t Gralloc1On0Adapter::doGetFunction( + int32_t intDescriptor) +{ + constexpr auto lastDescriptor = + static_cast<int32_t>(GRALLOC1_LAST_ADAPTER_FUNCTION); + if (intDescriptor < 0 || intDescriptor > lastDescriptor) { + ALOGE("Invalid function descriptor"); + return nullptr; + } + + auto descriptor = + static_cast<gralloc1_function_descriptor_t>(intDescriptor); + switch (descriptor) { + case GRALLOC1_FUNCTION_DUMP: + return asFP<GRALLOC1_PFN_DUMP>(dumpHook); + case GRALLOC1_FUNCTION_CREATE_DESCRIPTOR: + return asFP<GRALLOC1_PFN_CREATE_DESCRIPTOR>(createDescriptorHook); + case GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR: + return asFP<GRALLOC1_PFN_DESTROY_DESCRIPTOR>(destroyDescriptorHook); + case GRALLOC1_FUNCTION_SET_CONSUMER_USAGE: + return asFP<GRALLOC1_PFN_SET_CONSUMER_USAGE>(setConsumerUsageHook); + case GRALLOC1_FUNCTION_SET_DIMENSIONS: + return asFP<GRALLOC1_PFN_SET_DIMENSIONS>(setDimensionsHook); + case GRALLOC1_FUNCTION_SET_FORMAT: + return asFP<GRALLOC1_PFN_SET_FORMAT>(setFormatHook); + case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE: + return asFP<GRALLOC1_PFN_SET_PRODUCER_USAGE>(setProducerUsageHook); + case GRALLOC1_FUNCTION_GET_BACKING_STORE: + return asFP<GRALLOC1_PFN_GET_BACKING_STORE>( + bufferHook<decltype(&Buffer::getBackingStore), + &Buffer::getBackingStore, gralloc1_backing_store_t*>); + case GRALLOC1_FUNCTION_GET_CONSUMER_USAGE: + return asFP<GRALLOC1_PFN_GET_CONSUMER_USAGE>(getConsumerUsageHook); + case GRALLOC1_FUNCTION_GET_DIMENSIONS: + return asFP<GRALLOC1_PFN_GET_DIMENSIONS>( + bufferHook<decltype(&Buffer::getDimensions), + &Buffer::getDimensions, uint32_t*, uint32_t*>); + case GRALLOC1_FUNCTION_GET_FORMAT: + return asFP<GRALLOC1_PFN_GET_FORMAT>( + bufferHook<decltype(&Buffer::getFormat), + &Buffer::getFormat, int32_t*>); + case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE: + return asFP<GRALLOC1_PFN_GET_PRODUCER_USAGE>(getProducerUsageHook); + case GRALLOC1_FUNCTION_GET_STRIDE: + return asFP<GRALLOC1_PFN_GET_STRIDE>( + bufferHook<decltype(&Buffer::getStride), + &Buffer::getStride, uint32_t*>); + case GRALLOC1_FUNCTION_ALLOCATE: + // Not provided, since we'll use ALLOCATE_WITH_ID + return nullptr; + case GRALLOC1_FUNCTION_ALLOCATE_WITH_ID: + if (mDevice != nullptr) { + return asFP<GRALLOC1_PFN_ALLOCATE_WITH_ID>(allocateWithIdHook); + } else { + return nullptr; + } + case GRALLOC1_FUNCTION_RETAIN: + return asFP<GRALLOC1_PFN_RETAIN>( + managementHook<&Gralloc1On0Adapter::retain>); + case GRALLOC1_FUNCTION_RELEASE: + return asFP<GRALLOC1_PFN_RELEASE>( + managementHook<&Gralloc1On0Adapter::release>); + case GRALLOC1_FUNCTION_RETAIN_GRAPHIC_BUFFER: + return asFP<GRALLOC1_PFN_RETAIN_GRAPHIC_BUFFER>( + retainGraphicBufferHook); + case GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES: + return asFP<GRALLOC1_PFN_GET_NUM_FLEX_PLANES>( + bufferHook<decltype(&Buffer::getNumFlexPlanes), + &Buffer::getNumFlexPlanes, uint32_t*>); + case GRALLOC1_FUNCTION_LOCK: + return asFP<GRALLOC1_PFN_LOCK>( + lockHook<void*, &Gralloc1On0Adapter::lock>); + case GRALLOC1_FUNCTION_LOCK_FLEX: + return asFP<GRALLOC1_PFN_LOCK_FLEX>( + lockHook<struct android_flex_layout, + &Gralloc1On0Adapter::lockFlex>); + case GRALLOC1_FUNCTION_LOCK_YCBCR: + return asFP<GRALLOC1_PFN_LOCK_YCBCR>( + lockHook<struct android_ycbcr, + &Gralloc1On0Adapter::lockYCbCr>); + case GRALLOC1_FUNCTION_UNLOCK: + return asFP<GRALLOC1_PFN_UNLOCK>(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<uint32_t>(actualLength); + } else { + *outSize = std::min(*outSize, + static_cast<uint32_t>(mCachedDump.size())); + outBuffer = std::copy_n(mCachedDump.cbegin(), *outSize, outBuffer); + } +} + +gralloc1_error_t Gralloc1On0Adapter::createDescriptor( + gralloc1_buffer_descriptor_t* outDescriptor) +{ + auto descriptorId = sNextBufferDescriptorId++; + mDescriptors.emplace(descriptorId, + std::make_shared<Descriptor>(this, descriptorId)); + + 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); + + 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, bool wasAllocated) + : mHandle(handle), + mReferenceCount(1), + mStore(store), + mDescriptor(descriptor), + mStride(stride), + mWasAllocated(wasAllocated) {} + +gralloc1_error_t Gralloc1On0Adapter::allocate( + const std::shared_ptr<Descriptor>& descriptor, + gralloc1_backing_store_t store, + buffer_handle_t* outBufferHandle) +{ + ALOGV("allocate(%" PRIu64 ", %#" PRIx64 ")", descriptor->id, store); + + // 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 = static_cast<int>(descriptor->producerUsage) | + static_cast<int>(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<int>(descriptor->width), + static_cast<int>(descriptor->height), descriptor->format, + usage, &handle, &stride); + if (error != 0) { + ALOGE("gralloc0 allocation failed: %d (%s)", error, + strerror(-error)); + return GRALLOC1_ERROR_NO_RESOURCES; + } + + *outBufferHandle = handle; + auto buffer = std::make_shared<Buffer>(handle, store, *descriptor, stride, + true); + mBuffers.emplace(handle, std::move(buffer)); + + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::allocateWithIdHook( + gralloc1_device_t* device, gralloc1_buffer_descriptor_t descriptorId, + gralloc1_backing_store_t store, buffer_handle_t* outBuffer) +{ + auto adapter = getAdapter(device); + + auto descriptor = adapter->getDescriptor(descriptorId); + if (!descriptor) { + return GRALLOC1_ERROR_BAD_DESCRIPTOR; + } + + buffer_handle_t bufferHandle = nullptr; + auto error = adapter->allocate(descriptor, store, &bufferHandle); + if (error != GRALLOC1_ERROR_NONE) { + return error; + } + + *outBuffer = bufferHandle; + return error; +} + +gralloc1_error_t Gralloc1On0Adapter::retain( + const std::shared_ptr<Buffer>& buffer) +{ + buffer->retain(); + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::release( + const std::shared_ptr<Buffer>& buffer) +{ + 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( + const android::GraphicBuffer* graphicBuffer) +{ + ALOGV("retainGraphicBuffer(%p, %#" PRIx64 ")", + graphicBuffer->getNativeBuffer()->handle, graphicBuffer->getId()); + + buffer_handle_t handle = graphicBuffer->getNativeBuffer()->handle; + if (mBuffers.count(handle) != 0) { + mBuffers[handle]->retain(); + return GRALLOC1_ERROR_NONE; + } + + ALOGV("Calling registerBuffer(%p)", handle); + int result = mModule->registerBuffer(mModule, handle); + if (result != 0) { + ALOGE("gralloc0 register failed: %d", result); + return GRALLOC1_ERROR_NO_RESOURCES; + } + + Descriptor descriptor{this, sNextBufferDescriptorId++}; + descriptor.setDimensions(graphicBuffer->getWidth(), + graphicBuffer->getHeight()); + descriptor.setFormat(graphicBuffer->getPixelFormat()); + descriptor.setProducerUsage( + static_cast<gralloc1_producer_usage_t>(graphicBuffer->getUsage())); + descriptor.setConsumerUsage( + static_cast<gralloc1_consumer_usage_t>(graphicBuffer->getUsage())); + auto buffer = std::make_shared<Buffer>(handle, + static_cast<gralloc1_backing_store_t>(graphicBuffer->getId()), + descriptor, graphicBuffer->getStride(), false); + mBuffers.emplace(handle, std::move(buffer)); + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::lock( + const std::shared_ptr<Buffer>& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, void** outData, + const sp<Fence>& acquireFence) +{ + if (mMinorVersion >= 3) { + int result = mModule->lockAsync(mModule, buffer->getHandle(), + static_cast<int32_t>(producerUsage | consumerUsage), + accessRegion.left, accessRegion.top, accessRegion.width, + accessRegion.height, outData, acquireFence->dup()); + if (result != 0) { + return GRALLOC1_ERROR_UNSUPPORTED; + } + } else { + acquireFence->waitForever("Gralloc1On0Adapter::lock"); + int result = mModule->lock(mModule, buffer->getHandle(), + static_cast<int32_t>(producerUsage | consumerUsage), + accessRegion.left, accessRegion.top, accessRegion.width, + accessRegion.height, outData); + ALOGV("gralloc0 lock returned %d", result); + if (result != 0) { + return GRALLOC1_ERROR_UNSUPPORTED; + } + } + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::lockFlex( + const std::shared_ptr<Buffer>& /*buffer*/, + gralloc1_producer_usage_t /*producerUsage*/, + gralloc1_consumer_usage_t /*consumerUsage*/, + const gralloc1_rect_t& /*accessRegion*/, + struct android_flex_layout* /*outData*/, + const sp<Fence>& /*acquireFence*/) +{ + // TODO + return GRALLOC1_ERROR_UNSUPPORTED; +} + +gralloc1_error_t Gralloc1On0Adapter::lockYCbCr( + const std::shared_ptr<Buffer>& buffer, + gralloc1_producer_usage_t producerUsage, + gralloc1_consumer_usage_t consumerUsage, + const gralloc1_rect_t& accessRegion, struct android_ycbcr* outData, + const sp<Fence>& acquireFence) +{ + if (mMinorVersion >= 3 && mModule->lockAsync_ycbcr) { + int result = mModule->lockAsync_ycbcr(mModule, buffer->getHandle(), + static_cast<int>(producerUsage | consumerUsage), + accessRegion.left, accessRegion.top, accessRegion.width, + accessRegion.height, outData, acquireFence->dup()); + if (result != 0) { + return GRALLOC1_ERROR_UNSUPPORTED; + } + } else if (mModule->lock_ycbcr) { + acquireFence->waitForever("Gralloc1On0Adapter::lockYCbCr"); + int result = mModule->lock_ycbcr(mModule, buffer->getHandle(), + static_cast<int>(producerUsage | consumerUsage), + accessRegion.left, accessRegion.top, accessRegion.width, + accessRegion.height, outData); + ALOGV("gralloc0 lockYCbCr returned %d", result); + if (result != 0) { + return GRALLOC1_ERROR_UNSUPPORTED; + } + } else { + return GRALLOC1_ERROR_UNSUPPORTED; + } + + return GRALLOC1_ERROR_NONE; +} + +gralloc1_error_t Gralloc1On0Adapter::unlock( + const std::shared_ptr<Buffer>& buffer, + sp<Fence>* 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 = new Fence(fenceFd); + } + } else { + int result = mModule->unlock(mModule, buffer->getHandle()); + if (result != 0) { + ALOGE("gralloc0 unlock failed: %d", result); + } + } + return GRALLOC1_ERROR_NONE; +} + +std::shared_ptr<Gralloc1On0Adapter::Descriptor> +Gralloc1On0Adapter::getDescriptor(gralloc1_buffer_descriptor_t descriptorId) +{ + if (mDescriptors.count(descriptorId) == 0) { + return nullptr; + } + + return mDescriptors[descriptorId]; +} + +std::shared_ptr<Gralloc1On0Adapter::Buffer> Gralloc1On0Adapter::getBuffer( + buffer_handle_t bufferHandle) +{ + if (mBuffers.count(bufferHandle) == 0) { + return nullptr; + } + + return mBuffers[bufferHandle]; +} + +std::atomic<gralloc1_buffer_descriptor_t> + Gralloc1On0Adapter::sNextBufferDescriptorId(1); + +} // namespace android |