File indexing completed on 2024-11-10 04:57:06

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
0006     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 // this needs to be on top, epoxy has an error if you include it after GL/gl.h,
0011 // which Qt does include
0012 #include "utils/drm_format_helper.h"
0013 
0014 #include "compositor.h"
0015 #include "core/renderbackend.h"
0016 #include "core/shmgraphicsbufferallocator.h"
0017 #include "internalwindow.h"
0018 #include "swapchain.h"
0019 #include "window.h"
0020 
0021 #include <logging.h>
0022 
0023 #include <libdrm/drm_fourcc.h>
0024 #include <qpa/qwindowsysteminterface.h>
0025 
0026 namespace KWin
0027 {
0028 namespace QPA
0029 {
0030 static quint32 s_windowId = 0;
0031 
0032 Window::Window(QWindow *window)
0033     : QPlatformWindow(window)
0034     , m_windowId(++s_windowId)
0035     , m_scale(kwinApp()->devicePixelRatio())
0036 {
0037     Q_ASSERT(!window->property("_KWIN_WINDOW_IS_OFFSCREEN").toBool());
0038 }
0039 
0040 Window::~Window()
0041 {
0042     unmap();
0043 }
0044 
0045 Swapchain *Window::swapchain(const QHash<uint32_t, QList<uint64_t>> &formats)
0046 {
0047     const QSize nativeSize = geometry().size() * devicePixelRatio();
0048     if (!m_swapchain || m_swapchain->size() != nativeSize
0049         || !formats.contains(m_swapchain->format())
0050         || m_swapchain->modifiers() != formats[m_swapchain->format()]) {
0051         const bool software = window()->surfaceType() == QSurface::RasterSurface; // RasterGLSurface is unsupported by us
0052 
0053         GraphicsBufferAllocator *allocator;
0054         if (software) {
0055             static ShmGraphicsBufferAllocator shmAllocator;
0056             allocator = &shmAllocator;
0057         } else {
0058             allocator = Compositor::self()->backend()->graphicsBufferAllocator();
0059         }
0060 
0061         for (auto it = formats.begin(); it != formats.end(); it++) {
0062             if (auto info = FormatInfo::get(it.key()); info && info->bitsPerColor == 8 && info->alphaBits == 8) {
0063                 const auto options = GraphicsBufferOptions{
0064                     .size = nativeSize,
0065                     .format = it.key(),
0066                     .modifiers = it.value(),
0067                     .software = software,
0068                 };
0069                 auto buffer = allocator->allocate(options);
0070                 if (!buffer) {
0071                     continue;
0072                 }
0073                 m_swapchain = std::make_unique<Swapchain>(allocator, options, buffer);
0074                 break;
0075             }
0076         }
0077     }
0078     return m_swapchain.get();
0079 }
0080 
0081 void Window::invalidateSurface()
0082 {
0083     m_swapchain.reset();
0084 }
0085 
0086 void Window::setVisible(bool visible)
0087 {
0088     if (visible) {
0089         map();
0090     } else {
0091         unmap();
0092     }
0093 
0094     QPlatformWindow::setVisible(visible);
0095 }
0096 
0097 QSurfaceFormat Window::format() const
0098 {
0099     return m_format;
0100 }
0101 
0102 void Window::requestActivateWindow()
0103 {
0104 #if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
0105     QWindowSystemInterface::handleWindowActivated(window());
0106 #else
0107     QWindowSystemInterface::handleFocusWindowChanged(window());
0108 #endif
0109 }
0110 
0111 void Window::setGeometry(const QRect &rect)
0112 {
0113     const QRect oldGeometry = geometry();
0114     QPlatformWindow::setGeometry(rect);
0115 
0116     if (window()->isVisible() && rect.isValid()) {
0117         QWindowSystemInterface::handleGeometryChange(window(), geometry());
0118     }
0119 
0120     if (isExposed() && oldGeometry.size() != rect.size()) {
0121         QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), rect.size()));
0122     }
0123 }
0124 
0125 WId Window::winId() const
0126 {
0127     return m_windowId;
0128 }
0129 
0130 qreal Window::devicePixelRatio() const
0131 {
0132     return m_scale;
0133 }
0134 
0135 InternalWindow *Window::internalWindow() const
0136 {
0137     return m_handle;
0138 }
0139 
0140 void Window::map()
0141 {
0142     if (m_handle) {
0143         return;
0144     }
0145 
0146     m_handle = new InternalWindow(window());
0147 }
0148 
0149 void Window::unmap()
0150 {
0151     if (!m_handle) {
0152         return;
0153     }
0154 
0155     m_handle->destroyWindow();
0156     m_handle = nullptr;
0157 
0158     invalidateSurface();
0159 }
0160 
0161 }
0162 }