|  | /* | 
|  | * Copyright 2016 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | //#define LOG_NDEBUG 0 | 
|  |  | 
|  | #include <ui/Gralloc1.h> | 
|  |  | 
|  | #include <vector> | 
|  |  | 
|  | #undef LOG_TAG | 
|  | #define LOG_TAG GRALLOC1_LOG_TAG | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | namespace Gralloc1 { | 
|  |  | 
|  | Descriptor::~Descriptor() | 
|  | { | 
|  | int32_t intError = mShimDevice.mFunctions.destroyDescriptor( | 
|  | mShimDevice.mDevice, mDeviceId); | 
|  | auto error = static_cast<gralloc1_error_t>(intError); | 
|  | if (error != GRALLOC1_ERROR_NONE) { | 
|  | ALOGE("destroyDescriptor failed: %d", intError); | 
|  | } | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Descriptor::setDimensions(uint32_t width, uint32_t height) | 
|  | { | 
|  | int32_t intError = mShimDevice.mFunctions.setDimensions(mShimDevice.mDevice, | 
|  | mDeviceId, width, height); | 
|  | auto error = static_cast<gralloc1_error_t>(intError); | 
|  | if (error != GRALLOC1_ERROR_NONE) { | 
|  | return error; | 
|  | } | 
|  | mWidth = width; | 
|  | mHeight = height; | 
|  | return error; | 
|  | } | 
|  |  | 
|  | template <typename ApiType> | 
|  | struct Setter { | 
|  | typedef int32_t (*Type)(gralloc1_device_t*, gralloc1_buffer_descriptor_t, | 
|  | ApiType); | 
|  | }; | 
|  |  | 
|  | template <typename ApiType, typename ValueType> | 
|  | static inline gralloc1_error_t setHelper( | 
|  | typename Setter<ApiType>::Type setter, gralloc1_device_t* device, | 
|  | gralloc1_buffer_descriptor_t id, ValueType newValue, | 
|  | ValueType* cacheVariable) | 
|  | { | 
|  | int32_t intError = setter(device, id, static_cast<ApiType>(newValue)); | 
|  | auto error = static_cast<gralloc1_error_t>(intError); | 
|  | if (error != GRALLOC1_ERROR_NONE) { | 
|  | return error; | 
|  | } | 
|  | *cacheVariable = newValue; | 
|  | return error; | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Descriptor::setFormat(android_pixel_format_t format) | 
|  | { | 
|  | return setHelper<int32_t>(mShimDevice.mFunctions.setFormat.pfn, | 
|  | mShimDevice.mDevice, mDeviceId, format, &mFormat); | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Descriptor::setLayerCount(uint32_t layerCount) | 
|  | { | 
|  | if (mShimDevice.hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) { | 
|  | return setHelper<uint32_t>(mShimDevice.mFunctions.setLayerCount.pfn, | 
|  | mShimDevice.mDevice, mDeviceId, layerCount, &mLayerCount); | 
|  | } else { | 
|  | // Layered buffers are not supported on this device. | 
|  | return GRALLOC1_ERROR_UNSUPPORTED; | 
|  | } | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Descriptor::setProducerUsage(gralloc1_producer_usage_t usage) | 
|  | { | 
|  | return setHelper<uint64_t>(mShimDevice.mFunctions.setProducerUsage.pfn, | 
|  | mShimDevice.mDevice, mDeviceId, usage, &mProducerUsage); | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Descriptor::setConsumerUsage(gralloc1_consumer_usage_t usage) | 
|  | { | 
|  | return setHelper<uint64_t>(mShimDevice.mFunctions.setConsumerUsage.pfn, | 
|  | mShimDevice.mDevice, mDeviceId, usage, &mConsumerUsage); | 
|  | } | 
|  |  | 
|  | Device::Device(gralloc1_device_t* device) | 
|  | : mDevice(device), | 
|  | mCapabilities(loadCapabilities()), | 
|  | mFunctions() | 
|  | { | 
|  | if (!loadFunctions()) { | 
|  | ALOGE("Failed to load a required function, aborting"); | 
|  | abort(); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool Device::hasCapability(gralloc1_capability_t capability) const | 
|  | { | 
|  | return mCapabilities.count(capability) > 0; | 
|  | } | 
|  |  | 
|  | std::string Device::dump() | 
|  | { | 
|  | uint32_t length = 0; | 
|  | mFunctions.dump(mDevice, &length, nullptr); | 
|  |  | 
|  | std::vector<char> output; | 
|  | output.resize(length); | 
|  | mFunctions.dump(mDevice, &length, output.data()); | 
|  |  | 
|  | return std::string(output.cbegin(), output.cend()); | 
|  | } | 
|  |  | 
|  | std::shared_ptr<Descriptor> Device::createDescriptor() | 
|  | { | 
|  | gralloc1_buffer_descriptor_t descriptorId; | 
|  | int32_t intError = mFunctions.createDescriptor(mDevice, &descriptorId); | 
|  | auto error = static_cast<gralloc1_error_t>(intError); | 
|  | if (error != GRALLOC1_ERROR_NONE) { | 
|  | return nullptr; | 
|  | } | 
|  | auto descriptor = std::make_shared<Descriptor>(*this, descriptorId); | 
|  | return descriptor; | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::getStride(buffer_handle_t buffer, uint32_t* outStride) | 
|  | { | 
|  | int32_t intError = mFunctions.getStride(mDevice, buffer, outStride); | 
|  | return static_cast<gralloc1_error_t>(intError); | 
|  | } | 
|  |  | 
|  | static inline bool allocationSucceded(gralloc1_error_t error) | 
|  | { | 
|  | return error == GRALLOC1_ERROR_NONE || error == GRALLOC1_ERROR_NOT_SHARED; | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::allocate( | 
|  | const std::vector<std::shared_ptr<const Descriptor>>& descriptors, | 
|  | std::vector<buffer_handle_t>* outBuffers) | 
|  | { | 
|  | if (mFunctions.allocate.pfn == nullptr) { | 
|  | // Allocation is not supported on this device | 
|  | return GRALLOC1_ERROR_UNSUPPORTED; | 
|  | } | 
|  |  | 
|  | std::vector<gralloc1_buffer_descriptor_t> deviceIds; | 
|  | for (const auto& descriptor : descriptors) { | 
|  | deviceIds.emplace_back(descriptor->getDeviceId()); | 
|  | } | 
|  |  | 
|  | std::vector<buffer_handle_t> buffers(descriptors.size()); | 
|  | int32_t intError = mFunctions.allocate(mDevice, | 
|  | static_cast<uint32_t>(descriptors.size()), deviceIds.data(), | 
|  | buffers.data()); | 
|  | auto error = static_cast<gralloc1_error_t>(intError); | 
|  | if (allocationSucceded(error)) { | 
|  | *outBuffers = std::move(buffers); | 
|  | } | 
|  |  | 
|  | return error; | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::allocate( | 
|  | const std::shared_ptr<const Descriptor>& descriptor, | 
|  | gralloc1_backing_store_t id, buffer_handle_t* outBuffer) | 
|  | { | 
|  | gralloc1_error_t error = GRALLOC1_ERROR_NONE; | 
|  |  | 
|  | if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) { | 
|  | buffer_handle_t buffer = nullptr; | 
|  | int32_t intError = mFunctions.allocateWithId(mDevice, | 
|  | descriptor->getDeviceId(), id, &buffer); | 
|  | error = static_cast<gralloc1_error_t>(intError); | 
|  | if (allocationSucceded(error)) { | 
|  | *outBuffer = buffer; | 
|  | } | 
|  | } else { | 
|  | std::vector<std::shared_ptr<const Descriptor>> descriptors; | 
|  | descriptors.emplace_back(descriptor); | 
|  | std::vector<buffer_handle_t> buffers; | 
|  | error = allocate(descriptors, &buffers); | 
|  | if (allocationSucceded(error)) { | 
|  | *outBuffer = buffers[0]; | 
|  | } | 
|  | } | 
|  |  | 
|  | return error; | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::retain(buffer_handle_t buffer) | 
|  | { | 
|  | int32_t intError = mFunctions.retain(mDevice, buffer); | 
|  | return static_cast<gralloc1_error_t>(intError); | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::retain(const GraphicBuffer* buffer) | 
|  | { | 
|  | if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) { | 
|  | return mFunctions.retainGraphicBuffer(mDevice, buffer); | 
|  | } else { | 
|  | return retain(buffer->getNativeBuffer()->handle); | 
|  | } | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::release(buffer_handle_t buffer) | 
|  | { | 
|  | int32_t intError = mFunctions.release(mDevice, buffer); | 
|  | return static_cast<gralloc1_error_t>(intError); | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::getNumFlexPlanes(buffer_handle_t buffer, | 
|  | uint32_t* outNumPlanes) | 
|  | { | 
|  | uint32_t numPlanes = 0; | 
|  | int32_t intError = mFunctions.getNumFlexPlanes(mDevice, buffer, &numPlanes); | 
|  | auto error = static_cast<gralloc1_error_t>(intError); | 
|  | if (error == GRALLOC1_ERROR_NONE) { | 
|  | *outNumPlanes = numPlanes; | 
|  | } | 
|  | return error; | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::lock(buffer_handle_t buffer, | 
|  | gralloc1_producer_usage_t producerUsage, | 
|  | gralloc1_consumer_usage_t consumerUsage, | 
|  | const gralloc1_rect_t* accessRegion, void** outData, | 
|  | const sp<Fence>& acquireFence) | 
|  | { | 
|  | ALOGV("Calling lock(%p)", buffer); | 
|  | return lockHelper(mFunctions.lock.pfn, buffer, producerUsage, | 
|  | consumerUsage, accessRegion, outData, acquireFence); | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::lockFlex(buffer_handle_t 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) | 
|  | { | 
|  | ALOGV("Calling lockFlex(%p)", buffer); | 
|  | return lockHelper(mFunctions.lockFlex.pfn, buffer, producerUsage, | 
|  | consumerUsage, accessRegion, outData, acquireFence); | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::lockYCbCr(buffer_handle_t buffer, | 
|  | gralloc1_producer_usage_t producerUsage, | 
|  | gralloc1_consumer_usage_t consumerUsage, | 
|  | const gralloc1_rect_t* accessRegion, | 
|  | struct android_ycbcr* outData, | 
|  | const sp<Fence>& acquireFence) | 
|  | { | 
|  | ALOGV("Calling lockYCbCr(%p)", buffer); | 
|  | return lockHelper(mFunctions.lockYCbCr.pfn, buffer, producerUsage, | 
|  | consumerUsage, accessRegion, outData, acquireFence); | 
|  | } | 
|  |  | 
|  | gralloc1_error_t Device::unlock(buffer_handle_t buffer, sp<Fence>* outFence) | 
|  | { | 
|  | int32_t fenceFd = -1; | 
|  | int32_t intError = mFunctions.unlock(mDevice, buffer, &fenceFd); | 
|  | auto error = static_cast<gralloc1_error_t>(intError); | 
|  | if (error == GRALLOC1_ERROR_NONE) { | 
|  | *outFence = new Fence(fenceFd); | 
|  | } | 
|  | return error; | 
|  | } | 
|  |  | 
|  | std::unordered_set<gralloc1_capability_t> Device::loadCapabilities() | 
|  | { | 
|  | std::vector<int32_t> intCapabilities; | 
|  | uint32_t numCapabilities = 0; | 
|  | mDevice->getCapabilities(mDevice, &numCapabilities, nullptr); | 
|  |  | 
|  | intCapabilities.resize(numCapabilities); | 
|  | mDevice->getCapabilities(mDevice, &numCapabilities, intCapabilities.data()); | 
|  |  | 
|  | std::unordered_set<gralloc1_capability_t> capabilities; | 
|  | for (const auto intCapability : intCapabilities) { | 
|  | capabilities.emplace(static_cast<gralloc1_capability_t>(intCapability)); | 
|  | } | 
|  | return capabilities; | 
|  | } | 
|  |  | 
|  | bool Device::loadFunctions() | 
|  | { | 
|  | // Functions which must always be present | 
|  | if (!mFunctions.dump.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.createDescriptor.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.destroyDescriptor.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.setConsumerUsage.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.setDimensions.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.setFormat.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.setProducerUsage.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.getBackingStore.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.getConsumerUsage.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.getDimensions.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.getFormat.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.getProducerUsage.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.getStride.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.retain.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.release.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.getNumFlexPlanes.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.lock.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.lockFlex.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.unlock.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) { | 
|  | // These should always be present on the adapter | 
|  | if (!mFunctions.retainGraphicBuffer.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.lockYCbCr.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // allocateWithId may not be present if we're only able to map in this | 
|  | // process | 
|  | mFunctions.allocateWithId.load(mDevice, false); | 
|  | } else { | 
|  | // allocate may not be present if we're only able to map in this process | 
|  | mFunctions.allocate.load(mDevice, false); | 
|  | } | 
|  |  | 
|  | if (hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) { | 
|  | if (!mFunctions.setLayerCount.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | if (!mFunctions.getLayerCount.load(mDevice, true)) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<Gralloc1On0Adapter> Loader::mAdapter = nullptr; | 
|  |  | 
|  | Loader::Loader() | 
|  | : mDevice(nullptr) | 
|  | { | 
|  | hw_module_t const* module; | 
|  | int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); | 
|  | uint8_t majorVersion = (module->module_api_version >> 8) & 0xFF; | 
|  | uint8_t minorVersion = module->module_api_version & 0xFF; | 
|  | gralloc1_device_t* device = nullptr; | 
|  | if (majorVersion == 1) { | 
|  | gralloc1_open(module, &device); | 
|  | } else { | 
|  | if (!mAdapter) { | 
|  | mAdapter = std::make_unique<Gralloc1On0Adapter>(module); | 
|  | } | 
|  | device = mAdapter->getDevice(); | 
|  | } | 
|  | mDevice = std::make_unique<Gralloc1::Device>(device); | 
|  | } | 
|  |  | 
|  | Loader::~Loader() {} | 
|  |  | 
|  | std::unique_ptr<Device> Loader::getDevice() | 
|  | { | 
|  | return std::move(mDevice); | 
|  | } | 
|  |  | 
|  | } // namespace android::Gralloc1 | 
|  |  | 
|  | } // namespace android |