File indexing completed on 2025-04-20 10:57:33
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 "egl_dmabuf.h" 0014 #include "wayland/linuxdmabufv1clientbuffer.h" 0015 #include "wayland/surface_interface.h" 0016 0017 namespace KWin 0018 { 0019 0020 DmabufFeedback::DmabufFeedback(DrmGpu *gpu, EglGbmBackend *eglBackend) 0021 : m_gpu(gpu) 0022 , m_eglBackend(eglBackend) 0023 { 0024 } 0025 0026 void DmabufFeedback::renderingSurface() 0027 { 0028 if (m_surface && !m_attemptedThisFrame) { 0029 if (const auto &feedback = m_surface->dmabufFeedbackV1()) { 0030 feedback->setTranches({}); 0031 } 0032 m_surface = nullptr; 0033 } 0034 m_attemptedThisFrame = false; 0035 } 0036 0037 void DmabufFeedback::scanoutSuccessful(KWaylandServer::SurfaceInterface *surface) 0038 { 0039 if (surface != m_surface) { 0040 if (m_surface && m_surface->dmabufFeedbackV1()) { 0041 m_surface->dmabufFeedbackV1()->setTranches({}); 0042 } 0043 m_surface = surface; 0044 m_attemptedFormats = {}; 0045 } 0046 } 0047 0048 void DmabufFeedback::scanoutFailed(KWaylandServer::SurfaceInterface *surface, const QMap<uint32_t, QVector<uint64_t>> &formats) 0049 { 0050 m_attemptedThisFrame = true; 0051 if (surface != m_surface) { 0052 m_attemptedFormats = {}; 0053 if (m_surface && m_surface->dmabufFeedbackV1()) { 0054 m_surface->dmabufFeedbackV1()->setTranches({}); 0055 } 0056 m_surface = surface; 0057 } 0058 if (const auto &feedback = m_surface->dmabufFeedbackV1()) { 0059 const auto buffer = qobject_cast<KWaylandServer::LinuxDmaBufV1ClientBuffer *>(surface->buffer()); 0060 Q_ASSERT(buffer); 0061 const DmaBufAttributes &dmabufAttrs = buffer->attributes(); 0062 if (!m_attemptedFormats[dmabufAttrs.format].contains(dmabufAttrs.modifier)) { 0063 m_attemptedFormats[dmabufAttrs.format] << dmabufAttrs.modifier; 0064 QVector<KWaylandServer::LinuxDmaBufV1Feedback::Tranche> scanoutTranches; 0065 const auto tranches = m_eglBackend->dmabuf()->tranches(); 0066 for (const auto &tranche : tranches) { 0067 KWaylandServer::LinuxDmaBufV1Feedback::Tranche scanoutTranche; 0068 for (auto it = tranche.formatTable.constBegin(); it != tranche.formatTable.constEnd(); it++) { 0069 const uint32_t format = it.key(); 0070 const auto trancheModifiers = it.value(); 0071 const auto drmModifiers = formats[format]; 0072 for (const auto &mod : trancheModifiers) { 0073 if (drmModifiers.contains(mod) && !m_attemptedFormats[format].contains(mod)) { 0074 scanoutTranche.formatTable[format] << mod; 0075 } 0076 } 0077 } 0078 if (!scanoutTranche.formatTable.isEmpty()) { 0079 scanoutTranche.device = m_gpu->deviceId(); 0080 scanoutTranche.flags = KWaylandServer::LinuxDmaBufV1Feedback::TrancheFlag::Scanout; 0081 scanoutTranches << scanoutTranche; 0082 } 0083 } 0084 feedback->setTranches(scanoutTranches); 0085 } 0086 } 0087 } 0088 0089 }