File indexing completed on 2024-11-10 04:56:27

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "drm_dmabuf_feedback.h"
0010 
0011 #include "drm_egl_backend.h"
0012 #include "drm_gpu.h"
0013 #include "wayland/surface.h"
0014 
0015 namespace KWin
0016 {
0017 
0018 DmabufFeedback::DmabufFeedback(DrmGpu *gpu, EglGbmBackend *eglBackend)
0019     : m_gpu(gpu)
0020     , m_eglBackend(eglBackend)
0021 {
0022 }
0023 
0024 void DmabufFeedback::renderingSurface()
0025 {
0026     if (m_surface && !m_attemptedThisFrame) {
0027         if (const auto &feedback = m_surface->dmabufFeedbackV1()) {
0028             feedback->setTranches({});
0029         }
0030         m_surface = nullptr;
0031     }
0032     m_attemptedThisFrame = false;
0033 }
0034 
0035 void DmabufFeedback::scanoutSuccessful(SurfaceInterface *surface)
0036 {
0037     if (surface != m_surface) {
0038         if (m_surface && m_surface->dmabufFeedbackV1()) {
0039             m_surface->dmabufFeedbackV1()->setTranches({});
0040         }
0041         m_surface = surface;
0042         m_attemptedFormats = {};
0043     }
0044 }
0045 
0046 void DmabufFeedback::scanoutFailed(SurfaceInterface *surface, const QMap<uint32_t, QList<uint64_t>> &formats)
0047 {
0048     m_attemptedThisFrame = true;
0049     if (surface != m_surface) {
0050         m_attemptedFormats = {};
0051         if (m_surface && m_surface->dmabufFeedbackV1()) {
0052             m_surface->dmabufFeedbackV1()->setTranches({});
0053         }
0054         m_surface = surface;
0055     }
0056     if (const auto &feedback = m_surface->dmabufFeedbackV1()) {
0057         const DmaBufAttributes *dmabufAttrs = surface->buffer()->dmabufAttributes();
0058         if (!m_attemptedFormats[dmabufAttrs->format].contains(dmabufAttrs->modifier)) {
0059             m_attemptedFormats[dmabufAttrs->format] << dmabufAttrs->modifier;
0060             QList<LinuxDmaBufV1Feedback::Tranche> scanoutTranches;
0061             const auto tranches = m_eglBackend->tranches();
0062             for (const auto &tranche : tranches) {
0063                 LinuxDmaBufV1Feedback::Tranche scanoutTranche;
0064                 for (auto it = tranche.formatTable.constBegin(); it != tranche.formatTable.constEnd(); it++) {
0065                     const uint32_t format = it.key();
0066                     const auto trancheModifiers = it.value();
0067                     const auto drmModifiers = formats[format];
0068                     for (const auto &mod : trancheModifiers) {
0069                         if (drmModifiers.contains(mod) && !m_attemptedFormats[format].contains(mod)) {
0070                             scanoutTranche.formatTable[format] << mod;
0071                         }
0072                     }
0073                 }
0074                 if (!scanoutTranche.formatTable.isEmpty()) {
0075                     scanoutTranche.device = m_gpu->deviceId();
0076                     scanoutTranche.flags = LinuxDmaBufV1Feedback::TrancheFlag::Scanout;
0077                     scanoutTranches << scanoutTranche;
0078                 }
0079             }
0080             feedback->setTranches(scanoutTranches);
0081         }
0082     }
0083 }
0084 
0085 }