diff options
Diffstat (limited to 'services/surfaceflinger/DisplayHardware/HWComposer.cpp')
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 466 |
1 files changed, 227 insertions, 239 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 7a2f0f34ee..7e45dabdea 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -26,9 +26,11 @@ #include "HWComposer.h" +#include <android-base/properties.h> #include <compositionengine/Output.h> #include <compositionengine/OutputLayer.h> #include <compositionengine/impl/OutputLayerCompositionState.h> +#include <ftl/future.h> #include <log/log.h> #include <ui/DebugUtils.h> #include <ui/GraphicBuffer.h> @@ -36,8 +38,7 @@ #include <utils/Trace.h> #include "../Layer.h" // needed only for debugging -#include "../Promise.h" -#include "../SurfaceFlinger.h" +#include "../SurfaceFlingerProperties.h" #include "ComposerHal.h" #include "HWC2.h" @@ -72,6 +73,7 @@ namespace hal = android::hardware::graphics::composer::hal; +namespace android { namespace { using android::hardware::Return; @@ -80,81 +82,74 @@ using android::HWC2::ComposerCallback; class ComposerCallbackBridge : public hal::IComposerCallback { public: - ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId, - bool vsyncSwitchingSupported) - : mCallback(callback), - mSequenceId(sequenceId), - mVsyncSwitchingSupported(vsyncSwitchingSupported) {} + ComposerCallbackBridge(ComposerCallback* callback, bool vsyncSwitchingSupported) + : mCallback(callback), mVsyncSwitchingSupported(vsyncSwitchingSupported) {} - android::hardware::Return<void> onHotplug(hal::HWDisplayId display, - hal::Connection conn) override { - mCallback->onHotplugReceived(mSequenceId, display, conn); - return android::hardware::Void(); + Return<void> onHotplug(hal::HWDisplayId display, hal::Connection connection) override { + mCallback->onComposerHalHotplug(display, connection); + return Void(); } - android::hardware::Return<void> onRefresh(hal::HWDisplayId display) override { - mCallback->onRefreshReceived(mSequenceId, display); - return android::hardware::Void(); + Return<void> onRefresh(hal::HWDisplayId display) override { + mCallback->onComposerHalRefresh(display); + return Void(); } - android::hardware::Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override { + Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override { if (!mVsyncSwitchingSupported) { - mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt); + mCallback->onComposerHalVsync(display, timestamp, std::nullopt); } else { ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring."); } - return android::hardware::Void(); + return Void(); } - android::hardware::Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp, - hal::VsyncPeriodNanos vsyncPeriodNanos) override { + Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp, + hal::VsyncPeriodNanos vsyncPeriodNanos) override { if (mVsyncSwitchingSupported) { - mCallback->onVsyncReceived(mSequenceId, display, timestamp, - std::make_optional(vsyncPeriodNanos)); + mCallback->onComposerHalVsync(display, timestamp, vsyncPeriodNanos); } else { ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring."); } - return android::hardware::Void(); + return Void(); } - android::hardware::Return<void> onVsyncPeriodTimingChanged( - hal::HWDisplayId display, - const hal::VsyncPeriodChangeTimeline& updatedTimeline) override { - mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, updatedTimeline); - return android::hardware::Void(); + Return<void> onVsyncPeriodTimingChanged( + hal::HWDisplayId display, const hal::VsyncPeriodChangeTimeline& timeline) override { + mCallback->onComposerHalVsyncPeriodTimingChanged(display, timeline); + return Void(); } - android::hardware::Return<void> onSeamlessPossible(hal::HWDisplayId display) override { - mCallback->onSeamlessPossible(mSequenceId, display); - return android::hardware::Void(); + Return<void> onSeamlessPossible(hal::HWDisplayId display) override { + mCallback->onComposerHalSeamlessPossible(display); + return Void(); } private: - ComposerCallback* mCallback; - const int32_t mSequenceId; + ComposerCallback* const mCallback; const bool mVsyncSwitchingSupported; }; } // namespace -namespace android { - HWComposer::~HWComposer() = default; namespace impl { -HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) : mComposer(std::move(composer)) { -} +HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) + : mComposer(std::move(composer)), + mMaxVirtualDisplayDimension(static_cast<size_t>(sysprop::max_virtual_display_dimension(0))), + mUpdateDeviceProductInfoOnHotplugReconnect( + sysprop::update_device_product_info_on_hotplug_reconnect(false)) {} HWComposer::HWComposer(const std::string& composerServiceName) - : mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) { -} + : HWComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {} HWComposer::~HWComposer() { mDisplayData.clear(); } -void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) { +void HWComposer::setCallback(HWC2::ComposerCallback* callback) { loadCapabilities(); loadLayerMetadataSupport(); @@ -163,10 +158,9 @@ void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequ return; } mRegisteredCallback = true; - sp<ComposerCallbackBridge> callbackBridge( - new ComposerCallbackBridge(callback, sequenceId, - mComposer->isVsyncPeriodSwitchSupported())); - mComposer->registerCallback(callbackBridge); + + mComposer->registerCallback( + sp<ComposerCallbackBridge>::make(callback, mComposer->isVsyncPeriodSwitchSupported())); } bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort, @@ -186,7 +180,7 @@ bool HWComposer::hasCapability(hal::Capability capability) const { return mCapabilities.count(capability) > 0; } -bool HWComposer::hasDisplayCapability(DisplayId displayId, +bool HWComposer::hasDisplayCapability(HalDisplayId displayId, hal::DisplayCapability capability) const { RETURN_IF_INVALID_DISPLAY(displayId, false); return mDisplayData.at(displayId).hwcDisplay->getCapabilities().count(capability) > 0; @@ -204,6 +198,10 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hal::HWDisplayId } } +bool HWComposer::updatesDeviceProductInfoOnHotplugReconnect() const { + return mUpdateDeviceProductInfoOnHotplugReconnect; +} + bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) { const auto displayId = toPhysicalDisplayId(hwcDisplayId); if (!displayId) { @@ -214,14 +212,10 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) { RETURN_IF_INVALID_DISPLAY(*displayId, false); auto& displayData = mDisplayData[*displayId]; - if (displayData.isVirtual) { - LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display"); - return false; - } + LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s", + __FUNCTION__, to_string(*displayId).c_str()); { - std::lock_guard lock(displayData.lastHwVsyncLock); - // There have been reports of HWCs that signal several vsync events // with the same timestamp when turning the display off and on. This // is a bug in the HWC implementation, but filter the extra events @@ -242,49 +236,55 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) { return true; } -std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, - ui::PixelFormat* format) { - if (mRemainingHwcVirtualDisplays == 0) { - ALOGE("%s: No remaining virtual displays", __FUNCTION__); - return {}; +size_t HWComposer::getMaxVirtualDisplayCount() const { + return mComposer->getMaxVirtualDisplayCount(); +} + +size_t HWComposer::getMaxVirtualDisplayDimension() const { + return mMaxVirtualDisplayDimension; +} + +bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size resolution, + ui::PixelFormat* format, + std::optional<PhysicalDisplayId> mirror) { + if (!resolution.isValid()) { + ALOGE("%s: Invalid resolution %dx%d", __func__, resolution.width, resolution.height); + return false; } - if (SurfaceFlinger::maxVirtualDisplaySize != 0 && - (width > SurfaceFlinger::maxVirtualDisplaySize || - height > SurfaceFlinger::maxVirtualDisplaySize)) { - ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width, - height, SurfaceFlinger::maxVirtualDisplaySize); - return {}; + const uint32_t width = static_cast<uint32_t>(resolution.width); + const uint32_t height = static_cast<uint32_t>(resolution.height); + + if (mMaxVirtualDisplayDimension > 0 && + (width > mMaxVirtualDisplayDimension || height > mMaxVirtualDisplayDimension)) { + ALOGE("%s: Resolution %ux%u exceeds maximum dimension %zu", __func__, width, height, + mMaxVirtualDisplayDimension); + return false; } - hal::HWDisplayId hwcDisplayId = 0; - const auto error = static_cast<hal::Error>( - mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId)); - if (error != hal::Error::NONE) { - ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__); - return {}; + + std::optional<hal::HWDisplayId> hwcMirrorId; + if (mirror) { + hwcMirrorId = fromPhysicalDisplayId(*mirror); } + hal::HWDisplayId hwcDisplayId; + const auto error = static_cast<hal::Error>( + mComposer->createVirtualDisplay(width, height, format, hwcMirrorId, &hwcDisplayId)); + RETURN_IF_HWC_ERROR_FOR("createVirtualDisplay", error, displayId, false); + auto display = std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId, hal::DisplayType::VIRTUAL); display->setConnected(true); - - DisplayId displayId; - if (mFreeVirtualDisplayIds.empty()) { - displayId = getVirtualDisplayId(mNextVirtualDisplayId++); - } else { - displayId = *mFreeVirtualDisplayIds.begin(); - mFreeVirtualDisplayIds.erase(displayId); - } - auto& displayData = mDisplayData[displayId]; displayData.hwcDisplay = std::move(display); displayData.isVirtual = true; - - --mRemainingHwcVirtualDisplays; - return displayId; + return true; } -void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) { +void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, + PhysicalDisplayId displayId) { + mPhysicalDisplayIdMap[hwcDisplayId] = displayId; + if (!mInternalHwcDisplayId) { mInternalHwcDisplayId = hwcDisplayId; } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) { @@ -297,129 +297,117 @@ void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayI hal::DisplayType::PHYSICAL); newDisplay->setConnected(true); displayData.hwcDisplay = std::move(newDisplay); - mPhysicalDisplayIdMap[hwcDisplayId] = displayId; } -HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { - RETURN_IF_INVALID_DISPLAY(displayId, nullptr); +int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId, + hal::Attribute attribute) const { + int32_t value = 0; + auto error = static_cast<hal::Error>( + mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value)); - HWC2::Layer* layer; - auto error = mDisplayData[displayId].hwcDisplay->createLayer(&layer); - RETURN_IF_HWC_ERROR(error, displayId, nullptr); - return layer; + RETURN_IF_HWC_ERROR_FOR("getDisplayAttribute", error, *toPhysicalDisplayId(hwcDisplayId), -1); + return value; } -void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) { - RETURN_IF_INVALID_DISPLAY(displayId); +std::shared_ptr<HWC2::Layer> HWComposer::createLayer(HalDisplayId displayId) { + RETURN_IF_INVALID_DISPLAY(displayId, nullptr); - auto error = mDisplayData[displayId].hwcDisplay->destroyLayer(layer); - RETURN_IF_HWC_ERROR(error, displayId); + auto expected = mDisplayData[displayId].hwcDisplay->createLayer(); + if (!expected.has_value()) { + auto error = std::move(expected).error(); + RETURN_IF_HWC_ERROR(error, displayId, nullptr); + } + return std::move(expected).value(); } -nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const { - RETURN_IF_INVALID_DISPLAY(displayId, 0); - const auto& displayData = mDisplayData.at(displayId); - // this returns the last refresh timestamp. - // if the last one is not available, we estimate it based on - // the refresh period and whatever closest timestamp we have. - std::lock_guard lock(displayData.lastHwVsyncLock); - nsecs_t now = systemTime(CLOCK_MONOTONIC); - auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId); - return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos); -} +bool HWComposer::isConnected(PhysicalDisplayId displayId) const { + if (mDisplayData.count(displayId)) { + return mDisplayData.at(displayId).hwcDisplay->isConnected(); + } -bool HWComposer::isConnected(DisplayId displayId) const { - RETURN_IF_INVALID_DISPLAY(displayId, false); - return mDisplayData.at(displayId).hwcDisplay->isConnected(); + return false; } -std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs( - DisplayId displayId) const { +std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); - const auto& displayData = mDisplayData.at(displayId); - auto configs = displayData.hwcDisplay->getConfigs(); - if (displayData.configMap.empty()) { - for (size_t i = 0; i < configs.size(); ++i) { - displayData.configMap[i] = configs[i]; - } + const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId(); + std::vector<hal::HWConfigId> configIds; + auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds)); + RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {}); + + std::vector<HWCDisplayMode> modes; + modes.reserve(configIds.size()); + for (auto configId : configIds) { + modes.push_back(HWCDisplayMode{ + .hwcId = configId, + .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH), + .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT), + .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD), + .dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X), + .dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y), + .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP), + }); } - return configs; -} -std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig( - DisplayId displayId) const { - RETURN_IF_INVALID_DISPLAY(displayId, nullptr); + return modes; +} - std::shared_ptr<const HWC2::Display::Config> config; - auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config); - if (error == hal::Error::BAD_CONFIG) { - LOG_DISPLAY_ERROR(displayId, "No active config"); - return nullptr; - } +std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt); - RETURN_IF_HWC_ERROR(error, displayId, nullptr); + const auto hwcId = *fromPhysicalDisplayId(displayId); + ALOGV("[%" PRIu64 "] getActiveMode", hwcId); + hal::HWConfigId configId; + auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId)); - if (!config) { - LOG_DISPLAY_ERROR(displayId, "Unknown config"); - return nullptr; + if (error == hal::Error::BAD_CONFIG) { + LOG_DISPLAY_ERROR(displayId, "No active mode"); + return std::nullopt; } - return config; + return configId; } // Composer 2.4 -DisplayConnectionType HWComposer::getDisplayConnectionType(DisplayId displayId) const { - RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal); +ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal); const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay; - DisplayConnectionType type; + ui::DisplayConnectionType type; const auto error = hwcDisplay->getConnectionType(&type); const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId - ? DisplayConnectionType::Internal - : DisplayConnectionType::External; + ? ui::DisplayConnectionType::Internal + : ui::DisplayConnectionType::External; RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE); return type; } -bool HWComposer::isVsyncPeriodSwitchSupported(DisplayId displayId) const { +bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, false); return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported(); } -nsecs_t HWComposer::getDisplayVsyncPeriod(DisplayId displayId) const { +status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId, + nsecs_t* outVsyncPeriod) const { RETURN_IF_INVALID_DISPLAY(displayId, 0); - nsecs_t vsyncPeriodNanos; - auto error = mDisplayData.at(displayId).hwcDisplay->getDisplayVsyncPeriod(&vsyncPeriodNanos); - RETURN_IF_HWC_ERROR(error, displayId, 0); - return vsyncPeriodNanos; -} - -int HWComposer::getActiveConfigIndex(DisplayId displayId) const { - RETURN_IF_INVALID_DISPLAY(displayId, -1); - - int index; - auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index); - if (error == hal::Error::BAD_CONFIG) { - LOG_DISPLAY_ERROR(displayId, "No active config"); - return -1; - } - - RETURN_IF_HWC_ERROR(error, displayId, -1); - - if (index < 0) { - LOG_DISPLAY_ERROR(displayId, "Unknown config"); - return -1; + if (!isVsyncPeriodSwitchSupported(displayId)) { + return INVALID_OPERATION; } - - return index; + const auto hwcId = *fromPhysicalDisplayId(displayId); + Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0; + auto error = + static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos)); + RETURN_IF_HWC_ERROR(error, displayId, 0); + *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos); + return NO_ERROR; } -std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const { +std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); std::vector<ui::ColorMode> modes; @@ -428,7 +416,7 @@ std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const return modes; } -status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode, +status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode, ui::RenderIntent renderIntent) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -442,14 +430,12 @@ status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode, return NO_ERROR; } -void HWComposer::setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) { +void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) { RETURN_IF_INVALID_DISPLAY(displayId); auto& displayData = mDisplayData[displayId]; - if (displayData.isVirtual) { - LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); - return; - } + LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s", + __FUNCTION__, to_string(displayId).c_str()); // NOTE: we use our own internal lock here because we have to call // into the HWC with the lock held, and we want to make sure @@ -470,7 +456,7 @@ void HWComposer::setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) { ATRACE_INT(tag.c_str(), enabled == hal::Vsync::ENABLE ? 1 : 0); } -status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot, +status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target, ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -483,7 +469,9 @@ status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot, } status_t HWComposer::getDeviceCompositionChanges( - DisplayId displayId, bool frameUsesClientComposition, + HalDisplayId displayId, bool frameUsesClientComposition, + std::chrono::steady_clock::time_point earliestPresentTime, + const std::shared_ptr<FenceTime>& previousPresentFence, std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) { ATRACE_CALL(); @@ -500,12 +488,18 @@ status_t HWComposer::getDeviceCompositionChanges( hal::Error error = hal::Error::NONE; - // First try to skip validate altogether when there is no client - // composition. When there is client composition, since we haven't - // rendered to the client target yet, we should not attempt to skip - // validate. + // First try to skip validate altogether. We can do that when + // 1. The previous frame has not been presented yet or already passed the + // earliest time to present. Otherwise, we may present a frame too early. + // 2. There is no client composition. Otherwise, we first need to render the + // client target buffer. + const bool prevFencePending = + previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING; + const bool canPresentEarly = + !prevFencePending && std::chrono::steady_clock::now() < earliestPresentTime; + const bool canSkipValidate = !canPresentEarly && !frameUsesClientComposition; displayData.validateWasSkipped = false; - if (!frameUsesClientComposition) { + if (canSkipValidate) { sp<Fence> outPresentFence; uint32_t state = UINT32_MAX; error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state); @@ -553,12 +547,12 @@ status_t HWComposer::getDeviceCompositionChanges( return NO_ERROR; } -sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const { +sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); return mDisplayData.at(displayId).lastPresentFence; } -sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const { +sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const { RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); const auto& displayFences = mDisplayData.at(displayId).releaseFences; auto fence = displayFences.find(layer); @@ -569,7 +563,9 @@ sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* lay return fence->second; } -status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { +status_t HWComposer::presentAndGetReleaseFences( + HalDisplayId displayId, std::chrono::steady_clock::time_point earliestPresentTime, + const std::shared_ptr<FenceTime>& previousPresentFence) { ATRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -585,6 +581,13 @@ status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { return NO_ERROR; } + const bool previousFramePending = + previousPresentFence->getSignalTime() == Fence::SIGNAL_TIME_PENDING; + if (!previousFramePending) { + ATRACE_NAME("wait for earliest present time"); + std::this_thread::sleep_until(earliestPresentTime); + } + auto error = hwcDisplay->present(&displayData.lastPresentFence); RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR); @@ -597,14 +600,12 @@ status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { return NO_ERROR; } -status_t HWComposer::setPowerMode(DisplayId displayId, hal::PowerMode mode) { +status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto& displayData = mDisplayData[displayId]; - if (displayData.isVirtual) { - LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); - return INVALID_OPERATION; - } + LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s", + __FUNCTION__, to_string(displayId).c_str()); if (mode == hal::PowerMode::OFF) { setVsyncEnabled(displayId, hal::Vsync::DISABLE); @@ -652,25 +653,20 @@ status_t HWComposer::setPowerMode(DisplayId displayId, hal::PowerMode mode) { return NO_ERROR; } -status_t HWComposer::setActiveConfigWithConstraints( - DisplayId displayId, size_t configId, const hal::VsyncPeriodChangeConstraints& constraints, +status_t HWComposer::setActiveModeWithConstraints( + PhysicalDisplayId displayId, hal::HWConfigId hwcModeId, + const hal::VsyncPeriodChangeConstraints& constraints, hal::VsyncPeriodChangeTimeline* outTimeline) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); - auto& displayData = mDisplayData[displayId]; - if (displayData.configMap.count(configId) == 0) { - LOG_DISPLAY_ERROR(displayId, ("Invalid config " + std::to_string(configId)).c_str()); - return BAD_INDEX; - } - - auto error = - displayData.hwcDisplay->setActiveConfigWithConstraints(displayData.configMap[configId], - constraints, outTimeline); + auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId, + constraints, + outTimeline); RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); return NO_ERROR; } -status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) { +status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; @@ -683,17 +679,9 @@ status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transfor return NO_ERROR; } -void HWComposer::disconnectDisplay(DisplayId displayId) { +void HWComposer::disconnectDisplay(HalDisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId); auto& displayData = mDisplayData[displayId]; - - // If this was a virtual display, add its slot back for reuse by future - // virtual displays - if (displayData.isVirtual) { - mFreeVirtualDisplayIds.insert(displayId); - ++mRemainingHwcVirtualDisplays; - } - const auto hwcDisplayId = displayData.hwcDisplay->getId(); // TODO(b/74619554): Select internal/external display from remaining displays. @@ -706,27 +694,25 @@ void HWComposer::disconnectDisplay(DisplayId displayId) { mDisplayData.erase(displayId); } -status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence, +status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto& displayData = mDisplayData[displayId]; - if (!displayData.isVirtual) { - LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display"); - return INVALID_OPERATION; - } + LOG_FATAL_IF(!displayData.isVirtual, "%s: Invalid operation on physical display with ID %s", + __FUNCTION__, to_string(displayId).c_str()); auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence); RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); return NO_ERROR; } -void HWComposer::clearReleaseFences(DisplayId displayId) { +void HWComposer::clearReleaseFences(HalDisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId); mDisplayData[displayId].releaseFences.clear(); } -status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) { +status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; @@ -735,12 +721,12 @@ status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* ou return NO_ERROR; } -int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const { +int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, 0); return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata(); } -std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId, +std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId, ui::ColorMode colorMode) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); @@ -750,7 +736,7 @@ std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId, return renderIntents; } -mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) { +mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, {}); mat4 matrix; @@ -760,7 +746,7 @@ mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace return matrix; } -status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId, +status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, uint8_t* outComponentMask) { @@ -774,7 +760,7 @@ status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId, return NO_ERROR; } -status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled, +status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled, uint8_t componentMask, uint64_t maxFrames) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = @@ -788,7 +774,7 @@ status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool return NO_ERROR; } -status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, +status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames, uint64_t timestamp, DisplayedFrameStats* outStats) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = @@ -798,11 +784,12 @@ status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t max return NO_ERROR; } -std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) { - RETURN_IF_INVALID_DISPLAY(displayId, promise::yield<status_t>(BAD_INDEX)); +std::future<status_t> HWComposer::setDisplayBrightness(PhysicalDisplayId displayId, + float brightness) { + RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX)); auto& display = mDisplayData[displayId].hwcDisplay; - return promise::chain(display->setDisplayBrightness(brightness)) + return ftl::chain(display->setDisplayBrightness(brightness)) .then([displayId](hal::Error error) -> status_t { if (error == hal::Error::UNSUPPORTED) { RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); @@ -815,11 +802,7 @@ std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, floa }); } -bool HWComposer::isUsingVrComposer() const { - return getComposer()->isUsingVrComposer(); -} - -status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) { +status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on); if (error == hal::Error::UNSUPPORTED) { @@ -833,7 +816,7 @@ status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) { } status_t HWComposer::getSupportedContentTypes( - DisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) { + PhysicalDisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes); @@ -843,7 +826,7 @@ status_t HWComposer::getSupportedContentTypes( return NO_ERROR; } -status_t HWComposer::setContentType(DisplayId displayId, hal::ContentType contentType) { +status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType); if (error == hal::Error::UNSUPPORTED) { @@ -865,7 +848,8 @@ void HWComposer::dump(std::string& result) const { result.append(mComposer->dumpDebugInfo()); } -std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const { +std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId( + hal::HWDisplayId hwcDisplayId) const { if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId); it != mPhysicalDisplayIdMap.end()) { return it->second; @@ -873,7 +857,8 @@ std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hal::HWDisplayId hwcDis return {}; } -std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const { +std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId( + PhysicalDisplayId displayId) const { if (const auto it = mDisplayData.find(displayId); it != mDisplayData.end() && !it->second.isVirtual) { return it->second.hwcDisplay->getId(); @@ -883,11 +868,6 @@ std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId disp bool HWComposer::shouldIgnoreHotplugConnect(hal::HWDisplayId hwcDisplayId, bool hasDisplayIdentificationData) const { - if (isUsingVrComposer() && mInternalHwcDisplayId) { - ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId); - return true; - } - if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) { ALOGE("Ignoring connection of display %" PRIu64 " without identification data", hwcDisplayId); @@ -909,6 +889,16 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect( info = DisplayIdentificationInfo{.id = *displayId, .name = std::string(), .deviceProductInfo = std::nullopt}; + if (mUpdateDeviceProductInfoOnHotplugReconnect) { + uint8_t port; + DisplayIdentificationData data; + getDisplayIdentificationData(hwcDisplayId, &port, &data); + if (auto newInfo = parseDisplayIdentificationData(port, data)) { + info->deviceProductInfo = std::move(newInfo->deviceProductInfo); + } else { + ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId); + } + } } else { uint8_t port; DisplayIdentificationData data; @@ -937,7 +927,7 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect( port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL; } - return DisplayIdentificationInfo{.id = getFallbackDisplayId(port), + return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port), .name = isPrimary ? "Internal display" : "External display", .deviceProductInfo = std::nullopt}; @@ -986,8 +976,10 @@ void HWComposer::loadLayerMetadataSupport() { std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo; const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo); if (error != hardware::graphics::composer::V2_4::Error::NONE) { - ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys", - toString(error).c_str(), static_cast<int32_t>(error)); + if (error != hardware::graphics::composer::V2_4::Error::UNSUPPORTED) { + ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys", + toString(error).c_str(), static_cast<int32_t>(error)); + } return; } @@ -996,10 +988,6 @@ void HWComposer::loadLayerMetadataSupport() { } } -uint32_t HWComposer::getMaxVirtualDisplayCount() const { - return mComposer->getMaxVirtualDisplayCount(); -} - } // namespace impl } // namespace android |