| /* | |
| * 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 <ui/GraphicBuffer.h> | |
| #include <ui/Gralloc1On0Adapter.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; | |
| } | |
| 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::getDimensions(buffer_handle_t buffer, | |
| uint32_t* outWidth, uint32_t* outHeight) | |
| { | |
| uint32_t width = 0; | |
| uint32_t height = 0; | |
| int32_t intError = mFunctions.getDimensions(mDevice, buffer, &width, | |
| &height); | |
| auto error = static_cast<gralloc1_error_t>(intError); | |
| if (error == GRALLOC1_ERROR_NONE) { | |
| *outWidth = width; | |
| *outHeight = height; | |
| } | |
| return error; | |
| } | |
| gralloc1_error_t Device::getFormat(buffer_handle_t buffer, | |
| int32_t* outFormat) | |
| { | |
| int32_t format = 0; | |
| int32_t intError = mFunctions.getFormat(mDevice, buffer, &format); | |
| auto error = static_cast<gralloc1_error_t>(intError); | |
| if (error == GRALLOC1_ERROR_NONE) { | |
| *outFormat = format; | |
| } | |
| return error; | |
| } | |
| gralloc1_error_t Device::getLayerCount(buffer_handle_t buffer, | |
| uint32_t* outLayerCount) | |
| { | |
| if (hasCapability(GRALLOC1_CAPABILITY_LAYERED_BUFFERS)) { | |
| uint32_t layerCount = 0; | |
| int32_t intError = mFunctions.getLayerCount(mDevice, buffer, | |
| &layerCount); | |
| auto error = static_cast<gralloc1_error_t>(intError); | |
| if (error == GRALLOC1_ERROR_NONE) { | |
| *outLayerCount = layerCount; | |
| } | |
| return error; | |
| } else { | |
| // Layered buffers are not supported on this device. | |
| return GRALLOC1_ERROR_UNSUPPORTED; | |
| } | |
| } | |
| gralloc1_error_t Device::getProducerUsage(buffer_handle_t buffer, | |
| uint64_t* outProducerUsage) | |
| { | |
| uint64_t usage = 0; | |
| int32_t intError = mFunctions.getProducerUsage(mDevice, buffer, &usage); | |
| auto error = static_cast<gralloc1_error_t>(intError); | |
| if (error == GRALLOC1_ERROR_NONE) { | |
| *outProducerUsage = usage; | |
| } | |
| return error; | |
| } | |
| gralloc1_error_t Device::getConsumerUsage(buffer_handle_t buffer, | |
| uint64_t* outConsumerUsage) | |
| { | |
| uint64_t usage = 0; | |
| int32_t intError = mFunctions.getConsumerUsage(mDevice, buffer, &usage); | |
| auto error = static_cast<gralloc1_error_t>(intError); | |
| if (error == GRALLOC1_ERROR_NONE) { | |
| *outConsumerUsage = usage; | |
| } | |
| return error; | |
| } | |
| gralloc1_error_t Device::getBackingStore(buffer_handle_t buffer, | |
| uint64_t* outBackingStore) | |
| { | |
| uint64_t store = 0; | |
| int32_t intError = mFunctions.getBackingStore(mDevice, buffer, &store); | |
| auto error = static_cast<gralloc1_error_t>(intError); | |
| if (error == GRALLOC1_ERROR_NONE) { | |
| *outBackingStore = store; | |
| } | |
| return error; | |
| } | |
| gralloc1_error_t Device::getStride(buffer_handle_t buffer, | |
| uint32_t* outStride) | |
| { | |
| uint32_t stride = 0; | |
| int32_t intError = mFunctions.getStride(mDevice, buffer, &stride); | |
| auto error = static_cast<gralloc1_error_t>(intError); | |
| if (error == GRALLOC1_ERROR_NONE) { | |
| *outStride = stride; | |
| } | |
| return error; | |
| } | |
| 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, 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, 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, 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 |