File indexing completed on 2024-05-26 05:32:41

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"