Fix crash on destroying web entities and overlays

This commit is contained in:
Brad Davis 2016-10-03 16:42:50 -07:00
parent ca3572f991
commit 8c5028158f
5 changed files with 35 additions and 21 deletions

View file

@ -73,7 +73,12 @@ void Web3DOverlay::render(RenderArgs* args) {
QOpenGLContext * currentContext = QOpenGLContext::currentContext();
QSurface * currentSurface = currentContext->surface();
if (!_webSurface) {
_webSurface = new OffscreenQmlSurface();
auto deleter = [](OffscreenQmlSurface* webSurface) {
AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] {
webSurface->deleteLater();
});
};
_webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), deleter);
_webSurface->create(currentContext);
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/controls/"));
_webSurface->load("WebView.qml");
@ -95,8 +100,9 @@ void Web3DOverlay::render(RenderArgs* args) {
}
if (!_texture) {
_texture = gpu::TexturePointer(gpu::Texture::createExternal2D([this](uint32_t recycleTexture, void* recycleFence) {
_webSurface->releaseTexture({ recycleTexture, recycleFence });
auto webSurface = _webSurface;
_texture = gpu::TexturePointer(gpu::Texture::createExternal2D([webSurface](uint32_t recycleTexture, void* recycleFence) {
webSurface->releaseTexture({ recycleTexture, recycleFence });
}));
_texture->setSource(__FUNCTION__);
}

View file

@ -41,7 +41,7 @@ public:
virtual Web3DOverlay* createClone() const override;
private:
OffscreenQmlSurface* _webSurface{ nullptr };
QSharedPointer<OffscreenQmlSurface> _webSurface;
QMetaObject::Connection _connection;
gpu::TexturePointer _texture;
QString _url;

View file

@ -129,7 +129,19 @@ bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) {
// Save the original GL context, because creating a QML surface will create a new context
QOpenGLContext * currentContext = QOpenGLContext::currentContext();
QSurface * currentSurface = currentContext->surface();
_webSurface = new OffscreenQmlSurface();
auto deleter = [](OffscreenQmlSurface* webSurface) {
AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] {
webSurface->deleteLater();
});
};
_webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), deleter);
// The lifetime of the QML surface MUST be managed by the main thread
// Additionally, we MUST use local variables copied by value, rather than
// member variables, since they would implicitly refer to a this that
// is no longer valid
_webSurface->create(currentContext);
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/controls/"));
_webSurface->load("WebView.qml", [&](QQmlContext* context, QObject* obj) {
@ -215,9 +227,11 @@ void RenderableWebEntityItem::render(RenderArgs* args) {
_webSurface->resize(QSize(windowSize.x, windowSize.y));
if (!_texture) {
_texture = gpu::TexturePointer(gpu::Texture::createExternal2D([this](uint32_t recycleTexture, void* recycleFence) {
_webSurface->releaseTexture({ recycleTexture, recycleFence });
}));
auto webSurface = _webSurface;
auto recycler = [webSurface] (uint32_t recycleTexture, void* recycleFence) {
webSurface->releaseTexture({ recycleTexture, recycleFence });
};
_texture = gpu::TexturePointer(gpu::Texture::createExternal2D(recycler));
_texture->setSource(__FUNCTION__);
}
OffscreenQmlSurface::TextureAndFence newTextureAndFence;
@ -352,16 +366,7 @@ void RenderableWebEntityItem::destroyWebSurface() {
_mouseMoveConnection = QMetaObject::Connection();
QObject::disconnect(_hoverLeaveConnection);
_hoverLeaveConnection = QMetaObject::Connection();
// The lifetime of the QML surface MUST be managed by the main thread
// Additionally, we MUST use local variables copied by value, rather than
// member variables, since they would implicitly refer to a this that
// is no longer valid
auto webSurface = _webSurface;
AbstractViewStateInterface::instance()->postLambdaEvent([webSurface] {
webSurface->deleteLater();
});
_webSurface = nullptr;
_webSurface.reset();
}
}

View file

@ -78,7 +78,7 @@ private:
void destroyWebSurface();
glm::vec2 getWindowSize() const;
OffscreenQmlSurface* _webSurface{ nullptr };
QSharedPointer<OffscreenQmlSurface> _webSurface;
QMetaObject::Connection _connection;
gpu::TexturePointer _texture;
ivec2 _lastPress { INT_MIN };

View file

@ -182,8 +182,11 @@ GLTexture::~GLTexture() {
if (backend) {
if (_external) {
auto recycler = _gpuObject.getExternalRecycler();
assert(recycler);
backend->releaseExternalTexture(_id, recycler);
if (recycler) {
backend->releaseExternalTexture(_id, recycler);
} else {
qWarning() << "No recycler available for texture " << _id << " possible leak";
}
} else if (_id) {
backend->releaseTexture(_id, _size);
}