diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-11-15 01:02:20 +0100 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2019-11-15 01:02:20 +0100 |
commit | 0ee087f5a5edd7d1aa39fd15e0dc85985320c09a (patch) | |
tree | a998054898e2013407f38b4b6ea267d7f912bd21 | |
parent | cd78e8cd862a819ae2683ed98a131f2582e18609 (diff) | |
parent | b6b1d5899415fef3231120c08c56a1dc2e246940 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: Ibb3be39cbdaf363f017fdfd62e4647acbc3443cb
-rw-r--r-- | examples/qml/xmlhttprequest/Get.qml | 2 | ||||
-rw-r--r-- | examples/quick/scenegraph/fboitem/fboitem.qrc | 2 | ||||
-rw-r--r-- | examples/quick/scenegraph/fboitem/main.qml | 15 | ||||
-rw-r--r-- | examples/quick/scenegraph/fboitem/shaders/+qsb/checker.frag | bin | 0 -> 1615 bytes | |||
-rw-r--r-- | examples/quick/scenegraph/fboitem/shaders/checker.frag | 14 | ||||
-rw-r--r-- | examples/quick/scenegraph/fboitem/shaders/checker_rhi.frag | 22 | ||||
-rw-r--r-- | src/qmltyperegistrar/qmltyperegistrar.pro | 12 | ||||
-rw-r--r-- | src/qmltyperegistrar/qmltypes.prf | 13 | ||||
-rw-r--r-- | src/quick/items/qquickanimatedsprite.cpp | 35 | ||||
-rw-r--r-- | src/quick/items/qquickanimatedsprite_p.h | 11 | ||||
-rw-r--r-- | src/quick/items/qquickanimatedsprite_p_p.h | 5 | ||||
-rw-r--r-- | src/quick/items/qquickframebufferobject.cpp | 30 | ||||
-rw-r--r-- | src/quick/items/qquickframebufferobject.h | 3 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 13 | ||||
-rw-r--r-- | tests/auto/quick/qquickanimatedsprite/data/finishBehavior.qml | 18 | ||||
-rw-r--r-- | tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp | 26 |
16 files changed, 185 insertions, 36 deletions
diff --git a/examples/qml/xmlhttprequest/Get.qml b/examples/qml/xmlhttprequest/Get.qml index 1a35d32666..96cec2a99d 100644 --- a/examples/qml/xmlhttprequest/Get.qml +++ b/examples/qml/xmlhttprequest/Get.qml @@ -58,7 +58,7 @@ GetForm mouseArea.onClicked: Utils.makeRequest() - button.border.width: button.pressed ? 2 : 1 + button.border.width: mouseArea.pressed ? 2 : 1 text.text: "Request data.xml" } diff --git a/examples/quick/scenegraph/fboitem/fboitem.qrc b/examples/quick/scenegraph/fboitem/fboitem.qrc index 9d9db70654..eeb5c36afd 100644 --- a/examples/quick/scenegraph/fboitem/fboitem.qrc +++ b/examples/quick/scenegraph/fboitem/fboitem.qrc @@ -1,5 +1,7 @@ <RCC> <qresource prefix="/scenegraph/fboitem"> <file>main.qml</file> + <file>shaders/checker.frag</file> + <file>shaders/+qsb/checker.frag</file> </qresource> </RCC> diff --git a/examples/quick/scenegraph/fboitem/main.qml b/examples/quick/scenegraph/fboitem/main.qml index 92fa99e847..1f1829deda 100644 --- a/examples/quick/scenegraph/fboitem/main.qml +++ b/examples/quick/scenegraph/fboitem/main.qml @@ -67,20 +67,7 @@ Item { property size pixelSize: Qt.size(width / tileSize, height / tileSize); - fragmentShader: - " - uniform lowp vec4 color1; - uniform lowp vec4 color2; - uniform highp vec2 pixelSize; - varying highp vec2 qt_TexCoord0; - void main() { - highp vec2 tc = sign(sin(3.14159265358979323846 * qt_TexCoord0 * pixelSize)); - if (tc.x != tc.y) - gl_FragColor = color1; - else - gl_FragColor = color2; - } - " + fragmentShader: "qrc:/scenegraph/fboitem/shaders/checker.frag" } Renderer { diff --git a/examples/quick/scenegraph/fboitem/shaders/+qsb/checker.frag b/examples/quick/scenegraph/fboitem/shaders/+qsb/checker.frag Binary files differnew file mode 100644 index 0000000000..5037899d19 --- /dev/null +++ b/examples/quick/scenegraph/fboitem/shaders/+qsb/checker.frag diff --git a/examples/quick/scenegraph/fboitem/shaders/checker.frag b/examples/quick/scenegraph/fboitem/shaders/checker.frag new file mode 100644 index 0000000000..044b3bad58 --- /dev/null +++ b/examples/quick/scenegraph/fboitem/shaders/checker.frag @@ -0,0 +1,14 @@ +uniform lowp vec4 color1; +uniform lowp vec4 color2; +uniform highp vec2 pixelSize; + +varying highp vec2 qt_TexCoord0; + +void main() +{ + highp vec2 tc = sign(sin(3.14159265358979323846 * qt_TexCoord0 * pixelSize)); + if (tc.x != tc.y) + gl_FragColor = color1; + else + gl_FragColor = color2; +} diff --git a/examples/quick/scenegraph/fboitem/shaders/checker_rhi.frag b/examples/quick/scenegraph/fboitem/shaders/checker_rhi.frag new file mode 100644 index 0000000000..1e4131d026 --- /dev/null +++ b/examples/quick/scenegraph/fboitem/shaders/checker_rhi.frag @@ -0,0 +1,22 @@ +#version 440 + +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + + vec4 color1; + vec4 color2; + vec2 pixelSize; +} ubuf; + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +void main() +{ + vec2 tc = sign(sin(3.14159265358979323846 * qt_TexCoord0 * ubuf.pixelSize)); + if (tc.x != tc.y) + fragColor = ubuf.color1; + else + fragColor = ubuf.color2; +} diff --git a/src/qmltyperegistrar/qmltyperegistrar.pro b/src/qmltyperegistrar/qmltyperegistrar.pro index 8f4235c015..dff8f00ca3 100644 --- a/src/qmltyperegistrar/qmltyperegistrar.pro +++ b/src/qmltyperegistrar/qmltyperegistrar.pro @@ -18,7 +18,15 @@ HEADERS += \ build_integration.files = qmltypes.prf build_integration.path = $$[QT_HOST_DATA]/mkspecs/features -prefix_build: INSTALLS += build_integration -else: COPIES += build_integration + +prefix_build { + load(qt_build_paths) + qmltypes_to_builddir.files = qmltypes.prf + qmltypes_to_builddir.path = $$MODULE_BASE_OUTDIR/mkspecs/features + COPIES += qmltypes_to_builddir + INSTALLS += build_integration +} else { + COPIES += build_integration +} load(qt_tool) diff --git a/src/qmltyperegistrar/qmltypes.prf b/src/qmltyperegistrar/qmltypes.prf index 4fed3c69c7..ed11ef44cf 100644 --- a/src/qmltyperegistrar/qmltypes.prf +++ b/src/qmltyperegistrar/qmltypes.prf @@ -39,8 +39,17 @@ qt_module_deps += $$replace(QT_PRIVATE, -private$, '') qt_module_deps = $$replace(qt_module_deps, _private$, '') all_qt_module_deps = $$resolve_depends(qt_module_deps, "QT.", ".depends" ".run_depends") foreign_types = -for(dep, all_qt_module_deps): \ - foreign_types += $$[QT_INSTALL_LIBS]/metatypes/$$lower($$eval(QT.$${dep}.module))_metatypes.json +for(dep, all_qt_module_deps) { + METATYPES_FILENAME = $$lower($$eval(QT.$${dep}.module))_metatypes.json + INSTALLED_METATYPES = $$[QT_INSTALL_LIBS]/metatypes/$$METATYPES_FILENAME + isEmpty(MODULE_BASE_OUTDIR) { + foreign_types += $$INSTALLED_METATYPES + } else { + MODULE_BASE_METATYPES = $$MODULE_BASE_OUTDIR/lib/metatypes/$$METATYPES_FILENAME + exists($$MODULE_BASE_METATYPES): foreign_types += $$MODULE_BASE_METATYPES + else: foreign_types += $$INSTALLED_METATYPES + } +} QML_TYPEREGISTRAR_FLAGS = \ --generate-plugintypes=$$QMLTYPES_FILENAME \ diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp index 21c09f898d..b285fe56ed 100644 --- a/src/quick/items/qquickanimatedsprite.cpp +++ b/src/quick/items/qquickanimatedsprite.cpp @@ -263,6 +263,19 @@ QT_BEGIN_NAMESPACE */ /*! + \qmlproperty enumeration QtQuick::AnimatedSprite::finishBehavior + + The behavior when the animation finishes on its own. + + \value FinishAtInitialFrame + When the animation finishes it returns to the initial frame. + This is the default behavior. + + \value FinishAtFinalFrame + When the animation finishes it stays on the final frame. +*/ + +/*! \qmlmethod int QtQuick::AnimatedSprite::restart() Stops, then starts the sprite animation. @@ -381,6 +394,12 @@ int QQuickAnimatedSprite::currentFrame() const return d->m_curFrame; } +QQuickAnimatedSprite::FinishBehavior QQuickAnimatedSprite::finishBehavior() const +{ + Q_D(const QQuickAnimatedSprite); + return d->m_finishBehavior; +} + bool QQuickAnimatedSprite::isCurrentFrameChangedConnected() { IS_SIGNAL_CONNECTED(this, QQuickAnimatedSprite, currentFrameChanged, (int)); @@ -704,6 +723,16 @@ void QQuickAnimatedSprite::setCurrentFrame(int arg) //TODO-C: Probably only work } } +void QQuickAnimatedSprite::setFinishBehavior(FinishBehavior arg) +{ + Q_D(QQuickAnimatedSprite); + + if (d->m_finishBehavior != arg) { + d->m_finishBehavior = arg; + Q_EMIT finishBehaviorChanged(arg); + } +} + void QQuickAnimatedSprite::createEngine() { Q_D(QQuickAnimatedSprite); @@ -838,7 +867,11 @@ void QQuickAnimatedSprite::prepareNextFrame(QSGSpriteNode *node) progress = 0; } if (d->m_loops > 0 && d->m_curLoop >= d->m_loops) { - frameAt = 0; + if (d->m_finishBehavior == FinishAtInitialFrame) + frameAt = 0; + else + frameAt = frameCount() - 1; + d->m_curFrame = frameAt; d->m_running = false; emit runningChanged(false); emit finished(); diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h index 30f64e9def..c28b6ce3af 100644 --- a/src/quick/items/qquickanimatedsprite_p.h +++ b/src/quick/items/qquickanimatedsprite_p.h @@ -92,6 +92,7 @@ class Q_AUTOTEST_EXPORT QQuickAnimatedSprite : public QQuickItem Q_PROPERTY(int loops READ loops WRITE setLoops NOTIFY loopsChanged) Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(int currentFrame READ currentFrame WRITE setCurrentFrame NOTIFY currentFrameChanged) + Q_PROPERTY(FinishBehavior finishBehavior READ finishBehavior WRITE setFinishBehavior NOTIFY finishBehaviorChanged REVISION 15) QML_NAMED_ELEMENT(AnimatedSprite) public: @@ -101,6 +102,12 @@ public: }; Q_ENUM(LoopParameters) + enum FinishBehavior { + FinishAtInitialFrame, + FinishAtFinalFrame + }; + Q_ENUM(FinishBehavior) + bool running() const; bool interpolate() const; QUrl source() const; @@ -116,6 +123,7 @@ public: int loops() const; bool paused() const; int currentFrame() const; + FinishBehavior finishBehavior() const; Q_SIGNALS: @@ -135,6 +143,7 @@ Q_SIGNALS: void frameDurationChanged(int arg); void loopsChanged(int arg); void currentFrameChanged(int arg); + Q_REVISION(15) void finishBehaviorChanged(FinishBehavior arg); Q_REVISION(12) void finished(); @@ -163,7 +172,7 @@ public Q_SLOTS: void resetFrameDuration(); void setLoops(int arg); void setCurrentFrame(int arg); - + void setFinishBehavior(FinishBehavior arg); private Q_SLOTS: void createEngine(); diff --git a/src/quick/items/qquickanimatedsprite_p_p.h b/src/quick/items/qquickanimatedsprite_p_p.h index 3610e58861..fb8faefbee 100644 --- a/src/quick/items/qquickanimatedsprite_p_p.h +++ b/src/quick/items/qquickanimatedsprite_p_p.h @@ -57,11 +57,10 @@ QT_REQUIRE_CONFIG(quick_sprite); #include "qquickitem_p.h" #include "qquicksprite_p.h" +#include "qquickanimatedsprite_p.h" QT_BEGIN_NAMESPACE -class QQuickAnimatedSprite; - class QQuickAnimatedSpritePrivate : public QQuickItemPrivate { Q_DECLARE_PUBLIC(QQuickAnimatedSprite) @@ -78,6 +77,7 @@ public: , m_loops(-1) , m_curLoop(0) , m_pauseOffset(0) + , m_finishBehavior(QQuickAnimatedSprite::FinishAtInitialFrame) { } @@ -93,6 +93,7 @@ public: int m_loops; int m_curLoop; int m_pauseOffset; + QQuickAnimatedSprite::FinishBehavior m_finishBehavior; }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp index 190bc6853c..d5550e78b6 100644 --- a/src/quick/items/qquickframebufferobject.cpp +++ b/src/quick/items/qquickframebufferobject.cpp @@ -83,6 +83,11 @@ public: * Everything that relates to rendering must be located in the * QQuickFramebufferObject::Renderer class. * + * \warning This class is only functional when Qt Quick is rendering + * via OpenGL, either directly or through the \l{Scene Graph + * Adaptations}{RHI-based rendering path}. It is not compatible with + * other RHI backends, such as, Vulkan or Metal. + * * To avoid race conditions and read/write issues from two threads * it is important that the renderer and the item never read or * write shared variables. Communication between the item and the renderer @@ -109,10 +114,6 @@ public: * and can be used directly in \l {ShaderEffect}{ShaderEffects} and other * classes that consume texture providers. * - * \warning This class is only suitable when working directly with OpenGL. It - * is not compatible with the \l{Scene Graph Adaptations}{RHI-based rendering - * path}. - * * \sa {Scene Graph - Rendering FBOs}, {Scene Graph and Rendering} */ @@ -233,6 +234,13 @@ public Q_SLOTS: { if (renderPending) { renderPending = false; + + const bool needsWrap = QSGRendererInterface::isApiRhiBased(window->rendererInterface()->graphicsApi()); + if (needsWrap) { + window->beginExternalCommands(); + window->resetOpenGLState(); + } + fbo->bind(); QOpenGLContext::currentContext()->functions()->glViewport(0, 0, fbo->width(), fbo->height()); renderer->render(); @@ -241,6 +249,9 @@ public Q_SLOTS: if (msDisplayFbo) QOpenGLFramebufferObject::blitFramebuffer(msDisplayFbo, fbo); + if (needsWrap) + window->endExternalCommands(); + markDirty(QSGNode::DirtyMaterial); emit textureChanged(); } @@ -270,7 +281,8 @@ public: static inline bool isOpenGL(QSGRenderContext *rc) { QSGRendererInterface *rif = rc->sceneGraphContext()->rendererInterface(rc); - return !rif || rif->graphicsApi() == QSGRendererInterface::OpenGL; + return rif && (rif->graphicsApi() == QSGRendererInterface::OpenGL + || rif->graphicsApi() == QSGRendererInterface::OpenGLRhi); } /*! @@ -335,9 +347,11 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode displayTexture = n->msDisplayFbo->texture(); } - n->setTexture(window()->createTextureFromId(displayTexture, - n->fbo->size(), - QQuickWindow::TextureHasAlphaChannel)); + QSGTexture *wrapper = window()->createTextureFromNativeObject(QQuickWindow::NativeObjectTexture, + &displayTexture, 0, + n->fbo->size(), + QQuickWindow::TextureHasAlphaChannel); + n->setTexture(wrapper); } n->setTextureCoordinatesTransform(d->mirrorVertically ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform); diff --git a/src/quick/items/qquickframebufferobject.h b/src/quick/items/qquickframebufferobject.h index db143e48cf..e26c8293a6 100644 --- a/src/quick/items/qquickframebufferobject.h +++ b/src/quick/items/qquickframebufferobject.h @@ -48,7 +48,8 @@ class QOpenGLFramebufferObject; class QQuickFramebufferObjectPrivate; class QSGFramebufferObjectNode; -// ### Qt 6: To be removed. To be seen if an alternative will need to be introduced. +// ### Qt 6: Consider what to do here. QQuickFbo supports both direct OpenGL and +// OpenGL via QRhi, but it cannot function when running with another rhi backend. class Q_QUICK_EXPORT QQuickFramebufferObject : public QQuickItem { diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index cb4656874d..9b45750a3b 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -4735,8 +4735,7 @@ void QQuickWindow::setDefaultAlphaBuffer(bool useAlpha) adaptation. \note This function has no effect when running on the RHI graphics - abstraction. With the RHI, the functions to call when enqueuing native - graphics commands are beginExternalCommands() and endExternalCommands(). + abstraction and the underlying RHI backend is not OpenGL. \sa QQuickWindow::beforeRendering(), beginExternalCommands(), endExternalCommands() */ @@ -4744,7 +4743,7 @@ void QQuickWindow::resetOpenGLState() { Q_D(QQuickWindow); - if (d->rhi || !openglContext()) + if (!openglContext()) return; QOpenGLContext *ctx = openglContext(); @@ -4859,7 +4858,13 @@ const QQuickWindow::GraphicsStateInfo &QQuickWindow::graphicsStateInfo() directly and the RHI graphics abstraction layer is not in use. Refer to resetOpenGLState() in that case. - \sa endExternalCommands() + \note When the scenegraph is using the RHI graphics abstraction layer with + the OpenGL backend underneath, pay attention to the fact that the OpenGL + state in the context can have arbitrary settings, and this function does not + perform any resetting of the state back to defaults. Call + resetOpenGLState() if that is seen necessary. + + \sa endExternalCommands(), resetOpenGLState() \since 5.14 */ diff --git a/tests/auto/quick/qquickanimatedsprite/data/finishBehavior.qml b/tests/auto/quick/qquickanimatedsprite/data/finishBehavior.qml new file mode 100644 index 0000000000..13a0ef4622 --- /dev/null +++ b/tests/auto/quick/qquickanimatedsprite/data/finishBehavior.qml @@ -0,0 +1,18 @@ +import QtQuick 2.15 + +Rectangle { + color: "black" + width: 320 + height: 320 + + AnimatedSprite { + objectName: "sprite" + loops: 1 + source: "squarefacesprite.png" + frameCount: 6 + frameDuration: 64 + width: 160 + height: 160 + finishBehavior: AnimatedSprite.FinishAtFinalFrame + } +} diff --git a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp index b5366e2bb9..9f616c56e2 100644 --- a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp +++ b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp @@ -57,6 +57,7 @@ private slots: void test_changeSourceToSmallerImgKeepingBigFrameSize(); void test_infiniteLoops(); void test_implicitSize(); + void test_finishBehavior(); }; void tst_qquickanimatedsprite::initTestCase() @@ -428,6 +429,31 @@ void tst_qquickanimatedsprite::test_infiniteLoops() QCOMPARE(finishedSpy.count(), 0); } +void tst_qquickanimatedsprite::test_finishBehavior() +{ + QQuickView window; + window.setSource(testFileUrl("finishBehavior.qml")); + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QVERIFY(window.rootObject()); + + QQuickAnimatedSprite* sprite = window.rootObject()->findChild<QQuickAnimatedSprite*>("sprite"); + QVERIFY(sprite); + + QTRY_VERIFY(sprite->running()); + + // correctly stops at last frame + QSignalSpy finishedSpy(sprite, SIGNAL(finished())); + QVERIFY(finishedSpy.wait(2000)); + QCOMPARE(sprite->running(), false); + QCOMPARE(sprite->currentFrame(), 5); + + // correctly starts a second time + sprite->start(); + QTRY_VERIFY(sprite->running()); + QTRY_COMPARE(sprite->currentFrame(), 5); +} + QTEST_MAIN(tst_qquickanimatedsprite) #include "tst_qquickanimatedsprite.moc" |