setup qml surface contexts

This commit is contained in:
SamGondelman 2019-01-11 14:21:03 -08:00
parent 4b67a79561
commit 6fd34bf1f0
9 changed files with 142 additions and 141 deletions

View file

@ -2317,35 +2317,21 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
});
render::entities::WebEntityRenderer::setInitializeWebSurfaceOperator([](QSharedPointer<OffscreenQmlSurface> webSurface) {
webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(render::entities::WebEntityRenderer::QML);
webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
webSurface->getSurfaceContext()->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
});
render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([](const QString& url, bool htmlContent, QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface) {
bool isTablet = url == TabletScriptingInterface::QML;
if (htmlContent) {
// FIXME use the surface cache instead of explicit creation
webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), [](OffscreenQmlSurface* webSurface) {
AbstractViewStateInterface::instance()->sendLambdaEvent([webSurface] {
// WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown
// if the application has already stopped its event loop, delete must be explicit
delete webSurface;
});
});
webSurface->load(render::entities::WebEntityRenderer::QML, [url](QQmlContext* context, QObject* item) {
item->setProperty("url", url);
});
#if 0
// This doesn't work for some reason
webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(render::entities::WebEntityRenderer::QML);
cachedWebSurface = true;
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, [url, webSurface](QQmlContext* surfaceContext) {
webSurface->getRootItem()->setProperty("url", url);
});
#endif
auto rootItemLoadedFunctor = [url, webSurface] {
webSurface->getRootItem()->setProperty(render::entities::WebEntityRenderer::URL_PROPERTY, url);
};
if (webSurface->getRootItem()) {
rootItemLoadedFunctor();
} else {
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
}
} else {
// FIXME: the tablet should use the OffscreenQmlSurfaceCache
webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), [](OffscreenQmlSurface* webSurface) {
AbstractViewStateInterface::instance()->sendLambdaEvent([webSurface] {
// WebEngineView may run other threads (wasapi), so they must be deleted for a clean shutdown
@ -2353,9 +2339,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
delete webSurface;
});
});
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, [url](QQmlContext* surfaceContext) {
//setupQmlSurface(isTablet, url == OVERLAY_LOGIN_DIALOG.toString());
});
auto rootItemLoadedFunctor = [webSurface, url, isTablet] {
Application::setupQmlSurface(webSurface->getSurfaceContext(), isTablet || url == OVERLAY_LOGIN_DIALOG.toString());
};
if (webSurface->getRootItem()) {
rootItemLoadedFunctor();
} else {
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
}
webSurface->load(url);
cachedWebSurface = false;
}
@ -2394,7 +2385,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
rootItem->setProperty("url", "about:blank");
}
auto offscreenCache = DependencyManager::get<OffscreenQmlSurfaceCache>();
// FIXME prevents crash on shutdown, but we shoudln't have to do this check
if (offscreenCache) {
offscreenCache->release(render::entities::WebEntityRenderer::QML, webSurface);
}
@ -3239,6 +3229,61 @@ void Application::onDesktopRootItemCreated(QQuickItem* rootItem) {
#endif
}
void Application::setupQmlSurface(QQmlContext* surfaceContext, bool setAdditionalContextProperties) {
surfaceContext->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
surfaceContext->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
surfaceContext->setContextProperty("UserActivityLogger", DependencyManager::get<UserActivityLoggerScriptingInterface>().data());
surfaceContext->setContextProperty("Preferences", DependencyManager::get<Preferences>().data());
surfaceContext->setContextProperty("Vec3", new Vec3());
surfaceContext->setContextProperty("Quat", new Quat());
surfaceContext->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
surfaceContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
surfaceContext->setContextProperty("Snapshot", DependencyManager::get<Snapshot>().data());
if (setAdditionalContextProperties) {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto flags = tabletScriptingInterface->getFlags();
surfaceContext->setContextProperty("offscreenFlags", flags);
surfaceContext->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
surfaceContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
surfaceContext->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
surfaceContext->setContextProperty("KeyboardScriptingInterface", DependencyManager::get<KeyboardScriptingInterface>().data());
surfaceContext->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
surfaceContext->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
surfaceContext->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
// in Qt 5.10.0 there is already an "Audio" object in the QML context
// though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface"
surfaceContext->setContextProperty("AudioScriptingInterface", DependencyManager::get<AudioScriptingInterface>().data());
surfaceContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
surfaceContext->setContextProperty("fileDialogHelper", new FileDialogHelper());
surfaceContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
surfaceContext->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
surfaceContext->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
surfaceContext->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
surfaceContext->setContextProperty("DCModel", DependencyManager::get<DomainConnectionModel>().data());
surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
surfaceContext->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
surfaceContext->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
surfaceContext->setContextProperty("SoundCache", DependencyManager::get<SoundCacheScriptingInterface>().data());
surfaceContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
surfaceContext->setContextProperty("Render", AbstractViewStateInterface::instance()->getRenderEngine()->getConfiguration().get());
surfaceContext->setContextProperty("Workload", qApp->getGameWorkload()._engine->getConfiguration().get());
surfaceContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
surfaceContext->setContextProperty("Pointers", DependencyManager::get<PointerScriptingInterface>().data());
surfaceContext->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
surfaceContext->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface());
surfaceContext->setContextProperty("HiFiAbout", AboutUtil::getInstance());
surfaceContext->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
surfaceContext->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
}
}
void Application::updateCamera(RenderArgs& renderArgs, float deltaTime) {
PROFILE_RANGE(render, __FUNCTION__);
PerformanceTimer perfTimer("updateCamera");

View file

@ -589,6 +589,8 @@ private:
void maybeToggleMenuVisible(QMouseEvent* event) const;
void toggleTabletUI(bool shouldOpen = false) const;
static void setupQmlSurface(QQmlContext* surfaceContext, bool setAdditionalContextProperties);
MainWindow* _window;
QElapsedTimer& _sessionRunTimer;

View file

@ -82,9 +82,8 @@ Web3DOverlay::Web3DOverlay() {
connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface);
connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface);
//need to be intialized before Tablet 1st open
_cachedWebSurface = true;
render::entities::WebEntityRenderer::initializeWebSurface(_webSurface);
render::entities::WebEntityRenderer::acquireWebSurface("", true, _webSurface, _cachedWebSurface);
_webSurface->resume();
}
Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) :
@ -145,64 +144,6 @@ bool Web3DOverlay::isWebContent() const {
return false;
}
void Web3DOverlay::setupQmlSurface(bool isTablet, bool isLoginDialog) {
_webSurface->getSurfaceContext()->setContextProperty("Users", DependencyManager::get<UsersScriptingInterface>().data());
_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());
if (isTablet || isLoginDialog) {
_webSurface->getSurfaceContext()->setContextProperty("Account", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
_webSurface->getSurfaceContext()->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("MenuInterface", MenuScriptingInterface::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("KeyboardScriptingInterface", DependencyManager::get<KeyboardScriptingInterface>().data());
}
if (isTablet) {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto flags = tabletScriptingInterface->getFlags();
_webSurface->getSurfaceContext()->setContextProperty("offscreenFlags", flags);
_webSurface->getSurfaceContext()->setContextProperty("AddressManager", DependencyManager::get<AddressManager>().data());
_webSurface->getSurfaceContext()->setContextProperty("GlobalServices", AccountServicesScriptingInterface::getInstance()); // DEPRECATED - TO BE REMOVED
_webSurface->getSurfaceContext()->setContextProperty("AccountServices", AccountServicesScriptingInterface::getInstance());
// in Qt 5.10.0 there is already an "Audio" object in the QML context
// though I failed to find it (from QtMultimedia??). So.. let it be "AudioScriptingInterface"
_webSurface->getSurfaceContext()->setContextProperty("AudioScriptingInterface", DependencyManager::get<AudioScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
_webSurface->getSurfaceContext()->setContextProperty("HMD", DependencyManager::get<HMDScriptingInterface>().data());
_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("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("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<SoundCacheScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
_webSurface->getSurfaceContext()->setContextProperty("Render", AbstractViewStateInterface::instance()->getRenderEngine()->getConfiguration().get());
_webSurface->getSurfaceContext()->setContextProperty("Workload", qApp->getGameWorkload()._engine->getConfiguration().get());
_webSurface->getSurfaceContext()->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Pointers", DependencyManager::get<PointerScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Window", DependencyManager::get<WindowScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("Reticle", qApp->getApplicationCompositor().getReticleInterface());
_webSurface->getSurfaceContext()->setContextProperty("HiFiAbout", AboutUtil::getInstance());
_webSurface->getSurfaceContext()->setContextProperty("WalletScriptingInterface", DependencyManager::get<WalletScriptingInterface>().data());
_webSurface->getSurfaceContext()->setContextProperty("ResourceRequestObserver", DependencyManager::get<ResourceRequestObserver>().data());
}
}
void Web3DOverlay::setMaxFPS(uint8_t maxFPS) {
// FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces and the current rendering load)
_desiredMaxFPS = maxFPS;
@ -514,14 +455,14 @@ void Web3DOverlay::setURL(const QString& url) {
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);
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
_webSurface->getRootItem()->setProperty(render::entities::WebEntityRenderer::URL_PROPERTY, _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] {
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
rebuildWebSurface();
});
}

View file

@ -74,13 +74,12 @@ protected:
Transform evalRenderTransform() override;
private:
void setupQmlSurface(bool isTablet, bool isLoginDialog);
void rebuildWebSurface();
bool isWebContent() const;
InputMode _inputMode { Touch };
QSharedPointer<OffscreenQmlSurface> _webSurface;
bool _cachedWebSurface{ false };
bool _cachedWebSurface { false };
gpu::TexturePointer _texture;
QString _url;
QString _scriptURL;

View file

@ -31,8 +31,8 @@ using namespace render;
using namespace render::entities;
const QString WebEntityRenderer::QML = "Web3DSurface.qml";
const char* WebEntityRenderer::URL_PROPERTY = "url";
std::function<void(QSharedPointer<OffscreenQmlSurface>)> WebEntityRenderer::_initializeWebSurfaceOperator = nullptr;
std::function<void(QString, bool, QSharedPointer<OffscreenQmlSurface>&, bool&)> WebEntityRenderer::_acquireWebSurfaceOperator = nullptr;
std::function<void(QSharedPointer<OffscreenQmlSurface>&, bool&, std::vector<QMetaObject::Connection>&)> WebEntityRenderer::_releaseWebSurfaceOperator = nullptr;
@ -50,7 +50,6 @@ static uint32_t _currentWebCount { 0 };
static const uint32_t MAX_CONCURRENT_WEB_VIEWS = 20;
static QTouchDevice _touchDevice;
static const char* URL_PROPERTY = "url";
WebEntityRenderer::ContentType WebEntityRenderer::getContentType(const QString& urlString) {
if (urlString.isEmpty()) {
@ -80,9 +79,14 @@ WebEntityRenderer::WebEntityRenderer(const EntityItemPointer& entity) : Parent(e
_texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda());
_texture->setSource(__FUNCTION__);
// need to be intialized early
_cachedWebSurface = true;
WebEntityRenderer::initializeWebSurface(_webSurface);
if (_currentWebCount < MAX_CONCURRENT_WEB_VIEWS) {
_currentWebCount++;
WebEntityRenderer::acquireWebSurface("", true, _webSurface, _cachedWebSurface);
_contentType = ContentType::HtmlContent;
_fadeStartTime = usecTimestampNow();
_webSurface->resume();
qDebug() << "boop" << this << _webSurface << _webSurface->getRootItem();
}
_timer.setInterval(MSECS_PER_SECOND);
connect(&_timer, &QTimer::timeout, this, &WebEntityRenderer::onTimeout);
@ -149,9 +153,8 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe
}
bool WebEntityRenderer::needsRenderUpdate() const {
if (resultWithReadLock<bool>([&] {
// If we have rendered recently, and there is no web surface, we're going to create one
return !_webSurface;
if (resultWithReadLock<bool>([this] {
return _prevHasWebSurface != hasWebSurface() || _needsURLUpdate;
})) {
return true;
}
@ -188,16 +191,21 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
});
if (urlChanged) {
if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) {
destroyWebSurface();
// If we destroyed the surface, the URL change will be implicitly handled by the re-creation
urlChanged = false;
}
withWriteLock([&] {
_needsURLUpdate = true;
_sourceURL = newSourceUrl;
_contentType = newContentType;
});
if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) {
qDebug() << "boop2" << this << _webSurface << _webSurface->getRootItem();
destroyWebSurface();
// If we destroyed the surface, the URL change will be implicitly handled by the re-creation
urlChanged = false;
withWriteLock([&] {
_needsURLUpdate = false;
});
}
}
}
@ -209,17 +217,28 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
_alpha = entity->getAlpha();
if (_contentType == ContentType::NoContent) {
_prevHasWebSurface = false;
return;
}
// This work must be done on the main thread
// If we couldn't create a new web surface, exit
if (!hasWebSurface() && !buildWebSurface(entity)) {
if (!_webSurface) {
qDebug() << "boop3" << this << _webSurface << _webSurface->getRootItem();
buildWebSurface(entity);
}
_prevHasWebSurface = hasWebSurface();
if (!_prevHasWebSurface) {
qDebug() << "boop4" << this << _webSurface << _webSurface->getRootItem();
return;
}
if (urlChanged && _contentType == ContentType::HtmlContent) {
qDebug() << "boop6" << this << _webSurface << _webSurface->getRootItem();
if (_needsURLUpdate && _contentType == ContentType::HtmlContent) {
qDebug() << "boop7" << this << _webSurface << _webSurface->getRootItem();
_webSurface->getRootItem()->setProperty(URL_PROPERTY, _sourceURL);
_needsURLUpdate = false;
}
{
@ -252,7 +271,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
void* key = (void*)this;
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
withWriteLock([&] {
glm::vec2 windowSize = getWindowSize(entity);
_webSurface->resize(QSize(windowSize.x, windowSize.y));
updateModelTransformAndBound();
@ -305,16 +323,11 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
batch.setResourceTexture(0, nullptr);
}
bool WebEntityRenderer::hasWebSurface() {
bool WebEntityRenderer::hasWebSurface() const {
return (bool)_webSurface && _webSurface->getRootItem();
}
bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
if (_webSurface && !_webSurface->getRootItem()) {
// We're waiting on the root item
return false;
}
if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) {
qWarning() << "Too many concurrent web views to create new view";
return false;
@ -366,6 +379,7 @@ void WebEntityRenderer::hoverEnterEntity(const PointerEvent& event) {
if (_inputMode == WebInputMode::MOUSE) {
handlePointerEvent(event);
} else if (_webSurface) {
qDebug() << "boop5" << this << _webSurface << _webSurface->getRootItem();
PointerEvent webEvent = event;
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
_webSurface->hoverBeginEvent(webEvent, _touchDevice);

View file

@ -31,12 +31,7 @@ public:
Q_INVOKABLE void handlePointerEvent(const PointerEvent& event);
static const QString QML;
static void setInitializeWebSurfaceOperator(std::function<void(QSharedPointer<OffscreenQmlSurface>)> initializeWebSurfaceOperator) { _initializeWebSurfaceOperator = initializeWebSurfaceOperator; }
static void initializeWebSurface(QSharedPointer<OffscreenQmlSurface> webSurface) {
if (_initializeWebSurfaceOperator) {
_initializeWebSurfaceOperator(webSurface);
}
}
static const char* URL_PROPERTY;
static void setAcquireWebSurfaceOperator(std::function<void(const QString&, bool, QSharedPointer<OffscreenQmlSurface>&, bool&)> acquireWebSurfaceOperator) { _acquireWebSurfaceOperator = acquireWebSurfaceOperator; }
static void acquireWebSurface(const QString& url, bool htmlContent, QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface) {
@ -72,7 +67,7 @@ private:
void onTimeout();
bool buildWebSurface(const TypedEntityPointer& entity);
void destroyWebSurface();
bool hasWebSurface();
bool hasWebSurface() const;
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
int _geometryId{ 0 };
@ -84,7 +79,9 @@ private:
static ContentType getContentType(const QString& urlString);
ContentType _contentType { ContentType::NoContent };
QSharedPointer<OffscreenQmlSurface> _webSurface;
QSharedPointer<OffscreenQmlSurface> _webSurface { nullptr };
bool _prevHasWebSurface { false };
bool _needsURLUpdate { false };
bool _cachedWebSurface { false };
gpu::TexturePointer _texture;
@ -104,7 +101,6 @@ private:
std::vector<QMetaObject::Connection> _connections;
static std::function<void(QSharedPointer<OffscreenQmlSurface>)> _initializeWebSurfaceOperator;
static std::function<void(QString, bool, QSharedPointer<OffscreenQmlSurface>&, bool&)> _acquireWebSurfaceOperator;
static std::function<void(QSharedPointer<OffscreenQmlSurface>&, bool&, std::vector<QMetaObject::Connection>&)> _releaseWebSurfaceOperator;

View file

@ -66,6 +66,7 @@ void RenderEventHandler::onInitalize() {
qFatal("Unable to make QML rendering context current on render thread");
}
_shared->initializeRenderControl(_canvas.getContext());
_initialized = true;
}
void RenderEventHandler::resize() {
@ -150,22 +151,24 @@ void RenderEventHandler::onRender() {
}
void RenderEventHandler::onQuit() {
if (_canvas.getContext() != QOpenGLContextWrapper::currentContext()) {
qFatal("QML rendering context not current on render thread");
}
if (_initialized) {
if (_canvas.getContext() != QOpenGLContextWrapper::currentContext()) {
qFatal("QML rendering context not current on render thread");
}
if (_depthStencil) {
glDeleteRenderbuffers(1, &_depthStencil);
_depthStencil = 0;
}
if (_depthStencil) {
glDeleteRenderbuffers(1, &_depthStencil);
_depthStencil = 0;
}
if (_fbo) {
glDeleteFramebuffers(1, &_fbo);
_fbo = 0;
}
if (_fbo) {
glDeleteFramebuffers(1, &_fbo);
_fbo = 0;
}
_shared->shutdownRendering(_canvas, _currentSize);
_canvas.doneCurrent();
_shared->shutdownRendering(_canvas, _currentSize);
_canvas.doneCurrent();
}
_canvas.moveToThreadWithContext(qApp->thread());
moveToThread(qApp->thread());
QThread::currentThread()->quit();

View file

@ -53,6 +53,8 @@ private:
uint32_t _fbo{ 0 };
uint32_t _depthStencil{ 0 };
bool _initialized { false };
};
}}} // namespace hifi::qml::impl

View file

@ -9,9 +9,8 @@
#include "WebInputMode.h"
const char* webInputModeNames[] = {
"none",
"yaw",
"full"
"touch",
"mouse"
};
static const size_t WEB_INPUT_MODE_NAMES = (sizeof(webInputModeNames) / sizeof(webInputModeNames[0]));