File indexing completed on 2024-06-23 05:25:13
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2021 Xaver Hugl <xaver.hugl@gmail.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #pragma once 0011 0012 #include <QList> 0013 #include <QPoint> 0014 #include <QSize> 0015 0016 #include <chrono> 0017 #include <xf86drmMode.h> 0018 0019 #include "core/colorlut.h" 0020 #include "core/colorspace.h" 0021 #include "core/output.h" 0022 #include "core/renderloop_p.h" 0023 #include "drm_blob.h" 0024 #include "drm_connector.h" 0025 #include "drm_plane.h" 0026 0027 namespace KWin 0028 { 0029 0030 class DrmGpu; 0031 class DrmConnector; 0032 class DrmCrtc; 0033 class GammaRamp; 0034 class DrmConnectorMode; 0035 class DrmPipelineLayer; 0036 class DrmCommitThread; 0037 0038 class DrmGammaRamp 0039 { 0040 public: 0041 DrmGammaRamp(DrmCrtc *crtc, const std::shared_ptr<ColorTransformation> &transformation); 0042 0043 const ColorLUT &lut() const; 0044 std::shared_ptr<DrmBlob> blob() const; 0045 0046 private: 0047 const ColorLUT m_lut; 0048 std::shared_ptr<DrmBlob> m_blob; 0049 }; 0050 0051 class DrmPipeline 0052 { 0053 public: 0054 DrmPipeline(DrmConnector *conn); 0055 ~DrmPipeline(); 0056 0057 enum class Error { 0058 None, 0059 OutofMemory, 0060 InvalidArguments, 0061 NoPermission, 0062 FramePending, 0063 TestBufferFailed, 0064 Unknown, 0065 }; 0066 Q_ENUM(Error) 0067 0068 /** 0069 * tests the pending commit first and commits it if the test passes 0070 * if the test fails, there is a guarantee for no lasting changes 0071 */ 0072 Error present(); 0073 bool testScanout(); 0074 bool maybeModeset(); 0075 void forceLegacyModeset(); 0076 0077 bool needsModeset() const; 0078 void applyPendingChanges(); 0079 void revertPendingChanges(); 0080 0081 bool updateCursor(); 0082 0083 DrmConnector *connector() const; 0084 DrmGpu *gpu() const; 0085 0086 enum class PageflipType { 0087 Normal, 0088 CursorOnly, 0089 Modeset, 0090 }; 0091 void pageFlipped(std::chrono::nanoseconds timestamp, PageflipType type, PresentationMode mode); 0092 bool pageflipsPending() const; 0093 bool modesetPresentPending() const; 0094 void resetModesetPresentPending(); 0095 0096 QMap<uint32_t, QList<uint64_t>> formats() const; 0097 QMap<uint32_t, QList<uint64_t>> cursorFormats() const; 0098 bool hasCTM() const; 0099 bool hasGammaRamp() const; 0100 bool pruneModifier(); 0101 0102 void setOutput(DrmOutput *output); 0103 DrmOutput *output() const; 0104 0105 void setLayers(const std::shared_ptr<DrmPipelineLayer> &primaryLayer, const std::shared_ptr<DrmPipelineLayer> &cursorLayer); 0106 DrmPipelineLayer *primaryLayer() const; 0107 DrmPipelineLayer *cursorLayer() const; 0108 std::chrono::nanoseconds presentationDeadline() const; 0109 0110 DrmCrtc *crtc() const; 0111 std::shared_ptr<DrmConnectorMode> mode() const; 0112 bool active() const; 0113 bool activePending() const; 0114 bool enabled() const; 0115 DrmPlane::Transformations renderOrientation() const; 0116 PresentationMode presentationMode() const; 0117 uint32_t overscan() const; 0118 Output::RgbRange rgbRange() const; 0119 DrmConnector::DrmContentType contentType() const; 0120 const ColorDescription &colorDescription() const; 0121 const std::shared_ptr<IccProfile> &iccProfile() const; 0122 0123 void setCrtc(DrmCrtc *crtc); 0124 void setMode(const std::shared_ptr<DrmConnectorMode> &mode); 0125 void setActive(bool active); 0126 void setEnable(bool enable); 0127 void setRenderOrientation(DrmPlane::Transformations orientation); 0128 void setPresentationMode(PresentationMode mode); 0129 void setOverscan(uint32_t overscan); 0130 void setRgbRange(Output::RgbRange range); 0131 void setGammaRamp(const std::shared_ptr<ColorTransformation> &transformation); 0132 void setCTM(const QMatrix3x3 &ctm); 0133 void setContentType(DrmConnector::DrmContentType type); 0134 void setColorDescription(const ColorDescription &description); 0135 void setIccProfile(const std::shared_ptr<IccProfile> &profile); 0136 0137 enum class CommitMode { 0138 Test, 0139 TestAllowModeset, 0140 CommitModeset 0141 }; 0142 Q_ENUM(CommitMode) 0143 static Error commitPipelines(const QList<DrmPipeline *> &pipelines, CommitMode mode, const QList<DrmObject *> &unusedObjects = {}); 0144 0145 private: 0146 bool isBufferForDirectScanout() const; 0147 uint32_t calculateUnderscan(); 0148 static Error errnoToError(); 0149 std::shared_ptr<DrmBlob> createHdrMetadata(NamedTransferFunction transferFunction) const; 0150 0151 // legacy only 0152 Error presentLegacy(); 0153 Error legacyModeset(); 0154 Error applyPendingChangesLegacy(); 0155 bool setCursorLegacy(); 0156 static Error commitPipelinesLegacy(const QList<DrmPipeline *> &pipelines, CommitMode mode); 0157 0158 // atomic modesetting only 0159 Error prepareAtomicCommit(DrmAtomicCommit *commit, CommitMode mode); 0160 bool prepareAtomicModeset(DrmAtomicCommit *commit); 0161 Error prepareAtomicPresentation(DrmAtomicCommit *commit); 0162 void prepareAtomicCursor(DrmAtomicCommit *commit); 0163 void prepareAtomicDisable(DrmAtomicCommit *commit); 0164 static Error commitPipelinesAtomic(const QList<DrmPipeline *> &pipelines, CommitMode mode, const QList<DrmObject *> &unusedObjects); 0165 0166 DrmOutput *m_output = nullptr; 0167 DrmConnector *m_connector = nullptr; 0168 0169 bool m_modesetPresentPending = false; 0170 0171 struct State 0172 { 0173 DrmCrtc *crtc = nullptr; 0174 QMap<uint32_t, QList<uint64_t>> formats; 0175 bool active = true; // whether or not the pipeline should be currently used 0176 bool enabled = true; // whether or not the pipeline needs a crtc 0177 bool needsModeset = false; 0178 bool needsModesetProperties = false; 0179 std::shared_ptr<DrmConnectorMode> mode; 0180 uint32_t overscan = 0; 0181 Output::RgbRange rgbRange = Output::RgbRange::Automatic; 0182 PresentationMode presentationMode = PresentationMode::VSync; 0183 std::shared_ptr<ColorTransformation> colorTransformation; 0184 std::shared_ptr<DrmGammaRamp> gamma; 0185 std::shared_ptr<DrmBlob> ctm; 0186 DrmConnector::DrmContentType contentType = DrmConnector::DrmContentType::Graphics; 0187 0188 std::shared_ptr<IccProfile> iccProfile; 0189 ColorDescription colorDescription = ColorDescription::sRGB; 0190 0191 // the transformation that buffers submitted to the pipeline should have 0192 DrmPlane::Transformations renderOrientation = DrmPlane::Transformation::Rotate0; 0193 }; 0194 // the state that is to be tested next 0195 State m_pending; 0196 // the state that will be applied at the next real atomic commit 0197 State m_next; 0198 0199 std::unique_ptr<DrmCommitThread> m_commitThread; 0200 std::shared_ptr<DrmPipelineLayer> m_primaryLayer; 0201 std::shared_ptr<DrmPipelineLayer> m_cursorLayer; 0202 }; 0203 0204 }