qopenglcontext.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/kernel/qopenglcontext.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
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#include <qpa/qplatformopenglcontext.h>-
41#include <qpa/qplatformintegration.h>-
42#include "qopenglcontext.h"-
43#include "qopenglcontext_p.h"-
44#include "qwindow.h"-
45-
46#include <QtCore/QThreadStorage>-
47#include <QtCore/QThread>-
48-
49#include <QtGui/private/qguiapplication_p.h>-
50#include <QtGui/private/qopengl_p.h>-
51#include <QtGui/private/qwindow_p.h>-
52#include <QtGui/QScreen>-
53#include <qpa/qplatformnativeinterface.h>-
54-
55#include <private/qopenglextensions_p.h>-
56#include <private/qopenglversionfunctionsfactory_p.h>-
57-
58#include <private/qopengltexturehelper_p.h>-
59-
60#include <QDebug>-
61-
62#ifndef QT_OPENGL_ES_2-
63#include <QOpenGLFunctions_1_0>-
64#include <QOpenGLFunctions_3_2_Core>-
65#endif-
66-
67QT_BEGIN_NAMESPACE-
68-
69class QOpenGLVersionProfilePrivate-
70{-
71public:-
72 QOpenGLVersionProfilePrivate()-
73 : majorVersion(0),-
74 minorVersion(0),-
75 profile(QSurfaceFormat::NoProfile)-
76 {}
never executed: end of block
0
77-
78 int majorVersion;-
79 int minorVersion;-
80 QSurfaceFormat::OpenGLContextProfile profile;-
81};-
82-
83-
84/*!-
85 \class QOpenGLVersionProfile-
86 \inmodule QtGui-
87 \since 5.1-
88 \brief The QOpenGLVersionProfile class represents the version and if applicable-
89 the profile of an OpenGL context.-
90-
91 An object of this class can be passed to QOpenGLContext::versionFunctions() to-
92 request a functions object for a specific version and profile of OpenGL.-
93-
94 It also contains some helper functions to check if a version supports profiles-
95 or is a legacy version.-
96*/-
97-
98/*!-
99 Creates a default invalid QOpenGLVersionProfile object.-
100*/-
101QOpenGLVersionProfile::QOpenGLVersionProfile()-
102 : d(new QOpenGLVersionProfilePrivate)-
103{-
104}
never executed: end of block
0
105-
106/*!-
107 Creates a QOpenGLVersionProfile object initialised with the version and profile-
108 from \a format.-
109*/-
110QOpenGLVersionProfile::QOpenGLVersionProfile(const QSurfaceFormat &format)-
111 : d(new QOpenGLVersionProfilePrivate)-
112{-
113 d->majorVersion = format.majorVersion();-
114 d->minorVersion = format.minorVersion();-
115 d->profile = format.profile();-
116}
never executed: end of block
0
117-
118/*!-
119 Constructs a copy of \a other.-
120*/-
121QOpenGLVersionProfile::QOpenGLVersionProfile(const QOpenGLVersionProfile &other)-
122 : d(new QOpenGLVersionProfilePrivate)-
123{-
124 *d = *(other.d);-
125}
never executed: end of block
0
126-
127/*!-
128 Destroys the QOpenGLVersionProfile object.-
129*/-
130QOpenGLVersionProfile::~QOpenGLVersionProfile()-
131{-
132 delete d;-
133}
never executed: end of block
0
134-
135/*!-
136 Assigns the version and profile of \a rhs to this QOpenGLVersionProfile object.-
137*/-
138QOpenGLVersionProfile &QOpenGLVersionProfile::operator=(const QOpenGLVersionProfile &rhs)-
139{-
140 if (this == &rhs)
this == &rhsDescription
TRUEnever evaluated
FALSEnever evaluated
0
141 return *this;
never executed: return *this;
0
142 *d = *(rhs.d);-
143 return *this;
never executed: return *this;
0
144}-
145-
146/*!-
147 Returns a QPair<int,int> where the components represent the major and minor OpenGL-
148 version numbers respectively.-
149-
150 \sa setVersion()-
151*/-
152QPair<int, int> QOpenGLVersionProfile::version() const-
153{-
154 return qMakePair( d->majorVersion, d->minorVersion);
never executed: return qMakePair( d->majorVersion, d->minorVersion);
0
155}-
156-
157/*!-
158 Sets the major and minor version numbers to \a majorVersion and \a minorVersion respectively.-
159-
160 \sa version()-
161*/-
162void QOpenGLVersionProfile::setVersion(int majorVersion, int minorVersion)-
163{-
164 d->majorVersion = majorVersion;-
165 d->minorVersion = minorVersion;-
166}
never executed: end of block
0
167-
168/*!-
169 Returns the OpenGL profile. Only makes sense if profiles are supported by this version.-
170-
171 \sa setProfile()-
172*/-
173QSurfaceFormat::OpenGLContextProfile QOpenGLVersionProfile::profile() const-
174{-
175 return d->profile;
never executed: return d->profile;
0
176}-
177-
178/*!-
179 Sets the OpenGL profile \a profile. Only makes sense if profiles are supported by-
180 this version.-
181-
182 \sa profile()-
183*/-
184void QOpenGLVersionProfile::setProfile(QSurfaceFormat::OpenGLContextProfile profile)-
185{-
186 d->profile = profile;-
187}
never executed: end of block
0
188-
189/*!-
190 Returns \c true if profiles are supported by the OpenGL version returned by version(). Only-
191 OpenGL versions >= 3.2 support profiles.-
192-
193 \sa profile(), version()-
194*/-
195bool QOpenGLVersionProfile::hasProfiles() const-
196{-
197 return ( d->majorVersion > 3
never executed: return ( d->majorVersion > 3 || (d->majorVersion == 3 && d->minorVersion > 1));
0
198 || (d->majorVersion == 3 && d->minorVersion > 1));
never executed: return ( d->majorVersion > 3 || (d->majorVersion == 3 && d->minorVersion > 1));
0
199}-
200-
201/*!-
202 Returns \c true is the OpenGL version returned by version() contains deprecated functions-
203 and does not support profiles i.e. if the OpenGL version is <= 3.1.-
204*/-
205bool QOpenGLVersionProfile::isLegacyVersion() const-
206{-
207 return (d->majorVersion < 3 || (d->majorVersion == 3 && d->minorVersion == 0));
never executed: return (d->majorVersion < 3 || (d->majorVersion == 3 && d->minorVersion == 0));
0
208}-
209-
210/*!-
211 Returns \c true if the version number is valid. Note that for a default constructed-
212 QOpenGLVersionProfile object this function will return \c false.-
213-
214 \sa setVersion(), version()-
215*/-
216bool QOpenGLVersionProfile::isValid() const-
217{-
218 return d->majorVersion > 0 && d->minorVersion >= 0;
never executed: return d->majorVersion > 0 && d->minorVersion >= 0;
0
219}-
220-
221class QGuiGLThreadContext-
222{-
223public:-
224 QGuiGLThreadContext()-
225 : context(0)-
226 {-
227 }
never executed: end of block
0
228 ~QGuiGLThreadContext() {-
229 if (context)
contextDescription
TRUEnever evaluated
FALSEnever evaluated
0
230 context->doneCurrent();
never executed: context->doneCurrent();
0
231 }
never executed: end of block
0
232 QOpenGLContext *context;-
233};-
234-
235Q_GLOBAL_STATIC(QThreadStorage<QGuiGLThreadContext *>, qwindow_context_storage);
never executed: end of block
never executed: guard.store(QtGlobalStatic::Destroyed);
never executed: return &holder.value;
guard.load() =...c::InitializedDescription
TRUEnever evaluated
FALSEnever evaluated
0
236static QOpenGLContext *global_share_context = 0;-
237-
238#ifndef QT_NO_DEBUG-
239QHash<QOpenGLContext *, bool> QOpenGLContextPrivate::makeCurrentTracker;-
240QMutex QOpenGLContextPrivate::makeCurrentTrackerMutex;-
241#endif-
242-
243/*!-
244 \internal-
245-
246 This function is used by Qt::AA_ShareOpenGLContexts and the Qt-
247 WebEngine to set up context sharing across multiple windows. Do-
248 not use it for any other purpose.-
249-
250 Please maintain the binary compatibility of these functions.-
251*/-
252void qt_gl_set_global_share_context(QOpenGLContext *context)-
253{-
254 global_share_context = context;-
255}
never executed: end of block
0
256-
257/*!-
258 \internal-
259*/-
260QOpenGLContext *qt_gl_global_share_context()-
261{-
262 return global_share_context;
never executed: return global_share_context;
0
263}-
264-
265/*!-
266 \class QOpenGLContext-
267 \inmodule QtGui-
268 \since 5.0-
269 \brief The QOpenGLContext class represents a native OpenGL context, enabling-
270 OpenGL rendering on a QSurface.-
271-
272 QOpenGLContext represents the OpenGL state of an underlying OpenGL context.-
273 To set up a context, set its screen and format such that they match those-
274 of the surface or surfaces with which the context is meant to be used, if-
275 necessary make it share resources with other contexts with-
276 setShareContext(), and finally call create(). Use the return value or isValid()-
277 to check if the context was successfully initialized.-
278-
279 A context can be made current against a given surface by calling-
280 makeCurrent(). When OpenGL rendering is done, call swapBuffers() to swap-
281 the front and back buffers of the surface, so that the newly rendered-
282 content becomes visible. To be able to support certain platforms,-
283 QOpenGLContext requires that you call makeCurrent() again before starting-
284 rendering a new frame, after calling swapBuffers().-
285-
286 If the context is temporarily not needed, such as when the application is-
287 not rendering, it can be useful to delete it in order to free resources.-
288 You can connect to the aboutToBeDestroyed() signal to clean up any-
289 resources that have been allocated with different ownership from the-
290 QOpenGLContext itself.-
291-
292 Once a QOpenGLContext has been made current, you can render to it in a-
293 platform independent way by using Qt's OpenGL enablers such as-
294 QOpenGLFunctions, QOpenGLBuffer, QOpenGLShaderProgram, and-
295 QOpenGLFramebufferObject. It is also possible to use the platform's OpenGL-
296 API directly, without using the Qt enablers, although potentially at the-
297 cost of portability. The latter is necessary when wanting to use OpenGL 1.x-
298 or OpenGL ES 1.x.-
299-
300 For more information about the OpenGL API, refer to the official-
301 \l{http://www.opengl.org}{OpenGL documentation}.-
302-
303 For an example of how to use QOpenGLContext see the-
304 \l{OpenGL Window Example}{OpenGL Window} example.-
305-
306 \section1 Thread Affinity-
307-
308 QOpenGLContext can be moved to a different thread with moveToThread(). Do-
309 not call makeCurrent() from a different thread than the one to which the-
310 QOpenGLContext object belongs. A context can only be current in one thread-
311 and against one surface at a time, and a thread only has one context-
312 current at a time.-
313-
314 \section1 Context Resource Sharing-
315-
316 Resources, such as framebuffer objects, textures, and vertex buffer objects-
317 can be shared between contexts. Use setShareContext() before calling-
318 create() to specify that the contexts should share these resources.-
319 QOpenGLContext internally keeps track of a QOpenGLContextGroup object which-
320 can be accessed with shareGroup(), and which can be used to find all the-
321 contexts in a given share group. A share group consists of all contexts that-
322 have been successfully initialized and are sharing with an existing context in-
323 the share group. A non-sharing context has a share group consisting of a-
324 single context.-
325-
326 \section1 Default Framebuffer-
327-
328 On certain platforms, a framebuffer other than 0 might be the default frame-
329 buffer depending on the current surface. Instead of calling-
330 glBindFramebuffer(0), it is recommended that you use-
331 glBindFramebuffer(ctx->defaultFramebufferObject()), to ensure that your-
332 application is portable between different platforms. However, if you use-
333 QOpenGLFunctions::glBindFramebuffer(), this is done automatically for you.-
334-
335 \sa QOpenGLFunctions, QOpenGLBuffer, QOpenGLShaderProgram, QOpenGLFramebufferObject-
336*/-
337-
338/*!-
339 \internal-
340-
341 Set the current context. Returns the previously current context.-
342*/-
343QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)-
344{-
345 QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData();-
346 if (!threadContext) {
!threadContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
347 if (!QThread::currentThread()) {
!QThread::currentThread()Description
TRUEnever evaluated
FALSEnever evaluated
0
348 qWarning("No QTLS available. currentContext won't work");-
349 return 0;
never executed: return 0;
0
350 }-
351 threadContext = new QGuiGLThreadContext;-
352 qwindow_context_storage()->setLocalData(threadContext);-
353 }
never executed: end of block
0
354 QOpenGLContext *previous = threadContext->context;-
355 threadContext->context = context;-
356 return previous;
never executed: return previous;
0
357}-
358-
359int QOpenGLContextPrivate::maxTextureSize()-
360{-
361 if (max_texture_size != -1)
max_texture_size != -1Description
TRUEnever evaluated
FALSEnever evaluated
0
362 return max_texture_size;
never executed: return max_texture_size;
0
363-
364 Q_Q(QOpenGLContext);-
365 QOpenGLFunctions *funcs = q->functions();-
366 funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);-
367-
368#ifndef QT_OPENGL_ES-
369 if (!q->isOpenGLES()) {
!q->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
370 GLenum proxy = GL_PROXY_TEXTURE_2D;-
371-
372 GLint size;-
373 GLint next = 64;-
374 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);-
375-
376 QOpenGLFunctions_1_0 *gl1funcs = 0;-
377 QOpenGLFunctions_3_2_Core *gl3funcs = 0;-
378-
379 if (q->format().profile() == QSurfaceFormat::CoreProfile)
q->format().pr...t::CoreProfileDescription
TRUEnever evaluated
FALSEnever evaluated
0
380 gl3funcs = q->versionFunctions<QOpenGLFunctions_3_2_Core>();
never executed: gl3funcs = q->versionFunctions<QOpenGLFunctions_3_2_Core>();
0
381 else-
382 gl1funcs = q->versionFunctions<QOpenGLFunctions_1_0>();
never executed: gl1funcs = q->versionFunctions<QOpenGLFunctions_1_0>();
0
383-
384 Q_ASSERT(gl1funcs || gl3funcs);-
385-
386 if (gl1funcs)
gl1funcsDescription
TRUEnever evaluated
FALSEnever evaluated
0
387 gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
never executed: gl1funcs->glGetTexLevelParameteriv(proxy, 0, 0x1000, &size);
0
388 else-
389 gl3funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
never executed: gl3funcs->glGetTexLevelParameteriv(proxy, 0, 0x1000, &size);
0
390-
391 if (size == 0) {
size == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
392 return max_texture_size;
never executed: return max_texture_size;
0
393 }-
394 do {-
395 size = next;-
396 next = size * 2;-
397-
398 if (next > max_texture_size)
next > max_texture_sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
399 break;
never executed: break;
0
400 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);-
401 if (gl1funcs)
gl1funcsDescription
TRUEnever evaluated
FALSEnever evaluated
0
402 gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
never executed: gl1funcs->glGetTexLevelParameteriv(proxy, 0, 0x1000, &next);
0
403 else-
404 gl3funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
never executed: gl3funcs->glGetTexLevelParameteriv(proxy, 0, 0x1000, &next);
0
405-
406 } while (next > size);
next > sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
407-
408 max_texture_size = size;-
409 }
never executed: end of block
0
410#endif // QT_OPENGL_ES-
411-
412 return max_texture_size;
never executed: return max_texture_size;
0
413}-
414-
415/*!-
416 Returns the last context which called makeCurrent in the current thread,-
417 or 0, if no context is current.-
418*/-
419QOpenGLContext* QOpenGLContext::currentContext()-
420{-
421 QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData();-
422 if (threadContext) {
threadContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
423 return threadContext->context;
never executed: return threadContext->context;
0
424 }-
425 return 0;
never executed: return 0;
0
426}-
427-
428/*!-
429 Returns \c true if the \a first and \a second contexts are sharing OpenGL resources.-
430*/-
431bool QOpenGLContext::areSharing(QOpenGLContext *first, QOpenGLContext *second)-
432{-
433 return first->shareGroup() == second->shareGroup();
never executed: return first->shareGroup() == second->shareGroup();
0
434}-
435-
436/*!-
437 Returns the underlying platform context.-
438-
439 \internal-
440*/-
441QPlatformOpenGLContext *QOpenGLContext::handle() const-
442{-
443 Q_D(const QOpenGLContext);-
444 return d->platformGLContext;
never executed: return d->platformGLContext;
0
445}-
446-
447/*!-
448 Returns the underlying platform context with which this context is sharing.-
449-
450 \internal-
451*/-
452-
453QPlatformOpenGLContext *QOpenGLContext::shareHandle() const-
454{-
455 Q_D(const QOpenGLContext);-
456 if (d->shareContext)
d->shareContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
457 return d->shareContext->handle();
never executed: return d->shareContext->handle();
0
458 return 0;
never executed: return 0;
0
459}-
460-
461/*!-
462 Creates a new OpenGL context instance with parent object \a parent.-
463-
464 Before it can be used you need to set the proper format and call create().-
465-
466 \sa create(), makeCurrent()-
467*/-
468QOpenGLContext::QOpenGLContext(QObject *parent)-
469 : QObject(*new QOpenGLContextPrivate(), parent)-
470{-
471 setScreen(QGuiApplication::primaryScreen());-
472}
never executed: end of block
0
473-
474/*!-
475 Sets the \a format the OpenGL context should be compatible with. You need-
476 to call create() before it takes effect.-
477-
478 When the format is not explicitly set via this function, the format returned-
479 by QSurfaceFormat::defaultFormat() will be used. This means that when having-
480 multiple contexts, individual calls to this function can be replaced by one-
481 single call to QSurfaceFormat::setDefaultFormat() before creating the first-
482 context.-
483*/-
484void QOpenGLContext::setFormat(const QSurfaceFormat &format)-
485{-
486 Q_D(QOpenGLContext);-
487 d->requestedFormat = format;-
488}
never executed: end of block
0
489-
490/*!-
491 Makes this context share textures, shaders, and other OpenGL resources-
492 with \a shareContext. You need to call create() before it takes effect.-
493*/-
494void QOpenGLContext::setShareContext(QOpenGLContext *shareContext)-
495{-
496 Q_D(QOpenGLContext);-
497 d->shareContext = shareContext;-
498}
never executed: end of block
0
499-
500/*!-
501 Sets the \a screen the OpenGL context should be valid for. You need to call-
502 create() before it takes effect.-
503*/-
504void QOpenGLContext::setScreen(QScreen *screen)-
505{-
506 Q_D(QOpenGLContext);-
507 if (d->screen)
d->screenDescription
TRUEnever evaluated
FALSEnever evaluated
0
508 disconnect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(_q_screenDestroyed(QObject*)));
never executed: disconnect(d->screen, qFlagLocation("2""destroyed(QObject*)" "\0" __FILE__ ":" "508"), this, qFlagLocation("1""_q_screenDestroyed(QObject*)" "\0" __FILE__ ":" "508"));
0
509 d->screen = screen;-
510 if (!d->screen)
!d->screenDescription
TRUEnever evaluated
FALSEnever evaluated
0
511 d->screen = QGuiApplication::primaryScreen();
never executed: d->screen = QGuiApplication::primaryScreen();
0
512 if (d->screen)
d->screenDescription
TRUEnever evaluated
FALSEnever evaluated
0
513 connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(_q_screenDestroyed(QObject*)));
never executed: connect(d->screen, qFlagLocation("2""destroyed(QObject*)" "\0" __FILE__ ":" "513"), this, qFlagLocation("1""_q_screenDestroyed(QObject*)" "\0" __FILE__ ":" "513"));
0
514}
never executed: end of block
0
515-
516void QOpenGLContextPrivate::_q_screenDestroyed(QObject *object)-
517{-
518 Q_Q(QOpenGLContext);-
519 if (object == static_cast<QObject *>(screen)) {
object == stat...ect *>(screen)Description
TRUEnever evaluated
FALSEnever evaluated
0
520 screen = 0;-
521 q->setScreen(0);-
522 }
never executed: end of block
0
523}
never executed: end of block
0
524-
525/*!-
526 Set the native handles for this context. When create() is called and a-
527 native handle is set, configuration settings, like format(), are ignored-
528 since this QOpenGLContext will wrap an already created native context-
529 instead of creating a new one from scratch.-
530-
531 On some platforms the native context handle is not sufficient and other-
532 related handles (for example, for a window or display) have to be provided-
533 in addition. Therefore \a handle is variant containing a platform-specific-
534 value type. These classes can be found in the QtPlatformHeaders module.-
535-
536 When create() is called with native handles set, QOpenGLContext does not-
537 take ownership of the handles, so destroying the QOpenGLContext does not-
538 destroy the native context.-
539-
540 \note Some frameworks track the current context and surfaces internally.-
541 Making the adopted QOpenGLContext current via Qt will have no effect on such-
542 other frameworks' internal state. Therefore a subsequent makeCurrent done-
543 via the other framework may have no effect. It is therefore advisable to-
544 make explicit calls to make no context and surface current to reset the-
545 other frameworks' internal state after performing OpenGL operations via Qt.-
546-
547 \note Using foreign contexts with Qt windows and Qt contexts with windows-
548 and surfaces created by other frameworks may give unexpected results,-
549 depending on the platform, due to potential mismatches in context and window-
550 pixel formats. To make sure this does not happen, avoid making contexts and-
551 surfaces from different frameworks current together. Instead, prefer-
552 approaches based on context sharing where OpenGL resources like textures are-
553 accessible both from Qt's and the foreign framework's contexts.-
554-
555 \since 5.4-
556 \sa nativeHandle()-
557*/-
558void QOpenGLContext::setNativeHandle(const QVariant &handle)-
559{-
560 Q_D(QOpenGLContext);-
561 d->nativeHandle = handle;-
562}
never executed: end of block
0
563-
564/*!-
565 Returns the native handle for the context.-
566-
567 This function provides access to the QOpenGLContext's underlying native-
568 context. The returned variant contains a platform-specific value type. These-
569 classes can be found in the module QtPlatformHeaders.-
570-
571 On platforms where retrieving the native handle is not supported, or if-
572 neither create() nor setNativeHandle() was called, a null variant is-
573 returned.-
574-
575 \since 5.4-
576 \sa setNativeHandle()-
577 */-
578QVariant QOpenGLContext::nativeHandle() const-
579{-
580 Q_D(const QOpenGLContext);-
581 return d->nativeHandle;
never executed: return d->nativeHandle;
0
582}-
583-
584/*!-
585 Attempts to create the OpenGL context with the current configuration.-
586-
587 The current configuration includes the format, the share context, and the-
588 screen.-
589-
590 If the OpenGL implementation on your system does not support the requested-
591 version of OpenGL context, then QOpenGLContext will try to create the closest-
592 matching version. The actual created context properties can be queried-
593 using the QSurfaceFormat returned by the format() function. For example, if-
594 you request a context that supports OpenGL 4.3 Core profile but the driver-
595 and/or hardware only supports version 3.2 Core profile contexts then you will-
596 get a 3.2 Core profile context.-
597-
598 Returns \c true if the native context was successfully created and is ready to-
599 be used with makeCurrent(), swapBuffers(), etc.-
600-
601 \note If the context already exists, this function destroys the existing-
602 context first, and then creates a new one.-
603-
604 \sa makeCurrent(), format()-
605*/-
606bool QOpenGLContext::create()-
607{-
608 Q_D(QOpenGLContext);-
609 if (d->platformGLContext)
d->platformGLContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
610 destroy();
never executed: destroy();
0
611-
612 d->platformGLContext = QGuiApplicationPrivate::platformIntegration()->createPlatformOpenGLContext(this);-
613 if (!d->platformGLContext)
!d->platformGLContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
614 return false;
never executed: return false;
0
615 d->platformGLContext->initialize();-
616 d->platformGLContext->setContext(this);-
617 if (!d->platformGLContext->isSharing())
!d->platformGL...t->isSharing()Description
TRUEnever evaluated
FALSEnever evaluated
0
618 d->shareContext = 0;
never executed: d->shareContext = 0;
0
619 d->shareGroup = d->shareContext ? d->shareContext->shareGroup() : new QOpenGLContextGroup;
d->shareContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
620 d->shareGroup->d_func()->addContext(this);-
621 return isValid();
never executed: return isValid();
0
622}-
623-
624/*!-
625 \internal-
626-
627 Destroy the underlying platform context associated with this context.-
628-
629 If any other context is directly or indirectly sharing resources with this-
630 context, the shared resources, which includes vertex buffer objects, shader-
631 objects, textures, and framebuffer objects, are not freed. However,-
632 destroying the underlying platform context frees any state associated with-
633 the context.-
634-
635 After \c destroy() has been called, you must call create() if you wish to-
636 use the context again.-
637-
638 \note This implicitly calls doneCurrent() if the context is current.-
639-
640 \sa create()-
641*/-
642void QOpenGLContext::destroy()-
643{-
644 deleteQGLContext();-
645 Q_D(QOpenGLContext);-
646 if (d->platformGLContext)
d->platformGLContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
647 emit aboutToBeDestroyed();
never executed: aboutToBeDestroyed();
0
648 if (QOpenGLContext::currentContext() == this)
QOpenGLContext...text() == thisDescription
TRUEnever evaluated
FALSEnever evaluated
0
649 doneCurrent();
never executed: doneCurrent();
0
650 if (d->shareGroup)
d->shareGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
651 d->shareGroup->d_func()->removeContext(this);
never executed: d->shareGroup->d_func()->removeContext(this);
0
652 d->shareGroup = 0;-
653 delete d->platformGLContext;-
654 d->platformGLContext = 0;-
655 delete d->functions;-
656 d->functions = 0;-
657-
658 for (QAbstractOpenGLFunctions *func : qAsConst(d->externalVersionFunctions)) {-
659 QAbstractOpenGLFunctionsPrivate *func_d = QAbstractOpenGLFunctionsPrivate::get(func);-
660 func_d->owningContext = 0;-
661 func_d->initialized = false;-
662 }
never executed: end of block
0
663 d->externalVersionFunctions.clear();-
664 qDeleteAll(d->versionFunctions);-
665 d->versionFunctions.clear();-
666-
667 delete d->textureFunctions;-
668 d->textureFunctions = 0;-
669-
670 d->nativeHandle = QVariant();-
671}
never executed: end of block
0
672-
673/*!-
674 \fn void QOpenGLContext::aboutToBeDestroyed()-
675-
676 This signal is emitted before the underlying native OpenGL context is-
677 destroyed, such that users may clean up OpenGL resources that might-
678 otherwise be left dangling in the case of shared OpenGL contexts.-
679-
680 If you wish to make the context current in order to do clean-up, make sure-
681 to only connect to the signal using a direct connection.-
682*/-
683-
684/*!-
685 Destroys the QOpenGLContext object.-
686-
687 If this is the current context for the thread, doneCurrent() is also called.-
688*/-
689QOpenGLContext::~QOpenGLContext()-
690{-
691 destroy();-
692-
693#ifndef QT_NO_DEBUG-
694 QOpenGLContextPrivate::cleanMakeCurrentTracker(this);-
695#endif-
696}
never executed: end of block
0
697-
698/*!-
699 Returns if this context is valid, i.e. has been successfully created.-
700-
701 On some platforms the return value of \c false for a context that was-
702 successfully created previously indicates that the OpenGL context was lost.-
703-
704 The typical way to handle context loss scenarios in applications is to-
705 check via this function whenever makeCurrent() fails and returns \c false.-
706 If this function then returns \c false, recreate the underlying native-
707 OpenGL context by calling create(), call makeCurrent() again and then-
708 reinitialize all OpenGL resources.-
709-
710 \sa create()-
711*/-
712bool QOpenGLContext::isValid() const-
713{-
714 Q_D(const QOpenGLContext);-
715 return d->platformGLContext && d->platformGLContext->isValid();
never executed: return d->platformGLContext && d->platformGLContext->isValid();
0
716}-
717-
718/*!-
719 Get the QOpenGLFunctions instance for this context.-
720-
721 QOpenGLContext offers this as a convenient way to access QOpenGLFunctions-
722 without having to manage it manually.-
723-
724 The context or a sharing context must be current.-
725-
726 The returned QOpenGLFunctions instance is ready to be used and it-
727 does not need initializeOpenGLFunctions() to be called.-
728*/-
729QOpenGLFunctions *QOpenGLContext::functions() const-
730{-
731 Q_D(const QOpenGLContext);-
732 if (!d->functions)
!d->functionsDescription
TRUEnever evaluated
FALSEnever evaluated
0
733 const_cast<QOpenGLFunctions *&>(d->functions) = new QOpenGLExtensions(QOpenGLContext::currentContext());
never executed: const_cast<QOpenGLFunctions *&>(d->functions) = new QOpenGLExtensions(QOpenGLContext::currentContext());
0
734 return d->functions;
never executed: return d->functions;
0
735}-
736-
737/*!-
738 Get the QOpenGLExtraFunctions instance for this context.-
739-
740 QOpenGLContext offers this as a convenient way to access QOpenGLExtraFunctions-
741 without having to manage it manually.-
742-
743 The context or a sharing context must be current.-
744-
745 The returned QOpenGLExtraFunctions instance is ready to be used and it-
746 does not need initializeOpenGLFunctions() to be called.-
747-
748 \note QOpenGLExtraFunctions contains functionality that is not guaranteed to-
749 be available at runtime. Runtime availability depends on the platform,-
750 graphics driver, and the OpenGL version requested by the application.-
751-
752 \sa QOpenGLFunctions, QOpenGLExtraFunctions-
753*/-
754QOpenGLExtraFunctions *QOpenGLContext::extraFunctions() const-
755{-
756 return static_cast<QOpenGLExtraFunctions *>(functions());
never executed: return static_cast<QOpenGLExtraFunctions *>(functions());
0
757}-
758-
759/*!-
760 \fn T *QOpenGLContext::versionFunctions() const-
761-
762 \overload versionFunctions()-
763-
764 Returns a pointer to an object that provides access to all functions for-
765 the version and profile of this context. There is no need to call-
766 QAbstractOpenGLFunctions::initializeOpenGLFunctions() as long as this context-
767 is current. It is also possible to call this function when the context is not-
768 current, but in that case it is the caller's responsibility to ensure proper-
769 initialization by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions()-
770 afterwards.-
771-
772 Usually one would use the template version of this function to automatically-
773 have the result cast to the correct type.-
774-
775 \code-
776 QOpenGLFunctions_3_3_Core* funcs = 0;-
777 funcs = context->versionFunctions<QOpenGLFunctions_3_3_Core>();-
778 if (!funcs) {-
779 qWarning() << "Could not obtain required OpenGL context version";-
780 exit(1);-
781 }-
782 \endcode-
783-
784 It is possible to request a functions object for a different version and profile-
785 than that for which the context was created. To do this either use the template-
786 version of this function specifying the desired functions object type as the-
787 template parameter or by passing in a QOpenGLVersionProfile object as an argument-
788 to the non-template function.-
789-
790 Note that requests for function objects of other versions or profiles can fail and-
791 in doing so will return a null pointer. Situations in which creation of the functions-
792 object can fail are if the request cannot be satisfied due to asking for functions-
793 that are not in the version or profile of this context. For example:-
794-
795 \list-
796 \li Requesting a 3.3 core profile functions object would succeed.-
797 \li Requesting a 3.3 compatibility profile functions object would fail. We would fail-
798 to resolve the deprecated functions.-
799 \li Requesting a 4.3 core profile functions object would fail. We would fail to resolve-
800 the new core functions introduced in versions 4.0-4.3.-
801 \li Requesting a 3.1 functions object would succeed. There is nothing in 3.1 that is not-
802 also in 3.3 core.-
803 \endlist-
804-
805 Note that if creating a functions object via this method that the QOpenGLContext-
806 retains ownership of the object. This is to allow the object to be cached and shared.-
807*/-
808-
809/*!-
810 Returns a pointer to an object that provides access to all functions for the-
811 \a versionProfile of this context. There is no need to call-
812 QAbstractOpenGLFunctions::initializeOpenGLFunctions() as long as this context-
813 is current. It is also possible to call this function when the context is not-
814 current, but in that case it is the caller's responsibility to ensure proper-
815 initialization by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions()-
816 afterwards.-
817-
818 Usually one would use the template version of this function to automatically-
819 have the result cast to the correct type.-
820*/-
821QAbstractOpenGLFunctions *QOpenGLContext::versionFunctions(const QOpenGLVersionProfile &versionProfile) const-
822{-
823#ifndef QT_OPENGL_ES_2-
824 if (isOpenGLES()) {
isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
825 qWarning("versionFunctions: Not supported on OpenGL ES");-
826 return 0;
never executed: return 0;
0
827 }-
828#endif // QT_OPENGL_ES_2-
829-
830 Q_D(const QOpenGLContext);-
831 const QSurfaceFormat f = format();-
832-
833 // Ensure we have a valid version and profile. Default to context's if none specified-
834 QOpenGLVersionProfile vp = versionProfile;-
835 if (!vp.isValid())
!vp.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
836 vp = QOpenGLVersionProfile(f);
never executed: vp = QOpenGLVersionProfile(f);
0
837-
838 // Check that context is compatible with requested version-
839 const QPair<int, int> v = qMakePair(f.majorVersion(), f.minorVersion());-
840 if (v < vp.version())
v < vp.version()Description
TRUEnever evaluated
FALSEnever evaluated
0
841 return 0;
never executed: return 0;
0
842-
843 // If this context only offers core profile functions then we can't create-
844 // function objects for legacy or compatibility profile requests-
845 if (((vp.hasProfiles() && vp.profile() != QSurfaceFormat::CoreProfile) || vp.isLegacyVersion())
vp.hasProfiles()Description
TRUEnever evaluated
FALSEnever evaluated
vp.profile() !...t::CoreProfileDescription
TRUEnever evaluated
FALSEnever evaluated
vp.isLegacyVersion()Description
TRUEnever evaluated
FALSEnever evaluated
0
846 && f.profile() == QSurfaceFormat::CoreProfile)
f.profile() ==...t::CoreProfileDescription
TRUEnever evaluated
FALSEnever evaluated
0
847 return 0;
never executed: return 0;
0
848-
849 // Create object if suitable one not cached-
850 QAbstractOpenGLFunctions* funcs = 0;-
851 if (!d->versionFunctions.contains(vp)) {
!d->versionFun...s.contains(vp)Description
TRUEnever evaluated
FALSEnever evaluated
0
852 funcs = QOpenGLVersionFunctionsFactory::create(vp);-
853 if (funcs) {
funcsDescription
TRUEnever evaluated
FALSEnever evaluated
0
854 funcs->setOwningContext(this);-
855 d->versionFunctions.insert(vp, funcs);-
856 }
never executed: end of block
0
857 } else {
never executed: end of block
0
858 funcs = d->versionFunctions.value(vp);-
859 }
never executed: end of block
0
860-
861 if (funcs && QOpenGLContext::currentContext() == this)
funcsDescription
TRUEnever evaluated
FALSEnever evaluated
QOpenGLContext...text() == thisDescription
TRUEnever evaluated
FALSEnever evaluated
0
862 funcs->initializeOpenGLFunctions();
never executed: funcs->initializeOpenGLFunctions();
0
863-
864 return funcs;
never executed: return funcs;
0
865}-
866-
867/*!-
868 Returns the set of OpenGL extensions supported by this context.-
869-
870 The context or a sharing context must be current.-
871-
872 \sa hasExtension()-
873*/-
874QSet<QByteArray> QOpenGLContext::extensions() const-
875{-
876 Q_D(const QOpenGLContext);-
877 if (d->extensionNames.isEmpty()) {
d->extensionNames.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
878 QOpenGLExtensionMatcher matcher;-
879 d->extensionNames = matcher.extensions();-
880 }
never executed: end of block
0
881-
882 return d->extensionNames;
never executed: return d->extensionNames;
0
883}-
884-
885/*!-
886 Returns \c true if this OpenGL context supports the specified OpenGL-
887 \a extension, \c false otherwise.-
888-
889 The context or a sharing context must be current.-
890-
891 \sa extensions()-
892*/-
893bool QOpenGLContext::hasExtension(const QByteArray &extension) const-
894{-
895 return extensions().contains(extension);
never executed: return extensions().contains(extension);
0
896}-
897-
898/*!-
899 Call this to get the default framebuffer object for the current surface.-
900-
901 On some platforms (for instance, iOS) the default framebuffer object depends-
902 on the surface being rendered to, and might be different from 0. Thus,-
903 instead of calling glBindFramebuffer(0), you should call-
904 glBindFramebuffer(ctx->defaultFramebufferObject()) if you want your-
905 application to work across different Qt platforms.-
906-
907 If you use the glBindFramebuffer() in QOpenGLFunctions you do not have to-
908 worry about this, as it automatically binds the current context's-
909 defaultFramebufferObject() when 0 is passed.-
910-
911 \note Widgets that render via framebuffer objects, like QOpenGLWidget and-
912 QQuickWidget, will override the value returned from this function when-
913 painting is active, because at that time the correct "default" framebuffer-
914 is the widget's associated backing framebuffer, not the platform-specific-
915 one belonging to the top-level window's surface. This ensures the expected-
916 behavior for this function and other classes relying on it (for example,-
917 QOpenGLFramebufferObject::bindDefault() or-
918 QOpenGLFramebufferObject::release()).-
919-
920 \sa QOpenGLFramebufferObject-
921*/-
922GLuint QOpenGLContext::defaultFramebufferObject() const-
923{-
924 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
925 return 0;
never executed: return 0;
0
926-
927 Q_D(const QOpenGLContext);-
928 if (!d->surface || !d->surface->surfaceHandle())
!d->surfaceDescription
TRUEnever evaluated
FALSEnever evaluated
!d->surface->surfaceHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
929 return 0;
never executed: return 0;
0
930-
931 if (d->defaultFboRedirect)
d->defaultFboRedirectDescription
TRUEnever evaluated
FALSEnever evaluated
0
932 return d->defaultFboRedirect;
never executed: return d->defaultFboRedirect;
0
933-
934 return d->platformGLContext->defaultFramebufferObject(d->surface->surfaceHandle());
never executed: return d->platformGLContext->defaultFramebufferObject(d->surface->surfaceHandle());
0
935}-
936-
937/*!-
938 Makes the context current in the current thread, against the given-
939 \a surface. Returns \c true if successful.-
940-
941 If \a surface is 0 this is equivalent to calling doneCurrent().-
942-
943 Do not call this function from a different thread than the one the-
944 QOpenGLContext instance lives in. If you wish to use QOpenGLContext from a-
945 different thread you should first call make sure it's not current in the-
946 current thread, by calling doneCurrent() if necessary. Then call-
947 moveToThread(otherThread) before using it in the other thread.-
948-
949 \sa functions(), doneCurrent()-
950*/-
951bool QOpenGLContext::makeCurrent(QSurface *surface)-
952{-
953 Q_D(QOpenGLContext);-
954 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
955 return false;
never executed: return false;
0
956-
957 if (Q_UNLIKELY(thread() != QThread::currentThread()))
__builtin_expe...ead()), false)Description
TRUEnever evaluated
FALSEnever evaluated
0
958 qFatal("Cannot make QOpenGLContext current in a different thread");
never executed: QMessageLogger(__FILE__, 958, __PRETTY_FUNCTION__).fatal("Cannot make QOpenGLContext current in a different thread");
0
959-
960 if (!surface) {
!surfaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
961 doneCurrent();-
962 return true;
never executed: return true;
0
963 }-
964-
965 if (!surface->surfaceHandle())
!surface->surfaceHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
966 return false;
never executed: return false;
0
967 if (!surface->supportsOpenGL()) {
!surface->supportsOpenGL()Description
TRUEnever evaluated
FALSEnever evaluated
0
968 qWarning() << "QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;-
969 return false;
never executed: return false;
0
970 }-
971-
972 QOpenGLContext *previous = QOpenGLContextPrivate::setCurrentContext(this);-
973-
974 if (d->platformGLContext->makeCurrent(surface->surfaceHandle())) {
d->platformGLC...rfaceHandle())Description
TRUEnever evaluated
FALSEnever evaluated
0
975 d->surface = surface;-
976-
977 d->shareGroup->d_func()->deletePendingResources(this);-
978-
979#ifndef QT_NO_DEBUG-
980 QOpenGLContextPrivate::toggleMakeCurrentTracker(this, true);-
981#endif-
982-
983 return true;
never executed: return true;
0
984 }-
985-
986 QOpenGLContextPrivate::setCurrentContext(previous);-
987-
988 return false;
never executed: return false;
0
989}-
990-
991/*!-
992 Convenience function for calling makeCurrent with a 0 surface.-
993-
994 This results in no context being current in the current thread.-
995-
996 \sa makeCurrent(), currentContext()-
997*/-
998void QOpenGLContext::doneCurrent()-
999{-
1000 Q_D(QOpenGLContext);-
1001 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1002 return;
never executed: return;
0
1003-
1004 if (QOpenGLContext::currentContext() == this)
QOpenGLContext...text() == thisDescription
TRUEnever evaluated
FALSEnever evaluated
0
1005 d->shareGroup->d_func()->deletePendingResources(this);
never executed: d->shareGroup->d_func()->deletePendingResources(this);
0
1006-
1007 d->platformGLContext->doneCurrent();-
1008 QOpenGLContextPrivate::setCurrentContext(0);-
1009-
1010 d->surface = 0;-
1011}
never executed: end of block
0
1012-
1013/*!-
1014 Returns the surface the context has been made current with.-
1015-
1016 This is the surface passed as an argument to makeCurrent().-
1017*/-
1018QSurface *QOpenGLContext::surface() const-
1019{-
1020 Q_D(const QOpenGLContext);-
1021 return d->surface;
never executed: return d->surface;
0
1022}-
1023-
1024-
1025/*!-
1026 Swap the back and front buffers of \a surface.-
1027-
1028 Call this to finish a frame of OpenGL rendering, and make sure to-
1029 call makeCurrent() again before you begin a new frame.-
1030*/-
1031void QOpenGLContext::swapBuffers(QSurface *surface)-
1032{-
1033 Q_D(QOpenGLContext);-
1034 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1035 return;
never executed: return;
0
1036-
1037 if (!surface) {
!surfaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1038 qWarning("QOpenGLContext::swapBuffers() called with null argument");-
1039 return;
never executed: return;
0
1040 }-
1041-
1042 if (!surface->supportsOpenGL()) {
!surface->supportsOpenGL()Description
TRUEnever evaluated
FALSEnever evaluated
0
1043 qWarning("QOpenGLContext::swapBuffers() called with non-opengl surface");-
1044 return;
never executed: return;
0
1045 }-
1046-
1047 if (surface->surfaceClass() == QSurface::Window
surface->surfa...urface::WindowDescription
TRUEnever evaluated
FALSEnever evaluated
0
1048 && !qt_window_private(static_cast<QWindow *>(surface))->receivedExpose)
!qt_window_pri...receivedExposeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1049 {-
1050 qWarning("QOpenGLContext::swapBuffers() called with non-exposed window, behavior is undefined");-
1051 }
never executed: end of block
0
1052-
1053 QPlatformSurface *surfaceHandle = surface->surfaceHandle();-
1054 if (!surfaceHandle)
!surfaceHandleDescription
TRUEnever evaluated
FALSEnever evaluated
0
1055 return;
never executed: return;
0
1056-
1057#if !defined(QT_NO_DEBUG)-
1058 if (!QOpenGLContextPrivate::toggleMakeCurrentTracker(this, false))
!QOpenGLContex...r(this, false)Description
TRUEnever evaluated
FALSEnever evaluated
0
1059 qWarning("QOpenGLContext::swapBuffers() called without corresponding makeCurrent()");
never executed: QMessageLogger(__FILE__, 1059, __PRETTY_FUNCTION__).warning("QOpenGLContext::swapBuffers() called without corresponding makeCurrent()");
0
1060#endif-
1061 if (surface->format().swapBehavior() == QSurfaceFormat::SingleBuffer)
surface->forma...::SingleBufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
1062 functions()->glFlush();
never executed: functions()->glFlush();
0
1063 d->platformGLContext->swapBuffers(surfaceHandle);-
1064}
never executed: end of block
0
1065-
1066/*!-
1067 Resolves the function pointer to an OpenGL extension function, identified by \a procName-
1068-
1069 Returns 0 if no such function can be found.-
1070*/-
1071QFunctionPointer QOpenGLContext::getProcAddress(const QByteArray &procName) const-
1072{-
1073 return getProcAddress(procName.constData());
never executed: return getProcAddress(procName.constData());
0
1074}-
1075-
1076/*!-
1077 \overload-
1078 \since 5.8-
1079 */-
1080QFunctionPointer QOpenGLContext::getProcAddress(const char *procName) const-
1081{-
1082 Q_D(const QOpenGLContext);-
1083 if (!d->platformGLContext)
!d->platformGLContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
1084 return nullptr;
never executed: return nullptr;
0
1085 return d->platformGLContext->getProcAddress(procName);
never executed: return d->platformGLContext->getProcAddress(procName);
0
1086}-
1087-
1088/*!-
1089 Returns the format of the underlying platform context, if create() has been called.-
1090-
1091 Otherwise, returns the requested format.-
1092-
1093 The requested and the actual format may differ. Requesting a given OpenGL version does-
1094 not mean the resulting context will target exactly the requested version. It is only-
1095 guaranteed that the version/profile/options combination for the created context is-
1096 compatible with the request, as long as the driver is able to provide such a context.-
1097-
1098 For example, requesting an OpenGL version 3.x core profile context may result in an-
1099 OpenGL 4.x core profile context. Similarly, a request for OpenGL 2.1 may result in an-
1100 OpenGL 3.0 context with deprecated functions enabled. Finally, depending on the-
1101 driver, unsupported versions may result in either a context creation failure or in a-
1102 context for the highest supported version.-
1103-
1104 Similar differences are possible in the buffer sizes, for example, the resulting-
1105 context may have a larger depth buffer than requested. This is perfectly normal.-
1106*/-
1107QSurfaceFormat QOpenGLContext::format() const-
1108{-
1109 Q_D(const QOpenGLContext);-
1110 if (!d->platformGLContext)
!d->platformGLContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
1111 return d->requestedFormat;
never executed: return d->requestedFormat;
0
1112 return d->platformGLContext->format();
never executed: return d->platformGLContext->format();
0
1113}-
1114-
1115/*!-
1116 Returns the share group this context belongs to.-
1117*/-
1118QOpenGLContextGroup *QOpenGLContext::shareGroup() const-
1119{-
1120 Q_D(const QOpenGLContext);-
1121 return d->shareGroup;
never executed: return d->shareGroup;
0
1122}-
1123-
1124/*!-
1125 Returns the share context this context was created with.-
1126-
1127 If the underlying platform was not able to support the requested-
1128 sharing, this will return 0.-
1129*/-
1130QOpenGLContext *QOpenGLContext::shareContext() const-
1131{-
1132 Q_D(const QOpenGLContext);-
1133 return d->shareContext;
never executed: return d->shareContext;
0
1134}-
1135-
1136/*!-
1137 Returns the screen the context was created for.-
1138*/-
1139QScreen *QOpenGLContext::screen() const-
1140{-
1141 Q_D(const QOpenGLContext);-
1142 return d->screen;
never executed: return d->screen;
0
1143}-
1144-
1145/*!-
1146 internal: Needs to have a pointer to qGLContext. But since this is in Qt GUI we can't-
1147 have any type information.-
1148-
1149 \internal-
1150*/-
1151void *QOpenGLContext::qGLContextHandle() const-
1152{-
1153 Q_D(const QOpenGLContext);-
1154 return d->qGLContextHandle;
never executed: return d->qGLContextHandle;
0
1155}-
1156-
1157/*!-
1158 internal: If the delete function is specified QOpenGLContext "owns"-
1159 the passed context handle and will use the delete function to destroy it.-
1160-
1161 \internal-
1162*/-
1163void QOpenGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *))-
1164{-
1165 Q_D(QOpenGLContext);-
1166 d->qGLContextHandle = handle;-
1167 d->qGLContextDeleteFunction = qGLContextDeleteFunction;-
1168}
never executed: end of block
0
1169-
1170/*!-
1171 \internal-
1172*/-
1173void QOpenGLContext::deleteQGLContext()-
1174{-
1175 Q_D(QOpenGLContext);-
1176 if (d->qGLContextDeleteFunction && d->qGLContextHandle) {
d->qGLContextDeleteFunctionDescription
TRUEnever evaluated
FALSEnever evaluated
d->qGLContextHandleDescription
TRUEnever evaluated
FALSEnever evaluated
0
1177 d->qGLContextDeleteFunction(d->qGLContextHandle);-
1178 d->qGLContextDeleteFunction = 0;-
1179 d->qGLContextHandle = 0;-
1180 }
never executed: end of block
0
1181}
never executed: end of block
0
1182-
1183/*!-
1184 Returns the platform-specific handle for the OpenGL implementation that-
1185 is currently in use. (for example, a HMODULE on Windows)-
1186-
1187 On platforms that do not use dynamic GL switch the return value is null.-
1188-
1189 The library might be GL-only, meaning that windowing system interface-
1190 functions (for example EGL) may live in another, separate library.-
1191-
1192 \note This function requires that the QGuiApplication instance is already created.-
1193-
1194 \sa openGLModuleType()-
1195-
1196 \since 5.3-
1197 */-
1198void *QOpenGLContext::openGLModuleHandle()-
1199{-
1200#ifdef QT_OPENGL_DYNAMIC-
1201 QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();-
1202 Q_ASSERT(ni);-
1203 return ni->nativeResourceForIntegration(QByteArrayLiteral("glhandle"));-
1204#else-
1205 return 0;
never executed: return 0;
0
1206#endif-
1207}-
1208-
1209/*!-
1210 \enum QOpenGLContext::OpenGLModuleType-
1211 This enum defines the type of the underlying OpenGL implementation.-
1212-
1213 \value LibGL OpenGL-
1214 \value LibGLES OpenGL ES 2.0 or higher-
1215-
1216 \since 5.3-
1217*/-
1218-
1219/*!-
1220 Returns the underlying OpenGL implementation type.-
1221-
1222 On platforms where the OpenGL implementation is not dynamically-
1223 loaded, the return value is determined during compile time and never-
1224 changes.-
1225-
1226 \note A desktop OpenGL implementation may be capable of creating-
1227 ES-compatible contexts too. Therefore in most cases it is more-
1228 appropriate to check QSurfaceFormat::renderableType() or use-
1229 the convenience function isOpenGLES().-
1230-
1231 \note This function requires that the QGuiApplication instance is already created.-
1232-
1233 \since 5.3-
1234 */-
1235QOpenGLContext::OpenGLModuleType QOpenGLContext::openGLModuleType()-
1236{-
1237#if defined(QT_OPENGL_DYNAMIC)-
1238 Q_ASSERT(qGuiApp);-
1239 return QGuiApplicationPrivate::instance()->platformIntegration()->openGLModuleType();-
1240#elif defined(QT_OPENGL_ES_2)-
1241 return LibGLES;-
1242#else-
1243 return LibGL;
never executed: return LibGL;
0
1244#endif-
1245}-
1246-
1247/*!-
1248 Returns true if the context is an OpenGL ES context.-
1249-
1250 If the context has not yet been created, the result is based on the-
1251 requested format set via setFormat().-
1252-
1253 \sa create(), format(), setFormat()-
1254-
1255 \since 5.3-
1256 */-
1257bool QOpenGLContext::isOpenGLES() const-
1258{-
1259 return format().renderableType() == QSurfaceFormat::OpenGLES;
never executed: return format().renderableType() == QSurfaceFormat::OpenGLES;
0
1260}-
1261-
1262/*!-
1263 Returns \c true if the platform supports OpenGL rendering outside the main (gui)-
1264 thread.-
1265-
1266 The value is controlled by the platform plugin in use and may also depend on the-
1267 graphics drivers.-
1268-
1269 \since 5.5-
1270 */-
1271bool QOpenGLContext::supportsThreadedOpenGL()-
1272{-
1273 Q_ASSERT(qGuiApp);-
1274 return QGuiApplicationPrivate::instance()->platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL);
never executed: return QGuiApplicationPrivate::instance()->platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL);
0
1275}-
1276-
1277/*!-
1278 \since 5.5-
1279-
1280 Returns the application-wide shared OpenGL context, if present.-
1281 Otherwise, returns a null pointer.-
1282-
1283 This is useful if you need to upload OpenGL objects (buffers, textures,-
1284 etc.) before creating or showing a QOpenGLWidget or QQuickWidget.-
1285-
1286 \note You must set the Qt::AA_ShareOpenGLContexts flag on QGuiApplication-
1287 before creating the QGuiApplication object, otherwise Qt may not create a-
1288 global shared context.-
1289-
1290 \warning Do not attempt to make the context returned by this function-
1291 current on any surface. Instead, you can create a new context which shares-
1292 with the global one, and then make the new context current.-
1293-
1294 \sa Qt::AA_ShareOpenGLContexts, setShareContext(), makeCurrent()-
1295*/-
1296QOpenGLContext *QOpenGLContext::globalShareContext()-
1297{-
1298 Q_ASSERT(qGuiApp);-
1299 return qt_gl_global_share_context();
never executed: return qt_gl_global_share_context();
0
1300}-
1301-
1302/*!-
1303 \internal-
1304*/-
1305QOpenGLVersionFunctionsStorage *QOpenGLContext::functionsBackendStorage() const-
1306{-
1307 Q_D(const QOpenGLContext);-
1308 return &d->versionFunctionsStorage;
never executed: return &d->versionFunctionsStorage;
0
1309}-
1310-
1311/*!-
1312 \internal-
1313 */-
1314void QOpenGLContext::insertExternalFunctions(QAbstractOpenGLFunctions *f)-
1315{-
1316 Q_D(QOpenGLContext);-
1317 d->externalVersionFunctions.insert(f);-
1318}
never executed: end of block
0
1319-
1320/*!-
1321 \internal-
1322 */-
1323void QOpenGLContext::removeExternalFunctions(QAbstractOpenGLFunctions *f)-
1324{-
1325 Q_D(QOpenGLContext);-
1326 d->externalVersionFunctions.remove(f);-
1327}
never executed: end of block
0
1328-
1329/*!-
1330 \internal-
1331*/-
1332QOpenGLTextureHelper* QOpenGLContext::textureFunctions() const-
1333{-
1334 Q_D(const QOpenGLContext);-
1335 return d->textureFunctions;
never executed: return d->textureFunctions;
0
1336}-
1337-
1338/*!-
1339 \internal-
1340*/-
1341void QOpenGLContext::setTextureFunctions(QOpenGLTextureHelper* textureFuncs)-
1342{-
1343 Q_D(QOpenGLContext);-
1344 d->textureFunctions = textureFuncs;-
1345}
never executed: end of block
0
1346-
1347/*!-
1348 \class QOpenGLContextGroup-
1349 \since 5.0-
1350 \brief The QOpenGLContextGroup class represents a group of contexts sharing-
1351 OpenGL resources.-
1352 \inmodule QtGui-
1353-
1354 QOpenGLContextGroup is automatically created and managed by QOpenGLContext-
1355 instances. Its purpose is to identify all the contexts that are sharing-
1356 resources.-
1357-
1358 \sa QOpenGLContext::shareGroup()-
1359*/-
1360QOpenGLContextGroup::QOpenGLContextGroup()-
1361 : QObject(*new QOpenGLContextGroupPrivate())-
1362{-
1363}
never executed: end of block
0
1364-
1365/*!-
1366 \internal-
1367*/-
1368QOpenGLContextGroup::~QOpenGLContextGroup()-
1369{-
1370 Q_D(QOpenGLContextGroup);-
1371 d->cleanup();-
1372}
never executed: end of block
0
1373-
1374/*!-
1375 Returns all the QOpenGLContext objects in this share group.-
1376*/-
1377QList<QOpenGLContext *> QOpenGLContextGroup::shares() const-
1378{-
1379 Q_D(const QOpenGLContextGroup);-
1380 return d->m_shares;
never executed: return d->m_shares;
0
1381}-
1382-
1383/*!-
1384 Returns the QOpenGLContextGroup corresponding to the current context.-
1385-
1386 \sa QOpenGLContext::currentContext()-
1387*/-
1388QOpenGLContextGroup *QOpenGLContextGroup::currentContextGroup()-
1389{-
1390 QOpenGLContext *current = QOpenGLContext::currentContext();-
1391 return current ? current->shareGroup() : 0;
never executed: return current ? current->shareGroup() : 0;
0
1392}-
1393-
1394void QOpenGLContextGroupPrivate::addContext(QOpenGLContext *ctx)-
1395{-
1396 QMutexLocker locker(&m_mutex);-
1397 m_refs.ref();-
1398 m_shares << ctx;-
1399}
never executed: end of block
0
1400-
1401void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx)-
1402{-
1403 Q_Q(QOpenGLContextGroup);-
1404-
1405 bool deleteObject = false;-
1406-
1407 {-
1408 QMutexLocker locker(&m_mutex);-
1409 m_shares.removeOne(ctx);-
1410-
1411 if (ctx == m_context && !m_shares.isEmpty())
ctx == m_contextDescription
TRUEnever evaluated
FALSEnever evaluated
!m_shares.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1412 m_context = m_shares.constFirst();
never executed: m_context = m_shares.constFirst();
0
1413-
1414 if (!m_refs.deref()) {
!m_refs.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
1415 cleanup();-
1416 deleteObject = true;-
1417 }
never executed: end of block
0
1418 }-
1419-
1420 if (deleteObject) {
deleteObjectDescription
TRUEnever evaluated
FALSEnever evaluated
0
1421 if (q->thread() == QThread::currentThread())
q->thread() ==...urrentThread()Description
TRUEnever evaluated
FALSEnever evaluated
0
1422 delete q; // Delete directly to prevent leak, refer to QTBUG-29056
never executed: delete q;
0
1423 else-
1424 q->deleteLater();
never executed: q->deleteLater();
0
1425 }-
1426}
never executed: end of block
0
1427-
1428void QOpenGLContextGroupPrivate::cleanup()-
1429{-
1430 Q_Q(QOpenGLContextGroup);-
1431 {-
1432 QHash<QOpenGLMultiGroupSharedResource *, QOpenGLSharedResource *>::const_iterator it, end;-
1433 end = m_resources.constEnd();-
1434 for (it = m_resources.constBegin(); it != end; ++it)
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1435 it.key()->cleanup(q, it.value());
never executed: it.key()->cleanup(q, it.value());
0
1436 m_resources.clear();-
1437 }-
1438-
1439 QList<QOpenGLSharedResource *>::iterator it = m_sharedResources.begin();-
1440 QList<QOpenGLSharedResource *>::iterator end = m_sharedResources.end();-
1441-
1442 while (it != end) {
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1443 (*it)->invalidateResource();-
1444 (*it)->m_group = 0;-
1445 ++it;-
1446 }
never executed: end of block
0
1447-
1448 m_sharedResources.clear();-
1449-
1450 qDeleteAll(m_pendingDeletion.begin(), m_pendingDeletion.end());-
1451 m_pendingDeletion.clear();-
1452}
never executed: end of block
0
1453-
1454void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)-
1455{-
1456 QMutexLocker locker(&m_mutex);-
1457-
1458 const QList<QOpenGLSharedResource *> pending = m_pendingDeletion;-
1459 m_pendingDeletion.clear();-
1460-
1461 QList<QOpenGLSharedResource *>::const_iterator it = pending.begin();-
1462 QList<QOpenGLSharedResource *>::const_iterator end = pending.end();-
1463 while (it != end) {
it != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1464 (*it)->freeResource(ctx);-
1465 delete *it;-
1466 ++it;-
1467 }
never executed: end of block
0
1468}
never executed: end of block
0
1469-
1470/*!-
1471 \class QOpenGLSharedResource-
1472 \internal-
1473 \since 5.0-
1474 \brief The QOpenGLSharedResource class is used to keep track of resources-
1475 that are shared between OpenGL contexts (like textures, framebuffer-
1476 objects, shader programs, etc), and clean them up in a safe way when-
1477 they're no longer needed.-
1478 \inmodule QtGui-
1479-
1480 The QOpenGLSharedResource instance should never be deleted, instead free()-
1481 should be called when it's no longer needed. Thus it will be put on a queue-
1482 and freed at an appropriate time (when a context in the share group becomes-
1483 current).-
1484-
1485 The sub-class needs to implement two pure virtual functions. The first,-
1486 freeResource() must be implemented to actually do the freeing, for example-
1487 call glDeleteTextures() on a texture id. Qt makes sure a valid context in-
1488 the resource's share group is current at the time. The other,-
1489 invalidateResource(), is called by Qt in the circumstance when the last-
1490 context in the share group is destroyed before free() has been called. The-
1491 implementation of invalidateResource() should set any identifiers to 0 or-
1492 set a flag to prevent them from being used later on.-
1493*/-
1494QOpenGLSharedResource::QOpenGLSharedResource(QOpenGLContextGroup *group)-
1495 : m_group(group)-
1496{-
1497 QMutexLocker locker(&m_group->d_func()->m_mutex);-
1498 m_group->d_func()->m_sharedResources << this;-
1499}
never executed: end of block
0
1500-
1501QOpenGLSharedResource::~QOpenGLSharedResource()-
1502{-
1503}-
1504-
1505// schedule the resource for deletion at an appropriate time-
1506void QOpenGLSharedResource::free()-
1507{-
1508 if (!m_group) {
!m_groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
1509 delete this;-
1510 return;
never executed: return;
0
1511 }-
1512-
1513 QMutexLocker locker(&m_group->d_func()->m_mutex);-
1514 m_group->d_func()->m_sharedResources.removeOne(this);-
1515 m_group->d_func()->m_pendingDeletion << this;-
1516-
1517 // can we delete right away?-
1518 QOpenGLContext *current = QOpenGLContext::currentContext();-
1519 if (current && current->shareGroup() == m_group) {
currentDescription
TRUEnever evaluated
FALSEnever evaluated
current->share...p() == m_groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
1520 m_group->d_func()->deletePendingResources(current);-
1521 }
never executed: end of block
0
1522}
never executed: end of block
0
1523-
1524/*!-
1525 \class QOpenGLSharedResourceGuard-
1526 \internal-
1527 \since 5.0-
1528 \brief The QOpenGLSharedResourceGuard class is a convenience sub-class of-
1529 QOpenGLSharedResource to be used to track a single OpenGL object with a-
1530 GLuint identifier. The constructor takes a function pointer to a function-
1531 that will be used to free the resource if and when necessary.-
1532 \inmodule QtGui-
1533-
1534*/-
1535void QOpenGLSharedResourceGuard::freeResource(QOpenGLContext *context)-
1536{-
1537 if (m_id) {
m_idDescription
TRUEnever evaluated
FALSEnever evaluated
0
1538 QOpenGLFunctions functions(context);-
1539 m_func(&functions, m_id);-
1540 m_id = 0;-
1541 }
never executed: end of block
0
1542}
never executed: end of block
0
1543-
1544/*!-
1545 \class QOpenGLMultiGroupSharedResource-
1546 \internal-
1547 \since 5.0-
1548 \brief The QOpenGLMultiGroupSharedResource keeps track of a shared resource-
1549 that might be needed from multiple contexts, like a glyph cache or gradient-
1550 cache. One instance of the object is created for each group when necessary.-
1551 The shared resource instance should have a constructor that takes a-
1552 QOpenGLContext *. To get an instance for a given context one calls-
1553 T *QOpenGLMultiGroupSharedResource::value<T>(context), where T is a sub-class-
1554 of QOpenGLSharedResource.-
1555 \inmodule QtGui-
1556-
1557 You should not call free() on QOpenGLSharedResources owned by a-
1558 QOpenGLMultiGroupSharedResource instance.-
1559*/-
1560QOpenGLMultiGroupSharedResource::QOpenGLMultiGroupSharedResource()-
1561 : active(0),-
1562 m_mutex(QMutex::Recursive)-
1563{-
1564#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG-
1565 qDebug("Creating context group resource object %p.", this);-
1566#endif-
1567}
never executed: end of block
0
1568-
1569QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource()-
1570{-
1571#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG-
1572 qDebug("Deleting context group resource %p. Group size: %d.", this, m_groups.size());-
1573#endif-
1574 for (int i = 0; i < m_groups.size(); ++i) {
i < m_groups.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1575 if (!m_groups.at(i)->shares().isEmpty()) {
!m_groups.at(i...es().isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1576 QOpenGLContext *context = m_groups.at(i)->shares().constFirst();-
1577 QOpenGLSharedResource *resource = value(context);-
1578 if (resource)
resourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1579 resource->free();
never executed: resource->free();
0
1580 }
never executed: end of block
0
1581 m_groups.at(i)->d_func()->m_resources.remove(this);-
1582 active.deref();-
1583 }
never executed: end of block
0
1584#ifndef QT_NO_DEBUG-
1585 if (active.load() != 0) {
active.load() != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1586 qWarning("QtGui: Resources are still available at program shutdown.\n"-
1587 " This is possibly caused by a leaked QOpenGLWidget, \n"-
1588 " QOpenGLFramebufferObject or QOpenGLPixelBuffer.");-
1589 }
never executed: end of block
0
1590#endif-
1591}
never executed: end of block
0
1592-
1593void QOpenGLMultiGroupSharedResource::insert(QOpenGLContext *context, QOpenGLSharedResource *value)-
1594{-
1595#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG-
1596 qDebug("Inserting context group resource %p for context %p, managed by %p.", value, context, this);-
1597#endif-
1598 QOpenGLContextGroup *group = context->shareGroup();-
1599 Q_ASSERT(!group->d_func()->m_resources.contains(this));-
1600 group->d_func()->m_resources.insert(this, value);-
1601 m_groups.append(group);-
1602 active.ref();-
1603}
never executed: end of block
0
1604-
1605QOpenGLSharedResource *QOpenGLMultiGroupSharedResource::value(QOpenGLContext *context)-
1606{-
1607 QOpenGLContextGroup *group = context->shareGroup();-
1608 return group->d_func()->m_resources.value(this, 0);
never executed: return group->d_func()->m_resources.value(this, 0);
0
1609}-
1610-
1611QList<QOpenGLSharedResource *> QOpenGLMultiGroupSharedResource::resources() const-
1612{-
1613 QList<QOpenGLSharedResource *> result;-
1614 for (QList<QOpenGLContextGroup *>::const_iterator it = m_groups.constBegin(); it != m_groups.constEnd(); ++it) {
it != m_groups.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
1615 QOpenGLSharedResource *resource = (*it)->d_func()->m_resources.value(const_cast<QOpenGLMultiGroupSharedResource *>(this), 0);-
1616 if (resource)
resourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1617 result << resource;
never executed: result << resource;
0
1618 }
never executed: end of block
0
1619 return result;
never executed: return result;
0
1620}-
1621-
1622void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenGLSharedResource *value)-
1623{-
1624#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG-
1625 qDebug("Cleaning up context group resource %p, for group %p in thread %p.", this, group, QThread::currentThread());-
1626#endif-
1627 value->invalidateResource();-
1628 value->free();-
1629 active.deref();-
1630-
1631 Q_ASSERT(m_groups.contains(group));-
1632 m_groups.removeOne(group);-
1633}
never executed: end of block
0
1634-
1635#include "moc_qopenglcontext.cpp"-
1636-
1637QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9