diff --git a/src/backends/drm/drm_object_connector.cpp b/src/backends/drm/drm_object_connector.cpp index 7addc6f937..88d899552f 100644 --- a/src/backends/drm/drm_object_connector.cpp +++ b/src/backends/drm/drm_object_connector.cpp @@ -94,20 +94,25 @@ bool DrmConnectorMode::operator==(const DrmConnectorMode &otherMode) } DrmConnector::DrmConnector(DrmGpu *gpu, uint32_t connectorId) - : DrmObject(gpu, connectorId, { - PropertyDefinition(QByteArrayLiteral("CRTC_ID"), Requirement::Required), - PropertyDefinition(QByteArrayLiteral("non-desktop"), Requirement::Optional), - PropertyDefinition(QByteArrayLiteral("DPMS"), Requirement::RequiredForLegacy), - PropertyDefinition(QByteArrayLiteral("EDID"), Requirement::Optional), - PropertyDefinition(QByteArrayLiteral("overscan"), Requirement::Optional), - PropertyDefinition(QByteArrayLiteral("vrr_capable"), Requirement::Optional), - PropertyDefinition(QByteArrayLiteral("underscan"), Requirement::Optional, {QByteArrayLiteral("off"), QByteArrayLiteral("on"), QByteArrayLiteral("auto")}), - PropertyDefinition(QByteArrayLiteral("underscan vborder"), Requirement::Optional), - PropertyDefinition(QByteArrayLiteral("underscan hborder"), Requirement::Optional), - PropertyDefinition(QByteArrayLiteral("Broadcast RGB"), Requirement::Optional, {QByteArrayLiteral("Automatic"), QByteArrayLiteral("Full"), QByteArrayLiteral("Limited 16:235")}), - PropertyDefinition(QByteArrayLiteral("max bpc"), Requirement::Optional), - PropertyDefinition(QByteArrayLiteral("link-status"), Requirement::Optional, {QByteArrayLiteral("Good"), QByteArrayLiteral("Bad")}), - }, + : DrmObject(gpu, + connectorId, + {PropertyDefinition(QByteArrayLiteral("CRTC_ID"), Requirement::Required), + PropertyDefinition(QByteArrayLiteral("non-desktop"), Requirement::Optional), + PropertyDefinition(QByteArrayLiteral("DPMS"), Requirement::RequiredForLegacy), + PropertyDefinition(QByteArrayLiteral("EDID"), Requirement::Optional), + PropertyDefinition(QByteArrayLiteral("overscan"), Requirement::Optional), + PropertyDefinition(QByteArrayLiteral("vrr_capable"), Requirement::Optional), + PropertyDefinition(QByteArrayLiteral("underscan"), Requirement::Optional, + {QByteArrayLiteral("off"), QByteArrayLiteral("on"), QByteArrayLiteral("auto")}), + PropertyDefinition(QByteArrayLiteral("underscan vborder"), Requirement::Optional), + PropertyDefinition(QByteArrayLiteral("underscan hborder"), Requirement::Optional), + PropertyDefinition(QByteArrayLiteral("Broadcast RGB"), Requirement::Optional, + {QByteArrayLiteral("Automatic"), QByteArrayLiteral("Full"), QByteArrayLiteral("Limited 16:235")}), + PropertyDefinition(QByteArrayLiteral("max bpc"), Requirement::Optional), + PropertyDefinition(QByteArrayLiteral("link-status"), Requirement::Optional, + {QByteArrayLiteral("Good"), QByteArrayLiteral("Bad")}), + PropertyDefinition(QByteArrayLiteral("content type"), Requirement::Optional, + {QByteArrayLiteral("No Data"), QByteArrayLiteral("Graphics"), QByteArrayLiteral("Photo"), QByteArrayLiteral("Cinema"), QByteArrayLiteral("Game")})}, DRM_MODE_OBJECT_CONNECTOR) , m_pipeline(std::make_unique(this)) , m_conn(drmModeGetConnector(gpu->fd(), connectorId)) @@ -457,4 +462,19 @@ QDebug &operator<<(QDebug &s, const KWin::DrmConnector *obj) return s; } +DrmConnector::DrmContentType DrmConnector::kwinToDrmContentType(ContentType type) +{ + switch (type) { + case ContentType::None: + return DrmContentType::Graphics; + case ContentType::Photo: + return DrmContentType::Photo; + case ContentType::Video: + return DrmContentType::Cinema; + case ContentType::Game: + return DrmContentType::Game; + default: + Q_UNREACHABLE(); + } +} } diff --git a/src/backends/drm/drm_object_connector.h b/src/backends/drm/drm_object_connector.h index b6e824c128..54e8469104 100644 --- a/src/backends/drm/drm_object_connector.h +++ b/src/backends/drm/drm_object_connector.h @@ -64,6 +64,7 @@ public: Broadcast_RGB = 9, MaxBpc = 10, LinkStatus = 11, + ContentType = 12, Count }; @@ -76,6 +77,13 @@ public: Good = 0, Bad = 1 }; + enum class DrmContentType : uint64_t { + None = 0, + Graphics = 1, + Photo = 2, + Cinema = 3, + Game = 4 + }; bool init() override; bool updateProperties() override; @@ -103,6 +111,8 @@ public: Output::RgbRange rgbRange() const; LinkStatus linkStatus() const; + static DrmContentType kwinToDrmContentType(ContentType type); + private: QList> generateCommonModes(); std::shared_ptr generateMode(const QSize &size, float refreshRate); diff --git a/src/backends/drm/drm_output.cpp b/src/backends/drm/drm_output.cpp index 114c05290c..7d8451a19d 100644 --- a/src/backends/drm/drm_output.cpp +++ b/src/backends/drm/drm_output.cpp @@ -355,8 +355,10 @@ void DrmOutput::updateDpmsMode(DpmsMode dpmsMode) bool DrmOutput::present() { RenderLoopPrivate *renderLoopPrivate = RenderLoopPrivate::get(m_renderLoop.get()); - if (m_pipeline->syncMode() != renderLoopPrivate->presentMode) { + const auto type = DrmConnector::kwinToDrmContentType(contentType()); + if (m_pipeline->syncMode() != renderLoopPrivate->presentMode || type != m_pipeline->contentType()) { m_pipeline->setSyncMode(renderLoopPrivate->presentMode); + m_pipeline->setContentType(type); if (DrmPipeline::commitPipelines({m_pipeline}, DrmPipeline::CommitMode::Test) == DrmPipeline::Error::None) { m_pipeline->applyPendingChanges(); } else { diff --git a/src/backends/drm/drm_pipeline.cpp b/src/backends/drm/drm_pipeline.cpp index 24157eb159..dd753e4346 100644 --- a/src/backends/drm/drm_pipeline.cpp +++ b/src/backends/drm/drm_pipeline.cpp @@ -205,6 +205,10 @@ DrmPipeline::Error DrmPipeline::commitPipelinesAtomic(const QVectorgetProp(DrmConnector::PropertyIndex::ContentType)) { + contentType->setEnum(m_pending.contentType); + } + m_pending.crtc->setPending(DrmCrtc::PropertyIndex::VrrEnabled, m_pending.syncMode == RenderLoopPrivate::SyncMode::Adaptive); m_pending.crtc->setPending(DrmCrtc::PropertyIndex::Gamma_LUT, m_pending.gamma ? m_pending.gamma->blobId() : 0); const auto modeSize = m_pending.mode->size(); @@ -644,6 +648,11 @@ Output::RgbRange DrmPipeline::rgbRange() const return m_pending.rgbRange; } +DrmConnector::DrmContentType DrmPipeline::contentType() const +{ + return m_pending.contentType; +} + void DrmPipeline::setCrtc(DrmCrtc *crtc) { if (crtc && m_pending.crtc && crtc->gammaRampSize() != m_pending.crtc->gammaRampSize() && m_pending.colorTransformation) { @@ -708,4 +717,9 @@ void DrmPipeline::setColorTransformation(const std::shared_ptr(m_pending.crtc, transformation); } + +void DrmPipeline::setContentType(DrmConnector::DrmContentType type) +{ + m_pending.contentType = type; +} } diff --git a/src/backends/drm/drm_pipeline.h b/src/backends/drm/drm_pipeline.h index 5d6006f61c..eb9bc8f92d 100644 --- a/src/backends/drm/drm_pipeline.h +++ b/src/backends/drm/drm_pipeline.h @@ -20,6 +20,7 @@ #include "core/output.h" #include "core/renderloop_p.h" #include "drm_object_plane.h" +#include "drm_object_connector.h" namespace KWin { @@ -112,6 +113,7 @@ public: RenderLoopPrivate::SyncMode syncMode() const; uint32_t overscan() const; Output::RgbRange rgbRange() const; + DrmConnector::DrmContentType contentType() const; void setCrtc(DrmCrtc *crtc); void setMode(const std::shared_ptr &mode); @@ -124,6 +126,7 @@ public: void setOverscan(uint32_t overscan); void setRgbRange(Output::RgbRange range); void setColorTransformation(const std::shared_ptr &transformation); + void setContentType(DrmConnector::DrmContentType type); enum class CommitMode { Test, @@ -184,6 +187,7 @@ private: RenderLoopPrivate::SyncMode syncMode = RenderLoopPrivate::SyncMode::Fixed; std::shared_ptr colorTransformation; std::shared_ptr gamma; + DrmConnector::DrmContentType contentType = DrmConnector::DrmContentType::Graphics; std::shared_ptr layer; std::shared_ptr cursorLayer; diff --git a/src/backends/drm/drm_pipeline_legacy.cpp b/src/backends/drm/drm_pipeline_legacy.cpp index e82b309288..60624e0ee4 100644 --- a/src/backends/drm/drm_pipeline_legacy.cpp +++ b/src/backends/drm/drm_pipeline_legacy.cpp @@ -118,6 +118,9 @@ DrmPipeline::Error DrmPipeline::applyPendingChangesLegacy() qCWarning(KWIN_DRM) << "Setting gamma failed!" << strerror(errno); return errnoToError(); } + if (const auto contentType = m_connector->getProp(DrmConnector::PropertyIndex::ContentType)) { + contentType->setEnumLegacy(m_pending.contentType); + } setCursorLegacy(); moveCursorLegacy(); } diff --git a/src/composite.cpp b/src/composite.cpp index 41d4a20d89..3fe325d300 100644 --- a/src/composite.cpp +++ b/src/composite.cpp @@ -628,6 +628,7 @@ void Compositor::composite(RenderLoop *renderLoop) SurfaceItem *scanoutCandidate = superLayer->delegate()->scanoutCandidate(); renderLoop->setFullscreenSurface(scanoutCandidate); + output->setContentType(scanoutCandidate ? scanoutCandidate->contentType() : ContentType::None); renderLoop->beginFrame(); bool directScanout = false; diff --git a/src/core/output.cpp b/src/core/output.cpp index bd875d0eba..374ca8551d 100644 --- a/src/core/output.cpp +++ b/src/core/output.cpp @@ -393,4 +393,14 @@ void Output::setColorTransformation(const std::shared_ptr & Q_UNUSED(transformation); } +ContentType Output::contentType() const +{ + return m_contentType; +} + +void Output::setContentType(ContentType contentType) +{ + m_contentType = contentType; +} + } // namespace KWin diff --git a/src/core/output.h b/src/core/output.h index 220435c556..a65e726309 100644 --- a/src/core/output.h +++ b/src/core/output.h @@ -238,6 +238,9 @@ public: RenderLoop::VrrPolicy vrrPolicy() const; RgbRange rgbRange() const; + ContentType contentType() const; + void setContentType(ContentType contentType); + bool isPlaceholder() const; bool isNonDesktop() const; @@ -339,6 +342,7 @@ protected: QUuid m_uuid; int m_directScanoutCount = 0; int m_refCount = 1; + ContentType m_contentType = ContentType::None; friend class EffectScreenImpl; // to access m_effectScreen }; diff --git a/src/surfaceitem.cpp b/src/surfaceitem.cpp index faab5cd3af..eeb0fad253 100644 --- a/src/surfaceitem.cpp +++ b/src/surfaceitem.cpp @@ -152,6 +152,11 @@ WindowQuadList SurfaceItem::buildQuads() const return quads; } +ContentType SurfaceItem::contentType() const +{ + return ContentType::None; +} + SurfaceTexture::~SurfaceTexture() { } diff --git a/src/surfaceitem.h b/src/surfaceitem.h index c2aecf10f1..c76053bc25 100644 --- a/src/surfaceitem.h +++ b/src/surfaceitem.h @@ -6,6 +6,7 @@ #pragma once +#include "core/output.h" #include "item.h" namespace KWin @@ -41,6 +42,8 @@ public: void referencePreviousPixmap(); void unreferencePreviousPixmap(); + virtual ContentType contentType() const; + protected: explicit SurfaceItem(Window *window, Item *parent = nullptr); diff --git a/src/surfaceitem_wayland.cpp b/src/surfaceitem_wayland.cpp index 2199edb8d8..e8853953cd 100644 --- a/src/surfaceitem_wayland.cpp +++ b/src/surfaceitem_wayland.cpp @@ -137,6 +137,11 @@ std::unique_ptr SurfaceItemWayland::createPixmap() return std::make_unique(this); } +ContentType SurfaceItemWayland::contentType() const +{ + return m_surface->contentType(); +} + SurfacePixmapWayland::SurfacePixmapWayland(SurfaceItemWayland *item, QObject *parent) : SurfacePixmap(Compositor::self()->scene()->createSurfaceTextureWayland(this), parent) , m_item(item) diff --git a/src/surfaceitem_wayland.h b/src/surfaceitem_wayland.h index 4b0f157daf..53e5da76e3 100644 --- a/src/surfaceitem_wayland.h +++ b/src/surfaceitem_wayland.h @@ -31,6 +31,7 @@ public: QRegion shape() const override; QRegion opaque() const override; + ContentType contentType() const override; KWaylandServer::SurfaceInterface *surface() const;