diff options
Diffstat (limited to 'services/surfaceflinger/DisplayHardware/HWComposer.cpp')
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 466 |
1 files changed, 239 insertions, 227 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 7e45dabdea..7a2f0f34ee 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -26,11 +26,9 @@ #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> @@ -38,7 +36,8 @@ #include <utils/Trace.h> #include "../Layer.h" // needed only for debugging -#include "../SurfaceFlingerProperties.h" +#include "../Promise.h" +#include "../SurfaceFlinger.h" #include "ComposerHal.h" #include "HWC2.h" @@ -73,7 +72,6 @@ namespace hal = android::hardware::graphics::composer::hal; -namespace android { namespace { using android::hardware::Return; @@ -82,74 +80,81 @@ using android::HWC2::ComposerCallback; class ComposerCallbackBridge : public hal::IComposerCallback { public: - ComposerCallbackBridge(ComposerCallback* callback, bool vsyncSwitchingSupported) - : mCallback(callback), mVsyncSwitchingSupported(vsyncSwitchingSupported) {} + ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId, + bool vsyncSwitchingSupported) + : mCallback(callback), + mSequenceId(sequenceId), + mVsyncSwitchingSupported(vsyncSwitchingSupported) {} - Return<void> onHotplug(hal::HWDisplayId display, hal::Connection connection) override { - mCallback->onComposerHalHotplug(display, connection); - return Void(); + android::hardware::Return<void> onHotplug(hal::HWDisplayId display, + hal::Connection conn) override { + mCallback->onHotplugReceived(mSequenceId, display, conn); + return android::hardware::Void(); } - Return<void> onRefresh(hal::HWDisplayId display) override { - mCallback->onComposerHalRefresh(display); - return Void(); + android::hardware::Return<void> onRefresh(hal::HWDisplayId display) override { + mCallback->onRefreshReceived(mSequenceId, display); + return android::hardware::Void(); } - Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override { + android::hardware::Return<void> onVsync(hal::HWDisplayId display, int64_t timestamp) override { if (!mVsyncSwitchingSupported) { - mCallback->onComposerHalVsync(display, timestamp, std::nullopt); + mCallback->onVsyncReceived(mSequenceId, display, timestamp, std::nullopt); } else { ALOGW("Unexpected onVsync callback on composer >= 2.4, ignoring."); } - return Void(); + return android::hardware::Void(); } - Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp, - hal::VsyncPeriodNanos vsyncPeriodNanos) override { + android::hardware::Return<void> onVsync_2_4(hal::HWDisplayId display, int64_t timestamp, + hal::VsyncPeriodNanos vsyncPeriodNanos) override { if (mVsyncSwitchingSupported) { - mCallback->onComposerHalVsync(display, timestamp, vsyncPeriodNanos); + mCallback->onVsyncReceived(mSequenceId, display, timestamp, + std::make_optional(vsyncPeriodNanos)); } else { ALOGW("Unexpected onVsync_2_4 callback on composer <= 2.3, ignoring."); } - return Void(); + 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> onVsyncPeriodTimingChanged( + hal::HWDisplayId display, + const hal::VsyncPeriodChangeTimeline& updatedTimeline) override { + mCallback->onVsyncPeriodTimingChangedReceived(mSequenceId, display, updatedTimeline); + return android::hardware::Void(); } - Return<void> onSeamlessPossible(hal::HWDisplayId display) override { - mCallback->onComposerHalSeamlessPossible(display); - return Void(); + android::hardware::Return<void> onSeamlessPossible(hal::HWDisplayId display) override { + mCallback->onSeamlessPossible(mSequenceId, display); + return android::hardware::Void(); } private: - ComposerCallback* const mCallback; + ComposerCallback* mCallback; + const int32_t mSequenceId; const bool mVsyncSwitchingSupported; }; } // namespace +namespace android { + HWComposer::~HWComposer() = default; namespace impl { -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(std::unique_ptr<Hwc2::Composer> composer) : mComposer(std::move(composer)) { +} HWComposer::HWComposer(const std::string& composerServiceName) - : HWComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) {} + : mComposer(std::make_unique<Hwc2::impl::Composer>(composerServiceName)) { +} HWComposer::~HWComposer() { mDisplayData.clear(); } -void HWComposer::setCallback(HWC2::ComposerCallback* callback) { +void HWComposer::setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) { loadCapabilities(); loadLayerMetadataSupport(); @@ -158,9 +163,10 @@ void HWComposer::setCallback(HWC2::ComposerCallback* callback) { return; } mRegisteredCallback = true; - - mComposer->registerCallback( - sp<ComposerCallbackBridge>::make(callback, mComposer->isVsyncPeriodSwitchSupported())); + sp<ComposerCallbackBridge> callbackBridge( + new ComposerCallbackBridge(callback, sequenceId, + mComposer->isVsyncPeriodSwitchSupported())); + mComposer->registerCallback(callbackBridge); } bool HWComposer::getDisplayIdentificationData(hal::HWDisplayId hwcDisplayId, uint8_t* outPort, @@ -180,7 +186,7 @@ bool HWComposer::hasCapability(hal::Capability capability) const { return mCapabilities.count(capability) > 0; } -bool HWComposer::hasDisplayCapability(HalDisplayId displayId, +bool HWComposer::hasDisplayCapability(DisplayId displayId, hal::DisplayCapability capability) const { RETURN_IF_INVALID_DISPLAY(displayId, false); return mDisplayData.at(displayId).hwcDisplay->getCapabilities().count(capability) > 0; @@ -198,10 +204,6 @@ 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) { @@ -212,10 +214,14 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) { RETURN_IF_INVALID_DISPLAY(*displayId, false); auto& displayData = mDisplayData[*displayId]; - LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s", - __FUNCTION__, to_string(*displayId).c_str()); + if (displayData.isVirtual) { + LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display"); + return false; + } { + 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 @@ -236,55 +242,49 @@ bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) { return true; } -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; - } - - 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; +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 {}; } - std::optional<hal::HWDisplayId> hwcMirrorId; - if (mirror) { - hwcMirrorId = fromPhysicalDisplayId(*mirror); + 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 {}; } - - hal::HWDisplayId hwcDisplayId; + hal::HWDisplayId hwcDisplayId = 0; const auto error = static_cast<hal::Error>( - mComposer->createVirtualDisplay(width, height, format, hwcMirrorId, &hwcDisplayId)); - RETURN_IF_HWC_ERROR_FOR("createVirtualDisplay", error, displayId, false); + mComposer->createVirtualDisplay(width, height, format, &hwcDisplayId)); + if (error != hal::Error::NONE) { + ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__); + return {}; + } 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; - return true; -} -void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, - PhysicalDisplayId displayId) { - mPhysicalDisplayIdMap[hwcDisplayId] = displayId; + --mRemainingHwcVirtualDisplays; + return displayId; +} +void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, DisplayId displayId) { if (!mInternalHwcDisplayId) { mInternalHwcDisplayId = hwcDisplayId; } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) { @@ -297,117 +297,129 @@ void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId, hal::DisplayType::PHYSICAL); newDisplay->setConnected(true); displayData.hwcDisplay = std::move(newDisplay); + mPhysicalDisplayIdMap[hwcDisplayId] = displayId; } -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* HWComposer::createLayer(DisplayId displayId) { + RETURN_IF_INVALID_DISPLAY(displayId, nullptr); - RETURN_IF_HWC_ERROR_FOR("getDisplayAttribute", error, *toPhysicalDisplayId(hwcDisplayId), -1); - return value; + HWC2::Layer* layer; + auto error = mDisplayData[displayId].hwcDisplay->createLayer(&layer); + RETURN_IF_HWC_ERROR(error, displayId, nullptr); + return layer; } -std::shared_ptr<HWC2::Layer> HWComposer::createLayer(HalDisplayId displayId) { - RETURN_IF_INVALID_DISPLAY(displayId, nullptr); +void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) { + RETURN_IF_INVALID_DISPLAY(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(); + auto error = mDisplayData[displayId].hwcDisplay->destroyLayer(layer); + RETURN_IF_HWC_ERROR(error, displayId); } -bool HWComposer::isConnected(PhysicalDisplayId displayId) const { - if (mDisplayData.count(displayId)) { - return mDisplayData.at(displayId).hwcDisplay->isConnected(); - } +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); +} - return false; +bool HWComposer::isConnected(DisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, false); + return mDisplayData.at(displayId).hwcDisplay->isConnected(); } -std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const { +std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs( + DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); - 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), - }); + 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]; + } } - - return modes; + return configs; } -std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const { - RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt); - - const auto hwcId = *fromPhysicalDisplayId(displayId); - ALOGV("[%" PRIu64 "] getActiveMode", hwcId); - hal::HWConfigId configId; - auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId)); +std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig( + DisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, nullptr); + 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 mode"); - return std::nullopt; + LOG_DISPLAY_ERROR(displayId, "No active config"); + return nullptr; + } + + RETURN_IF_HWC_ERROR(error, displayId, nullptr); + + if (!config) { + LOG_DISPLAY_ERROR(displayId, "Unknown config"); + return nullptr; } - return configId; + return config; } // Composer 2.4 -ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const { - RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal); +DisplayConnectionType HWComposer::getDisplayConnectionType(DisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal); const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay; - ui::DisplayConnectionType type; + DisplayConnectionType type; const auto error = hwcDisplay->getConnectionType(&type); const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId - ? ui::DisplayConnectionType::Internal - : ui::DisplayConnectionType::External; + ? DisplayConnectionType::Internal + : DisplayConnectionType::External; RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE); return type; } -bool HWComposer::isVsyncPeriodSwitchSupported(PhysicalDisplayId displayId) const { +bool HWComposer::isVsyncPeriodSwitchSupported(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, false); return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported(); } -status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId, - nsecs_t* outVsyncPeriod) const { +nsecs_t HWComposer::getDisplayVsyncPeriod(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, 0); - if (!isVsyncPeriodSwitchSupported(displayId)) { - return INVALID_OPERATION; - } - const auto hwcId = *fromPhysicalDisplayId(displayId); - Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0; - auto error = - static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos)); + nsecs_t vsyncPeriodNanos; + auto error = mDisplayData.at(displayId).hwcDisplay->getDisplayVsyncPeriod(&vsyncPeriodNanos); RETURN_IF_HWC_ERROR(error, displayId, 0); - *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos); - return NO_ERROR; + 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; + } + + return index; } -std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const { +std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); std::vector<ui::ColorMode> modes; @@ -416,7 +428,7 @@ std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId return modes; } -status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMode mode, +status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode, ui::RenderIntent renderIntent) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -430,12 +442,14 @@ status_t HWComposer::setActiveColorMode(PhysicalDisplayId displayId, ui::ColorMo return NO_ERROR; } -void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled) { +void HWComposer::setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) { RETURN_IF_INVALID_DISPLAY(displayId); auto& displayData = mDisplayData[displayId]; - LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s", - __FUNCTION__, to_string(displayId).c_str()); + if (displayData.isVirtual) { + LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); + return; + } // 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 @@ -456,7 +470,7 @@ void HWComposer::setVsyncEnabled(PhysicalDisplayId displayId, hal::Vsync enabled ATRACE_INT(tag.c_str(), enabled == hal::Vsync::ENABLE ? 1 : 0); } -status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot, +status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target, ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -469,9 +483,7 @@ status_t HWComposer::setClientTarget(HalDisplayId displayId, uint32_t slot, } status_t HWComposer::getDeviceCompositionChanges( - HalDisplayId displayId, bool frameUsesClientComposition, - std::chrono::steady_clock::time_point earliestPresentTime, - const std::shared_ptr<FenceTime>& previousPresentFence, + DisplayId displayId, bool frameUsesClientComposition, std::optional<android::HWComposer::DeviceRequestedChanges>* outChanges) { ATRACE_CALL(); @@ -488,18 +500,12 @@ status_t HWComposer::getDeviceCompositionChanges( hal::Error error = hal::Error::NONE; - // 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; + // 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. displayData.validateWasSkipped = false; - if (canSkipValidate) { + if (!frameUsesClientComposition) { sp<Fence> outPresentFence; uint32_t state = UINT32_MAX; error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state); @@ -547,12 +553,12 @@ status_t HWComposer::getDeviceCompositionChanges( return NO_ERROR; } -sp<Fence> HWComposer::getPresentFence(HalDisplayId displayId) const { +sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); return mDisplayData.at(displayId).lastPresentFence; } -sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const { +sp<Fence> HWComposer::getLayerReleaseFence(DisplayId 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); @@ -563,9 +569,7 @@ sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* return fence->second; } -status_t HWComposer::presentAndGetReleaseFences( - HalDisplayId displayId, std::chrono::steady_clock::time_point earliestPresentTime, - const std::shared_ptr<FenceTime>& previousPresentFence) { +status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { ATRACE_CALL(); RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); @@ -581,13 +585,6 @@ status_t HWComposer::presentAndGetReleaseFences( 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); @@ -600,12 +597,14 @@ status_t HWComposer::presentAndGetReleaseFences( return NO_ERROR; } -status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) { +status_t HWComposer::setPowerMode(DisplayId displayId, hal::PowerMode mode) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto& displayData = mDisplayData[displayId]; - LOG_FATAL_IF(displayData.isVirtual, "%s: Invalid operation on virtual display with ID %s", - __FUNCTION__, to_string(displayId).c_str()); + if (displayData.isVirtual) { + LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); + return INVALID_OPERATION; + } if (mode == hal::PowerMode::OFF) { setVsyncEnabled(displayId, hal::Vsync::DISABLE); @@ -653,20 +652,25 @@ status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mo return NO_ERROR; } -status_t HWComposer::setActiveModeWithConstraints( - PhysicalDisplayId displayId, hal::HWConfigId hwcModeId, - const hal::VsyncPeriodChangeConstraints& constraints, +status_t HWComposer::setActiveConfigWithConstraints( + DisplayId displayId, size_t configId, const hal::VsyncPeriodChangeConstraints& constraints, hal::VsyncPeriodChangeTimeline* outTimeline) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); - auto error = mDisplayData[displayId].hwcDisplay->setActiveConfigWithConstraints(hwcModeId, - constraints, - outTimeline); + 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); RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); return NO_ERROR; } -status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& transform) { +status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& displayData = mDisplayData[displayId]; @@ -679,9 +683,17 @@ status_t HWComposer::setColorTransform(HalDisplayId displayId, const mat4& trans return NO_ERROR; } -void HWComposer::disconnectDisplay(HalDisplayId displayId) { +void HWComposer::disconnectDisplay(DisplayId 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. @@ -694,25 +706,27 @@ void HWComposer::disconnectDisplay(HalDisplayId displayId) { mDisplayData.erase(displayId); } -status_t HWComposer::setOutputBuffer(HalVirtualDisplayId displayId, const sp<Fence>& acquireFence, +status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto& displayData = mDisplayData[displayId]; - LOG_FATAL_IF(!displayData.isVirtual, "%s: Invalid operation on physical display with ID %s", - __FUNCTION__, to_string(displayId).c_str()); + if (!displayData.isVirtual) { + LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display"); + return INVALID_OPERATION; + } auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence); RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); return NO_ERROR; } -void HWComposer::clearReleaseFences(HalDisplayId displayId) { +void HWComposer::clearReleaseFences(DisplayId displayId) { RETURN_IF_INVALID_DISPLAY(displayId); mDisplayData[displayId].releaseFences.clear(); } -status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* outCapabilities) { +status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; @@ -721,12 +735,12 @@ status_t HWComposer::getHdrCapabilities(HalDisplayId displayId, HdrCapabilities* return NO_ERROR; } -int32_t HWComposer::getSupportedPerFrameMetadata(HalDisplayId displayId) const { +int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const { RETURN_IF_INVALID_DISPLAY(displayId, 0); return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata(); } -std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayId, +std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId, ui::ColorMode colorMode) const { RETURN_IF_INVALID_DISPLAY(displayId, {}); @@ -736,7 +750,7 @@ std::vector<ui::RenderIntent> HWComposer::getRenderIntents(HalDisplayId displayI return renderIntents; } -mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Dataspace dataspace) { +mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) { RETURN_IF_INVALID_DISPLAY(displayId, {}); mat4 matrix; @@ -746,7 +760,7 @@ mat4 HWComposer::getDataspaceSaturationMatrix(HalDisplayId displayId, ui::Datasp return matrix; } -status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayId, +status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, uint8_t* outComponentMask) { @@ -760,7 +774,7 @@ status_t HWComposer::getDisplayedContentSamplingAttributes(HalDisplayId displayI return NO_ERROR; } -status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bool enabled, +status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled, uint8_t componentMask, uint64_t maxFrames) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = @@ -774,7 +788,7 @@ status_t HWComposer::setDisplayContentSamplingEnabled(HalDisplayId displayId, bo return NO_ERROR; } -status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t maxFrames, +status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, uint64_t timestamp, DisplayedFrameStats* outStats) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = @@ -784,12 +798,11 @@ status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t return NO_ERROR; } -std::future<status_t> HWComposer::setDisplayBrightness(PhysicalDisplayId displayId, - float brightness) { - RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield<status_t>(BAD_INDEX)); +std::future<status_t> HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) { + RETURN_IF_INVALID_DISPLAY(displayId, promise::yield<status_t>(BAD_INDEX)); auto& display = mDisplayData[displayId].hwcDisplay; - return ftl::chain(display->setDisplayBrightness(brightness)) + return promise::chain(display->setDisplayBrightness(brightness)) .then([displayId](hal::Error error) -> status_t { if (error == hal::Error::UNSUPPORTED) { RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); @@ -802,7 +815,11 @@ std::future<status_t> HWComposer::setDisplayBrightness(PhysicalDisplayId display }); } -status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) { +bool HWComposer::isUsingVrComposer() const { + return getComposer()->isUsingVrComposer(); +} + +status_t HWComposer::setAutoLowLatencyMode(DisplayId displayId, bool on) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on); if (error == hal::Error::UNSUPPORTED) { @@ -816,7 +833,7 @@ status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) } status_t HWComposer::getSupportedContentTypes( - PhysicalDisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) { + DisplayId displayId, std::vector<hal::ContentType>* outSupportedContentTypes) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = mDisplayData[displayId].hwcDisplay->getSupportedContentTypes(outSupportedContentTypes); @@ -826,7 +843,7 @@ status_t HWComposer::getSupportedContentTypes( return NO_ERROR; } -status_t HWComposer::setContentType(PhysicalDisplayId displayId, hal::ContentType contentType) { +status_t HWComposer::setContentType(DisplayId displayId, hal::ContentType contentType) { RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); const auto error = mDisplayData[displayId].hwcDisplay->setContentType(contentType); if (error == hal::Error::UNSUPPORTED) { @@ -848,8 +865,7 @@ void HWComposer::dump(std::string& result) const { result.append(mComposer->dumpDebugInfo()); } -std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId( - hal::HWDisplayId hwcDisplayId) const { +std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const { if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId); it != mPhysicalDisplayIdMap.end()) { return it->second; @@ -857,8 +873,7 @@ std::optional<PhysicalDisplayId> HWComposer::toPhysicalDisplayId( return {}; } -std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId( - PhysicalDisplayId displayId) const { +std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const { if (const auto it = mDisplayData.find(displayId); it != mDisplayData.end() && !it->second.isVirtual) { return it->second.hwcDisplay->getId(); @@ -868,6 +883,11 @@ std::optional<hal::HWDisplayId> HWComposer::fromPhysicalDisplayId( 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); @@ -889,16 +909,6 @@ 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; @@ -927,7 +937,7 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect( port = isPrimary ? LEGACY_DISPLAY_TYPE_PRIMARY : LEGACY_DISPLAY_TYPE_EXTERNAL; } - return DisplayIdentificationInfo{.id = PhysicalDisplayId::fromPort(port), + return DisplayIdentificationInfo{.id = getFallbackDisplayId(port), .name = isPrimary ? "Internal display" : "External display", .deviceProductInfo = std::nullopt}; @@ -976,10 +986,8 @@ void HWComposer::loadLayerMetadataSupport() { std::vector<Hwc2::IComposerClient::LayerGenericMetadataKey> supportedMetadataKeyInfo; const auto error = mComposer->getLayerGenericMetadataKeys(&supportedMetadataKeyInfo); if (error != hardware::graphics::composer::V2_4::Error::NONE) { - 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)); - } + ALOGE("%s: %s failed: %s (%d)", __FUNCTION__, "getLayerGenericMetadataKeys", + toString(error).c_str(), static_cast<int32_t>(error)); return; } @@ -988,6 +996,10 @@ void HWComposer::loadLayerMetadataSupport() { } } +uint32_t HWComposer::getMaxVirtualDisplayCount() const { + return mComposer->getMaxVirtualDisplayCount(); +} + } // namespace impl } // namespace android |