web entity fixes

This commit is contained in:
SamGondelman 2019-01-14 15:40:37 -08:00
parent 6fd34bf1f0
commit 1d2270e9c7
6 changed files with 69 additions and 94 deletions

View file

@ -2317,7 +2317,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP; return DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation() * Vectors::UP;
}); });
render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([](const QString& url, bool htmlContent, QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface) { render::entities::WebEntityRenderer::setAcquireWebSurfaceOperator([this](const QString& url, bool htmlContent, QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface) {
bool isTablet = url == TabletScriptingInterface::QML; bool isTablet = url == TabletScriptingInterface::QML;
if (htmlContent) { if (htmlContent) {
webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(render::entities::WebEntityRenderer::QML); webSurface = DependencyManager::get<OffscreenQmlSurfaceCache>()->acquire(render::entities::WebEntityRenderer::QML);
@ -2328,7 +2328,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
if (webSurface->getRootItem()) { if (webSurface->getRootItem()) {
rootItemLoadedFunctor(); rootItemLoadedFunctor();
} else { } else {
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor); QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
} }
} else { } else {
// FIXME: the tablet should use the OffscreenQmlSurfaceCache // FIXME: the tablet should use the OffscreenQmlSurfaceCache
@ -2345,7 +2345,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
if (webSurface->getRootItem()) { if (webSurface->getRootItem()) {
rootItemLoadedFunctor(); rootItemLoadedFunctor();
} else { } else {
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor); QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
} }
webSurface->load(url); webSurface->load(url);
cachedWebSurface = false; cachedWebSurface = false;
@ -2354,7 +2354,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
const uint8_t TABLET_FPS = 90; const uint8_t TABLET_FPS = 90;
webSurface->setMaxFps(isTablet ? TABLET_FPS : DEFAULT_MAX_FPS); webSurface->setMaxFps(isTablet ? TABLET_FPS : DEFAULT_MAX_FPS);
}); });
render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([](QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface, std::vector<QMetaObject::Connection>& connections) { render::entities::WebEntityRenderer::setReleaseWebSurfaceOperator([this](QSharedPointer<OffscreenQmlSurface>& webSurface, bool& cachedWebSurface, std::vector<QMetaObject::Connection>& connections) {
QQuickItem* rootItem = webSurface->getRootItem(); QQuickItem* rootItem = webSurface->getRootItem();
if (rootItem && rootItem->objectName() == "tabletRoot") { if (rootItem && rootItem->objectName() == "tabletRoot") {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();

View file

@ -82,8 +82,7 @@ Web3DOverlay::Web3DOverlay() {
connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface); connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface);
connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface); connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface);
render::entities::WebEntityRenderer::acquireWebSurface("", true, _webSurface, _cachedWebSurface); buildWebSurface(true);
_webSurface->resume();
} }
Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) : Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) :
@ -114,12 +113,12 @@ void Web3DOverlay::destroyWebSurface() {
} }
} }
void Web3DOverlay::buildWebSurface() { void Web3DOverlay::buildWebSurface(bool overrideWeb) {
if (_webSurface) { if (_webSurface) {
return; return;
} }
render::entities::WebEntityRenderer::acquireWebSurface(_url, isWebContent(), _webSurface, _cachedWebSurface); render::entities::WebEntityRenderer::acquireWebSurface(_url, overrideWeb || isWebContent(), _webSurface, _cachedWebSurface);
onResizeWebSurface(); onResizeWebSurface();
_webSurface->resume(); _webSurface->resume();
@ -172,7 +171,7 @@ void Web3DOverlay::render(RenderArgs* args) {
} }
if (!_webSurface) { if (!_webSurface) {
emit requestWebSurface(); emit requestWebSurface(false);
return; return;
} }

View file

@ -57,7 +57,7 @@ public:
Mouse Mouse
}; };
void buildWebSurface(); void buildWebSurface(bool overrideWeb = false);
void destroyWebSurface(); void destroyWebSurface();
void onResizeWebSurface(); void onResizeWebSurface();
@ -68,7 +68,7 @@ signals:
void scriptEventReceived(const QVariant& message); void scriptEventReceived(const QVariant& message);
void webEventReceived(const QVariant& message); void webEventReceived(const QVariant& message);
void resizeWebSurface(); void resizeWebSurface();
void requestWebSurface(); void requestWebSurface(bool overrideWeb);
protected: protected:
Transform evalRenderTransform() override; Transform evalRenderTransform() override;

View file

