diff --git a/src/backends/drm/drm_connector.cpp b/src/backends/drm/drm_connector.cpp index 56badb41be..417fc66e02 100644 --- a/src/backends/drm/drm_connector.cpp +++ b/src/backends/drm/drm_connector.cpp @@ -304,19 +304,6 @@ bool DrmConnector::updateProperties() if (scalingMode.isValid() && scalingMode.hasEnum(ScalingMode::Full_Aspect)) { m_modes.append(generateCommonModes()); } - if (m_pipeline->mode()) { - if (const auto mode = findMode(*m_pipeline->mode()->nativeMode())) { - m_pipeline->setMode(mode); - } else { - m_pipeline->setMode(m_modes.constFirst()); - } - } else { - m_pipeline->setMode(m_modes.constFirst()); - } - m_pipeline->applyPendingChanges(); - if (m_pipeline->output()) { - m_pipeline->output()->updateModes(); - } } m_mstPath.clear(); diff --git a/src/backends/drm/drm_gpu.cpp b/src/backends/drm/drm_gpu.cpp index 39b14856ce..e0e756aa8f 100644 --- a/src/backends/drm/drm_gpu.cpp +++ b/src/backends/drm/drm_gpu.cpp @@ -250,6 +250,15 @@ bool DrmGpu::updateOutputs() } } + // update crtc properties + for (const auto &crtc : std::as_const(m_crtcs)) { + crtc->updateProperties(); + } + // update plane properties + for (const auto &plane : std::as_const(m_planes)) { + plane->updateProperties(); + } + // check for added and removed connectors QList existing; QList addedOutputs; @@ -292,6 +301,8 @@ bool DrmGpu::updateOutputs() // only "enable" VR headsets here; Workspace makes this decision for normal outputs pipeline->setEnable(conn->isNonDesktop()); pipeline->applyPendingChanges(); + } else { + output->updateConnectorProperties(); } if (stillExists) { it++; @@ -301,14 +312,6 @@ bool DrmGpu::updateOutputs() } } - // update crtc properties - for (const auto &crtc : std::as_const(m_crtcs)) { - crtc->updateProperties(); - } - // update plane properties - for (const auto &plane : std::as_const(m_planes)) { - plane->updateProperties(); - } DrmPipeline::Error err = testPendingConfiguration(); if (err == DrmPipeline::Error::None) { for (const auto &pipeline : std::as_const(m_pipelines)) { diff --git a/src/backends/drm/drm_output.cpp b/src/backends/drm/drm_output.cpp index 68d43d7ae4..aff25314c5 100644 --- a/src/backends/drm/drm_output.cpp +++ b/src/backends/drm/drm_output.cpp @@ -35,7 +35,6 @@ namespace KWin { -static const bool s_allowColorspaceIntel = qEnvironmentVariableIntValue("KWIN_DRM_ALLOW_INTEL_COLORSPACE") == 1; static const bool s_disableTripleBuffering = qEnvironmentVariableIntValue("KWIN_DRM_DISABLE_TRIPLE_BUFFERING") == 1; DrmOutput::DrmOutput(const std::shared_ptr &conn) @@ -44,68 +43,30 @@ DrmOutput::DrmOutput(const std::shared_ptr &conn) , m_connector(conn) { m_pipeline->setOutput(this); - m_renderLoop->setRefreshRate(m_pipeline->mode()->refreshRate()); if (m_gpu->atomicModeSetting() && !s_disableTripleBuffering) { m_renderLoop->setMaxPendingFrameCount(2); } - Capabilities capabilities = Capability::Dpms | Capability::IccProfile; - State initialState; - - if (conn->overscan.isValid() || conn->underscan.isValid()) { - capabilities |= Capability::Overscan; - initialState.overscan = conn->overscan.isValid() ? conn->overscan.value() : conn->underscanVBorder.value(); - } - if (conn->vrrCapable.isValid() && conn->vrrCapable.value()) { - capabilities |= Capability::Vrr; - } - if (gpu()->asyncPageflipSupported()) { - capabilities |= Capability::Tearing; - } - if (conn->broadcastRGB.isValid()) { - capabilities |= Capability::RgbRange; - initialState.rgbRange = DrmConnector::broadcastRgbToRgbRange(conn->broadcastRGB.enumValue()); - } - if (m_connector->hdrMetadata.isValid() && m_connector->edid()->supportsPQ()) { - capabilities |= Capability::HighDynamicRange; - } - if (m_connector->colorspace.isValid() && m_connector->colorspace.hasEnum(DrmConnector::Colorspace::BT2020_RGB) && m_connector->edid()->supportsBT2020()) { - if (!m_gpu->isI915() || s_allowColorspaceIntel) { - capabilities |= Capability::WideColorGamut; - } - } - if (conn->isInternal()) { - // TODO only set this if an orientation sensor is available? - capabilities |= Capability::AutoRotation; - } - - const Edid *edid = conn->edid(); + const Edid *edid = m_connector->edid(); setInformation(Information{ - .name = conn->connectorName(), + .name = m_connector->connectorName(), .manufacturer = edid->manufacturerString(), - .model = conn->modelName(), + .model = m_connector->modelName(), .serialNumber = edid->serialNumber(), .eisaId = edid->eisaId(), - .physicalSize = conn->physicalSize(), + .physicalSize = m_connector->physicalSize(), .edid = *edid, - .subPixel = conn->subpixel(), - .capabilities = capabilities, - .panelOrientation = conn->panelOrientation.isValid() ? DrmConnector::toKWinTransform(conn->panelOrientation.enumValue()) : OutputTransform::Normal, - .internal = conn->isInternal(), - .nonDesktop = conn->isNonDesktop(), - .mstPath = conn->mstPath(), + .subPixel = m_connector->subpixel(), + .capabilities = computeCapabilities(), + .panelOrientation = m_connector->panelOrientation.isValid() ? DrmConnector::toKWinTransform(m_connector->panelOrientation.enumValue()) : OutputTransform::Normal, + .internal = m_connector->isInternal(), + .nonDesktop = m_connector->isNonDesktop(), + .mstPath = m_connector->mstPath(), .maxPeakBrightness = edid->desiredMaxLuminance(), .maxAverageBrightness = edid->desiredMaxFrameAverageLuminance(), .minBrightness = edid->desiredMinLuminance(), }); - - initialState.modes = getModes(); - initialState.currentMode = m_pipeline->mode(); - if (!initialState.currentMode) { - initialState.currentMode = initialState.modes.constFirst(); - } - - setState(initialState); + updateConnectorProperties(); m_turnOffTimer.setSingleShot(true); m_turnOffTimer.setInterval(dimAnimationTime()); @@ -244,8 +205,10 @@ DrmPlane::Transformations outputToPlaneTransform(OutputTransform transform) } } -void DrmOutput::updateModes() +void DrmOutput::updateConnectorProperties() { + updateInformation(); + State next = m_state; next.modes = getModes(); @@ -266,12 +229,61 @@ void DrmOutput::updateModes() next.currentMode = m_pipeline->mode(); if (!next.currentMode) { + // some mode needs to be set next.currentMode = next.modes.constFirst(); + m_renderLoop->setRefreshRate(next.currentMode->refreshRate()); + m_pipeline->setMode(std::static_pointer_cast(next.currentMode)); + m_pipeline->applyPendingChanges(); } setState(next); } +static const bool s_allowColorspaceIntel = qEnvironmentVariableIntValue("KWIN_DRM_ALLOW_INTEL_COLORSPACE") == 1; + +Output::Capabilities DrmOutput::computeCapabilities() const +{ + Capabilities capabilities = Capability::Dpms | Capability::IccProfile; + if (m_connector->overscan.isValid() || m_connector->underscan.isValid()) { + capabilities |= Capability::Overscan; + } + if (m_connector->vrrCapable.isValid() && m_connector->vrrCapable.value()) { + capabilities |= Capability::Vrr; + } + if (gpu()->asyncPageflipSupported()) { + capabilities |= Capability::Tearing; + } + if (m_connector->broadcastRGB.isValid()) { + capabilities |= Capability::RgbRange; + } + if (m_connector->hdrMetadata.isValid() && m_connector->edid()->supportsPQ()) { + capabilities |= Capability::HighDynamicRange; + } + if (m_connector->colorspace.isValid() && m_connector->colorspace.hasEnum(DrmConnector::Colorspace::BT2020_RGB) && m_connector->edid()->supportsBT2020()) { + if (!m_gpu->isI915() || s_allowColorspaceIntel) { + capabilities |= Capability::WideColorGamut; + } + } + if (m_connector->isInternal()) { + // TODO only set this if an orientation sensor is available? + capabilities |= Capability::AutoRotation; + } + return capabilities; +} + +void DrmOutput::updateInformation() +{ + // not all changes are currently handled by the rest of KWin + // so limit the changes to what's verified to work + const Edid *edid = m_connector->edid(); + Information nextInfo = m_information; + nextInfo.capabilities = computeCapabilities(); + nextInfo.maxPeakBrightness = edid->desiredMaxLuminance(); + nextInfo.maxAverageBrightness = edid->desiredMaxFrameAverageLuminance(); + nextInfo.minBrightness = edid->desiredMinLuminance(); + setInformation(nextInfo); +} + void DrmOutput::updateDpmsMode(DpmsMode dpmsMode) { State next = m_state; diff --git a/src/backends/drm/drm_output.h b/src/backends/drm/drm_output.h index 8d424147cf..2b3d614e57 100644 --- a/src/backends/drm/drm_output.h +++ b/src/backends/drm/drm_output.h @@ -48,7 +48,6 @@ public: bool queueChanges(const std::shared_ptr &properties); void applyQueuedChanges(const std::shared_ptr &properties); void revertQueuedChanges(); - void updateModes(); void updateDpmsMode(DpmsMode dpmsMode); bool updateCursorLayer() override; @@ -62,11 +61,15 @@ public: QVector3D channelFactors() const; bool needsColormanagement() const; + void updateConnectorProperties(); + private: bool setDrmDpmsMode(DpmsMode mode); void setDpmsMode(DpmsMode mode) override; bool doSetChannelFactors(const QVector3D &rgb); ColorDescription createColorDescription(const std::shared_ptr &props) const; + Capabilities computeCapabilities() const; + void updateInformation(); QList> getModes() const; diff --git a/src/core/output.cpp b/src/core/output.cpp index 18404ccc5a..f316c9c588 100644 --- a/src/core/output.cpp +++ b/src/core/output.cpp @@ -552,8 +552,12 @@ static QUuid generateOutputId(const QString &eisaId, const QString &model, void Output::setInformation(const Information &information) { + const auto oldInfo = m_information; m_information = information; m_uuid = generateOutputId(eisaId(), model(), serialNumber(), name()); + if (oldInfo.capabilities != information.capabilities) { + Q_EMIT capabilitiesChanged(); + } } void Output::setState(const State &state)