Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: Ibb3be39cbdaf363f017fdfd62e4647acbc3443cb
This commit is contained in:
commit
0ee087f5a5
|
@ -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"
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 {
|
||||
|
|
Binary file not shown.
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -262,6 +262,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()
|
||||
|
||||
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue