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 QtOpenGL 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 "qapplication.h"
41#include "qplatformdefs.h"
42#include "qgl.h"
43#include <qdebug.h>
44#include <qglfunctions.h>
45
46#include <qdatetime.h>
47
48#include <stdlib.h> // malloc
49
50#include "qpixmap.h"
51#include "qimage.h"
52#include "qgl_p.h"
53
54#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
55
56#include <qpa/qplatformopenglcontext.h>
57
58#include <qglpixelbuffer.h>
59#include <qglframebufferobject.h>
60#include <private/qopenglextensions_p.h>
61
62#include <private/qimage_p.h>
63#include <qpa/qplatformpixmap.h>
64#include <private/qglpixelbuffer_p.h>
65#include <private/qimagepixmapcleanuphooks_p.h>
66#include "qcolormap.h"
67#include "qfile.h"
68#include <qmutex.h>
69
70#include "qsurfaceformat.h"
71#include <private/qapplication_p.h>
72#include <qpa/qplatformopenglcontext.h>
73#include <qpa/qplatformwindow.h>
74
75#ifndef QT_OPENGL_ES_2
76#include <qopenglfunctions_1_1.h>
77#endif
78
79// #define QT_GL_CONTEXT_RESOURCE_DEBUG
80
81QT_BEGIN_NAMESPACE
82
83class QGLDefaultExtensions
84{
85public:
86 QGLDefaultExtensions() : extensions(0) {
87 QGLTemporaryContext tempContext;
88 Q_ASSERT(QOpenGLContext::currentContext());
89 QOpenGLExtensions *ext = qgl_extensions();
90 Q_ASSERT(ext);
91 extensions = ext->openGLExtensions();
92 features = ext->openGLFeatures();
93 }
94
95 QOpenGLFunctions::OpenGLFeatures features;
96 QOpenGLExtensions::OpenGLExtensions extensions;
97};
98
99Q_GLOBAL_STATIC(QGLDefaultExtensions, qtDefaultExtensions)
100
101bool qgl_hasFeature(QOpenGLFunctions::OpenGLFeature feature)
102{
103 if (QOpenGLContext::currentContext())
104 return QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(feature);
105 return qtDefaultExtensions()->features & feature;
106}
107
108bool qgl_hasExtension(QOpenGLExtensions::OpenGLExtension extension)
109{
110 if (QOpenGLContext::currentContext())
111 return qgl_extensions()->hasOpenGLExtension(extension);
112 return qtDefaultExtensions()->extensions & extension;
113}
114
115QOpenGLExtensions::OpenGLExtensions extensions;
116
117/*
118 Returns the GL extensions for the current QOpenGLContext. If there is no
119 current QOpenGLContext, a default context will be created and the extensions
120 for that context will be returned instead.
121*/
122QOpenGLExtensions* qgl_extensions()
123{
124 if (QOpenGLContext *context = QOpenGLContext::currentContext())
125 return static_cast<QOpenGLExtensions *>(context->functions());
126
127 Q_ASSERT(false);
128 return 0;
129}
130
131QOpenGLFunctions *qgl_functions()
132{
133 return qgl_extensions(); // QOpenGLExtensions is just a subclass of QOpenGLFunctions
134}
135
136#ifndef QT_OPENGL_ES_2
137QOpenGLFunctions_1_1 *qgl1_functions()
138{
139 QOpenGLFunctions_1_1 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_1>();
140 f->initializeOpenGLFunctions();
141 return f;
142}
143#endif
144
145struct QGLThreadContext {
146 ~QGLThreadContext() {
147 if (context)
148 context->doneCurrent();
149 }
150 QGLContext *context;
151};
152
153Q_GLOBAL_STATIC(QGLFormat, qgl_default_format)
154
155class QGLDefaultOverlayFormat: public QGLFormat
156{
157public:
158 inline QGLDefaultOverlayFormat()
159 {
160 setOption(QGL::FormatOption(0xffffU << 16)); // turn off all options
161 setOption(QGL::DirectRendering);
162 setPlane(1);
163 }
164};
165Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
166
167Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
168QGLSignalProxy *QGLSignalProxy::instance()
169{
170 QGLSignalProxy *proxy = theSignalProxy();
171 if (proxy && qApp && proxy->thread() != qApp->thread()) {
172 if (proxy->thread() == QThread::currentThread())
173 proxy->moveToThread(qApp->thread());
174 }
175 return proxy;
176}
177
178
179/*!
180 \namespace QGL
181 \inmodule QtOpenGL
182
183 \brief The QGL namespace specifies miscellaneous identifiers used
184 in the Qt OpenGL module.
185*/
186
187/*!
188 \enum QGL::FormatOption
189
190 This enum specifies the format options that can be used to configure an OpenGL
191 context. These are set using QGLFormat::setOption().
192
193 \value DoubleBuffer Specifies the use of double buffering.
194 \value DepthBuffer Enables the use of a depth buffer.
195 \value Rgba Specifies that the context should use RGBA as its pixel format.
196 \value AlphaChannel Enables the use of an alpha channel.
197 \value AccumBuffer Enables the use of an accumulation buffer.
198 \value StencilBuffer Enables the use of a stencil buffer.
199 \value StereoBuffers Enables the use of a stereo buffers for use with visualization hardware.
200 \value DirectRendering Specifies that the context is used for direct rendering to a display.
201 \value HasOverlay Enables the use of an overlay.
202 \value SampleBuffers Enables the use of sample buffers.
203 \value DeprecatedFunctions Enables the use of deprecated functionality for OpenGL 3.x
204 contexts. A context with deprecated functionality enabled is
205 called a full context in the OpenGL specification.
206 \value SingleBuffer Specifies the use of a single buffer, as opposed to double buffers.
207 \value NoDepthBuffer Disables the use of a depth buffer.
208 \value ColorIndex Specifies that the context should use a color index as its pixel format.
209 \value NoAlphaChannel Disables the use of an alpha channel.
210 \value NoAccumBuffer Disables the use of an accumulation buffer.
211 \value NoStencilBuffer Disables the use of a stencil buffer.
212 \value NoStereoBuffers Disables the use of stereo buffers.
213 \value IndirectRendering Specifies that the context is used for indirect rendering to a buffer.
214 \value NoOverlay Disables the use of an overlay.
215 \value NoSampleBuffers Disables the use of sample buffers.
216 \value NoDeprecatedFunctions Disables the use of deprecated functionality for OpenGL 3.x
217 contexts. A context with deprecated functionality disabled is
218 called a forward compatible context in the OpenGL specification.
219*/
220
221/*****************************************************************************
222 QGLFormat implementation
223 *****************************************************************************/
224
225
226/*!
227 \class QGLFormat
228 \inmodule QtOpenGL
229 \obsolete
230
231 \brief The QGLFormat class specifies the display format of an OpenGL
232 rendering context.
233
234 A display format has several characteristics:
235 \list
236 \li \l{setDoubleBuffer()}{Double or single buffering.}
237 \li \l{setDepth()}{Depth buffer.}
238 \li \l{setRgba()}{RGBA or color index mode.}
239 \li \l{setAlpha()}{Alpha channel.}
240 \li \l{setAccum()}{Accumulation buffer.}
241 \li \l{setStencil()}{Stencil buffer.}
242 \li \l{setStereo()}{Stereo buffers.}
243 \li \l{setDirectRendering()}{Direct rendering.}
244 \li \l{setOverlay()}{Presence of an overlay.}
245 \li \l{setPlane()}{Plane of an overlay.}
246 \li \l{setSampleBuffers()}{Multisample buffers.}
247 \endlist
248
249 You can also specify preferred bit depths for the color buffer,
250 depth buffer, alpha buffer, accumulation buffer and the stencil
251 buffer with the functions: setRedBufferSize(), setGreenBufferSize(),
252 setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(),
253 setAccumBufferSize() and setStencilBufferSize().
254
255 Note that even if you specify that you prefer a 32 bit depth
256 buffer (e.g. with setDepthBufferSize(32)), the format that is
257 chosen may not have a 32 bit depth buffer, even if there is a
258 format available with a 32 bit depth buffer. The main reason for
259 this is how the system dependant picking algorithms work on the
260 different platforms, and some format options may have higher
261 precedence than others.
262
263 You create and tell a QGLFormat object what rendering options you
264 want from an OpenGL rendering context.
265
266 OpenGL drivers or accelerated hardware may or may not support
267 advanced features such as alpha channel or stereographic viewing.
268 If you request some features that the driver/hardware does not
269 provide when you create a QGLWidget, you will get a rendering
270 context with the nearest subset of features.
271
272 There are different ways to define the display characteristics of
273 a rendering context. One is to create a QGLFormat and make it the
274 default for the entire application:
275 \snippet code/src_opengl_qgl.cpp 0
276
277 Or you can specify the desired format when creating an object of
278 your QGLWidget subclass:
279 \snippet code/src_opengl_qgl.cpp 1
280
281 After the widget has been created, you can find out which of the
282 requested features the system was able to provide:
283 \snippet code/src_opengl_qgl.cpp 2
284
285 \legalese
286 OpenGL is a trademark of Silicon Graphics, Inc. in the
287 United States and other countries.
288 \endlegalese
289
290 \sa QGLContext, QGLWidget
291*/
292
293#ifndef QT_OPENGL_ES
294
295static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
296{
297#define M(row,col) m[col*4+row]
298 out[0] =
299 M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
300 out[1] =
301 M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
302 out[2] =
303 M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
304 out[3] =
305 M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
306#undef M
307}
308
309static inline GLint qgluProject(GLdouble objx, GLdouble objy, GLdouble objz,
310 const GLdouble model[16], const GLdouble proj[16],
311 const GLint viewport[4],
312 GLdouble * winx, GLdouble * winy, GLdouble * winz)
313{
314 GLdouble in[4], out[4];
315
316 in[0] = objx;
317 in[1] = objy;
318 in[2] = objz;
319 in[3] = 1.0;
320 transform_point(out, model, in);
321 transform_point(in, proj, out);
322
323 if (in[3] == 0.0)
324 return GL_FALSE;
325
326 in[0] /= in[3];
327 in[1] /= in[3];
328 in[2] /= in[3];
329
330 *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
331 *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
332
333 *winz = (1 + in[2]) / 2;
334 return GL_TRUE;
335}
336
337#endif // !QT_OPENGL_ES
338
339/*!
340 Constructs a QGLFormat object with the following default settings:
341 \list
342 \li \l{setDoubleBuffer()}{Double buffer:} Enabled.
343 \li \l{setDepth()}{Depth buffer:} Enabled.
344 \li \l{setRgba()}{RGBA:} Enabled (i.e., color index disabled).
345 \li \l{setAlpha()}{Alpha channel:} Disabled.
346 \li \l{setAccum()}{Accumulator buffer:} Disabled.
347 \li \l{setStencil()}{Stencil buffer:} Enabled.
348 \li \l{setStereo()}{Stereo:} Disabled.
349 \li \l{setDirectRendering()}{Direct rendering:} Enabled.
350 \li \l{setOverlay()}{Overlay:} Disabled.
351 \li \l{setPlane()}{Plane:} 0 (i.e., normal plane).
352 \li \l{setSampleBuffers()}{Multisample buffers:} Disabled.
353 \endlist
354*/
355
356QGLFormat::QGLFormat()
357{
358 d = new QGLFormatPrivate;
359}
360
361
362/*!
363 Creates a QGLFormat object that is a copy of the current
364 defaultFormat().
365
366 If \a options is not 0, the default format is modified by the
367 specified format options. The \a options parameter should be
368 QGL::FormatOption values OR'ed together.
369
370 This constructor makes it easy to specify a certain desired format
371 in classes derived from QGLWidget, for example:
372 \snippet code/src_opengl_qgl.cpp 3
373
374 Note that there are QGL::FormatOption values to turn format settings
375 both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer,
376 QGL::DirectRendering and QGL::IndirectRendering, etc.
377
378 The \a plane parameter defaults to 0 and is the plane which this
379 format should be associated with. Not all OpenGL implementations
380 supports overlay/underlay rendering planes.
381
382 \sa defaultFormat(), setOption(), setPlane()
383*/
384
385QGLFormat::QGLFormat(QGL::FormatOptions options, int plane)
386{
387 d = new QGLFormatPrivate;
388 QGL::FormatOptions newOpts = options;
389 d->opts = defaultFormat().d->opts;
390 d->opts |= (newOpts & 0xffff);
391 d->opts &= ~(newOpts >> 16);
392 d->pln = plane;
393}
394
395/*!
396 \internal
397*/
398void QGLFormat::detach()
399{
400 if (d->ref.loadRelaxed() != 1) {
401 QGLFormatPrivate *newd = new QGLFormatPrivate(d);
402 if (!d->ref.deref())
403 delete d;
404 d = newd;
405 }
406}
407
408/*!
409 Constructs a copy of \a other.
410*/
411
412QGLFormat::QGLFormat(const QGLFormat &other)
413{
414 d = other.d;
415 d->ref.ref();
416}
417
418/*!
419 Assigns \a other to this object.
420*/
421
422QGLFormat &QGLFormat::operator=(const QGLFormat &other)
423{
424 if (d != other.d) {
425 other.d->ref.ref();
426 if (!d->ref.deref())
427 delete d;
428 d = other.d;
429 }
430 return *this;
431}
432
433/*!
434 Destroys the QGLFormat.
435*/
436QGLFormat::~QGLFormat()
437{
438 if (!d->ref.deref())
439 delete d;
440}
441
442/*!
443 Returns an OpenGL format for the window format specified by \a format.
444*/
445QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format)
446{
447 QGLFormat retFormat;
448 if (format.alphaBufferSize() >= 0)
449 retFormat.setAlphaBufferSize(format.alphaBufferSize());
450 if (format.blueBufferSize() >= 0)
451 retFormat.setBlueBufferSize(format.blueBufferSize());
452 if (format.greenBufferSize() >= 0)
453 retFormat.setGreenBufferSize(format.greenBufferSize());
454 if (format.redBufferSize() >= 0)
455 retFormat.setRedBufferSize(format.redBufferSize());
456 if (format.depthBufferSize() >= 0)
457 retFormat.setDepthBufferSize(format.depthBufferSize());
458 if (format.samples() > 1) {
459 retFormat.setSampleBuffers(true);
460 retFormat.setSamples(format.samples());
461 }
462 if (format.stencilBufferSize() > 0) {
463 retFormat.setStencil(true);
464 retFormat.setStencilBufferSize(format.stencilBufferSize());
465 }
466 retFormat.setSwapInterval(format.swapInterval());
467 retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer);
468 retFormat.setStereo(format.stereo());
469 retFormat.setVersion(format.majorVersion(), format.minorVersion());
470 retFormat.setProfile(static_cast<QGLFormat::OpenGLContextProfile>(format.profile()));
471 return retFormat;
472}
473
474/*!
475 Returns a window format for the OpenGL format specified by \a format.
476*/
477QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format)
478{
479 QSurfaceFormat retFormat;
480 if (format.alpha())
481 retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize());
482 if (format.blueBufferSize() >= 0)
483 retFormat.setBlueBufferSize(format.blueBufferSize());
484 if (format.greenBufferSize() >= 0)
485 retFormat.setGreenBufferSize(format.greenBufferSize());
486 if (format.redBufferSize() >= 0)
487 retFormat.setRedBufferSize(format.redBufferSize());
488 if (format.depth())
489 retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize());
490 retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
491 if (format.sampleBuffers())
492 retFormat.setSamples(format.samples() == -1 ? 4 : format.samples());
493 if (format.stencil())
494 retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize());
495 retFormat.setSwapInterval(format.swapInterval());
496 retFormat.setStereo(format.stereo());
497 retFormat.setMajorVersion(format.majorVersion());
498 retFormat.setMinorVersion(format.minorVersion());
499 retFormat.setProfile(static_cast<QSurfaceFormat::OpenGLContextProfile>(format.profile()));
500 // QGLFormat has no way to set DeprecatedFunctions, that is, to tell that forward
501 // compatibility should not be requested. Some drivers fail to ignore the fwdcompat
502 // bit with compatibility profiles so make sure it is not set.
503 if (format.profile() == QGLFormat::CompatibilityProfile)
504 retFormat.setOption(QSurfaceFormat::DeprecatedFunctions);
505 return retFormat;
506}
507
508void QGLContextPrivate::setupSharing() {
509 Q_Q(QGLContext);
510 QOpenGLContext *sharedContext = guiGlContext->shareContext();
511 if (sharedContext) {
512 QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext);
513 sharing = true;
514 QGLContextGroup::addShare(q, actualSharedContext);
515 }
516}
517
518void QGLContextPrivate::refreshCurrentFbo()
519{
520 QOpenGLContextPrivate *guiGlContextPrivate =
521 guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
522
523 // if QOpenGLFramebufferObjects have been used in the mean-time, we've lost our cached value
524 if (guiGlContextPrivate && guiGlContextPrivate->qgl_current_fbo_invalid) {
525 GLint current;
526 QOpenGLFunctions *funcs = qgl_functions();
527 funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &current);
528
529 current_fbo = current;
530
531 guiGlContextPrivate->qgl_current_fbo_invalid = false;
532 }
533}
534
535void QGLContextPrivate::setCurrentFbo(GLuint fbo)
536{
537 current_fbo = fbo;
538
539 QOpenGLContextPrivate *guiGlContextPrivate =
540 guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
541
542 if (guiGlContextPrivate)
543 guiGlContextPrivate->qgl_current_fbo_invalid = false;
544}
545
546
547/*!
548 \fn bool QGLFormat::doubleBuffer() const
549
550 Returns \c true if double buffering is enabled; otherwise returns
551 false. Double buffering is enabled by default.
552
553 \sa setDoubleBuffer()
554*/
555
556/*!
557 If \a enable is true sets double buffering; otherwise sets single
558 buffering.
559
560 Double buffering is enabled by default.
561
562 Double buffering is a technique where graphics are rendered on an
563 off-screen buffer and not directly to the screen. When the drawing
564 has been completed, the program calls a swapBuffers() function to
565 exchange the screen contents with the buffer. The result is
566 flicker-free drawing and often better performance.
567
568 Note that single buffered contexts are currently not supported
569 with EGL.
570
571 \sa doubleBuffer(), QGLContext::swapBuffers(),
572 QGLWidget::swapBuffers()
573*/
574
575void QGLFormat::setDoubleBuffer(bool enable)
576{
577 setOption(enable ? QGL::DoubleBuffer : QGL::SingleBuffer);
578}
579
580
581/*!
582 \fn bool QGLFormat::depth() const
583
584 Returns \c true if the depth buffer is enabled; otherwise returns
585 false. The depth buffer is enabled by default.
586
587 \sa setDepth(), setDepthBufferSize()
588*/
589
590/*!
591 If \a enable is true enables the depth buffer; otherwise disables
592 the depth buffer.
593
594 The depth buffer is enabled by default.
595
596 The purpose of a depth buffer (or Z-buffering) is to remove hidden
597 surfaces. Pixels are assigned Z values based on the distance to
598 the viewer. A pixel with a high Z value is closer to the viewer
599 than a pixel with a low Z value. This information is used to
600 decide whether to draw a pixel or not.
601
602 \sa depth(), setDepthBufferSize()
603*/
604
605void QGLFormat::setDepth(bool enable)
606{
607 setOption(enable ? QGL::DepthBuffer : QGL::NoDepthBuffer);
608}
609
610
611/*!
612 \fn bool QGLFormat::rgba() const
613
614 Returns \c true if RGBA color mode is set. Returns \c false if color
615 index mode is set. The default color mode is RGBA.
616
617 \sa setRgba()
618*/
619
620/*!
621 If \a enable is true sets RGBA mode. If \a enable is false sets
622 color index mode.
623
624 The default color mode is RGBA.
625
626 RGBA is the preferred mode for most OpenGL applications. In RGBA
627 color mode you specify colors as red + green + blue + alpha
628 quadruplets.
629
630 In color index mode you specify an index into a color lookup
631 table.
632
633 \sa rgba()
634*/
635
636void QGLFormat::setRgba(bool enable)
637{
638 setOption(enable ? QGL::Rgba : QGL::ColorIndex);
639}
640
641
642/*!
643 \fn bool QGLFormat::alpha() const
644
645 Returns \c true if the alpha buffer in the framebuffer is enabled;
646 otherwise returns \c false. The alpha buffer is disabled by default.
647
648 \sa setAlpha(), setAlphaBufferSize()
649*/
650
651/*!
652 If \a enable is true enables the alpha buffer; otherwise disables
653 the alpha buffer.
654
655 The alpha buffer is disabled by default.
656
657 The alpha buffer is typically used for implementing transparency
658 or translucency. The A in RGBA specifies the transparency of a
659 pixel.
660
661 \sa alpha(), setAlphaBufferSize()
662*/
663
664void QGLFormat::setAlpha(bool enable)
665{
666 setOption(enable ? QGL::AlphaChannel : QGL::NoAlphaChannel);
667}
668
669
670/*!
671 \fn bool QGLFormat::accum() const
672
673 Returns \c true if the accumulation buffer is enabled; otherwise
674 returns \c false. The accumulation buffer is disabled by default.
675
676 \sa setAccum(), setAccumBufferSize()
677*/
678
679/*!
680 If \a enable is true enables the accumulation buffer; otherwise
681 disables the accumulation buffer.
682
683 The accumulation buffer is disabled by default.
684
685 The accumulation buffer is used to create blur effects and
686 multiple exposures.
687
688 \sa accum(), setAccumBufferSize()
689*/
690
691void QGLFormat::setAccum(bool enable)
692{
693 setOption(enable ? QGL::AccumBuffer : QGL::NoAccumBuffer);
694}
695
696
697/*!
698 \fn bool QGLFormat::stencil() const
699
700 Returns \c true if the stencil buffer is enabled; otherwise returns
701 false. The stencil buffer is enabled by default.
702
703 \sa setStencil(), setStencilBufferSize()
704*/
705
706/*!
707 If \a enable is true enables the stencil buffer; otherwise
708 disables the stencil buffer.
709
710 The stencil buffer is enabled by default.
711
712 The stencil buffer masks certain parts of the drawing area so that
713 masked parts are not drawn on.
714
715 \sa stencil(), setStencilBufferSize()
716*/
717
718void QGLFormat::setStencil(bool enable)
719{
720 setOption(enable ? QGL::StencilBuffer: QGL::NoStencilBuffer);
721}
722
723
724/*!
725 \fn bool QGLFormat::stereo() const
726
727 Returns \c true if stereo buffering is enabled; otherwise returns
728 false. Stereo buffering is disabled by default.
729
730 \sa setStereo()
731*/
732
733/*!
734 If \a enable is true enables stereo buffering; otherwise disables
735 stereo buffering.
736
737 Stereo buffering is disabled by default.
738
739 Stereo buffering provides extra color buffers to generate left-eye
740 and right-eye images.
741
742 \sa stereo()
743*/
744
745void QGLFormat::setStereo(bool enable)
746{
747 setOption(enable ? QGL::StereoBuffers : QGL::NoStereoBuffers);
748}
749
750
751/*!
752 \fn bool QGLFormat::directRendering() const
753
754 Returns \c true if direct rendering is enabled; otherwise returns
755 false.
756
757 Direct rendering is enabled by default.
758
759 \sa setDirectRendering()
760*/
761
762/*!
763 If \a enable is true enables direct rendering; otherwise disables
764 direct rendering.
765
766 Direct rendering is enabled by default.
767
768 Enabling this option will make OpenGL bypass the underlying window
769 system and render directly from hardware to the screen, if this is
770 supported by the system.
771
772 \sa directRendering()
773*/
774
775void QGLFormat::setDirectRendering(bool enable)
776{
777 setOption(enable ? QGL::DirectRendering : QGL::IndirectRendering);
778}
779
780/*!
781 \fn bool QGLFormat::sampleBuffers() const
782
783 Returns \c true if multisample buffer support is enabled; otherwise
784 returns \c false.
785
786 The multisample buffer is disabled by default.
787
788 \sa setSampleBuffers()
789*/
790
791/*!
792 If \a enable is true, a GL context with multisample buffer support
793 is picked; otherwise ignored.
794
795 \sa sampleBuffers(), setSamples(), samples()
796*/
797void QGLFormat::setSampleBuffers(bool enable)
798{
799 setOption(enable ? QGL::SampleBuffers : QGL::NoSampleBuffers);
800}
801
802/*!
803 Returns the number of samples per pixel when multisampling is
804 enabled. By default, the highest number of samples that is
805 available is used.
806
807 \sa setSampleBuffers(), sampleBuffers(), setSamples()
808*/
809int QGLFormat::samples() const
810{
811 return d->numSamples;
812}
813
814/*!
815 Set the preferred number of samples per pixel when multisampling
816 is enabled to \a numSamples. By default, the highest number of
817 samples available is used.
818
819 \sa setSampleBuffers(), sampleBuffers(), samples()
820*/
821void QGLFormat::setSamples(int numSamples)
822{
823 detach();
824 if (numSamples < 0) {
825 qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples);
826 return;
827 }
828 d->numSamples = numSamples;
829 setSampleBuffers(numSamples > 0);
830}
831
832/*!
833 \since 4.2
834
835 Set the preferred swap interval. This can be used to sync the GL
836 drawing into a system window to the vertical refresh of the screen.
837 Setting an \a interval value of 0 will turn the vertical refresh syncing
838 off, any value higher than 0 will turn the vertical syncing on.
839
840 Under Windows and under X11, where the \c{WGL_EXT_swap_control}
841 and \c{GLX_SGI_video_sync} extensions are used, the \a interval
842 parameter can be used to set the minimum number of video frames
843 that are displayed before a buffer swap will occur. In effect,
844 setting the \a interval to 10, means there will be 10 vertical
845 retraces between every buffer swap.
846
847 Under Windows the \c{WGL_EXT_swap_control} extension has to be present,
848 and under X11 the \c{GLX_SGI_video_sync} extension has to be present.
849*/
850void QGLFormat::setSwapInterval(int interval)
851{
852 detach();
853 d->swapInterval = interval;
854}
855
856/*!
857 \since 4.2
858
859 Returns the currently set swap interval. -1 is returned if setting
860 the swap interval isn't supported in the system GL implementation.
861*/
862int QGLFormat::swapInterval() const
863{
864 return d->swapInterval;
865}
866
867/*!
868 \fn bool QGLFormat::hasOverlay() const
869
870 Returns \c true if overlay plane is enabled; otherwise returns \c false.
871
872 Overlay is disabled by default.
873
874 \sa setOverlay()
875*/
876
877/*!
878 If \a enable is true enables an overlay plane; otherwise disables
879 the overlay plane.
880
881 Enabling the overlay plane will cause QGLWidget to create an
882 additional context in an overlay plane. See the QGLWidget
883 documentation for further information.
884
885 \sa hasOverlay()
886*/
887
888void QGLFormat::setOverlay(bool enable)
889{
890 setOption(enable ? QGL::HasOverlay : QGL::NoOverlay);
891}
892
893/*!
894 Returns the plane of this format. The default for normal formats
895 is 0, which means the normal plane. The default for overlay
896 formats is 1, which is the first overlay plane.
897
898 \sa setPlane(), defaultOverlayFormat()
899*/
900int QGLFormat::plane() const
901{
902 return d->pln;
903}
904
905/*!
906 Sets the requested plane to \a plane. 0 is the normal plane, 1 is
907 the first overlay plane, 2 is the second overlay plane, etc.; -1,
908 -2, etc. are underlay planes.
909
910 Note that in contrast to other format specifications, the plane
911 specifications will be matched exactly. This means that if you
912 specify a plane that the underlying OpenGL system cannot provide,
913 an \l{QGLWidget::isValid()}{invalid} QGLWidget will be
914 created.
915
916 \sa plane()
917*/
918void QGLFormat::setPlane(int plane)
919{
920 detach();
921 d->pln = plane;
922}
923
924/*!
925 Sets the format option to \a opt.
926
927 \sa testOption()
928*/
929
930void QGLFormat::setOption(QGL::FormatOptions opt)
931{
932 detach();
933 if (opt & 0xffff)
934 d->opts |= opt;
935 else
936 d->opts &= ~(opt >> 16);
937}
938
939
940
941/*!
942 Returns \c true if format option \a opt is set; otherwise returns \c false.
943
944 \sa setOption()
945*/
946
947bool QGLFormat::testOption(QGL::FormatOptions opt) const
948{
949 if (opt & 0xffff)
950 return (d->opts & opt) != 0;
951 else
952 return (d->opts & (opt >> 16)) == 0;
953}
954
955/*!
956 Set the minimum depth buffer size to \a size.
957
958 \sa depthBufferSize(), setDepth(), depth()
959*/
960void QGLFormat::setDepthBufferSize(int size)
961{
962 detach();
963 if (size < 0) {
964 qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size);
965 return;
966 }
967 d->depthSize = size;
968 setDepth(size > 0);
969}
970
971/*!
972 Returns the depth buffer size.
973
974 \sa depth(), setDepth(), setDepthBufferSize()
975*/
976int QGLFormat::depthBufferSize() const
977{
978 return d->depthSize;
979}
980
981/*!
982 \since 4.2
983
984 Set the preferred red buffer size to \a size.
985
986 \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
987*/
988void QGLFormat::setRedBufferSize(int size)
989{
990 detach();
991 if (size < 0) {
992 qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size);
993 return;
994 }
995 d->redSize = size;
996}
997
998/*!
999 \since 4.2
1000
1001 Returns the red buffer size.
1002
1003 \sa setRedBufferSize()
1004*/
1005int QGLFormat::redBufferSize() const
1006{
1007 return d->redSize;
1008}
1009
1010/*!
1011 \since 4.2
1012
1013 Set the preferred green buffer size to \a size.
1014
1015 \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
1016*/
1017void QGLFormat::setGreenBufferSize(int size)
1018{
1019 detach();
1020 if (size < 0) {
1021 qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size);
1022 return;
1023 }
1024 d->greenSize = size;
1025}
1026
1027/*!
1028 \since 4.2
1029
1030 Returns the green buffer size.
1031
1032 \sa setGreenBufferSize()
1033*/
1034int QGLFormat::greenBufferSize() const
1035{
1036 return d->greenSize;
1037}
1038
1039/*!
1040 \since 4.2
1041
1042 Set the preferred blue buffer size to \a size.
1043
1044 \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize()
1045*/
1046void QGLFormat::setBlueBufferSize(int size)
1047{
1048 detach();
1049 if (size < 0) {
1050 qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size);
1051 return;
1052 }
1053 d->blueSize = size;
1054}
1055
1056/*!
1057 \since 4.2
1058
1059 Returns the blue buffer size.
1060
1061 \sa setBlueBufferSize()
1062*/
1063int QGLFormat::blueBufferSize() const
1064{
1065 return d->blueSize;
1066}
1067
1068/*!
1069 Set the preferred alpha buffer size to \a size.
1070 This function implicitly enables the alpha channel.
1071
1072 \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize()
1073*/
1074void QGLFormat::setAlphaBufferSize(int size)
1075{
1076 detach();
1077 if (size < 0) {
1078 qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size);
1079 return;
1080 }
1081 d->alphaSize = size;
1082 setAlpha(size > 0);
1083}
1084
1085/*!
1086 Returns the alpha buffer size.
1087
1088 \sa alpha(), setAlpha(), setAlphaBufferSize()
1089*/
1090int QGLFormat::alphaBufferSize() const
1091{
1092 return d->alphaSize;
1093}
1094
1095/*!
1096 Set the preferred accumulation buffer size, where \a size is the
1097 bit depth for each RGBA component.
1098
1099 \sa accum(), setAccum(), accumBufferSize()
1100*/
1101void QGLFormat::setAccumBufferSize(int size)
1102{
1103 detach();
1104 if (size < 0) {
1105 qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size);
1106 return;
1107 }
1108 d->accumSize = size;
1109 setAccum(size > 0);
1110}
1111
1112/*!
1113 Returns the accumulation buffer size.
1114
1115 \sa setAccumBufferSize(), accum(), setAccum()
1116*/
1117int QGLFormat::accumBufferSize() const
1118{
1119 return d->accumSize;
1120}
1121
1122/*!
1123 Set the preferred stencil buffer size to \a size.
1124
1125 \sa stencilBufferSize(), setStencil(), stencil()
1126*/
1127void QGLFormat::setStencilBufferSize(int size)
1128{
1129 detach();
1130 if (size < 0) {
1131 qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size);
1132 return;
1133 }
1134 d->stencilSize = size;
1135 setStencil(size > 0);
1136}
1137
1138/*!
1139 Returns the stencil buffer size.
1140
1141 \sa stencil(), setStencil(), setStencilBufferSize()
1142*/
1143int QGLFormat::stencilBufferSize() const
1144{
1145 return d->stencilSize;
1146}
1147
1148/*!
1149 \since 4.7
1150
1151 Set the OpenGL version to the \a major and \a minor numbers. If a
1152 context compatible with the requested OpenGL version cannot be
1153 created, a context compatible with version 1.x is created instead.
1154
1155 \sa majorVersion(), minorVersion()
1156*/
1157void QGLFormat::setVersion(int major, int minor)
1158{
1159 if (major < 1 || minor < 0) {
1160 qWarning("QGLFormat::setVersion: Cannot set zero or negative version number %d.%d", major, minor);
1161 return;
1162 }
1163 detach();
1164 d->majorVersion = major;
1165 d->minorVersion = minor;
1166}
1167
1168/*!
1169 \since 4.7
1170
1171 Returns the OpenGL major version.
1172
1173 \sa setVersion(), minorVersion()
1174*/
1175int QGLFormat::majorVersion() const
1176{
1177 return d->majorVersion;
1178}
1179
1180/*!
1181 \since 4.7
1182
1183 Returns the OpenGL minor version.
1184
1185 \sa setVersion(), majorVersion()
1186*/
1187int QGLFormat::minorVersion() const
1188{
1189 return d->minorVersion;
1190}
1191
1192/*!
1193 \enum QGLFormat::OpenGLContextProfile
1194 \since 4.7
1195
1196 This enum describes the OpenGL context profiles that can be
1197 specified for contexts implementing OpenGL version 3.2 or
1198 higher. These profiles are different from OpenGL ES profiles.
1199
1200 \value NoProfile OpenGL version is lower than 3.2.
1201 \value CoreProfile Functionality deprecated in OpenGL version 3.0 is not available.
1202 \value CompatibilityProfile Functionality from earlier OpenGL versions is available.
1203*/
1204
1205/*!
1206 \since 4.7
1207
1208 Set the OpenGL context profile to \a profile. The \a profile is
1209 ignored if the requested OpenGL version is less than 3.2.
1210
1211 \sa profile()
1212*/
1213void QGLFormat::setProfile(OpenGLContextProfile profile)
1214{
1215 detach();
1216 d->profile = profile;
1217}
1218
1219/*!
1220 \since 4.7
1221
1222 Returns the OpenGL context profile.
1223
1224 \sa setProfile()
1225*/
1226QGLFormat::OpenGLContextProfile QGLFormat::profile() const
1227{
1228 return d->profile;
1229}
1230
1231
1232/*!
1233 \fn bool QGLFormat::hasOpenGL()
1234
1235 Returns \c true if the window system has any OpenGL support;
1236 otherwise returns \c false.
1237
1238 \warning This function must not be called until the QApplication
1239 object has been created.
1240*/
1241bool QGLFormat::hasOpenGL()
1242{
1243 return QApplicationPrivate::platformIntegration()
1244 ->hasCapability(QPlatformIntegration::OpenGL);
1245}
1246
1247/*!
1248 \fn bool QGLFormat::hasOpenGLOverlays()
1249
1250 Returns \c true if the window system supports OpenGL overlays;
1251 otherwise returns \c false.
1252
1253 \warning This function must not be called until the QApplication
1254 object has been created.
1255*/
1256bool QGLFormat::hasOpenGLOverlays()
1257{
1258 return false;
1259}
1260
1261QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString)
1262{
1263 QGLFormat::OpenGLVersionFlags versionFlags = QGLFormat::OpenGL_Version_None;
1264
1265 if (versionString.startsWith(QLatin1String("OpenGL ES"))) {
1266 const auto parts = versionString.splitRef(QLatin1Char(' '));
1267 if (parts.size() >= 3) {
1268 if (parts[2].startsWith(QLatin1String("1."))) {
1269 if (parts[1].endsWith(QLatin1String("-CM"))) {
1270 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_0 |
1271 QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1272 if (parts[2].startsWith(QLatin1String("1.1")))
1273 versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_1 |
1274 QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1275 } else {
1276 // Not -CM, must be CL, CommonLite
1277 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
1278 if (parts[2].startsWith(QLatin1String("1.1")))
1279 versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
1280 }
1281 } else {
1282 // OpenGL ES version 2.0 or higher
1283 versionFlags |= QGLFormat::OpenGL_ES_Version_2_0;
1284 }
1285 } else {
1286 // if < 3 parts to the name, it is an unrecognised OpenGL ES
1287 qWarning("Unrecognised OpenGL ES version");
1288 }
1289 } else {
1290 // not ES, regular OpenGL, the version numbers are first in the string
1291 if (versionString.startsWith(QLatin1String("1."))) {
1292 switch (versionString[2].toLatin1()) {
1293 case '5':
1294 versionFlags |= QGLFormat::OpenGL_Version_1_5;
1295 Q_FALLTHROUGH();
1296 case '4':
1297 versionFlags |= QGLFormat::OpenGL_Version_1_4;
1298 Q_FALLTHROUGH();
1299 case '3':
1300 versionFlags |= QGLFormat::OpenGL_Version_1_3;
1301 Q_FALLTHROUGH();
1302 case '2':
1303 versionFlags |= QGLFormat::OpenGL_Version_1_2;
1304 Q_FALLTHROUGH();
1305 case '1':
1306 versionFlags |= QGLFormat::OpenGL_Version_1_1;
1307 Q_FALLTHROUGH();
1308 default:
1309 break;
1310 }
1311 } else if (versionString.startsWith(QLatin1String("2."))) {
1312 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1313 QGLFormat::OpenGL_Version_1_2 |
1314 QGLFormat::OpenGL_Version_1_3 |
1315 QGLFormat::OpenGL_Version_1_4 |
1316 QGLFormat::OpenGL_Version_1_5 |
1317 QGLFormat::OpenGL_Version_2_0;
1318 if (versionString[2].toLatin1() == '1')
1319 versionFlags |= QGLFormat::OpenGL_Version_2_1;
1320 } else if (versionString.startsWith(QLatin1String("3."))) {
1321 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1322 QGLFormat::OpenGL_Version_1_2 |
1323 QGLFormat::OpenGL_Version_1_3 |
1324 QGLFormat::OpenGL_Version_1_4 |
1325 QGLFormat::OpenGL_Version_1_5 |
1326 QGLFormat::OpenGL_Version_2_0 |
1327 QGLFormat::OpenGL_Version_2_1 |
1328 QGLFormat::OpenGL_Version_3_0;
1329 switch (versionString[2].toLatin1()) {
1330 case '3':
1331 versionFlags |= QGLFormat::OpenGL_Version_3_3;
1332 Q_FALLTHROUGH();
1333 case '2':
1334 versionFlags |= QGLFormat::OpenGL_Version_3_2;
1335 Q_FALLTHROUGH();
1336 case '1':
1337 versionFlags |= QGLFormat::OpenGL_Version_3_1;
1338 Q_FALLTHROUGH();
1339 case '0':
1340 break;
1341 default:
1342 versionFlags |= QGLFormat::OpenGL_Version_3_1 |
1343 QGLFormat::OpenGL_Version_3_2 |
1344 QGLFormat::OpenGL_Version_3_3;
1345 break;
1346 }
1347 } else if (versionString.startsWith(QLatin1String("4."))) {
1348 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1349 QGLFormat::OpenGL_Version_1_2 |
1350 QGLFormat::OpenGL_Version_1_3 |
1351 QGLFormat::OpenGL_Version_1_4 |
1352 QGLFormat::OpenGL_Version_1_5 |
1353 QGLFormat::OpenGL_Version_2_0 |
1354 QGLFormat::OpenGL_Version_2_1 |
1355 QGLFormat::OpenGL_Version_3_0 |
1356 QGLFormat::OpenGL_Version_3_1 |
1357 QGLFormat::OpenGL_Version_3_2 |
1358 QGLFormat::OpenGL_Version_3_3 |
1359 QGLFormat::OpenGL_Version_4_0;
1360 switch (versionString[2].toLatin1()) {
1361 case '3':
1362 versionFlags |= QGLFormat::OpenGL_Version_4_3;
1363 Q_FALLTHROUGH();
1364 case '2':
1365 versionFlags |= QGLFormat::OpenGL_Version_4_2;
1366 Q_FALLTHROUGH();
1367 case '1':
1368 versionFlags |= QGLFormat::OpenGL_Version_4_1;
1369 Q_FALLTHROUGH();
1370 case '0':
1371 break;
1372 default:
1373 versionFlags |= QGLFormat::OpenGL_Version_4_1 |
1374 QGLFormat::OpenGL_Version_4_2 |
1375 QGLFormat::OpenGL_Version_4_3;
1376 break;
1377 }
1378 } else {
1379 versionFlags |= QGLFormat::OpenGL_Version_1_1 |
1380 QGLFormat::OpenGL_Version_1_2 |
1381 QGLFormat::OpenGL_Version_1_3 |
1382 QGLFormat::OpenGL_Version_1_4 |
1383 QGLFormat::OpenGL_Version_1_5 |
1384 QGLFormat::OpenGL_Version_2_0 |
1385 QGLFormat::OpenGL_Version_2_1 |
1386 QGLFormat::OpenGL_Version_3_0 |
1387 QGLFormat::OpenGL_Version_3_1 |
1388 QGLFormat::OpenGL_Version_3_2 |
1389 QGLFormat::OpenGL_Version_3_3 |
1390 QGLFormat::OpenGL_Version_4_0 |
1391 QGLFormat::OpenGL_Version_4_1 |
1392 QGLFormat::OpenGL_Version_4_2 |
1393 QGLFormat::OpenGL_Version_4_3;
1394 }
1395 }
1396 return versionFlags;
1397}
1398
1399/*!
1400 \enum QGLFormat::OpenGLVersionFlag
1401 \since 4.2
1402
1403 This enum describes the various OpenGL versions that are
1404 recognized by Qt. Use the QGLFormat::openGLVersionFlags() function
1405 to identify which versions that are supported at runtime.
1406
1407 \value OpenGL_Version_None If no OpenGL is present or if no OpenGL context is current.
1408
1409 \value OpenGL_Version_1_1 OpenGL version 1.1 or higher is present.
1410
1411 \value OpenGL_Version_1_2 OpenGL version 1.2 or higher is present.
1412
1413 \value OpenGL_Version_1_3 OpenGL version 1.3 or higher is present.
1414
1415 \value OpenGL_Version_1_4 OpenGL version 1.4 or higher is present.
1416
1417 \value OpenGL_Version_1_5 OpenGL version 1.5 or higher is present.
1418
1419 \value OpenGL_Version_2_0 OpenGL version 2.0 or higher is present.
1420 Note that version 2.0 supports all the functionality of version 1.5.
1421
1422 \value OpenGL_Version_2_1 OpenGL version 2.1 or higher is present.
1423
1424 \value OpenGL_Version_3_0 OpenGL version 3.0 or higher is present.
1425
1426 \value OpenGL_Version_3_1 OpenGL version 3.1 or higher is present.
1427 Note that OpenGL version 3.1 or higher does not necessarily support all the features of
1428 version 3.0 and lower.
1429
1430 \value OpenGL_Version_3_2 OpenGL version 3.2 or higher is present.
1431
1432 \value OpenGL_Version_3_3 OpenGL version 3.3 or higher is present.
1433
1434 \value OpenGL_Version_4_0 OpenGL version 4.0 or higher is present.
1435
1436 \value OpenGL_Version_4_1 OpenGL version 4.1 or higher is present.
1437
1438 \value OpenGL_Version_4_2 OpenGL version 4.2 or higher is present.
1439
1440 \value OpenGL_Version_4_3 OpenGL version 4.3 or higher is present.
1441
1442 \value OpenGL_ES_CommonLite_Version_1_0 OpenGL ES version 1.0 Common Lite or higher is present.
1443
1444 \value OpenGL_ES_Common_Version_1_0 OpenGL ES version 1.0 Common or higher is present.
1445 The Common profile supports all the features of Common Lite.
1446
1447 \value OpenGL_ES_CommonLite_Version_1_1 OpenGL ES version 1.1 Common Lite or higher is present.
1448
1449 \value OpenGL_ES_Common_Version_1_1 OpenGL ES version 1.1 Common or higher is present.
1450 The Common profile supports all the features of Common Lite.
1451
1452 \value OpenGL_ES_Version_2_0 OpenGL ES version 2.0 or higher is present.
1453 Note that OpenGL ES version 2.0 does not support all the features of OpenGL ES 1.x.
1454 So if OpenGL_ES_Version_2_0 is returned, none of the ES 1.x flags are returned.
1455
1456 See also \l{http://www.opengl.org} for more information about the different
1457 revisions of OpenGL.
1458
1459 \sa openGLVersionFlags()
1460*/
1461
1462/*!
1463 \since 4.2
1464
1465 Identifies, at runtime, which OpenGL versions that are supported
1466 by the current platform.
1467
1468 Note that if OpenGL version 1.5 is supported, its predecessors
1469 (i.e., version 1.4 and lower) are also supported. To identify the
1470 support of a particular feature, like multi texturing, test for
1471 the version in which the feature was first introduced (i.e.,
1472 version 1.3 in the case of multi texturing) to adapt to the largest
1473 possible group of runtime platforms.
1474
1475 This function needs a valid current OpenGL context to work;
1476 otherwise it will return OpenGL_Version_None.
1477
1478 \sa hasOpenGL(), hasOpenGLOverlays()
1479*/
1480QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
1481{
1482 static bool cachedDefault = false;
1483 static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
1484 QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
1485 QGLTemporaryContext *tmpContext = 0;
1486
1487 if (currentCtx && currentCtx->d_func()->version_flags_cached)
1488 return currentCtx->d_func()->version_flags;
1489
1490 if (!currentCtx) {
1491 if (cachedDefault) {
1492 return defaultVersionFlags;
1493 } else {
1494 if (!hasOpenGL())
1495 return defaultVersionFlags;
1496 tmpContext = new QGLTemporaryContext;
1497 cachedDefault = true;
1498 }
1499 }
1500
1501 QString versionString(QLatin1String(reinterpret_cast<const char*>(qgl_functions()->glGetString(GL_VERSION))));
1502 OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString);
1503 if (currentCtx) {
1504 currentCtx->d_func()->version_flags_cached = true;
1505 currentCtx->d_func()->version_flags = versionFlags;
1506 }
1507 if (tmpContext) {
1508 defaultVersionFlags = versionFlags;
1509 delete tmpContext;
1510 }
1511
1512 return versionFlags;
1513}
1514
1515
1516/*!
1517 Returns the default QGLFormat for the application. All QGLWidget
1518 objects that are created use this format unless another format is
1519 specified, e.g. when they are constructed.
1520
1521 If no special default format has been set using
1522 setDefaultFormat(), the default format is the same as that created
1523 with QGLFormat().
1524
1525 \sa setDefaultFormat()
1526*/
1527
1528QGLFormat QGLFormat::defaultFormat()
1529{
1530 return *qgl_default_format();
1531}
1532
1533/*!
1534 Sets a new default QGLFormat for the application to \a f. For
1535 example, to set single buffering as the default instead of double
1536 buffering, your main() might contain code like this:
1537 \snippet code/src_opengl_qgl.cpp 4
1538
1539 \sa defaultFormat()
1540*/
1541
1542void QGLFormat::setDefaultFormat(const QGLFormat &f)
1543{
1544 *qgl_default_format() = f;
1545}
1546
1547
1548/*!
1549 Returns the default QGLFormat for overlay contexts.
1550
1551 The default overlay format is:
1552 \list
1553 \li \l{setDoubleBuffer()}{Double buffer:} Disabled.
1554 \li \l{setDepth()}{Depth buffer:} Disabled.
1555 \li \l{setRgba()}{RGBA:} Disabled (i.e., color index enabled).
1556 \li \l{setAlpha()}{Alpha channel:} Disabled.
1557 \li \l{setAccum()}{Accumulator buffer:} Disabled.
1558 \li \l{setStencil()}{Stencil buffer:} Disabled.
1559 \li \l{setStereo()}{Stereo:} Disabled.
1560 \li \l{setDirectRendering()}{Direct rendering:} Enabled.
1561 \li \l{setOverlay()}{Overlay:} Disabled.
1562 \li \l{setSampleBuffers()}{Multisample buffers:} Disabled.
1563 \li \l{setPlane()}{Plane:} 1 (i.e., first overlay plane).
1564 \endlist
1565
1566 \sa setDefaultFormat()
1567*/
1568
1569QGLFormat QGLFormat::defaultOverlayFormat()
1570{
1571 return *defaultOverlayFormatInstance();
1572}
1573
1574/*!
1575 Sets a new default QGLFormat for overlay contexts to \a f. This
1576 format is used whenever a QGLWidget is created with a format that
1577 hasOverlay() enabled.
1578
1579 For example, to get a double buffered overlay context (if
1580 available), use code like this:
1581
1582 \snippet code/src_opengl_qgl.cpp 5
1583
1584 As usual, you can find out after widget creation whether the
1585 underlying OpenGL system was able to provide the requested
1586 specification:
1587
1588 \snippet code/src_opengl_qgl.cpp 6
1589
1590 \sa defaultOverlayFormat()
1591*/
1592
1593void QGLFormat::setDefaultOverlayFormat(const QGLFormat &f)
1594{
1595 QGLFormat *defaultFormat = defaultOverlayFormatInstance();
1596 *defaultFormat = f;
1597 // Make sure the user doesn't request that the overlays themselves
1598 // have overlays, since it is unlikely that the system supports
1599 // infinitely many planes...
1600 defaultFormat->setOverlay(false);
1601}
1602
1603
1604/*!
1605 Returns \c true if all the options of the two QGLFormat objects
1606 \a a and \a b are equal; otherwise returns \c false.
1607
1608 \relates QGLFormat
1609*/
1610
1611bool operator==(const QGLFormat& a, const QGLFormat& b)
1612{
1613 return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
1614 && a.d->pln == b.d->pln
1615 && a.d->alphaSize == b.d->alphaSize
1616 && a.d->accumSize == b.d->accumSize
1617 && a.d->stencilSize == b.d->stencilSize
1618 && a.d->depthSize == b.d->depthSize
1619 && a.d->redSize == b.d->redSize
1620 && a.d->greenSize == b.d->greenSize
1621 && a.d->blueSize == b.d->blueSize
1622 && a.d->numSamples == b.d->numSamples
1623 && a.d->swapInterval == b.d->swapInterval
1624 && a.d->majorVersion == b.d->majorVersion
1625 && a.d->minorVersion == b.d->minorVersion
1626 && a.d->profile == b.d->profile);
1627}
1628
1629#ifndef QT_NO_DEBUG_STREAM
1630QDebug operator<<(QDebug dbg, const QGLFormat &f)
1631{
1632 const QGLFormatPrivate * const d = f.d;
1633
1634 QDebugStateSaver saver(dbg);
1635 dbg.nospace() << "QGLFormat("
1636 << "options " << d->opts
1637 << ", plane " << d->pln
1638 << ", depthBufferSize " << d->depthSize
1639 << ", accumBufferSize " << d->accumSize
1640 << ", stencilBufferSize " << d->stencilSize
1641 << ", redBufferSize " << d->redSize
1642 << ", greenBufferSize " << d->greenSize
1643 << ", blueBufferSize " << d->blueSize
1644 << ", alphaBufferSize " << d->alphaSize
1645 << ", samples " << d->numSamples
1646 << ", swapInterval " << d->swapInterval
1647 << ", majorVersion " << d->majorVersion
1648 << ", minorVersion " << d->minorVersion
1649 << ", profile " << d->profile
1650 << ')';
1651
1652 return dbg;
1653}
1654#endif
1655
1656
1657/*!
1658 Returns \c false if all the options of the two QGLFormat objects
1659 \a a and \a b are equal; otherwise returns \c true.
1660
1661 \relates QGLFormat
1662*/
1663
1664bool operator!=(const QGLFormat& a, const QGLFormat& b)
1665{
1666 return !(a == b);
1667}
1668
1669struct QGLContextGroupList {
1670 void append(QGLContextGroup *group) {
1671 QMutexLocker locker(&m_mutex);
1672 m_list.append(group);
1673 }
1674
1675 void remove(QGLContextGroup *group) {
1676 QMutexLocker locker(&m_mutex);
1677 m_list.removeOne(group);
1678 }
1679
1680 QList<QGLContextGroup *> m_list;
1681 QRecursiveMutex m_mutex;
1682};
1683
1684Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups)
1685
1686/*****************************************************************************
1687 QGLContext implementation
1688 *****************************************************************************/
1689
1690QGLContextGroup::QGLContextGroup(const QGLContext *context)
1691 : m_context(context), m_refs(1)
1692{
1693 qt_context_groups()->append(this);
1694}
1695
1696QGLContextGroup::~QGLContextGroup()
1697{
1698 qt_context_groups()->remove(this);
1699}
1700
1701const QGLContext *qt_gl_transfer_context(const QGLContext *ctx)
1702{
1703 if (!ctx)
1704 return 0;
1705 QList<const QGLContext *> shares
1706 (QGLContextPrivate::contextGroup(ctx)->shares());
1707 if (shares.size() >= 2)
1708 return (ctx == shares.at(0)) ? shares.at(1) : shares.at(0);
1709 else
1710 return 0;
1711}
1712
1713QGLContextPrivate::QGLContextPrivate(QGLContext *context)
1714 : internal_context(false)
1715 , q_ptr(context)
1716 , texture_destroyer(0)
1717 , functions(0)
1718{
1719 group = new QGLContextGroup(context);
1720
1721 texture_destroyer = new QGLTextureDestroyer;
1722}
1723
1724QGLContextPrivate::~QGLContextPrivate()
1725{
1726 delete functions;
1727
1728 if (!group->m_refs.deref()) {
1729 Q_ASSERT(group->context() == q_ptr);
1730 delete group;
1731 }
1732
1733 delete texture_destroyer;
1734}
1735
1736void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
1737{
1738 Q_Q(QGLContext);
1739 glFormat = reqFormat = format;
1740 valid = false;
1741 q->setDevice(dev);
1742
1743 guiGlContext = 0;
1744 ownContext = false;
1745 fbo = 0;
1746 crWin = false;
1747 initDone = false;
1748 sharing = false;
1749 max_texture_size = -1;
1750 version_flags_cached = false;
1751 version_flags = QGLFormat::OpenGL_Version_None;
1752 current_fbo = 0;
1753 default_fbo = 0;
1754 active_engine = 0;
1755 workaround_needsFullClearOnEveryFrame = false;
1756 workaround_brokenFBOReadBack = false;
1757 workaround_brokenTexSubImage = false;
1758 workaroundsCached = false;
1759
1760 workaround_brokenTextureFromPixmap = false;
1761 workaround_brokenTextureFromPixmap_init = false;
1762
1763 workaround_brokenAlphaTexSubImage = false;
1764 workaround_brokenAlphaTexSubImage_init = false;
1765
1766 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
1767 vertexAttributeArraysEnabledState[i] = false;
1768}
1769
1770QGLContext* QGLContext::currentCtx = 0;
1771
1772/*
1773 QGLTemporaryContext implementation
1774*/
1775class QGLTemporaryContextPrivate
1776{
1777public:
1778 QWindow *window;
1779 QOpenGLContext *context;
1780
1781 QGLContext *oldContext;
1782};
1783
1784QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
1785 : d(new QGLTemporaryContextPrivate)
1786{
1787 d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext());
1788
1789 d->window = new QWindow;
1790 d->window->setSurfaceType(QWindow::OpenGLSurface);
1791 d->window->setGeometry(QRect(0, 0, 3, 3));
1792 d->window->create();
1793
1794 d->context = new QOpenGLContext;
1795#if !defined(QT_OPENGL_ES)
1796 if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
1797 // On desktop, request latest released version
1798 QSurfaceFormat format;
1799#if defined(Q_OS_MAC)
1800 // OS X is limited to OpenGL 3.2 Core Profile at present
1801 // so set that here. If we use compatibility profile it
1802 // only reports 2.x contexts.
1803 format.setMajorVersion(3);
1804 format.setMinorVersion(2);
1805 format.setProfile(QSurfaceFormat::CoreProfile);
1806#else
1807 format.setMajorVersion(4);
1808 format.setMinorVersion(3);
1809#endif
1810 d->context->setFormat(format);
1811 }
1812#endif // QT_OPENGL_ES
1813 d->context->create();
1814 d->context->makeCurrent(d->window);
1815}
1816
1817QGLTemporaryContext::~QGLTemporaryContext()
1818{
1819 if (d->oldContext)
1820 d->oldContext->makeCurrent();
1821
1822 delete d->context;
1823 delete d->window;
1824}
1825
1826/*
1827 Read back the contents of the currently bound framebuffer, used in
1828 QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
1829 QGLFramebufferObject::toImage()
1830*/
1831
1832static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
1833{
1834 Q_ASSERT(!img.isNull());
1835 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1836 // OpenGL gives RGBA; Qt wants ARGB
1837 uint *p = (uint*)img.bits();
1838 uint *end = p + w*h;
1839 if (alpha_format && include_alpha) {
1840 while (p < end) {
1841 uint a = *p << 24;
1842 *p = (*p >> 8) | a;
1843 p++;
1844 }
1845 } else {
1846 // This is an old legacy fix for PowerPC based Macs, which
1847 // we shouldn't remove
1848 while (p < end) {
1849 *p = 0xff000000 | (*p>>8);
1850 ++p;
1851 }
1852 }
1853 } else {
1854 // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
1855 for (int y = 0; y < h; y++) {
1856 uint *q = (uint*)img.scanLine(y);
1857 for (int x=0; x < w; ++x) {
1858 const uint pixel = *q;
1859 if (alpha_format && include_alpha) {
1860 *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff)
1861 | (pixel & 0xff00ff00);
1862 } else {
1863 *q = 0xff000000 | ((pixel << 16) & 0xff0000)
1864 | ((pixel >> 16) & 0xff) | (pixel & 0x00ff00);
1865 }
1866
1867 q++;
1868 }
1869 }
1870
1871 }
1872 img = img.mirrored();
1873}
1874
1875QImage qt_gl_read_frame_buffer(const QSize &size, bool alpha_format, bool include_alpha)
1876{
1877 QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied
1878 : QImage::Format_RGB32);
1879 if (img.isNull())
1880 return QImage();
1881 int w = size.width();
1882 int h = size.height();
1883 qgl_functions()->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1884 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1885 return img;
1886}
1887
1888QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
1889{
1890 QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
1891 if (img.isNull())
1892 return QImage();
1893 int w = size.width();
1894 int h = size.height();
1895#ifndef QT_OPENGL_ES
1896 if (!QOpenGLContext::currentContext()->isOpenGLES()) {
1897
1898 qgl1_functions()->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
1899 }
1900#endif // QT_OPENGL_ES
1901 convertFromGLImage(img, w, h, alpha_format, include_alpha);
1902 return img;
1903}
1904
1905Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache)
1906
1907QGLTextureCache::QGLTextureCache()
1908 : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though
1909{
1910 QImagePixmapCleanupHooks::instance()->addPlatformPixmapModificationHook(cleanupTexturesForPixampData);
1911 QImagePixmapCleanupHooks::instance()->addPlatformPixmapDestructionHook(cleanupBeforePixmapDestruction);
1912 QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);
1913}
1914
1915QGLTextureCache::~QGLTextureCache()
1916{
1917 QImagePixmapCleanupHooks::instance()->removePlatformPixmapModificationHook(cleanupTexturesForPixampData);
1918 QImagePixmapCleanupHooks::instance()->removePlatformPixmapDestructionHook(cleanupBeforePixmapDestruction);
1919 QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
1920}
1921
1922void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
1923{
1924 QWriteLocker locker(&m_lock);
1925 const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
1926 const bool inserted = m_cache.insert(cacheKey, texture, cost);
1927 Q_UNUSED(inserted) Q_ASSERT(inserted);
1928}
1929
1930void QGLTextureCache::remove(qint64 key)
1931{
1932 QWriteLocker locker(&m_lock);
1933 QMutexLocker groupLocker(&qt_context_groups()->m_mutex);
1934 QList<QGLContextGroup *>::const_iterator it = qt_context_groups()->m_list.constBegin();
1935 while (it != qt_context_groups()->m_list.constEnd()) {
1936 const QGLTextureCacheKey cacheKey = {key, *it};
1937 m_cache.remove(cacheKey);
1938 ++it;
1939 }
1940}
1941
1942bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
1943{
1944 QWriteLocker locker(&m_lock);
1945 QList<QGLTextureCacheKey> keys = m_cache.keys();
1946 for (int i = 0; i < keys.size(); ++i) {
1947 QGLTexture *tex = m_cache.object(keys.at(i));
1948 if (tex->id == textureId && tex->context == ctx) {
1949 tex->options |= QGLContext::MemoryManagedBindOption; // forces a glDeleteTextures() call
1950 m_cache.remove(keys.at(i));
1951 return true;
1952 }
1953 }
1954 return false;
1955}
1956
1957void QGLTextureCache::removeContextTextures(QGLContext* ctx)
1958{
1959 QWriteLocker locker(&m_lock);
1960 QList<QGLTextureCacheKey> keys = m_cache.keys();
1961 for (int i = 0; i < keys.size(); ++i) {
1962 const QGLTextureCacheKey &key = keys.at(i);
1963 if (m_cache.object(key)->context == ctx)
1964 m_cache.remove(key);
1965 }
1966}
1967
1968/*
1969 a hook that removes textures from the cache when a pixmap/image
1970 is deref'ed
1971*/
1972void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
1973{
1974 qt_gl_texture_cache()->remove(cacheKey);
1975}
1976
1977
1978void QGLTextureCache::cleanupTexturesForPixampData(QPlatformPixmap* pmd)
1979{
1980 cleanupTexturesForCacheKey(pmd->cacheKey());
1981}
1982
1983void QGLTextureCache::cleanupBeforePixmapDestruction(QPlatformPixmap* pmd)
1984{
1985 // Remove any bound textures first:
1986 cleanupTexturesForPixampData(pmd);
1987}
1988
1989QGLTextureCache *QGLTextureCache::instance()
1990{
1991 return qt_gl_texture_cache();
1992}
1993
1994// DDS format structure
1995struct DDSFormat {
1996 quint32 dwSize;
1997 quint32 dwFlags;
1998 quint32 dwHeight;
1999 quint32 dwWidth;
2000 quint32 dwLinearSize;
2001 quint32 dummy1;
2002 quint32 dwMipMapCount;
2003 quint32 dummy2[11];
2004 struct {
2005 quint32 dummy3[2];
2006 quint32 dwFourCC;
2007 quint32 dummy4[5];
2008 } ddsPixelFormat;
2009};
2010
2011// compressed texture pixel formats
2012#define FOURCC_DXT1 0x31545844
2013#define FOURCC_DXT2 0x32545844
2014#define FOURCC_DXT3 0x33545844
2015#define FOURCC_DXT4 0x34545844
2016#define FOURCC_DXT5 0x35545844
2017
2018// ####TODO Properly #ifdef this class to use #define symbols actually defined
2019// by system GL includes
2020#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
2021#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
2022#endif
2023
2024#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2025#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
2026#endif
2027
2028#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2029#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
2030#endif
2031
2032#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
2033#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
2034#endif
2035
2036#ifndef GL_GENERATE_MIPMAP_SGIS
2037#define GL_GENERATE_MIPMAP_SGIS 0x8191
2038#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
2039#endif
2040
2041/*!
2042 \class QGLContext
2043 \inmodule QtOpenGL
2044 \obsolete
2045
2046 \brief The QGLContext class encapsulates an OpenGL rendering context.
2047
2048 An OpenGL rendering context is a complete set of OpenGL state
2049 variables. The rendering context's \l {QGL::FormatOption} {format}
2050 is set in the constructor, but it can also be set later with
2051 setFormat(). The format options that are actually set are returned
2052 by format(); the options you asked for are returned by
2053 requestedFormat(). Note that after a QGLContext object has been
2054 constructed, the actual OpenGL context must be created by
2055 explicitly calling the \l{create()}
2056 function. The makeCurrent() function makes this context the
2057 current rendering context. You can make \e no context current
2058 using doneCurrent(). The reset() function will reset the context
2059 and make it invalid.
2060
2061 You can examine properties of the context with, e.g. isValid(),
2062 isSharing(), initialized(), windowCreated() and
2063 overlayTransparentColor().
2064
2065 If you're using double buffering you can swap the screen contents
2066 with the off-screen buffer using swapBuffers().
2067
2068 Please note that QGLContext is not thread safe.
2069*/
2070
2071/*!
2072 \enum QGLContext::BindOption
2073 \since 4.6
2074
2075 A set of options to decide how to bind a texture using bindTexture().
2076
2077 \value NoBindOption Don't do anything, pass the texture straight
2078 through.
2079
2080 \value InvertedYBindOption Specifies that the texture should be flipped
2081 over the X axis so that the texture coordinate 0,0 corresponds to
2082 the top left corner. Inverting the texture implies a deep copy
2083 prior to upload.
2084
2085 \value MipmapBindOption Specifies that bindTexture() should try
2086 to generate mipmaps. If the GL implementation supports the \c
2087 GL_SGIS_generate_mipmap extension, mipmaps will be automatically
2088 generated for the texture. Mipmap generation is only supported for
2089 the \c GL_TEXTURE_2D target.
2090
2091 \value PremultipliedAlphaBindOption Specifies that the image should be
2092 uploaded with premultiplied alpha and does a conversion accordingly.
2093
2094 \value LinearFilteringBindOption Specifies that the texture filtering
2095 should be set to GL_LINEAR. Default is GL_NEAREST. If mipmap is
2096 also enabled, filtering will be set to GL_LINEAR_MIPMAP_LINEAR.
2097
2098 \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
2099 would mirror the image and automatically generate mipmaps. This
2100 option helps preserve this default behavior.
2101
2102 \omitvalue CanFlipNativePixmapBindOption \omit Used by x11 from pixmap to choose
2103 whether or not it can bind the pixmap upside down or not. \endomit
2104
2105 \omitvalue MemoryManagedBindOption \omit Used by paint engines to
2106 indicate that the pixmap should be memory managed along side with
2107 the pixmap/image that it stems from, e.g. installing destruction
2108 hooks in them. \endomit
2109
2110 \omitvalue TemporarilyCachedBindOption \omit Used by paint engines on some
2111 platforms to indicate that the pixmap or image texture is possibly
2112 cached only temporarily and must be destroyed immediately after the use. \endomit
2113
2114 \omitvalue InternalBindOption
2115*/
2116
2117/*!
2118 \obsolete
2119
2120 Constructs an OpenGL context for the given paint \a device, which
2121 can be a widget or a pixmap. The \a format specifies several
2122 display options for the context.
2123
2124 If the underlying OpenGL/Window system cannot satisfy all the
2125 features requested in \a format, the nearest subset of features
2126 will be used. After creation, the format() method will return the
2127 actual format obtained.
2128
2129 Note that after a QGLContext object has been constructed, \l
2130 create() must be called explicitly to create the actual OpenGL
2131 context. The context will be \l {isValid()}{invalid} if it was not
2132 possible to obtain a GL context at all.
2133*/
2134
2135QGLContext::QGLContext(const QGLFormat &format, QPaintDevice *device)
2136 : d_ptr(new QGLContextPrivate(this))
2137{
2138 Q_D(QGLContext);
2139 d->init(device, format);
2140}
2141
2142/*!
2143 Constructs an OpenGL context with the given \a format which
2144 specifies several display options for the context.
2145
2146 If the underlying OpenGL/Window system cannot satisfy all the
2147 features requested in \a format, the nearest subset of features
2148 will be used. After creation, the format() method will return the
2149 actual format obtained.
2150
2151 Note that after a QGLContext object has been constructed, \l
2152 create() must be called explicitly to create the actual OpenGL
2153 context. The context will be \l {isValid()}{invalid} if it was not
2154 possible to obtain a GL context at all.
2155
2156 \sa format(), isValid()
2157*/
2158QGLContext::QGLContext(const QGLFormat &format)
2159 : d_ptr(new QGLContextPrivate(this))
2160{
2161 Q_D(QGLContext);
2162 d->init(0, format);
2163}
2164
2165static void qDeleteQGLContext(void *handle)
2166{
2167 QGLContext *context = static_cast<QGLContext *>(handle);
2168 delete context;
2169}
2170
2171QGLContext::QGLContext(QOpenGLContext *context)
2172 : d_ptr(new QGLContextPrivate(this))
2173{
2174 Q_D(QGLContext);
2175 d->init(0, QGLFormat::fromSurfaceFormat(context->format()));
2176 d->guiGlContext = context;
2177 d->guiGlContext->setQGLContextHandle(this, qDeleteQGLContext);
2178 d->ownContext = false;
2179 d->valid = context->isValid();
2180 d->setupSharing();
2181}
2182
2183/*!
2184 Returns the OpenGL context handle.
2185*/
2186QOpenGLContext *QGLContext::contextHandle() const
2187{
2188 Q_D(const QGLContext);
2189 return d->guiGlContext;
2190}
2191
2192/*!
2193 Returns an OpenGL context for the window context specified by the \a context
2194 parameter.
2195*/
2196QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context)
2197{
2198 if (!context)
2199 return 0;
2200 if (context->qGLContextHandle()) {
2201 return reinterpret_cast<QGLContext *>(context->qGLContextHandle());
2202 }
2203 QGLContext *glContext = new QGLContext(context);
2204 //Don't call create on context. This can cause the platformFormat to be set on the widget, which
2205 //will cause the platformWindow to be recreated.
2206 return glContext;
2207}
2208
2209/*!
2210 Destroys the OpenGL context and frees its resources.
2211*/
2212
2213QGLContext::~QGLContext()
2214{
2215 // remove any textures cached in this context
2216 QGLTextureCache::instance()->removeContextTextures(this);
2217
2218 // clean up resources specific to this context
2219 d_ptr->cleanup();
2220
2221 QGLSignalProxy::instance()->emitAboutToDestroyContext(this);
2222 reset();
2223}
2224
2225void QGLContextPrivate::cleanup()
2226{
2227}
2228
2229#define ctx q_ptr
2230void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled)
2231{
2232 Q_Q(QGLContext);
2233 Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT);
2234#ifdef glEnableVertexAttribArray
2235 Q_ASSERT(glEnableVertexAttribArray);
2236#endif
2237
2238 if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled)
2239 q->functions()->glDisableVertexAttribArray(arrayIndex);
2240
2241 if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled)
2242 q->functions()->glEnableVertexAttribArray(arrayIndex);
2243
2244 vertexAttributeArraysEnabledState[arrayIndex] = enabled;
2245}
2246
2247void QGLContextPrivate::syncGlState()
2248{
2249 Q_Q(QGLContext);
2250#ifdef glEnableVertexAttribArray
2251 Q_ASSERT(glEnableVertexAttribArray);
2252#endif
2253 for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) {
2254 if (vertexAttributeArraysEnabledState[i])
2255 q->functions()->glEnableVertexAttribArray(i);
2256 else
2257 q->functions()->glDisableVertexAttribArray(i);
2258 }
2259
2260}
2261#undef ctx
2262
2263void QGLContextPrivate::swapRegion(const QRegion &)
2264{
2265 Q_Q(QGLContext);
2266 q->swapBuffers();
2267}
2268
2269/*!
2270 \overload
2271
2272 Reads the compressed texture file \a fileName and generates a 2D GL
2273 texture from it.
2274
2275 This function can load DirectDrawSurface (DDS) textures in the
2276 DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression
2277 and \c GL_EXT_texture_compression_s3tc extensions are supported.
2278
2279 Since 4.6.1, textures in the ETC1 format can be loaded if the
2280 \c GL_OES_compressed_ETC1_RGB8_texture extension is supported
2281 and the ETC1 texture has been encapsulated in the PVR container format.
2282 Also, textures in the PVRTC2 and PVRTC4 formats can be loaded
2283 if the \c GL_IMG_texture_compression_pvrtc extension is supported.
2284
2285 \sa deleteTexture()
2286*/
2287
2288GLuint QGLContext::bindTexture(const QString &fileName)
2289{
2290 QGLTexture texture(this);
2291 QSize size = texture.bindCompressedTexture(fileName);
2292 if (!size.isValid())
2293 return 0;
2294 return texture.id;
2295}
2296
2297static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
2298{
2299 if (texture_format == GL_BGRA) {
2300 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2301 return ((src_pixel << 24) & 0xff000000)
2302 | ((src_pixel >> 24) & 0x000000ff)
2303 | ((src_pixel << 8) & 0x00ff0000)
2304 | ((src_pixel >> 8) & 0x0000ff00);
2305 } else {
2306 return src_pixel;
2307 }
2308 } else { // GL_RGBA
2309 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2310 return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
2311 } else {
2312 return ((src_pixel << 16) & 0xff0000)
2313 | ((src_pixel >> 16) & 0xff)
2314 | (src_pixel & 0xff00ff00);
2315 }
2316 }
2317}
2318
2319static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format)
2320{
2321 Q_ASSERT(dst.depth() == 32);
2322 Q_ASSERT(img.depth() == 32);
2323
2324 if (dst.size() != img.size()) {
2325 int target_width = dst.width();
2326 int target_height = dst.height();
2327 qreal sx = target_width / qreal(img.width());
2328 qreal sy = target_height / qreal(img.height());
2329
2330 quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here
2331 const uchar *srcPixels = img.constScanLine(img.height() - 1);
2332 int sbpl = img.bytesPerLine();
2333 int dbpl = dst.bytesPerLine();
2334
2335 int ix = int(0x00010000 / sx);
2336 int iy = int(0x00010000 / sy);
2337
2338 quint32 basex = int(0.5 * ix);
2339 quint32 srcy = int(0.5 * iy);
2340
2341 // scale, swizzle and mirror in one loop
2342 while (target_height--) {
2343 const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
2344 int srcx = basex;
2345 for (int x=0; x<target_width; ++x) {
2346 dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format);
2347 srcx += ix;
2348 }
2349 dest = (quint32 *)(((uchar *) dest) + dbpl);
2350 srcy += iy;
2351 }
2352 } else {
2353 const int width = img.width();
2354 const int height = img.height();
2355 const uint *p = (const uint*) img.scanLine(img.height() - 1);
2356 uint *q = (uint*) dst.scanLine(0);
2357
2358 if (texture_format == GL_BGRA) {
2359 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2360 // mirror + swizzle
2361 for (int i=0; i < height; ++i) {
2362 const uint *end = p + width;
2363 while (p < end) {
2364 *q = ((*p << 24) & 0xff000000)
2365 | ((*p >> 24) & 0x000000ff)
2366 | ((*p << 8) & 0x00ff0000)
2367 | ((*p >> 8) & 0x0000ff00);
2368 p++;
2369 q++;
2370 }
2371 p -= 2 * width;
2372 }
2373 } else {
2374 const uint bytesPerLine = img.bytesPerLine();
2375 for (int i=0; i < height; ++i) {
2376 memcpy(q, p, bytesPerLine);
2377 q += width;
2378 p -= width;
2379 }
2380 }
2381 } else {
2382 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
2383 for (int i=0; i < height; ++i) {
2384 const uint *end = p + width;
2385 while (p < end) {
2386 *q = (*p << 8) | ((*p >> 24) & 0xff);
2387 p++;
2388 q++;
2389 }
2390 p -= 2 * width;
2391 }
2392 } else {
2393 for (int i=0; i < height; ++i) {
2394 const uint *end = p + width;
2395 while (p < end) {
2396 *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
2397 p++;
2398 q++;
2399 }
2400 p -= 2 * width;
2401 }
2402 }
2403 }
2404 }
2405}
2406
2407/*! \internal */
2408QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
2409 QGLContext::BindOptions options)
2410{
2411 Q_Q(QGLContext);
2412
2413 const qint64 key = image.cacheKey();
2414 QGLTexture *texture = textureCacheLookup(key, target);
2415 if (texture) {
2416 if (image.paintingActive()) {
2417 // A QPainter is active on the image - take the safe route and replace the texture.
2418 q->deleteTexture(texture->id);
2419 texture = 0;
2420 } else {
2421 qgl_functions()->glBindTexture(target, texture->id);
2422 return texture;
2423 }
2424 }
2425
2426 if (!texture)
2427 texture = bindTexture(image, target, format, key, options);
2428 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
2429 Q_ASSERT(texture);
2430
2431 // Enable the cleanup hooks for this image so that the texture cache entry is removed when the
2432 // image gets deleted:
2433 QImagePixmapCleanupHooks::enableCleanupHooks(image);
2434
2435 return texture;
2436}
2437
2438// #define QGL_BIND_TEXTURE_DEBUG
2439
2440// ####TODO Properly #ifdef this file to use #define symbols actually defined
2441// by OpenGL/ES includes
2442#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
2443#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
2444#endif
2445
2446// map from Qt's ARGB endianness-dependent format to GL's big-endian RGBA layout
2447static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
2448{
2449 const int width = img.width();
2450 const int height = img.height();
2451
2452 if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
2453 || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
2454 {
2455 for (int i = 0; i < height; ++i) {
2456 uint *p = (uint *) img.scanLine(i);
2457 for (int x = 0; x < width; ++x)
2458 p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
2459 }
2460 } else {
2461 for (int i = 0; i < height; ++i) {
2462 uint *p = (uint *) img.scanLine(i);
2463 for (int x = 0; x < width; ++x)
2464 p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
2465 }
2466 }
2467}
2468
2469QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat,
2470 const qint64 key, QGLContext::BindOptions options)
2471{
2472 Q_Q(QGLContext);
2473 QOpenGLFunctions *funcs = qgl_functions();
2474
2475#ifdef QGL_BIND_TEXTURE_DEBUG
2476 printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x, key=%llx\n",
2477 image.width(), image.height(), internalFormat, int(options), key);
2478 QTime time;
2479 time.start();
2480#endif
2481
2482#ifndef QT_NO_DEBUG
2483 // Reset the gl error stack...git
2484 while (funcs->glGetError() != GL_NO_ERROR) ;
2485#endif
2486
2487 // Scale the pixmap if needed. GL textures needs to have the
2488 // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
2489 // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
2490 int tx_w = qNextPowerOfTwo(image.width() - 1);
2491 int tx_h = qNextPowerOfTwo(image.height() - 1);
2492
2493 QImage img = image;
2494
2495 if (!qgl_extensions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)
2496 && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
2497 && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
2498 {
2499 img = img.scaled(tx_w, tx_h);
2500#ifdef QGL_BIND_TEXTURE_DEBUG
2501 printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed());
2502
2503#endif
2504 }
2505
2506 GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST;
2507
2508 GLuint tx_id;
2509 funcs->glGenTextures(1, &tx_id);
2510 funcs->glBindTexture(target, tx_id);
2511 funcs->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filtering);
2512
2513 QOpenGLContext *ctx = QOpenGLContext::currentContext();
2514 bool genMipmap = !ctx->isOpenGLES();
2515 if (glFormat.directRendering()
2516 && (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::GenerateMipmap))
2517 && target == GL_TEXTURE_2D
2518 && (options & QGLContext::MipmapBindOption))
2519 {
2520#if !defined(QT_OPENGL_ES_2)
2521 if (genMipmap) {
2522 funcs->glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
2523 funcs->glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
2524 } else {
2525 funcs->glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
2526 genMipmap = true;
2527 }
2528#else
2529 funcs->glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
2530 genMipmap = true;
2531#endif
2532 funcs->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
2533 ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
2534#ifdef QGL_BIND_TEXTURE_DEBUG
2535 printf(" - generating mipmaps (%d ms)\n", time.elapsed());
2536#endif
2537 } else {
2538 funcs->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filtering);
2539 }
2540
2541 QImage::Format target_format = img.format();
2542 bool premul = options & QGLContext::PremultipliedAlphaBindOption;
2543 bool needsbyteswap = true;
2544 GLenum externalFormat;
2545 GLuint pixel_type;
2546 if (target_format == QImage::Format_RGBA8888
2547 || target_format == QImage::Format_RGBA8888_Premultiplied
2548 || target_format == QImage::Format_RGBX8888) {
2549 externalFormat = GL_RGBA;
2550 pixel_type = GL_UNSIGNED_BYTE;
2551 needsbyteswap = false;
2552 } else if (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat)) {
2553 externalFormat = GL_BGRA;
2554 needsbyteswap = false;
2555 if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
2556 pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
2557 else
2558 pixel_type = GL_UNSIGNED_BYTE;
2559 } else {
2560 externalFormat = GL_RGBA;
2561 pixel_type = GL_UNSIGNED_BYTE;
2562 }
2563
2564 switch (target_format) {
2565 case QImage::Format_ARGB32:
2566 if (premul) {
2567 img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
2568#ifdef QGL_BIND_TEXTURE_DEBUG
2569 printf(" - converted ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
2570#endif
2571 }
2572 break;
2573 case QImage::Format_ARGB32_Premultiplied:
2574 if (!premul) {
2575 img = img.convertToFormat(target_format = QImage::Format_ARGB32);
2576#ifdef QGL_BIND_TEXTURE_DEBUG
2577 printf(" - converted ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
2578#endif
2579 }
2580 break;
2581 case QImage::Format_RGBA8888:
2582 if (premul) {
2583 img = img.convertToFormat(target_format = QImage::Format_RGBA8888_Premultiplied);
2584#ifdef QGL_BIND_TEXTURE_DEBUG
2585 printf(" - converted RGBA8888 -> RGBA8888_Premultiplied (%d ms) \n", time.elapsed());
2586#endif
2587 }
2588 break;
2589 case QImage::Format_RGBA8888_Premultiplied:
2590 if (!premul) {
2591 img = img.convertToFormat(target_format = QImage::Format_RGBA8888);
2592#ifdef QGL_BIND_TEXTURE_DEBUG
2593 printf(" - converted RGBA8888_Premultiplied -> RGBA8888 (%d ms) \n", time.elapsed());
2594#endif
2595 }
2596 break;
2597 case QImage::Format_RGB16:
2598 pixel_type = GL_UNSIGNED_SHORT_5_6_5;
2599 externalFormat = GL_RGB;
2600 internalFormat = GL_RGB;
2601 needsbyteswap = false;
2602 break;
2603 case QImage::Format_RGB32:
2604 case QImage::Format_RGBX8888:
2605 break;
2606 default:
2607 // Ideally more formats would be converted directly to an RGBA8888 format,
2608 // but we are only guaranteed to have a fast conversion to an ARGB format.
2609 if (img.hasAlphaChannel()) {
2610 img = img.convertToFormat(premul
2611 ? QImage::Format_ARGB32_Premultiplied
2612 : QImage::Format_ARGB32);
2613#ifdef QGL_BIND_TEXTURE_DEBUG
2614 printf(" - converted to 32-bit alpha format (%d ms)\n", time.elapsed());
2615#endif
2616 } else {
2617 img = img.convertToFormat(QImage::Format_RGB32);
2618#ifdef QGL_BIND_TEXTURE_DEBUG
2619 printf(" - converted to 32-bit (%d ms)\n", time.elapsed());
2620#endif
2621 }
2622 }
2623
2624 if (options & QGLContext::InvertedYBindOption) {
2625 if (img.isDetached()) {
2626 int ipl = img.bytesPerLine() / 4;
2627 int h = img.height();
2628 for (int y=0; y<h/2; ++y) {
2629 int *a = (int *) img.scanLine(y);
2630 int *b = (int *) img.scanLine(h - y - 1);
2631 for (int x=0; x<ipl; ++x)
2632 qSwap(a[x], b[x]);
2633 }
2634 } else {
2635 // Create a new image and copy across. If we use the
2636 // above in-place code then a full copy of the image is
2637 // made before the lines are swapped, which processes the
2638 // data twice. This version should only do it once.
2639 img = img.mirrored();
2640 }
2641#ifdef QGL_BIND_TEXTURE_DEBUG
2642 printf(" - flipped bits over y (%d ms)\n", time.elapsed());
2643#endif
2644 }
2645
2646 if (needsbyteswap) {
2647 // The only case where we end up with a depth different from
2648 // 32 in the switch above is for the RGB16 case, where we do
2649 // not need a byteswap.
2650 Q_ASSERT(img.depth() == 32);
2651 qgl_byteSwapImage(img, pixel_type);
2652#ifdef QGL_BIND_TEXTURE_DEBUG
2653 printf(" - did byte swapping (%d ms)\n", time.elapsed());
2654#endif
2655 }
2656 if (ctx->isOpenGLES()) {
2657 // OpenGL/ES requires that the internal and external formats be
2658 // identical.
2659 internalFormat = externalFormat;
2660 }
2661#ifdef QGL_BIND_TEXTURE_DEBUG
2662 printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
2663 img.format(), externalFormat, internalFormat, pixel_type);
2664#endif
2665
2666 const QImage &constRef = img; // to avoid detach in bits()...
2667 funcs->glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
2668 pixel_type, constRef.bits());
2669 if (genMipmap && ctx->isOpenGLES())
2670 q->functions()->glGenerateMipmap(target);
2671#ifndef QT_NO_DEBUG
2672 GLenum error = funcs->glGetError();
2673 if (error != GL_NO_ERROR) {
2674 qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target);
2675 }
2676#endif
2677
2678#ifdef QGL_BIND_TEXTURE_DEBUG
2679 static int totalUploadTime = 0;
2680 totalUploadTime += time.elapsed();
2681 printf(" - upload done in %d ms, (accumulated: %d ms)\n", time.elapsed(), totalUploadTime);
2682#endif
2683
2684
2685 // this assumes the size of a texture is always smaller than the max cache size
2686 int cost = img.width()*img.height()*4/1024;
2687 QGLTexture *texture = new QGLTexture(q, tx_id, target, options);
2688 QGLTextureCache::instance()->insert(q, key, texture, cost);
2689
2690 return texture;
2691}
2692
2693QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target)
2694{
2695 Q_Q(QGLContext);
2696 QGLTexture *texture = QGLTextureCache::instance()->getTexture(q, key);
2697 if (texture && texture->target == target
2698 && (texture->context == q || QGLContext::areSharing(q, texture->context)))
2699 {
2700 return texture;
2701 }
2702 return 0;
2703}
2704
2705/*! \internal */
2706QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options)
2707{
2708 Q_Q(QGLContext);
2709 QPlatformPixmap *pd = pixmap.handle();
2710 Q_UNUSED(pd);
2711
2712 const qint64 key = pixmap.cacheKey();
2713 QGLTexture *texture = textureCacheLookup(key, target);
2714 if (texture) {
2715 if (pixmap.paintingActive()) {
2716 // A QPainter is active on the pixmap - take the safe route and replace the texture.
2717 q->deleteTexture(texture->id);
2718 texture = 0;
2719 } else {
2720 qgl_functions()->glBindTexture(target, texture->id);
2721 return texture;
2722 }
2723 }
2724
2725 if (!texture) {
2726 QImage image;
2727 QPaintEngine* paintEngine = pixmap.paintEngine();
2728 if (!paintEngine || paintEngine->type() != QPaintEngine::Raster)
2729 image = pixmap.toImage();
2730 else {
2731 // QRasterPixmapData::toImage() will deep-copy the backing QImage if there's an active QPainter on it.
2732 // For performance reasons, we don't want that here, so we temporarily redirect the paint engine.
2733 QPaintDevice* currentPaintDevice = paintEngine->paintDevice();
2734 paintEngine->setPaintDevice(0);
2735 image = pixmap.toImage();
2736 paintEngine->setPaintDevice(currentPaintDevice);
2737 }
2738
2739 // If the system depth is 16 and the pixmap doesn't have an alpha channel
2740 // then we convert it to RGB16 in the hope that it gets uploaded as a 16
2741 // bit texture which is much faster to access than a 32-bit one.
2742 if (pixmap.depth() == 16 && !image.hasAlphaChannel() )
2743 image = image.convertToFormat(QImage::Format_RGB16);
2744 texture = bindTexture(image, target, format, key, options);
2745 }
2746 // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
2747 Q_ASSERT(texture);
2748
2749 if (texture->id > 0)
2750 QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
2751
2752 return texture;
2753}
2754
2755/*! \internal */
2756int QGLContextPrivate::maxTextureSize()
2757{
2758 if (max_texture_size != -1)
2759 return max_texture_size;
2760
2761 QOpenGLFunctions *funcs = qgl_functions();
2762 funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
2763
2764#ifndef QT_OPENGL_ES
2765 Q_Q(QGLContext);
2766 if (!q->contextHandle()->isOpenGLES()) {
2767 GLenum proxy = GL_PROXY_TEXTURE_2D;
2768
2769 GLint size;
2770 GLint next = 64;
2771 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2772 QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
2773 gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
2774 if (size == 0) {
2775 return max_texture_size;
2776 }
2777 do {
2778 size = next;
2779 next = size * 2;
2780
2781 if (next > max_texture_size)
2782 break;
2783 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
2784 gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
2785 } while (next > size);
2786
2787 max_texture_size = size;
2788 }
2789#endif
2790
2791 return max_texture_size;
2792}
2793
2794/*!
2795 Returns a QGLFunctions object that is initialized for this context.
2796 */
2797QGLFunctions *QGLContext::functions() const
2798{
2799 QGLContextPrivate *d = const_cast<QGLContextPrivate *>(d_func());
2800 if (!d->functions) {
2801 d->functions = new QGLFunctions(this);
2802 d->functions->initializeGLFunctions(this);
2803 }
2804 return d->functions;
2805}
2806
2807/*!
2808 Generates and binds a 2D GL texture to the current context, based
2809 on \a image. The generated texture id is returned and can be used in
2810 later \c glBindTexture() calls.
2811
2812 \overload
2813*/
2814GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
2815{
2816 if (image.isNull())
2817 return 0;
2818
2819 Q_D(QGLContext);
2820 QGLTexture *texture = d->bindTexture(image, target, format, DefaultBindOption);
2821 return texture->id;
2822}
2823
2824/*!
2825 \since 4.6
2826
2827 Generates and binds a 2D GL texture to the current context, based
2828 on \a image. The generated texture id is returned and can be used
2829 in later \c glBindTexture() calls.
2830
2831 The \a target parameter specifies the texture target. The default
2832 target is \c GL_TEXTURE_2D.
2833
2834 The \a format parameter sets the internal format for the
2835 texture. The default format is \c GL_RGBA.
2836
2837 The binding \a options are a set of options used to decide how to
2838 bind the texture to the context.
2839
2840 The texture that is generated is cached, so multiple calls to
2841 bindTexture() with the same QImage will return the same texture
2842 id.
2843
2844 Note that we assume default values for the glPixelStore() and
2845 glPixelTransfer() parameters.
2846
2847 \sa deleteTexture()
2848*/
2849GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
2850{
2851 if (image.isNull())
2852 return 0;
2853
2854 Q_D(QGLContext);
2855 QGLTexture *texture = d->bindTexture(image, target, format, options);
2856 return texture->id;
2857}
2858
2859/*! \overload
2860
2861 Generates and binds a 2D GL texture based on \a pixmap.
2862*/
2863GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
2864{
2865 if (pixmap.isNull())
2866 return 0;
2867
2868 Q_D(QGLContext);
2869 QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
2870 return texture->id;
2871}
2872
2873/*!
2874 \overload
2875 \since 4.6
2876
2877 Generates and binds a 2D GL texture to the current context, based
2878 on \a pixmap.
2879*/
2880GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
2881{
2882 if (pixmap.isNull())
2883 return 0;
2884
2885 Q_D(QGLContext);
2886 QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
2887 return texture->id;
2888}
2889
2890/*!
2891 Removes the texture identified by \a id from the texture cache,
2892 and calls glDeleteTextures() to delete the texture from the
2893 context.
2894
2895 \sa bindTexture()
2896*/
2897void QGLContext::deleteTexture(GLuint id)
2898{
2899 if (QGLTextureCache::instance()->remove(this, id))
2900 return;
2901 qgl_functions()->glDeleteTextures(1, &id);
2902}
2903
2904void qt_add_rect_to_array(const QRectF &r, GLfloat *array)
2905{
2906 qreal left = r.left();
2907 qreal right = r.right();
2908 qreal top = r.top();
2909 qreal bottom = r.bottom();
2910
2911 array[0] = left;
2912 array[1] = top;
2913 array[2] = right;
2914 array[3] = top;
2915 array[4] = right;
2916 array[5] = bottom;
2917 array[6] = left;
2918 array[7] = bottom;
2919}
2920
2921void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *array)
2922{
2923 array[0] = x1;
2924 array[1] = y1;
2925 array[2] = x2;
2926 array[3] = y1;
2927 array[4] = x2;
2928 array[5] = y2;
2929 array[6] = x1;
2930 array[7] = y2;
2931}
2932
2933#if !defined(QT_OPENGL_ES_2)
2934
2935static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
2936{
2937 QOpenGLFunctions *funcs = qgl_functions();
2938 GLfloat tx = 1.0f;
2939 GLfloat ty = 1.0f;
2940
2941#ifdef QT_OPENGL_ES
2942 Q_UNUSED(textureWidth);
2943 Q_UNUSED(textureHeight);
2944 Q_UNUSED(textureTarget);
2945#else
2946 if (textureTarget != GL_TEXTURE_2D && !QOpenGLContext::currentContext()->isOpenGLES()) {
2947 if (textureWidth == -1 || textureHeight == -1) {
2948 QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
2949 gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
2950 gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
2951 }
2952
2953 tx = GLfloat(textureWidth);
2954 ty = GLfloat(textureHeight);
2955 }
2956#endif
2957
2958 GLfloat texCoordArray[4*2] = {
2959 0, ty, tx, ty, tx, 0, 0, 0
2960 };
2961
2962 GLfloat vertexArray[4*2];
2963 qt_add_rect_to_array(target, vertexArray);
2964
2965 QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
2966 gl1funcs->glVertexPointer(2, GL_FLOAT, 0, vertexArray);
2967 gl1funcs->glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
2968
2969 gl1funcs->glEnableClientState(GL_VERTEX_ARRAY);
2970 gl1funcs->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2971 funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
2972
2973 gl1funcs->glDisableClientState(GL_VERTEX_ARRAY);
2974 gl1funcs->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2975}
2976
2977#endif // !QT_OPENGL_ES_2
2978
2979/*!
2980 \since 4.4
2981
2982 This function supports the following use cases:
2983
2984 \list
2985 \li On OpenGL and OpenGL ES 1.x it draws the given texture, \a textureId,
2986 to the given target rectangle, \a target, in OpenGL model space. The
2987 \a textureTarget should be a 2D texture target.
2988 \li On OpenGL and OpenGL ES 2.x, if a painter is active, not inside a
2989 beginNativePainting / endNativePainting block, and uses the
2990 engine with type QPaintEngine::OpenGL2, the function will draw the given
2991 texture, \a textureId, to the given target rectangle, \a target,
2992 respecting the current painter state. This will let you draw a texture
2993 with the clip, transform, render hints, and composition mode set by the
2994 painter. Note that the texture target needs to be GL_TEXTURE_2D for this
2995 use case, and that this is the only supported use case under OpenGL ES 2.x.
2996 \endlist
2997
2998*/
2999void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
3000{
3001#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2)
3002 if (d_ptr->active_engine &&
3003 d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
3004 QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
3005 if (!eng->isNativePaintingActive()) {
3006 QRectF src(0, 0, target.width(), target.height());
3007 QSize size(target.width(), target.height());
3008 if (eng->drawTexture(target, textureId, size, src))
3009 return;
3010 }
3011 }
3012#endif
3013
3014#ifndef QT_OPENGL_ES_2
3015 QOpenGLFunctions *funcs = qgl_functions();
3016 if (!contextHandle()->isOpenGLES()) {
3017#ifdef QT_OPENGL_ES
3018 if (textureTarget != GL_TEXTURE_2D) {
3019 qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES");
3020 return;
3021 }
3022#else
3023 const bool wasEnabled = funcs->glIsEnabled(GL_TEXTURE_2D);
3024 GLint oldTexture;
3025 funcs->glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
3026#endif
3027
3028 funcs->glEnable(textureTarget);
3029 funcs->glBindTexture(textureTarget, textureId);
3030
3031 qDrawTextureRect(target, -1, -1, textureTarget);
3032
3033#ifdef QT_OPENGL_ES
3034 funcs->glDisable(textureTarget);
3035#else
3036 if (!wasEnabled)
3037 funcs->glDisable(textureTarget);
3038 funcs->glBindTexture(textureTarget, oldTexture);
3039#endif
3040 return;
3041 }
3042#else
3043 Q_UNUSED(target);
3044 Q_UNUSED(textureId);
3045 Q_UNUSED(textureTarget);
3046#endif
3047 qWarning("drawTexture() with OpenGL ES 2.0 requires an active OpenGL2 paint engine");
3048}
3049
3050/*!
3051 \since 4.4
3052
3053 This function supports the following use cases:
3054
3055 \list
3056 \li By default it draws the given texture, \a textureId,
3057 at the given \a point in OpenGL model space. The
3058 \a textureTarget should be a 2D texture target.
3059 \li If a painter is active, not inside a
3060 beginNativePainting / endNativePainting block, and uses the
3061 engine with type QPaintEngine::OpenGL2, the function will draw the given
3062 texture, \a textureId, at the given \a point,
3063 respecting the current painter state. This will let you draw a texture
3064 with the clip, transform, render hints, and composition mode set by the
3065 painter. Note that the texture target needs to be GL_TEXTURE_2D for this
3066 use case.
3067 \endlist
3068
3069 \note This function is not supported under any version of OpenGL ES.
3070*/
3071void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
3072{
3073#ifdef QT_OPENGL_ES
3074 Q_UNUSED(point);
3075 Q_UNUSED(textureId);
3076 Q_UNUSED(textureTarget);
3077#else
3078 if (!contextHandle()->isOpenGLES()) {
3079 QOpenGLFunctions *funcs = qgl_functions();
3080 const bool wasEnabled = funcs->glIsEnabled(GL_TEXTURE_2D);
3081 GLint oldTexture;
3082 funcs->glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
3083
3084 funcs->glEnable(textureTarget);
3085 funcs->glBindTexture(textureTarget, textureId);
3086
3087 GLint textureWidth;
3088 GLint textureHeight;
3089
3090 QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
3091 gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
3092 gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
3093
3094 if (d_ptr->active_engine &&
3095 d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
3096 QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
3097 if (!eng->isNativePaintingActive()) {
3098 QRectF dest(point, QSizeF(textureWidth, textureHeight));
3099 QRectF src(0, 0, textureWidth, textureHeight);
3100 QSize size(textureWidth, textureHeight);
3101 if (eng->drawTexture(dest, textureId, size, src))
3102 return;
3103 }
3104 }
3105
3106 qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget);
3107
3108 if (!wasEnabled)
3109 funcs->glDisable(textureTarget);
3110 funcs->glBindTexture(textureTarget, oldTexture);
3111 return;
3112 }
3113#endif
3114 qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead");
3115}
3116
3117/*!
3118 This function sets the limit for the texture cache to \a size,
3119 expressed in kilobytes.
3120
3121 By default, the cache limit is approximately 64 MB.
3122
3123 \sa textureCacheLimit()
3124*/
3125void QGLContext::setTextureCacheLimit(int size)
3126{
3127 QGLTextureCache::instance()->setMaxCost(size);
3128}
3129
3130/*!
3131 Returns the current texture cache limit in kilobytes.
3132
3133 \sa setTextureCacheLimit()
3134*/
3135int QGLContext::textureCacheLimit()
3136{
3137 return QGLTextureCache::instance()->maxCost();
3138}
3139
3140
3141/*!
3142 \fn QGLFormat QGLContext::format() const
3143
3144 Returns the frame buffer format that was obtained (this may be a
3145 subset of what was requested).
3146
3147 \sa requestedFormat()
3148*/
3149
3150/*!
3151 \fn QGLFormat QGLContext::requestedFormat() const
3152
3153 Returns the frame buffer format that was originally requested in
3154 the constructor or setFormat().
3155
3156 \sa format()
3157*/
3158
3159/*!
3160 Sets a \a format for this context. The context is \l{reset()}{reset}.
3161
3162 Call create() to create a new GL context that tries to match the
3163 new format.
3164
3165 \snippet code/src_opengl_qgl.cpp 7
3166
3167 \sa format(), reset(), create()
3168*/
3169
3170void QGLContext::setFormat(const QGLFormat &format)
3171{
3172 Q_D(QGLContext);
3173 reset();
3174 d->glFormat = d->reqFormat = format;
3175}
3176
3177/*!
3178 \internal
3179*/
3180void QGLContext::setDevice(QPaintDevice *pDev)
3181{
3182 Q_D(QGLContext);
3183 // Do not touch the valid flag here. The context is either a new one and
3184 // valid is not yet set or it is adapted from a valid QOpenGLContext in which
3185 // case it must remain valid.
3186 d->paintDevice = pDev;
3187 if (d->paintDevice && (d->paintDevice->devType() != QInternal::Widget
3188 && d->paintDevice->devType() != QInternal::Pixmap
3189 && d->paintDevice->devType() != QInternal::Pbuffer)) {
3190 qWarning("QGLContext: Unsupported paint device type");
3191 }
3192}
3193
3194/*!
3195 \fn bool QGLContext::isValid() const
3196
3197 Returns \c true if a GL rendering context has been successfully
3198 created; otherwise returns \c false.
3199*/
3200
3201/*!
3202 \fn void QGLContext::setValid(bool valid)
3203 \internal
3204
3205 Forces the GL rendering context to be valid.
3206*/
3207
3208/*!
3209 \fn bool QGLContext::isSharing() const
3210
3211 Returns \c true if this context is sharing its GL context with
3212 another QGLContext, otherwise false is returned. Note that context
3213 sharing might not be supported between contexts with different
3214 formats.
3215*/
3216
3217/*!
3218 Returns \c true if \a context1 and \a context2 are sharing their
3219 GL resources such as textures, shader programs, etc;
3220 otherwise returns \c false.
3221
3222 \since 4.6
3223*/
3224bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *context2)
3225{
3226 if (!context1 || !context2)
3227 return false;
3228 return context1->d_ptr->group == context2->d_ptr->group;
3229}
3230
3231/*!
3232 \fn bool QGLContext::deviceIsPixmap() const
3233
3234 Returns \c true if the paint device of this context is a pixmap;
3235 otherwise returns \c false.
3236
3237 Since Qt 5 the paint device is never actually a pixmap. renderPixmap() is
3238 however still simulated using framebuffer objects and readbacks, and this
3239 function will return \c true in this case.
3240*/
3241
3242/*!
3243 \fn bool QGLContext::windowCreated() const
3244
3245 Returns \c true if a window has been created for this context;
3246 otherwise returns \c false.
3247
3248 \sa setWindowCreated()
3249*/
3250
3251/*!
3252 \fn void QGLContext::setWindowCreated(bool on)
3253
3254 If \a on is true the context has had a window created for it. If
3255 \a on is false no window has been created for the context.
3256
3257 \sa windowCreated()
3258*/
3259
3260/*!
3261 \fn uint QGLContext::colorIndex(const QColor& c) const
3262
3263 \internal
3264
3265 Returns a colormap index for the color c, in ColorIndex mode. Used
3266 by qglColor() and qglClearColor().
3267*/
3268uint QGLContext::colorIndex(const QColor&) const
3269{
3270 return 0;
3271}
3272
3273/*!
3274 \fn bool QGLContext::initialized() const
3275
3276 Returns \c true if this context has been initialized, i.e. if
3277 QGLWidget::initializeGL() has been performed on it; otherwise
3278 returns \c false.
3279
3280 \sa setInitialized()
3281*/
3282
3283/*!
3284 \fn void QGLContext::setInitialized(bool on)
3285
3286 If \a on is true the context has been initialized, i.e.
3287 QGLContext::setInitialized() has been called on it. If \a on is
3288 false the context has not been initialized.
3289
3290 \sa initialized()
3291*/
3292
3293/*!
3294 \fn const QGLContext* QGLContext::currentContext()
3295
3296 Returns the current context, i.e. the context to which any OpenGL
3297 commands will currently be directed. Returns 0 if no context is
3298 current.
3299
3300 \sa makeCurrent()
3301*/
3302
3303/*!
3304 \fn QColor QGLContext::overlayTransparentColor() const
3305
3306 If this context is a valid context in an overlay plane, returns
3307 the plane's transparent color. Otherwise returns an \l{QColor::isValid()}{invalid} color.
3308
3309 The returned color's \l{QColormap::pixel()}{pixel} value is
3310 the index of the transparent color in the colormap of the overlay
3311 plane. (Naturally, the color's RGB values are meaningless.)
3312
3313 The returned QColor object will generally work as expected only
3314 when passed as the argument to QGLWidget::qglColor() or
3315 QGLWidget::qglClearColor(). Under certain circumstances it can
3316 also be used to draw transparent graphics with a QPainter.
3317*/
3318QColor QGLContext::overlayTransparentColor() const
3319{
3320 return QColor(); // Invalid color
3321}
3322
3323/*!
3324 Creates the GL context. Returns \c true if it was successful in
3325 creating a valid GL rendering context on the paint device
3326 specified in the constructor; otherwise returns \c false (i.e. the
3327 context is invalid).
3328
3329 If the OpenGL implementation on your system does not support the requested
3330 version of OpenGL context, then QGLContext will try to create the closest
3331 matching version. The actual created context properties can be queried
3332 using the QGLFormat returned by the format() function. For example, if
3333 you request a context that supports OpenGL 4.3 Core profile but the driver
3334 and/or hardware only supports version 3.2 Core profile contexts then you will
3335 get a 3.2 Core profile context.
3336
3337 After successful creation, format() returns the set of features of
3338 the created GL rendering context.
3339
3340 If \a shareContext points to a valid QGLContext, this method will
3341 try to establish OpenGL display list and texture object sharing
3342 between this context and the \a shareContext. Note that this may
3343 fail if the two contexts have different \l {format()} {formats}.
3344 Use isSharing() to see if sharing is in effect.
3345
3346 \warning Implementation note: initialization of C++ class
3347 members usually takes place in the class constructor. QGLContext
3348 is an exception because it must be simple to customize. The
3349 virtual functions chooseContext() (and chooseVisual() for X11) can
3350 be reimplemented in a subclass to select a particular context. The
3351 problem is that virtual functions are not properly called during
3352 construction (even though this is correct C++) because C++
3353 constructs class hierarchies from the bottom up. For this reason
3354 we need a create() function.
3355
3356 \sa chooseContext(), format(), isValid()
3357*/
3358
3359bool QGLContext::create(const QGLContext* shareContext)
3360{
3361 Q_D(QGLContext);
3362 if (!d->paintDevice && !d->guiGlContext)
3363 return false;
3364
3365 reset();
3366 d->valid = chooseContext(shareContext);
3367 if (d->valid && d->paintDevice && d->paintDevice->devType() == QInternal::Widget) {
3368 QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice));
3369 wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer();
3370 }
3371 return d->valid;
3372}
3373
3374bool QGLContext::isValid() const
3375{
3376 Q_D(const QGLContext);
3377 return d->valid;
3378}
3379
3380void QGLContext::setValid(bool valid)
3381{
3382 Q_D(QGLContext);
3383 d->valid = valid;
3384}
3385
3386bool QGLContext::isSharing() const
3387{
3388 Q_D(const QGLContext);
3389 return d->group->isSharing();
3390}
3391
3392QGLFormat QGLContext::format() const
3393{
3394 Q_D(const QGLContext);
3395 return d->glFormat;
3396}
3397
3398QGLFormat QGLContext::requestedFormat() const
3399{
3400 Q_D(const QGLContext);
3401 return d->reqFormat;
3402}
3403
3404 QPaintDevice* QGLContext::device() const
3405{
3406 Q_D(const QGLContext);
3407 return d->paintDevice;
3408}
3409
3410bool QGLContext::deviceIsPixmap() const
3411{
3412 Q_D(const QGLContext);
3413 return !d->readback_target_size.isEmpty();
3414}
3415
3416
3417bool QGLContext::windowCreated() const
3418{
3419 Q_D(const QGLContext);
3420 return d->crWin;
3421}
3422
3423
3424void QGLContext::setWindowCreated(bool on)
3425{
3426 Q_D(QGLContext);
3427 d->crWin = on;
3428}
3429
3430bool QGLContext::initialized() const
3431{
3432 Q_D(const QGLContext);
3433 return d->initDone;
3434}
3435
3436void QGLContext::setInitialized(bool on)
3437{
3438 Q_D(QGLContext);
3439 d->initDone = on;
3440}
3441
3442const QGLContext* QGLContext::currentContext()
3443{
3444 if (const QOpenGLContext *threadContext = QOpenGLContext::currentContext()) {
3445 return QGLContext::fromOpenGLContext(const_cast<QOpenGLContext *>(threadContext));
3446 }
3447 return 0;
3448}
3449
3450void QGLContextPrivate::setCurrentContext(QGLContext *context)
3451{
3452 Q_UNUSED(context);
3453}
3454
3455/*!
3456 Moves the QGLContext to the given \a thread.
3457
3458 Enables calling swapBuffers() and makeCurrent() on the context in
3459 the given thread.
3460*/
3461void QGLContext::moveToThread(QThread *thread)
3462{
3463 Q_D(QGLContext);
3464 if (d->guiGlContext)
3465 d->guiGlContext->moveToThread(thread);
3466}
3467
3468/*!
3469 \fn bool QGLContext::chooseContext(const QGLContext* shareContext = 0)
3470
3471 This semi-internal function is called by create(). It creates a
3472 system-dependent OpenGL handle that matches the format() of \a
3473 shareContext as closely as possible, returning true if successful
3474 or false if a suitable handle could not be found.
3475
3476 On Windows, it calls the virtual function choosePixelFormat(),
3477 which finds a matching pixel format identifier. On X11, it calls
3478 the virtual function chooseVisual() which finds an appropriate X
3479 visual. On other platforms it may work differently.
3480*/
3481bool QGLContext::chooseContext(const QGLContext* shareContext)
3482{
3483 Q_D(QGLContext);
3484 if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) {
3485 // Unlike in Qt 4, the only possible target is a widget backed by an OpenGL-based
3486 // QWindow. Pixmaps in particular are not supported anymore as paint devices since
3487 // starting from Qt 5 QPixmap is raster-backed on almost all platforms.
3488 d->valid = false;
3489 }else {
3490 QWidget *widget = static_cast<QWidget *>(d->paintDevice);
3491 QGLFormat glformat = format();
3492 QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat);
3493 if (widget->testAttribute(Qt::WA_TranslucentBackground))
3494 winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8));
3495
3496 QWindow *window = widget->windowHandle();
3497 if (!window->handle()
3498 || window->surfaceType() != QWindow::OpenGLSurface
3499 || window->requestedFormat() != winFormat)
3500 {
3501 window->setSurfaceType(QWindow::OpenGLSurface);
3502 window->setFormat(winFormat);
3503 window->destroy();
3504 window->create();
3505 }
3506
3507 if (d->ownContext)
3508 delete d->guiGlContext;
3509 d->ownContext = true;
3510 QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0;
3511 d->guiGlContext = new QOpenGLContext;
3512 d->guiGlContext->setFormat(winFormat);
3513 d->guiGlContext->setShareContext(shareGlContext);
3514 d->valid = d->guiGlContext->create();
3515
3516 if (d->valid)
3517 d->guiGlContext->setQGLContextHandle(this, 0);
3518
3519 d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format());
3520 d->setupSharing();
3521 }
3522
3523
3524 return d->valid;
3525}
3526
3527/*!
3528 \fn void QGLContext::reset()
3529
3530 Resets the context and makes it invalid.
3531
3532 \sa create(), isValid()
3533*/
3534void QGLContext::reset()
3535{
3536 Q_D(QGLContext);
3537 if (!d->valid)
3538 return;
3539 d->cleanup();
3540
3541 d->crWin = false;
3542 d->sharing = false;
3543 d->valid = false;
3544 d->transpColor = QColor();
3545 d->initDone = false;
3546 QGLContextGroup::removeShare(this);
3547 if (d->guiGlContext) {
3548 if (QOpenGLContext::currentContext() == d->guiGlContext)
3549 doneCurrent();
3550 if (d->ownContext) {
3551 if (d->guiGlContext->thread() == QThread::currentThread())
3552 delete d->guiGlContext;
3553 else
3554 d->guiGlContext->deleteLater();
3555 } else
3556 d->guiGlContext->setQGLContextHandle(0,0);
3557 d->guiGlContext = 0;
3558 }
3559 d->ownContext = false;
3560}
3561
3562/*!
3563 \fn void QGLContext::makeCurrent()
3564
3565 Makes this context the current OpenGL rendering context. All GL
3566 functions you call operate on this context until another context
3567 is made current.
3568
3569 In some very rare cases the underlying call may fail. If this
3570 occurs an error message is output to stderr.
3571
3572 If you call this from a thread other than the main UI thread,
3573 make sure you've first pushed the context to the relevant thread
3574 from the UI thread using moveToThread().
3575*/
3576void QGLContext::makeCurrent()
3577{
3578 Q_D(QGLContext);
3579 if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
3580 return;
3581
3582 QWidget *widget = static_cast<QWidget *>(d->paintDevice);
3583 if (!widget->windowHandle())
3584 return;
3585
3586 if (d->guiGlContext->makeCurrent(widget->windowHandle())) {
3587 if (!d->workaroundsCached) {
3588 d->workaroundsCached = true;
3589 const char *renderer = reinterpret_cast<const char *>(d->guiGlContext->functions()->glGetString(GL_RENDERER));
3590 if (renderer && strstr(renderer, "Mali")) {
3591 d->workaround_brokenFBOReadBack = true;
3592 }
3593 }
3594 }
3595}
3596
3597/*!
3598 \fn void QGLContext::swapBuffers() const
3599
3600 Call this to finish a frame of OpenGL rendering, and make sure to
3601 call makeCurrent() again before issuing any further OpenGL commands,
3602 for example as part of a new frame.
3603*/
3604void QGLContext::swapBuffers() const
3605{
3606 Q_D(const QGLContext);
3607 if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
3608 return;
3609
3610 QWidget *widget = static_cast<QWidget *>(d->paintDevice);
3611 if (!widget->windowHandle())
3612 return;
3613
3614 d->guiGlContext->swapBuffers(widget->windowHandle());
3615}
3616
3617/*!
3618 \fn void QGLContext::doneCurrent()
3619
3620 Makes no GL context the current context. Normally, you do not need
3621 to call this function; QGLContext calls it as necessary.
3622*/
3623void QGLContext::doneCurrent()
3624{
3625 Q_D(QGLContext);
3626 d->guiGlContext->doneCurrent();
3627}
3628
3629/*!
3630 \fn QPaintDevice* QGLContext::device() const
3631
3632 Returns the paint device set for this context.
3633
3634 \sa QGLContext::QGLContext()
3635*/
3636
3637/*****************************************************************************
3638 QGLWidget implementation
3639 *****************************************************************************/
3640
3641
3642/*!
3643 \class QGLWidget
3644 \inmodule QtOpenGL
3645 \obsolete
3646
3647 \brief The QGLWidget class is a widget for rendering OpenGL graphics.
3648
3649 QGLWidget provides functionality for displaying OpenGL graphics
3650 integrated into a Qt application. It is very simple to use. You
3651 inherit from it and use the subclass like any other QWidget,
3652 except that you have the choice between using QPainter and
3653 standard OpenGL rendering commands.
3654
3655 \note This class is part of the legacy \l {Qt OpenGL} module and,
3656 like the other \c QGL classes, should be avoided in the new
3657 applications. Instead, starting from Qt 5.4, prefer using
3658 QOpenGLWidget and the \c QOpenGL classes.
3659
3660 QGLWidget provides three convenient virtual functions that you can
3661 reimplement in your subclass to perform the typical OpenGL tasks:
3662
3663 \list
3664 \li paintGL() - Renders the OpenGL scene. Gets called whenever the widget
3665 needs to be updated.
3666 \li resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
3667 called whenever the widget has been resized (and also when it
3668 is shown for the first time because all newly created widgets get a
3669 resize event automatically).
3670 \li initializeGL() - Sets up the OpenGL rendering context, defines display
3671 lists, etc. Gets called once before the first time resizeGL() or
3672 paintGL() is called.
3673 \endlist
3674
3675 Here is a rough outline of how a QGLWidget subclass might look:
3676
3677 \snippet code/src_opengl_qgl.cpp 8
3678
3679 If you need to trigger a repaint from places other than paintGL()
3680 (a typical example is when using \l{QTimer}{timers} to
3681 animate scenes), you should call the widget's updateGL() function.
3682
3683 Your widget's OpenGL rendering context is made current when
3684 paintGL(), resizeGL(), or initializeGL() is called. If you need to
3685 call the standard OpenGL API functions from other places (e.g. in
3686 your widget's constructor or in your own paint functions), you
3687 must call makeCurrent() first.
3688
3689 QGLWidget provides functions for requesting a new display
3690 \l{QGLFormat}{format} and you can also create widgets with
3691 customized rendering \l{QGLContext}{contexts}.
3692
3693 You can also share OpenGL display lists between QGLWidget objects (see
3694 the documentation of the QGLWidget constructors for details).
3695
3696 Note that under Windows, the QGLContext belonging to a QGLWidget
3697 has to be recreated when the QGLWidget is reparented. This is
3698 necessary due to limitations on the Windows platform. This will
3699 most likely cause problems for users that have subclassed and
3700 installed their own QGLContext on a QGLWidget. It is possible to
3701 work around this issue by putting the QGLWidget inside a dummy
3702 widget and then reparenting the dummy widget, instead of the
3703 QGLWidget. This will side-step the issue altogether, and is what
3704 we recommend for users that need this kind of functionality.
3705
3706 On \macos, when Qt is built with Cocoa support, a QGLWidget
3707 can't have any sibling widgets placed ontop of itself. This is due
3708 to limitations in the Cocoa API and is not supported by Apple.
3709
3710 \section1 Overlays
3711
3712 The QGLWidget creates a GL overlay context in addition to the
3713 normal context if overlays are supported by the underlying system.
3714
3715 If you want to use overlays, you specify it in the
3716 \l{QGLFormat}{format}. (Note: Overlay must be requested in the format
3717 passed to the QGLWidget constructor.) Your GL widget should also
3718 implement some or all of these virtual methods:
3719
3720 \list
3721 \li paintOverlayGL()
3722 \li resizeOverlayGL()
3723 \li initializeOverlayGL()
3724 \endlist
3725
3726 These methods work in the same way as the normal paintGL() etc.
3727 functions, except that they will be called when the overlay
3728 context is made current. You can explicitly make the overlay
3729 context current by using makeOverlayCurrent(), and you can access
3730 the overlay context directly (e.g. to ask for its transparent
3731 color) by calling overlayContext().
3732
3733 On X servers in which the default visual is in an overlay plane,
3734 non-GL Qt windows can also be used for overlays.
3735
3736 \section1 Painting Techniques
3737
3738 As described above, subclass QGLWidget to render pure 3D content in the
3739 following way:
3740
3741 \list
3742 \li Reimplement the QGLWidget::initializeGL() and QGLWidget::resizeGL() to
3743 set up the OpenGL state and provide a perspective transformation.
3744 \li Reimplement QGLWidget::paintGL() to paint the 3D scene, calling only
3745 OpenGL functions to draw on the widget.
3746 \endlist
3747
3748 It is also possible to draw 2D graphics onto a QGLWidget subclass, it is necessary
3749 to reimplement QGLWidget::paintEvent() and do the following:
3750
3751 \list
3752 \li Construct a QPainter object.
3753 \li Initialize it for use on the widget with the QPainter::begin() function.
3754 \li Draw primitives using QPainter's member functions.
3755 \li Call QPainter::end() to finish painting.
3756 \endlist
3757
3758 \section1 Threading
3759
3760 As of Qt version 4.8, support for doing threaded GL rendering has
3761 been improved. There are three scenarios that we currently support:
3762 \list
3763 \li 1. Buffer swapping in a thread.
3764
3765 Swapping buffers in a double buffered context may be a
3766 synchronous, locking call that may be a costly operation in some
3767 GL implementations. Especially so on embedded devices. It's not
3768 optimal to have the CPU idling while the GPU is doing a buffer
3769 swap. In those cases it is possible to do the rendering in the
3770 main thread and do the actual buffer swap in a separate
3771 thread. This can be done with the following steps:
3772
3773 1. Call doneCurrent() in the main thread when the rendering is
3774 finished.
3775
3776 2. Call QGLContext::moveToThread(swapThread) to transfer ownership
3777 of the context to the swapping thread.
3778
3779 3. Notify the swapping thread that it can grab the context.
3780
3781 4. Make the rendering context current in the swapping thread with
3782 makeCurrent() and then call swapBuffers().
3783
3784 5. Call doneCurrent() in the swapping thread.
3785
3786 6. Call QGLContext::moveToThread(qApp->thread()) and notify the
3787 main thread that swapping is done.
3788
3789 Doing this will free up the main thread so that it can continue
3790 with, for example, handling UI events or network requests. Even if
3791 there is a context swap involved, it may be preferable compared to
3792 having the main thread wait while the GPU finishes the swap
3793 operation. Note that this is highly implementation dependent.
3794
3795 \li 2. Texture uploading in a thread.
3796
3797 Doing texture uploads in a thread may be very useful for
3798 applications handling large amounts of images that needs to be
3799 displayed, like for instance a photo gallery application. This is
3800 supported in Qt through the existing bindTexture() API. A simple
3801 way of doing this is to create two sharing QGLWidgets. One is made
3802 current in the main GUI thread, while the other is made current in
3803 the texture upload thread. The widget in the uploading thread is
3804 never shown, it is only used for sharing textures with the main
3805 thread. For each texture that is bound via bindTexture(), notify
3806 the main thread so that it can start using the texture.
3807
3808 \li 3. Using QPainter to draw into a QGLWidget in a thread.
3809
3810 In Qt 4.8, it is possible to draw into a QGLWidget using a
3811 QPainter in a separate thread. Note that this is also possible for
3812 QGLPixelBuffers and QGLFramebufferObjects. Since this is only
3813 supported in the GL 2 paint engine, OpenGL 2.0 or OpenGL ES 2.0 is
3814 required.
3815
3816 QGLWidgets can only be created in the main GUI thread. This means
3817 a call to doneCurrent() is necessary to release the GL context
3818 from the main thread, before the widget can be drawn into by
3819 another thread. You then need to call QGLContext::moveToThread()
3820 to transfer ownership of the context to the thread in which you
3821 want to make it current.
3822 Also, the main GUI thread will dispatch resize and
3823 paint events to a QGLWidget when the widget is resized, or parts
3824 of it becomes exposed or needs redrawing. It is therefore
3825 necessary to handle those events because the default
3826 implementations inside QGLWidget will try to make the QGLWidget's
3827 context current, which again will interfere with any threads
3828 rendering into the widget. Reimplement QGLWidget::paintEvent() and
3829 QGLWidget::resizeEvent() to notify the rendering thread that a
3830 resize or update is necessary, and be careful not to call the base
3831 class implementation. If you are rendering an animation, it might
3832 not be necessary to handle the paint event at all since the
3833 rendering thread is doing regular updates. Then it would be enough
3834 to reimplement QGLWidget::paintEvent() to do nothing.
3835
3836 \endlist
3837
3838 As a general rule when doing threaded rendering: be aware that
3839 binding and releasing contexts in different threads have to be
3840 synchronized by the user. A GL rendering context can only be
3841 current in one thread at any time. If you try to open a QPainter
3842 on a QGLWidget and the widget's rendering context is current in
3843 another thread, it will fail.
3844
3845 In addition to this, rendering using raw GL calls in a separate
3846 thread is supported.
3847
3848 \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
3849 countries.}
3850
3851 \sa QOpenGLWidget, QGLPixelBuffer
3852*/
3853
3854/*!
3855 Constructs an OpenGL widget with a \a parent widget.
3856
3857 The \l{QGLFormat::defaultFormat()}{default format} is
3858 used. The widget will be \l{isValid()}{invalid} if the
3859 system has no \l{QGLFormat::hasOpenGL()}{OpenGL support}.
3860
3861 The \a parent and widget flag, \a f, arguments are passed
3862 to the QWidget constructor.
3863
3864 If \a shareWidget is a valid QGLWidget, this widget will share
3865 OpenGL display lists and texture objects with \a shareWidget. But
3866 if \a shareWidget and this widget have different \l {format()}
3867 {formats}, sharing might not be possible. You can check whether
3868 sharing is in effect by calling isSharing().
3869
3870 The initialization of OpenGL rendering state, etc. should be done
3871 by overriding the initializeGL() function, rather than in the
3872 constructor of your QGLWidget subclass.
3873
3874 \sa QGLFormat::defaultFormat(), {Textures Example}
3875*/
3876
3877QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
3878 : QWidget(*(new QGLWidgetPrivate), parent, f)
3879{
3880 Q_D(QGLWidget);
3881 d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
3882}
3883
3884/*!
3885 \internal
3886 */
3887QGLWidget::QGLWidget(QGLWidgetPrivate &dd, const QGLFormat &format, QWidget *parent, const QGLWidget *shareWidget, Qt::WindowFlags f)
3888 : QWidget(dd, parent, f)
3889{
3890 Q_D(QGLWidget);
3891 d->init(new QGLContext(format, this), shareWidget);
3892
3893}
3894
3895
3896/*!
3897 Constructs an OpenGL widget with parent \a parent.
3898
3899 The \a format argument specifies the desired
3900 \l{QGLFormat}{rendering options}.
3901 If the underlying OpenGL/Window system
3902 cannot satisfy all the features requested in \a format, the
3903 nearest subset of features will be used. After creation, the
3904 format() method will return the actual format obtained.
3905
3906 The widget will be \l{isValid()}{invalid} if the system
3907 has no \l{QGLFormat::hasOpenGL()}{OpenGL support}.
3908
3909 The \a parent and widget flag, \a f, arguments are passed
3910 to the QWidget constructor.
3911
3912 If \a shareWidget is a valid QGLWidget, this widget will share
3913 OpenGL display lists and texture objects with \a shareWidget. But
3914 if \a shareWidget and this widget have different \l {format()}
3915 {formats}, sharing might not be possible. You can check whether
3916 sharing is in effect by calling isSharing().
3917
3918 The initialization of OpenGL rendering state, etc. should be done
3919 by overriding the initializeGL() function, rather than in the
3920 constructor of your QGLWidget subclass.
3921
3922 \sa QGLFormat::defaultFormat(), isValid()
3923*/
3924
3925QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* shareWidget,
3926 Qt::WindowFlags f)
3927 : QWidget(*(new QGLWidgetPrivate), parent, f)
3928{
3929 Q_D(QGLWidget);
3930 d->init(new QGLContext(format, this), shareWidget);
3931}
3932
3933/*!
3934 Constructs an OpenGL widget with parent \a parent.
3935
3936 The \a context argument is a pointer to the QGLContext that
3937 you wish to be bound to this widget. This allows you to pass in
3938 your own QGLContext sub-classes.
3939
3940 The widget will be \l{isValid()}{invalid} if the system
3941 has no \l{QGLFormat::hasOpenGL()}{OpenGL support}.
3942
3943 The \a parent and widget flag, \a f, arguments are passed
3944 to the QWidget constructor.
3945
3946 If \a shareWidget is a valid QGLWidget, this widget will share
3947 OpenGL display lists and texture objects with \a shareWidget. But
3948 if \a shareWidget and this widget have different \l {format()}
3949 {formats}, sharing might not be possible. You can check whether
3950 sharing is in effect by calling isSharing().
3951
3952 The initialization of OpenGL rendering state, etc. should be done
3953 by overriding the initializeGL() function, rather than in the
3954 constructor of your QGLWidget subclass.
3955
3956 \sa QGLFormat::defaultFormat(), isValid()
3957*/
3958QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, const QGLWidget *shareWidget,
3959 Qt::WindowFlags f)
3960 : QWidget(*(new QGLWidgetPrivate), parent, f)
3961{
3962 Q_D(QGLWidget);
3963 d->init(context, shareWidget);
3964}
3965
3966/*!
3967 Destroys the widget.
3968*/
3969
3970QGLWidget::~QGLWidget()
3971{
3972 Q_D(QGLWidget);
3973 delete d->glcx;
3974 d->glcx = 0;
3975 d->cleanupColormaps();
3976}
3977
3978/*!
3979 \fn QGLFormat QGLWidget::format() const
3980
3981 Returns the format of the contained GL rendering context.
3982*/
3983
3984/*!
3985 \fn bool QGLWidget::doubleBuffer() const
3986
3987 Returns \c true if the contained GL rendering context has double
3988 buffering; otherwise returns \c false.
3989
3990 \sa QGLFormat::doubleBuffer()
3991*/
3992
3993/*!
3994 \fn void QGLWidget::setAutoBufferSwap(bool on)
3995
3996 If \a on is true automatic GL buffer swapping is switched on;
3997 otherwise it is switched off.
3998
3999 If \a on is true and the widget is using a double-buffered format,
4000 the background and foreground GL buffers will automatically be
4001 swapped after each paintGL() call.
4002
4003 The buffer auto-swapping is on by default.
4004
4005 \sa autoBufferSwap(), doubleBuffer(), swapBuffers()
4006*/
4007
4008/*!
4009 \fn bool QGLWidget::autoBufferSwap() const
4010
4011 Returns \c true if the widget is doing automatic GL buffer swapping;
4012 otherwise returns \c false.
4013
4014 \sa setAutoBufferSwap()
4015*/
4016
4017/*!
4018 \fn QFunctionPointer QGLContext::getProcAddress(const QString &proc) const
4019
4020 Returns a function pointer to the GL extension function passed in
4021 \a proc. \nullptr is returned if a pointer to the function could not be
4022 obtained.
4023*/
4024QFunctionPointer QGLContext::getProcAddress(const QString &procName) const
4025{
4026 Q_D(const QGLContext);
4027 return d->guiGlContext->getProcAddress(procName.toLatin1());
4028}
4029
4030/*!
4031 \fn bool QGLWidget::isValid() const
4032
4033 Returns \c true if the widget has a valid GL rendering context;
4034 otherwise returns \c false. A widget will be invalid if the system
4035 has no \l{QGLFormat::hasOpenGL()}{OpenGL support}.
4036*/
4037
4038bool QGLWidget::isValid() const
4039{
4040 Q_D(const QGLWidget);
4041 return d->glcx && d->glcx->isValid();
4042}
4043
4044/*!
4045 \fn bool QGLWidget::isSharing() const
4046
4047 Returns \c true if this widget's GL context is shared with another GL
4048 context, otherwise false is returned. Context sharing might not be
4049 possible if the widgets use different formats.
4050
4051 \sa format()
4052*/
4053
4054bool QGLWidget::isSharing() const
4055{
4056 Q_D(const QGLWidget);
4057 return d->glcx->isSharing();
4058}
4059
4060/*!
4061 \fn void QGLWidget::makeCurrent()
4062
4063 Makes this widget the current widget for OpenGL operations, i.e.
4064 makes the widget's rendering context the current OpenGL rendering
4065 context.
4066*/
4067
4068void QGLWidget::makeCurrent()
4069{
4070 Q_D(QGLWidget);
4071 d->makeCurrent();
4072}
4073
4074bool QGLWidgetPrivate::makeCurrent()
4075{
4076 glcx->makeCurrent();
4077 return QGLContext::currentContext() == glcx;
4078}
4079
4080/*!
4081 \fn void QGLWidget::doneCurrent()
4082
4083 Makes no GL context the current context. Normally, you do not need
4084 to call this function; QGLContext calls it as necessary. However,
4085 it may be useful in multithreaded environments.
4086*/
4087
4088void QGLWidget::doneCurrent()
4089{
4090 Q_D(QGLWidget);
4091 d->glcx->doneCurrent();
4092}
4093
4094/*!
4095 \fn void QGLWidget::swapBuffers()
4096
4097 Swaps the screen contents with an off-screen buffer. This only
4098 works if the widget's format specifies double buffer mode.
4099
4100 Normally, there is no need to explicitly call this function
4101 because it is done automatically after each widget repaint, i.e.
4102 each time after paintGL() has been executed.
4103
4104 \sa doubleBuffer(), setAutoBufferSwap(), QGLFormat::setDoubleBuffer()
4105*/
4106
4107void QGLWidget::swapBuffers()
4108{
4109 Q_D(QGLWidget);
4110 d->glcx->swapBuffers();
4111}
4112
4113
4114/*!
4115 \fn const QGLContext* QGLWidget::overlayContext() const
4116
4117 Returns the overlay context of this widget, or \nullptr if this
4118 widget has no overlay.
4119
4120 \sa context()
4121*/
4122const QGLContext* QGLWidget::overlayContext() const
4123{
4124 return nullptr;
4125}
4126
4127/*!
4128 \fn void QGLWidget::makeOverlayCurrent()
4129
4130 Makes the overlay context of this widget current. Use this if you
4131 need to issue OpenGL commands to the overlay context outside of
4132 initializeOverlayGL(), resizeOverlayGL(), and paintOverlayGL().
4133
4134 Does nothing if this widget has no overlay.
4135
4136 \sa makeCurrent()
4137*/
4138void QGLWidget::makeOverlayCurrent()
4139{
4140}
4141
4142/*!
4143 \obsolete
4144
4145 Sets a new format for this widget.
4146
4147 If the underlying OpenGL/Window system cannot satisfy all the
4148 features requested in \a format, the nearest subset of features will