File indexing completed on 2026-06-07 16:15:42

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
0006     SPDX-FileCopyrightText: 2019 Roman Gilg <subdiff@gmail.com>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 #pragma once
0011 
0012 #include "abstract_egl_backend.h"
0013 #include "core/outputlayer.h"
0014 #include "utils/damagejournal.h"
0015 
0016 #include <KWayland/Client/buffer.h>
0017 
0018 #include <memory>
0019 
0020 class QTemporaryFile;
0021 struct wl_buffer;
0022 struct wl_shm;
0023 struct gbm_bo;
0024 
0025 namespace KWin
0026 {
0027 class GLFramebuffer;
0028 
0029 namespace Wayland
0030 {
0031 class WaylandBackend;
0032 class WaylandOutput;
0033 class WaylandEglBackend;
0034 
0035 class WaylandEglLayerBuffer
0036 {
0037 public:
0038     WaylandEglLayerBuffer(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, WaylandEglBackend *backend);
0039     ~WaylandEglLayerBuffer();
0040 
0041     wl_buffer *buffer() const;
0042     GLFramebuffer *framebuffer() const;
0043     GLFramebuffer *shadowFramebuffer() const;
0044     GLTexture *shadowTexture() const;
0045     int age() const;
0046 
0047 private:
0048     WaylandEglBackend *m_backend;
0049     wl_buffer *m_buffer = nullptr;
0050     gbm_bo *m_bo = nullptr;
0051     std::unique_ptr<GLFramebuffer> m_framebuffer;
0052     std::unique_ptr<GLFramebuffer> m_shadowFramebuffer;
0053     std::shared_ptr<GLTexture> m_texture;
0054     std::shared_ptr<GLTexture> m_shadowTexture;
0055     int m_age = 0;
0056     friend class WaylandEglLayerSwapchain;
0057 };
0058 
0059 class WaylandEglLayerSwapchain
0060 {
0061 public:
0062     WaylandEglLayerSwapchain(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, WaylandEglBackend *backend);
0063     ~WaylandEglLayerSwapchain();
0064 
0065     QSize size() const;
0066 
0067     std::shared_ptr<WaylandEglLayerBuffer> acquire();
0068     void release(std::shared_ptr<WaylandEglLayerBuffer> buffer);
0069 
0070 private:
0071     WaylandEglBackend *m_backend;
0072     QSize m_size;
0073     QVector<std::shared_ptr<WaylandEglLayerBuffer>> m_buffers;
0074     int m_index = 0;
0075 };
0076 
0077 class WaylandEglPrimaryLayer : public OutputLayer
0078 {
0079 public:
0080     WaylandEglPrimaryLayer(WaylandOutput *output, WaylandEglBackend *backend);
0081     ~WaylandEglPrimaryLayer() override;
0082 
0083     GLFramebuffer *fbo() const;
0084     void present();
0085 
0086     std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
0087     bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
0088 
0089 private:
0090     WaylandOutput *m_waylandOutput;
0091     DamageJournal m_damageJournal;
0092     std::unique_ptr<WaylandEglLayerSwapchain> m_swapchain;
0093     std::shared_ptr<WaylandEglLayerBuffer> m_buffer;
0094     WaylandEglBackend *const m_backend;
0095 
0096     friend class WaylandEglBackend;
0097 };
0098 
0099 class WaylandEglCursorLayer : public OutputLayer
0100 {
0101     Q_OBJECT
0102 
0103 public:
0104     WaylandEglCursorLayer(WaylandOutput *output, WaylandEglBackend *backend);
0105     ~WaylandEglCursorLayer() override;
0106 
0107     qreal scale() const;
0108     void setScale(qreal scale);
0109 
0110     QPoint hotspot() const;
0111     void setHotspot(const QPoint &hotspot);
0112 
0113     QSize size() const;
0114     void setSize(const QSize &size);
0115 
0116     std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
0117     bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
0118 
0119 private:
0120     WaylandOutput *m_output;
0121     WaylandEglBackend *m_backend;
0122     std::unique_ptr<WaylandEglLayerSwapchain> m_swapchain;
0123     std::shared_ptr<WaylandEglLayerBuffer> m_buffer;
0124     QPoint m_hotspot;
0125     QSize m_size;
0126     qreal m_scale = 1.0;
0127 };
0128 
0129 /**
0130  * @brief OpenGL Backend using Egl on a Wayland surface.
0131  *
0132  * This Backend is the basis for a session compositor running on top of a Wayland system compositor.
0133  * It creates a Surface as large as the screen and maps it as a fullscreen shell surface on the
0134  * system compositor. The OpenGL context is created on the Wayland surface, so for rendering X11 is
0135  * not involved.
0136  *
0137  * Also in repainting the backend is currently still rather limited. Only supported mode is fullscreen
0138  * repaints, which is obviously not optimal. Best solution is probably to go for buffer_age extension
0139  * and make it the only available solution next to fullscreen repaints.
0140  */
0141 class WaylandEglBackend : public AbstractEglBackend
0142 {
0143     Q_OBJECT
0144 public:
0145     WaylandEglBackend(WaylandBackend *b);
0146     ~WaylandEglBackend() override;
0147 
0148     WaylandBackend *backend() const;
0149 
0150     std::unique_ptr<SurfaceTexture> createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
0151     std::unique_ptr<SurfaceTexture> createSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
0152 
0153     void init() override;
0154     void present(Output *output) override;
0155     OutputLayer *primaryLayer(Output *output) override;
0156     WaylandEglCursorLayer *cursorLayer(Output *output);
0157 
0158     std::shared_ptr<KWin::GLTexture> textureForOutput(KWin::Output *output) const override;
0159 
0160 private:
0161     bool initializeEgl();
0162     bool initBufferConfigs();
0163     bool initRenderingContext();
0164     bool createEglWaylandOutput(Output *output);
0165     void cleanupSurfaces() override;
0166 
0167     struct Layers
0168     {
0169         std::unique_ptr<WaylandEglPrimaryLayer> primaryLayer;
0170         std::unique_ptr<WaylandEglCursorLayer> cursorLayer;
0171     };
0172 
0173     WaylandBackend *m_backend;
0174     std::map<Output *, Layers> m_outputs;
0175     bool m_havePlatformBase;
0176 };
0177 
0178 } // namespace Wayland
0179 } // namespace KWin