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