File indexing completed on 2024-11-10 04:56:30
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2016 Roman Gilg <subdiff@gmail.com> 0006 SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 #include "drm_plane.h" 0011 0012 #include "config-kwin.h" 0013 0014 #include "drm_buffer.h" 0015 #include "drm_commit.h" 0016 #include "drm_gpu.h" 0017 #include "drm_logging.h" 0018 #include "drm_pointer.h" 0019 0020 #include <drm_fourcc.h> 0021 0022 namespace KWin 0023 { 0024 0025 DrmPlane::DrmPlane(DrmGpu *gpu, uint32_t planeId) 0026 : DrmObject(gpu, planeId, DRM_MODE_OBJECT_PLANE) 0027 , type(this, QByteArrayLiteral("type"), { 0028 QByteArrayLiteral("Overlay"), 0029 QByteArrayLiteral("Primary"), 0030 QByteArrayLiteral("Cursor"), 0031 }) 0032 , srcX(this, QByteArrayLiteral("SRC_X")) 0033 , srcY(this, QByteArrayLiteral("SRC_Y")) 0034 , srcW(this, QByteArrayLiteral("SRC_W")) 0035 , srcH(this, QByteArrayLiteral("SRC_H")) 0036 , crtcX(this, QByteArrayLiteral("CRTC_X")) 0037 , crtcY(this, QByteArrayLiteral("CRTC_Y")) 0038 , crtcW(this, QByteArrayLiteral("CRTC_W")) 0039 , crtcH(this, QByteArrayLiteral("CRTC_H")) 0040 , fbId(this, QByteArrayLiteral("FB_ID")) 0041 , crtcId(this, QByteArrayLiteral("CRTC_ID")) 0042 , rotation(this, QByteArrayLiteral("rotation"), { 0043 QByteArrayLiteral("rotate-0"), 0044 QByteArrayLiteral("rotate-90"), 0045 QByteArrayLiteral("rotate-180"), 0046 QByteArrayLiteral("rotate-270"), 0047 QByteArrayLiteral("reflect-x"), 0048 QByteArrayLiteral("reflect-y"), 0049 }) 0050 , inFormats(this, QByteArrayLiteral("IN_FORMATS")) 0051 , alpha(this, QByteArrayLiteral("alpha")) 0052 , pixelBlendMode(this, QByteArrayLiteral("pixel blend mode"), { 0053 QByteArrayLiteral("None"), 0054 QByteArrayLiteral("Pre-multiplied"), 0055 QByteArrayLiteral("Coverage"), 0056 }) 0057 , colorEncoding(this, QByteArrayLiteral("COLOR_ENCODING"), { 0058 QByteArrayLiteral("ITU-R BT.601 YCbCr"), 0059 QByteArrayLiteral("ITU-R BT.709 YCbCr"), 0060 QByteArrayLiteral("ITU-R BT.2020 YCbCr"), 0061 }) 0062 , colorRange(this, QByteArrayLiteral("COLOR_RANGE"), { 0063 QByteArrayLiteral("YCbCr limited range"), 0064 QByteArrayLiteral("YCbCr full range"), 0065 }) 0066 , vmHotspotX(this, QByteArrayLiteral("HOTSPOT_X")) 0067 , vmHotspotY(this, QByteArrayLiteral("HOTSPOT_Y")) 0068 , inFenceFd(this, QByteArrayLiteral("IN_FENCE_FD")) 0069 { 0070 } 0071 0072 bool DrmPlane::updateProperties() 0073 { 0074 DrmUniquePtr<drmModePlane> p(drmModeGetPlane(gpu()->fd(), id())); 0075 if (!p) { 0076 qCWarning(KWIN_DRM) << "Failed to get kernel plane" << id(); 0077 return false; 0078 } 0079 DrmPropertyList props = queryProperties(); 0080 type.update(props); 0081 srcX.update(props); 0082 srcY.update(props); 0083 srcW.update(props); 0084 srcH.update(props); 0085 crtcX.update(props); 0086 crtcY.update(props); 0087 crtcW.update(props); 0088 crtcH.update(props); 0089 fbId.update(props); 0090 crtcId.update(props); 0091 rotation.update(props); 0092 inFormats.update(props); 0093 alpha.update(props); 0094 pixelBlendMode.update(props); 0095 colorEncoding.update(props); 0096 colorRange.update(props); 0097 vmHotspotX.update(props); 0098 vmHotspotY.update(props); 0099 inFenceFd.update(props); 0100 0101 if (!type.isValid() || !srcX.isValid() || !srcY.isValid() || !srcW.isValid() || !srcH.isValid() 0102 || !crtcX.isValid() || !crtcY.isValid() || !crtcW.isValid() || !crtcH.isValid() || !fbId.isValid()) { 0103 return false; 0104 } 0105 0106 m_possibleCrtcs = p->possible_crtcs; 0107 0108 // read formats from blob if available and if modifiers are supported, and from the plane object if not 0109 m_supportedFormats.clear(); 0110 if (inFormats.isValid() && inFormats.immutableBlob() && gpu()->addFB2ModifiersSupported()) { 0111 drmModeFormatModifierIterator iterator{}; 0112 while (drmModeFormatModifierBlobIterNext(inFormats.immutableBlob(), &iterator)) { 0113 m_supportedFormats[iterator.fmt].push_back(iterator.mod); 0114 } 0115 } else { 0116 // if we don't have modifier support, assume the cursor needs a linear buffer 0117 const QList<uint64_t> modifiers = {type.enumValue() == TypeIndex::Cursor ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID}; 0118 for (uint32_t i = 0; i < p->count_formats; i++) { 0119 m_supportedFormats.insert(p->formats[i], modifiers); 0120 } 0121 if (m_supportedFormats.isEmpty()) { 0122 qCWarning(KWIN_DRM) << "Driver doesn't advertise any formats for this plane. Falling back to XRGB8888 without explicit modifiers"; 0123 m_supportedFormats.insert(DRM_FORMAT_XRGB8888, modifiers); 0124 } 0125 } 0126 return true; 0127 } 0128 0129 void DrmPlane::set(DrmAtomicCommit *commit, const QPoint &srcPos, const QSize &srcSize, const QRect &dst) 0130 { 0131 // Src* are in 16.16 fixed point format 0132 commit->addProperty(srcX, srcPos.x() << 16); 0133 commit->addProperty(srcX, srcPos.x() << 16); 0134 commit->addProperty(srcY, srcPos.y() << 16); 0135 commit->addProperty(srcW, srcSize.width() << 16); 0136 commit->addProperty(srcH, srcSize.height() << 16); 0137 commit->addProperty(crtcX, dst.x()); 0138 commit->addProperty(crtcY, dst.y()); 0139 commit->addProperty(crtcW, dst.width()); 0140 commit->addProperty(crtcH, dst.height()); 0141 } 0142 0143 bool DrmPlane::isCrtcSupported(int pipeIndex) const 0144 { 0145 return (m_possibleCrtcs & (1 << pipeIndex)); 0146 } 0147 0148 QMap<uint32_t, QList<uint64_t>> DrmPlane::formats() const 0149 { 0150 return m_supportedFormats; 0151 } 0152 0153 std::shared_ptr<DrmFramebuffer> DrmPlane::currentBuffer() const 0154 { 0155 return m_current; 0156 } 0157 0158 void DrmPlane::setCurrentBuffer(const std::shared_ptr<DrmFramebuffer> &b) 0159 { 0160 m_current = b; 0161 } 0162 0163 void DrmPlane::disable(DrmAtomicCommit *commit) 0164 { 0165 commit->addProperty(crtcId, 0); 0166 commit->addBuffer(this, nullptr); 0167 } 0168 0169 void DrmPlane::releaseCurrentBuffer() 0170 { 0171 if (m_current) { 0172 m_current->releaseBuffer(); 0173 } 0174 } 0175 0176 int32_t DrmPlane::transformationToDegrees(DrmPlane::Transformations transformation) 0177 { 0178 if (transformation & DrmPlane::Transformation::Rotate0) { 0179 return 0; 0180 } else if (transformation & DrmPlane::Transformation::Rotate90) { 0181 return 90; 0182 } else if (transformation & DrmPlane::Transformation::Rotate180) { 0183 return 180; 0184 } else { 0185 return 270; 0186 } 0187 } 0188 } 0189 0190 #include "moc_drm_plane.cpp"