Add default format to QSurfaceFormat

Add defaultFormat() and setDefaultFormat() statics to QSurfaceFormat.
These define the default values for the requestedFormat members of
QOpenGLContext, QWindow and QOpenGLWidget (and implicitly QOpenGLWindow,
QQuickWindow, etc.)

This replaces QQuickWindow::setDefaultFormat() which can now be removed.

The main inspiration here is not the convenience (avoiding setFormat() calls
for all windows/widgets), but robustness: by setting the format once at the start
of the application, all windows and contexts, including the internal share context
used by QOpenGLWidget and QQuickWidget, will use the same format, eliminating
the possibility of failing due to trying to share between incompatible contexts.

Furthermore, since such a functionality is anyway mandatory for QQuickWindow
(due to the possibility of creating windows from QML code), extending it to
QSurfaceFormat and QOpenGLContext/QWindow is the next logical step.

Change-Id: Ie94486adc489d17fecfcebb7050fecedffd2688b
Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
This commit is contained in:
Laszlo Agocs 2014-08-07 16:45:05 +02:00
parent 41a7072195
commit 22e4391413
8 changed files with 112 additions and 4 deletions

View File

@ -489,6 +489,12 @@ QOpenGLContext::QOpenGLContext(QObject *parent)
/*!
Sets the \a format the OpenGL context should be compatible with. You need
to call create() before it takes effect.
When the format is not explicitly set via this function, the format returned
by QSurfaceFormat::defaultFormat() will be used. This means that when having
multiple contexts, individual calls to this function can be replaced by one
single call to QSurfaceFormat::setDefaultFormat() before creating the first
context.
*/
void QOpenGLContext::setFormat(const QSurfaceFormat &format)
{

View File

@ -211,6 +211,7 @@ public:
, workaround_missingPrecisionQualifiers(false)
, active_engine(0)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
virtual ~QOpenGLContextPrivate()

View File

@ -196,6 +196,9 @@ public:
/*!
Constructs a default initialized QSurfaceFormat.
\note By default OpenGL 2.0 is requested since this provides the highest
grade of portability between platforms and OpenGL implementations.
*/
QSurfaceFormat::QSurfaceFormat() : d(new QSurfaceFormatPrivate)
{
@ -730,6 +733,43 @@ int QSurfaceFormat::swapInterval() const
return d->swapInterval;
}
Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format)
/*!
Sets the global default surface \a format.
This format is used by default in QOpenGLContext, QWindow, QOpenGLWidget and
similar classes.
It can always be overridden on a per-instance basis by using the class in
question's own setFormat() function. However, it is often more convenient to
set the format for all windows once at the start of the application. It also
guarantees proper behavior in cases where shared contexts are required,
because settings the format via this function guarantees that all contexts
and surfaces, even the ones created internally by Qt, will use the same
format.
\since 5.4
\sa defaultFormat()
*/
void QSurfaceFormat::setDefaultFormat(const QSurfaceFormat &format)
{
*qt_default_surface_format() = format;
}
/*!
Returns the global default surface format.
When setDefaultFormat() is not called, this is a default-constructed QSurfaceFormat.
\since 5.4
\sa setDefaultFormat()
*/
QSurfaceFormat QSurfaceFormat::defaultFormat()
{
return *qt_default_surface_format();
}
/*!
Returns \c true if all the options of the two QSurfaceFormat objects
\a a and \a b are equal.

View File

@ -138,6 +138,9 @@ public:
int swapInterval() const;
void setSwapInterval(int interval);
static void setDefaultFormat(const QSurfaceFormat &format);
static QSurfaceFormat defaultFormat();
private:
QSurfaceFormatPrivate *d;

View File

@ -224,6 +224,8 @@ void QWindowPrivate::init()
exit(1);
}
QGuiApplicationPrivate::window_list.prepend(q);
requestedFormat = QSurfaceFormat::defaultFormat();
}
/*!
@ -672,7 +674,13 @@ void QWindow::setModality(Qt::WindowModality modality)
this function after create() has been called will not re-resolve the
surface format of the native surface.
\sa create(), destroy()
When the format is not explicitly set via this function, the format returned
by QSurfaceFormat::defaultFormat() will be used. This means that when having
multiple windows, individual calls to this function can be replaced by one
single call to QSurfaceFormat::setDefaultFormat() before creating the first
window.
\sa create(), destroy(), QSurfaceFormat::setDefaultFormat()
*/
void QWindow::setFormat(const QSurfaceFormat &format)
{

View File

@ -178,3 +178,22 @@ void MyGLWidget::cleanup()
doneCurrent();
}
//! [5]
//! [6]
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setVersion(3, 2);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
MyWidget widget;
widget.show();
return app.exec();
}
//! [6]

