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;
});
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;
if (htmlContent) {
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()) {
rootItemLoadedFunctor();
} else {
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
}
} else {
// FIXME: the tablet should use the OffscreenQmlSurfaceCache
@ -2345,7 +2345,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
if (webSurface->getRootItem()) {
rootItemLoadedFunctor();
} else {
connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
QObject::connect(webSurface.data(), &hifi::qml::OffscreenSurface::rootContextCreated, rootItemLoadedFunctor);
}
webSurface->load(url);
cachedWebSurface = false;
@ -2354,7 +2354,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
const uint8_t TABLET_FPS = 90;
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();
if (rootItem && rootItem->objectName() == "tabletRoot") {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();

View file

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

View file

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

View file

@ -79,14 +79,8 @@ WebEntityRenderer::WebEntityRenderer(const EntityItemPointer& entity) : Parent(e
_texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda());
_texture->setSource(__FUNCTION__);
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();
}
_contentType = ContentType::HtmlContent;
buildWebSurface(entity, "");
_timer.setInterval(MSECS_PER_SECOND);
connect(&_timer, &QTimer::timeout, this, &WebEntityRenderer::onTimeout);
@ -154,7 +148,7 @@ bool WebEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointe
bool WebEntityRenderer::needsRenderUpdate() const {
if (resultWithReadLock<bool>([this] {
return _prevHasWebSurface != hasWebSurface() || _needsURLUpdate;
return !_webSurface;
})) {
return true;
}
@ -181,30 +175,22 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene
// destroy the existing surface (because surfaces don't support changing the root
// object, so subsequent loads of content just overlap the existing content
bool urlChanged = false;
auto newSourceURL = entity->getSourceUrl();
{
auto newSourceUrl = entity->getSourceUrl();
auto newContentType = getContentType(newSourceUrl);
auto newContentType = getContentType(newSourceURL);
ContentType currentContentType;
withReadLock([&] {
urlChanged = _sourceURL != newSourceUrl;
urlChanged = _sourceURL != newSourceURL;
currentContentType = _contentType;
});
if (urlChanged) {
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;
});
}
}
}
@ -217,67 +203,63 @@ 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 (!_webSurface) {
qDebug() << "boop3" << this << _webSurface << _webSurface->getRootItem();
buildWebSurface(entity);
buildWebSurface(entity, newSourceURL);
}
_prevHasWebSurface = hasWebSurface();
if (!_prevHasWebSurface) {
qDebug() << "boop4" << this << _webSurface << _webSurface->getRootItem();
return;
}
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;
}
{
auto scriptURL = entity->getScriptURL();
if (_scriptURL != scriptURL) {
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
_scriptURL = scriptURL;
}
}
{
auto maxFPS = entity->getMaxFPS();
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);
} else {
_webSurface->setMaxFps(_maxFPS);
if (_webSurface && _webSurface->getRootItem()) {
if (_webSurface->getRootItem()) {
if (_contentType == ContentType::HtmlContent && urlChanged) {
_webSurface->getRootItem()->setProperty(URL_PROPERTY, newSourceURL);
_sourceURL = newSourceURL;
}
{
auto scriptURL = entity->getScriptURL();
if (_scriptURL != scriptURL) {
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
_scriptURL = scriptURL;
}
}
{
auto maxFPS = entity->getMaxFPS();
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);
} else {
_webSurface->setMaxFps(maxFPS);
}
_maxFPS = maxFPS;
}
}
{
auto contextPosition = entity->getWorldPosition();
if (_contextPosition != contextPosition) {
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(contextPosition));
_contextPosition = contextPosition;
}
}
_maxFPS = maxFPS;
}
}
if (_contextPosition != entity->getWorldPosition()) {
_contextPosition = entity->getWorldPosition();
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(_contextPosition));
}
void* key = (void*)this;
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity] () {
withWriteLock([&] {
glm::vec2 windowSize = getWindowSize(entity);
_webSurface->resize(QSize(windowSize.x, windowSize.y));
updateModelTransformAndBound();
_renderTransform = getModelTransform();
_renderTransform.postScale(entity->getScaledDimensions());
void* key = (void*)this;
AbstractViewStateInterface::instance()->pushPostUpdateLambda(key, [this, entity]() {
withWriteLock([&] {
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);
}
bool WebEntityRenderer::hasWebSurface() const {
return (bool)_webSurface && _webSurface->getRootItem();
}
bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
void WebEntityRenderer::buildWebSurface(const EntityItemPointer& entity, const QString& newSourceURL) {
if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) {
qWarning() << "Too many concurrent web views to create new view";
return false;
return;
}
++_currentWebCount;
WebEntityRenderer::acquireWebSurface(_sourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface);
WebEntityRenderer::acquireWebSurface(newSourceURL, _contentType == ContentType::HtmlContent, _webSurface, _cachedWebSurface);
_fadeStartTime = usecTimestampNow();
_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) {
emit DependencyManager::get<EntityScriptingInterface>()->webEventReceived(entityItemID, message);
}));
return _webSurface->getRootItem();
}
void WebEntityRenderer::destroyWebSurface() {

View file

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

View file

@ -3496,6 +3496,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
}
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_DPI, uint16_t, setDPI);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SCRIPT_URL, QString, setScriptURL);