25#include <QCryptographicHash>
31#include <drm_fourcc.h>
32#include <libdrm/drm_mode.h>
38static const bool s_allowColorspaceIntel = qEnvironmentVariableIntValue(
"KWIN_DRM_ALLOW_INTEL_COLORSPACE") == 1;
42 , m_pipeline(conn->pipeline())
51 if (conn->overscan.isValid() || conn->underscan.isValid()) {
53 initialState.
overscan = conn->overscan.isValid() ? conn->overscan.value() : conn->underscanVBorder.value();
55 if (conn->vrrCapable.isValid() && conn->vrrCapable.value()) {
58 if (
gpu()->asyncPageflipSupported()) {
61 if (conn->broadcastRGB.isValid()) {
65 if (m_connector->hdrMetadata.isValid() && m_connector->edid()->supportsPQ()) {
73 if (conn->isInternal()) {
80 .
name = conn->connectorName(),
82 .model = conn->modelName(),
85 .physicalSize = conn->physicalSize(),
87 .subPixel = conn->subpixel(),
90 .internal = conn->isInternal(),
91 .nonDesktop = conn->isNonDesktop(),
92 .mstPath = conn->mstPath(),
98 initialState.
modes = getModes();
106 m_turnOffTimer.setSingleShot(
true);
108 connect(&m_turnOffTimer, &QTimer::timeout,
this, [
this] {
120 if (!m_pipeline->
crtc()) {
121 qCWarning(KWIN_DRM) <<
"Can't lease connector: No suitable crtc available";
124 qCDebug(KWIN_DRM) <<
"adding connector" << m_pipeline->
connector()->
id() <<
"to lease";
126 objectList << m_pipeline->
crtc()->
id();
140 qCDebug(KWIN_DRM) <<
"ended lease for connector" << m_pipeline->
connector()->
id();
154QList<std::shared_ptr<OutputMode>> DrmOutput::getModes()
const
158 QList<std::shared_ptr<OutputMode>> ret;
159 ret.reserve(drmModes.count());
160 for (
const auto &drmMode : drmModes) {
166void DrmOutput::setDpmsMode(DpmsMode mode)
169 if (!m_turnOffTimer.isActive()) {
170 Q_EMIT
aboutToTurnOff(std::chrono::milliseconds(m_turnOffTimer.interval()));
171 m_turnOffTimer.start();
174 if (m_turnOffTimer.isActive() || (mode !=
dpmsMode() && setDrmDpmsMode(mode))) {
177 m_turnOffTimer.stop();
181bool DrmOutput::setDrmDpmsMode(DpmsMode mode)
188 if (active == isActive) {
202 doSetChannelFactors(m_channelFactors);
208 qCWarning(KWIN_DRM) <<
"Setting dpms mode failed!";
218 switch (transform.
kind()) {
220 return PlaneTrans::Rotate0;
222 return PlaneTrans::ReflectX | PlaneTrans::Rotate0;
224 return PlaneTrans::Rotate90;
226 return PlaneTrans::ReflectX | PlaneTrans::Rotate90;
228 return PlaneTrans::Rotate180;
230 return PlaneTrans::ReflectX | PlaneTrans::Rotate180;
232 return PlaneTrans::Rotate270;
234 return PlaneTrans::ReflectX | PlaneTrans::Rotate270;
243 next.
modes = getModes();
245 if (m_pipeline->
crtc()) {
254 qCWarning(KWIN_DRM) <<
"Setting changed mode failed!";
301 }
else if (!needsModeset) {
302 qCWarning(KWIN_DRM) <<
"Presentation failed!" << strerror(errno);
310 return m_connector.get();
326 m_pipeline->
setMode(std::static_pointer_cast<DrmConnectorMode>(mode));
338 if (bt2020 || hdr || m_pipeline->
iccProfile()) {
341 m_pipeline->
setCTM(QMatrix3x3{});
346ColorDescription DrmOutput::createColorDescription(
const std::shared_ptr<OutputChangeSet> &props)
const
357 }
else if (
const auto profile = props->iccProfile.value_or(
m_state.
iccProfile)) {
366 if (!m_connector->isConnected()) {
404 doSetChannelFactors(m_channelFactors);
427 return m_channelFactors == rgb || doSetChannelFactors(rgb);
430bool DrmOutput::doSetChannelFactors(
const QVector3D &rgb)
433 m_channelFactors = rgb;
442 if (m_pipeline->
hasCTM()) {
444 ctm(0, 0) = inGamma22.x();
445 ctm(1, 1) = inGamma22.y();
446 ctm(2, 2) = inGamma22.z();
451 m_channelFactorsNeedShaderFallback =
false;
454 m_pipeline->
setCTM(QMatrix3x3());
464 m_channelFactorsNeedShaderFallback =
false;
472 m_channelFactorsNeedShaderFallback = m_channelFactors != QVector3D{1, 1, 1};
478 return m_channelFactors;
483 static bool forceColorManagement = qEnvironmentVariableIntValue(
"KWIN_DRM_FORCE_COLOR_MANAGEMENT") != 0;
488#include "moc_drm_output.cpp"
static const ColorDescription sRGB
static QVector3D nitsToEncoded(const QVector3D &rgb, NamedTransferFunction tf, double sdrBrightness)
Colorimetry interpolateGamutTo(const Colorimetry &one, double factor) const
static const Colorimetry & fromName(NamedColorimetry name)
std::shared_ptr< OutputFrame > m_frame
std::unique_ptr< RenderLoop > m_renderLoop
static Output::RgbRange broadcastRgbToRgbRange(BroadcastRgbOptions rgbRange)
std::shared_ptr< DrmConnectorMode > findMode(const drmModeModeInfo &modeInfo) const
static OutputTransform toKWinTransform(PanelOrientation orientation)
QList< std::shared_ptr< DrmConnectorMode > > modes() const
DrmPlane * primaryPlane() const
drmModeModeInfo queryCurrentMode()
bool needsModeset() const
DrmBackend * platform() const
DrmPipeline::Error testPendingConfiguration()
bool setChannelFactors(const QVector3D &rgb) override
bool queueChanges(const std::shared_ptr< OutputChangeSet > &properties)
DrmOutputLayer * primaryLayer() const override
DrmOutput(const std::shared_ptr< DrmConnector > &connector)
bool present(const std::shared_ptr< OutputFrame > &frame) override
bool addLeaseObjects(QList< uint32_t > &objectList)
DrmPipeline * pipeline() const
bool updateCursorLayer() override
void updateDpmsMode(DpmsMode dpmsMode)
void revertQueuedChanges()
bool needsColormanagement() const
QVector3D channelFactors() const
DrmOutputLayer * cursorLayer() const override
DrmConnector * connector() const
void leased(DrmLease *lease)
void applyQueuedChanges(const std::shared_ptr< OutputChangeSet > &properties)
virtual QRegion currentDamage() const
Output::RgbRange rgbRange() const
DrmPipelineLayer * cursorLayer() const
DrmConnector * connector() const
bool hasGammaRamp() const
uint32_t overscan() const
void setOutput(DrmOutput *output)
void setContentType(DrmConnector::DrmContentType type)
PresentationMode presentationMode() const
void setMode(const std::shared_ptr< DrmConnectorMode > &mode)
bool needsModeset() const
const std::shared_ptr< IccProfile > & iccProfile() const
void revertPendingChanges()
void setRgbRange(Output::RgbRange range)
void applyPendingChanges()
const ColorDescription & colorDescription() const
void setEnable(bool enable)
void setCTM(const QMatrix3x3 &ctm)
void setActive(bool active)
static Error commitPipelines(const QList< DrmPipeline * > &pipelines, CommitMode mode, const QList< DrmObject * > &unusedObjects={})
void setColorDescription(const ColorDescription &description)
void setRenderOrientation(DrmPlane::Transformations orientation)
void setPresentationMode(PresentationMode mode)
std::shared_ptr< DrmConnectorMode > mode() const
void setIccProfile(const std::shared_ptr< IccProfile > &profile)
DrmPipelineLayer * primaryLayer() const
void setOverscan(uint32_t overscan)
bool activePending() const
void setGammaRamp(const std::shared_ptr< ColorTransformation > &transformation)
QString manufacturerString() const
double desiredMinLuminance() const
QByteArray eisaId() const
std::optional< double > desiredMaxFrameAverageLuminance() const
QByteArray serialNumber() const
std::optional< Colorimetry > colorimetry() const
std::optional< double > desiredMaxLuminance() const
std::shared_ptr< OutputMode > currentMode() const
void outputChange(const QRegion &damagedRegion)
uint32_t refreshRate() const
void setInformation(const Information &information)
void setState(const State &state)
OutputTransform transform() const
static std::chrono::milliseconds dimAnimationTime()
void aboutToChange(OutputChangeSet *changeSet)
uint32_t sdrBrightness() const
const Edid & edid() const
void aboutToTurnOff(std::chrono::milliseconds time)
Information m_information
Capabilities capabilities() const
DpmsMode dpmsMode() const
DrmPlane::Transformations outputToPlaneTransform(OutputTransform transform)
std::shared_ptr< OutputMode > currentMode
QList< std::shared_ptr< OutputMode > > modes
ColorDescription colorDescription
OutputTransform manualTransform
std::shared_ptr< IccProfile > iccProfile
std::optional< double > maxAverageBrightnessOverride
OutputTransform transform
std::optional< double > minBrightnessOverride
AutoRotationPolicy autoRotatePolicy
std::optional< double > maxPeakBrightnessOverride