1 /*
2     KWin - the KDE window manager
3     This file is part of the KDE project.
4 
5     SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
6     SPDX-FileCopyrightText: 2009, 2010, 2011 Martin Gräßlin <mgraesslin@kde.org>
7 
8     SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 
11 #ifndef KWIN_SCENE_OPENGL_H
12 #define KWIN_SCENE_OPENGL_H
13 
14 #include "openglbackend.h"
15 
16 #include "decorationitem.h"
17 #include "scene.h"
18 #include "shadow.h"
19 
20 #include "kwinglutils.h"
21 
22 namespace KWin
23 {
24 class LanczosFilter;
25 class OpenGLBackend;
26 
27 class KWIN_EXPORT SceneOpenGL
28     : public Scene
29 {
30     Q_OBJECT
31 public:
32     class EffectFrame;
33     ~SceneOpenGL() override;
34     bool initFailed() const override;
35     void paint(AbstractOutput *output, const QRegion &damage, const QList<Toplevel *> &windows,
36                RenderLoop *renderLoop) override;
37     Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override;
38     Shadow *createShadow(Toplevel *toplevel) override;
39     OverlayWindow *overlayWindow() const override;
40     bool makeOpenGLContextCurrent() override;
41     void doneOpenGLContextCurrent() override;
42     bool supportsNativeFence() const override;
43     DecorationRenderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
44     virtual QMatrix4x4 projectionMatrix() const = 0;
45     bool animationsSupported() const override;
46     PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override;
47     PlatformSurfaceTexture *createPlatformSurfaceTextureX11(SurfacePixmapX11 *pixmap) override;
48     PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap) override;
49 
debug()50     bool debug() const { return m_debug; }
51     void initDebugOutput();
52 
backend()53     OpenGLBackend *backend() const {
54         return m_backend;
55     }
56 
57     QVector<QByteArray> openGLPlatformInterfaceExtensions() const override;
58     QSharedPointer<GLTexture> textureForOutput(AbstractOutput *output) const override;
59 
60     static SceneOpenGL *createScene(QObject *parent);
61 
62 protected:
63     SceneOpenGL(OpenGLBackend *backend, QObject *parent = nullptr);
64     void paintBackground(const QRegion &region) override;
65     void aboutToStartPainting(AbstractOutput *output, const QRegion &damage) override;
66     void extendPaintRegion(QRegion &region, bool opaqueFullscreen) override;
67     QMatrix4x4 transformation(int mask, const ScreenPaintData &data) const;
68     void paintDesktop(int desktop, int mask, const QRegion &region, ScreenPaintData &data) override;
69     void paintEffectQuickView(EffectQuickView *w) override;
70 
71     void handleGraphicsReset(GLenum status);
72 
73     virtual void doPaintBackground(const QVector<float> &vertices) = 0;
74     virtual void updateProjectionMatrix(const QRect &geometry) = 0;
75 
76 protected:
77     bool init_ok;
78 private:
79     bool viewportLimitsMatched(const QSize &size) const;
80 
81 private:
82     bool m_resetOccurred = false;
83     bool m_debug;
84     OpenGLBackend *m_backend;
85 };
86 
87 class SceneOpenGL2 : public SceneOpenGL
88 {
89     Q_OBJECT
90 public:
91     explicit SceneOpenGL2(OpenGLBackend *backend, QObject *parent = nullptr);
92     ~SceneOpenGL2() override;
compositingType()93     CompositingType compositingType() const override {
94         return OpenGLCompositing;
95     }
96 
97     static bool supported(OpenGLBackend *backend);
98 
projectionMatrix()99     QMatrix4x4 projectionMatrix() const override { return m_projectionMatrix; }
screenProjectionMatrix()100     QMatrix4x4 screenProjectionMatrix() const override { return m_screenProjectionMatrix; }
101 
102 protected:
103     void paintSimpleScreen(int mask, const QRegion &region) override;
104     void paintGenericScreen(int mask, const ScreenPaintData &data) override;
105     void doPaintBackground(const QVector< float >& vertices) override;
106     Scene::Window *createWindow(Toplevel *t) override;
107     void finalDrawWindow(EffectWindowImpl* w, int mask, const QRegion &region, WindowPaintData& data) override;
108     void updateProjectionMatrix(const QRect &geometry) override;
109     void paintCursor(const QRegion &region) override;
110 
111 private:
112     void performPaintWindow(EffectWindowImpl* w, int mask, const QRegion &region, WindowPaintData& data);
113 
114     LanczosFilter *m_lanczosFilter;
115     QScopedPointer<GLTexture> m_cursorTexture;
116     bool m_cursorTextureDirty = false;
117     QMatrix4x4 m_projectionMatrix;
118     QMatrix4x4 m_screenProjectionMatrix;
119     GLuint vao;
120 };
121 
122 class OpenGLWindow final : public Scene::Window
123 {
124     Q_OBJECT
125 
126 public:
127     struct RenderNode
128     {
129         GLTexture *texture = nullptr;
130         WindowQuadList quads;
131         QMatrix4x4 transformMatrix;
132         int firstVertex = 0;
133         int vertexCount = 0;
134         qreal opacity = 1;
135         bool hasAlpha = false;
136         TextureCoordinateType coordinateType = UnnormalizedCoordinates;
137     };
138 
139     struct RenderContext
140     {
141         QVector<RenderNode> renderNodes;
142         QStack<QMatrix4x4> transforms;
143         const QRegion clip;
144         const WindowPaintData &paintData;
145         const bool hardwareClipping;
146     };
147 
148     OpenGLWindow(Toplevel *toplevel, SceneOpenGL *scene);
149     ~OpenGLWindow() override;
150 
151     void performPaint(int mask, const QRegion &region, const WindowPaintData &data) override;
152     QSharedPointer<GLTexture> windowTexture() override;
153 
154 private:
155     QMatrix4x4 modelViewProjectionMatrix(int mask, const WindowPaintData &data) const;
156     QVector4D modulate(float opacity, float brightness) const;
157     void setBlendEnabled(bool enabled);
158     void createRenderNode(Item *item, RenderContext *context);
159 
160     SceneOpenGL *m_scene;
161     bool m_blendingEnabled = false;
162 };
163 
164 class SceneOpenGL::EffectFrame
165     : public Scene::EffectFrame
166 {
167 public:
168     EffectFrame(EffectFrameImpl* frame, SceneOpenGL *scene);
169     ~EffectFrame() override;
170 
171     void free() override;
172     void freeIconFrame() override;
173     void freeTextFrame() override;
174     void freeSelection() override;
175 
176     void render(const QRegion &region, double opacity, double frameOpacity) override;
177 
178     void crossFadeIcon() override;
179     void crossFadeText() override;
180 
181     static void cleanup();
182 
183 private:
184     void updateTexture();
185     void updateTextTexture();
186 
187     GLTexture *m_texture;
188     GLTexture *m_textTexture;
189     GLTexture *m_oldTextTexture;
190     QPixmap *m_textPixmap; // need to keep the pixmap around to workaround some driver problems
191     GLTexture *m_iconTexture;
192     GLTexture *m_oldIconTexture;
193     GLTexture *m_selectionTexture;
194     GLVertexBuffer *m_unstyledVBO;
195     SceneOpenGL *m_scene;
196 
197     static GLTexture* m_unstyledTexture;
198     static QPixmap* m_unstyledPixmap; // need to keep the pixmap around to workaround some driver problems
199     static void updateUnstyledTexture(); // Update OpenGL unstyled frame texture
200 };
201 
202 /**
203  * @short OpenGL implementation of Shadow.
204  *
205  * This class extends Shadow by the Elements required for OpenGL rendering.
206  * @author Martin Gräßlin <mgraesslin@kde.org>
207  */
208 class SceneOpenGLShadow
209     : public Shadow
210 {
211 public:
212     explicit SceneOpenGLShadow(Toplevel *toplevel);
213     ~SceneOpenGLShadow() override;
214 
shadowTexture()215     GLTexture *shadowTexture() {
216         return m_texture.data();
217     }
218 protected:
219     bool prepareBackend() override;
220 private:
221     QSharedPointer<GLTexture> m_texture;
222 };
223 
224 class SceneOpenGLDecorationRenderer : public DecorationRenderer
225 {
226     Q_OBJECT
227 public:
228     enum class DecorationPart : int {
229         Left,
230         Top,
231         Right,
232         Bottom,
233         Count
234     };
235     explicit SceneOpenGLDecorationRenderer(Decoration::DecoratedClientImpl *client);
236     ~SceneOpenGLDecorationRenderer() override;
237 
238     void render(const QRegion &region) override;
239 
texture()240     GLTexture *texture() {
241         return m_texture.data();
242     }
texture()243     GLTexture *texture() const {
244         return m_texture.data();
245     }
246 
247 private:
248     void resizeTexture();
249     QScopedPointer<GLTexture> m_texture;
250 };
251 
252 class KWIN_EXPORT OpenGLFactory : public SceneFactory
253 {
254     Q_OBJECT
255     Q_INTERFACES(KWin::SceneFactory)
256     Q_PLUGIN_METADATA(IID "org.kde.kwin.Scene" FILE "opengl.json")
257 
258 public:
259     explicit OpenGLFactory(QObject *parent = nullptr);
260     ~OpenGLFactory() override;
261 
262     Scene *create(QObject *parent = nullptr) const override;
263 };
264 
265 } // namespace
266 
267 #endif
268