Eagerly cache QML surfaces for Web3D overlays to prevent stutter on loading the tablet

This commit is contained in:
Brad Davis 2017-01-11 13:54:25 -08:00
parent db5e4db79f
commit f235a52a6d
5 changed files with 106 additions and 15 deletions

View file

@ -89,6 +89,7 @@
#include <OctalCode.h>
#include <OctreeSceneStats.h>
#include <OffscreenUi.h>
#include <gl/OffscreenQmlSurfaceCache.h>
#include <gl/OffscreenGLCanvas.h>
#include <PathUtils.h>
#include <PerfStat.h>
@ -512,6 +513,7 @@ bool setupEssentials(int& argc, char** argv) {
DependencyManager::set<InterfaceParentFinder>();
DependencyManager::set<EntityTreeRenderer>(true, qApp, qApp);
DependencyManager::set<CompositorHelper>();
DependencyManager::set<OffscreenQmlSurfaceCache>();
return previousSessionCrashed;
}
@ -2003,6 +2005,10 @@ void Application::initializeUi() {
showCursor(compositorHelper->getAllowMouseCapture() ? Qt::BlankCursor : Qt::ArrowCursor);
}
});
// Pre-create a couple of Web3D overlays to speed up tablet UI
auto offscreenSurfaceCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
offscreenSurfaceCache->reserve(Web3DOverlay::QML, 2);
}
void Application::paintGL() {

View file

@ -28,14 +28,15 @@
#include <AbstractViewStateInterface.h>
#include <gl/OffscreenQmlSurface.h>
#include <gl/OffscreenQmlSurfaceCache.h>
static const float DPI = 30.47f;
static const float INCHES_TO_METERS = 1.0f / 39.3701f;
static const float METERS_TO_INCHES = 39.3701f;
static const float OPAQUE_ALPHA_THRESHOLD = 0.99f;
QString const Web3DOverlay::TYPE = "web3d";
const QString Web3DOverlay::TYPE = "web3d";
const QString Web3DOverlay::QML = "Web3DOverlay.qml";
Web3DOverlay::Web3DOverlay() : _dpi(DPI) {
_touchDevice.setCapabilities(QTouchDevice::Position);
_touchDevice.setType(QTouchDevice::TouchScreen);
@ -80,8 +81,9 @@ Web3DOverlay::~Web3DOverlay() {
// is no longer valid
auto webSurface = _webSurface;
AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] {
webSurface->deleteLater();
DependencyManager::get<OffscreenQmlSurfaceCache>()->release(QML, webSurface);
});
_webSurface.reset();
}
auto geometryCache = DependencyManager::get<GeometryCache>();
if (geometryCache) {
@ -109,23 +111,14 @@ void Web3DOverlay::render(RenderArgs* args) {
QOpenGLContext * currentContext = QOpenGLContext::currentContext();
QSurface * currentSurface = currentContext->surface();
if (!_webSurface) {
auto deleter = [](OffscreenQmlSurface* webSurface) {
AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] {
webSurface->deleteLater();
});
};
_webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), deleter);
_webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(QML);
_webSurface->setMaxFps(10);
// FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces
// and the current rendering load)
_webSurface->setMaxFps(10);
_webSurface->create(currentContext);
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
_webSurface->load("Web3DOverlay.qml");
_webSurface->resume();
_webSurface->resize(QSize(_resolution.x, _resolution.y));
_webSurface->getRootItem()->setProperty("url", _url);
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
_webSurface->getRootContext()->setContextProperty("ApplicationInterface", qApp);
_webSurface->resize(QSize(_resolution.x, _resolution.y));
currentContext->makeCurrent(currentSurface);
auto forwardPointerEvent = [=](unsigned int overlayID, const PointerEvent& event) {

View file

@ -21,6 +21,7 @@ class Web3DOverlay : public Billboard3DOverlay {
Q_OBJECT
public:
static const QString QML;
static QString const TYPE;
virtual QString getType() const override { return TYPE; }

View file

@ -0,0 +1,57 @@
//
// Created by Bradley Austin Davis on 2017-01-11
// Copyright 2013-2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "OffscreenQmlSurfaceCache.h"
#include <QtGui/QOpenGLContext>
#include <QtQml/QQmlContext>
#include <PathUtils.h>
#include "OffscreenQmlSurface.h"
OffscreenQmlSurfaceCache::OffscreenQmlSurfaceCache() {
}
OffscreenQmlSurfaceCache::~OffscreenQmlSurfaceCache() {
_cache.clear();
}
QSharedPointer<OffscreenQmlSurface> OffscreenQmlSurfaceCache::acquire(const QString& rootSource) {
auto& list = _cache[rootSource];
if (list.empty()) {
list.push_back(buildSurface(rootSource));
}
auto result = list.front();
list.pop_front();
return result;
}
void OffscreenQmlSurfaceCache::reserve(const QString& rootSource, int count) {
auto& list = _cache[rootSource];
while (list.size() < count) {
list.push_back(buildSurface(rootSource));
}
}
void OffscreenQmlSurfaceCache::release(const QString& rootSource, const QSharedPointer<OffscreenQmlSurface>& surface) {
surface->pause();
_cache[rootSource].push_back(surface);
}
QSharedPointer<OffscreenQmlSurface> OffscreenQmlSurfaceCache::buildSurface(const QString& rootSource) {
auto surface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface());
QOpenGLContext* currentContext = QOpenGLContext::currentContext();
QSurface* currentSurface = currentContext->surface();
surface->create(currentContext);
surface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
surface->load(rootSource);
surface->getRootContext()->setContextProperty("ApplicationInterface", qApp);
surface->resize(QSize(100, 100));
currentContext->makeCurrent(currentSurface);
return surface;
}

View file

@ -0,0 +1,34 @@
//
// Created by Bradley Austin Davis on 2017-01-11
// Copyright 2013-2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_OffscreenQmlSurfaceCache_h
#define hifi_OffscreenQmlSurfaceCahce_h
#include "DependencyManager.h"
#include <QtCore/QSharedPointer>
class OffscreenQmlSurface;
class OffscreenQmlSurfaceCache : public Dependency {
SINGLETON_DEPENDENCY
public:
OffscreenQmlSurfaceCache();
virtual ~OffscreenQmlSurfaceCache();
QSharedPointer<OffscreenQmlSurface> acquire(const QString& rootSource);
void release(const QString& rootSource, const QSharedPointer<OffscreenQmlSurface>& surface);
void reserve(const QString& rootSource, int count = 1);
private:
QSharedPointer<OffscreenQmlSurface> buildSurface(const QString& rootSource);
QHash<QString, QList<QSharedPointer<OffscreenQmlSurface>>> _cache;
};
#endif