@ -79,14 +79,8 @@ WebEntityRenderer::WebEntityRenderer(const EntityItemPointer& entity) : Parent(e
_texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda()); _texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda());
_texture->setSource(__FUNCTION__); _texture->setSource(__FUNCTION__);
if (_currentWebCount < MAX_CONCURRENT_WEB_VIEWS) { _contentType = ContentType::HtmlContent;
_currentWebCount++; buildWebSurface(entity, "");
WebEntityRenderer::acquireWebSurface("", true, _webSurface, _cachedWebSurface);
_contentType = ContentType::HtmlContent;
_fadeStartTime = usecTimestampNow();
_webSurface->resume();
qDebug() << "boop" << this << _webSurface << _webSurface->getRootItem();
}
_timer.setInterval(MSECS_PER_SECOND); _timer.setInterval(MSECS_PER_SECOND);
connect(&_timer, &QTimer::timeout, this, &WebEntityRenderer::onTimeout); connect(&_timer, &QTimer::timeout, this, &WebEntityRenderer::onTimeout);
@ -154,7 +148,7 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe
bool WebEntityRenderer::needsRenderUpdate() const { bool WebEntityRenderer::needsRenderUpdate() const {
if (resultWithReadLock<bool>([this] { if (resultWithReadLock<bool>([this] {
return _prevHasWebSurface != hasWebSurface() || _needsURLUpdate; return !_webSurface;
})) { })) {
return true; return true;
} }
@ -181,30 +175,22 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
// destroy the existing surface (because surfaces don't support changing the root // destroy the existing surface (because surfaces don't support changing the root
// object, so subsequent loads of content just overlap the existing content // object, so subsequent loads of content just overlap the existing content
bool urlChanged = false; bool urlChanged = false;
auto newSourceURL = entity->getSourceUrl();
{ {
auto newSourceUrl = entity->getSourceUrl(); auto newContentType = getContentType(newSourceURL);
auto newContentType = getContentType(newSourceUrl);
ContentType currentContentType; ContentType currentContentType;
withReadLock([&] { withReadLock([&] {
urlChanged = _sourceURL != newSourceUrl; urlChanged = _sourceURL != newSourceURL;
currentContentType = _contentType; currentContentType = _contentType;
}); });
if (urlChanged) { if (urlChanged) {
withWriteLock([&] { withWriteLock([&] {
_needsURLUpdate = true;
_sourceURL = newSourceUrl;
_contentType = newContentType; _contentType = newContentType;
}); });
if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) { if (newContentType != ContentType::HtmlContent || currentContentType != ContentType::HtmlContent) {
qDebug() << "boop2" << this << _webSurface << _webSurface->getRootItem();
destroyWebSurface(); destroyWebSurface();
// If we destroyed the surface, the URL change will be implicitly handled by the re-creation
urlChanged = false;
withWriteLock([&] {
_needsURLUpdate = false;
});
} }
} }
} }
@ -217,67 +203,63 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
_alpha = entity->getAlpha(); _alpha = entity->getAlpha();
if (_contentType == ContentType::NoContent) { if (_contentType == ContentType::NoContent) {
_prevHasWebSurface = false;
return; return;
} }
// This work must be done on the main thread // This work must be done on the main thread
// If we couldn't create a new web surface, exit
if (!_webSurface) { if (!_webSurface) {
qDebug() << "boop3" << this << _webSurface << _webSurface->getRootItem(); buildWebSurface(entity, newSourceURL);
buildWebSurface(entity);
} }
_prevHasWebSurface = hasWebSurface(); if (_webSurface && _webSurface->getRootItem()) {
if (!_prevHasWebSurface) { if (_webSurface->getRootItem()) {
qDebug() << "boop4" << this << _webSurface << _webSurface->getRootItem(); if (_contentType == ContentType::HtmlContent && urlChanged) {
return; _webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL);
} _sourceURL = newSourceURL;
}
qDebug() << "boop6" << this << _webSurface << _webSurface->getRootItem();
if (_needsURLUpdate && _contentType == ContentType::HtmlContent) { {
qDebug() << "boop7" << this << _webSurface << _webSurface->getRootItem(); auto scriptURL = entity->getScriptURL();
_webSurface->getRootItem()->setProperty(URL_PROPERTY, _sourceURL); if (_scriptURL != scriptURL) {
_needsURLUpdate = false; _webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
} _scriptURL = scriptURL;
}
{ }
auto scriptURL = entity->getScriptURL();
if (_scriptURL != scriptURL) { {
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL); auto maxFPS = entity->getMaxFPS();
_scriptURL = scriptURL; if (_maxFPS != maxFPS) {
} // We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
} // FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the web entity
if (QUrl(_sourceURL).host().endsWith("youtube.com", Qt::CaseInsensitive)) {
{ _webSurface->setMaxFps(YOUTUBE_MAX_FPS);
auto maxFPS = entity->getMaxFPS(); } else {
if (_maxFPS != maxFPS) { _webSurface->setMaxFps(maxFPS);
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS. }
// FIXME this doesn't handle redirects or shortened URLs, consider using a signaling method from the web entity _maxFPS = maxFPS;
if (QUrl(_sourceURL).host().endsWith("youtube.com", Qt::CaseInsensitive)) { }
_webSurface->setMaxFps(YOUTUBE_MAX_FPS); }
} else {
_webSurface->setMaxFps(_maxFPS); {
auto contextPosition = entity->getWorldPosition();
if (_contextPosition != contextPosition) {
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(contextPosition));
_contextPosition = contextPosition;
}
} }
_maxFPS = maxFPS;
} }
}
if (_contextPosition != entity->getWorldPosition()) { void* key = (void*)this;
_contextPosition = entity->getWorldPosition(); AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() {
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition)); withWriteLock([&] {
} glm::vec2 windowSize = getWindowSize(entity);
_webSurface->resize(QSize(windowSize.x, windowSize.y));
void* key = (void*)this; updateModelTransformAndBound();
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () { _renderTransform = getModelTransform();
withWriteLock([&] { _renderTransform.postScale(entity->getScaledDimensions());
glm::vec2 windowSize = getWindowSize(entity); });
_webSurface->resize(QSize(windowSize.x, windowSize.y));
updateModelTransformAndBound();
_renderTransform = getModelTransform();
_renderTransform.postScale(entity->getScaledDimensions());
}); });
}); }
}); });
} }
@ -323,18 +305,14 @@ void WebEntityRenderer::doRender(RenderArgs* args) {
batch.setResourceTexture(0, nullptr); batch.setResourceTexture(0, nullptr);
} }
bool WebEntityRenderer::hasWebSurface() const { void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL) {
return (bool)_webSurface && _webSurface->getRootItem();
}
bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) {
qWarning() << "Too many concurrent web views to create new view"; qWarning() << "Too many concurrent web views to create new view";
return false; return;
} }
++_currentWebCount; ++_currentWebCount;
WebEntityRenderer::acquireWebSurface(_sourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface); WebEntityRenderer::acquireWebSurface(newSourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface);
_fadeStartTime = usecTimestampNow(); _fadeStartTime = usecTimestampNow();
_webSurface->resume(); _webSurface->resume();
@ -344,8 +322,6 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
_connections.push_back(QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, [entityItemID](const QVariant& message) { _connections.push_back(QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, [entityItemID](const QVariant& message) {
emit DependencyManager::get<EntityScriptingInterface>()->webEventReceived(entityItemID, message); emit DependencyManager::get<EntityScriptingInterface>()->webEventReceived(entityItemID, message);
})); }));
return _webSurface->getRootItem();
} }
void WebEntityRenderer::destroyWebSurface() { void WebEntityRenderer::destroyWebSurface() {

View file

@ -65,9 +65,8 @@ protected:
private: private:
void onTimeout(); void onTimeout();
bool buildWebSurface(const TypedEntityPointer& entity); void buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL);
void destroyWebSurface(); void destroyWebSurface();
bool hasWebSurface() const;
glm::vec2 getWindowSize(const TypedEntityPointer& entity) const; glm::vec2 getWindowSize(const TypedEntityPointer& entity) const;
int _geometryId{ 0 }; int _geometryId{ 0 };
@ -80,8 +79,6 @@ private:
ContentType _contentType { ContentType::NoContent }; ContentType _contentType { ContentType::NoContent };
QSharedPointer<OffscreenQmlSurface> _webSurface { nullptr }; QSharedPointer<OffscreenQmlSurface> _webSurface { nullptr };
bool _prevHasWebSurface { false };
bool _needsURLUpdate { false };
bool _cachedWebSurface { false }; bool _cachedWebSurface { false };
gpu::TexturePointer _texture; gpu::TexturePointer _texture;

View file

@ -3496,6 +3496,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
} }
if (properties.getType() == EntityTypes::Web) { if (properties.getType() == EntityTypes::Web) {
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA, float, setAlpha);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_URL, QString, setScriptURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_URL, QString, setScriptURL);