author | baocheng sun <baocheng.sun@amlogic.com> | 2020-05-26 11:48:44 (GMT) |
---|---|---|
committer | baocheng sun <baocheng.sun@amlogic.com> | 2020-05-28 02:15:01 (GMT) |
commit | f34c749ec03c46df0271a0b30278e27906a13ef6 (patch) | |
tree | a368ad94990dbc1573010c2dcdc8ee7579cbc4b4 | |
parent | adc88c28ecfdcd18df302ff9dc260d04965bd792 (diff) | |
download | hwcomposer-f34c749ec03c46df0271a0b30278e27906a13ef6.zip hwcomposer-f34c749ec03c46df0271a0b30278e27906a13ef6.tar.gz hwcomposer-f34c749ec03c46df0271a0b30278e27906a13ef6.tar.bz2 |
hwc: add vendor composer service [1/1]
PD#SWPL-26849
Problem:
enable vendor composer service for R
Solution:
add vendor composer service
Verify:
newton
Change-Id: I83cdbb61da0af5d4ae49fba63af9d308f941d452
Signed-off-by: baocheng sun <baocheng.sun@amlogic.com>
22 files changed, 1905 insertions, 805 deletions
diff --git a/service/2.1/utils/hal/Android.bp b/service/2.1/utils/hal/Android.bp index 45831a1..40f3dd0 100644..100755 --- a/service/2.1/utils/hal/Android.bp +++ b/service/2.1/utils/hal/Android.bp @@ -19,15 +19,13 @@ cc_library_headers { vendor: true, shared_libs: [ "android.hardware.graphics.composer@2.1", - "android.hardware.graphics.mapper@2.0", - "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.composer@2.1-resources-vendor", "libhardware", // TODO remove hwcomposer2.h dependency "libamgralloc_ext_vendor@2", ], export_shared_lib_headers: [ "android.hardware.graphics.composer@2.1", - "android.hardware.graphics.mapper@2.0", - "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.composer@2.1-resources-vendor", "libhardware", "libamgralloc_ext_vendor@2", ], diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h index 90d9b98..4b8c6bb 100644 --- a/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h +++ b/service/2.1/utils/hal/include/composer-hal/2.1/Composer.h @@ -67,6 +67,14 @@ class ComposerImpl : public Interface { } } + // we do not have HWC2_CAPABILITY_SKIP_VALIDATE defined in + // IComposer::Capability. However, this is defined in hwcomposer2.h, + // so if the device returns it, add it manually to be returned to the + // client + if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) { + caps.push_back(static_cast<IComposer::Capability>(HWC2_CAPABILITY_SKIP_VALIDATE)); + } + hidl_vec<IComposer::Capability> caps_reply; caps_reply.setToExternal(caps.data(), caps.size()); hidl_cb(caps_reply); @@ -80,8 +88,7 @@ class ComposerImpl : public Interface { Return<void> createClient(IComposer::createClient_cb hidl_cb) override { std::unique_lock<std::mutex> lock(mClientMutex); - bool destroyed = waitForClientDestroyedLocked(lock); - if (!destroyed) { + if (!waitForClientDestroyedLocked(lock)) { hidl_cb(Error::NO_RESOURCES, nullptr); return Void(); } diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h index 095189f..47ead41 100644 --- a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h +++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h @@ -27,7 +27,7 @@ #include <android/hardware/graphics/composer/2.1/IComposerClient.h> #include <composer-hal/2.1/ComposerCommandEngine.h> #include <composer-hal/2.1/ComposerHal.h> -#include <composer-hal/2.1/ComposerResources.h> +#include <composer-resources/2.1/ComposerResources.h> #include <log/log.h> namespace android { diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h index d87110a..ab67eb1 100644 --- a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h +++ b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h @@ -24,7 +24,7 @@ #include <composer-command-buffer/2.1/ComposerCommandBuffer.h> #include <composer-hal/2.1/ComposerHal.h> -#include <composer-hal/2.1/ComposerResources.h> +#include <composer-resources/2.1/ComposerResources.h> // TODO remove hwcomposer_defs.h dependency #include <hardware/hwcomposer_defs.h> #include <log/log.h> @@ -39,8 +39,10 @@ namespace hal { // TODO own a CommandReaderBase rather than subclassing class ComposerCommandEngine : protected CommandReaderBase { public: - ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources) - : mHal(hal), mResources(resources) {} + ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources) + : mHal(hal), mResources(resources) { + mWriter = createCommandWriter(kWriterInitialSize); + } virtual ~ComposerCommandEngine() = default; @@ -74,16 +76,16 @@ class ComposerCommandEngine : protected CommandReaderBase { return Error::BAD_PARAMETER; } - return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles) - ? Error::NONE - : Error::NO_RESOURCES; + return mWriter->writeQueue(outQueueChanged, outCommandLength, outCommandHandles) + ? Error::NONE + : Error::NO_RESOURCES; } - const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); } + const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter->getMQDescriptor(); } void reset() { CommandReaderBase::reset(); - mWriter.reset(); + mWriter->reset(); } protected: @@ -140,13 +142,36 @@ class ComposerCommandEngine : protected CommandReaderBase { } } + virtual std::unique_ptr<CommandWriterBase> createCommandWriter(size_t writerInitialSize) { + return std::make_unique<CommandWriterBase>(writerInitialSize); + } + + virtual Error executeValidateDisplayInternal() { + std::vector<Layer> changedLayers; + std::vector<IComposerClient::Composition> compositionTypes; + uint32_t displayRequestMask = 0x0; + std::vector<Layer> requestedLayers; + std::vector<uint32_t> requestMasks; + + auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, + &displayRequestMask, &requestedLayers, &requestMasks); + mResources->setDisplayMustValidateState(mCurrentDisplay, false); + if (err == Error::NONE) { + mWriter->setChangedCompositionTypes(changedLayers, compositionTypes); + mWriter->setDisplayRequests(displayRequestMask, requestedLayers, requestMasks); + } else { + mWriter->setError(getCommandLoc(), err); + } + return err; + } + bool executeSelectDisplay(uint16_t length) { if (length != CommandWriterBase::kSelectDisplayLength) { return false; } mCurrentDisplay = read64(); - mWriter.selectDisplay(mCurrentDisplay); + mWriter->selectDisplay(mCurrentDisplay); return true; } @@ -174,7 +199,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -195,7 +220,7 @@ class ComposerCommandEngine : protected CommandReaderBase { bool closeFence = true; const native_handle_t* clientTarget; - ComposerResources::ReplacedBufferHandle replacedClientTarget; + ComposerResources::ReplacedHandle replacedClientTarget(true); auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle, &clientTarget, &replacedClientTarget); if (err == Error::NONE) { @@ -208,7 +233,7 @@ class ComposerCommandEngine : protected CommandReaderBase { close(fence); } if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -226,7 +251,7 @@ class ComposerCommandEngine : protected CommandReaderBase { bool closeFence = true; const native_handle_t* outputBuffer; - ComposerResources::ReplacedBufferHandle replacedOutputBuffer; + ComposerResources::ReplacedHandle replacedOutputBuffer(true); auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle, &outputBuffer, &replacedOutputBuffer); if (err == Error::NONE) { @@ -239,7 +264,7 @@ class ComposerCommandEngine : protected CommandReaderBase { close(fence); } if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -249,23 +274,7 @@ class ComposerCommandEngine : protected CommandReaderBase { if (length != CommandWriterBase::kValidateDisplayLength) { return false; } - - std::vector<Layer> changedLayers; - std::vector<IComposerClient::Composition> compositionTypes; - uint32_t displayRequestMask = 0x0; - std::vector<Layer> requestedLayers; - std::vector<uint32_t> requestMasks; - - auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, - &displayRequestMask, &requestedLayers, &requestMasks); - mResources->setDisplayMustValidateState(mCurrentDisplay, false); - if (err == Error::NONE) { - mWriter.setChangedCompositionTypes(changedLayers, compositionTypes); - mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks); - } else { - mWriter.setError(getCommandLoc(), err); - } - + executeValidateDisplayInternal(); return true; } @@ -283,29 +292,17 @@ class ComposerCommandEngine : protected CommandReaderBase { ? Error::NOT_VALIDATED : mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences); if (err == Error::NONE) { - mWriter.setPresentOrValidateResult(1); - mWriter.setPresentFence(presentFence); - mWriter.setReleaseFences(layers, fences); + mWriter->setPresentOrValidateResult(1); + mWriter->setPresentFence(presentFence); + mWriter->setReleaseFences(layers, fences); return true; } } // Present has failed. We need to fallback to validate - std::vector<Layer> changedLayers; - std::vector<IComposerClient::Composition> compositionTypes; - uint32_t displayRequestMask = 0x0; - std::vector<Layer> requestedLayers; - std::vector<uint32_t> requestMasks; - - auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, - &displayRequestMask, &requestedLayers, &requestMasks); - mResources->setDisplayMustValidateState(mCurrentDisplay, false); + auto err = executeValidateDisplayInternal(); if (err == Error::NONE) { - mWriter.setPresentOrValidateResult(0); - mWriter.setChangedCompositionTypes(changedLayers, compositionTypes); - mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks); - } else { - mWriter.setError(getCommandLoc(), err); + mWriter->setPresentOrValidateResult(0); } return true; @@ -318,7 +315,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->acceptDisplayChanges(mCurrentDisplay); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -334,10 +331,10 @@ class ComposerCommandEngine : protected CommandReaderBase { std::vector<int> fences; auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences); if (err == Error::NONE) { - mWriter.setPresentFence(presentFence); - mWriter.setReleaseFences(layers, fences); + mWriter->setPresentFence(presentFence); + mWriter->setReleaseFences(layers, fences); } else { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -351,7 +348,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(), readSigned()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -369,7 +366,7 @@ class ComposerCommandEngine : protected CommandReaderBase { bool closeFence = true; const native_handle_t* buffer; - ComposerResources::ReplacedBufferHandle replacedBuffer; + ComposerResources::ReplacedHandle replacedBuffer(true); auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache, rawHandle, &buffer, &replacedBuffer); if (err == Error::NONE) { @@ -382,7 +379,7 @@ class ComposerCommandEngine : protected CommandReaderBase { close(fence); } if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -397,7 +394,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto damage = readRegion(length / 4); auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -410,7 +407,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -423,7 +420,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -436,7 +433,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -449,7 +446,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -462,7 +459,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -475,7 +472,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -489,14 +486,14 @@ class ComposerCommandEngine : protected CommandReaderBase { auto rawHandle = readHandle(); const native_handle_t* stream; - ComposerResources::ReplacedStreamHandle replacedStream; + ComposerResources::ReplacedHandle replacedStream(false); auto err = mResources->getLayerSidebandStream(mCurrentDisplay, mCurrentLayer, rawHandle, &stream, &replacedStream); if (err == Error::NONE) { err = mHal->setLayerSidebandStream(mCurrentDisplay, mCurrentLayer, stream); } if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -509,7 +506,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -522,7 +519,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -537,7 +534,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto region = readRegion(length / 4); auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -550,7 +547,7 @@ class ComposerCommandEngine : protected CommandReaderBase { auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read()); if (err != Error::NONE) { - mWriter.setError(getCommandLoc(), err); + mWriter->setError(getCommandLoc(), err); } return true; @@ -579,12 +576,12 @@ class ComposerCommandEngine : protected CommandReaderBase { }; } - ComposerHal* mHal; - ComposerResources* mResources; - // 64KiB minus a small space for metadata such as read/write pointers static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16; - CommandWriterBase mWriter{kWriterInitialSize}; + + ComposerHal* mHal; + ComposerResources* mResources; + std::unique_ptr<CommandWriterBase> mWriter; Display mCurrentDisplay = 0; Layer mCurrentLayer = 0; diff --git a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h deleted file mode 100755 index 8c22ebc..0000000 --- a/service/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h +++ b/dev/null @@ -1,717 +0,0 @@ -/* - * Copyright 2018 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. - */ - -#pragma once - -#ifndef LOG_TAG -#warning "ComposerResources.h included without LOG_TAG" -#endif - -#include <memory> -#include <mutex> -#include <unordered_map> -#include <vector> - -#include <android/hardware/graphics/mapper/2.0/IMapper.h> -#include <android/hardware/graphics/mapper/3.0/IMapper.h> -#include <log/log.h> - -#include <hwbinder/IPCThreadState.h> -#include "am_gralloc_ext.h" - -#define UVM_DEV_PATH "/dev/uvm" -#define UVM_IOC_MAGIC 'U' -#define UVM_IOC_SET_PID _IOWR(UVM_IOC_MAGIC, 2, struct uvm_pid_data) - -namespace android { -namespace hardware { -namespace graphics { -namespace composer { -namespace V2_1 { -namespace hal { - -class ComposerUVMHandle { -public: - ComposerUVMHandle() : mFd(-1) {} - - ~ComposerUVMHandle() { - if (mFd >=0) - close(mFd); - } - - int setUVM() { - ::android::hardware::IPCThreadState *ipc = ::android::hardware::IPCThreadState::self(); - const pid_t pid = ipc->getCallingPid(); - - struct uvm_pid_data { - int pid; - } pid_data; - - pid_data.pid = pid; - - ALOGD("setUVM with pid %d", pid); - if (ioctl(mFd, UVM_IOC_SET_PID, &pid_data) != 0) { - ALOGE("setUVM pid %d ioctl error %s", pid, strerror(errno)); - return -1; - } - return 0; - } - - bool init() { - mFd = open(UVM_DEV_PATH, O_RDWR); - if (mFd <= 0) { - ALOGE("open uvm device error"); - return false; - } - setUVM(); - return true; - } - -private: - int mFd; -}; - -// wrapper for IMapper to import buffers and sideband streams -class ComposerHandleImporter { - public: - bool init() { - mMapper3 = mapper::V3_0::IMapper::getService(); - if (mMapper3) { - return true; - } - ALOGD_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0"); - - mMapper2 = mapper::V2_0::IMapper::getService(); - ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service"); - - return mMapper2 != nullptr; - } - - Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) { - if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) { - *outBufferHandle = nullptr; - return Error::NONE; - } - - const native_handle_t* bufferHandle; - if (mMapper2) { - mapper::V2_0::Error error; - mMapper2->importBuffer( - rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { - error = tmpError; - bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); - }); - if (error != mapper::V2_0::Error::NONE) { - return Error::NO_RESOURCES; - } - } - if (mMapper3) { - mapper::V3_0::Error error; - mMapper3->importBuffer( - rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { - error = tmpError; - bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); - }); - if (error != mapper::V3_0::Error::NONE) { - return Error::NO_RESOURCES; - } - } - - *outBufferHandle = bufferHandle; - return Error::NONE; - } - - void freeBuffer(const native_handle_t* bufferHandle) { - if (bufferHandle) { - if (mMapper2) { - mMapper2->freeBuffer( - static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); - } else if (mMapper3) { - mMapper3->freeBuffer( - static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); - } - } - } - - Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) { - const native_handle_t* streamHandle = nullptr; - if (rawHandle) { - streamHandle = native_handle_clone(rawHandle); - if (!streamHandle) { - return Error::NO_RESOURCES; - } - } - - *outStreamHandle = streamHandle; - return Error::NONE; - } - - void freeStream(const native_handle_t* streamHandle) { - if (streamHandle) { - native_handle_close(streamHandle); - native_handle_delete(const_cast<native_handle_t*>(streamHandle)); - } - } - - private: - sp<mapper::V2_0::IMapper> mMapper2; - sp<mapper::V3_0::IMapper> mMapper3; -}; - -class ComposerHandleCache { - public: - enum class HandleType { - INVALID, - BUFFER, - STREAM, - }; - - enum class DrmFbType { - DRM_FB_UNDEFINED = 0, - // scattered buffer, can be used for rendering. - DRM_FB_RENDER = 1, - // contiguous buffer, can be used for scanout. - DRM_FB_SCANOUT, - // video type, used for video. - DRM_FB_VIDEO, - DRM_FB_VIDEO_OVERLAY, - }; - - ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize) - : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {} - - // must be initialized later with initCache - ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {} - - ~ComposerHandleCache() { - switch (mHandleType) { - case HandleType::BUFFER: - for (auto handle : mHandles) { - mImporter.freeBuffer(handle); - } - break; - case HandleType::STREAM: - for (auto handle : mHandles) { - mImporter.freeStream(handle); - } - break; - default: - break; - } - } - - ComposerHandleCache(const ComposerHandleCache&) = delete; - ComposerHandleCache& operator=(const ComposerHandleCache&) = delete; - - bool initCache(HandleType type, uint32_t cacheSize) { - // already initialized - if (mHandleType != HandleType::INVALID) { - return false; - } - - mHandleType = type; - mHandles.resize(cacheSize, nullptr); - - return true; - } - - Error lookupCache(uint32_t slot, const native_handle_t** outHandle) { - if (slot >= 0 && slot < mHandles.size()) { - *outHandle = mHandles[slot]; - return Error::NONE; - } else { - return Error::BAD_PARAMETER; - } - } - - Error updateCache(uint32_t slot, const native_handle_t* handle, - const native_handle** outReplacedHandle) { - if (slot >= 0 && slot < mHandles.size()) { - auto& cachedHandle = mHandles[slot]; - *outReplacedHandle = cachedHandle; - cachedHandle = handle; - return Error::NONE; - } else { - return Error::BAD_PARAMETER; - } - } - - // release cache - Error releaseCache(uint32_t slot) { - if (slot >= 0 && slot < mHandles.size()) { - switch (mHandleType) { - case HandleType::BUFFER: - for (; slot < mHandles.size(); slot++) { - if (mHandles[slot]) - mImporter.freeBuffer(mHandles[slot]); - mHandles[slot] = nullptr; - } - break; - case HandleType::STREAM: - for (; slot < mHandles.size(); slot++) { - if (mHandles[slot]) - mImporter.freeStream(mHandles[slot]); - mHandles[slot] = nullptr; - } - break; - default: - break; - } - return Error::NONE; - } else { - return Error::BAD_PARAMETER; - } - } - - bool isChangedFromeVideoToUi(const native_handle_t* handle) { - bool changed = false; - if (am_gralloc_is_omx_v4l_buffer(handle) || am_gralloc_is_omx2_v4l2_buffer(handle) || - am_gralloc_is_omx_metadata_buffer(handle)) { - mFbType = DrmFbType::DRM_FB_VIDEO; - } else if (am_gralloc_is_overlay_buffer(handle)) { - mFbType = DrmFbType::DRM_FB_VIDEO_OVERLAY; - } else if (am_gralloc_is_coherent_buffer(handle)) { - if (mFbType == DrmFbType::DRM_FB_VIDEO || - mFbType == DrmFbType::DRM_FB_VIDEO_OVERLAY) { - changed = true; - } - mFbType = DrmFbType::DRM_FB_SCANOUT; - } else { - if (mFbType == DrmFbType::DRM_FB_VIDEO || - mFbType == DrmFbType::DRM_FB_VIDEO_OVERLAY) { - changed = true; - } - mFbType = DrmFbType::DRM_FB_RENDER; - } - return changed; - } - - // when fromCache is true, look up in the cache; otherwise, update the cache - Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle, - const native_handle_t** outHandle, const native_handle** outReplacedHandle) { - Error error = Error::NONE; - - if (fromCache) { - *outReplacedHandle = nullptr; - error = lookupCache(slot, outHandle); - } else { - if (mHandleType == HandleType::BUFFER && isChangedFromeVideoToUi(inHandle)) { - ALOGD("FB type changed from video to UI, fromcache(%d):slot(%d)", fromCache, slot); - releaseCache(0); - } - - *outHandle = inHandle; - error = updateCache(slot, inHandle, outReplacedHandle); - } - - return error; - } - - private: - ComposerHandleImporter& mImporter; - HandleType mHandleType = HandleType::INVALID; - DrmFbType mFbType = DrmFbType::DRM_FB_UNDEFINED; - std::vector<const native_handle_t*> mHandles; -}; - -// layer resource -class ComposerLayerResource { - public: - ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize) - : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize), - mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {} - - virtual ~ComposerLayerResource() = default; - - Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, - const native_handle_t** outHandle, const native_handle** outReplacedHandle) { - return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); - } - - Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle, - const native_handle_t** outHandle, - const native_handle** outReplacedHandle) { - return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle, - outReplacedHandle); - } - - protected: - ComposerHandleCache mBufferCache; - ComposerHandleCache mSidebandStreamCache; -}; - -// display resource -class ComposerDisplayResource { - public: - enum class DisplayType { - PHYSICAL, - VIRTUAL, - }; - - virtual ~ComposerDisplayResource() = default; - - ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, - uint32_t outputBufferCacheSize) - : mType(type), - mClientTargetCache(importer), - mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, - outputBufferCacheSize), - mMustValidate(true) {} - - bool initClientTargetCache(uint32_t cacheSize) { - return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize); - } - - bool isVirtual() const { return mType == DisplayType::VIRTUAL; } - - Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle, - const native_handle_t** outHandle, - const native_handle** outReplacedHandle) { - return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle, - outReplacedHandle); - } - - Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, - const native_handle_t** outHandle, - const native_handle** outReplacedHandle) { - return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle, - outReplacedHandle); - } - - bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) { - auto result = mLayerResources.emplace(layer, std::move(layerResource)); - return result.second; - } - - bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; } - - ComposerLayerResource* findLayerResource(Layer layer) { - auto layerIter = mLayerResources.find(layer); - if (layerIter == mLayerResources.end()) { - return nullptr; - } - - return layerIter->second.get(); - } - - std::vector<Layer> getLayers() const { - std::vector<Layer> layers; - layers.reserve(mLayerResources.size()); - for (const auto& layerKey : mLayerResources) { - layers.push_back(layerKey.first); - } - return layers; - } - - void setMustValidateState(bool mustValidate) { mMustValidate = mustValidate; } - - bool mustValidate() const { return mMustValidate; } - - protected: - const DisplayType mType; - ComposerHandleCache mClientTargetCache; - ComposerHandleCache mOutputBufferCache; - bool mMustValidate; - - std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources; -}; - -class ComposerResources { - private: - template <bool isBuffer> - class ReplacedHandle; - - public: - static std::unique_ptr<ComposerResources> create() { - auto resources = std::make_unique<ComposerResources>(); - return resources->init() ? std::move(resources) : nullptr; - } - - ComposerResources() = default; - virtual ~ComposerResources() = default; - - bool init() { - bool result = mImporter.init(); - mUVMHandle.init(); - - return result; - } - - using RemoveDisplay = - std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>; - void clear(RemoveDisplay removeDisplay) { - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - for (const auto& displayKey : mDisplayResources) { - Display display = displayKey.first; - const ComposerDisplayResource& displayResource = *displayKey.second; - removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers()); - } - mDisplayResources.clear(); - } - - Error addPhysicalDisplay(Display display) { - auto displayResource = - createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0); - - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - auto result = mDisplayResources.emplace(display, std::move(displayResource)); - return result.second ? Error::NONE : Error::BAD_DISPLAY; - } - - Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) { - auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL, - outputBufferCacheSize); - - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - auto result = mDisplayResources.emplace(display, std::move(displayResource)); - return result.second ? Error::NONE : Error::BAD_DISPLAY; - } - - Error removeDisplay(Display display) { - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY; - } - - Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) { - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); - if (!displayResource) { - return Error::BAD_DISPLAY; - } - - return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE - : Error::BAD_PARAMETER; - } - - Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) { - auto layerResource = createLayerResource(bufferCacheSize); - - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); - if (!displayResource) { - return Error::BAD_DISPLAY; - } - - return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE - : Error::BAD_LAYER; - } - - Error removeLayer(Display display, Layer layer) { - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); - if (!displayResource) { - return Error::BAD_DISPLAY; - } - - return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER; - } - - using ReplacedBufferHandle = ReplacedHandle<true>; - using ReplacedStreamHandle = ReplacedHandle<false>; - - Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache, - const native_handle_t* rawHandle, - const native_handle_t** outBufferHandle, - ReplacedBufferHandle* outReplacedBuffer) { - return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle, - outBufferHandle, outReplacedBuffer); - } - - Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache, - const native_handle_t* rawHandle, - const native_handle_t** outBufferHandle, - ReplacedBufferHandle* outReplacedBuffer) { - return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle, - outBufferHandle, outReplacedBuffer); - } - - Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache, - const native_handle_t* rawHandle, const native_handle_t** outBufferHandle, - ReplacedBufferHandle* outReplacedBuffer) { - return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle, - outBufferHandle, outReplacedBuffer); - } - - Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle, - const native_handle_t** outStreamHandle, - ReplacedStreamHandle* outReplacedStream) { - return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle, - outStreamHandle, outReplacedStream); - } - - void setDisplayMustValidateState(Display display, bool mustValidate) { - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - auto* displayResource = findDisplayResourceLocked(display); - if (displayResource) { - displayResource->setMustValidateState(mustValidate); - } - } - - bool mustValidateDisplay(Display display) { - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - auto* displayResource = findDisplayResourceLocked(display); - if (displayResource) { - return displayResource->mustValidate(); - } - return false; - } - - protected: - virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource( - ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) { - return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize); - } - - virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) { - return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize); - } - - ComposerDisplayResource* findDisplayResourceLocked(Display display) { - auto iter = mDisplayResources.find(display); - if (iter == mDisplayResources.end()) { - return nullptr; - } - return iter->second.get(); - } - - ComposerHandleImporter mImporter; - ComposerUVMHandle mUVMHandle; - - std::mutex mDisplayResourcesMutex; - std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources; - - private: - enum class Cache { - CLIENT_TARGET, - OUTPUT_BUFFER, - LAYER_BUFFER, - LAYER_SIDEBAND_STREAM, - }; - - // When a buffer in the cache is replaced by a new one, we must keep it - // alive until it has been replaced in ComposerHal. - template <bool isBuffer> - class ReplacedHandle { - public: - ReplacedHandle() = default; - ReplacedHandle(const ReplacedHandle&) = delete; - ReplacedHandle& operator=(const ReplacedHandle&) = delete; - - ~ReplacedHandle() { reset(); } - - void reset(ComposerHandleImporter* importer = nullptr, - const native_handle_t* handle = nullptr) { - if (mHandle) { - if (isBuffer) { - mImporter->freeBuffer(mHandle); - } else { - mImporter->freeStream(mHandle); - } - } - - mImporter = importer; - mHandle = handle; - } - - private: - ComposerHandleImporter* mImporter = nullptr; - const native_handle_t* mHandle = nullptr; - }; - - template <Cache cache, bool isBuffer> - Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache, - const native_handle_t* rawHandle, const native_handle_t** outHandle, - ReplacedHandle<isBuffer>* outReplacedHandle) { - Error error; - - // import the raw handle (or ignore raw handle when fromCache is true) - const native_handle_t* importedHandle = nullptr; - if (!fromCache) { - error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle) - : mImporter.importStream(rawHandle, &importedHandle); - if (error != Error::NONE) { - return error; - } - } - - std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); - - // find display/layer resource - const bool needLayerResource = - (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM); - ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); - ComposerLayerResource* layerResource = (displayResource && needLayerResource) - ? displayResource->findLayerResource(layer) - : nullptr; - - // lookup or update cache - const native_handle_t* replacedHandle = nullptr; - if (displayResource && (!needLayerResource || layerResource)) { - switch (cache) { - case Cache::CLIENT_TARGET: - error = displayResource->getClientTarget(slot, fromCache, importedHandle, - outHandle, &replacedHandle); - break; - case Cache::OUTPUT_BUFFER: - error = displayResource->getOutputBuffer(slot, fromCache, importedHandle, - outHandle, &replacedHandle); - break; - case Cache::LAYER_BUFFER: - error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle, - &replacedHandle); - break; - case Cache::LAYER_SIDEBAND_STREAM: - error = layerResource->getSidebandStream(slot, fromCache, importedHandle, - outHandle, &replacedHandle); - break; - default: - error = Error::BAD_PARAMETER; - break; - } - - if (error != Error::NONE) { - ALOGW("invalid cache %d slot %d", int(cache), int(slot)); - } - } else if (!displayResource) { - error = Error::BAD_DISPLAY; - } else { - error = Error::BAD_LAYER; - } - - // clean up on errors - if (error != Error::NONE) { - if (!fromCache) { - if (isBuffer) { - mImporter.freeBuffer(importedHandle); - } else { - mImporter.freeStream(importedHandle); - } - } - return error; - } - - outReplacedHandle->reset(&mImporter, replacedHandle); - - return Error::NONE; - } -}; - -} // namespace hal -} // namespace V2_1 -} // namespace composer -} // namespace graphics -} // namespace hardware -} // namespace android diff --git a/service/2.1/utils/resources/Android.bp b/service/2.1/utils/resources/Android.bp new file mode 100644 index 0000000..9098603 --- a/dev/null +++ b/service/2.1/utils/resources/Android.bp @@ -0,0 +1,53 @@ +// +// Copyright (C) 2019 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. + +cc_library_shared { + name: "android.hardware.graphics.composer@2.1-resources-vendor", + defaults: ["hidl_defaults"], + vendor: true, + shared_libs: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.mapper@4.0", + "libcutils", + "libhardware", // TODO remove hwcomposer2.h dependency + "libhidlbase", + "liblog", + "libutils", + "libamgralloc_ext_vendor@2", + ], + export_shared_lib_headers: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.mapper@2.0", + "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.mapper@4.0", + "libhardware", + "libhidlbase", + "liblog", + "libutils", + "libamgralloc_ext_vendor@2", + ], + header_libs: [ + "android.hardware.graphics.composer@2.1-command-buffer", + ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.1-command-buffer", + ], + export_include_dirs: ["include"], + srcs: [ + "ComposerResources.cpp", + ], +} diff --git a/service/2.1/utils/resources/ComposerResources.cpp b/service/2.1/utils/resources/ComposerResources.cpp new file mode 100644 index 0000000..46d552d --- a/dev/null +++ b/service/2.1/utils/resources/ComposerResources.cpp @@ -0,0 +1,607 @@ +/* + * Copyright 2019 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_TAG "ComposerResources" + +#include <hwbinder/IPCThreadState.h> +#include "composer-resources/2.1/ComposerResources.h" +#include "am_gralloc_ext.h" +#include <sys/ioctl.h> + +#define UVM_DEV_PATH "/dev/uvm" +#define UVM_IOC_MAGIC 'U' +#define UVM_IOC_SET_PID _IOWR(UVM_IOC_MAGIC, 2, struct uvm_pid_data) + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace hal { + +ComposerUVMHandle::ComposerUVMHandle() : mFd(-1) { +} + +ComposerUVMHandle::~ComposerUVMHandle() { + if (mFd >=0) + close(mFd); +} + +bool ComposerUVMHandle::init() { + mFd = open(UVM_DEV_PATH, O_RDWR); + if (mFd <= 0) { + ALOGE("open uvm device error"); + return false; + } + setUVM(); + return true; +} + +int ComposerUVMHandle::setUVM() { + ::android::hardware::IPCThreadState *ipc = ::android::hardware::IPCThreadState::self(); + const pid_t pid = ipc->getCallingPid(); + + struct uvm_pid_data { + int pid; + } pid_data; + + pid_data.pid = pid; + + ALOGD("setUVM with pid %d", pid); + if (ioctl(mFd, UVM_IOC_SET_PID, &pid_data) != 0) { + ALOGE("setUVM pid %d ioctl error %s", pid, strerror(errno)); + return -1; + } + return 0; +} + +bool ComposerHandleImporter::init() { + mMapper4 = mapper::V4_0::IMapper::getService(); + if (mMapper4) { + return true; + } + ALOGI_IF(!mMapper4, "failed to get mapper 4.0 service, falling back to mapper 3.0"); + + mMapper3 = mapper::V3_0::IMapper::getService(); + if (mMapper3) { + return true; + } + ALOGI_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0"); + + mMapper2 = mapper::V2_0::IMapper::getService(); + ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service"); + + return mMapper2 != nullptr; +} + +Error ComposerHandleImporter::importBuffer(const native_handle_t* rawHandle, + const native_handle_t** outBufferHandle) { + if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) { + *outBufferHandle = nullptr; + return Error::NONE; + } + + const native_handle_t* bufferHandle; + if (mMapper2) { + mapper::V2_0::Error error; + mMapper2->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { + error = tmpError; + bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); + }); + if (error != mapper::V2_0::Error::NONE) { + return Error::NO_RESOURCES; + } + } + if (mMapper3) { + mapper::V3_0::Error error; + mMapper3->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { + error = tmpError; + bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); + }); + if (error != mapper::V3_0::Error::NONE) { + return Error::NO_RESOURCES; + } + } + if (mMapper4) { + mapper::V4_0::Error error; + mMapper4->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { + error = tmpError; + bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); + }); + if (error != mapper::V4_0::Error::NONE) { + return Error::NO_RESOURCES; + } + } + + *outBufferHandle = bufferHandle; + return Error::NONE; +} + +void ComposerHandleImporter::freeBuffer(const native_handle_t* bufferHandle) { + if (bufferHandle) { + if (mMapper2) { + mMapper2->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); + } else if (mMapper3) { + mMapper3->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); + } else if (mMapper4) { + mMapper4->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); + } + } +} + +Error ComposerHandleImporter::importStream(const native_handle_t* rawHandle, + const native_handle_t** outStreamHandle) { + const native_handle_t* streamHandle = nullptr; + if (rawHandle) { + streamHandle = native_handle_clone(rawHandle); + if (!streamHandle) { + return Error::NO_RESOURCES; + } + } + + *outStreamHandle = streamHandle; + return Error::NONE; +} + +void ComposerHandleImporter::freeStream(const native_handle_t* streamHandle) { + if (streamHandle) { + native_handle_close(streamHandle); + native_handle_delete(const_cast<native_handle_t*>(streamHandle)); + } +} + +ComposerHandleCache::ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, + uint32_t cacheSize) + : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {} + +// must be initialized later with initCache +ComposerHandleCache::ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {} + +ComposerHandleCache::~ComposerHandleCache() { + switch (mHandleType) { + case HandleType::BUFFER: + for (auto handle : mHandles) { + mImporter.freeBuffer(handle); + } + break; + case HandleType::STREAM: + for (auto handle : mHandles) { + mImporter.freeStream(handle); + } + break; + default: + break; + } +} + +bool ComposerHandleCache::initCache(HandleType type, uint32_t cacheSize) { + // already initialized + if (mHandleType != HandleType::INVALID) { + return false; + } + + mHandleType = type; + mHandles.resize(cacheSize, nullptr); + + return true; +} + +Error ComposerHandleCache::lookupCache(uint32_t slot, const native_handle_t** outHandle) { + if (slot >= 0 && slot < mHandles.size()) { + *outHandle = mHandles[slot]; + return Error::NONE; + } else { + return Error::BAD_PARAMETER; + } +} + +Error ComposerHandleCache::updateCache(uint32_t slot, const native_handle_t* handle, + const native_handle** outReplacedHandle) { + if (slot >= 0 && slot < mHandles.size()) { + auto& cachedHandle = mHandles[slot]; + *outReplacedHandle = cachedHandle; + cachedHandle = handle; + return Error::NONE; + } else { + return Error::BAD_PARAMETER; + } +} + +// release cache +Error ComposerHandleCache::releaseCache(uint32_t slot) { + if (slot >= 0 && slot < mHandles.size()) { + switch (mHandleType) { + case HandleType::BUFFER: + for (; slot < mHandles.size(); slot++) { + if (mHandles[slot]) + mImporter.freeBuffer(mHandles[slot]); + mHandles[slot] = nullptr; + } + break; + case HandleType::STREAM: + for (; slot < mHandles.size(); slot++) { + if (mHandles[slot]) + mImporter.freeStream(mHandles[slot]); + mHandles[slot] = nullptr; + } + break; + default: + break; + } + return Error::NONE; + } else { + return Error::BAD_PARAMETER; + } +} + +bool ComposerHandleCache::isChangedFromeVideoToUi(const native_handle_t* handle) { + bool changed = false; + if (am_gralloc_is_omx_v4l_buffer(handle) || am_gralloc_is_omx2_v4l2_buffer(handle) || + am_gralloc_is_omx_metadata_buffer(handle)) { + mFbType = DrmFbType::DRM_FB_VIDEO; + } else if (am_gralloc_is_overlay_buffer(handle)) { + mFbType = DrmFbType::DRM_FB_VIDEO_OVERLAY; + } else if (am_gralloc_is_coherent_buffer(handle)) { + if (mFbType == DrmFbType::DRM_FB_VIDEO || + mFbType == DrmFbType::DRM_FB_VIDEO_OVERLAY) { + changed = true; + } + mFbType = DrmFbType::DRM_FB_SCANOUT; + } else { + if (mFbType == DrmFbType::DRM_FB_VIDEO || + mFbType == DrmFbType::DRM_FB_VIDEO_OVERLAY) { + changed = true; + } + mFbType = DrmFbType::DRM_FB_RENDER; + } + return changed; +} + +// when fromCache is true, look up in the cache; otherwise, update the cache +Error ComposerHandleCache::getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + Error error = Error::NONE; + + if (fromCache) { + *outReplacedHandle = nullptr; + error = lookupCache(slot, outHandle); + } else { + if (mHandleType == HandleType::BUFFER && isChangedFromeVideoToUi(inHandle)) { + ALOGD("FB type changed from video to UI, fromcache(%d):slot(%d)", fromCache, slot); + releaseCache(0); + } + + *outHandle = inHandle; + error = updateCache(slot, inHandle, outReplacedHandle); + } + + return error; +} + +ComposerLayerResource::ComposerLayerResource(ComposerHandleImporter& importer, + uint32_t bufferCacheSize) + : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize), + mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {} + +Error ComposerLayerResource::getBuffer(uint32_t slot, bool fromCache, + const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); +} + +Error ComposerLayerResource::getSidebandStream(uint32_t slot, bool fromCache, + const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); +} + +ComposerDisplayResource::ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, + uint32_t outputBufferCacheSize) + : mType(type), + mClientTargetCache(importer), + mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, outputBufferCacheSize), + mMustValidate(true) {} + +bool ComposerDisplayResource::initClientTargetCache(uint32_t cacheSize) { + return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize); +} + +bool ComposerDisplayResource::isVirtual() const { + return mType == DisplayType::VIRTUAL; +} + +Error ComposerDisplayResource::getClientTarget(uint32_t slot, bool fromCache, + const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); +} + +Error ComposerDisplayResource::getOutputBuffer(uint32_t slot, bool fromCache, + const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); +} + +bool ComposerDisplayResource::addLayer(Layer layer, + std::unique_ptr<ComposerLayerResource> layerResource) { + auto result = mLayerResources.emplace(layer, std::move(layerResource)); + return result.second; +} + +bool ComposerDisplayResource::removeLayer(Layer layer) { + return mLayerResources.erase(layer) > 0; +} + +ComposerLayerResource* ComposerDisplayResource::findLayerResource(Layer layer) { + auto layerIter = mLayerResources.find(layer); + if (layerIter == mLayerResources.end()) { + return nullptr; + } + + return layerIter->second.get(); +} + +std::vector<Layer> ComposerDisplayResource::getLayers() const { + std::vector<Layer> layers; + layers.reserve(mLayerResources.size()); + for (const auto& layerKey : mLayerResources) { + layers.push_back(layerKey.first); + } + return layers; +} + +void ComposerDisplayResource::setMustValidateState(bool mustValidate) { + mMustValidate = mustValidate; +} + +bool ComposerDisplayResource::mustValidate() const { + return mMustValidate; +} + +std::unique_ptr<ComposerResources> ComposerResources::create() { + auto resources = std::make_unique<ComposerResources>(); + return resources->init() ? std::move(resources) : nullptr; +} + +bool ComposerResources::init() { + bool result = mImporter.init(); + mUVMHandle.init(); + return result; +} + +void ComposerResources::clear(RemoveDisplay removeDisplay) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + for (const auto& displayKey : mDisplayResources) { + Display display = displayKey.first; + const ComposerDisplayResource& displayResource = *displayKey.second; + removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers()); + } + mDisplayResources.clear(); +} + +Error ComposerResources::addPhysicalDisplay(Display display) { + auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0); + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + auto result = mDisplayResources.emplace(display, std::move(displayResource)); + return result.second ? Error::NONE : Error::BAD_DISPLAY; +} + +Error ComposerResources::addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) { + auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL, + outputBufferCacheSize); + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + auto result = mDisplayResources.emplace(display, std::move(displayResource)); + return result.second ? Error::NONE : Error::BAD_DISPLAY; +} + +Error ComposerResources::removeDisplay(Display display) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY; +} + +Error ComposerResources::setDisplayClientTargetCacheSize(Display display, + uint32_t clientTargetCacheSize) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + if (!displayResource) { + return Error::BAD_DISPLAY; + } + + return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE + : Error::BAD_PARAMETER; +} + +Error ComposerResources::addLayer(Display display, Layer layer, uint32_t bufferCacheSize) { + auto layerResource = createLayerResource(bufferCacheSize); + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + if (!displayResource) { + return Error::BAD_DISPLAY; + } + + return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE + : Error::BAD_LAYER; +} + +Error ComposerResources::removeLayer(Display display, Layer layer) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + if (!displayResource) { + return Error::BAD_DISPLAY; + } + + return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER; +} + +Error ComposerResources::getDisplayClientTarget(Display display, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, + const native_handle_t** outBufferHandle, + ReplacedHandle* outReplacedBuffer) { + return getHandle(display, 0, slot, Cache::CLIENT_TARGET, fromCache, rawHandle, outBufferHandle, + outReplacedBuffer); +} + +Error ComposerResources::getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, + const native_handle_t** outBufferHandle, + ReplacedHandle* outReplacedBuffer) { + return getHandle(display, 0, slot, Cache::OUTPUT_BUFFER, fromCache, rawHandle, outBufferHandle, + outReplacedBuffer); +} + +Error ComposerResources::getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, + const native_handle_t** outBufferHandle, + ReplacedHandle* outReplacedBuffer) { + return getHandle(display, layer, slot, Cache::LAYER_BUFFER, fromCache, rawHandle, + outBufferHandle, outReplacedBuffer); +} + +Error ComposerResources::getLayerSidebandStream(Display display, Layer layer, + const native_handle_t* rawHandle, + const native_handle_t** outStreamHandle, + ReplacedHandle* outReplacedStream) { + return getHandle(display, layer, 0, Cache::LAYER_SIDEBAND_STREAM, false, rawHandle, + outStreamHandle, outReplacedStream); +} + +void ComposerResources::setDisplayMustValidateState(Display display, bool mustValidate) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + auto* displayResource = findDisplayResourceLocked(display); + if (displayResource) { + displayResource->setMustValidateState(mustValidate); + } +} + +bool ComposerResources::mustValidateDisplay(Display display) { + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + auto* displayResource = findDisplayResourceLocked(display); + if (displayResource) { + return displayResource->mustValidate(); + } + return false; +} + +std::unique_ptr<ComposerDisplayResource> ComposerResources::createDisplayResource( + ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) { + return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize); +} + +std::unique_ptr<ComposerLayerResource> ComposerResources::createLayerResource( + uint32_t bufferCacheSize) { + return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize); +} + +ComposerDisplayResource* ComposerResources::findDisplayResourceLocked(Display display) { + auto iter = mDisplayResources.find(display); + if (iter == mDisplayResources.end()) { + return nullptr; + } + return iter->second.get(); +} + +Error ComposerResources::getHandle(Display display, Layer layer, uint32_t slot, Cache cache, + bool fromCache, const native_handle_t* rawHandle, + const native_handle_t** outHandle, + ReplacedHandle* outReplacedHandle) { + Error error; + + // import the raw handle (or ignore raw handle when fromCache is true) + const native_handle_t* importedHandle = nullptr; + if (!fromCache) { + error = (outReplacedHandle->isBuffer()) + ? mImporter.importBuffer(rawHandle, &importedHandle) + : mImporter.importStream(rawHandle, &importedHandle); + if (error != Error::NONE) { + return error; + } + } + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + + // find display/layer resource + const bool needLayerResource = (cache == ComposerResources::Cache::LAYER_BUFFER || + cache == ComposerResources::Cache::LAYER_SIDEBAND_STREAM); + ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); + ComposerLayerResource* layerResource = (displayResource && needLayerResource) + ? displayResource->findLayerResource(layer) + : nullptr; + + // lookup or update cache + const native_handle_t* replacedHandle = nullptr; + if (displayResource && (!needLayerResource || layerResource)) { + switch (cache) { + case ComposerResources::Cache::CLIENT_TARGET: + error = displayResource->getClientTarget(slot, fromCache, importedHandle, outHandle, + &replacedHandle); + break; + case ComposerResources::Cache::OUTPUT_BUFFER: + error = displayResource->getOutputBuffer(slot, fromCache, importedHandle, outHandle, + &replacedHandle); + break; + case ComposerResources::Cache::LAYER_BUFFER: + error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle, + &replacedHandle); + break; + case ComposerResources::Cache::LAYER_SIDEBAND_STREAM: + error = layerResource->getSidebandStream(slot, fromCache, importedHandle, outHandle, + &replacedHandle); + break; + default: + error = Error::BAD_PARAMETER; + break; + } + + if (error != Error::NONE) { + ALOGW("invalid cache %d slot %d", int(cache), int(slot)); + } + } else if (!displayResource) { + error = Error::BAD_DISPLAY; + } else { + error = Error::BAD_LAYER; + } + + // clean up on errors + if (error != Error::NONE) { + if (!fromCache) { + if (outReplacedHandle->isBuffer()) { + mImporter.freeBuffer(importedHandle); + } else { + mImporter.freeStream(importedHandle); + } + } + return error; + } + + outReplacedHandle->reset(&mImporter, replacedHandle); + + return Error::NONE; +} + +} // namespace hal +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h b/service/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h new file mode 100644 index 0000000..95c2f34 --- a/dev/null +++ b/service/2.1/utils/resources/include/composer-resources/2.1/ComposerResources.h @@ -0,0 +1,288 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "ComposerResources.h included without LOG_TAG" +#endif + +#include <memory> +#include <mutex> +#include <unordered_map> +#include <vector> + +#include <android/hardware/graphics/composer/2.1/types.h> + +#include <android/hardware/graphics/mapper/2.0/IMapper.h> +#include <android/hardware/graphics/mapper/3.0/IMapper.h> +#include <android/hardware/graphics/mapper/4.0/IMapper.h> +#include <log/log.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_1 { +namespace hal { + +class ComposerUVMHandle { +public: + ComposerUVMHandle(); + ~ComposerUVMHandle(); + + bool init(); + int setUVM(); + +private: + int mFd; +}; + +// wrapper for IMapper to import buffers and sideband streams +class ComposerHandleImporter { + public: + bool init(); + + Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle); + void freeBuffer(const native_handle_t* bufferHandle); + Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle); + void freeStream(const native_handle_t* streamHandle); + + private: + sp<mapper::V2_0::IMapper> mMapper2; + sp<mapper::V3_0::IMapper> mMapper3; + sp<mapper::V4_0::IMapper> mMapper4; +}; + +class ComposerHandleCache { + public: + enum class HandleType { + INVALID, + BUFFER, + STREAM, + }; + + enum class DrmFbType { + DRM_FB_UNDEFINED = 0, + // scattered buffer, can be used for rendering. + DRM_FB_RENDER = 1, + // contiguous buffer, can be used for scanout. + DRM_FB_SCANOUT, + // video type, used for video. + DRM_FB_VIDEO, + DRM_FB_VIDEO_OVERLAY, + }; + + ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize); + + // must be initialized later with initCache + ComposerHandleCache(ComposerHandleImporter& importer); + + ~ComposerHandleCache(); + + ComposerHandleCache(const ComposerHandleCache&) = delete; + ComposerHandleCache& operator=(const ComposerHandleCache&) = delete; + + bool initCache(HandleType type, uint32_t cacheSize); + Error lookupCache(uint32_t slot, const native_handle_t** outHandle); + Error updateCache(uint32_t slot, const native_handle_t* handle, + const native_handle** outReplacedHandle); + + Error releaseCache(uint32_t slot); + bool isChangedFromeVideoToUi(const native_handle_t* handle); + + // when fromCache is true, look up in the cache; otherwise, update the cache + Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, const native_handle** outReplacedHandle); + + private: + ComposerHandleImporter& mImporter; + HandleType mHandleType = HandleType::INVALID; + DrmFbType mFbType = DrmFbType::DRM_FB_UNDEFINED; + std::vector<const native_handle_t*> mHandles; +}; + +// layer resource +class ComposerLayerResource { + public: + ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize); + + virtual ~ComposerLayerResource() = default; + + Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, const native_handle** outReplacedHandle); + Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle); + + protected: + ComposerHandleCache mBufferCache; + ComposerHandleCache mSidebandStreamCache; +}; + +// display resource +class ComposerDisplayResource { + public: + enum class DisplayType { + PHYSICAL, + VIRTUAL, + }; + + virtual ~ComposerDisplayResource() = default; + + ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, + uint32_t outputBufferCacheSize); + + bool initClientTargetCache(uint32_t cacheSize); + + bool isVirtual() const; + + Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle); + + Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle); + + bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource); + bool removeLayer(Layer layer); + ComposerLayerResource* findLayerResource(Layer layer); + std::vector<Layer> getLayers() const; + + void setMustValidateState(bool mustValidate); + + bool mustValidate() const; + + protected: + const DisplayType mType; + ComposerHandleCache mClientTargetCache; + ComposerHandleCache mOutputBufferCache; + bool mMustValidate; + + std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources; +}; + +class ComposerResources { + public: + static std::unique_ptr<ComposerResources> create(); + + ComposerResources() = default; + virtual ~ComposerResources() = default; + + bool init(); + + using RemoveDisplay = + std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>; + void clear(RemoveDisplay removeDisplay); + + Error addPhysicalDisplay(Display display); + Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize); + + Error removeDisplay(Display display); + + Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize); + + Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize); + Error removeLayer(Display display, Layer layer); + + void setDisplayMustValidateState(Display display, bool mustValidate); + + bool mustValidateDisplay(Display display); + + // When a buffer in the cache is replaced by a new one, we must keep it + // alive until it has been replaced in ComposerHal. + class ReplacedHandle { + public: + explicit ReplacedHandle(bool isBuffer) : mIsBuffer(isBuffer) {} + ReplacedHandle(const ReplacedHandle&) = delete; + ReplacedHandle& operator=(const ReplacedHandle&) = delete; + + ~ReplacedHandle() { reset(); } + + bool isBuffer() { return mIsBuffer; } + + void reset(ComposerHandleImporter* importer = nullptr, + const native_handle_t* handle = nullptr) { + if (mHandle) { + if (mIsBuffer) { + mImporter->freeBuffer(mHandle); + } else { + mImporter->freeStream(mHandle); + } + } + + mImporter = importer; + mHandle = handle; + } + + private: + bool mIsBuffer; + ComposerHandleImporter* mImporter = nullptr; + const native_handle_t* mHandle = nullptr; + }; + + Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, + const native_handle_t** outBufferHandle, + ReplacedHandle* outReplacedBuffer); + + Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, + const native_handle_t** outBufferHandle, + ReplacedHandle* outReplacedBuffer); + + Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache, + const native_handle_t* rawHandle, const native_handle_t** outBufferHandle, + ReplacedHandle* outReplacedBuffer); + + Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle, + const native_handle_t** outStreamHandle, + ReplacedHandle* outReplacedStream); + + protected: + virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource( + ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize); + + virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize); + + ComposerDisplayResource* findDisplayResourceLocked(Display display); + + ComposerHandleImporter mImporter; + ComposerUVMHandle mUVMHandle; + + std::mutex mDisplayResourcesMutex; + std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources; + + private: + enum class Cache { + CLIENT_TARGET, + OUTPUT_BUFFER, + LAYER_BUFFER, + LAYER_SIDEBAND_STREAM, + }; + + Error getHandle(Display display, Layer layer, uint32_t slot, Cache cache, bool fromCache, + const native_handle_t* rawHandle, const native_handle_t** outHandle, + ReplacedHandle* outReplacedHandle); +}; + +} // namespace hal +} // namespace V2_1 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h index 93da0a5..9b3aa90 100644 --- a/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h +++ b/service/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h @@ -173,6 +173,14 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> { Error getRenderIntents(Display display, ColorMode mode, std::vector<RenderIntent>* outIntents) override { if (!mDispatch.getRenderIntents) { + IComposerClient::DisplayType type; + if (getDisplayType(display, &type) == Error::BAD_DISPLAY) { + return Error::BAD_DISPLAY; + } + if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_P3) { + return Error::BAD_PARAMETER; + } + *outIntents = std::vector<RenderIntent>({RenderIntent::COLORIMETRIC}); return Error::NONE; } @@ -199,6 +207,9 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> { Error setColorMode_2_2(Display display, ColorMode mode, RenderIntent intent) override { if (!mDispatch.setColorModeWithRenderIntent) { + if (intent < RenderIntent::COLORIMETRIC || intent > RenderIntent::TONE_MAP_ENHANCE) { + return Error::BAD_PARAMETER; + } if (intent != RenderIntent::COLORIMETRIC) { return Error::UNSUPPORTED; } @@ -282,6 +293,7 @@ class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> { private: using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>; using BaseType2_1::getColorModes; + using BaseType2_1::getDisplayType; using BaseType2_1::mDevice; using BaseType2_1::setColorMode; using BaseType2_1::createVirtualDisplay; diff --git a/service/2.2/utils/resources/Android.bp b/service/2.2/utils/resources/Android.bp new file mode 100644 index 0000000..d040143 --- a/dev/null +++ b/service/2.2/utils/resources/Android.bp @@ -0,0 +1,29 @@ +// +// Copyright (C) 2019 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. + +cc_library_shared { + name: "android.hardware.graphics.composer@2.2-resources-vendor", + defaults: ["hidl_defaults"], + vendor: true, + shared_libs: [ + "android.hardware.graphics.composer@2.1-resources-vendor", + "android.hardware.graphics.composer@2.2", + ], + export_shared_lib_headers: [ + "android.hardware.graphics.composer@2.1-resources-vendor", + "android.hardware.graphics.composer@2.2", + ], + export_include_dirs: ["include"], +} diff --git a/service/2.2/utils/resources/ComposerResources.cpp b/service/2.2/utils/resources/ComposerResources.cpp new file mode 100644 index 0000000..a0610a3 --- a/dev/null +++ b/service/2.2/utils/resources/ComposerResources.cpp @@ -0,0 +1,84 @@ +/* + * Copyright 2019 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_TAG "ComposerResources 2.2" + +#include "composer-resources/2.2/ComposerResources.h" + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_2 { +namespace hal { + +using V2_1::Display; +using V2_1::Error; +using V2_1::Layer; +using V2_1::hal::ComposerHandleCache; +using V2_1::hal::ComposerHandleImporter; + +Error ComposerDisplayResource::getReadbackBuffer(const native_handle_t* inHandle, + const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + const uint32_t slot = 0; + const bool fromCache = false; + return mReadbackBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); +} + +std::unique_ptr<ComposerResources> ComposerResources::create() { + auto resources = std::make_unique<ComposerResources>(); + return resources->init() ? std::move(resources) : nullptr; +} + +Error ComposerResources::getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle, + const native_handle_t** outHandle, + ReplacedHandle* outReplacedHandle) { + // import buffer + const native_handle_t* importedHandle; + Error error = mImporter.importBuffer(rawHandle, &importedHandle); + if (error != Error::NONE) { + return error; + } + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + + auto iter = mDisplayResources.find(display); + if (iter == mDisplayResources.end()) { + mImporter.freeBuffer(importedHandle); + return Error::BAD_DISPLAY; + } + ComposerDisplayResource& displayResource = + *static_cast<ComposerDisplayResource*>(iter->second.get()); + + // update cache + const native_handle_t* replacedHandle; + error = displayResource.getReadbackBuffer(importedHandle, outHandle, &replacedHandle); + if (error != Error::NONE) { + mImporter.freeBuffer(importedHandle); + return error; + } + + outReplacedHandle->reset(&mImporter, replacedHandle); + return Error::NONE; +} + +} // namespace hal +} // namespace V2_2 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h b/service/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h new file mode 100644 index 0000000..33012e9 --- a/dev/null +++ b/service/2.2/utils/resources/include/composer-resources/2.2/ComposerResources.h @@ -0,0 +1,105 @@ +/* + * Copyright 2018 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "ComposerResources.h included without LOG_TAG" +#endif + +#include <composer-resources/2.1/ComposerResources.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_2 { +namespace hal { + +using V2_1::hal::ComposerHandleCache; +using V2_1::hal::ComposerHandleImporter; + +class ComposerDisplayResource : public V2_1::hal::ComposerDisplayResource { + public: + ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, + uint32_t outputBufferCacheSize) + : V2_1::hal::ComposerDisplayResource(type, importer, outputBufferCacheSize), + mReadbackBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, 1) {} + + Error getReadbackBuffer(const native_handle_t* inHandle, const native_handle_t** outHandle, + const native_handle** outReplacedHandle) { + const uint32_t slot = 0; + const bool fromCache = false; + return mReadbackBufferCache.getHandle(slot, fromCache, inHandle, outHandle, + outReplacedHandle); + } + + protected: + ComposerHandleCache mReadbackBufferCache; +}; + +class ComposerResources : public V2_1::hal::ComposerResources { + public: + static std::unique_ptr<ComposerResources> create() { + auto resources = std::make_unique<ComposerResources>(); + return resources->init() ? std::move(resources) : nullptr; + } + + Error getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle, + const native_handle_t** outHandle, + ReplacedHandle* outReplacedHandle) { + // import buffer + const native_handle_t* importedHandle; + Error error = mImporter.importBuffer(rawHandle, &importedHandle); + if (error != Error::NONE) { + return error; + } + + std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); + + auto iter = mDisplayResources.find(display); + if (iter == mDisplayResources.end()) { + mImporter.freeBuffer(importedHandle); + return Error::BAD_DISPLAY; + } + ComposerDisplayResource& displayResource = + *static_cast<ComposerDisplayResource*>(iter->second.get()); + + // update cache + const native_handle_t* replacedHandle; + error = displayResource.getReadbackBuffer(importedHandle, outHandle, &replacedHandle); + if (error != Error::NONE) { + mImporter.freeBuffer(importedHandle); + return error; + } + + outReplacedHandle->reset(&mImporter, replacedHandle); + return Error::NONE; + } + + protected: + std::unique_ptr<V2_1::hal::ComposerDisplayResource> createDisplayResource( + ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) override { + return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize); + } +}; + +} // namespace hal +} // namespace V2_2 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.3/default/Android.bp b/service/2.3/default/Android.bp index 4cde6e1..4702122 100644 --- a/service/2.3/default/Android.bp +++ b/service/2.3/default/Android.bp @@ -25,12 +25,13 @@ cc_binary { header_libs: [ "android.hardware.graphics.composer@2.3-passthrough-vendor", ], + shared_libs: [ "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", "android.hardware.graphics.composer@2.3", - "android.hardware.graphics.mapper@2.0", - "android.hardware.graphics.mapper@3.0", + "android.hardware.graphics.composer@2.1-resources-vendor", + "android.hardware.graphics.composer@2.2-resources-vendor", "libbase", "libbinder", "libcutils", diff --git a/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h index d3b29bb..e0e1394 100644 --- a/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h +++ b/service/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h @@ -294,9 +294,6 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> { (brightness < 0.0f && brightness != -1.0f)) { return Error::BAD_PARAMETER; } - if (!mDispatch.setDisplayBrightness) { - return Error::UNSUPPORTED; - } int32_t error = mDispatch.setDisplayBrightness(mDevice, display, brightness); return static_cast<Error>(error); } @@ -307,6 +304,13 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> { return false; } + if (!BaseType2_1::initDispatch(HWC2_FUNCTION_GET_DISPLAY_CAPABILITIES, + &mDispatch.getDisplayCapabilities) || + !BaseType2_1::initDispatch(HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS, + &mDispatch.setDisplayBrightness)) { + return false; + } + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA, &mDispatch.getDisplayIdentificationData); this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM, @@ -317,14 +321,10 @@ class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> { &mDispatch.setDisplayedContentSamplingEnabled); this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAYED_CONTENT_SAMPLE, &mDispatch.getDisplayedContentSample); - this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_CAPABILITIES, - &mDispatch.getDisplayCapabilities); this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_PER_FRAME_METADATA_BLOBS, &mDispatch.setLayerPerFrameMetadataBlobs); this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_BRIGHTNESS_SUPPORT, &mDispatch.getDisplayBrightnessSupport); - this->initOptionalDispatch(HWC2_FUNCTION_SET_DISPLAY_BRIGHTNESS, - &mDispatch.setDisplayBrightness); return true; } diff --git a/service/2.4/default/Android.bp b/service/2.4/default/Android.bp new file mode 100644 index 0000000..5b48e19 --- a/dev/null +++ b/service/2.4/default/Android.bp @@ -0,0 +1,48 @@ +// +// Copyright 2019 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. +// + +cc_binary { + name: "android.hardware.graphics.composer@2.4-service.droidlogic", + defaults: ["hidl_defaults"], + vendor: true, + relative_install_path: "hw", + srcs: ["service.cpp"], + vintf_fragments: ["android.hardware.graphics.composer@2.4-service.droidlogic.xml"], + init_rc: ["android.hardware.graphics.composer@2.4-service.droidlogic.rc"], + header_libs: [ + "android.hardware.graphics.composer@2.4-passthrough-vendor", + ], + shared_libs: [ + "android.hardware.graphics.composer@2.1", + "android.hardware.graphics.composer@2.2", + "android.hardware.graphics.composer@2.3", + "android.hardware.graphics.composer@2.4", + "android.hardware.graphics.composer@2.1-resources-vendor", + "android.hardware.graphics.composer@2.2-resources-vendor", + "libbase", + "libbinder", + "libcutils", + "libfmq", + "libhardware", + "libhidlbase", + "libhwc2on1adapter", + "libhwc2onfbadapter", + "liblog", + "libsync", + "libutils", + "libamgralloc_ext_vendor@2", + ], +} diff --git a/service/2.4/default/OWNERS b/service/2.4/default/OWNERS new file mode 100644 index 0000000..cc6d937 --- a/dev/null +++ b/service/2.4/default/OWNERS @@ -0,0 +1,4 @@ +# Graphics team +lpy@google.com +stoza@google.com +vhau@google.com diff --git a/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.rc b/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.rc new file mode 100644 index 0000000..ef0573f --- a/dev/null +++ b/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.rc @@ -0,0 +1,7 @@ +service vendor.hwcomposer-2-4 /vendor/bin/hw/android.hardware.graphics.composer@2.4-service.droidlogic + class hal animation + user system + group graphics drmrpc + capabilities SYS_NICE + onrestart restart surfaceflinger + writepid /dev/cpuset/system-background/tasks diff --git a/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.xml b/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.xml new file mode 100644 index 0000000..7f37bbd --- a/dev/null +++ b/service/2.4/default/android.hardware.graphics.composer@2.4-service.droidlogic.xml @@ -0,0 +1,11 @@ +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.graphics.composer</name> + <transport>hwbinder</transport> + <version>2.4</version> + <interface> + <name>IComposer</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/service/2.4/default/service.cpp b/service/2.4/default/service.cpp new file mode 100644 index 0000000..98dac3e --- a/dev/null +++ b/service/2.4/default/service.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2019 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. + */ + +#include <sched.h> + +#include <android/hardware/graphics/composer/2.4/IComposer.h> +#include <binder/ProcessState.h> +#include <composer-passthrough/2.4/HwcLoader.h> +#include <hidl/HidlTransportSupport.h> + +using android::hardware::graphics::composer::V2_4::IComposer; +using android::hardware::graphics::composer::V2_4::passthrough::HwcLoader; + +int main() { + // the conventional HAL might start binder services + android::ProcessState::initWithDriver("/dev/vndbinder"); + android::ProcessState::self()->setThreadPoolMaxThreadCount(4); + android::ProcessState::self()->startThreadPool(); + + // same as SF main thread + struct sched_param param = {0}; + param.sched_priority = 2; + if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) { + ALOGE("Couldn't set SCHED_FIFO: %d", errno); + } + + android::hardware::configureRpcThreadpool(4, true /* will join */); + + android::sp<IComposer> composer = HwcLoader::load(); + if (composer == nullptr) { + return 1; + } + if (composer->registerAsService() != android::NO_ERROR) { + ALOGE("failed to register service"); + return 1; + } + + android::hardware::joinRpcThreadpool(); + + ALOGE("service is terminating"); + return 1; +} diff --git a/service/2.4/utils/passthrough/Android.bp b/service/2.4/utils/passthrough/Android.bp new file mode 100644 index 0000000..9bd0cf9 --- a/dev/null +++ b/service/2.4/utils/passthrough/Android.bp @@ -0,0 +1,30 @@ +// +// Copyright 2019 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. +// + +cc_library_headers { + name: "android.hardware.graphics.composer@2.4-passthrough-vendor", + defaults: ["hidl_defaults"], + vendor: true, + header_libs: [ + "android.hardware.graphics.composer@2.3-passthrough-vendor", + "android.hardware.graphics.composer@2.4-hal", + ], + export_header_lib_headers: [ + "android.hardware.graphics.composer@2.3-passthrough-vendor", + "android.hardware.graphics.composer@2.4-hal", + ], + export_include_dirs: ["include"], +} diff --git a/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h b/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h new file mode 100644 index 0000000..d28e006 --- a/dev/null +++ b/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcHal.h @@ -0,0 +1,402 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcHal.h included without LOG_TAG" +#endif + +#include <type_traits> + +#include <android/hardware/graphics/composer/2.4/IComposerClient.h> +#include <composer-hal/2.4/ComposerHal.h> +#include <composer-passthrough/2.3/HwcHal.h> +#include <hardware/hwcomposer_defs.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_4 { +namespace passthrough { + +namespace detail { + +using common::V1_1::RenderIntent; +using common::V1_2::ColorMode; +using common::V1_2::Dataspace; +using common::V1_2::Hdr; +using common::V1_2::PixelFormat; +using V2_1::Config; +using V2_1::Display; +using V2_1::Layer; +using V2_4::Error; + +// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 +template <typename Hal> +class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal> { + public: + void registerEventCallback_2_4(hal::ComposerHal::EventCallback_2_4* callback) override { + mEventCallback_2_4 = callback; + + BaseType2_1::mDispatch.registerCallback( + mDevice, HWC2_CALLBACK_HOTPLUG, this, + reinterpret_cast<hwc2_function_pointer_t>(hotplugHook)); + BaseType2_1::mDispatch.registerCallback( + mDevice, HWC2_CALLBACK_REFRESH, this, + reinterpret_cast<hwc2_function_pointer_t>(refreshHook)); + BaseType2_1::mDispatch.registerCallback( + mDevice, HWC2_CALLBACK_VSYNC_2_4, this, + reinterpret_cast<hwc2_function_pointer_t>(vsync_2_4_Hook)); + BaseType2_1::mDispatch.registerCallback( + mDevice, HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, this, + reinterpret_cast<hwc2_function_pointer_t>(vsyncPeriodTimingChangedHook)); + BaseType2_1::mDispatch.registerCallback( + mDevice, HWC2_CALLBACK_SEAMLESS_POSSIBLE, this, + reinterpret_cast<hwc2_function_pointer_t>(seamlessPossibleHook)); + } + + void unregisterEventCallback_2_4() override { + // we assume the callback functions + // + // - can be unregistered + // - can be in-flight + // - will never be called afterward + // + // which is likely incorrect + BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr); + BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr); + BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_2_4, this, nullptr); + BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED, + this, nullptr); + BaseType2_1::mDispatch.registerCallback(mDevice, HWC2_CALLBACK_SEAMLESS_POSSIBLE, this, + nullptr); + + mEventCallback_2_4 = nullptr; + } + + Error getDisplayCapabilities_2_4( + Display display, + std::vector<IComposerClient::DisplayCapability>* outCapabilities) override { + std::vector<V2_3::IComposerClient::DisplayCapability> capabilities; + V2_3::Error error_2_3 = BaseType2_3::getDisplayCapabilities(display, &capabilities); + Error error = static_cast<Error>(error_2_3); + if (error != Error::NONE) { + return error; + } + outCapabilities->clear(); + outCapabilities->reserve(capabilities.size()); + for (auto capability : capabilities) { + outCapabilities->push_back(static_cast<IComposerClient::DisplayCapability>(capability)); + } + return Error::NONE; + } + + Error getDisplayConnectionType(Display display, + IComposerClient::DisplayConnectionType* outType) override { + if (!mDispatch.getDisplayConnectionType) { + return Error::UNSUPPORTED; + } + + uint32_t type = HWC2_DISPLAY_CONNECTION_TYPE_INTERNAL; + int32_t error = mDispatch.getDisplayConnectionType(mDevice, display, &type); + *outType = static_cast<IComposerClient::DisplayConnectionType>(type); + return static_cast<Error>(error); + } + + Error getDisplayAttribute_2_4(Display display, Config config, + IComposerClient::Attribute attribute, + int32_t* outValue) override { + int32_t err = BaseType2_1::mDispatch.getDisplayAttribute( + mDevice, display, config, static_cast<int32_t>(attribute), outValue); + if (err != HWC2_ERROR_NONE && *outValue == -1) { + // Convert the error from hwcomposer2 to IComposerClient definition + return Error::BAD_PARAMETER; + } + return static_cast<Error>(err); + } + + Error getDisplayVsyncPeriod(Display display, VsyncPeriodNanos* outVsyncPeriod) override { + if (!mDispatch.getDisplayVsyncPeriod) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.getDisplayVsyncPeriod(mDevice, display, outVsyncPeriod); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error setActiveConfigWithConstraints( + Display display, Config config, + const IComposerClient::VsyncPeriodChangeConstraints& vsyncPeriodChangeConstraints, + VsyncPeriodChangeTimeline* timeline) override { + if (!mDispatch.setActiveConfigWithConstraints) { + return Error::UNSUPPORTED; + } + + hwc_vsync_period_change_constraints_t vsync_period_change_constraints; + vsync_period_change_constraints.desiredTimeNanos = + vsyncPeriodChangeConstraints.desiredTimeNanos; + vsync_period_change_constraints.seamlessRequired = + vsyncPeriodChangeConstraints.seamlessRequired; + + hwc_vsync_period_change_timeline_t out_timeline; + int32_t error = mDispatch.setActiveConfigWithConstraints( + mDevice, display, config, &vsync_period_change_constraints, &out_timeline); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + timeline->newVsyncAppliedTimeNanos = out_timeline.newVsyncAppliedTimeNanos; + timeline->refreshRequired = out_timeline.refreshRequired; + timeline->refreshTimeNanos = out_timeline.refreshTimeNanos; + return Error::NONE; + } + + Error setAutoLowLatencyMode(Display display, bool on) override { + if (!mDispatch.setAutoLowLatencyMode) { + return Error::UNSUPPORTED; + } + + int32_t error = mDispatch.setAutoLowLatencyMode(mDevice, display, on); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error getSupportedContentTypes( + Display display, + std::vector<IComposerClient::ContentType>* outSupportedContentTypes) override { + if (!mDispatch.getSupportedContentTypes) { + return Error::UNSUPPORTED; + } + + uint32_t count = 0; + int32_t error = mDispatch.getSupportedContentTypes(mDevice, display, &count, nullptr); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + + outSupportedContentTypes->resize(count); + + error = mDispatch.getSupportedContentTypes( + mDevice, display, &count, + reinterpret_cast<std::underlying_type<IComposerClient::ContentType>::type*>( + outSupportedContentTypes->data())); + if (error != HWC2_ERROR_NONE) { + *outSupportedContentTypes = std::vector<IComposerClient::ContentType>(); + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error setContentType(Display display, IComposerClient::ContentType contentType) override { + if (!mDispatch.setContentType) { + return Error::UNSUPPORTED; + } + + int32_t error = + mDispatch.setContentType(mDevice, display, static_cast<int32_t>(contentType)); + if (error != HWC2_ERROR_NONE) { + return static_cast<Error>(error); + } + return Error::NONE; + } + + Error validateDisplay_2_4( + Display display, std::vector<Layer>* outChangedLayers, + std::vector<IComposerClient::Composition>* outCompositionTypes, + uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers, + std::vector<uint32_t>* outRequestMasks, + IComposerClient::ClientTargetProperty* outClientTargetProperty) override { + auto err = static_cast<Error>(BaseType2_1::validateDisplay( + display, outChangedLayers, outCompositionTypes, outDisplayRequestMask, + outRequestedLayers, outRequestMasks)); + if (err != Error::NONE) { + return err; + } + + if (mDispatch.getClientTargetProperty) { + hwc_client_target_property_t clientTargetProperty; + err = static_cast<Error>( + mDispatch.getClientTargetProperty(mDevice, display, &clientTargetProperty)); + outClientTargetProperty->pixelFormat = + static_cast<PixelFormat>(clientTargetProperty.pixelFormat); + outClientTargetProperty->dataspace = + static_cast<Dataspace>(clientTargetProperty.dataspace); + } + + return err; + } + + Error setLayerGenericMetadata(Display display, Layer layer, const std::string& key, + bool mandatory, const std::vector<uint8_t>& value) override { + if (!mDispatch.setLayerGenericMetadata) { + return Error::UNSUPPORTED; + } + + if (key.size() > std::numeric_limits<uint32_t>::max()) { + return Error::BAD_PARAMETER; + } + + if (value.size() > std::numeric_limits<uint32_t>::max()) { + return Error::BAD_PARAMETER; + } + + int32_t error = mDispatch.setLayerGenericMetadata( + mDevice, display, layer, static_cast<uint32_t>(key.size()), key.c_str(), mandatory, + static_cast<uint32_t>(value.size()), value.data()); + return static_cast<Error>(error); + } + + Error getLayerGenericMetadataKeys( + std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) override { + if (!mDispatch.getLayerGenericMetadataKey) { + return Error::UNSUPPORTED; + } + + std::vector<IComposerClient::LayerGenericMetadataKey> keys; + + uint32_t index = 0; + uint32_t keyLength = 0; + while (true) { + mDispatch.getLayerGenericMetadataKey(mDevice, index, &keyLength, nullptr, nullptr); + if (keyLength == 0) { + break; + } + + IComposerClient::LayerGenericMetadataKey key; + std::string keyName; + keyName.resize(keyLength); + mDispatch.getLayerGenericMetadataKey(mDevice, index, &keyLength, keyName.data(), + &key.mandatory); + key.name = keyName; + keys.emplace_back(std::move(key)); + + // Only attempt to load the first 100 keys to avoid an infinite loop + // if something goes wrong + if (++index > 100) { + break; + } + } + + *outKeys = std::move(keys); + return Error::NONE; + } + + protected: + bool initDispatch() override { + if (!BaseType2_3::initDispatch()) { + return false; + } + + if (!BaseType2_1::initDispatch(HWC2_FUNCTION_GET_DISPLAY_VSYNC_PERIOD, + &mDispatch.getDisplayVsyncPeriod) || + !BaseType2_1::initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS, + &mDispatch.setActiveConfigWithConstraints)) { + return false; + } + + this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_CONNECTION_TYPE, + &mDispatch.getDisplayConnectionType); + this->initOptionalDispatch(HWC2_FUNCTION_SET_AUTO_LOW_LATENCY_MODE, + &mDispatch.setAutoLowLatencyMode); + this->initOptionalDispatch(HWC2_FUNCTION_GET_SUPPORTED_CONTENT_TYPES, + &mDispatch.getSupportedContentTypes); + this->initOptionalDispatch(HWC2_FUNCTION_SET_CONTENT_TYPE, &mDispatch.setContentType); + this->initOptionalDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_PROPERTY, + &mDispatch.getClientTargetProperty); + this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_GENERIC_METADATA, + &mDispatch.setLayerGenericMetadata); + this->initOptionalDispatch(HWC2_FUNCTION_GET_LAYER_GENERIC_METADATA_KEY, + &mDispatch.getLayerGenericMetadataKey); + + return true; + } + + static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display, + int32_t connected) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback_2_4->onHotplug(display, + static_cast<IComposerCallback::Connection>(connected)); + } + + static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback_2_4->onRefresh(display); + } + + static void vsyncHook(hwc2_callback_data_t callbackData, hwc2_display_t display, + int64_t timestamp) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback_2_4->onVsync(display, timestamp); + } + + static void vsync_2_4_Hook(hwc2_callback_data_t callbackData, hwc2_display_t display, + int64_t timestamp, hwc2_vsync_period_t vsyncPeriodNanos) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback_2_4->onVsync_2_4(display, timestamp, vsyncPeriodNanos); + } + + static void vsyncPeriodTimingChangedHook(hwc2_callback_data_t callbackData, + hwc2_display_t display, + hwc_vsync_period_change_timeline_t* updated_timeline) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + VsyncPeriodChangeTimeline timeline; + timeline.newVsyncAppliedTimeNanos = updated_timeline->newVsyncAppliedTimeNanos; + timeline.refreshRequired = updated_timeline->refreshRequired; + timeline.refreshTimeNanos = updated_timeline->refreshTimeNanos; + hal->mEventCallback_2_4->onVsyncPeriodTimingChanged(display, timeline); + } + + static void seamlessPossibleHook(hwc2_callback_data_t callbackData, hwc2_display_t display) { + auto hal = static_cast<HwcHalImpl*>(callbackData); + hal->mEventCallback_2_4->onSeamlessPossible(display); + } + + private: + struct { + HWC2_PFN_GET_DISPLAY_CONNECTION_TYPE getDisplayConnectionType; + HWC2_PFN_GET_DISPLAY_VSYNC_PERIOD getDisplayVsyncPeriod; + HWC2_PFN_SET_ACTIVE_CONFIG_WITH_CONSTRAINTS setActiveConfigWithConstraints; + HWC2_PFN_SET_AUTO_LOW_LATENCY_MODE setAutoLowLatencyMode; + HWC2_PFN_GET_SUPPORTED_CONTENT_TYPES getSupportedContentTypes; + HWC2_PFN_SET_CONTENT_TYPE setContentType; + HWC2_PFN_GET_CLIENT_TARGET_PROPERTY getClientTargetProperty; + HWC2_PFN_SET_LAYER_GENERIC_METADATA setLayerGenericMetadata; + HWC2_PFN_GET_LAYER_GENERIC_METADATA_KEY getLayerGenericMetadataKey; + } mDispatch = {}; + + hal::ComposerHal::EventCallback_2_4* mEventCallback_2_4 = nullptr; + + using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>; + using BaseType2_3 = V2_3::passthrough::detail::HwcHalImpl<Hal>; + using BaseType2_1::mDevice; +}; + +} // namespace detail + +using HwcHal = detail::HwcHalImpl<hal::ComposerHal>; + +} // namespace passthrough +} // namespace V2_4 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android diff --git a/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h b/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h new file mode 100644 index 0000000..a7cc588 --- a/dev/null +++ b/service/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h @@ -0,0 +1,79 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#ifndef LOG_TAG +#warning "HwcLoader.h included without LOG_TAG" +#endif + +#include <composer-hal/2.4/Composer.h> +#include <composer-hal/2.4/ComposerHal.h> +#include <composer-passthrough/2.3/HwcLoader.h> +#include <composer-passthrough/2.4/HwcHal.h> + +namespace android { +namespace hardware { +namespace graphics { +namespace composer { +namespace V2_4 { +namespace passthrough { + +class HwcLoader : public V2_3::passthrough::HwcLoader { + public: + static IComposer* load() { + const hw_module_t* module = loadModule(); + if (!module) { + return nullptr; + } + + auto hal = createHalWithAdapter(module); + if (!hal) { + return nullptr; + } + + return createComposer(std::move(hal)).release(); + } + + // create a ComposerHal instance + static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) { + auto hal = std::make_unique<HwcHal>(); + return hal->initWithModule(module) ? std::move(hal) : nullptr; + } + + // create a ComposerHal instance, insert an adapter if necessary + static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) { + bool adapted; + hwc2_device_t* device = openDeviceWithAdapter(module, &adapted); + if (!device) { + return nullptr; + } + auto hal = std::make_unique<HwcHal>(); + return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr; + } + + // create an IComposer instance + static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) { + return hal::Composer::create(std::move(hal)); + } +}; + +} // namespace passthrough +} // namespace V2_4 +} // namespace composer +} // namespace graphics +} // namespace hardware +} // namespace android |