diff options
author | Long Ling <longling@google.com> | 2021-10-01 14:25:49 -0700 |
---|---|---|
committer | Long Ling <longling@google.com> | 2021-11-10 09:56:46 -0800 |
commit | 7b05ff5a12b053069bd9f1c07e3ad0ca9b463ec1 (patch) | |
tree | 49329c7e8dca4c05ab5b025db08528d9900bd07a /hwc3/ComposerClient.cpp | |
parent | 4af8d97f8d51a73eb5dad71ba4fad4e0ad412cee (diff) |
hwc: migrate to composer3
Bug: 201321174
Change-Id: I31834ad240c89f25427958f887a3c5015e9cb535
Diffstat (limited to 'hwc3/ComposerClient.cpp')
-rw-r--r-- | hwc3/ComposerClient.cpp | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp new file mode 100644 index 0000000..aaf6df9 --- /dev/null +++ b/hwc3/ComposerClient.cpp @@ -0,0 +1,539 @@ +/* + * Copyright (C) 2021 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL) + +#include <android-base/logging.h> + +#include "ComposerClient.h" +#include "Util.h" + +namespace aidl::android::hardware::graphics::composer3::impl { + +bool ComposerClient::init() { + DEBUG_FUNC(); + mResources = IResourceManager::create(); + if (!mResources) { + LOG(ERROR) << "failed to create composer resources"; + return false; + } + + mCommandEngine = std::make_unique<ComposerCommandEngine>(mHal, mResources.get()); + if (mCommandEngine == nullptr) { + return false; + } + if (!mCommandEngine->init()) { + mCommandEngine = nullptr; + return false; + } + + return true; +} + +ComposerClient::~ComposerClient() { + DEBUG_FUNC(); + // not initialized + if (!mCommandEngine) { + return; + } + + LOG(DEBUG) << "destroying composer client"; + + mHal->unregisterEventCallback(); + destroyResources(); + + if (mOnClientDestroyed) { + mOnClientDestroyed(); + } + + LOG(DEBUG) << "removed composer client"; +} + +// no need to check nullptr for output parameter, the aidl stub code won't pass nullptr +ndk::ScopedAStatus ComposerClient::createLayer(int64_t display, int32_t bufferSlotCount, + int64_t* layer) { + DEBUG_FUNC(); + auto err = mHal->createLayer(display, layer); + if (!err) { + err = mResources->addLayer(display, *layer, bufferSlotCount); + if (err) { + layer = 0; + } + } + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::createVirtualDisplay(int32_t width, int32_t height, + AidlPixelFormat formatHint, + int32_t outputBufferSlotCount, + VirtualDisplay* display) { + DEBUG_FUNC(); + auto err = mHal->createVirtualDisplay(width, height, formatHint, display); + if (!err) { + err = mResources->addVirtualDisplay(display->display, outputBufferSlotCount); + } + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t display, int64_t layer) { + DEBUG_FUNC(); + auto err = mHal->destroyLayer(display, layer); + if (!err) { + err = mResources->removeLayer(display, layer); + } + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t display) { + DEBUG_FUNC(); + auto err = mHal->destroyVirtualDisplay(display); + if (!err) { + err = mResources->removeDisplay(display); + } + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::executeCommands(int32_t inLength, + const std::vector<AidlNativeHandle>& inHandles, + ExecuteCommandsStatus* status) { + DEBUG_FUNC(); + std::lock_guard<std::mutex> lock(mCommandEngineMutex); + auto err = mCommandEngine->execute(inLength, inHandles, status); + mCommandEngine->reset(); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t display, int32_t* config) { + DEBUG_FUNC(); + auto err = mHal->getActiveConfig(display, config); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getColorModes(int64_t display, + std::vector<ColorMode>* colorModes) { + DEBUG_FUNC(); + auto err = mHal->getColorModes(display, colorModes); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDataspaceSaturationMatrix(common::Dataspace dataspace, + std::vector<float>* matrix) { + DEBUG_FUNC(); + if (dataspace != common::Dataspace::SRGB_LINEAR) { + return ndk::ScopedAStatus::fromStatus(EX_BAD_PARAMETER); + } + + auto err = mHal->getDataspaceSaturationMatrix(dataspace, matrix); + if (err) { + constexpr std::array<float, 16> unit { + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + }; + matrix->clear(); + matrix->insert(matrix->begin(), unit.begin(), unit.end()); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus ComposerClient::getDisplayAttribute(int64_t display, int32_t config, + DisplayAttribute attribute, int32_t* value) { + DEBUG_FUNC(); + auto err = mHal->getDisplayAttribute(display, config, attribute, value); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayBrightnessSupport(int64_t display, bool* support) { + DEBUG_FUNC(); + auto err = mHal->getDisplayBrightnessSupport(display, support); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(int64_t display, + std::vector<DisplayCapability>* caps) { + DEBUG_FUNC(); + auto err = mHal->getDisplayCapabilities(display, caps); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayConfigs(int64_t display, + std::vector<int32_t>* configs) { + DEBUG_FUNC(); + auto err = mHal->getDisplayConfigs(display, configs); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayConnectionType(int64_t display, + DisplayConnectionType* type) { + DEBUG_FUNC(); + auto err = mHal->getDisplayConnectionType(display, type); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayIdentificationData(int64_t display, + DisplayIdentification* id) { + DEBUG_FUNC(); + auto err = mHal->getDisplayIdentificationData(display, id); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t display, std::string* name) { + DEBUG_FUNC(); + auto err = mHal->getDisplayName(display, name); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(int64_t display, int32_t* vsyncPeriod) { + DEBUG_FUNC(); + auto err = mHal->getDisplayVsyncPeriod(display, vsyncPeriod); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayedContentSample(int64_t display, int64_t maxFrames, + int64_t timestamp, + DisplayContentSample* samples) { + DEBUG_FUNC(); + auto err = mHal->getDisplayedContentSample(display, maxFrames, timestamp, samples); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDisplayedContentSamplingAttributes( + int64_t display, DisplayContentSamplingAttributes* attrs) { + DEBUG_FUNC(); + auto err = mHal->getDisplayedContentSamplingAttributes(display, attrs); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getDozeSupport(int64_t display, bool* support) { + DEBUG_FUNC(); + auto err = mHal->getDozeSupport(display, support); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getHdrCapabilities(int64_t display, HdrCapabilities* caps) { + DEBUG_FUNC(); + auto err = mHal->getHdrCapabilities(display, caps); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getLayerGenericMetadataKeys( + std::vector<LayerGenericMetadataKey>* keys) { + DEBUG_FUNC(); + auto err = mHal->getLayerGenericMetadataKeys(keys); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(int32_t* count) { + DEBUG_FUNC(); + auto err = mHal->getMaxVirtualDisplayCount(count); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getOutputCommandQueue( + MQDescriptor<int32_t, SynchronizedReadWrite>* descriptor) { + DEBUG_FUNC(); + std::lock_guard<std::mutex> lock(mCommandEngineMutex); + mCommandEngine->getOutputMQDescriptor(descriptor); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus ComposerClient::getPerFrameMetadataKeys(int64_t display, + std::vector<PerFrameMetadataKey>* keys) { + DEBUG_FUNC(); + auto err = mHal->getPerFrameMetadataKeys(display, keys); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getReadbackBufferAttributes(int64_t display, + ReadbackBufferAttributes* attrs) { + DEBUG_FUNC(); + auto err = mHal->getReadbackBufferAttributes(display, attrs); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getReadbackBufferFence(int64_t display, + ndk::ScopedFileDescriptor* acquireFence) { + DEBUG_FUNC(); + auto err = mHal->getReadbackBufferFence(display, acquireFence); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getRenderIntents(int64_t display, ColorMode mode, + std::vector<RenderIntent>* intents) { + DEBUG_FUNC(); + auto err = mHal->getRenderIntents(display, mode, intents); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::getSupportedContentTypes(int64_t display, + std::vector<ContentType>* types) { + DEBUG_FUNC(); + auto err = mHal->getSupportedContentTypes(display, types); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::registerCallback( + const std::shared_ptr<IComposerCallback>& callback) { + DEBUG_FUNC(); + // no locking as we require this function to be called only once + mHalEventCallback = std::make_unique<HalEventCallback>(mHal, mResources.get(), callback); + mHal->registerEventCallback(mHalEventCallback.get()); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t display, int32_t config) { + DEBUG_FUNC(); + auto err = mHal->setActiveConfig(display, config); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints( + int64_t display, int32_t config, const VsyncPeriodChangeConstraints& constraints, + VsyncPeriodChangeTimeline* timeline) { + DEBUG_FUNC(); + auto err = mHal->setActiveConfigWithConstraints(display, config, constraints, timeline); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t display, bool on) { + DEBUG_FUNC(); + auto err = mHal->setAutoLowLatencyMode(display, on); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t display, int32_t count) { + DEBUG_FUNC(); + auto err = mResources->setDisplayClientTargetCacheSize(display, count); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setColorMode(int64_t display, ColorMode mode, + RenderIntent intent) { + DEBUG_FUNC(); + auto err = mHal->setColorMode(display, mode, intent); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setContentType(int64_t display, ContentType type) { + DEBUG_FUNC(); + auto err = mHal->setContentType(display, type); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setDisplayBrightness(int64_t display, float brightness) { + DEBUG_FUNC(); + auto err = mHal->setDisplayBrightness(display, brightness); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setDisplayedContentSamplingEnabled( + int64_t display, bool enable, FormatColorComponent componentMask, int64_t maxFrames) { + DEBUG_FUNC(); + auto err = mHal->setDisplayedContentSamplingEnabled(display, enable, componentMask, maxFrames); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setInputCommandQueue( + const MQDescriptor<int32_t, SynchronizedReadWrite>& descriptor) { + DEBUG_FUNC(); + std::lock_guard<std::mutex> lock(mCommandEngineMutex); + auto err = mCommandEngine->setInputMQDescriptor(descriptor) ? 0 : EX_NO_RESOURCES; + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display, PowerMode mode) { + DEBUG_FUNC(); + auto err = mHal->setPowerMode(display, mode); + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setReadbackBuffer( + int64_t display, const AidlNativeHandle& aidlBuffer, + const ndk::ScopedFileDescriptor& releaseFence) { + DEBUG_FUNC(); + buffer_handle_t readbackBuffer; + // Note ownership of the buffer is not passed to resource manager. + buffer_handle_t buffer = ::android::makeFromAidl(aidlBuffer); + auto bufReleaser = mResources->createReleaser(true /* isBuffer */); + auto err = mResources->getDisplayReadbackBuffer(display, buffer, + readbackBuffer, bufReleaser.get()); + if (!err) { + err = mHal->setReadbackBuffer(display, readbackBuffer, releaseFence); + } + return ndk::ScopedAStatus::fromStatus(err); +} + +ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t display, bool enabled) { + DEBUG_FUNC(); + auto err = mHal->setVsyncEnabled(display, enabled); + return ndk::ScopedAStatus::fromStatus(err); +} + +void ComposerClient::HalEventCallback::onHotplug(int64_t display, bool connected) { + DEBUG_FUNC(); + if (connected) { + if (mResources->hasDisplay(display)) { + // This is a subsequent hotplug "connected" for a display. This signals a + // display change and thus the framework may want to reallocate buffers. We + // need to free all cached handles, since they are holding a strong reference + // to the underlying buffers. + cleanDisplayResources(display); + mResources->removeDisplay(display); + } + mResources->addPhysicalDisplay(display); + } else { + mResources->removeDisplay(display); + } + + auto ret = mCallback->onHotplug(display, connected); + if (!ret.isOk()) { + LOG(ERROR) << "failed to send onHotplug:" << ret.getDescription(); + } +} + +void ComposerClient::HalEventCallback::onRefresh(int64_t display) { + DEBUG_FUNC(); + mResources->setDisplayMustValidateState(display, true); + auto ret = mCallback->onRefresh(display); + if (!ret.isOk()) { + LOG(ERROR) << "failed to send onRefresh:" << ret.getDescription(); + } +} + +void ComposerClient::HalEventCallback::onVsync(int64_t display, int64_t timestamp, + int32_t vsyncPeriodNanos) { + DEBUG_FUNC(); + auto ret = mCallback->onVsync(display, timestamp, vsyncPeriodNanos); + if (!ret.isOk()) { + LOG(ERROR) << "failed to send onVsync:" << ret.getDescription(); + } +} + +void ComposerClient::HalEventCallback::onVsyncPeriodTimingChanged( + int64_t display, const VsyncPeriodChangeTimeline& timeline) { + DEBUG_FUNC(); + auto ret = mCallback->onVsyncPeriodTimingChanged(display, timeline); + if (!ret.isOk()) { + LOG(ERROR) << "failed to send onVsyncPeriodTimingChanged:" << ret.getDescription(); + } +} + +void ComposerClient::HalEventCallback::onSeamlessPossible(int64_t display) { + DEBUG_FUNC(); + auto ret = mCallback->onSeamlessPossible(display); + if (!ret.isOk()) { + LOG(ERROR) << "failed to send onSealmessPossible:" << ret.getDescription(); + } +} + +void ComposerClient::HalEventCallback::cleanDisplayResources(int64_t display) { + DEBUG_FUNC(); + size_t cacheSize; + auto err = mResources->getDisplayClientTargetCacheSize(display, &cacheSize); + if (!err) { + for (int slot = 0; slot < cacheSize; slot++) { + // Replace the buffer slots with NULLs. Keep the old handle until it is + // replaced in ComposerHal, otherwise we risk leaving a dangling pointer. + buffer_handle_t outHandle; + auto bufReleaser = mResources->createReleaser(true /* isBuffer */); + err = mResources->getDisplayClientTarget(display, slot, /*useCache*/ true, + /*rawHandle*/ nullptr, outHandle, + bufReleaser.get()); + if (err) { + continue; + } + const std::vector<common::Rect> damage; + ndk::ScopedFileDescriptor fence; // empty fence + common::Dataspace dataspace = common::Dataspace::UNKNOWN; + err = mHal->setClientTarget(display, outHandle, fence, dataspace, damage); + if (err) { + LOG(ERROR) << "Can't clean slot " << slot + << " of the client target buffer cache for display" << display; + } + } + } else { + LOG(ERROR) << "Can't clean client target cache for display " << display; + } + + err = mResources->getDisplayOutputBufferCacheSize(display, &cacheSize); + if (!err) { + for (int slot = 0; slot < cacheSize; slot++) { + // Replace the buffer slots with NULLs. Keep the old handle until it is + // replaced in ComposerHal, otherwise we risk leaving a dangling pointer. + buffer_handle_t outputBuffer; + auto bufReleaser = mResources->createReleaser(true /* isBuffer */); + err = mResources->getDisplayOutputBuffer(display, slot, /*useCache*/ true, + /*rawHandle*/ nullptr, outputBuffer, + bufReleaser.get()); + if (err) { + continue; + } + ndk::ScopedFileDescriptor emptyFd; + err = mHal->setOutputBuffer(display, outputBuffer, /*fence*/ emptyFd); + if (err) { + LOG(ERROR) << "Can't clean slot " << slot + << " of the output buffer cache for display " << display; + } + } + } else { + LOG(ERROR) << "Can't clean output buffer cache for display " << display; + } +} + +void ComposerClient::destroyResources() { + DEBUG_FUNC(); + // We want to call hwc2_close here (and move hwc2_open to the + // constructor), with the assumption that hwc2_close would + // + // - clean up all resources owned by the client + // - make sure all displays are blank (since there is no layer) + // + // But since SF used to crash at this point, different hwcomposer2 + // implementations behave differently on hwc2_close. Our only portable + // choice really is to abort(). But that is not an option anymore + // because we might also have VTS or VR as clients that can come and go. + // + // Below we manually clean all resources (layers and virtual + // displays), and perform a presentDisplay afterwards. + mResources->clear([this](int64_t display, bool isVirtual, const std::vector<int64_t> layers) { + LOG(WARNING) << "destroying client resources for display " << display; + for (auto layer : layers) { + mHal->destroyLayer(display, layer); + } + + if (isVirtual) { + mHal->destroyVirtualDisplay(display); + } else { + LOG(WARNING) << "performing a final presentDisplay"; + std::vector<int64_t> changedLayers; + std::vector<Composition> compositionTypes; + uint32_t displayRequestMask = 0; + std::vector<int64_t> requestedLayers; + std::vector<uint32_t> requestMasks; + ClientTargetProperty clientTargetProperty; + mHal->validateDisplay(display, &changedLayers, &compositionTypes, &displayRequestMask, + &requestedLayers, &requestMasks, &clientTargetProperty); + mHal->acceptDisplayChanges(display); + + ndk::ScopedFileDescriptor presentFence; + std::vector<int64_t> releasedLayers; + std::vector<ndk::ScopedFileDescriptor> releaseFences; + mHal->presentDisplay(display, presentFence, &releasedLayers, &releaseFences); + } + }); + mResources.reset(); +} + +} // namespace aidl::android::hardware::graphics::composer3::impl |