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 #ifndef KWIN_SCENE_OPENGL_BACKEND_H
11 #define KWIN_SCENE_OPENGL_BACKEND_H
12 
13 #include <QObject>
14 #include <QRegion>
15 
16 #include <kwin_export.h>
17 
18 namespace KWin
19 {
20 class AbstractOutput;
21 class OpenGLBackend;
22 class OverlayWindow;
23 class PlatformSurfaceTexture;
24 class SurfaceItem;
25 class SurfacePixmapInternal;
26 class SurfacePixmapX11;
27 class SurfacePixmapWayland;
28 class GLTexture;
29 
30 /**
31  * @brief The OpenGLBackend creates and holds the OpenGL context and is responsible for Texture from Pixmap.
32  *
33  * The OpenGLBackend is an abstract base class used by the SceneOpenGL to abstract away the differences
34  * between various OpenGL windowing systems such as GLX and EGL.
35  *
36  * A concrete implementation has to create and release the OpenGL context in a way so that the
37  * SceneOpenGL does not have to care about it.
38  *
39  * In addition a major task for this class is to generate the SceneOpenGLTexturePrivate which is
40  * able to perform the texture from pixmap operation in the given backend.
41  *
42  * @author Martin Gräßlin <mgraesslin@kde.org>
43  */
44 class KWIN_EXPORT OpenGLBackend : public QObject
45 {
46     Q_OBJECT
47 
48 public:
49     OpenGLBackend();
50     virtual ~OpenGLBackend();
51 
52     virtual void init() = 0;
53 
54     virtual PlatformSurfaceTexture *createPlatformSurfaceTextureInternal(SurfacePixmapInternal *pixmap);
55     virtual PlatformSurfaceTexture *createPlatformSurfaceTextureX11(SurfacePixmapX11 *pixmap);
56     virtual PlatformSurfaceTexture *createPlatformSurfaceTextureWayland(SurfacePixmapWayland *pixmap);
57 
58     /**
59      * Notifies about starting to paint.
60      *
61      * @p damage contains the reported damage as suggested by windows and effects on prepaint calls.
62      */
63     virtual void aboutToStartPainting(AbstractOutput *output, const QRegion &damage);
64     virtual bool makeCurrent() = 0;
65     virtual void doneCurrent() = 0;
66     virtual QRegion beginFrame(AbstractOutput *output) = 0;
67     virtual void endFrame(AbstractOutput *output, const QRegion &damage, const QRegion &damagedRegion) = 0;
68     /**
69      * Tries to directly scan out a surface to the screen)
70      * @return if the scanout fails (or is not supported on the specified screen)
71      */
72     virtual bool scanout(AbstractOutput *output, SurfaceItem *surfaceItem);
73 
74     /**
75      * @brief Returns the OverlayWindow used by the backend.
76      *
77      * A backend does not have to use an OverlayWindow, this is mostly for the X world.
78      * In case the backend does not use an OverlayWindow it is allowed to return @c null.
79      * It's the task of the caller to check whether it is @c null.
80      *
81      * @return :OverlayWindow*
82      */
83     virtual OverlayWindow *overlayWindow() const;
84     /**
85      * @brief Whether the creation of the Backend failed.
86      *
87      * The SceneOpenGL should test whether the Backend got constructed correctly. If this method
88      * returns @c true, the SceneOpenGL should not try to start the rendering.
89      *
90      * @return bool @c true if the creation of the Backend failed, @c false otherwise.
91      */
isFailed()92     bool isFailed() const {
93         return m_failed;
94     }
95     /**
96      * @brief Whether the backend uses direct rendering.
97      *
98      * Some OpenGLScene modes require direct rendering. E.g. the OpenGL 2 should not be used
99      * if direct rendering is not supported by the Scene.
100      *
101      * @return bool @c true if the GL context is direct, @c false if indirect
102      */
isDirectRendering()103     bool isDirectRendering() const {
104         return m_directRendering;
105     }
106 
supportsBufferAge()107     bool supportsBufferAge() const {
108         return m_haveBufferAge;
109     }
110 
supportsPartialUpdate()111     bool supportsPartialUpdate() const
112     {
113         return m_havePartialUpdate;
114     }
supportsSwapBuffersWithDamage()115     bool supportsSwapBuffersWithDamage() const
116     {
117         return m_haveSwapBuffersWithDamage;
118     }
119 
supportsNativeFence()120     bool supportsNativeFence() const
121     {
122         return m_haveNativeFence;
123     }
124     virtual bool directScanoutAllowed(AbstractOutput *output) const;
125 
126     /**
127      * The backend specific extensions (e.g. EGL/GLX extensions).
128      *
129      * Not the OpenGL (ES) extension!
130      */
extensions()131     QList<QByteArray> extensions() const {
132         return m_extensions;
133     }
134 
135     /**
136      * @returns whether the backend specific extensions contains @p extension.
137      */
hasExtension(const QByteArray & extension)138     bool hasExtension(const QByteArray &extension) const {
139         return m_extensions.contains(extension);
140     }
141 
142     /**
143      * Copy a region of pixels from the current read to the current draw buffer
144      */
145     void copyPixels(const QRegion &region);
146 
147     virtual QSharedPointer<GLTexture> textureForOutput(AbstractOutput *output) const;
148 
149 protected:
150     /**
151      * @brief Sets the backend initialization to failed.
152      *
153      * This method should be called by the concrete subclass in case the initialization failed.
154      * The given @p reason is logged as a warning.
155      *
156      * @param reason The reason why the initialization failed.
157      */
158     void setFailed(const QString &reason);
159     /**
160      * @brief Sets whether the OpenGL context is direct.
161      *
162      * Should be called by the concrete subclass once it is determined whether the OpenGL context is
163      * direct or indirect.
164      * If the subclass does not call this method, the backend defaults to @c false.
165      *
166      * @param direct @c true if the OpenGL context is direct, @c false if indirect
167      */
setIsDirectRendering(bool direct)168     void setIsDirectRendering(bool direct) {
169         m_directRendering = direct;
170     }
171 
setSupportsBufferAge(bool value)172     void setSupportsBufferAge(bool value) {
173         m_haveBufferAge = value;
174     }
175 
setSupportsPartialUpdate(bool value)176     void setSupportsPartialUpdate(bool value)
177     {
178         m_havePartialUpdate = value;
179     }
180 
setSupportsSwapBuffersWithDamage(bool value)181     void setSupportsSwapBuffersWithDamage(bool value)
182     {
183         m_haveSwapBuffersWithDamage = value;
184     }
185 
setSupportsNativeFence(bool value)186     void setSupportsNativeFence(bool value)
187     {
188         m_haveNativeFence = value;
189     }
190 
191     /**
192      * Sets the platform-specific @p extensions.
193      *
194      * These are the EGL/GLX extensions, not the OpenGL extensions
195      */
setExtensions(const QList<QByteArray> & extensions)196     void setExtensions(const QList<QByteArray> &extensions) {
197         m_extensions = extensions;
198     }
199 
200 private:
201     /**
202      * @brief Whether direct rendering is used, defaults to @c false.
203      */
204     bool m_directRendering;
205     /**
206      * @brief Whether the backend supports GLX_EXT_buffer_age / EGL_EXT_buffer_age.
207      */
208     bool m_haveBufferAge;
209     /**
210      * @brief Whether the backend supports EGL_KHR_partial_update
211      */
212     bool m_havePartialUpdate = false;
213     bool m_haveSwapBuffersWithDamage = false;
214     /**
215      * @brief Whether the backend supports EGL_ANDROID_native_fence_sync.
216      */
217     bool m_haveNativeFence = false;
218     /**
219      * @brief Whether the initialization failed, of course default to @c false.
220      */
221     bool m_failed;
222     QList<QByteArray> m_extensions;
223 };
224 
225 }
226 
227 #endif
228