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

source code of qtbase/src/gui/kernel/qopenglcontext_p.h