| /* |
| * 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 <mutex> |
| #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 |
| |
| 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<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::mutex mDescriptorMutex; |
| std::unordered_map<gralloc1_buffer_descriptor_t, |
| std::shared_ptr<Descriptor>> mDescriptors; |
| std::mutex mBufferMutex; |
| std::unordered_map<buffer_handle_t, std::shared_ptr<Buffer>> mBuffers; |
| }; |
| |
| } // namespace android |
| |
| #endif |