summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichal Klocek <michal.klocek@theqtcompany.com>2016-05-13 17:53:14 +0200
committerMichal Klocek <michal.klocek@qt.io>2016-08-24 13:13:20 +0000
commite2b8c3fe8f83cf448df4b0476f4f0dd4dd7d1b80 (patch)
tree1224f012afbdf6daf605fb6fb6f414fc769b3909 /src
parent8a4091c2104913294b4dc7b06c8e9fb2c022f51e (diff)
Fix textures memory leak on second X11 screen
Fix for QTBUG-48969 was only half-baked patch and introduced massive memory leak on fbo and texture alloctaions. Delete fbo and extra allocated textures. Task-number: QTBUG-52575 Task-number: QTBUG-48969 Change-Id: I2148f37cd27dab9e40ab72caeb6857752b69379f Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/core/delegated_frame_node.cpp82
-rw-r--r--src/core/delegated_frame_node.h5
2 files changed, 67 insertions, 20 deletions
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index c7c106177..363814789 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -70,7 +70,6 @@
#include <QSGSimpleRectNode>
#include <QSGSimpleTextureNode>
#include <QSGTexture>
-#include <QtGui/QOffscreenSurface>
#include <private/qsgadaptationlayer_p.h>
#if !defined(QT_NO_EGL)
@@ -91,6 +90,7 @@ namespace QtWebEngineCore {
class MailboxTexture : public QSGTexture, protected QOpenGLFunctions {
public:
MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QSize textureSize);
+ ~MailboxTexture();
virtual int textureId() const Q_DECL_OVERRIDE { return m_textureId; }
virtual QSize textureSize() const Q_DECL_OVERRIDE { return m_textureSize; }
virtual bool hasAlphaChannel() const Q_DECL_OVERRIDE { return m_hasAlpha; }
@@ -108,6 +108,9 @@ private:
QSize m_textureSize;
bool m_hasAlpha;
GLenum m_target;
+#if defined(USE_X11)
+ bool m_ownsTexture;
+#endif
#ifdef Q_OS_QNX
EGLStreamData m_eglStreamData;
#endif
@@ -280,6 +283,9 @@ MailboxTexture::MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QS
, m_textureSize(textureSize)
, m_hasAlpha(false)
, m_target(GL_TEXTURE_2D)
+#if defined(USE_X11)
+ , m_ownsTexture(false)
+#endif
{
initializeOpenGLFunctions();
@@ -290,6 +296,21 @@ MailboxTexture::MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QS
m_textureSize = QSize(1, 1);
}
+MailboxTexture::~MailboxTexture()
+{
+#if defined(USE_X11)
+ // This is rare case, where context is not shared
+ // we created extra texture in current context, so
+ // delete it now
+ if (m_ownsTexture) {
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext() ;
+ QOpenGLFunctions *funcs = currentContext->functions();
+ GLuint id(m_textureId);
+ funcs->glDeleteTextures(1, &id);
+ }
+#endif
+}
+
void MailboxTexture::bind()
{
glBindTexture(m_target, m_textureId);
@@ -390,8 +411,25 @@ RectClipNode::RectClipNode(const QRectF &rect)
DelegatedFrameNode::DelegatedFrameNode()
: m_numPendingSyncPoints(0)
+#if defined(USE_X11)
+ , m_contextShared(true)
+#endif
{
setFlag(UsePreprocess);
+#if defined(USE_X11)
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext() ;
+ QOpenGLContext *sharedContext = qt_gl_global_share_context();
+ if (!QOpenGLContext::areSharing(currentContext, sharedContext)) {
+ static bool allowNotSharedContextWarningShown = true;
+ if (allowNotSharedContextWarningShown) {
+ allowNotSharedContextWarningShown = false;
+ qWarning("Context is not shared, textures will be copied between contexts.");
+ }
+ m_offsurface.reset(new QOffscreenSurface);
+ m_offsurface->create();
+ m_contextShared = false;
+ }
+#endif
}
DelegatedFrameNode::~DelegatedFrameNode()
@@ -430,30 +468,28 @@ void DelegatedFrameNode::preprocess()
#if defined(USE_X11)
// Workaround when context is not shared QTBUG-48969
// Make slow copy between two contexts.
- QOpenGLContext *currentContext = QOpenGLContext::currentContext() ;
- QOpenGLContext *sharedContext = qt_gl_global_share_context();
- if (!QOpenGLContext::areSharing(currentContext,sharedContext)) {
- static bool allowNotSharedContextWarningShown = true;
- if (allowNotSharedContextWarningShown) {
- allowNotSharedContextWarningShown = false;
- qWarning("Context is not shared, textures will be copied between contexts.");
- }
+ if (!m_contextShared) {
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext() ;
+ QOpenGLContext *sharedContext = qt_gl_global_share_context();
+
+ QSurface *surface = currentContext->surface();
+ Q_ASSERT(m_offsurface);
+ sharedContext->makeCurrent(m_offsurface.data());
+ QOpenGLFunctions *funcs = sharedContext->functions();
+
+ GLuint fbo = 0;
+ funcs->glGenFramebuffers(1, &fbo);
Q_FOREACH (MailboxTexture *mailboxTexture, mailboxesToFetch) {
gfx::TransferableFence fence = transferredFences.take(mailboxTexture->mailboxHolder().sync_point);
waitChromiumSync(&fence);
deleteChromiumSync(&fence);
- QSurface *surface = currentContext->surface();
// Read texture into QImage from shared context.
// Switch to shared context.
- QOffscreenSurface offsurface;
- offsurface.create();
- sharedContext->makeCurrent(&offsurface);
- QOpenGLFunctions *funcs = sharedContext->functions();
+ sharedContext->makeCurrent(m_offsurface.data());
+ funcs = sharedContext->functions();
QImage img(mailboxTexture->textureSize(), QImage::Format_RGBA8888_Premultiplied);
- GLuint fbo = 0;
- funcs->glGenFramebuffers(1, &fbo);
funcs->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mailboxTexture->m_textureId, 0);
GLenum status = funcs->glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -461,13 +497,12 @@ void DelegatedFrameNode::preprocess()
qWarning("fbo error, skipping slow copy...");
continue;
}
-
- funcs->glReadPixels(0, 0, mailboxTexture->textureSize().width(), mailboxTexture->textureSize().height(), GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
- funcs->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ funcs->glReadPixels(0, 0, mailboxTexture->textureSize().width(), mailboxTexture->textureSize().height(),
+ GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
// Restore current context.
- currentContext->makeCurrent(surface);
// Create texture from QImage in current context.
+ currentContext->makeCurrent(surface);
GLuint texture = 0;
funcs = currentContext->functions();
funcs->glGenTextures(1, &texture);
@@ -479,7 +514,14 @@ void DelegatedFrameNode::preprocess()
funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mailboxTexture->textureSize().width(), mailboxTexture->textureSize().height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
mailboxTexture->m_textureId = texture;
+ mailboxTexture->m_ownsTexture = true;
}
+ // Cleanup allocated resources
+ sharedContext->makeCurrent(m_offsurface.data());
+ funcs = sharedContext->functions();
+ funcs->glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ funcs->glDeleteFramebuffers(1, &fbo);
+ currentContext->makeCurrent(surface);
} else
#endif
{
diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h
index eed03fadd..d888935b2 100644
--- a/src/core/delegated_frame_node.h
+++ b/src/core/delegated_frame_node.h
@@ -45,6 +45,7 @@
#include <QSharedData>
#include <QSharedPointer>
#include <QWaitCondition>
+#include <QtGui/QOffscreenSurface>
#include "chromium_gpu_helper.h"
#include "render_widget_host_view_qt_delegate.h"
@@ -98,6 +99,10 @@ private:
QMap<uint32, gfx::TransferableFence> m_mailboxGLFences;
QWaitCondition m_mailboxesFetchedWaitCond;
QMutex m_mutex;
+#if defined(USE_X11)
+ bool m_contextShared;
+ QScopedPointer<QOffscreenSurface> m_offsurface;
+#endif
};
} // namespace QtWebEngineCore