View File

@ -107,7 +107,8 @@ QT_BEGIN_NAMESPACE
setFormat(). Keep in mind however that having multiple QOpenGLWidget
instances in the same window requires that they all use the same
format, or at least formats that do not make the contexts
non-sharable.
non-sharable. To overcome this issue, prefer using
QSurfaceFormat::setDefaultFormat() instead of setFormat().
\section1 Painting Techniques
@ -190,7 +191,7 @@ QT_BEGIN_NAMESPACE
\snippet code/doc_gui_widgets_qopenglwidget.cpp 0
Alternatively, the prefixing of each and every OpenGL call can be avoidided by deriving
Alternatively, the prefixing of each and every OpenGL call can be avoided by deriving
from QOpenGLFunctions instead:
\snippet code/doc_gui_widgets_qopenglwidget.cpp 1
@ -206,6 +207,12 @@ QT_BEGIN_NAMESPACE
\snippet code/doc_gui_widgets_qopenglwidget.cpp 3
As described above, it is simpler and more robust to set the requested format
globally so that it applies to all windows and contexts during the lifetime of
the application. Below is an example of this:
\snippet code/doc_gui_widgets_qopenglwidget.cpp 6
\section1 Relation to QGLWidget
The legacy QtOpenGL module (classes prefixed with QGL) provides a widget
@ -392,6 +399,7 @@ public:
paintDevice(0),
inBackingStorePaint(false)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
~QOpenGLWidgetPrivate()
@ -620,13 +628,18 @@ QOpenGLWidget::~QOpenGLWidget()
/*!
Sets the requested surface \a format.
When the format is not explicitly set via this function, the format returned by
QSurfaceFormat::defaultFormat() will be used. This means that when having multiple
OpenGL widgets, individual calls to this function can be replaced by one single call to
QSurfaceFormat::setDefaultFormat() before creating the first widget.
\note Requesting an alpha buffer via this function will not lead to the desired results
and should be avoided. Instead, use Qt::WA_AlwaysStackOnTop to enable semi-transparent
QOpenGLWidget instances with other widgets visible underneath. Keep in mind however that
this breaks the stacking order, so it will no longer be possible to have other widgets
on top of the QOpenGLWidget.
\sa format(), Qt::WA_AlwaysStackOnTop
\sa format(), Qt::WA_AlwaysStackOnTop, QSurfaceFormat::setDefaultFormat()
*/
void QOpenGLWidget::setFormat(const QSurfaceFormat &format)
{

View File

@ -102,6 +102,7 @@ private slots:
void textureblitterPartOriginTopLeftSourceRectTransform();
void textureblitterFullTargetRectTransform();
void textureblitterPartTargetRectTransform();
void defaultSurfaceFormat();
#ifdef USE_GLX
void glxContextWrap();
@ -1110,6 +1111,23 @@ void tst_QOpenGL::textureblitterPartTargetRectTransform()
QCOMPARE(targetBottomRight, expectedBottomRight);
}
void tst_QOpenGL::defaultSurfaceFormat()
{
QSurfaceFormat fmt;
QVERIFY(QSurfaceFormat::defaultFormat() == fmt);
fmt.setDepthBufferSize(16);
QSurfaceFormat::setDefaultFormat(fmt);
QVERIFY(QSurfaceFormat::defaultFormat() == fmt);
QCOMPARE(QSurfaceFormat::defaultFormat().depthBufferSize(), 16);
QScopedPointer<QWindow> window(new QWindow);
QVERIFY(window->requestedFormat() == fmt);
QScopedPointer<QOpenGLContext> context(new QOpenGLContext);
QVERIFY(context->format() == fmt);
}
#ifdef USE_GLX
void tst_QOpenGL::glxContextWrap()
{