diff options
7 files changed, 158 insertions, 21 deletions
diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp index 21d415bbb6..082bd01fd0 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.cpp @@ -347,30 +347,106 @@ void QQmlPreviewHandler::setCurrentWindow(QQuickWindow *window) return; if (m_currentWindow) { + disconnect(m_currentWindow.data(), &QQuickWindow::beforeSynchronizing, + this, &QQmlPreviewHandler::beforeSynchronizing); + disconnect(m_currentWindow.data(), &QQuickWindow::afterSynchronizing, + this, &QQmlPreviewHandler::afterSynchronizing); + disconnect(m_currentWindow.data(), &QQuickWindow::beforeRendering, + this, &QQmlPreviewHandler::beforeRendering); disconnect(m_currentWindow.data(), &QQuickWindow::frameSwapped, this, &QQmlPreviewHandler::frameSwapped); m_fpsTimer.stop(); - m_frames = 0; + m_rendering = FrameTime(); + m_synchronizing = FrameTime(); } m_currentWindow = window; if (m_currentWindow) { + connect(m_currentWindow.data(), &QQuickWindow::beforeSynchronizing, + this, &QQmlPreviewHandler::beforeSynchronizing, Qt::DirectConnection); + connect(m_currentWindow.data(), &QQuickWindow::afterSynchronizing, + this, &QQmlPreviewHandler::afterSynchronizing, Qt::DirectConnection); + connect(m_currentWindow.data(), &QQuickWindow::beforeRendering, + this, &QQmlPreviewHandler::beforeRendering, Qt::DirectConnection); connect(m_currentWindow.data(), &QQuickWindow::frameSwapped, - this, &QQmlPreviewHandler::frameSwapped); + this, &QQmlPreviewHandler::frameSwapped, Qt::DirectConnection); m_fpsTimer.start(); } } +void QQmlPreviewHandler::beforeSynchronizing() +{ + m_synchronizing.beginFrame(); +} + +void QQmlPreviewHandler::afterSynchronizing() +{ + + if (m_rendering.elapsed >= 0) + m_rendering.endFrame(); + m_synchronizing.recordFrame(); + m_synchronizing.endFrame(); +} + +void QQmlPreviewHandler::beforeRendering() +{ + m_rendering.beginFrame(); +} + void QQmlPreviewHandler::frameSwapped() { - ++m_frames; + m_rendering.recordFrame(); +} + +void QQmlPreviewHandler::FrameTime::beginFrame() +{ + timer.start(); +} + +void QQmlPreviewHandler::FrameTime::recordFrame() +{ + elapsed = timer.elapsed(); +} + +void QQmlPreviewHandler::FrameTime::endFrame() +{ + if (elapsed < min) + min = static_cast<quint16>(qMax(0ll, elapsed)); + if (elapsed > max) + max = static_cast<quint16>(qMin(qint64(std::numeric_limits<quint16>::max()), elapsed)); + total = static_cast<quint16>(qBound(0ll, qint64(std::numeric_limits<quint16>::max()), + elapsed + total)); + ++number; + elapsed = -1; +} + +void QQmlPreviewHandler::FrameTime::reset() +{ + min = std::numeric_limits<quint16>::max(); + max = 0; + total = 0; + number = 0; } void QQmlPreviewHandler::fpsTimerHit() { - emit fps(m_frames); - m_frames = 0; + const FpsInfo info = { + m_synchronizing.number, + m_synchronizing.min, + m_synchronizing.max, + m_synchronizing.total, + + m_rendering.number, + m_rendering.min, + m_rendering.max, + m_rendering.total + }; + + emit fps(info); + + m_rendering.reset(); + m_synchronizing.reset(); } void QQmlPreviewHandler::tryCreateObject() diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h index d5888d67a4..7526b11cd7 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewhandler.h @@ -46,6 +46,7 @@ #include <QtCore/qvector.h> #include <QtCore/qrect.h> #include <QtCore/qpointer.h> +#include <QtCore/qelapsedtimer.h> #include <QtQml/qqmlengine.h> QT_BEGIN_NAMESPACE @@ -73,9 +74,21 @@ public: void clear(); + struct FpsInfo { + quint16 numSyncs; + quint16 minSync; + quint16 maxSync; + quint16 totalSync; + + quint16 numRenders; + quint16 minRender; + quint16 maxRender; + quint16 totalRender; + }; + signals: void error(const QString &message); - void fps(quint16 frames); + void fps(const FpsInfo &info); protected: bool eventFilter(QObject *obj, QEvent *event); @@ -83,7 +96,12 @@ private: void tryCreateObject(); void showObject(QObject *object); void setCurrentWindow(QQuickWindow *window); + + void beforeSynchronizing(); + void afterSynchronizing(); + void beforeRendering(); void frameSwapped(); + void fpsTimerHit(); void removeTranslators(); @@ -96,7 +114,23 @@ private: QQmlPreviewPosition m_lastPosition; QTimer m_fpsTimer; - quint16 m_frames = 0; + + struct FrameTime { + void beginFrame(); + void recordFrame(); + void endFrame(); + void reset(); + + QElapsedTimer timer; + qint64 elapsed = -1; + quint16 min = std::numeric_limits<quint16>::max(); + quint16 max = 0; + quint16 total = 0; + quint16 number = 0; + }; + + FrameTime m_rendering; + FrameTime m_synchronizing; QScopedPointer<QTranslator> m_qtTranslator; QScopedPointer<QTranslator> m_qmlTranslator; @@ -104,4 +138,6 @@ private: QT_END_NAMESPACE +Q_DECLARE_METATYPE(QQmlPreviewHandler::FpsInfo) + #endif // QQMLPREVIEWHANDLER_H diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp index b6074f5712..937ca48456 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.cpp @@ -172,10 +172,12 @@ void QQmlPreviewServiceImpl::forwardError(const QString &error) emit messageToClient(name(), packet.data()); } -void QQmlPreviewServiceImpl::forwardFps(quint16 frames) +void QQmlPreviewServiceImpl::forwardFps(const QQmlPreviewHandler::FpsInfo &frames) { QQmlDebugPacket packet; - packet << static_cast<qint8>(Fps) << frames; + packet << static_cast<qint8>(Fps) + << frames.numSyncs << frames.minSync << frames.maxSync << frames.totalSync + << frames.numRenders << frames.minRender << frames.maxRender << frames.totalRender; emit messageToClient(name(), packet.data()); } diff --git a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.h b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.h index 4ddbf949b7..b13ef43501 100644 --- a/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.h +++ b/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewservice.h @@ -78,7 +78,7 @@ public: void forwardRequest(const QString &file); void forwardError(const QString &error); - void forwardFps(quint16 frames); + void forwardFps(const QQmlPreviewHandler::FpsInfo &frames); signals: void error(const QString &file); diff --git a/src/qmldebug/qqmlpreviewclient.cpp b/src/qmldebug/qqmlpreviewclient.cpp index ba27457765..60937b9cfd 100644 --- a/src/qmldebug/qqmlpreviewclient.cpp +++ b/src/qmldebug/qqmlpreviewclient.cpp @@ -75,9 +75,10 @@ void QQmlPreviewClient::messageReceived(const QByteArray &message) break; } case Fps: { - quint16 frames; - packet >> frames; - emit fps(frames); + FpsInfo info; + packet >> info.numSyncs >> info.minSync >> info.maxSync >> info.totalSync + >> info.numRenders >> info.minRender >> info.maxRender >> info.totalRender; + emit fps(info); break; } default: diff --git a/src/qmldebug/qqmlpreviewclient_p.h b/src/qmldebug/qqmlpreviewclient_p.h index 67615cabb2..65661613e9 100644 --- a/src/qmldebug/qqmlpreviewclient_p.h +++ b/src/qmldebug/qqmlpreviewclient_p.h @@ -76,6 +76,18 @@ public: Language }; + struct FpsInfo { + quint16 numSyncs = 0; + quint16 minSync = std::numeric_limits<quint16>::max(); + quint16 maxSync = 0; + quint16 totalSync = 0; + + quint16 numRenders = 0; + quint16 minRender = std::numeric_limits<quint16>::max(); + quint16 maxRender = 0; + quint16 totalRender = 0; + }; + QQmlPreviewClient(QQmlDebugConnection *parent); void messageReceived(const QByteArray &message) override; @@ -91,7 +103,7 @@ public: signals: void request(const QString &path); void error(const QString &message); - void fps(quint16 frames); + void fps(const FpsInfo &info); }; QT_END_NAMESPACE diff --git a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp index 14254d9725..b4f8f389cf 100644 --- a/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp +++ b/tests/auto/qml/debugger/qqmlpreview/tst_qqmlpreview.cpp @@ -57,7 +57,7 @@ private: QStringList m_filesNotFound; QStringList m_directories; QStringList m_serviceErrors; - quint16 m_frames = 0; + QQmlPreviewClient::FpsInfo m_frameStats; private slots: void cleanup() final; @@ -105,8 +105,9 @@ QList<QQmlDebugClient *> tst_QQmlPreview::createClients() QObject::connect(m_client, &QQmlPreviewClient::error, this, [this](const QString &error) { m_serviceErrors.append(error); }); - QObject::connect(m_client, &QQmlPreviewClient::fps, this, [this](quint16 frames) { - m_frames += frames; + QObject::connect(m_client, &QQmlPreviewClient::fps, + this, [this](const QQmlPreviewClient::FpsInfo &info) { + m_frameStats = info; }); return QList<QQmlDebugClient *>({m_client}); @@ -141,7 +142,7 @@ void tst_QQmlPreview::cleanup() m_files.clear(); m_filesNotFound.clear(); m_serviceErrors.clear(); - m_frames = 0; + m_frameStats = QQmlPreviewClient::FpsInfo(); } void tst_QQmlPreview::connect() @@ -336,10 +337,19 @@ void tst_QQmlPreview::fps() QCOMPARE(startQmlProcess(file), ConnectSuccess); QVERIFY(m_client); m_client->triggerLoad(testFileUrl(file)); - if (QGuiApplication::platformName() != "offscreen") - QTRY_VERIFY(m_frames > 100); - else + if (QGuiApplication::platformName() != "offscreen") { + QTRY_VERIFY(m_frameStats.numSyncs > 10); + QVERIFY(m_frameStats.minSync <= m_frameStats.maxSync); + QVERIFY(m_frameStats.totalSync / m_frameStats.numSyncs >= m_frameStats.minSync - 1); + QVERIFY(m_frameStats.totalSync / m_frameStats.numSyncs <= m_frameStats.maxSync); + + QVERIFY(m_frameStats.numRenders > 0); + QVERIFY(m_frameStats.minRender <= m_frameStats.maxRender); + QVERIFY(m_frameStats.totalRender / m_frameStats.numRenders >= m_frameStats.minRender - 1); + QVERIFY(m_frameStats.totalRender / m_frameStats.numRenders <= m_frameStats.maxRender); + } else { QSKIP("offscreen rendering doesn't produce any frames"); + } } void tst_QQmlPreview::language() |