aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickwindow.cpp130
-rw-r--r--src/quick/items/qquickwindow.h8
-rw-r--r--src/quick/items/qquickwindow_p.h3
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp76
4 files changed, 215 insertions, 2 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 6a56a5dc82..a494f5ea5d 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -77,7 +77,9 @@ QT_BEGIN_NAMESPACE
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
-bool QQuickWindowPrivate::defaultAlphaBuffer(0);
+bool QQuickWindowPrivate::defaultAlphaBuffer = false;
+bool QQuickWindowPrivate::defaultFormatInitialized = false;
+QSurfaceFormat QQuickWindowPrivate::defaultFormat;
void QQuickWindowPrivate::updateFocusItemTransform()
{
@@ -457,7 +459,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
}
q->setSurfaceType(QWindow::OpenGLSurface);
- q->setFormat(sg->defaultSurfaceFormat());
+ q->setFormat(q->defaultFormat());
animationController = new QQuickAnimatorController();
animationController->m_window = q;
@@ -3420,6 +3422,130 @@ void QQuickWindow::resetOpenGLState()
}
/*!
+ * \brief QQuickWindow::setDefaultFormat
+ * \since 5.4
+ * @brief Sets the global default surface format that is used for all new QQuickWindow instances.
+ *
+ * While it is possible to specify a QSurfaceFormat for every QQuickWindow by
+ * calling the member function setFormat(), windows may also be created from
+ * QML by using the Window and ApplicationWindow elements. In this case there
+ * is no C++ code involved in the creation of the window instance, yet
+ * applications may still wish to set certain surface format values, for
+ * example to request a given OpenGL version or profile. Such applications can
+ * call this static functions in main(). \a format will be used for all Quick
+ * windows created afterwards.
+ *
+ * \note The default value for the default format is not necessarily a
+ * default-constructed QSurfaceFormat. It may already have depth, stencil and alpha
+ * buffer sizes set. Unless there is a need to change all these sizes, the format should
+ * first be queried via defaultFormat() and the changes should be applied to that,
+ * instead of merely starting with default-constructed QSurfaceFormat.
+ *
+ * \sa setFormat(), format(), defaultFormat()
+ */
+void QQuickWindow::setDefaultFormat(const QSurfaceFormat &format)
+{
+ QQuickWindowPrivate::defaultFormatInitialized = true;
+ QQuickWindowPrivate::defaultFormat = format;
+}
+
+/*!
+ * \brief QQuickWindow::defaultFormat
+ * \since 5.4
+ * \return The global default surface format that is used for all QQuickWindow instances.
+ * \note This function requires a QGuiApplication or QApplication instance.
+ */
+QSurfaceFormat QQuickWindow::defaultFormat()
+{
+ if (!QQuickWindowPrivate::defaultFormatInitialized) {
+ QQuickWindowPrivate::defaultFormatInitialized = true;
+ QQuickWindowPrivate::defaultFormat = QSGRenderLoop::instance()->sceneGraphContext()->defaultSurfaceFormat();
+ }
+ return QQuickWindowPrivate::defaultFormat;
+}
+
+/*!
+ * \brief QQuickWindow::glslVersion
+ * \since 5.4
+ * \return The OpenGL Shading Language version for this window.
+ *
+ * QML components that need to be usable on different platforms and environments may need
+ * to deal with different OpenGL versions if they include ShaderEffect items. The source
+ * code for a given shader may not be compatible with an OpenGL context that targets a
+ * different OpenGL version or profile, hence it might be necessary to provide multiple
+ * versions of the shader. This property helps in deciding which shader source should be
+ * chosen.
+ *
+ * The value corresponds to GLSL version declarations, for example an OpenGL 4.2 core
+ * profile context will result in the value \e{420 core}, while an OpenGL ES 3.0 context
+ * gives \e{300 es}. For OpenGL (ES) 2 the value will be an empty string since the
+ * corresponding shading language does not use version declarations.
+ *
+ * \note The value does not necessarily indicate that the shader source must target that
+ * specific version. For example, compatibility profiles and ES 3.x all allow using
+ * OpenGL 2 style shaders. The most important for reusable components is to check for
+ * core profiles since these do not accept shaders with the old syntax.
+ *
+ * \sa setFormat(), glslIsCoreProfile()
+ */
+QString QQuickWindow::glslVersion() const
+{
+ QString ver;
+ QOpenGLContext *ctx = openglContext();
+ if (ctx) {
+ const QSurfaceFormat fmt = ctx->format();
+ if (fmt.renderableType() == QSurfaceFormat::OpenGLES
+ && fmt.majorVersion() >= 3) {
+ ver += QLatin1Char(fmt.majorVersion() + '0');
+ ver += QLatin1Char(fmt.minorVersion() + '0');
+ ver += QLatin1String("0 es");
+ } else if (fmt.renderableType() == QSurfaceFormat::OpenGL
+ && fmt.majorVersion() >= 3) {
+ if (fmt.version() == qMakePair(3, 0)) {
+ ver = QStringLiteral("130");
+ } else if (fmt.version() == qMakePair(3, 1)) {
+ ver = QStringLiteral("140");
+ } else if (fmt.version() == qMakePair(3, 2)) {
+ ver = QStringLiteral("150");
+ } else {
+ ver += QLatin1Char(fmt.majorVersion() + '0');
+ ver += QLatin1Char(fmt.minorVersion() + '0');
+ ver += QLatin1Char('0');
+ }
+ if (fmt.version() >= qMakePair(3, 2)) {
+ if (fmt.profile() == QSurfaceFormat::CoreProfile)
+ ver += QStringLiteral(" core");
+ else if (fmt.profile() == QSurfaceFormat::CompatibilityProfile)
+ ver += QStringLiteral(" compatibility");
+ }
+ }
+ }
+ return ver;
+}
+
+/*!
+ * \brief QQuickWindow::glslIsCoreProfile
+ * \since 5.4
+ * \return True if the window is rendering using OpenGL core profile.
+ *
+ * This is convenience function to check if the window's OpenGL context is a core profile
+ * context. It is more efficient to perform the check via this function than parsing the
+ * string returned from glslVersion().
+ *
+ * Resusable QML components will typically use this function in bindings in order to
+ * choose between core and non core profile compatible shader sources.
+ *
+ * To retrieve more information about the shading language, use glslVersion().
+ *
+ * \sa glslVersion()
+ */
+bool QQuickWindow::glslIsCoreProfile() const
+{
+ QOpenGLContext *ctx = openglContext();
+ return ctx ? ctx->format().profile() == QSurfaceFormat::CoreProfile : false;
+}
+
+/*!
\qmlproperty string Window::title
The window's title in the windowing system.
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index 2572f31375..1a4adb0785 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -67,6 +67,8 @@ class Q_QUICK_EXPORT QQuickWindow : public QWindow
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(QQuickItem* contentItem READ contentItem CONSTANT)
Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged REVISION 1)
+ Q_PROPERTY(QString glslVersion READ glslVersion CONSTANT REVISION 2)
+ Q_PROPERTY(bool glslIsCoreProfile READ glslIsCoreProfile CONSTANT REVISION 2)
Q_CLASSINFO("DefaultProperty", "data")
Q_DECLARE_PRIVATE(QQuickWindow)
public:
@@ -136,6 +138,12 @@ public:
QOpenGLContext *openglContext() const;
+ static void setDefaultFormat(const QSurfaceFormat &format);
+ static QSurfaceFormat defaultFormat();
+
+ QString glslVersion() const;
+ bool glslIsCoreProfile() const;
+
Q_SIGNALS:
void frameSwapped();
Q_REVISION(2) void openglContextCreated(QOpenGLContext *context);
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 421651b483..872a054666 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -247,6 +247,9 @@ public:
QString *untranslatedMessage,
bool isEs);
+ static bool defaultFormatInitialized;
+ static QSurfaceFormat defaultFormat;
+
private:
static void cleanupNodesOnShutdown(QQuickItem *);
};
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index 28945c4cb5..4ec479a924 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -357,6 +357,9 @@ private slots:
void contentItemSize();
+ void defaultSurfaceFormat();
+ void glslVersion();
+
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -1741,6 +1744,79 @@ void tst_qquickwindow::contentItemSize()
QCOMPARE(QSizeF(rect->width(), rect->height()), size);
}
+void tst_qquickwindow::defaultSurfaceFormat()
+{
+ // It is quite difficult to verify anything for real since the resulting format after
+ // surface/context creation can be anything, depending on the platform and drivers,
+ // and many options and settings may fail in various configurations, but test at
+ // least using some harmless settings to check that the global, static format is
+ // taken into account in the requested format.
+
+ QSurfaceFormat savedDefaultFormat = QQuickWindow::defaultFormat();
+
+ // Verify that depth and stencil are set, as they should be, unless they are disabled
+ // via environment variables.
+ QVERIFY(savedDefaultFormat.depthBufferSize() >= 16);
+ QVERIFY(savedDefaultFormat.stencilBufferSize() >= 8);
+
+ QSurfaceFormat format = savedDefaultFormat;
+ format.setSwapInterval(0);
+ format.setRedBufferSize(8);
+ format.setGreenBufferSize(8);
+ format.setBlueBufferSize(8);
+ format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ format.setOption(QSurfaceFormat::DebugContext);
+ QQuickWindow::setDefaultFormat(format);
+
+ QQuickWindow window;
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ const QSurfaceFormat reqFmt = window.requestedFormat();
+ QCOMPARE(format.swapInterval(), reqFmt.swapInterval());
+ QCOMPARE(format.redBufferSize(), reqFmt.redBufferSize());
+ QCOMPARE(format.greenBufferSize(), reqFmt.greenBufferSize());
+ QCOMPARE(format.blueBufferSize(), reqFmt.blueBufferSize());
+ QCOMPARE(format.profile(), reqFmt.profile());
+ QCOMPARE(int(format.options()), int(reqFmt.options()));
+
+ QQuickWindow::setDefaultFormat(savedDefaultFormat);
+}
+
+void tst_qquickwindow::glslVersion()
+{
+ QQuickWindow window;
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ // Core profile is never requested by default.
+ QVERIFY(!window.glslIsCoreProfile());
+
+ // Get the format from the context, not the window. The actual OpenGL version and
+ // related settings are associated with the context and are only written back to the
+ // context's format.
+ QSurfaceFormat format = window.openglContext()->format();
+
+ if (format.renderableType() == QSurfaceFormat::OpenGL) {
+ if (format.majorVersion() == 2)
+ QCOMPARE(window.glslVersion(), QString());
+ else if (format.majorVersion() == 3)
+ QVERIFY(window.glslVersion().startsWith('3')
+ || window.glslVersion() == QStringLiteral("130")
+ || window.glslVersion() == QStringLiteral("140")
+ || window.glslVersion() == QStringLiteral("150"));
+ else if (format.majorVersion() == 4)
+ QVERIFY(window.glslVersion().startsWith('4'));
+ QVERIFY(!window.glslVersion().contains(QStringLiteral("core")));
+ QVERIFY(!window.glslVersion().contains(QStringLiteral("es")));
+ } else if (format.renderableType() == QSurfaceFormat::OpenGLES) {
+ if (format.majorVersion() == 2)
+ QCOMPARE(window.glslVersion(), QString());
+ else
+ QVERIFY(window.glslVersion().contains(QStringLiteral("es")));
+ }
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"