Merge pull request #11458 from jherico/fix/tablet_latency

Fix long tablet lag on first load
This commit is contained in:
Andrew Meadows 2017-09-26 16:18:31 -07:00 committed by GitHub
commit dafadf82bb
6 changed files with 86 additions and 82 deletions

View file

@ -2369,6 +2369,7 @@ void Application::initializeUi() {
// Pre-create a couple of Web3D overlays to speed up tablet UI // Pre-create a couple of Web3D overlays to speed up tablet UI
auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>(); auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
offscreenSurfaceCache->reserve(TabletScriptingInterface::QML, 1);
offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2); offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
} }

View file

@ -62,6 +62,7 @@ static const float OPAQUE_ALPHA_THRESHOLD = 0.99f;
const QString Web3DOverlay::TYPE = "web3d"; const QString Web3DOverlay::TYPE = "web3d";
const QString Web3DOverlay::QML = "Web3DOverlay.qml"; const QString Web3DOverlay::QML = "Web3DOverlay.qml";
Web3DOverlay::Web3DOverlay() : _dpi(DPI) { Web3DOverlay::Web3DOverlay() : _dpi(DPI) {
_touchDevice.setCapabilities(QTouchDevice::Position); _touchDevice.setCapabilities(QTouchDevice::Position);
_touchDevice.setType(QTouchDevice::TouchScreen); _touchDevice.setType(QTouchDevice::TouchScreen);
@ -97,6 +98,10 @@ Web3DOverlay::~Web3DOverlay() {
} }
} }
void Web3DOverlay::rebuildWebSurface() {
destroyWebSurface();
buildWebSurface();
}
void Web3DOverlay::destroyWebSurface() { void Web3DOverlay::destroyWebSurface() {
if (!_webSurface) { if (!_webSurface) {
@ -136,17 +141,23 @@ void Web3DOverlay::buildWebSurface() {
return; return;
} }
gl::withSavedContext([&] { gl::withSavedContext([&] {
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(pickURL());
// FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces // FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces
// and the current rendering load) // and the current rendering load)
if (_currentMaxFPS != _desiredMaxFPS) { if (_currentMaxFPS != _desiredMaxFPS) {
setMaxFPS(_desiredMaxFPS); setMaxFPS(_desiredMaxFPS);
} }
loadSourceURL();
_webSurface->resume(); if (isWebContent()) {
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(QML);
_webSurface->getRootItem()->setProperty("url", _url);
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
} else {
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(_url);
setupQmlSurface();
}
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
_webSurface->resize(QSize(_resolution.x, _resolution.y)); _webSurface->resize(QSize(_resolution.x, _resolution.y));
_webSurface->getRootItem()->setProperty("url", _url); _webSurface->resume();
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
}); });
auto selfOverlayID = getOverlayID(); auto selfOverlayID = getOverlayID();
@ -187,88 +198,61 @@ void Web3DOverlay::update(float deltatime) {
Parent::update(deltatime); Parent::update(deltatime);
} }
QString Web3DOverlay::pickURL() { bool Web3DOverlay::isWebContent() const {
QUrl sourceUrl(_url); QUrl sourceUrl(_url);
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
_url.toLower().endsWith(".htm") || _url.toLower().endsWith(".html")) { _url.toLower().endsWith(".htm") || _url.toLower().endsWith(".html")) {
if (_webSurface) { return true;
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
}
return "Web3DOverlay.qml";
} else {
return QUrl::fromLocalFile(PathUtils::resourcesPath()).toString() + "/" + _url;
} }
return false;
} }
void Web3DOverlay::loadSourceURL() { void Web3DOverlay::setupQmlSurface() {
if (!_webSurface) { _webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
return; _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
} _webSurface->getSurfaceContext()->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
_webSurface->getSurfaceContext()->setContextProperty("Vec3", new Vec3());
_webSurface->getSurfaceContext()->setContextProperty("Quat", new Quat());
_webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
_webSurface->getSurfaceContext()->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
QUrl sourceUrl(_url); if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" || auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
_url.toLower().endsWith(".htm") || _url.toLower().endsWith(".html")) { auto flags = tabletScriptingInterface->getFlags();
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); _webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags);
_webSurface->load("Web3DOverlay.qml"); _webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
_webSurface->resume(); _webSurface->getSurfaceContext()->setContextProperty("Account", AccountScriptingInterface::getInstance());
_webSurface->getRootItem()->setProperty("url", _url); _webSurface->getSurfaceContext()->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data());
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); _webSurface->getSurfaceContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
} else {
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath()));
_webSurface->load(_url, [&](QQmlContext* context, QObject* obj) {});
_webSurface->resume();
_webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
_webSurface->getSurfaceContext()->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
_webSurface->getSurfaceContext()->setContextProperty("Vec3", new Vec3());
_webSurface->getSurfaceContext()->setContextProperty("Quat", new Quat());
_webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get()); _webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
_webSurface->getSurfaceContext()->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data()); _webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
_webSurface->getSurfaceContext()->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data()); _webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
_webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
_webSurface->getSurfaceContext()->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data());
_webSurface->getSurfaceContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
_webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
_webSurface->getSurfaceContext()->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().data());
_webSurface->getSurfaceContext()->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") { _webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto flags = tabletScriptingInterface->getFlags();
_webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags); tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
_webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data()); // mark the TabletProxy object as cpp ownership.
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountScriptingInterface::getInstance()); QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
_webSurface->getSurfaceContext()->setContextProperty("Audio", DependencyManager::get<AudioScriptingInterface>().data()); _webSurface->getSurfaceContext()->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
_webSurface->getSurfaceContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data()); // Override min fps for tablet UI, for silky smooth scrolling
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data()); setMaxFPS(90);
_webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
_webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
_webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
_webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
_webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
_webSurface->getSurfaceContext()->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data());
_webSurface->getSurfaceContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
_webSurface->getSurfaceContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
_webSurface->getSurfaceContext()->setContextProperty("SoundCache", DependencyManager::get<SoundCache>().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);
}
} }
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getPosition()));
} }
void Web3DOverlay::setMaxFPS(uint8_t maxFPS) { void Web3DOverlay::setMaxFPS(uint8_t maxFPS) {
@ -594,11 +578,25 @@ QVariant Web3DOverlay::getProperty(const QString& property) {
} }
void Web3DOverlay::setURL(const QString& url) { void Web3DOverlay::setURL(const QString& url) {
_url = url; if (url != _url) {
if (_webSurface) { bool wasWebContent = isWebContent();
AbstractViewStateInterface::instance()->postLambdaEvent([this, url] { _url = url;
loadSourceURL(); 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();
});
}
}
} }
} }

