/* * 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 = mNumFlexPlanes; 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; const uint32_t mNumFlexPlanes; // 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