From 575520fe3063f3d6deac5e8266b3e886ac25d88a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 27 Apr 2018 15:08:10 -0700 Subject: [PATCH] Ensure we actually delete the QML scenegraph! --- libraries/qml/src/qml/impl/SharedObject.cpp | 7 +- tests/qml/qml/controls/WebEntityView.qml | 15 ++++ tests/qml/src/main.cpp | 84 ++++++++++++++------- 3 files changed, 78 insertions(+), 28 deletions(-) diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp index 7bcb216ba8..2fde057ca8 100644 --- a/libraries/qml/src/qml/impl/SharedObject.cpp +++ b/libraries/qml/src/qml/impl/SharedObject.cpp @@ -90,14 +90,17 @@ SharedObject::~SharedObject() { _renderControl = nullptr; } + if (_rootItem) { + delete _rootItem; + _rootItem = nullptr; + } + if (_quickWindow) { _quickWindow->destroy(); delete _quickWindow; _quickWindow = nullptr; } - // _rootItem is parented to the quickWindow, so needs no explicit destruction - if (_qmlContext) { auto engine = _qmlContext->engine(); delete _qmlContext; diff --git a/tests/qml/qml/controls/WebEntityView.qml b/tests/qml/qml/controls/WebEntityView.qml index a6c38f4abd..5bd29ef457 100644 --- a/tests/qml/qml/controls/WebEntityView.qml +++ b/tests/qml/qml/controls/WebEntityView.qml @@ -10,6 +10,21 @@ import QtQuick 2.5 import QtWebEngine 1.5 +import Hifi 1.0 + +/* +TestItem { + Rectangle { + anchors.fill: parent + anchors.margins: 10 + color: "blue" + property string url: "" + ColorAnimation on color { + loops: Animation.Infinite; from: "blue"; to: "yellow"; duration: 1000 + } + } +} +*/ WebEngineView { id: webViewCore diff --git a/tests/qml/src/main.cpp b/tests/qml/src/main.cpp index cd5a567e95..ec4012898f 100644 --- a/tests/qml/src/main.cpp +++ b/tests/qml/src/main.cpp @@ -48,6 +48,17 @@ namespace gl { extern void initModuleGl(); } +class QTestItem : public QQuickItem { + Q_OBJECT +public: + QTestItem(QQuickItem* parent = nullptr) : QQuickItem(parent) { + qDebug() << __FUNCTION__; + } + + ~QTestItem() { + qDebug() << __FUNCTION__; + } +}; QUrl getTestResource(const QString& relativePath) { static QString dir; @@ -89,9 +100,10 @@ private: GLuint _fbo{ 0 }; const QSize _qmlSize{ 640, 480 }; bool _aboutToQuit{ false }; + uint64_t _createStopTime; void initGl(); void updateSurfaces(); - void buildSurface(QmlInfo& qmlInfo); + void buildSurface(QmlInfo& qmlInfo, bool allowVideo); void destroySurface(QmlInfo& qmlInfo); void resizeWindow(const QSize& size); void draw(); @@ -111,8 +123,10 @@ TestWindow::TestWindow() { QSurfaceFormat::setDefaultFormat(format); setFormat(format); - show(); + qmlRegisterType("Hifi", 1, 0, "TestItem"); + show(); + _createStopTime = usecTimestampNow() + (3000u * USECS_PER_SECOND); resize(QSize(800, 600)); @@ -167,40 +181,56 @@ QString getSourceUrl() { return SOURCE_URLS[index]; } +#define CACHE_WEBVIEWS 0 +#if CACHE_WEBVIEWS +static std::list _cache; +#endif -void TestWindow::buildSurface(QmlInfo& qmlInfo) { +hifi::qml::QmlContextObjectCallback callback = [](QQmlContext* context, QQuickItem* item) { + item->setProperty(URL_PROPERTY, getSourceUrl()); +}; + +void TestWindow::buildSurface(QmlInfo& qmlInfo, bool allowVideo) { ++_surfaceCount; - auto lifetimeSecs = (uint32_t)(2.0f + (randFloat() * 10.0f)); + auto lifetimeSecs = (uint32_t)(5.0f + (randFloat() * 10.0f)); auto lifetimeUsecs = (USECS_PER_SECOND * lifetimeSecs); qmlInfo.lifetime = lifetimeUsecs + usecTimestampNow(); qmlInfo.texture = 0; - auto& surface = qmlInfo.surface; - surface.reset(new hifi::qml::OffscreenSurface()); - surface->setMaxFps(DEFAULT_MAX_FPS); - surface->resize(_qmlSize); - surface->setMaxFps(DEFAULT_MAX_FPS); - hifi::qml::QmlContextObjectCallback callback = [](QQmlContext* context, QQuickItem* item) { - item->setProperty(URL_PROPERTY, getSourceUrl()); - }; - surface->load(getTestResource(CONTROL_URL), callback); - surface->resume(); +#if CACHE_WEBVIEWS + if (_cache.empty()) { + _cache.emplace_back(new hifi::qml::OffscreenSurface()); + auto& surface = _cache.back(); + surface->load(getTestResource(CONTROL_URL)); + surface->setMaxFps(DEFAULT_MAX_FPS); + } + qmlInfo.surface = _cache.front(); + _cache.pop_front(); +#else + qmlInfo.surface.reset(new hifi::qml::OffscreenSurface()); + qmlInfo.surface->load(getTestResource(CONTROL_URL)); + qmlInfo.surface->setMaxFps(DEFAULT_MAX_FPS); +#endif + + qmlInfo.surface->resize(_qmlSize); + auto url = allowVideo ? "https://www.youtube.com/watch?v=gDXwhHm4GhM" : getSourceUrl(); + qmlInfo.surface->getRootItem()->setProperty(URL_PROPERTY, url); + qmlInfo.surface->resume(); } + void TestWindow::destroySurface(QmlInfo& qmlInfo) { auto& surface = qmlInfo.surface; - QQuickItem* rootItem = surface->getRootItem(); - if (rootItem) { - QObject* obj = rootItem->findChild("webEngineView"); - if (!obj && rootItem->objectName() == "webEngineView") { - obj = rootItem; - } - if (obj) { - // stop loading - QMetaObject::invokeMethod(obj, "stop"); - } + auto webView = surface->getRootItem(); + if (webView) { + // stop loading + QMetaObject::invokeMethod(webView, "stop"); + webView->setProperty(URL_PROPERTY, "about:blank"); } surface->pause(); +#if CACHE_WEBVIEWS + _cache.push_back(surface); +#endif surface.reset(); } @@ -211,8 +241,8 @@ void TestWindow::updateSurfaces() { for (size_t y = 0; y < DIVISIONS_Y; ++y) { auto& qmlInfo = _surfaces[x][y]; if (!qmlInfo.surface) { - if (randFloat() > 0.99f) { - buildSurface(qmlInfo); + if (now < _createStopTime && randFloat() > 0.99f) { + buildSurface(qmlInfo, x == 0 && y == 0); } else { continue; } @@ -298,3 +328,5 @@ int main(int argc, char** argv) { app.exec(); return 0; } + +#include "main.moc" \ No newline at end of file