View file

@ -31,8 +31,6 @@ public:
Web3DOverlay(const Web3DOverlay* Web3DOverlay); Web3DOverlay(const Web3DOverlay* Web3DOverlay);
virtual ~Web3DOverlay(); virtual ~Web3DOverlay();
QString pickURL();
void loadSourceURL();
void setMaxFPS(uint8_t maxFPS); void setMaxFPS(uint8_t maxFPS);
virtual void render(RenderArgs* args) override; virtual void render(RenderArgs* args) override;
virtual const render::ShapeKey getShapeKey() override; virtual const render::ShapeKey getShapeKey() override;
@ -79,6 +77,10 @@ signals:
void releaseWebSurface(); void releaseWebSurface();
private: private:
void setupQmlSurface();
void rebuildWebSurface();
bool isWebContent() const;
InputMode _inputMode { Touch }; InputMode _inputMode { Touch };
QSharedPointer<OffscreenQmlSurface> _webSurface; QSharedPointer<OffscreenQmlSurface> _webSurface;
gpu::TexturePointer _texture; gpu::TexturePointer _texture;

View file

@ -26,6 +26,8 @@
// FIXME move to global app properties // FIXME move to global app properties
const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system"; const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system"; const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
const QString TabletScriptingInterface::QML = "hifi/tablet/TabletRoot.qml";
TabletScriptingInterface::TabletScriptingInterface() { TabletScriptingInterface::TabletScriptingInterface() {
} }

View file

@ -42,6 +42,7 @@ class TabletScriptingInterface : public QObject, public Dependency {
public: public:
TabletScriptingInterface(); TabletScriptingInterface();
~TabletScriptingInterface(); ~TabletScriptingInterface();
static const QString QML;
void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; } void setToolbarScriptingInterface(ToolbarScriptingInterface* toolbarScriptingInterface) { _toolbarScriptingInterface = toolbarScriptingInterface; }

View file

@ -97,7 +97,7 @@
checkTablet() checkTablet()
tabletScalePercentage = getTabletScalePercentageFromSettings(); tabletScalePercentage = getTabletScalePercentageFromSettings();
UIWebTablet = new WebTablet("qml/hifi/tablet/TabletRoot.qml", UIWebTablet = new WebTablet("hifi/tablet/TabletRoot.qml",
DEFAULT_WIDTH * (tabletScalePercentage / 100), DEFAULT_WIDTH * (tabletScalePercentage / 100),
null, activeHand, true, null, false); null, activeHand, true, null, false);
UIWebTablet.register(); UIWebTablet.register();