File indexing completed on 2026-03-08 12:24:31
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 <QPoint> 0013 #include <QSize> 0014 #include <QVector> 0015 0016 #include <chrono> 0017 #include <xf86drmMode.h> 0018 0019 #include "core/colorlut.h" 0020 #include "core/output.h" 0021 #include "core/renderloop_p.h" 0022 #include "drm_connector.h" 0023 #include "drm_plane.h" 0024 0025 namespace KWin 0026 { 0027 0028 class DrmGpu; 0029 class DrmConnector; 0030 class DrmCrtc; 0031 class GammaRamp; 0032 class DrmConnectorMode; 0033 class DrmPipelineLayer; 0034 class DrmOverlayLayer; 0035 0036 class DrmGammaRamp 0037 { 0038 public: 0039 DrmGammaRamp(DrmCrtc *crtc, const std::shared_ptr<ColorTransformation> &transformation); 0040 ~DrmGammaRamp(); 0041 0042 const ColorLUT &lut() const; 0043 uint32_t blobId() const; 0044 0045 private: 0046 DrmGpu *m_gpu; 0047 const ColorLUT m_lut; 0048 uint32_t m_blobId = 0; 0049 }; 0050 0051 class DrmCTM 0052 { 0053 public: 0054 DrmCTM(DrmGpu *gpu, const QMatrix3x3 &ctm); 0055 ~DrmCTM(); 0056 0057 uint32_t blobId() const; 0058 0059 private: 0060 DrmGpu *const m_gpu; 0061 uint32_t m_blobId = 0; 0062 }; 0063 0064 class DrmPipeline 0065 { 0066 public: 0067 DrmPipeline(DrmConnector *conn); 0068 ~DrmPipeline(); 0069 0070 enum class Error { 0071 None, 0072 OutofMemory, 0073 InvalidArguments, 0074 NoPermission, 0075 FramePending, 0076 TestBufferFailed, 0077 Unknown, 0078 }; 0079 Q_ENUM(Error) 0080 0081 /** 0082 * tests the pending commit first and commits it if the test passes 0083 * if the test fails, there is a guarantee for no lasting changes 0084 */ 0085 Error present(); 0086 bool testScanout(); 0087 bool maybeModeset(); 0088 0089 bool needsModeset() const; 0090 void applyPendingChanges(); 0091 void revertPendingChanges(); 0092 0093 bool setCursor(const QPoint &hotspot = QPoint()); 0094 bool moveCursor(); 0095 0096 DrmConnector *connector() const; 0097 DrmCrtc *currentCrtc() const; 0098 DrmGpu *gpu() const; 0099 0100 void pageFlipped(std::chrono::nanoseconds timestamp); 0101 bool pageflipPending() const; 0102 bool modesetPresentPending() const; 0103 void resetModesetPresentPending(); 0104 void printDebugInfo() const; 0105 /** 0106 * what size buffers submitted to this pipeline should have 0107 */ 0108 QSize bufferSize() const; 0109 0110 QMap<uint32_t, QVector<uint64_t>> formats() const; 0111 QMap<uint32_t, QVector<uint64_t>> cursorFormats() const; 0112 bool pruneModifier(); 0113 0114 void setOutput(DrmOutput *output); 0115 DrmOutput *output() const; 0116 0117 DrmCrtc *crtc() const; 0118 std::shared_ptr<DrmConnectorMode> mode() const; 0119 bool active() const; 0120 bool activePending() const; 0121 bool enabled() const; 0122 DrmPipelineLayer *primaryLayer() const; 0123 DrmOverlayLayer *cursorLayer() const; 0124 DrmPlane::Transformations renderOrientation() const; 0125 DrmPlane::Transformations bufferOrientation() const; 0126 RenderLoopPrivate::SyncMode syncMode() const; 0127 uint32_t overscan() const; 0128 Output::RgbRange rgbRange() const; 0129 DrmConnector::DrmContentType contentType() const; 0130 0131 void setCrtc(DrmCrtc *crtc); 0132 void setMode(const std::shared_ptr<DrmConnectorMode> &mode); 0133 void setActive(bool active); 0134 void setEnable(bool enable); 0135 void setLayers(const std::shared_ptr<DrmPipelineLayer> &primaryLayer, const std::shared_ptr<DrmOverlayLayer> &cursorLayer); 0136 void setRenderOrientation(DrmPlane::Transformations orientation); 0137 void setBufferOrientation(DrmPlane::Transformations orientation); 0138 void setSyncMode(RenderLoopPrivate::SyncMode mode); 0139 void setOverscan(uint32_t overscan); 0140 void setRgbRange(Output::RgbRange range); 0141 void setGammaRamp(const std::shared_ptr<ColorTransformation> &transformation); 0142 void setCTM(const QMatrix3x3 &ctm); 0143 void setContentType(DrmConnector::DrmContentType type); 0144 0145 enum class CommitMode { 0146 Test, 0147 TestAllowModeset, 0148 Commit, 0149 CommitModeset 0150 }; 0151 Q_ENUM(CommitMode) 0152 static Error commitPipelines(const QVector<DrmPipeline *> &pipelines, CommitMode mode, const QVector<DrmObject *> &unusedObjects = {}); 0153 0154 private: 0155 bool isBufferForDirectScanout() const; 0156 uint32_t calculateUnderscan(); 0157 static Error errnoToError(); 0158 void checkHardwareRotation(); 0159 0160 // legacy only 0161 Error presentLegacy(); 0162 Error legacyModeset(); 0163 Error applyPendingChangesLegacy(); 0164 bool setCursorLegacy(); 0165 bool moveCursorLegacy(); 0166 static Error commitPipelinesLegacy(const QVector<DrmPipeline *> &pipelines, CommitMode mode); 0167 0168 // atomic modesetting only 0169 bool populateAtomicValues(drmModeAtomicReq *req); 0170 void atomicCommitFailed(); 0171 void atomicTestSuccessful(); 0172 void atomicCommitSuccessful(); 0173 void atomicModesetSuccessful(); 0174 void prepareAtomicModeset(); 0175 bool prepareAtomicPresentation(); 0176 void prepareAtomicDisable(); 0177 static Error commitPipelinesAtomic(const QVector<DrmPipeline *> &pipelines, CommitMode mode, const QVector<DrmObject *> &unusedObjects); 0178 0179 // logging helpers 0180 enum class PrintMode { 0181 OnlyChanged, 0182 All, 0183 }; 0184 static void printFlags(uint32_t flags); 0185 0186 DrmOutput *m_output = nullptr; 0187 DrmConnector *m_connector = nullptr; 0188 0189 bool m_pageflipPending = false; 0190 bool m_modesetPresentPending = false; 0191 0192 struct State 0193 { 0194 DrmCrtc *crtc = nullptr; 0195 QMap<uint32_t, QVector<uint64_t>> formats; 0196 bool active = true; // whether or not the pipeline should be currently used 0197 bool enabled = true; // whether or not the pipeline needs a crtc 0198 bool needsModeset = false; 0199 std::shared_ptr<DrmConnectorMode> mode; 0200 uint32_t overscan = 0; 0201 Output::RgbRange rgbRange = Output::RgbRange::Automatic; 0202 RenderLoopPrivate::SyncMode syncMode = RenderLoopPrivate::SyncMode::Fixed; 0203 std::shared_ptr<ColorTransformation> colorTransformation; 0204 std::shared_ptr<DrmGammaRamp> gamma; 0205 std::shared_ptr<DrmCTM> ctm; 0206 DrmConnector::DrmContentType contentType = DrmConnector::DrmContentType::Graphics; 0207 0208 std::shared_ptr<DrmPipelineLayer> layer; 0209 std::shared_ptr<DrmOverlayLayer> cursorLayer; 0210 QPoint cursorHotspot; 0211 0212 // the transformation that this pipeline will apply to submitted buffers 0213 DrmPlane::Transformations bufferOrientation = DrmPlane::Transformation::Rotate0; 0214 // the transformation that buffers submitted to the pipeline should have 0215 DrmPlane::Transformations renderOrientation = DrmPlane::Transformation::Rotate0; 0216 }; 0217 // the state that is to be tested next 0218 State m_pending; 0219 // the state that will be applied at the next real atomic commit 0220 State m_next; 0221 // the state that is already committed 0222 State m_current; 0223 }; 0224 0225 }