1/****************************************************************************
2**
3** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
4** Copyright (C) 2016 The Qt Company Ltd.
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPL3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or (at your option) the GNU General
29** Public license version 3 or any later version approved by the KDE Free
30** Qt Foundation. The licenses are as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32** included in the packaging of this file. Please review the following
33** information to ensure the GNU General Public License requirements will
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35** https://www.gnu.org/licenses/gpl-3.0.html.
36**
37** $QT_END_LICENSE$
38**
39**
40** This file was generated by glgen version 0.1
41** Command line was: glgen
42**
43** glgen is Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB)
44**
45** This is an auto-generated file.
46** Do not edit! All changes made to it will be lost.
47**
48****************************************************************************/
49
50#include "qopenglversionfunctions.h"
51#include "qopenglversionfunctions_p.h"
52#include "qopenglcontext.h"
53#include "qdebug.h"
54
55QT_BEGIN_NAMESPACE
56
57QOpenGLContextVersionData::~QOpenGLContextVersionData()
58{
59 for (auto *f : qAsConst(externalFunctions)) {
60 auto *fp = QAbstractOpenGLFunctionsPrivate::get(f);
61 fp->owningContext = nullptr;
62 fp->initialized = false;
63 }
64 externalFunctions.clear();
65 qDeleteAll(functions);
66 functions.clear();
67}
68
69QOpenGLContextVersionData *QOpenGLContextVersionData::forContext(QOpenGLContext *context)
70{
71 QOpenGLContextPrivate *context_d = QOpenGLContextPrivate::get(context);
72 if (context_d->versionFunctions == nullptr)
73 context_d->versionFunctions = new QOpenGLContextVersionData;
74
75 return static_cast<QOpenGLContextVersionData *>(context_d->versionFunctions);
76}
77
78#define QT_OPENGL_COUNT_FUNCTIONS(ret, name, args) +1
79#define QT_OPENGL_FUNCTION_NAMES(ret, name, args) \
80 "gl"#name"\0"
81#define QT_OPENGL_IMPLEMENT(CLASS, FUNCTIONS) \
82void CLASS::init() \
83{ \
84 const char *names = FUNCTIONS(QT_OPENGL_FUNCTION_NAMES); \
85 const char *name = names; \
86 for (int i = 0; i < FUNCTIONS(QT_OPENGL_COUNT_FUNCTIONS); ++i) { \
87 functions[i] = context->getProcAddress(name); \
88 name += strlen(name) + 1; \
89 } \
90}
91
92QOpenGLVersionFunctionsStorage::QOpenGLVersionFunctionsStorage()
93 : backends(nullptr)
94{
95}
96
97QOpenGLVersionFunctionsStorage::~QOpenGLVersionFunctionsStorage()
98{
99#if !QT_CONFIG(opengles2)
100 if (backends) {
101
102 int i = 0;
103
104#define DELETE_BACKEND(X) \
105 if (backends[i] && !--backends[i]->refs) \
106 delete static_cast<QOpenGLFunctions_##X##Backend*>(backends[i]); \
107 ++i;
108
109 QT_OPENGL_VERSIONS(DELETE_BACKEND)
110#undef DELETE_BACKEND
111 delete[] backends;
112 }
113#endif
114}
115
116QOpenGLVersionFunctionsBackend *QOpenGLVersionFunctionsStorage::backend(QOpenGLContext *context, QOpenGLVersionFunctionsBackend::Version v)
117{
118#if QT_CONFIG(opengles2)
119 Q_UNUSED(context);
120 Q_UNUSED(v);
121 return 0;
122#else
123 if (!backends) {
124 backends = new QOpenGLVersionFunctionsBackend *[QOpenGLVersionFunctionsBackend::OpenGLVersionBackendCount];
125 memset(backends, 0, sizeof(QOpenGLVersionFunctionsBackend *)*QOpenGLVersionFunctionsBackend::OpenGLVersionBackendCount);
126 }
127 if (backends[v])
128 return backends[v];
129
130 switch(v) {
131#define VERSION_ENUM(X) QOpenGLVersionFunctionsBackend::OpenGL_##X
132#define CREATE_BACKEND(X) \
133 case VERSION_ENUM(X): \
134 backends[VERSION_ENUM(X)] = new QOpenGLFunctions_##X##Backend(context); \
135 break;
136 QT_OPENGL_VERSIONS(CREATE_BACKEND)
137 case QOpenGLVersionFunctionsBackend::OpenGLVersionBackendCount:
138 Q_UNREACHABLE();
139 }
140 // the storage keeps one ref
141 ++backends[v]->refs;
142 return backends[v];
143#endif
144}
145
146QOpenGLVersionFunctionsBackend *QAbstractOpenGLFunctionsPrivate::functionsBackend(QOpenGLContext *context, QOpenGLVersionFunctionsBackend::Version v)
147{
148 Q_ASSERT(context);
149 return QOpenGLContextVersionData::forContext(context)->functionsStorage.backend(context, v);
150}
151
152void QAbstractOpenGLFunctionsPrivate::insertExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f)
153{
154 Q_ASSERT(context);
155 QOpenGLContextVersionData::forContext(context)->externalFunctions.insert(f);
156}
157
158void QAbstractOpenGLFunctionsPrivate::removeExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f)
159{
160 Q_ASSERT(context);
161 QOpenGLContextVersionData::forContext(context)->externalFunctions.remove(f);
162}
163
164/*!
165 \class QAbstractOpenGLFunctions
166 \inmodule QtOpenGL
167 \since 5.1
168 \brief The QAbstractOpenGLFunctions class is the base class of a family of
169 classes that expose all functions for each OpenGL version and
170 profile.
171
172 OpenGL implementations on different platforms are able to link to a variable
173 number of OpenGL functions depending upon the OpenGL ABI on that platform.
174 For example, on Microsoft Windows only functions up to those in OpenGL 1.1
175 can be linked to at build time. All other functions must be resolved at
176 runtime. The traditional solution to this has been to use either
177 QOpenGLContext::getProcAddress() or QOpenGLFunctions. The former is tedious
178 and error prone and means dealing directly with function pointers. The
179 latter only exposes those functions common to OpenGL ES 2 and desktop
180 OpenGL. There is however much new OpenGL functionality that is useful when
181 writing real world OpenGL applications.
182
183 Qt now provides a family of classes which all inherit from
184 QAbstractOpenGLFunctions which expose every core OpenGL function by way of a
185 corresponding member function. There is a class for every valid combination
186 of OpenGL version and profile. Each class follows the naming convention:
187 \badcode
188 QOpenGLFunctions_<MAJOR VERSION>_<MINOR VERSION>[_PROFILE]
189 \endcode
190
191 For OpenGL versions 1.0 through to 3.0 there are no profiles, leading to the
192 classes:
193
194 \list
195 \li QOpenGLFunctions_1_0
196 \li QOpenGLFunctions_1_1
197 \li QOpenGLFunctions_1_2
198 \li QOpenGLFunctions_1_3
199 \li QOpenGLFunctions_1_4
200 \li QOpenGLFunctions_1_5
201 \li QOpenGLFunctions_2_0
202 \li QOpenGLFunctions_2_1
203 \li QOpenGLFunctions_3_0
204 \endlist
205
206 where each class inherits from QAbstractOpenGLFunctions.
207
208 OpenGL version 3.1 removed many deprecated functions leading to a much
209 simpler and generic API.
210
211 With OpenGL 3.2 the concept of profiles was introduced. Two profiles are
212 currently defined for OpenGL: Core and Compatibility.
213
214 The Core profile does not include any of the functions that were removed
215 in OpenGL 3.1. The Compatibility profile contains all functions in the
216 Core profile of the same version plus all of the functions that were
217 removed in OpenGL 3.1. In this way the Compatibility profile classes allow
218 use of newer OpenGL functionality but also allows you to keep using your
219 legacy OpenGL code. For new OpenGL code the Core profile should be
220 preferred.
221
222 Please note that some vendors, notably Apple, do not implement the
223 Compatibility profile. Therefore if you wish to target new OpenGL features
224 on \macos then you should ensure that you request a Core profile context via
225 QSurfaceFormat::setProfile().
226
227 Qt provides classes for all version and Core and Compatibility profile
228 combinations. The classes for OpenGL versions 3.1 through to 4.3 are:
229
230 \list
231 \li QOpenGLFunctions_3_1
232 \li QOpenGLFunctions_3_2_Core
233 \li QOpenGLFunctions_3_2_Compatibility
234 \li QOpenGLFunctions_3_3_Core
235 \li QOpenGLFunctions_3_3_Compatibility
236 \li QOpenGLFunctions_4_0_Core
237 \li QOpenGLFunctions_4_0_Compatibility
238 \li QOpenGLFunctions_4_1_Core
239 \li QOpenGLFunctions_4_1_Compatibility
240 \li QOpenGLFunctions_4_2_Core
241 \li QOpenGLFunctions_4_2_Compatibility
242 \li QOpenGLFunctions_4_3_Core
243 \li QOpenGLFunctions_4_3_Compatibility
244 \endlist
245
246 where each class inherits from QAbstractOpenGLFunctions.
247
248 A pointer to an object of the class corresponding to the version and
249 profile of OpenGL in use can be obtained from
250 QOpenGLVersionFunctionsFactory::get(). If obtained in this way, note that
251 the QOpenGLContext retains ownership of the object. This is so that the
252 instance can be cached and shared.
253
254 Before calling any of the exposed OpenGL functions you must ensure that the
255 object has resolved the function pointers to the OpenGL functions. This
256 only needs to be done once per instance with initializeOpenGLFunctions().
257 Once initialized, the object can be used to call any OpenGL function for
258 the corresponding version and profile. Note that initializeOpenGLFunctions()
259 can fail in some circumstances so check the return value. Situations in
260 which initialization can fail are if you have a functions object for a version
261 or profile that contains functions that are not part of the context being
262 used to resolve the function pointers.
263
264 If you exclusively use function objects then you will get compile time
265 errors if you attempt to use a function not included in that version and
266 profile. This is obviously a lot easier to debug than undefined behavior
267 at run time.
268
269 \sa QOpenGLVersionFunctionsFactory::get()
270*/
271/*!
272 Constructs a QAbstractOpenGLFunctions object.
273*/
274QAbstractOpenGLFunctions::QAbstractOpenGLFunctions()
275 : d_ptr(new QAbstractOpenGLFunctionsPrivate)
276{
277}
278
279/*!
280 Destroys a QAbstractOpenGLFunctions object.
281*/
282QAbstractOpenGLFunctions::~QAbstractOpenGLFunctions()
283{
284 Q_D(QAbstractOpenGLFunctions);
285 if (d->owningContext)
286 d->removeExternalFunctions(d->owningContext, this);
287 delete d_ptr;
288}
289
290/*! \internal
291 */
292bool QAbstractOpenGLFunctions::initializeOpenGLFunctions()
293{
294 Q_D(QAbstractOpenGLFunctions);
295 d->initialized = true;
296
297 // For a subclass whose instance is not created via
298 // QOpenGLContext::versionFunctions() owningContext is not set. Set it now
299 // and register such instances to the context as external ones. These are
300 // not owned by the context but still need certain cleanup when the context
301 // is destroyed.
302 if (!d->owningContext) {
303 d->owningContext = QOpenGLContext::currentContext();
304 if (d->owningContext)
305 d->insertExternalFunctions(d->owningContext, this);
306 }
307
308 return true;
309}
310
311/*! \internal
312 */
313bool QAbstractOpenGLFunctions::isInitialized() const
314{
315 Q_D(const QAbstractOpenGLFunctions);
316 return d->initialized;
317}
318
319/*! \internal
320 */
321void QAbstractOpenGLFunctions::setOwningContext(const QOpenGLContext *context)
322{
323 Q_D(QAbstractOpenGLFunctions);
324 d->owningContext = const_cast<QOpenGLContext*>(context);
325}
326
327/*! \internal
328 */
329QOpenGLContext *QAbstractOpenGLFunctions::owningContext() const
330{
331 Q_D(const QAbstractOpenGLFunctions);
332 return d->owningContext;
333}
334
335#if !QT_CONFIG(opengles2)
336
337QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_0_CoreBackend, QT_OPENGL_1_0_FUNCTIONS)
338QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_1_CoreBackend, QT_OPENGL_1_1_FUNCTIONS)
339
340QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_2_CoreBackend, QT_OPENGL_1_2_FUNCTIONS)
341QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_3_CoreBackend, QT_OPENGL_1_3_FUNCTIONS)
342QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_4_CoreBackend, QT_OPENGL_1_4_FUNCTIONS)
343QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_5_CoreBackend, QT_OPENGL_1_5_FUNCTIONS)
344QT_OPENGL_IMPLEMENT(QOpenGLFunctions_2_0_CoreBackend, QT_OPENGL_2_0_FUNCTIONS)
345QT_OPENGL_IMPLEMENT(QOpenGLFunctions_2_1_CoreBackend, QT_OPENGL_2_1_FUNCTIONS)
346QT_OPENGL_IMPLEMENT(QOpenGLFunctions_3_0_CoreBackend, QT_OPENGL_3_0_FUNCTIONS)
347QT_OPENGL_IMPLEMENT(QOpenGLFunctions_3_1_CoreBackend, QT_OPENGL_3_1_FUNCTIONS)
348QT_OPENGL_IMPLEMENT(QOpenGLFunctions_3_2_CoreBackend, QT_OPENGL_3_2_FUNCTIONS)
349QT_OPENGL_IMPLEMENT(QOpenGLFunctions_3_3_CoreBackend, QT_OPENGL_3_3_FUNCTIONS)
350QT_OPENGL_IMPLEMENT(QOpenGLFunctions_4_0_CoreBackend, QT_OPENGL_4_0_FUNCTIONS)
351QT_OPENGL_IMPLEMENT(QOpenGLFunctions_4_1_CoreBackend, QT_OPENGL_4_1_FUNCTIONS)
352QT_OPENGL_IMPLEMENT(QOpenGLFunctions_4_2_CoreBackend, QT_OPENGL_4_2_FUNCTIONS)
353QT_OPENGL_IMPLEMENT(QOpenGLFunctions_4_3_CoreBackend, QT_OPENGL_4_3_FUNCTIONS)
354QT_OPENGL_IMPLEMENT(QOpenGLFunctions_4_4_CoreBackend, QT_OPENGL_4_4_FUNCTIONS)
355QT_OPENGL_IMPLEMENT(QOpenGLFunctions_4_5_CoreBackend, QT_OPENGL_4_5_FUNCTIONS)
356
357QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_0_DeprecatedBackend, QT_OPENGL_1_0_DEPRECATED_FUNCTIONS)
358QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_1_DeprecatedBackend, QT_OPENGL_1_1_DEPRECATED_FUNCTIONS)
359
360QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_2_DeprecatedBackend, QT_OPENGL_1_2_DEPRECATED_FUNCTIONS)
361QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_3_DeprecatedBackend, QT_OPENGL_1_3_DEPRECATED_FUNCTIONS)
362QT_OPENGL_IMPLEMENT(QOpenGLFunctions_1_4_DeprecatedBackend, QT_OPENGL_1_4_DEPRECATED_FUNCTIONS)
363QT_OPENGL_IMPLEMENT(QOpenGLFunctions_2_0_DeprecatedBackend, QT_OPENGL_2_0_DEPRECATED_FUNCTIONS)
364QT_OPENGL_IMPLEMENT(QOpenGLFunctions_3_0_DeprecatedBackend, QT_OPENGL_3_0_DEPRECATED_FUNCTIONS)
365QT_OPENGL_IMPLEMENT(QOpenGLFunctions_3_3_DeprecatedBackend, QT_OPENGL_3_3_DEPRECATED_FUNCTIONS)
366QT_OPENGL_IMPLEMENT(QOpenGLFunctions_4_5_DeprecatedBackend, QT_OPENGL_4_5_DEPRECATED_FUNCTIONS)
367
368#else
369
370// No backends for OpenGL ES 2
371
372#endif // !QT_CONFIG(opengles2)
373
374QT_END_NAMESPACE
375