File indexing completed on 2025-04-27 11:33:00

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #pragma once
0010 #include "core/outputlayer.h"
0011 #include "openglbackend.h"
0012 #include "openglsurfacetexture_x11.h"
0013 #include "utils/damagejournal.h"
0014 #include "x11eventfilter.h"
0015 
0016 #include <epoxy/glx.h>
0017 #include <fixx11h.h>
0018 #include <xcb/glx.h>
0019 
0020 #include <kwingltexture.h>
0021 #include <kwingltexture_p.h>
0022 
0023 #include <QHash>
0024 #include <memory>
0025 
0026 namespace KWin
0027 {
0028 
0029 class GlxPixmapTexturePrivate;
0030 class VsyncMonitor;
0031 class X11StandaloneBackend;
0032 class GlxBackend;
0033 
0034 // GLX_MESA_swap_interval
0035 using glXSwapIntervalMESA_func = int (*)(unsigned int interval);
0036 extern glXSwapIntervalMESA_func glXSwapIntervalMESA;
0037 
0038 class FBConfigInfo
0039 {
0040 public:
0041     GLXFBConfig fbconfig;
0042     int bind_texture_format;
0043     int texture_targets;
0044     int y_inverted;
0045     int mipmap;
0046 };
0047 
0048 // ------------------------------------------------------------------
0049 
0050 class SwapEventFilter : public X11EventFilter
0051 {
0052 public:
0053     SwapEventFilter(xcb_drawable_t drawable, xcb_glx_drawable_t glxDrawable);
0054     bool event(xcb_generic_event_t *event) override;
0055 
0056 private:
0057     xcb_drawable_t m_drawable;
0058     xcb_glx_drawable_t m_glxDrawable;
0059 };
0060 
0061 class GlxLayer : public OutputLayer
0062 {
0063 public:
0064     GlxLayer(GlxBackend *backend);
0065 
0066     std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
0067     bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
0068 
0069 private:
0070     GlxBackend *const m_backend;
0071 };
0072 
0073 /**
0074  * @brief OpenGL Backend using GLX over an X overlay window.
0075  */
0076 class GlxBackend : public OpenGLBackend
0077 {
0078     Q_OBJECT
0079 
0080 public:
0081     GlxBackend(Display *display, X11StandaloneBackend *backend);
0082     ~GlxBackend() override;
0083     std::unique_ptr<SurfaceTexture> createSurfaceTextureX11(SurfacePixmapX11 *pixmap) override;
0084     OutputLayerBeginFrameInfo beginFrame();
0085     void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion);
0086     void present(Output *output) override;
0087     bool makeCurrent() override;
0088     void doneCurrent() override;
0089     OverlayWindow *overlayWindow() const override;
0090     void init() override;
0091     OutputLayer *primaryLayer(Output *output) override;
0092 
0093     Display *display() const
0094     {
0095         return m_x11Display;
0096     }
0097 
0098 private:
0099     void vblank(std::chrono::nanoseconds timestamp);
0100     void present(const QRegion &damage);
0101     bool initBuffer();
0102     bool checkVersion();
0103     void initExtensions();
0104     bool initRenderingContext();
0105     bool initFbConfig();
0106     void initVisualDepthHashTable();
0107     void setSwapInterval(int interval);
0108     void screenGeometryChanged();
0109 
0110     int visualDepth(xcb_visualid_t visual) const;
0111     const FBConfigInfo &infoForVisual(xcb_visualid_t visual);
0112 
0113     /**
0114      * @brief The OverlayWindow used by this Backend.
0115      */
0116     std::unique_ptr<OverlayWindow> m_overlayWindow;
0117     ::Window window;
0118     GLXFBConfig fbconfig;
0119     GLXWindow glxWindow;
0120     GLXContext ctx;
0121     QHash<xcb_visualid_t, FBConfigInfo> m_fbconfigHash;
0122     QHash<xcb_visualid_t, int> m_visualDepthHash;
0123     std::unique_ptr<SwapEventFilter> m_swapEventFilter;
0124     std::unique_ptr<GLFramebuffer> m_fbo;
0125     DamageJournal m_damageJournal;
0126     QRegion m_lastRenderedRegion;
0127     int m_bufferAge;
0128     bool m_haveMESACopySubBuffer = false;
0129     bool m_haveMESASwapControl = false;
0130     bool m_haveEXTSwapControl = false;
0131     bool m_haveSGISwapControl = false;
0132     Display *m_x11Display;
0133     X11StandaloneBackend *m_backend;
0134     std::unique_ptr<VsyncMonitor> m_vsyncMonitor;
0135     std::unique_ptr<GlxLayer> m_layer;
0136     friend class GlxPixmapTexturePrivate;
0137 };
0138 
0139 class GlxPixmapTexture final : public GLTexture
0140 {
0141 public:
0142     explicit GlxPixmapTexture(GlxBackend *backend);
0143 
0144     bool create(SurfacePixmapX11 *texture);
0145 
0146 private:
0147     Q_DECLARE_PRIVATE(GlxPixmapTexture)
0148 };
0149 
0150 class GlxPixmapTexturePrivate final : public GLTexturePrivate
0151 {
0152 public:
0153     GlxPixmapTexturePrivate(GlxPixmapTexture *texture, GlxBackend *backend);
0154     ~GlxPixmapTexturePrivate() override;
0155 
0156     bool create(SurfacePixmapX11 *texture);
0157 
0158 protected:
0159     void onDamage() override;
0160 
0161 private:
0162     GlxBackend *m_backend;
0163     GlxPixmapTexture *q;
0164     GLXPixmap m_glxPixmap;
0165 };
0166 
0167 class GlxSurfaceTextureX11 final : public OpenGLSurfaceTextureX11
0168 {
0169 public:
0170     GlxSurfaceTextureX11(GlxBackend *backend, SurfacePixmapX11 *pixmap);
0171 
0172     bool create() override;
0173     void update(const QRegion &region) override;
0174 };
0175 
0176 } // namespace