/* KWin - the KDE window manager This file is part of the KDE project. SPDX-FileCopyrightText: 2021 Xaver Hugl SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include #include #include #include #include "core/colorpipeline.h" #include "core/colorspace.h" #include "core/output.h" #include "core/renderloop_p.h" #include "drm_blob.h" #include "drm_connector.h" #include "drm_plane.h" namespace KWin { class DrmGpu; class DrmConnector; class DrmCrtc; class DrmConnectorMode; class DrmPipelineLayer; class DrmCommitThread; class OutputFrame; class DrmPipeline { public: DrmPipeline(DrmConnector *conn); ~DrmPipeline(); enum class Error { None, OutofMemory, InvalidArguments, NoPermission, FramePending, TestBufferFailed, Unknown, }; Q_ENUM(Error) /** * tests the pending commit first and commits it if the test passes * if the test fails, there is a guarantee for no lasting changes */ Error present(const std::shared_ptr &frame); bool maybeModeset(const std::shared_ptr &frame); void forceLegacyModeset(); bool needsModeset() const; void applyPendingChanges(); void revertPendingChanges(); bool updateCursor(); DrmConnector *connector() const; DrmGpu *gpu() const; void pageFlipped(std::chrono::nanoseconds timestamp); bool modesetPresentPending() const; void resetModesetPresentPending(); DrmCommitThread *commitThread() const; QHash> formats(DrmPlane::TypeIndex planeType) const; bool pruneModifier(); QList recommendedSizes(DrmPlane::TypeIndex planeType) const; void setOutput(DrmOutput *output); DrmOutput *output() const; void setLayers(const std::shared_ptr &primaryLayer, const std::shared_ptr &cursorLayer); DrmPipelineLayer *primaryLayer() const; DrmPipelineLayer *cursorLayer() const; std::chrono::nanoseconds presentationDeadline() const; DrmCrtc *crtc() const; std::shared_ptr mode() const; bool active() const; bool activePending() const; bool enabled() const; PresentationMode presentationMode() const; uint32_t overscan() const; Output::RgbRange rgbRange() const; DrmConnector::DrmContentType contentType() const; const std::shared_ptr &iccProfile() const; void setCrtc(DrmCrtc *crtc); void setMode(const std::shared_ptr &mode); void setActive(bool active); void setEnable(bool enable); void setPresentationMode(PresentationMode mode); void setOverscan(uint32_t overscan); void setRgbRange(Output::RgbRange range); void setCrtcColorPipeline(const ColorPipeline &pipeline); void setContentType(DrmConnector::DrmContentType type); void setIccProfile(const std::shared_ptr &profile); void setHighDynamicRange(bool hdr); void setWideColorGamut(bool wcg); /** * amdgpu drops cursor updates with adaptive sync: https://gitlab.freedesktop.org/drm/amd/-/issues/2186 */ bool amdgpuVrrWorkaroundActive() const; enum class CommitMode { Test, TestAllowModeset, CommitModeset }; Q_ENUM(CommitMode) static Error commitPipelines(const QList &pipelines, CommitMode mode, const QList &unusedObjects = {}); private: bool isBufferForDirectScanout() const; uint32_t calculateUnderscan(); static Error errnoToError(); std::shared_ptr createHdrMetadata(TransferFunction::Type transferFunction) const; // legacy only Error presentLegacy(const std::shared_ptr &frame); Error legacyModeset(); Error setLegacyGamma(); Error applyPendingChangesLegacy(); bool setCursorLegacy(); static Error commitPipelinesLegacy(const QList &pipelines, CommitMode mode, const QList &unusedObjects); // atomic modesetting only Error prepareAtomicCommit(DrmAtomicCommit *commit, CommitMode mode, const std::shared_ptr &frame); bool prepareAtomicModeset(DrmAtomicCommit *commit); Error prepareAtomicPresentation(DrmAtomicCommit *commit, const std::shared_ptr &frame); void prepareAtomicCursor(DrmAtomicCommit *commit); void prepareAtomicDisable(DrmAtomicCommit *commit); static Error commitPipelinesAtomic(const QList &pipelines, CommitMode mode, const std::shared_ptr &frame, const QList &unusedObjects); DrmOutput *m_output = nullptr; DrmConnector *m_connector = nullptr; bool m_modesetPresentPending = false; ColorPipeline m_currentLegacyGamma; struct State { DrmCrtc *crtc = nullptr; QHash> formats; bool active = true; // whether or not the pipeline should be currently used bool enabled = true; // whether or not the pipeline needs a crtc bool needsModeset = false; bool needsModesetProperties = false; std::shared_ptr mode; uint32_t overscan = 0; Output::RgbRange rgbRange = Output::RgbRange::Automatic; PresentationMode presentationMode = PresentationMode::VSync; ColorPipeline crtcColorPipeline; DrmConnector::DrmContentType contentType = DrmConnector::DrmContentType::Graphics; std::shared_ptr iccProfile; bool hdr = false; bool wcg = false; }; // the state that is to be tested next State m_pending; // the state that will be applied at the next real atomic commit State m_next; std::unique_ptr m_commitThread; std::shared_ptr m_primaryLayer; std::shared_ptr m_cursorLayer; }; }