aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/quick/quickwidgets/CMakeLists.txt2
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/CMakeLists.txt (renamed from examples/quick/quickwidgets/qquickviewcomparison/CMakeLists.txt)21
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/doc/images/qquickwidgetversuswindow-opengl-example.jpgbin0 -> 25452 bytes
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/doc/src/qquickwidgetversuswindow_opengl.qdoc62
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/fbitem.cpp (renamed from examples/quick/quickwidgets/qquickviewcomparison/fbitem.cpp)0
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/fbitem.h (renamed from examples/quick/quickwidgets/qquickviewcomparison/fbitem.h)0
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/logo.cpp (renamed from examples/quick/quickwidgets/qquickviewcomparison/logo.cpp)0
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/logo.h (renamed from examples/quick/quickwidgets/qquickviewcomparison/logo.h)0
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/main.cpp (renamed from examples/quick/quickwidgets/qquickviewcomparison/main.cpp)0
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/mainwindow.cpp (renamed from examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp)2
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/mainwindow.h (renamed from examples/quick/quickwidgets/qquickviewcomparison/mainwindow.h)0
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/qquickwidgetversuswindow_opengl.pro (renamed from examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.pro)6
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/qquickwidgetversuswindow_opengl.qrc (renamed from examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.qrc)2
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/test.qml (renamed from examples/quick/quickwidgets/qquickviewcomparison/test.qml)0
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/wobble.frag (renamed from examples/quick/quickwidgets/qquickviewcomparison/wobble.frag)0
-rw-r--r--examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/wobble.frag.qsb (renamed from examples/quick/quickwidgets/qquickviewcomparison/wobble.frag.qsb)bin1717 -> 1717 bytes
-rw-r--r--examples/quick/quickwidgets/quickwidget/CMakeLists.txt3
-rw-r--r--examples/quick/quickwidgets/quickwidget/customgl.qml69
-rw-r--r--examples/quick/quickwidgets/quickwidget/fbitem.cpp100
-rw-r--r--examples/quick/quickwidgets/quickwidget/fbitem.h64
-rw-r--r--examples/quick/quickwidgets/quickwidget/main.cpp79
-rw-r--r--examples/quick/quickwidgets/quickwidget/quickwidget.pro3
-rw-r--r--examples/quick/quickwidgets/quickwidget/quickwidget.qrc2
-rw-r--r--examples/quick/quickwidgets/quickwidget/rotatingsquare.qml29
-rw-r--r--examples/quick/quickwidgets/quickwidget/rotatingsquaretab.qml76
-rw-r--r--examples/quick/quickwidgets/quickwidgets.pro2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp23
-rw-r--r--src/quick/items/qquickrendercontrol_p.h8
-rw-r--r--src/quick/scenegraph/qsgrhisupport.cpp9
-rw-r--r--src/quick/scenegraph/qsgrhisupport_p.h1
-rw-r--r--src/quickwidgets/CMakeLists.txt8
-rw-r--r--src/quickwidgets/qquickwidget.cpp558
-rw-r--r--src/quickwidgets/qquickwidget_p.h32
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp17
34 files changed, 499 insertions, 679 deletions
diff --git a/examples/quick/quickwidgets/CMakeLists.txt b/examples/quick/quickwidgets/CMakeLists.txt
index e0537e1e01..f205e23600 100644
--- a/examples/quick/quickwidgets/CMakeLists.txt
+++ b/examples/quick/quickwidgets/CMakeLists.txt
@@ -1,2 +1,2 @@
qt_internal_add_example(quickwidget)
-qt_internal_add_example(qquickviewcomparison)
+qt_internal_add_example(qquickwidgetversuswindow_opengl)
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/CMakeLists.txt b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/CMakeLists.txt
index 2ac77c313c..c49bb915ec 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/CMakeLists.txt
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.16)
-project(qquickviewcomparison LANGUAGES CXX)
+project(qquickwidgetversuswindow_opengl LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
@@ -7,23 +7,22 @@ if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quick/quickwidgets/qquickviewcomparison")
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quick/quickwidgets/qquickwidgetversuswindow_opengl")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick QuickWidgets ShaderTools Widgets)
-qt_add_executable(qquickviewcomparison
+qt_add_executable(qquickwidgetversuswindow_opengl
fbitem.cpp fbitem.h
logo.cpp logo.h
main.cpp
mainwindow.cpp mainwindow.h
)
-set_target_properties(qquickviewcomparison PROPERTIES
+set_target_properties(qquickwidgetversuswindow_opengl PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
-
-target_link_libraries(qquickviewcomparison PUBLIC
+target_link_libraries(qquickwidgetversuswindow_opengl PUBLIC
Qt::Core
Qt::Gui
Qt::Quick
@@ -31,24 +30,24 @@ target_link_libraries(qquickviewcomparison PUBLIC
Qt::Widgets
)
-qt_add_qml_module(qquickviewcomparison
+qt_add_qml_module(qquickwidgetversuswindow_opengl
URI fbitem
VERSION 1.0
QML_FILES test.qml
- RESOURCE_PREFIX /qquickviewcomparison
+ RESOURCE_PREFIX /qquickwidgetversuswindow_opengl
NO_RESOURCE_TARGET_PATH
)
-qt6_add_shaders(qquickviewcomparison "shaders"
+qt6_add_shaders(qquickwidgetversuswindow_opengl "shaders"
PRECOMPILE
OPTIMIZED
PREFIX
- "/qquickviewcomparison"
+ "/qquickwidgetversuswindow_opengl"
FILES
"wobble.frag"
)
-install(TARGETS qquickviewcomparison
+install(TARGETS qquickwidgetversuswindow_opengl
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/doc/images/qquickwidgetversuswindow-opengl-example.jpg b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/doc/images/qquickwidgetversuswindow-opengl-example.jpg
new file mode 100644
index 0000000000..584ac4ed69
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/doc/images/qquickwidgetversuswindow-opengl-example.jpg
Binary files differ
diff --git a/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/doc/src/qquickwidgetversuswindow_opengl.qdoc b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/doc/src/qquickwidgetversuswindow_opengl.qdoc
new file mode 100644
index 0000000000..97ad7ddd8b
--- /dev/null
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/doc/src/qquickwidgetversuswindow_opengl.qdoc
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \title QQuickWidget - QQuickView Comparison Example
+ \example quickwidgets/qquickwidgetversuswindow_opengl
+ \brief Demonstrates the benefits of QQuickWidget over a QQuickView embedded as a native window.
+ \image qquickwidgetversuswindow-opengl-example.jpg
+
+ The example allows showing the same Qt Quick scene within the same
+ QWidget-based user interface using two different approaches: one is using a
+ QQuickView and using it as a child window and
+ QWidget::createWindowContainer(). The other is using QQuickWidget which
+ acts as a true QWidget and supports, among others, better clipping and
+ stacking, as is expected from a true QWidget.
+
+ The Qt Quick scene also uses direct OpenGL rendering, proving that with
+ QQuickWidget the rendering still happens using the accelerated 3D API. The
+ implication of this is that the example is tied to OpenGL and will not work
+ with other graphics APIs (Vulkan, Metal, Direct 3D).
+
+ Clicking on the Show Overlay checkbox demonstrates a widget stacking case
+ that is not rendering as expected when embedding a native window, while
+ QQuickWidget makes it render as expected.
+
+ Multisample antialiasing can also be exercised. When enabling it via the
+ corresponding checkbox, QQuickWidget will internally render into a
+ multisample renderbuffer, which is then resolved into a regular,
+ non-multisample 2D texture after each render pass, thus enabling
+ multisampling for the Qt Quick content without affecting the rest of the
+ QWidget UI. With QQuickView the native window will request multisampling
+ for its corresponding window surface, bringing similar results, if
+ supported by the platform.
+
+ The Qt Quick scene is interactive: typing into the text field is possible
+ regardless of which embedding technology is used. QQuickWidget takes care
+ of forwarding input events to the underlying Qt Quick scene automatically.
+*/
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/fbitem.cpp b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/fbitem.cpp
index 139fcbae5c..139fcbae5c 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/fbitem.cpp
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/fbitem.cpp
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/fbitem.h
index 573cfd7866..573cfd7866 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/fbitem.h
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/fbitem.h
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/logo.cpp b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/logo.cpp
index b11c326034..b11c326034 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/logo.cpp
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/logo.cpp
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/logo.h b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/logo.h
index 7e58bbb7b7..7e58bbb7b7 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/logo.h
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/logo.h
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/main.cpp b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/main.cpp
index c0a26eefba..c0a26eefba 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/main.cpp
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/main.cpp
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/mainwindow.cpp
index b393937809..27d320892e 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.cpp
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/mainwindow.cpp
@@ -158,7 +158,7 @@ void MainWindow::updateView()
? m_currentRootObject->property("currentText").toString()
: QStringLiteral("Hello Qt");
- QUrl source("qrc:qquickviewcomparison/test.qml");
+ QUrl source("qrc:qquickwidgetversuswindow_opengl/test.qml");
if (m_state == UseWindow) {
auto *quickView = new QQuickView;
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.h b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/mainwindow.h
index d182b70960..d182b70960 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/mainwindow.h
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/mainwindow.h
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.pro b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/qquickwidgetversuswindow_opengl.pro
index 7809c20b3a..42930b1ecd 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.pro
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/qquickwidgetversuswindow_opengl.pro
@@ -1,5 +1,5 @@
TEMPLATE = app
-TARGET = qquickviewcomparison
+TARGET = qquickwidgetversuswindow_opengl
CONFIG += qmltypes
QML_IMPORT_NAME = fbitem
@@ -16,9 +16,9 @@ HEADERS += mainwindow.h \
logo.h \
fbitem.h
-RESOURCES += qquickviewcomparison.qrc
+RESOURCES += qquickwidgetversuswindow_opengl.qrc
OTHER_FILES += test.qml
-target.path = $$[QT_INSTALL_EXAMPLES]/quick/quickwidgets/qquickviewcomparison
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/quickwidgets/qquickwidgetversuswindow_opengl
INSTALLS += target
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.qrc b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/qquickwidgetversuswindow_opengl.qrc
index e545c993c0..4650ef97e8 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/qquickviewcomparison.qrc
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/qquickwidgetversuswindow_opengl.qrc
@@ -1,5 +1,5 @@
<RCC>
- <qresource prefix="/qquickviewcomparison">
+ <qresource prefix="/qquickwidgetversuswindow_opengl">
<file>test.qml</file>
<file>wobble.frag.qsb</file>
</qresource>
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/test.qml b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/test.qml
index 8224320509..8224320509 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/test.qml
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/test.qml
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/wobble.frag b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/wobble.frag
index 9fddf1a162..9fddf1a162 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/wobble.frag
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/wobble.frag
diff --git a/examples/quick/quickwidgets/qquickviewcomparison/wobble.frag.qsb b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/wobble.frag.qsb
index ab764e8326..ab764e8326 100644
--- a/examples/quick/quickwidgets/qquickviewcomparison/wobble.frag.qsb
+++ b/examples/quick/quickwidgets/qquickwidgetversuswindow_opengl/wobble.frag.qsb
Binary files differ
diff --git a/examples/quick/quickwidgets/quickwidget/CMakeLists.txt b/examples/quick/quickwidgets/quickwidget/CMakeLists.txt
index f3cd7688c3..c8121d81a4 100644
--- a/examples/quick/quickwidgets/quickwidget/CMakeLists.txt
+++ b/examples/quick/quickwidgets/quickwidget/CMakeLists.txt
@@ -12,7 +12,6 @@ set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quick/quickwidgets/quickwidget")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick QuickWidgets Widgets)
qt_add_executable(quickwidget
- fbitem.cpp fbitem.h
main.cpp
)
@@ -33,9 +32,7 @@ qt_add_qml_module(quickwidget
URI QuickWidgetExample
VERSION 1.0
QML_FILES
- customgl.qml
rotatingsquare.qml
- rotatingsquaretab.qml
RESOURCE_PREFIX /quickwidget
NO_RESOURCE_TARGET_PATH
)
diff --git a/examples/quick/quickwidgets/quickwidget/customgl.qml b/examples/quick/quickwidgets/quickwidget/customgl.qml
deleted file mode 100644
index 577f006bd7..0000000000
--- a/examples/quick/quickwidgets/quickwidget/customgl.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-import QuickWidgetExample 1.0
-
-Rectangle {
- color: "lightGray"
-
- FbItem {
- anchors.fill: parent
- anchors.margins: 10
- }
-
- Text {
- anchors.left: parent.left
- anchors.bottom: parent.bottom
- anchors.margins: 15
- text: "QQuickFramebufferObject with animated clear color"
- color: "white"
- }
-}
diff --git a/examples/quick/quickwidgets/quickwidget/fbitem.cpp b/examples/quick/quickwidgets/quickwidget/fbitem.cpp
deleted file mode 100644
index 3e98168dcf..0000000000
--- a/examples/quick/quickwidgets/quickwidget/fbitem.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "fbitem.h"
-#include <QOpenGLFramebufferObject>
-#include <QOpenGLContext>
-#include <QOpenGLFunctions>
-#include <QtCore/QDebug>
-
-#if QT_CONFIG(opengl)
-class FbRenderer : public QQuickFramebufferObject::Renderer
-{
-public:
- FbRenderer() { }
-
- // The lifetime of the FBO and this class depends on how QQuickWidget
- // manages the scenegraph and context when it comes to showing and hiding
- // the widget. The actual behavior is proven by the debug prints.
- ~FbRenderer() override {
- qDebug("FbRenderer destroyed");
- }
-
- void render() override {
- QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
- f->glClearColor(c, 0, 0, 1);
- f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- c += 0.01f * dir;
- if (c >= 1.0f || c <= 0.0f)
- dir *= -1;
- update();
- }
-
- QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override {
- qDebug() << "Creating FBO" << size;
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- return new QOpenGLFramebufferObject(size, format);
- }
-
-private:
- float c = 0;
- int dir = 1;
-};
-#endif
-
-QQuickFramebufferObject::Renderer *FbItem::createRenderer() const
-{
-#if QT_CONFIG(opengl)
- return new FbRenderer;
-#else
- return nullptr;
-#endif
-}
diff --git a/examples/quick/quickwidgets/quickwidget/fbitem.h b/examples/quick/quickwidgets/quickwidget/fbitem.h
deleted file mode 100644
index eb5ec1f1d0..0000000000
--- a/examples/quick/quickwidgets/quickwidget/fbitem.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef FBITEM_H
-#define FBITEM_H
-
-#include <QtQuick/QQuickFramebufferObject>
-
-class FbItem : public QQuickFramebufferObject
-{
- Q_OBJECT
- QML_ELEMENT
-public:
- Renderer *createRenderer() const override;
-};
-
-#endif
diff --git a/examples/quick/quickwidgets/quickwidget/main.cpp b/examples/quick/quickwidgets/quickwidget/main.cpp
index 191adcc451..5d1bc38aa7 100644
--- a/examples/quick/quickwidgets/quickwidget/main.cpp
+++ b/examples/quick/quickwidgets/quickwidget/main.cpp
@@ -48,14 +48,18 @@
**
****************************************************************************/
+#include <QApplication>
+#include <QCommandLineParser>
#include <QQuickWidget>
#include <QQuickItem>
#include <QQmlError>
-#include <QtWidgets>
-#include "fbitem.h"
-
-static bool optMultipleSample = false;
-static bool optCoreProfile = false;
+#include <QMdiArea>
+#include <QLCDNumber>
+#include <QFileDialog>
+#include <QStatusBar>
+#include <QMainWindow>
+#include <QMenuBar>
+#include <QPushButton>
class MainWindow : public QMainWindow {
Q_OBJECT
@@ -74,14 +78,12 @@ private:
QQuickWidget *m_quickWidget;
};
+static bool optMultipleSample = false;
+
MainWindow::MainWindow()
: m_quickWidget(new QQuickWidget)
{
QSurfaceFormat format;
- if (optCoreProfile) {
- format.setVersion(4, 4);
- format.setProfile(QSurfaceFormat::CoreProfile);
- }
if (optMultipleSample)
format.setSamples(4);
m_quickWidget->setFormat(format);
@@ -120,23 +122,45 @@ MainWindow::MainWindow()
void MainWindow::createQuickWidgetsInTabs(QMdiArea *mdiArea)
{
- QTabWidget *tabWidget = new QTabWidget;
+ // A QQuickWidget should work like any other widget when it comes to being
+ // in layouts, in tab widgets, MDI areas, etc. It can also be freely
+ // reparented and made top-level.
+ QTabWidget *tabWidget = new QTabWidget;
const QSize size(400, 400);
-
- QQuickWidget *w = new QQuickWidget;
- w->resize(size);
- w->setResizeMode(QQuickWidget::SizeRootObjectToView);
- w->setSource(QUrl("qrc:quickwidget/rotatingsquaretab.qml"));
-
- tabWidget->addTab(w, tr("Plain Quick content"));
-
- w = new QQuickWidget;
- w->resize(size);
- w->setResizeMode(QQuickWidget::SizeRootObjectToView);
- w->setSource(QUrl("qrc:quickwidget/customgl.qml"));
-
- tabWidget->addTab(w, tr("Custom OpenGL drawing"));
+ const QString msgToTopLevel = QLatin1String("Break out to top-level window");
+ const QString msgFromTopLevel = QLatin1String("Move back under tab widget");
+
+ static const int N = 4;
+ static const QColor colorTab[N] = { Qt::green, Qt::blue, Qt::yellow, Qt::magenta };
+ for (int i = 0; i < N; ++i) {
+ QQuickWidget *widget = new QQuickWidget;
+ widget->resize(size);
+ widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
+ QObject::connect(widget, &QQuickWidget::statusChanged, widget, [widget, i] {
+ if (widget->status() == QQuickWidget::Ready) {
+ if (QQuickItem *rootItem = widget->rootObject()) {
+ rootItem->setProperty("rectColor", colorTab[i]);
+ }
+ }
+ });
+ widget->setSource(QUrl("qrc:quickwidget/rotatingsquare.qml"));
+ widget->setWindowTitle(QString::asprintf("Tab %d", i + 1));
+ QPushButton *btn = new QPushButton(msgToTopLevel, widget);
+ connect(btn, &QPushButton::clicked, widget, [=] {
+ if (widget->parent()) {
+ widget->setAttribute(Qt::WA_DeleteOnClose, true);
+ widget->setParent(nullptr);
+ widget->show();
+ btn->setText(msgFromTopLevel);
+ } else {
+ widget->setAttribute(Qt::WA_DeleteOnClose, false);
+ tabWidget->addTab(widget, widget->windowTitle());
+ btn->setText(msgToTopLevel);
+ }
+ });
+ tabWidget->addTab(widget, QString::asprintf("Tab %d", i + 1));
+ }
mdiArea->addSubWindow(tabWidget);
tabWidget->show();
@@ -197,25 +221,20 @@ int main(int argc, char **argv)
{
QApplication app(argc, argv);
- // this example and QQuickWidget are only functional when rendering with OpenGL
- QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
-
QCoreApplication::setApplicationName("Qt QQuickWidget Example");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
+
QCommandLineParser parser;
parser.setApplicationDescription(QCoreApplication::applicationName());
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption multipleSampleOption("multisample", "Multisampling");
parser.addOption(multipleSampleOption);
- QCommandLineOption coreProfileOption("coreprofile", "Use core profile");
- parser.addOption(coreProfileOption);
parser.process(app);
optMultipleSample = parser.isSet(multipleSampleOption);
- optCoreProfile = parser.isSet(coreProfileOption);
MainWindow mainWindow;
mainWindow.show();
diff --git a/examples/quick/quickwidgets/quickwidget/quickwidget.pro b/examples/quick/quickwidgets/quickwidget/quickwidget.pro
index b824c520f5..9c31ac28f3 100644
--- a/examples/quick/quickwidgets/quickwidget/quickwidget.pro
+++ b/examples/quick/quickwidgets/quickwidget/quickwidget.pro
@@ -7,8 +7,7 @@ CONFIG += qmltypes
QML_IMPORT_NAME = QuickWidgetExample
QML_IMPORT_MAJOR_VERSION = 1
-SOURCES += main.cpp fbitem.cpp
-HEADERS += fbitem.h
+SOURCES += main.cpp
RESOURCES += quickwidget.qrc
diff --git a/examples/quick/quickwidgets/quickwidget/quickwidget.qrc b/examples/quick/quickwidgets/quickwidget/quickwidget.qrc
index 85a49b75ca..c073b7b80d 100644
--- a/examples/quick/quickwidgets/quickwidget/quickwidget.qrc
+++ b/examples/quick/quickwidgets/quickwidget/quickwidget.qrc
@@ -1,7 +1,5 @@
<RCC>
<qresource prefix="/quickwidget">
<file>rotatingsquare.qml</file>
- <file>rotatingsquaretab.qml</file>
- <file>customgl.qml</file>
</qresource>
</RCC>
diff --git a/examples/quick/quickwidgets/quickwidget/rotatingsquare.qml b/examples/quick/quickwidgets/quickwidget/rotatingsquare.qml
index 5d3bb72fbe..08b769d80f 100644
--- a/examples/quick/quickwidgets/quickwidget/rotatingsquare.qml
+++ b/examples/quick/quickwidgets/quickwidget/rotatingsquare.qml
@@ -48,10 +48,11 @@
**
****************************************************************************/
-import QtQuick 2.0
+import QtQuick 2.8
Rectangle {
id: root
+ property color rectColor: "red"
Rectangle {
property int d: 100
@@ -59,13 +60,35 @@ Rectangle {
width: d
height: d
anchors.centerIn: parent
- color: "red"
+ color: root.rectColor
NumberAnimation on rotation { from: 0; to: 360; duration: 2000; loops: Animation.Infinite; }
}
Text {
+ id: text
anchors.centerIn: parent
- text: "Qt Quick running in a widget"
+ property string api
+ Connections {
+ target: text.GraphicsInfo
+ function onApiChanged() {
+ var api = text.GraphicsInfo.api;
+ if (api === GraphicsInfo.Software)
+ text.api = "Software";
+ else if (api === GraphicsInfo.OpenGL)
+ text.api = "OpenGL on QRhi";
+ else if (api === GraphicsInfo.Direct3D11)
+ text.api = "D3D11 on QRhi";
+ else if (api === GraphicsInfo.Vulkan)
+ text.api = "Vulkan on QRhi";
+ else if (api === GraphicsInfo.Metal)
+ text.api = "Metal on QRhi";
+ else if (api === GraphicsInfo.Null)
+ text.api = "Null on QRhi";
+ else
+ text.api = "Unknown API";
+ }
+ }
+ text: "Qt Quick running in a widget\nGraphicsInfo.api says: " + api
}
function performLayerBasedGrab(fn) {
diff --git a/examples/quick/quickwidgets/quickwidget/rotatingsquaretab.qml b/examples/quick/quickwidgets/quickwidget/rotatingsquaretab.qml
deleted file mode 100644
index 116a8f8729..0000000000
--- a/examples/quick/quickwidgets/quickwidget/rotatingsquaretab.qml
+++ /dev/null
@@ -1,76 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-import QtQuick 2.0
-
-Rectangle {
- gradient: Gradient {
- GradientStop { position: 0; color: "steelblue" }
- GradientStop { position: 1; color: "black" }
- }
-
- Rectangle {
- property int d: 100
- id: square
- width: d
- height: d
- anchors.centerIn: parent
- color: "green"
- NumberAnimation on rotation { from: 360; to: 0; duration: 4000; loops: Animation.Infinite; }
- }
-
- Text {
- anchors.centerIn: parent
- text: "Qt Quick running in a tab widget"
- color: "purple"
- font.bold: true
- font.pointSize: 14
- }
-}
diff --git a/examples/quick/quickwidgets/quickwidgets.pro b/examples/quick/quickwidgets/quickwidgets.pro
index be932f33d0..14d1893776 100644
--- a/examples/quick/quickwidgets/quickwidgets.pro
+++ b/examples/quick/quickwidgets/quickwidgets.pro
@@ -1,3 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = quickwidget \
- qquickviewcomparison
+ qquickwidgetversuswindow_opengl
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index 5d29408b06..2c5e3e184c 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -157,7 +157,8 @@ QQuickRenderControlPrivate::QQuickRenderControlPrivate(QQuickRenderControl *rend
ownRhi(true),
cb(nullptr),
offscreenSurface(nullptr),
- sampleCount(1)
+ sampleCount(1),
+ frameStatus(NotRecordingFrame)
{
if (!sg) {
qAddPostRoutine(cleanup);
@@ -428,6 +429,7 @@ void QQuickRenderControl::invalidate()
// also essential to allow a subsequent initialize() to succeed.
d->rc->invalidate();
+ d->frameStatus = QQuickRenderControlPrivate::NotRecordingFrame;
d->initialized = false;
}
@@ -635,7 +637,23 @@ void QQuickRenderControl::beginFrame()
emit d->window->beforeFrameBegin();
- d->rhi->beginOffscreenFrame(&d->cb);
+ QRhi::FrameOpResult result = d->rhi->beginOffscreenFrame(&d->cb);
+
+ switch (result) {
+ case QRhi::FrameOpSuccess:
+ case QRhi::FrameOpSwapChainOutOfDate:
+ d->frameStatus = QQuickRenderControlPrivate::RecordingFrame;
+ break;
+ case QRhi::FrameOpError:
+ d->frameStatus = QQuickRenderControlPrivate::ErrorInBeginFrame;
+ break;
+ case QRhi::FrameOpDeviceLost:
+ d->frameStatus = QQuickRenderControlPrivate::DeviceLostInBeginFrame;
+ break;
+ default:
+ d->frameStatus = QQuickRenderControlPrivate::NotRecordingFrame;
+ break;
+ }
}
/*!
@@ -658,6 +676,7 @@ void QQuickRenderControl::endFrame()
d->rhi->endOffscreenFrame();
d->cb = nullptr;
+ d->frameStatus = QQuickRenderControlPrivate::NotRecordingFrame;
emit d->window->afterFrameEnd();
}
diff --git a/src/quick/items/qquickrendercontrol_p.h b/src/quick/items/qquickrendercontrol_p.h
index acf84c8a23..f6588072a4 100644
--- a/src/quick/items/qquickrendercontrol_p.h
+++ b/src/quick/items/qquickrendercontrol_p.h
@@ -65,6 +65,13 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRenderControlPrivate : public QObjectPrivate
public:
Q_DECLARE_PUBLIC(QQuickRenderControl)
+ enum FrameStatus {
+ NotRecordingFrame,
+ RecordingFrame,
+ DeviceLostInBeginFrame,
+ ErrorInBeginFrame
+ };
+
QQuickRenderControlPrivate(QQuickRenderControl *renderControl);
static QQuickRenderControlPrivate *get(QQuickRenderControl *renderControl) {
@@ -96,6 +103,7 @@ public:
QRhiCommandBuffer *cb;
QOffscreenSurface *offscreenSurface;
int sampleCount;
+ FrameStatus frameStatus;
};
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgrhisupport.cpp b/src/quick/scenegraph/qsgrhisupport.cpp
index 6c29a866d7..f56db5568d 100644
--- a/src/quick/scenegraph/qsgrhisupport.cpp
+++ b/src/quick/scenegraph/qsgrhisupport.cpp
@@ -455,9 +455,9 @@ const void *QSGRhiSupport::rifResource(QSGRendererInterface::Resource res,
}
}
-int QSGRhiSupport::chooseSampleCountForWindowWithRhi(QWindow *window, QRhi *rhi)
+int QSGRhiSupport::chooseSampleCount(int samples, QRhi *rhi)
{
- int msaaSampleCount = qMax(QSurfaceFormat::defaultFormat().samples(), window->requestedFormat().samples());
+ int msaaSampleCount = samples;
if (qEnvironmentVariableIsSet("QSG_SAMPLES"))
msaaSampleCount = qEnvironmentVariableIntValue("QSG_SAMPLES");
msaaSampleCount = qMax(1, msaaSampleCount);
@@ -480,6 +480,11 @@ int QSGRhiSupport::chooseSampleCountForWindowWithRhi(QWindow *window, QRhi *rhi)
return msaaSampleCount;
}
+int QSGRhiSupport::chooseSampleCountForWindowWithRhi(QWindow *window, QRhi *rhi)
+{
+ return chooseSampleCount(qMax(QSurfaceFormat::defaultFormat().samples(), window->requestedFormat().samples()), rhi);
+}
+
// must be called on the main thread
QOffscreenSurface *QSGRhiSupport::maybeCreateOffscreenSurface(QWindow *window)
{
diff --git a/src/quick/scenegraph/qsgrhisupport_p.h b/src/quick/scenegraph/qsgrhisupport_p.h
index 101941875e..e7267c5826 100644
--- a/src/quick/scenegraph/qsgrhisupport_p.h
+++ b/src/quick/scenegraph/qsgrhisupport_p.h
@@ -92,6 +92,7 @@ class Q_QUICK_PRIVATE_EXPORT QSGRhiSupport
public:
static QSGRhiSupport *instance_internal();
static QSGRhiSupport *instance();
+ static int chooseSampleCount(int samples, QRhi *rhi);
static int chooseSampleCountForWindowWithRhi(QWindow *window, QRhi *rhi);
static QImage grabAndBlockInCurrentFrame(QRhi *rhi, QRhiCommandBuffer *cb, QRhiTexture *src = nullptr);
static void checkEnvQSgInfo();
diff --git a/src/quickwidgets/CMakeLists.txt b/src/quickwidgets/CMakeLists.txt
index 4b6ebc0ad3..f9aaef9533 100644
--- a/src/quickwidgets/CMakeLists.txt
+++ b/src/quickwidgets/CMakeLists.txt
@@ -38,11 +38,3 @@ qt_internal_extend_target(QuickWidgets CONDITION QT_FEATURE_accessibility
qaccessiblequickwidget.cpp qaccessiblequickwidget_p.h
qaccessiblequickwidgetfactory.cpp qaccessiblequickwidgetfactory_p.h
)
-
-## Scopes:
-#####################################################################
-
-qt_internal_extend_target(QuickWidgets CONDITION QT_FEATURE_opengl
- LIBRARIES
- Qt::OpenGLPrivate
-)
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 95c1be879c..6d586f8828 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -40,6 +40,7 @@
#include "qquickwidget.h"
#include "qquickwidget_p.h"
#include "qaccessiblequickwidgetfactory_p.h"
+#include <QtWidgets/private/qwidgetrepaintmanager_p.h>
#include "private/qquickwindow_p.h"
#include "private/qquickitem_p.h"
@@ -60,14 +61,6 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformintegration.h>
-#if QT_CONFIG(opengl)
-#include <private/qopenglcontext_p.h>
-#include <private/qopenglextensions_p.h>
-#include <QOpenGLFramebufferObject>
-#include <QOpenGLContext>
-#include <QOpenGLFunctions>
-#include <QtOpenGL/qpa/qplatformbackingstoreopenglsupport.h>
-#endif
#include <QtGui/QPainter>
#include <QtQuick/QSGRendererInterface>
@@ -212,17 +205,12 @@ void QQuickWidgetPrivate::init(QQmlEngine* e)
useSoftwareRenderer = true;
if (!useSoftwareRenderer) {
-#if QT_CONFIG(opengl)
- if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface))
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering))
setRenderToTexture();
else
-#endif
qWarning("QQuickWidget is not supported on this platform.");
}
- if (QSGRhiSupport::instance()->rhiBackend() != QRhi::OpenGLES2)
- qWarning("QQuickWidget is only supported on OpenGL. Use QQuickWindow::setGraphicsApi() to override the default.");
-
engine = e;
if (!engine.isNull() && !engine.data()->incubationController())
@@ -248,38 +236,24 @@ void QQuickWidgetPrivate::ensureEngine() const
void QQuickWidgetPrivate::invalidateRenderControl()
{
-#if QT_CONFIG(opengl)
- if (!useSoftwareRenderer) {
- if (!context) // this is not an error, could be called before creating the context, or multiple times
- return;
-
- bool success = context->makeCurrent(offscreenSurface);
- if (!success) {
- qWarning("QQuickWidget::invalidateRenderControl could not make context current");
- return;
- }
+ if (!useSoftwareRenderer && rhi) {
+ // For the user's own OpenGL code connected to some QQuickWindow signals.
+ rhi->makeThreadLocalNativeContextCurrent();
}
-#endif
renderControl->invalidate();
-
- // Many things can happen inside the above invalidate() call, including a
- // change of current context. Restore if needed since some code will rely
- // on the fact that this function makes and leaves the context current.
-#if QT_CONFIG(opengl)
- if (!useSoftwareRenderer && context) {
- if (QOpenGLContext::currentContext() != context)
- context->makeCurrent(offscreenSurface);
- }
-#endif
}
void QQuickWidgetPrivate::handleWindowChange()
{
Q_Q(QQuickWidget);
- if (offscreenWindow->isPersistentSceneGraph() && qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts))
+ if (offscreenWindow->isPersistentSceneGraph()
+ && qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts)
+ && rhiConfig().api() == QPlatformBackingStoreRhiConfig::OpenGL)
+ {
return;
+ }
// In case of !isPersistentSceneGraph or when we need a new context due to
// the need to share resources with the new window's context, we must both
@@ -298,21 +272,19 @@ void QQuickWidgetPrivate::handleWindowChange()
QObject::connect(renderControl, SIGNAL(sceneChanged()), q, SLOT(triggerUpdate()));
execute();
- if (!useSoftwareRenderer)
- destroyContext();
}
QQuickWidgetPrivate::QQuickWidgetPrivate()
: root(nullptr)
, component(nullptr)
, offscreenWindow(nullptr)
- , offscreenSurface(nullptr)
, renderControl(nullptr)
-#if QT_CONFIG(opengl)
- , fbo(nullptr)
- , resolvedFbo(nullptr)
- , context(nullptr)
-#endif
+ , rhi(nullptr)
+ , outputTexture(nullptr)
+ , depthStencil(nullptr)
+ , msaaBuffer(nullptr)
+ , rt(nullptr)
+ , rtRp(nullptr)
, resizeMode(QQuickWidget::SizeViewToRootObject)
, initialSize(0,0)
, eventPending(false)
@@ -321,28 +293,18 @@ QQuickWidgetPrivate::QQuickWidgetPrivate()
, requestedSamples(0)
, useSoftwareRenderer(false)
, forceFullUpdate(false)
+ , deviceLost(false)
{
}
-QQuickWidgetPrivate::~QQuickWidgetPrivate()
+void QQuickWidgetPrivate::destroy()
{
+ Q_Q(QQuickWidget);
invalidateRenderControl();
-
- if (useSoftwareRenderer) {
- delete renderControl;
- delete offscreenWindow;
- } else {
-#if QT_CONFIG(opengl)
- // context and offscreenSurface are current at this stage, if the context was created.
- Q_ASSERT(!context || (QOpenGLContext::currentContext() == context && context->surface() == offscreenSurface));
- delete resolvedFbo;
- delete fbo;
- delete offscreenWindow;
- delete renderControl;
-
- destroyContext();
-#endif
- }
+ q->destroyFramebufferObject();
+ delete offscreenWindow;
+ delete renderControl;
+ offscreenRenderer.reset();
}
void QQuickWidgetPrivate::execute()
@@ -382,35 +344,36 @@ void QQuickWidgetPrivate::itemGeometryChanged(QQuickItem *resizeItem, QQuickGeom
void QQuickWidgetPrivate::render(bool needsSync)
{
+ Q_Q(QQuickWidget);
if (!useSoftwareRenderer) {
-#if QT_CONFIG(opengl)
+ if (deviceLost) {
+ deviceLost = false;
+ initializeWithRhi();
+ q->createFramebufferObject();
+ }
+
+ if (!rhi)
+ return;
+
// createFramebufferObject() bails out when the size is empty. In this case
// we cannot render either.
- if (!fbo)
+ if (!outputTexture)
return;
- Q_ASSERT(context);
-
- bool current = context->makeCurrent(offscreenSurface);
-
- if (!current && !context->isValid()) {
- renderControl->invalidate();
- current = context->create() && context->makeCurrent(offscreenSurface);
- if (current) {
- offscreenWindow->setGraphicsDevice(QQuickGraphicsDevice::fromOpenGLContext(context));
- renderControl->initialize();
- }
+ renderControl->beginFrame();
+ QQuickRenderControlPrivate::FrameStatus frameStatus = QQuickRenderControlPrivate::get(renderControl)->frameStatus;
+ if (frameStatus == QQuickRenderControlPrivate::DeviceLostInBeginFrame) {
+ // graphics resources controlled by us must be released
+ invalidateRenderControl();
+ // skip this round and hope that the tlw's repaint manager will manage to reinitialize
+ deviceLost = true;
+ return;
}
-
- if (!current) {
- qWarning("QQuickWidget: Cannot render due to failing makeCurrent()");
+ if (frameStatus != QQuickRenderControlPrivate::RecordingFrame) {
+ qWarning("QQuickWidget: Failed to begin recording a frame");
return;
}
- QOpenGLContextPrivate::get(context)->defaultFboRedirect = fbo->handle();
-
- renderControl->beginFrame();
-
if (needsSync) {
renderControl->polishItems();
renderControl->sync();
@@ -419,17 +382,6 @@ void QQuickWidgetPrivate::render(bool needsSync)
renderControl->render();
renderControl->endFrame();
-
- context->makeCurrent(offscreenSurface);
- if (resolvedFbo) {
- QRect rect(QPoint(0, 0), fbo->size());
- QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect);
- }
-
- static_cast<QOpenGLExtensions *>(context->functions())->flushShared();
-
- QOpenGLContextPrivate::get(context)->defaultFboRedirect = 0;
-#endif
} else {
//Software Renderer
if (needsSync) {
@@ -461,14 +413,9 @@ void QQuickWidgetPrivate::renderSceneGraph()
if (!q->isVisible() || fakeHidden)
return;
- if (!useSoftwareRenderer) {
-#if QT_CONFIG(opengl)
- if (!context) {
- qWarning("QQuickWidget: Attempted to render scene with no context");
- return;
- }
-#endif
- Q_ASSERT(offscreenSurface);
+ if (!useSoftwareRenderer && !rhi) {
+ qWarning("QQuickWidget: Attempted to render scene with no rhi");
+ return;
}
render(true);
@@ -488,25 +435,35 @@ void QQuickWidgetPrivate::renderSceneGraph()
QImage QQuickWidgetPrivate::grabFramebuffer()
{
- if (!useSoftwareRenderer) {
-#if QT_CONFIG(opengl)
- if (!context)
- return QImage();
-
- context->makeCurrent(offscreenSurface);
-#endif
+ if (!useSoftwareRenderer && !rhi)
+ return QImage();
+
+ // grabWindow() does not work for the rhi case, we are in control of the
+ // render target, and so it is up to us to read it back. When the software
+ // renderer is in use, just call grabWindow().
+
+ if (outputTexture) {
+ render(true);
+ QRhiCommandBuffer *cb = nullptr;
+ rhi->beginOffscreenFrame(&cb);
+ QRhiResourceUpdateBatch *resUpd = rhi->nextResourceUpdateBatch();
+ QRhiReadbackResult readResult;
+ resUpd->readBackTexture(QRhiReadbackDescription(outputTexture), &readResult);
+ cb->resourceUpdate(resUpd);
+ rhi->endOffscreenFrame();
+ if (!readResult.data.isEmpty()) {
+ QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()),
+ readResult.pixelSize.width(), readResult.pixelSize.height(),
+ QImage::Format_RGBA8888_Premultiplied);
+ if (rhi->isYUpInFramebuffer())
+ return wrapperImage.mirrored();
+ else
+ return wrapperImage.copy();
+ }
+ return QImage();
}
-
- // grabWindow() does not work for the OpenGL + render control case, so we
- // prefer the FBO's toImage() if available. When the software renderer
- // is in use, however, there will be no FBO and we fall back to grabWindow()
- // instead.
- return
-#if QT_CONFIG(opengl)
- fbo != nullptr ? fbo->toImage() :
-#endif
- offscreenWindow->grabWindow();
+ return offscreenWindow->grabWindow();
}
// Intentionally not overriding the QQuickWindow's focusObject.
@@ -568,10 +525,10 @@ QImage QQuickWidgetPrivate::grabFramebuffer()
However, the above mentioned advantages come at the expense of performance:
\list
- \li Unlike QQuickWindow and QQuickView, QQuickWidget requires rendering into OpenGL
- framebuffer objects, which needs to be enforced by calling
- QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL) at startup.
- This will naturally carry a minor performance hit.
+ \li Unlike QQuickWindow and QQuickView, QQuickWidget involves at least one
+ additional render pass targeting an offscreen color buffer, typically a 2D
+ texture, followed by drawing a texture quad. This means increased load
+ especially for the fragment processing of the GPU.
\li Using QQuickWidget disables the \l{threaded_render_loop}{threaded render loop} on all
platforms. This means that some of the benefits of threaded rendering, for example
@@ -583,6 +540,24 @@ QImage QQuickWidgetPrivate::grabFramebuffer()
entire purpose of QQuickWidget is to render Quick scenes without a separate native
window, hence making it a native widget should always be avoided.
+ \section1 Graphics API Support
+
+ QQuickWidget is functional with all the 3D graphics APIs supported by Qt
+ Quick, as well as the \c software backend. Other backends, for example
+ OpenVG, are not compatible however and attempting to construct a
+ QQuickWidget will lead to problems.
+
+ Overriding the platform's default graphics API is done the same way as with
+ QQuickWindow and QQuickView: either by calling
+ QQuickWindow::setGraphicsApi() early on before constructing the first
+ QQuickWidget, or by setting the \c{QSG_RHI_BACKEND} environment variable.
+
+ \note One top-level window can only use one single graphics API for
+ rendering. For example, attempting to place a QQuickWidget using Vulkan and
+ a QOpenGLWidget in the widget hierarchy of the same top-level window,
+ problems will occur and one of the widgets will not be rendering as
+ expected.
+
\section1 Scene Graph and Context Persistency
QQuickWidget honors QQuickWindow::isPersistentSceneGraph(), meaning that
@@ -592,20 +567,19 @@ QImage QQuickWidgetPrivate::grabFramebuffer()
related resources be released whenever the widget becomes hidden. By default
persistency is enabled, just like with QQuickWindow.
- When running with the OpenGL backend of the scene graph, QQuickWindow
- offers the possibility to disable persistent OpenGL contexts as well. This
- setting is currently ignored by QQuickWidget and the context is always
- persistent. The OpenGL context is thus not destroyed when hiding the
- widget. The context is destroyed only when the widget is destroyed or when
- the widget gets reparented into another top-level widget's child hierarchy.
- However, some applications, in particular those that have their own
- graphics resources due to performing custom OpenGL rendering in the Qt
- Quick scene, may wish to disable the latter since they may not be prepared
- to handle the loss of the context when moving a QQuickWidget into another
- window. Such applications can set the
- QCoreApplication::AA_ShareOpenGLContexts attribute. For a discussion on the
- details of resource initialization and cleanup, refer to the QOpenGLWidget
- documentation.
+ When running with the OpenGL, QQuickWindow offers the possibility to
+ disable persistent OpenGL contexts as well. This setting is currently
+ ignored by QQuickWidget and the context is always persistent. The OpenGL
+ context is thus not destroyed when hiding the widget. The context is
+ destroyed only when the widget is destroyed or when the widget gets
+ reparented into another top-level widget's child hierarchy. However, some
+ applications, in particular those that have their own graphics resources
+ due to performing custom OpenGL rendering in the Qt Quick scene, may wish
+ to disable the latter since they may not be prepared to handle the loss of
+ the context when moving a QQuickWidget into another window. Such
+ applications can set the QCoreApplication::AA_ShareOpenGLContexts
+ attribute. For a discussion on the details of resource initialization and
+ cleanup, refer to the QOpenGLWidget documentation.
\note QQuickWidget offers less fine-grained control over its internal
OpenGL context than QOpenGLWidget, and there are subtle differences, most
@@ -633,13 +607,6 @@ QImage QQuickWidgetPrivate::grabFramebuffer()
Qt::WA_TranslucentBackground on the top-level window, request an alpha channel, and
change the Qt Quick Scenegraph's clear color to Qt::transparent via setClearColor().
- \section1 Support when not using OpenGL
-
- In addition to OpenGL, the \c software backend of Qt Quick also supports
- QQuickWidget. Other backends, for example OpenVG, are not
- compatible however and attempting to construct a QQuickWidget will lead to
- problems.
-
\section1 Tab Key Handling
On press of the \c[TAB] key, the item inside the QQuickWidget gets focus. If
@@ -706,6 +673,13 @@ QQuickWidget::~QQuickWidget()
Q_D(QQuickWidget);
delete d->root;
d->root = nullptr;
+
+ // NB! resetting graphics resources must be done from this destructor,
+ // *not* from the private class' destructor. This is due to how destruction
+ // works and due to the QWidget dtor (for toplevels) destroying the repaint
+ // manager and rhi before the (QObject) private gets destroyed. Hence must
+ // do it here early on.
+ d->destroy();
}
/*!
@@ -1010,7 +984,7 @@ void QQuickWidgetPrivate::handleContextCreationFailure(const QSurfaceFormat &)
QString translatedMessage;
QString untranslatedMessage;
- QQuickWindowPrivate::rhiCreationFailureMessage(QLatin1String("OpenGL"), &translatedMessage, &untranslatedMessage);
+ QQuickWindowPrivate::rhiCreationFailureMessage(QLatin1String("QRhi"), &translatedMessage, &untranslatedMessage);
static const QMetaMethod errorSignal = QMetaMethod::fromSignal(&QQuickWidget::sceneGraphError);
const bool signalConnected = q->isSignalConnected(errorSignal);
@@ -1025,72 +999,90 @@ void QQuickWidgetPrivate::handleContextCreationFailure(const QSurfaceFormat &)
qFatal("%s", qPrintable(untranslatedMessage));
}
+static inline QPlatformBackingStoreRhiConfig::Api graphicsApiToBackingStoreRhiApi(QSGRendererInterface::GraphicsApi api)
+{
+ switch (api) {
+ case QSGRendererInterface::OpenGL:
+ return QPlatformBackingStoreRhiConfig::OpenGL;
+ case QSGRendererInterface::Vulkan:
+ return QPlatformBackingStoreRhiConfig::Vulkan;
+ case QSGRendererInterface::Direct3D11:
+ return QPlatformBackingStoreRhiConfig::D3D11;
+ case QSGRendererInterface::Metal:
+ return QPlatformBackingStoreRhiConfig::Metal;
+ default:
+ return QPlatformBackingStoreRhiConfig::Null;
+ }
+}
+
// Never called by Software Rendering backend
-void QQuickWidgetPrivate::createContext()
+void QQuickWidgetPrivate::initializeWithRhi()
{
-#if QT_CONFIG(opengl)
Q_Q(QQuickWidget);
+ QWidgetPrivate *tlwd = QWidgetPrivate::get(q->window());
+ // when reparenting, the rhi may suddenly be different
+ if (rhi) {
+ QRhi *tlwRhi = nullptr;
+ if (QWidgetRepaintManager *repaintManager = tlwd->maybeRepaintManager())
+ tlwRhi = repaintManager->rhi();
+ if (tlwRhi && rhi != tlwRhi)
+ rhi = nullptr;
+ }
+
// On hide-show we may invalidate() (when !isPersistentSceneGraph) but our
// context is kept. We may need to initialize() again, though.
- const bool reinit = context && !offscreenWindow->isSceneGraphInitialized();
+ const bool onlyNeedsSgInit = rhi && !offscreenWindow->isSceneGraphInitialized();
- if (!reinit) {
- if (context)
+ if (!onlyNeedsSgInit) {
+ if (rhi)
return;
- context = new QOpenGLContext;
- context->setFormat(offscreenWindow->requestedFormat());
- context->setScreen(q->screen());
- QOpenGLContext *shareContext = qt_gl_global_share_context();
- if (!shareContext)
- shareContext = QWidgetPrivate::get(q->window())->shareContext();
- if (shareContext) {
- context->setShareContext(shareContext);
- context->setScreen(shareContext->screen());
- }
- if (!context->create()) {
- delete context;
- context = nullptr;
- handleContextCreationFailure(offscreenWindow->requestedFormat());
- return;
+ if (QWidgetRepaintManager *repaintManager = tlwd->maybeRepaintManager())
+ rhi = repaintManager->rhi();
+
+ if (!rhi) {
+ // The widget (and its parent chain, if any) may not be shown at
+ // all, yet one may still want to use it for grabs. This is
+ // ridiculous of course because the rendering infrastructure is
+ // tied to the top-level widget that initializes upon expose, but
+ // it has to be supported.
+ offscreenRenderer.setConfig(rhiConfig());
+ offscreenRenderer.setFormat(q->format());
+ // no window passed in, so no swapchain, but we get a functional QRhi which we own
+ if (offscreenRenderer.create())
+ rhi = offscreenRenderer.rhi();
}
- offscreenSurface = new QOffscreenSurface;
- // Pass the context's format(), which, now that the underlying platform context is created,
- // contains a QSurfaceFormat representing the _actual_ format of the underlying
- // configuration. This is essential to get a surface that is compatible with the context.
- offscreenSurface->setFormat(context->format());
- offscreenSurface->setScreen(context->screen());
- offscreenSurface->create();
+ // Could be that something else already initialized the window with some
+ // other graphics API for the QRhi, that's not good.
+ if (rhi && rhi->backend() != QBackingStoreRhiSupport::apiToRhiBackend(graphicsApiToBackingStoreRhiApi(QQuickWindow::graphicsApi()))) {
+ qWarning("The top-level window is not using the expected graphics API for composition, "
+ "'%s' is not compatible with this QQuickWidget",
+ rhi->backendName());
+ rhi = nullptr;
+ }
}
- if (context->makeCurrent(offscreenSurface)) {
+ if (rhi) {
if (!offscreenWindow->isSceneGraphInitialized()) {
- offscreenWindow->setGraphicsDevice(QQuickGraphicsDevice::fromOpenGLContext(context));
+ offscreenWindow->setGraphicsDevice(QQuickGraphicsDevice::fromRhi(rhi));
+#if QT_CONFIG(vulkan)
+ if (QWindow *w = q->window()->windowHandle())
+ offscreenWindow->setVulkanInstance(w->vulkanInstance());
+#endif
renderControl->initialize();
}
- } else
-#endif
- qWarning("QQuickWidget: Failed to make context current");
-}
-
-// Never called by Software Rendering backend
-void QQuickWidgetPrivate::destroyContext()
-{
-#if QT_CONFIG(opengl)
- delete context;
- context = nullptr;
-#endif
- delete offscreenSurface;
- offscreenSurface = nullptr;
+ } else {
+ qWarning("QQuickWidget: Failed to get a QRhi from the top-level widget's window");
+ }
}
void QQuickWidget::createFramebufferObject()
{
Q_D(QQuickWidget);
- // Could come from Show -> createContext -> sceneGraphInitialized in which case the size may
+ // Could come from Show -> initializeWithRhi -> sceneGraphInitialized in which case the size may
// still be invalid on some platforms. Bail out. A resize will come later on.
if (size().isEmpty())
return;
@@ -1109,82 +1101,85 @@ void QQuickWidget::createFramebufferObject()
return;
}
-#if QT_CONFIG(opengl)
- if (!d->context) {
- qWarning("QQuickWidget: Attempted to create FBO with no context");
- return;
- }
-
- QOpenGLContext *shareWindowContext = QWidgetPrivate::get(window())->shareContext();
- if (shareWindowContext && d->context->shareContext() != shareWindowContext && !qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts)) {
- d->context->setShareContext(shareWindowContext);
- d->context->setScreen(shareWindowContext->screen());
- if (!d->context->create())
- qWarning("QQuickWidget: Failed to recreate context");
- // The screen may be different so we must recreate the offscreen surface too.
- // Unlike QOpenGLContext, QOffscreenSurface's create() does not recreate so have to destroy() first.
- d->offscreenSurface->destroy();
- d->offscreenSurface->setScreen(d->context->screen());
- d->offscreenSurface->create();
- }
-
- bool current = d->context->makeCurrent(d->offscreenSurface);
- if (!current) {
- qWarning("QQuickWidget: Failed to make context current when creating FBO");
+ if (!d->rhi) {
+ qWarning("QQuickWidget: Attempted to create output texture with no QRhi");
return;
}
int samples = d->requestedSamples;
- if (!QOpenGLExtensions(d->context).hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
+ if (d->rhi->isFeatureSupported(QRhi::MultisampleRenderBuffer))
+ samples = QSGRhiSupport::chooseSampleCount(samples, d->rhi);
+ else
samples = 0;
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setSamples(samples);
-
- // The default framebuffer for normal windows have sRGB support on OS X which leads to the Qt Quick text item
- // utilizing sRGB blending. To get identical results with QQuickWidget we have to have our framebuffer backed
- // by an sRGB texture.
-#ifdef Q_OS_MACOS
- if (d->context->hasExtension("GL_ARB_framebuffer_sRGB")
- && d->context->hasExtension("GL_EXT_texture_sRGB")
- && d->context->hasExtension("GL_EXT_texture_sRGB_decode")) {
- format.setInternalTextureFormat(GL_SRGB8_ALPHA8_EXT);
- }
-#endif
-
const QSize fboSize = size() * devicePixelRatio();
- // Could be a simple hide - show, in which case the previous fbo is just fine.
- if (!d->fbo || d->fbo->size() != fboSize) {
- delete d->fbo;
- d->fbo = new QOpenGLFramebufferObject(fboSize, format);
+ // Could be a simple hide - show, in which case the previous texture is just fine.
+ if (!d->outputTexture) {
+ d->outputTexture = d->rhi->newTexture(QRhiTexture::RGBA8, fboSize, 1, QRhiTexture::RenderTarget);
+ if (!d->outputTexture->create()) {
+ qWarning("QQuickWidget: failed to create output texture of size %dx%d",
+ fboSize.width(), fboSize.height());
+ }
}
-
- // When compositing in the backingstore, sampling the sRGB texture would perform an
- // sRGB-linear conversion which is not what we want when the final framebuffer (the window's)
- // is sRGB too. Disable the conversion.
-#ifdef Q_OS_MACOS
- if (format.internalTextureFormat() == GL_SRGB8_ALPHA8_EXT) {
- QOpenGLFunctions *funcs = d->context->functions();
- funcs->glBindTexture(GL_TEXTURE_2D, d->fbo->texture());
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+ if (!d->depthStencil) {
+ d->depthStencil = d->rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, fboSize, samples);
+ if (!d->depthStencil->create()) {
+ qWarning("QQuickWidget: failed to create depth/stencil buffer of size %dx%d and sample count %d",
+ fboSize.width(), fboSize.height(), samples);
+ }
+ }
+ if (samples > 1 && !d->msaaBuffer) {
+ d->msaaBuffer = d->rhi->newRenderBuffer(QRhiRenderBuffer::Color, fboSize, samples);
+ if (!d->msaaBuffer->create()) {
+ qWarning("QQuickWidget: failed to create multisample renderbuffer of size %dx%d and sample count %d",
+ fboSize.width(), fboSize.height(), samples);
+ }
+ }
+ if (!d->rt) {
+ QRhiTextureRenderTargetDescription rtDesc;
+ QRhiColorAttachment colorAtt;
+ if (samples <= 1) {
+ colorAtt.setTexture(d->outputTexture);
+ } else {
+ colorAtt.setRenderBuffer(d->msaaBuffer);
+ colorAtt.setResolveTexture(d->outputTexture);
+ }
+ rtDesc.setColorAttachments({ colorAtt });
+ rtDesc.setDepthStencilBuffer(d->depthStencil);
+ d->rt = d->rhi->newTextureRenderTarget(rtDesc);
+ d->rtRp = d->rt->newCompatibleRenderPassDescriptor();
+ d->rt->setRenderPassDescriptor(d->rtRp);
+ d->rt->create();
+ }
+ if (d->outputTexture->pixelSize() != fboSize) {
+ d->outputTexture->setPixelSize(fboSize);
+ if (!d->outputTexture->create()) {
+ qWarning("QQuickWidget: failed to create resized output texture of size %dx%d",
+ fboSize.width(), fboSize.height());
+ }
+ d->depthStencil->setPixelSize(fboSize);
+ if (!d->depthStencil->create()) {
+ qWarning("QQuickWidget: failed to create resized depth/stencil buffer of size %dx%d",
+ fboSize.width(), fboSize.height());
+ }
+ if (d->msaaBuffer) {
+ d->msaaBuffer->setPixelSize(fboSize);
+ if (!d->msaaBuffer->create()) {
+ qWarning("QQuickWidget: failed to create resized multisample renderbuffer of size %dx%d",
+ fboSize.width(), fboSize.height());
+ }
+ }
}
-#endif
- GLuint textureId = d->fbo->texture();
- d->offscreenWindow->setRenderTarget( QQuickRenderTarget::fromOpenGLTexture(textureId, fboSize, samples));
+ d->offscreenWindow->setRenderTarget(QQuickRenderTarget::fromRhiRenderTarget(d->rt));
d->renderControl->setSamples(samples);
- if (samples > 0)
- d->resolvedFbo = new QOpenGLFramebufferObject(fboSize);
-
// Sanity check: The window must not have an underlying platform window.
// Having one would mean create() was called and platforms that only support
// a single native window were in trouble.
Q_ASSERT(!d->offscreenWindow->handle());
-#endif
}
void QQuickWidget::destroyFramebufferObject()
@@ -1196,12 +1191,16 @@ void QQuickWidget::destroyFramebufferObject()
return;
}
-#if QT_CONFIG(opengl)
- delete d->fbo;
- d->fbo = nullptr;
- delete d->resolvedFbo;
- d->resolvedFbo = nullptr;
-#endif
+ delete d->rt;
+ d->rt = nullptr;
+ delete d->rtRp;
+ d->rtRp = nullptr;
+ delete d->depthStencil;
+ d->depthStencil = nullptr;
+ delete d->msaaBuffer;
+ d->msaaBuffer = nullptr;
+ delete d->outputTexture;
+ d->outputTexture = nullptr;
}
QQuickWidget::ResizeMode QQuickWidget::resizeMode() const
@@ -1279,8 +1278,17 @@ void QQuickWidgetPrivate::setRootObject(QObject *obj)
}
}
-#if QT_CONFIG(opengl)
-GLuint QQuickWidgetPrivate::textureId() const
+QPlatformBackingStoreRhiConfig QQuickWidgetPrivate::rhiConfig() const
+{
+ if (useSoftwareRenderer)
+ return {};
+
+ QPlatformBackingStoreRhiConfig config(graphicsApiToBackingStoreRhiApi(QQuickWindow::graphicsApi()));
+ config.setDebugLayer(QSGRhiSupport::instance()->isDebugLayerRequested());
+ return config;
+}
+
+QRhiTexture *QQuickWidgetPrivate::texture() const
{
Q_Q(const QQuickWidget);
if (!q->isWindow() && q->internalWinId()) {
@@ -1288,8 +1296,7 @@ GLuint QQuickWidgetPrivate::textureId() const
<< "Consider setting Qt::AA_DontCreateNativeWidgetSiblings";
return 0;
}
- return resolvedFbo ? resolvedFbo->texture()
- : (fbo ? fbo->texture() : 0);
+ return outputTexture;
}
QPlatformTextureList::Flags QQuickWidgetPrivate::textureListFlags()
@@ -1298,7 +1305,6 @@ QPlatformTextureList::Flags QQuickWidgetPrivate::textureListFlags()
flags |= QPlatformTextureList::NeedsPremultipliedAlphaBlending;
return flags;
}
-#endif
/*!
\internal
@@ -1388,13 +1394,12 @@ void QQuickWidget::resizeEvent(QResizeEvent *e)
createFramebufferObject();
}
} else {
-#if QT_CONFIG(opengl)
- if (d->context) {
+ if (d->rhi) {
// Bail out when receiving a resize after scenegraph invalidation. This can happen
// during hide - resize - show sequences and also during application exit.
- if (!d->fbo && !d->offscreenWindow->isSceneGraphInitialized())
+ if (!d->outputTexture && !d->offscreenWindow->isSceneGraphInitialized())
return;
- if (!d->fbo || d->fbo->size() != size() * devicePixelRatio()) {
+ if (!d->outputTexture || d->outputTexture->pixelSize() != size() * devicePixelRatio()) {
needsSync = true;
createFramebufferObject();
}
@@ -1402,14 +1407,13 @@ void QQuickWidget::resizeEvent(QResizeEvent *e)
// This will result in a scenegraphInitialized() signal which
// is connected to createFramebufferObject().
needsSync = true;
- d->createContext();
+ d->initializeWithRhi();
}
- if (!d->context) {
- qWarning("QQuickWidget::resizeEvent() no OpenGL context");
+ if (!d->rhi) {
+ qWarning("QQuickWidget::resizeEvent() no QRhi");
return;
}
-#endif
}
d->render(needsSync);
@@ -1493,7 +1497,7 @@ void QQuickWidget::showEvent(QShowEvent *)
bool shouldTriggerUpdate = true;
if (!d->useSoftwareRenderer) {
- d->createContext();
+ d->initializeWithRhi();
if (d->offscreenWindow->isSceneGraphInitialized()) {
shouldTriggerUpdate = false;
@@ -1657,26 +1661,22 @@ bool QQuickWidget::event(QEvent *e)
return eventResult;
}
+ case QEvent::WindowAboutToChangeInternal:
+ d->invalidateRenderControl();
+ d->rhi = nullptr;
+ break;
+
case QEvent::WindowChangeInternal:
d->handleWindowChange();
break;
- case QEvent::ScreenChangeInternal: {
+ case QEvent::ScreenChangeInternal:
+ {
QScreen *newScreen = screen();
if (d->offscreenWindow)
d->offscreenWindow->setScreen(newScreen);
- if (d->offscreenSurface)
- d->offscreenSurface->setScreen(newScreen);
-#if QT_CONFIG(opengl)
- if (d->context)
- d->context->setScreen(newScreen);
-#endif
- if (d->useSoftwareRenderer
-#if QT_CONFIG(opengl)
- || d->fbo
-#endif
- ) {
+ if (d->useSoftwareRenderer || d->outputTexture) {
// This will check the size taking the devicePixelRatio into account
// and recreate if needed.
createFramebufferObject();
@@ -1898,10 +1898,6 @@ void QQuickWidget::propagateFocusObjectChanged(QObject *focusObject)
emit window->focusObjectChanged(focusObject);
}
-#if QT_CONFIG(opengl)
-Q_CONSTRUCTOR_FUNCTION(qt_registerDefaultPlatformBackingStoreOpenGLSupport);
-#endif
-
QT_END_NAMESPACE
#include "moc_qquickwidget.cpp"
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index d42fafec8d..a489f8c8cb 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -53,6 +53,8 @@
#include "qquickwidget.h"
#include <private/qwidget_p.h>
+#include <private/qrhi_p.h>
+#include <private/qbackingstorerhisupport_p.h>
#include <QtCore/qurl.h>
#include <QtCore/qelapsedtimer.h>
@@ -71,9 +73,6 @@ class QQmlError;
class QQuickItem;
class QQmlComponent;
class QQuickRenderControl;
-class QOpenGLContext;
-class QOffscreenSurface;
-class QOpenGLFramebufferObject;
class QQuickWidgetPrivate
: public QWidgetPrivate,
@@ -85,8 +84,8 @@ public:
static const QQuickWidgetPrivate* get(const QQuickWidget *view) { return view->d_func(); }
QQuickWidgetPrivate();
- ~QQuickWidgetPrivate();
+ void destroy();
void execute();
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &oldGeometry) override;
void initResize();
@@ -96,17 +95,13 @@ public:
void setRootObject(QObject *);
void render(bool needsSync);
void renderSceneGraph();
- void createContext();
- void destroyContext();
+ void initializeWithRhi();
void handleContextCreationFailure(const QSurfaceFormat &format);
-#if QT_CONFIG(opengl)
- GLuint textureId() const override;
+ QPlatformBackingStoreRhiConfig rhiConfig() const override;
+ QRhiTexture *texture() const override;
QPlatformTextureList::Flags textureListFlags() override;
QImage grabFramebuffer() override;
-#else
- QImage grabFramebuffer();
-#endif
void init(QQmlEngine* e = 0);
void initOffscreenWindow();
@@ -124,14 +119,14 @@ public:
QQmlComponent *component;
QBasicTimer resizetimer;
QQuickWindow *offscreenWindow;
- QOffscreenSurface *offscreenSurface;
QQuickRenderControl *renderControl;
-#if QT_CONFIG(opengl)
- QOpenGLFramebufferObject *fbo;
- QOpenGLFramebufferObject *resolvedFbo;
- QOpenGLContext *context;
-#endif
+ QRhi *rhi;
+ QRhiTexture *outputTexture;
+ QRhiRenderBuffer *depthStencil;
+ QRhiRenderBuffer *msaaBuffer;
+ QRhiTextureRenderTarget *rt;
+ QRhiRenderPassDescriptor *rtRp;
QQuickWidget::ResizeMode resizeMode;
QSize initialSize;
@@ -148,6 +143,9 @@ public:
QImage softwareImage;
QRegion updateRegion;
bool forceFullUpdate;
+ bool deviceLost;
+
+ QBackingStoreRhiSupport offscreenRenderer;
};
class QQuickWidgetOffscreenWindow: public QQuickWindow
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
index a63ebde084..f6a91d8534 100644
--- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -127,6 +127,7 @@ public:
tst_qquickwidget();
private slots:
+ void initTestCase();
void showHide();
void reparentAfterShow();
void changeGeometry();
@@ -165,6 +166,20 @@ tst_qquickwidget::tst_qquickwidget()
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
}
+void tst_qquickwidget::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+
+ // ### QTBUG-101884 Skip this test in the QEMU configs in the CI. That runs
+ // with the offscreen plugin and the software backend of Qt Quick. Until
+ // some of the test cases are investigated, skip the whole test.
+ if ((QGuiApplication::platformName() == QLatin1String("offscreen"))
+ || (QGuiApplication::platformName() == QLatin1String("minimal")))
+ {
+ QSKIP("Skipping due to using a an offscreen platform / software rendering");
+ }
+}
+
void tst_qquickwidget::showHide()
{
QWidget window;
@@ -380,8 +395,6 @@ void tst_qquickwidget::engine()
void tst_qquickwidget::readback()
{
- QWidget window;
-
QScopedPointer<QQuickWidget> view(new QQuickWidget);
view->setSource(testFileUrl("rectangle.qml"));