diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2021-08-13 08:13:57 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-08-24 10:30:56 +0000 |
commit | 39222e23092233329d455793f814695901b7c5ce (patch) | |
tree | a296ef0d14b472c94c54b5ae6fb52e1e9c721a71 | |
parent | 386a4cd5ab75583f239a00c472041144f2ab1906 (diff) |
Keep reference to buffer until it has been replaced
For the code path which uses QWaylandBufferMaterial, the buffer
could potentially be deleted before the material had been
updated, which could cause issues if the render thread was
currently using the textures.
In the default code path this was handled by keeping a reference
to the buffer in the texture provider, but in the alternative YUV
format code path, we did not increase the reference count of the
buffer, so it would be deleted immediately when it was replaced
rather than wait for the sync with the render thread.
Task-number: QTBUG-95715
Change-Id: Ic6038ea8281e2a2e292d12150d1fffedb5c3b76e
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
(cherry picked from commit 6b9a27d77e226a3d0ce9fa9b4974f70c9ef4a30e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/compositor/compositor_api/qwaylandquickitem.cpp | 52 | ||||
-rw-r--r-- | src/compositor/compositor_api/qwaylandquickitem_p.h | 2 |
2 files changed, 32 insertions, 22 deletions
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp index ecaf4e67f..eb326a294 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.cpp +++ b/src/compositor/compositor_api/qwaylandquickitem.cpp @@ -361,6 +361,35 @@ void QWaylandBufferMaterial::ensureTextures(int count) m_scenegraphTextures << nullptr; } } + +void QWaylandBufferMaterial::setBufferRef(QWaylandQuickItem *surfaceItem, const QWaylandBufferRef &ref) +{ + m_bufferRef = ref; + for (int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++) { + if (auto texture = ref.toOpenGLTexture(plane)) { + QQuickWindow::CreateTextureOptions opt; + QWaylandQuickSurface *waylandSurface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface()); + if (waylandSurface != nullptr && waylandSurface->useTextureAlpha()) + opt |= QQuickWindow::TextureHasAlphaChannel; + QSGTexture *scenegraphTexture; + if (ref.bufferFormatEgl() == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES) { + scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNativeExternalOES(texture->textureId(), + surfaceItem->window(), + ref.size(), + opt); + } else { + scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNative(texture->textureId(), + surfaceItem->window(), + ref.size(), + opt); + } + scenegraphTexture->setFiltering(surfaceItem->smooth() ? QSGTexture::Linear : QSGTexture::Nearest); + setTextureForPlane(plane, texture, scenegraphTexture); + } + } + + bind(); +} #endif // QT_CONFIG(opengl) QMutex *QWaylandQuickItemPrivate::mutex = nullptr; @@ -1503,28 +1532,7 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat if (d->newTexture) { d->newTexture = false; - for (int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++) - if (auto texture = ref.toOpenGLTexture(plane)) { - QQuickWindow::CreateTextureOptions opt; - QWaylandQuickSurface *waylandSurface = qobject_cast<QWaylandQuickSurface *>(surface()); - if (waylandSurface != nullptr && waylandSurface->useTextureAlpha()) - opt |= QQuickWindow::TextureHasAlphaChannel; - QSGTexture *scenegraphTexture; - if (ref.bufferFormatEgl() == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES) { - scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNativeExternalOES(texture->textureId(), - window(), - ref.size(), - opt); - } else { - scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNative(texture->textureId(), - window(), - ref.size(), - opt); - } - scenegraphTexture->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest); - material->setTextureForPlane(plane, texture, scenegraphTexture); - } - material->bind(); + material->setBufferRef(this, ref); } const QSize surfaceSize = ref.size() / surface()->bufferScale(); diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h index 34acdeab7..09b9f6785 100644 --- a/src/compositor/compositor_api/qwaylandquickitem_p.h +++ b/src/compositor/compositor_api/qwaylandquickitem_p.h @@ -77,6 +77,7 @@ public: ~QWaylandBufferMaterial() override; void setTextureForPlane(int plane, QOpenGLTexture *texture, QSGTexture *scenegraphTexture); + void setBufferRef(QWaylandQuickItem *surfaceItem, const QWaylandBufferRef &ref); void bind(); void updateScenegraphTextures(QRhi *rhi); @@ -93,6 +94,7 @@ private: const QWaylandBufferRef::BufferFormatEgl m_format; QVarLengthArray<QOpenGLTexture*, 3> m_textures; QVarLengthArray<QSGTexture*, 3> m_scenegraphTextures; + QWaylandBufferRef m_bufferRef; }; #endif // QT_CONFIG(opengl) |