File indexing completed on 2025-04-20 10:57:36
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_gpu.h" 0016 #include "drm_logging.h" 0017 #include "drm_pointer.h" 0018 0019 #include <drm_fourcc.h> 0020 0021 namespace KWin 0022 { 0023 0024 DrmPlane::DrmPlane(DrmGpu *gpu, uint32_t planeId) 0025 : DrmObject(gpu, planeId, { 0026 PropertyDefinition(QByteArrayLiteral("type"), Requirement::Required, {QByteArrayLiteral("Overlay"), QByteArrayLiteral("Primary"), QByteArrayLiteral("Cursor")}), 0027 PropertyDefinition(QByteArrayLiteral("SRC_X"), Requirement::Required), 0028 PropertyDefinition(QByteArrayLiteral("SRC_Y"), Requirement::Required), 0029 PropertyDefinition(QByteArrayLiteral("SRC_W"), Requirement::Required), 0030 PropertyDefinition(QByteArrayLiteral("SRC_H"), Requirement::Required), 0031 PropertyDefinition(QByteArrayLiteral("CRTC_X"), Requirement::Required), 0032 PropertyDefinition(QByteArrayLiteral("CRTC_Y"), Requirement::Required), 0033 PropertyDefinition(QByteArrayLiteral("CRTC_W"), Requirement::Required), 0034 PropertyDefinition(QByteArrayLiteral("CRTC_H"), Requirement::Required), 0035 PropertyDefinition(QByteArrayLiteral("FB_ID"), Requirement::Required), 0036 PropertyDefinition(QByteArrayLiteral("CRTC_ID"), Requirement::Required), 0037 PropertyDefinition(QByteArrayLiteral("rotation"), Requirement::Optional, {QByteArrayLiteral("rotate-0"), QByteArrayLiteral("rotate-90"), QByteArrayLiteral("rotate-180"), QByteArrayLiteral("rotate-270"), QByteArrayLiteral("reflect-x"), QByteArrayLiteral("reflect-y")}), 0038 PropertyDefinition(QByteArrayLiteral("IN_FORMATS"), Requirement::Optional), 0039 }, 0040 DRM_MODE_OBJECT_PLANE) 0041 { 0042 } 0043 0044 bool DrmPlane::init() 0045 { 0046 DrmUniquePtr<drmModePlane> p(drmModeGetPlane(gpu()->fd(), id())); 0047 0048 if (!p) { 0049 qCWarning(KWIN_DRM) << "Failed to get kernel plane" << id(); 0050 return false; 0051 } 0052 0053 m_possibleCrtcs = p->possible_crtcs; 0054 0055 bool success = initProps(); 0056 if (success) { 0057 if (const auto prop = getProp(PropertyIndex::Rotation)) { 0058 m_supportedTransformations = Transformations(); 0059 auto checkSupport = [this, prop](Transformation t) { 0060 if (prop->hasEnum(t)) { 0061 m_supportedTransformations |= t; 0062 } 0063 }; 0064 checkSupport(Transformation::Rotate0); 0065 checkSupport(Transformation::Rotate90); 0066 checkSupport(Transformation::Rotate180); 0067 checkSupport(Transformation::Rotate270); 0068 checkSupport(Transformation::ReflectX); 0069 checkSupport(Transformation::ReflectY); 0070 } else { 0071 m_supportedTransformations = Transformation::Rotate0; 0072 } 0073 0074 // read formats from blob if available and if modifiers are supported, and from the plane object if not 0075 if (const auto formatProp = getProp(PropertyIndex::In_Formats); formatProp && formatProp->immutableBlob() && gpu()->addFB2ModifiersSupported()) { 0076 drmModeFormatModifierIterator iterator{}; 0077 while (drmModeFormatModifierBlobIterNext(formatProp->immutableBlob(), &iterator)) { 0078 m_supportedFormats[iterator.fmt].push_back(iterator.mod); 0079 } 0080 } else { 0081 for (uint32_t i = 0; i < p->count_formats; i++) { 0082 m_supportedFormats.insert(p->formats[i], {DRM_FORMAT_MOD_LINEAR}); 0083 } 0084 } 0085 if (m_supportedFormats.isEmpty()) { 0086 qCWarning(KWIN_DRM) << "Driver doesn't advertise any formats for this plane. Falling back to XRGB8888 without explicit modifiers"; 0087 m_supportedFormats.insert(DRM_FORMAT_XRGB8888, {}); 0088 } 0089 } 0090 return success; 0091 } 0092 0093 DrmPlane::TypeIndex DrmPlane::type() const 0094 { 0095 const auto &prop = getProp(PropertyIndex::Type); 0096 return prop->enumForValue<DrmPlane::TypeIndex>(prop->current()); 0097 } 0098 0099 void DrmPlane::setNext(const std::shared_ptr<DrmFramebuffer> &b) 0100 { 0101 m_next = b; 0102 } 0103 0104 DrmPlane::Transformations DrmPlane::transformation() 0105 { 0106 if (auto property = getProp(PropertyIndex::Rotation)) { 0107 return Transformations(static_cast<uint32_t>(property->pending())); 0108 } 0109 return Transformations(Transformation::Rotate0); 0110 } 0111 0112 void DrmPlane::flipBuffer() 0113 { 0114 m_current = m_next; 0115 m_next = nullptr; 0116 } 0117 0118 void DrmPlane::set(const QPoint &srcPos, const QSize &srcSize, const QRect &dst) 0119 { 0120 // Src* are in 16.16 fixed point format 0121 setPending(PropertyIndex::SrcX, srcPos.x() << 16); 0122 setPending(PropertyIndex::SrcY, srcPos.y() << 16); 0123 setPending(PropertyIndex::SrcW, srcSize.width() << 16); 0124 setPending(PropertyIndex::SrcH, srcSize.height() << 16); 0125 setPending(PropertyIndex::CrtcX, dst.x()); 0126 setPending(PropertyIndex::CrtcY, dst.y()); 0127 setPending(PropertyIndex::CrtcW, dst.width()); 0128 setPending(PropertyIndex::CrtcH, dst.height()); 0129 } 0130 0131 void DrmPlane::setBuffer(DrmFramebuffer *buffer) 0132 { 0133 setPending(PropertyIndex::FbId, buffer ? buffer->framebufferId() : 0); 0134 } 0135 0136 bool DrmPlane::isCrtcSupported(int pipeIndex) const 0137 { 0138 return (m_possibleCrtcs & (1 << pipeIndex)); 0139 } 0140 0141 QMap<uint32_t, QVector<uint64_t>> DrmPlane::formats() const 0142 { 0143 return m_supportedFormats; 0144 } 0145 0146 std::shared_ptr<DrmFramebuffer> DrmPlane::current() const 0147 { 0148 return m_current; 0149 } 0150 0151 std::shared_ptr<DrmFramebuffer> DrmPlane::next() const 0152 { 0153 return m_next; 0154 } 0155 0156 void DrmPlane::setCurrent(const std::shared_ptr<DrmFramebuffer> &b) 0157 { 0158 m_current = b; 0159 } 0160 0161 DrmPlane::Transformations DrmPlane::supportedTransformations() const 0162 { 0163 return m_supportedTransformations; 0164 } 0165 0166 void DrmPlane::disable() 0167 { 0168 setPending(PropertyIndex::CrtcId, 0); 0169 setPending(PropertyIndex::FbId, 0); 0170 m_next = nullptr; 0171 } 0172 0173 void DrmPlane::releaseBuffers() 0174 { 0175 if (m_next) { 0176 m_next->releaseBuffer(); 0177 } 0178 if (m_current) { 0179 m_current->releaseBuffer(); 0180 } 0181 } 0182 }