1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtGui module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QOPENGLCONTEXT_P_H |
41 | #define QOPENGLCONTEXT_P_H |
42 | |
43 | // |
44 | // W A R N I N G |
45 | // ------------- |
46 | // |
47 | // This file is not part of the Qt API. It exists purely as an |
48 | // implementation detail. This header file may change from version to |
49 | // version without notice, or even be removed. |
50 | // |
51 | // We mean it. |
52 | // |
53 | |
54 | #include <QtGui/private/qtguiglobal_p.h> |
55 | |
56 | #ifndef QT_NO_OPENGL |
57 | |
58 | #include <qopengl.h> |
59 | #include "qopenglcontext.h" |
60 | #include <private/qobject_p.h> |
61 | #include <qmutex.h> |
62 | |
63 | #include <QtCore/QByteArray> |
64 | #include <QtCore/QHash> |
65 | #include <QtCore/QSet> |
66 | |
67 | QT_BEGIN_NAMESPACE |
68 | |
69 | |
70 | class QOpenGLFunctions; |
71 | class QOpenGLContext; |
72 | class QOpenGLFramebufferObject; |
73 | class QOpenGLMultiGroupSharedResource; |
74 | |
75 | class Q_GUI_EXPORT QOpenGLSharedResource |
76 | { |
77 | public: |
78 | QOpenGLSharedResource(QOpenGLContextGroup *group); |
79 | virtual ~QOpenGLSharedResource() = 0; |
80 | |
81 | QOpenGLContextGroup *group() const { return m_group; } |
82 | |
83 | // schedule the resource for deletion at an appropriate time |
84 | void free(); |
85 | |
86 | protected: |
87 | // the resource's share group no longer exists, invalidate the resource |
88 | virtual void invalidateResource() = 0; |
89 | |
90 | // a valid context in the group is current, free the resource |
91 | virtual void freeResource(QOpenGLContext *context) = 0; |
92 | |
93 | private: |
94 | QOpenGLContextGroup *m_group; |
95 | |
96 | friend class QOpenGLContextGroup; |
97 | friend class QOpenGLContextGroupPrivate; |
98 | friend class QOpenGLMultiGroupSharedResource; |
99 | |
100 | Q_DISABLE_COPY_MOVE(QOpenGLSharedResource) |
101 | }; |
102 | |
103 | class Q_GUI_EXPORT QOpenGLSharedResourceGuard : public QOpenGLSharedResource |
104 | { |
105 | public: |
106 | typedef void (*FreeResourceFunc)(QOpenGLFunctions *functions, GLuint id); |
107 | QOpenGLSharedResourceGuard(QOpenGLContext *context, GLuint id, FreeResourceFunc func) |
108 | : QOpenGLSharedResource(context->shareGroup()) |
109 | , m_id(id) |
110 | , m_func(func) |
111 | { |
112 | } |
113 | |
114 | GLuint id() const { return m_id; } |
115 | |
116 | protected: |
117 | void invalidateResource() override |
118 | { |
119 | m_id = 0; |
120 | } |
121 | |
122 | void freeResource(QOpenGLContext *context) override; |
123 | |
124 | private: |
125 | GLuint m_id; |
126 | FreeResourceFunc m_func; |
127 | }; |
128 | |
129 | class Q_GUI_EXPORT QOpenGLContextGroupPrivate : public QObjectPrivate |
130 | { |
131 | Q_DECLARE_PUBLIC(QOpenGLContextGroup) |
132 | public: |
133 | QOpenGLContextGroupPrivate() |
134 | : m_context(nullptr) |
135 | , m_refs(0) |
136 | { |
137 | } |
138 | |
139 | void addContext(QOpenGLContext *ctx); |
140 | void removeContext(QOpenGLContext *ctx); |
141 | |
142 | void cleanup(); |
143 | |
144 | void deletePendingResources(QOpenGLContext *ctx); |
145 | |
146 | QOpenGLContext *m_context; |
147 | |
148 | QList<QOpenGLContext *> m_shares; |
149 | QRecursiveMutex m_mutex; |
150 | |
151 | QHash<QOpenGLMultiGroupSharedResource *, QOpenGLSharedResource *> m_resources; |
152 | QAtomicInt m_refs; |
153 | |
154 | QList<QOpenGLSharedResource *> m_sharedResources; |
155 | QList<QOpenGLSharedResource *> m_pendingDeletion; |
156 | }; |
157 | |
158 | class Q_GUI_EXPORT QOpenGLMultiGroupSharedResource |
159 | { |
160 | public: |
161 | QOpenGLMultiGroupSharedResource(); |
162 | ~QOpenGLMultiGroupSharedResource(); |
163 | |
164 | void insert(QOpenGLContext *context, QOpenGLSharedResource *value); |
165 | void cleanup(QOpenGLContextGroup *group, QOpenGLSharedResource *value); |
166 | |
167 | QOpenGLSharedResource *value(QOpenGLContext *context); |
168 | |
169 | QList<QOpenGLSharedResource *> resources() const; |
170 | |
171 | template <typename T> |
172 | T *value(QOpenGLContext *context) { |
173 | QOpenGLContextGroup *group = context->shareGroup(); |
174 | // Have to use our own mutex here, not the group's, since |
175 | // m_groups has to be protected too against any concurrent access. |
176 | QMutexLocker locker(&m_mutex); |
177 | T *resource = static_cast<T *>(group->d_func()->m_resources.value(this, nullptr)); |
178 | if (!resource) { |
179 | resource = new T(context); |
180 | insert(context, resource); |
181 | } |
182 | return resource; |
183 | } |
184 | |
185 | private: |
186 | QAtomicInt active; |
187 | QList<QOpenGLContextGroup *> m_groups; |
188 | QRecursiveMutex m_mutex; |
189 | }; |
190 | |
191 | class QPaintEngineEx; |
192 | class QOpenGLFunctions; |
193 | class QOpenGLTextureHelper; |
194 | class QOpenGLVertexArrayObjectHelper; |
195 | |
196 | class Q_GUI_EXPORT QOpenGLContextVersionFunctionHelper |
197 | { |
198 | public: |
199 | virtual ~QOpenGLContextVersionFunctionHelper() {} |
200 | }; |
201 | |
202 | class Q_GUI_EXPORT QOpenGLContextPrivate : public QObjectPrivate |
203 | { |
204 | Q_DECLARE_PUBLIC(QOpenGLContext) |
205 | public: |
206 | QOpenGLContextPrivate() |
207 | : platformGLContext(nullptr) |
208 | , shareContext(nullptr) |
209 | , shareGroup(nullptr) |
210 | , screen(nullptr) |
211 | , surface(nullptr) |
212 | , functions(nullptr) |
213 | , textureFunctions(nullptr) |
214 | , versionFunctions(nullptr) |
215 | , vaoHelper(nullptr) |
216 | , vaoHelperDestroyCallback(nullptr) |
217 | , max_texture_size(-1) |
218 | , workaround_brokenFBOReadBack(false) |
219 | , workaround_brokenTexSubImage(false) |
220 | , workaround_missingPrecisionQualifiers(false) |
221 | , active_engine(nullptr) |
222 | , qgl_current_fbo_invalid(false) |
223 | , qgl_current_fbo(nullptr) |
224 | , defaultFboRedirect(0) |
225 | { |
226 | requestedFormat = QSurfaceFormat::defaultFormat(); |
227 | } |
228 | |
229 | ~QOpenGLContextPrivate() |
230 | { |
231 | //do not delete the QOpenGLContext handle here as it is deleted in |
232 | //QWidgetPrivate::deleteTLSysExtra() |
233 | |
234 | delete versionFunctions; |
235 | } |
236 | |
237 | void adopt(QPlatformOpenGLContext *); |
238 | |
239 | QSurfaceFormat requestedFormat; |
240 | QPlatformOpenGLContext *platformGLContext; |
241 | QOpenGLContext *shareContext; |
242 | QOpenGLContextGroup *shareGroup; |
243 | QScreen *screen; |
244 | QSurface *surface; |
245 | QOpenGLFunctions *functions; |
246 | mutable QSet<QByteArray> extensionNames; |
247 | QOpenGLTextureHelper* textureFunctions; |
248 | std::function<void()> textureFunctionsDestroyCallback; |
249 | QOpenGLContextVersionFunctionHelper *versionFunctions; |
250 | QOpenGLVertexArrayObjectHelper *vaoHelper; |
251 | using QOpenGLVertexArrayObjectHelperDestroyCallback_t = void (*)(QOpenGLVertexArrayObjectHelper *); |
252 | QOpenGLVertexArrayObjectHelperDestroyCallback_t vaoHelperDestroyCallback; |
253 | |
254 | GLint max_texture_size; |
255 | |
256 | bool workaround_brokenFBOReadBack; |
257 | bool workaround_brokenTexSubImage; |
258 | bool workaround_missingPrecisionQualifiers; |
259 | |
260 | QPaintEngineEx *active_engine; |
261 | |
262 | bool qgl_current_fbo_invalid; |
263 | |
264 | // Set and unset in QOpenGLFramebufferObject::bind()/unbind(). |
265 | // (Only meaningful for QOGLFBO since an FBO might be bound by other means) |
266 | // Saves us from querying the driver for the current FBO in most paths. |
267 | QOpenGLFramebufferObject *qgl_current_fbo; |
268 | |
269 | GLuint defaultFboRedirect; |
270 | |
271 | static QOpenGLContext *setCurrentContext(QOpenGLContext *context); |
272 | |
273 | int maxTextureSize(); |
274 | |
275 | static QOpenGLContextPrivate *get(QOpenGLContext *context) |
276 | { |
277 | return context ? context->d_func() : nullptr; |
278 | } |
279 | |
280 | #if !defined(QT_NO_DEBUG) |
281 | static bool toggleMakeCurrentTracker(QOpenGLContext *context, bool value) |
282 | { |
283 | QMutexLocker locker(&makeCurrentTrackerMutex); |
284 | bool old = makeCurrentTracker.value(context, false); |
285 | makeCurrentTracker.insert(context, value); |
286 | return old; |
287 | } |
288 | static void cleanMakeCurrentTracker(QOpenGLContext *context) |
289 | { |
290 | QMutexLocker locker(&makeCurrentTrackerMutex); |
291 | makeCurrentTracker.remove(context); |
292 | } |
293 | static QHash<QOpenGLContext *, bool> makeCurrentTracker; |
294 | static QMutex makeCurrentTrackerMutex; |
295 | #endif |
296 | |
297 | void _q_screenDestroyed(QObject *object); |
298 | }; |
299 | |
300 | Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context); |
301 | Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); |
302 | |
303 | QT_END_NAMESPACE |
304 | |
305 | #endif // QT_NO_OPENGL |
306 | #endif // QOPENGLCONTEXT_P_H |
307 | |