1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qsurfaceformat.h"
41
42#include <QtCore/qatomic.h>
43#include <QtCore/QDebug>
44#include <QOpenGLContext>
45#include <QtGui/qcolorspace.h>
46#include <QtGui/qguiapplication.h>
47
48#ifdef major
49#undef major
50#endif
51
52#ifdef minor
53#undef minor
54#endif
55
56QT_BEGIN_NAMESPACE
57
58class QSurfaceFormatPrivate
59{
60public:
61 explicit QSurfaceFormatPrivate(QSurfaceFormat::FormatOptions _opts = { })
62 : ref(1)
63 , opts(_opts)
64 , redBufferSize(-1)
65 , greenBufferSize(-1)
66 , blueBufferSize(-1)
67 , alphaBufferSize(-1)
68 , depthSize(-1)
69 , stencilSize(-1)
70 , swapBehavior(QSurfaceFormat::DefaultSwapBehavior)
71 , numSamples(-1)
72 , renderableType(QSurfaceFormat::DefaultRenderableType)
73 , profile(QSurfaceFormat::NoProfile)
74 , major(2)
75 , minor(0)
76 , swapInterval(1) // default to vsync
77 {
78 }
79
80 QSurfaceFormatPrivate(const QSurfaceFormatPrivate *other)
81 : ref(1),
82 opts(other->opts),
83 redBufferSize(other->redBufferSize),
84 greenBufferSize(other->greenBufferSize),
85 blueBufferSize(other->blueBufferSize),
86 alphaBufferSize(other->alphaBufferSize),
87 depthSize(other->depthSize),
88 stencilSize(other->stencilSize),
89 swapBehavior(other->swapBehavior),
90 numSamples(other->numSamples),
91 renderableType(other->renderableType),
92 profile(other->profile),
93 major(other->major),
94 minor(other->minor),
95 swapInterval(other->swapInterval),
96 colorSpace(other->colorSpace)
97 {
98 }
99
100 QAtomicInt ref;
101 QSurfaceFormat::FormatOptions opts;
102 int redBufferSize;
103 int greenBufferSize;
104 int blueBufferSize;
105 int alphaBufferSize;
106 int depthSize;
107 int stencilSize;
108 QSurfaceFormat::SwapBehavior swapBehavior;
109 int numSamples;
110 QSurfaceFormat::RenderableType renderableType;
111 QSurfaceFormat::OpenGLContextProfile profile;
112 int major;
113 int minor;
114 int swapInterval;
115 QColorSpace colorSpace;
116};
117
118/*!
119 \class QSurfaceFormat
120 \since 5.0
121 \brief The QSurfaceFormat class represents the format of a QSurface.
122 \inmodule QtGui
123
124 The format includes the size of the color buffers, red, green, and blue;
125 the size of the alpha buffer; the size of the depth and stencil buffers;
126 and number of samples per pixel for multisampling. In addition, the format
127 contains surface configuration parameters such as OpenGL profile and
128 version for rendering, whether or not to enable stereo buffers, and swap
129 behaviour.
130
131 \note When troubleshooting context or window format issues, it can be
132 helpful to enable the logging category \c{qt.qpa.gl}. Depending on the
133 platform, this may print useful debug information when it comes to OpenGL
134 initialization and the native visual or framebuffer configurations which
135 QSurfaceFormat gets mapped to.
136*/
137
138/*!
139 \enum QSurfaceFormat::FormatOption
140
141 This enum contains format options for use with QSurfaceFormat.
142
143 \value StereoBuffers Used to request stereo buffers in the surface format.
144 \value DebugContext Used to request a debug context with extra debugging information.
145 \value DeprecatedFunctions Used to request that deprecated functions be included
146 in the OpenGL context profile. If not specified, you should get a forward compatible context
147 without support functionality marked as deprecated. This requires OpenGL version 3.0 or higher.
148 \value ResetNotification Enables notifications about resets of the OpenGL context. The status is then
149 queryable via the context's \l{QOpenGLContext::isValid()}{isValid()} function. Note that not setting
150 this flag does not guarantee that context state loss never occurs. Additionally, some implementations
151 may choose to report context loss regardless of this flag. Platforms that support dynamically enabling
152 the monitoring of the loss of context, such as, Windows with WGL, or Linux/X11 (xcb) with GLX, will
153 monitor the status in every call to \l{QOpenGLContext::makeCurrent()}{makeCurrent()}. See
154 \l{QOpenGLContext::isValid()}{isValid()} for more information on this.
155*/
156
157/*!
158 \enum QSurfaceFormat::SwapBehavior
159
160 This enum is used by QSurfaceFormat to specify the swap behaviour of a surface. The swap behaviour
161 is mostly transparent to the application, but it affects factors such as rendering latency and
162 throughput.
163
164 \value DefaultSwapBehavior The default, unspecified swap behaviour of the platform.
165 \value SingleBuffer Used to request single buffering, which might result in flickering
166 when OpenGL rendering is done directly to screen without an intermediate offscreen
167 buffer.
168 \value DoubleBuffer This is typically the default swap behaviour on desktop platforms,
169 consisting of one back buffer and one front buffer. Rendering is done to the back
170 buffer, and then the back buffer and front buffer are swapped, or the contents of
171 the back buffer are copied to the front buffer, depending on the implementation.
172 \value TripleBuffer This swap behaviour is sometimes used in order to decrease the
173 risk of skipping a frame when the rendering rate is just barely keeping up with
174 the screen refresh rate. Depending on the platform it might also lead to slightly
175 more efficient use of the GPU due to improved pipelining behaviour. Triple buffering
176 comes at the cost of an extra frame of memory usage and latency, and might not be
177 supported depending on the underlying platform.
178*/
179
180/*!
181 \enum QSurfaceFormat::RenderableType
182
183 This enum specifies the rendering backend for the surface.
184
185 \value DefaultRenderableType The default, unspecified rendering method
186 \value OpenGL Desktop OpenGL rendering
187 \value OpenGLES OpenGL ES 2.0 rendering
188 \value OpenVG Open Vector Graphics rendering
189*/
190
191/*!
192 \enum QSurfaceFormat::OpenGLContextProfile
193
194 This enum is used to specify the OpenGL context profile, in
195 conjunction with QSurfaceFormat::setMajorVersion() and
196 QSurfaceFormat::setMinorVersion().
197
198 Profiles are exposed in OpenGL 3.2 and above, and are used
199 to choose between a restricted core profile, and a compatibility
200 profile which might contain deprecated support functionality.
201
202 Note that the core profile might still contain functionality that
203 is deprecated and scheduled for removal in a higher version. To
204 get access to the deprecated functionality for the core profile
205 in the set OpenGL version you can use the QSurfaceFormat format option
206 QSurfaceFormat::DeprecatedFunctions.
207
208 \value NoProfile OpenGL version is lower than 3.2. For 3.2 and newer this is same as CoreProfile.
209 \value CoreProfile Functionality deprecated in OpenGL version 3.0 is not available.
210 \value CompatibilityProfile Functionality from earlier OpenGL versions is available.
211*/
212
213/*!
214 \enum QSurfaceFormat::ColorSpace
215
216 This enum is used to specify the preferred color space, controlling if the
217 window's associated default framebuffer is able to do updates and blending
218 in a given encoding instead of the standard linear operations.
219
220 \value DefaultColorSpace The default, unspecified color space.
221
222 \value sRGBColorSpace When \c{GL_ARB_framebuffer_sRGB} or
223 \c{GL_EXT_framebuffer_sRGB} is supported by the platform and this value is
224 set, the window will be created with an sRGB-capable default
225 framebuffer. Note that some platforms may return windows with a sRGB-capable
226 default framebuffer even when not requested explicitly.
227 */
228
229/*!
230 Constructs a default initialized QSurfaceFormat.
231
232 \note By default OpenGL 2.0 is requested since this provides the highest
233 grade of portability between platforms and OpenGL implementations.
234*/
235QSurfaceFormat::QSurfaceFormat() : d(new QSurfaceFormatPrivate)
236{
237}
238
239/*!
240 Constructs a QSurfaceFormat with the given format \a options.
241*/
242QSurfaceFormat::QSurfaceFormat(QSurfaceFormat::FormatOptions options) :
243 d(new QSurfaceFormatPrivate(options))
244{
245}
246
247/*!
248 \internal
249*/
250void QSurfaceFormat::detach()
251{
252 if (d->ref.loadRelaxed() != 1) {
253 QSurfaceFormatPrivate *newd = new QSurfaceFormatPrivate(d);
254 if (!d->ref.deref())
255 delete d;
256 d = newd;
257 }
258}
259
260/*!
261 Constructs a copy of \a other.
262*/
263QSurfaceFormat::QSurfaceFormat(const QSurfaceFormat &other)
264{
265 d = other.d;
266 d->ref.ref();
267}
268
269/*!
270 Assigns \a other to this object.
271*/
272QSurfaceFormat &QSurfaceFormat::operator=(const QSurfaceFormat &other)
273{
274 if (d != other.d) {
275 other.d->ref.ref();
276 if (!d->ref.deref())
277 delete d;
278 d = other.d;
279 }
280 return *this;
281}
282
283/*!
284 Destroys the QSurfaceFormat.
285*/
286QSurfaceFormat::~QSurfaceFormat()
287{
288 if (!d->ref.deref())
289 delete d;
290}
291
292/*!
293 \fn bool QSurfaceFormat::stereo() const
294
295 Returns \c true if stereo buffering is enabled; otherwise returns
296 false. Stereo buffering is disabled by default.
297
298 \sa setStereo()
299*/
300
301/*!
302 If \a enable is true enables stereo buffering; otherwise disables
303 stereo buffering.
304
305 Stereo buffering is disabled by default.
306
307 Stereo buffering provides extra color buffers to generate left-eye
308 and right-eye images.
309
310 \sa stereo()
311*/
312void QSurfaceFormat::setStereo(bool enable)
313{
314 QSurfaceFormat::FormatOptions newOptions = d->opts;
315 newOptions.setFlag(QSurfaceFormat::StereoBuffers, enable);
316
317 if (int(newOptions) != int(d->opts)) {
318 detach();
319 d->opts = newOptions;
320 }
321}
322
323/*!
324 Returns the number of samples per pixel when multisampling is
325 enabled, or \c -1 when multisampling is disabled. The default
326 return value is \c -1.
327
328 \sa setSamples()
329*/
330int QSurfaceFormat::samples() const
331{
332 return d->numSamples;
333}
334
335/*!
336 Set the preferred number of samples per pixel when multisampling
337 is enabled to \a numSamples. By default, multisampling is disabled.
338
339 \sa samples()
340*/
341void QSurfaceFormat::setSamples(int numSamples)
342{
343 if (d->numSamples != numSamples) {
344 detach();
345 d->numSamples = numSamples;
346 }
347}
348
349/*!
350 \since 5.3
351
352 Sets the format options to \a options.
353
354 \sa options(), testOption()
355*/
356void QSurfaceFormat::setOptions(QSurfaceFormat::FormatOptions options)
357{
358 if (int(d->opts) != int(options)) {
359 detach();
360 d->opts = options;
361 }
362}
363
364/*!
365 \since 5.3
366
367 Sets the format option \a option if \a on is true; otherwise, clears the option.
368
369 \sa setOptions(), options(), testOption()
370*/
371void QSurfaceFormat::setOption(QSurfaceFormat::FormatOption option, bool on)
372{
373 if (testOption(option) == on)
374 return;
375 detach();
376 if (on)
377 d->opts |= option;
378 else
379 d->opts &= ~option;
380}
381
382/*!
383 \since 5.3
384
385 Returns true if the format option \a option is set; otherwise returns false.
386
387 \sa options()
388*/
389bool QSurfaceFormat::testOption(QSurfaceFormat::FormatOption option) const
390{
391 return d->opts & option;
392}
393
394/*!
395 \since 5.3
396
397 Returns the currently set format options.
398
399 \sa setOption(), setOptions(), testOption()
400*/
401QSurfaceFormat::FormatOptions QSurfaceFormat::options() const
402{
403 return d->opts;
404}
405
406/*!
407 Set the minimum depth buffer size to \a size.
408
409 \sa depthBufferSize()
410*/
411void QSurfaceFormat::setDepthBufferSize(int size)
412{
413 if (d->depthSize != size) {
414 detach();
415 d->depthSize = size;
416 }
417}
418
419/*!
420 Returns the depth buffer size.
421
422 \sa setDepthBufferSize()
423*/
424int QSurfaceFormat::depthBufferSize() const
425{
426 return d->depthSize;
427}
428
429/*!
430 Set the swap \a behavior of the surface.
431
432 The swap behavior specifies whether single, double, or triple
433 buffering is desired. The default, DefaultSwapBehavior,
434 gives the default swap behavior of the platform.
435*/
436void QSurfaceFormat::setSwapBehavior(SwapBehavior behavior)
437{
438 if (d->swapBehavior != behavior) {
439 detach();
440 d->swapBehavior = behavior;
441 }
442}
443
444/*!
445 Returns the configured swap behaviour.
446
447 \sa setSwapBehavior()
448*/
449QSurfaceFormat::SwapBehavior QSurfaceFormat::swapBehavior() const
450{
451 return d->swapBehavior;
452}
453
454/*!
455 Returns \c true if the alpha buffer size is greater than zero.
456
457 This means that the surface might be used with per pixel
458 translucency effects.
459*/
460bool QSurfaceFormat::hasAlpha() const
461{
462 return d->alphaBufferSize > 0;
463}
464
465/*!
466 Set the preferred stencil buffer size to \a size bits.
467
468 \sa stencilBufferSize()
469*/
470void QSurfaceFormat::setStencilBufferSize(int size)
471{
472 if (d->stencilSize != size) {
473 detach();
474 d->stencilSize = size;
475 }
476}
477
478/*!
479 Returns the stencil buffer size in bits.
480
481 \sa setStencilBufferSize()
482*/
483int QSurfaceFormat::stencilBufferSize() const
484{
485 return d->stencilSize;
486}
487
488/*!
489 Get the size in bits of the red channel of the color buffer.
490*/
491int QSurfaceFormat::redBufferSize() const
492{
493 return d->redBufferSize;
494}
495
496/*!
497 Get the size in bits of the green channel of the color buffer.
498*/
499int QSurfaceFormat::greenBufferSize() const
500{
501 return d->greenBufferSize;
502}
503
504/*!
505 Get the size in bits of the blue channel of the color buffer.
506*/
507int QSurfaceFormat::blueBufferSize() const
508{
509 return d->blueBufferSize;
510}
511
512/*!
513 Get the size in bits of the alpha channel of the color buffer.
514*/
515int QSurfaceFormat::alphaBufferSize() const
516{
517 return d->alphaBufferSize;
518}
519
520/*!
521 Set the desired \a size in bits of the red channel of the color buffer.
522*/
523void QSurfaceFormat::setRedBufferSize(int size)
524{
525 if (d->redBufferSize != size) {
526 detach();
527 d->redBufferSize = size;
528 }
529}
530
531/*!
532 Set the desired \a size in bits of the green channel of the color buffer.
533*/
534void QSurfaceFormat::setGreenBufferSize(int size)
535{
536 if (d->greenBufferSize != size) {
537 detach();
538 d->greenBufferSize = size;
539 }
540}
541
542/*!
543 Set the desired \a size in bits of the blue channel of the color buffer.
544*/
545void QSurfaceFormat::setBlueBufferSize(int size)
546{
547 if (d->blueBufferSize != size) {
548 detach();
549 d->blueBufferSize = size;
550 }
551}
552
553/*!
554 Set the desired \a size in bits of the alpha channel of the color buffer.
555*/
556void QSurfaceFormat::setAlphaBufferSize(int size)
557{
558 if (d->alphaBufferSize != size) {
559 detach();
560 d->alphaBufferSize = size;
561 }
562}
563
564/*!
565 Sets the desired renderable \a type.
566
567 Chooses between desktop OpenGL, OpenGL ES, and OpenVG.
568*/
569void QSurfaceFormat::setRenderableType(RenderableType type)
570{
571 if (d->renderableType != type) {
572 detach();
573 d->renderableType = type;
574 }
575}
576
577/*!
578 Gets the renderable type.
579
580 Chooses between desktop OpenGL, OpenGL ES, and OpenVG.
581*/
582QSurfaceFormat::RenderableType QSurfaceFormat::renderableType() const
583{
584 return d->renderableType;
585}
586
587/*!
588 Sets the desired OpenGL context \a profile.
589
590 This setting is ignored if the requested OpenGL version is
591 less than 3.2.
592*/
593void QSurfaceFormat::setProfile(OpenGLContextProfile profile)
594{
595 if (d->profile != profile) {
596 detach();
597 d->profile = profile;
598 }
599}
600
601/*!
602 Get the configured OpenGL context profile.
603
604 This setting is ignored if the requested OpenGL version is
605 less than 3.2.
606*/
607QSurfaceFormat::OpenGLContextProfile QSurfaceFormat::profile() const
608{
609 return d->profile;
610}
611
612/*!
613 Sets the desired \a major OpenGL version.
614*/
615void QSurfaceFormat::setMajorVersion(int major)
616{
617 if (d->major != major) {
618 detach();
619 d->major = major;
620 }
621}
622
623/*!
624 Returns the major OpenGL version.
625
626 The default version is 2.0.
627*/
628int QSurfaceFormat::majorVersion() const
629{
630 return d->major;
631}
632
633/*!
634 Sets the desired \a minor OpenGL version.
635
636 The default version is 2.0.
637*/
638void QSurfaceFormat::setMinorVersion(int minor)
639{
640 if (d->minor != minor) {
641 detach();
642 d->minor = minor;
643 }
644}
645
646/*!
647 Returns the minor OpenGL version.
648*/
649int QSurfaceFormat::minorVersion() const
650{
651 return d->minor;
652}
653
654/*!
655 Returns a QPair<int, int> representing the OpenGL version.
656
657 Useful for version checks, for example format.version() >= qMakePair(3, 2)
658*/
659QPair<int, int> QSurfaceFormat::version() const
660{
661 return qMakePair(d->major, d->minor);
662}
663
664/*!
665 Sets the desired \a major and \a minor OpenGL versions.
666
667 The default version is 2.0.
668*/
669void QSurfaceFormat::setVersion(int major, int minor)
670{
671 if (d->minor != minor || d->major != major) {
672 detach();
673 d->minor = minor;
674 d->major = major;
675 }
676}
677
678/*!
679 Sets the preferred swap interval. The swap interval specifies the
680 minimum number of video frames that are displayed before a buffer
681 swap occurs. This can be used to sync the GL drawing into a window
682 to the vertical refresh of the screen.
683
684 Setting an \a interval value of 0 will turn the vertical refresh
685 syncing off, any value higher than 0 will turn the vertical
686 syncing on. Setting \a interval to a higher value, for example 10,
687 results in having 10 vertical retraces between every buffer swap.
688
689 The default interval is 1.
690
691 Changing the swap interval may not be supported by the underlying
692 platform. In this case, the request will be silently ignored.
693
694 \since 5.3
695
696 \sa swapInterval()
697 */
698void QSurfaceFormat::setSwapInterval(int interval)
699{
700 if (d->swapInterval != interval) {
701 detach();
702 d->swapInterval = interval;
703 }
704}
705
706/*!
707 Returns the swap interval.
708
709 \since 5.3
710
711 \sa setSwapInterval()
712*/
713int QSurfaceFormat::swapInterval() const
714{
715 return d->swapInterval;
716}
717
718/*!
719 Sets the preferred \a colorSpace.
720
721 For example, this allows requesting windows with default framebuffers that
722 are sRGB-capable on platforms that support it.
723
724 \note When the requested color space is not supported by the platform, the
725 request is ignored. Query the QSurfaceFormat after window creation to verify
726 if the color space request could be honored or not.
727
728 \note This setting controls if the default framebuffer of the window is
729 capable of updates and blending in a given color space. It does not change
730 applications' output by itself. The applications' rendering code will still
731 have to opt in via the appropriate OpenGL calls to enable updates and
732 blending to be performed in the given color space instead of using the
733 standard linear operations.
734
735 \since 6.0
736
737 \sa colorSpace()
738 */
739void QSurfaceFormat::setColorSpace(const QColorSpace &colorSpace)
740{
741 if (d->colorSpace != colorSpace) {
742 detach();
743 d->colorSpace = colorSpace;
744 }
745}
746
747/*!
748 \overload
749
750 Sets the colorspace to one of the predefined values.
751
752 \since 5.10
753
754 \sa colorSpace()
755 */
756void QSurfaceFormat::setColorSpace(ColorSpace colorSpace)
757{
758 switch (colorSpace) {
759 case DefaultColorSpace:
760 setColorSpace(QColorSpace());
761 break;
762 case sRGBColorSpace:
763 setColorSpace(QColorSpace::SRgb);
764 break;
765 }
766}
767
768/*!
769 \return the color space.
770
771 \since 5.10
772
773 \sa setColorSpace()
774*/
775const QColorSpace &QSurfaceFormat::colorSpace() const
776{
777 return d->colorSpace;
778}
779
780Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format)
781
782/*!
783 Sets the global default surface \a format.
784
785 This format is used by default in QOpenGLContext, QWindow, QOpenGLWidget and
786 similar classes.
787
788 It can always be overridden on a per-instance basis by using the class in
789 question's own setFormat() function. However, it is often more convenient to
790 set the format for all windows once at the start of the application. It also
791 guarantees proper behavior in cases where shared contexts are required,
792 because settings the format via this function guarantees that all contexts
793 and surfaces, even the ones created internally by Qt, will use the same
794 format.
795
796 \note When setting Qt::AA_ShareOpenGLContexts, it is strongly recommended to
797 place the call to this function before the construction of the
798 QGuiApplication or QApplication. Otherwise \a format will not be applied to
799 the global share context and therefore issues may arise with context sharing
800 afterwards.
801
802 \since 5.4
803 \sa defaultFormat()
804 */
805void QSurfaceFormat::setDefaultFormat(const QSurfaceFormat &format)
806{
807#ifndef QT_NO_OPENGL
808 if (qApp) {
809 QOpenGLContext *globalContext = QOpenGLContext::globalShareContext();
810 if (globalContext && globalContext->isValid()) {
811 qWarning("Warning: Setting a new default format with a different version or profile "
812 "after the global shared context is created may cause issues with context "
813 "sharing.");
814 }
815 }
816#endif
817 *qt_default_surface_format() = format;
818}
819
820/*!
821 Returns the global default surface format.
822
823 When setDefaultFormat() is not called, this is a default-constructed QSurfaceFormat.
824
825 \since 5.4
826 \sa setDefaultFormat()
827 */
828QSurfaceFormat QSurfaceFormat::defaultFormat()
829{
830 return *qt_default_surface_format();
831}
832
833/*!
834 Returns \c true if all the options of the two QSurfaceFormat objects
835 \a a and \a b are equal.
836
837 \relates QSurfaceFormat
838*/
839bool operator==(const QSurfaceFormat& a, const QSurfaceFormat& b)
840{
841 return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
842 && a.d->stencilSize == b.d->stencilSize
843 && a.d->redBufferSize == b.d->redBufferSize
844 && a.d->greenBufferSize == b.d->greenBufferSize
845 && a.d->blueBufferSize == b.d->blueBufferSize
846 && a.d->alphaBufferSize == b.d->alphaBufferSize
847 && a.d->depthSize == b.d->depthSize
848 && a.d->numSamples == b.d->numSamples
849 && a.d->swapBehavior == b.d->swapBehavior
850 && a.d->profile == b.d->profile
851 && a.d->major == b.d->major
852 && a.d->minor == b.d->minor
853 && a.d->swapInterval == b.d->swapInterval);
854}
855
856/*!
857 Returns \c false if all the options of the two QSurfaceFormat objects
858 \a a and \a b are equal; otherwise returns \c true.
859
860 \relates QSurfaceFormat
861*/
862bool operator!=(const QSurfaceFormat& a, const QSurfaceFormat& b)
863{
864 return !(a == b);
865}
866
867#ifndef QT_NO_DEBUG_STREAM
868QDebug operator<<(QDebug dbg, const QSurfaceFormat &f)
869{
870 const QSurfaceFormatPrivate * const d = f.d;
871 QDebugStateSaver saver(dbg);
872
873 dbg.nospace() << "QSurfaceFormat("
874 << "version " << d->major << '.' << d->minor
875 << ", options " << d->opts
876 << ", depthBufferSize " << d->depthSize
877 << ", redBufferSize " << d->redBufferSize
878 << ", greenBufferSize " << d->greenBufferSize
879 << ", blueBufferSize " << d->blueBufferSize
880 << ", alphaBufferSize " << d->alphaBufferSize
881 << ", stencilBufferSize " << d->stencilSize
882 << ", samples " << d->numSamples
883 << ", swapBehavior " << d->swapBehavior
884 << ", swapInterval " << d->swapInterval
885 << ", colorSpace " << d->colorSpace
886 << ", profile " << d->profile
887 << ')';
888
889 return dbg;
890}
891#endif
892
893QT_END_NAMESPACE
894