From 40c42d35a5ba6560e21187bad60d5255df78d49b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 25 Sep 2017 17:50:04 -0700 Subject: [PATCH] Fix long tablet lag on first load --- interface/src/Application.cpp | 1 + interface/src/ui/overlays/Web3DOverlay.cpp | 156 +++++++++--------- interface/src/ui/overlays/Web3DOverlay.h | 6 +- .../ui/src/ui/TabletScriptingInterface.cpp | 2 + .../ui/src/ui/TabletScriptingInterface.h | 1 + scripts/system/tablet-ui/tabletUI.js | 2 +- 6 files changed, 86 insertions(+), 82 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e1c3af1939..55b5ba4bd3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2369,6 +2369,7 @@ void Application::initializeUi() { // Pre-create a couple of Web3D overlays to speed up tablet UI auto offscreenSurfaceCache = DependencyManager::get(); + offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1); offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); } diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index 0807d1c117..c8433766b9 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -62,6 +62,7 @@ static const float OPAQUE_ALPHA_THRESHOLD = 0.99f; const QString Web3DOverlay::TYPE = "web3d"; const QString Web3DOverlay::QML = "Web3DOverlay.qml"; + Web3DOverlay::Web3DOverlay() : _dpi(DPI) { _touchDevice.setCapabilities(QTouchDevice::Position); _touchDevice.setType(QTouchDevice::TouchScreen); @@ -97,6 +98,10 @@ Web3DOverlay::~Web3DOverlay() { } } +void Web3DOverlay::rebuildWebSurface() { + destroyWebSurface(); + buildWebSurface(); +} void Web3DOverlay::destroyWebSurface() { if (!_webSurface) { @@ -136,17 +141,23 @@ void Web3DOverlay::buildWebSurface() { return; } gl::withSavedContext([&] { - _webSurface = DependencyManager::get()->acquire(pickURL()); // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // and the current rendering load) if (_currentMaxFPS != _desiredMaxFPS) { setMaxFPS(_desiredMaxFPS); } - loadSourceURL(); - _webSurface->resume(); + + if (isWebContent()) { + _webSurface = DependencyManager::get()->acquire(QML); + _webSurface->getRootItem()->setProperty("url", _url); + _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); + } else { + _webSurface = DependencyManager::get()->acquire(_url); + setupQmlSurface(); + } + _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); _webSurface->resize(QSize(_resolution.x, _resolution.y)); - _webSurface->getRootItem()->setProperty("url", _url); - _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); + _webSurface->resume(); }); auto selfOverlayID = getOverlayID(); @@ -187,88 +198,61 @@ void Web3DOverlay::update(float deltatime) { Parent::update(deltatime); } -QString Web3DOverlay::pickURL() { +bool Web3DOverlay::isWebContent() const { QUrl sourceUrl(_url); if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || _url.toLower().endsWith(".htm") || _url.toLower().endsWith(".html")) { - if (_webSurface) { - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); - } - return "Web3DOverlay.qml"; - } else { - return QUrl::fromLocalFile(PathUtils::resourcesPath()).toString() + "/" + _url; + return true; } + return false; } -void Web3DOverlay::loadSourceURL() { - if (!_webSurface) { - return; - } +void Web3DOverlay::setupQmlSurface() { + _webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("UserActivityLogger", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Preferences", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Vec3", new Vec3()); + _webSurface->getSurfaceContext()->setContextProperty("Quat", new Quat()); + _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); + _webSurface->getSurfaceContext()->setContextProperty("Entities", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Snapshot", DependencyManager::get().data()); - QUrl sourceUrl(_url); - if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || - _url.toLower().endsWith(".htm") || _url.toLower().endsWith(".html")) { + if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { + auto tabletScriptingInterface = DependencyManager::get(); + auto flags = tabletScriptingInterface->getFlags(); - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); - _webSurface->load("Web3DOverlay.qml"); - _webSurface->resume(); - _webSurface->getRootItem()->setProperty("url", _url); - _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); - - } else { - _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath())); - _webSurface->load(_url, [&](QQmlContext* context, QObject* obj) {}); - _webSurface->resume(); - - _webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags); + _webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Account", AccountScriptingInterface::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("Audio", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("AudioStats", DependencyManager::get()->getStats().data()); _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("UserActivityLogger", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("Preferences", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("Vec3", new Vec3()); - _webSurface->getSurfaceContext()->setContextProperty("Quat", new Quat()); + _webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper()); _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); - _webSurface->getSurfaceContext()->setContextProperty("Entities", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("Snapshot", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("DCModel", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("AvatarList", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance()); + _webSurface->getSurfaceContext()->setContextProperty("InputConfiguration", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("SoundCache", DependencyManager::get().data()); + _webSurface->getSurfaceContext()->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance()); - if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { - auto tabletScriptingInterface = DependencyManager::get(); - auto flags = tabletScriptingInterface->getFlags(); + _webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../"); - _webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags); - _webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("Account", AccountScriptingInterface::getInstance()); - _webSurface->getSurfaceContext()->setContextProperty("Audio", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("AudioStats", DependencyManager::get()->getStats().data()); - _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper()); - _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get()->getMyAvatar().get()); - _webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("DCModel", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance()); - _webSurface->getSurfaceContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance()); - _webSurface->getSurfaceContext()->setContextProperty("AvatarList", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance()); - _webSurface->getSurfaceContext()->setContextProperty("InputConfiguration", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("SoundCache", DependencyManager::get().data()); - _webSurface->getSurfaceContext()->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance()); - - _webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../"); - - tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data()); - - // mark the TabletProxy object as cpp ownership. - QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); - _webSurface->getSurfaceContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); - - // Override min fps for tablet UI, for silky smooth scrolling - setMaxFPS(90); - } + tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data()); + // mark the TabletProxy object as cpp ownership. + QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"); + _webSurface->getSurfaceContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership); + // Override min fps for tablet UI, for silky smooth scrolling + setMaxFPS(90); } - _webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition())); } void Web3DOverlay::setMaxFPS(uint8_t maxFPS) { @@ -594,11 +578,25 @@ QVariant Web3DOverlay::getProperty(const QString& property) { } void Web3DOverlay::setURL(const QString& url) { - _url = url; - if (_webSurface) { - AbstractViewStateInterface::instance()->postLambdaEvent([this, url] { - loadSourceURL(); - }); + if (url != _url) { + bool wasWebContent = isWebContent(); + _url = url; + if (_webSurface) { + if (wasWebContent && isWebContent()) { + // If we're just targeting a new web URL, then switch to that without messing around + // with the underlying QML + AbstractViewStateInterface::instance()->postLambdaEvent([this, url] { + _webSurface->getRootItem()->setProperty("url", _url); + _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); + }); + } else { + // If we're switching to or from web content, or between different QML content + // we need to destroy and rebuild the entire QML surface + AbstractViewStateInterface::instance()->postLambdaEvent([this, url] { + rebuildWebSurface(); + }); + } + } } } diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 6bd540d120..9b7be11a4a 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -31,8 +31,6 @@ public: Web3DOverlay(const Web3DOverlay* Web3DOverlay); virtual ~Web3DOverlay(); - QString pickURL(); - void loadSourceURL(); void setMaxFPS(uint8_t maxFPS); virtual void render(RenderArgs* args) override; virtual const render::ShapeKey getShapeKey() override; @@ -79,6 +77,10 @@ signals: void releaseWebSurface(); private: + void setupQmlSurface(); + void rebuildWebSurface(); + bool isWebContent() const; + InputMode _inputMode { Touch }; QSharedPointer _webSurface; gpu::TexturePointer _texture; diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 8ab03b60d0..4e625c2494 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -26,6 +26,8 @@ // FIXME move to global app properties const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; +const QString TabletScriptingInterface::QML = "hifi/tablet/TabletRoot.qml"; + TabletScriptingInterface::TabletScriptingInterface() { } diff --git a/libraries/ui/src/ui/TabletScriptingInterface.h b/libraries/ui/src/ui/TabletScriptingInterface.h index d3590ec62e..386bce45a8 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.h +++ b/libraries/ui/src/ui/TabletScriptingInterface.h @@ -42,6 +42,7 @@ class TabletScriptingInterface : public QObject, public Dependency { public: TabletScriptingInterface(); ~TabletScriptingInterface(); + static const QString QML; void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; } diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 63c1cc51aa..9ecd0f0230 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -97,7 +97,7 @@ checkTablet() tabletScalePercentage = getTabletScalePercentageFromSettings(); - UIWebTablet = new WebTablet("qml/hifi/tablet/TabletRoot.qml", + UIWebTablet = new WebTablet("hifi/tablet/TabletRoot.qml", DEFAULT_WIDTH * (tabletScalePercentage / 100), null, activeHand, true, null, false); UIWebTablet.register();