diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 4fbefb37d874906b2fb9c0526a59ea070e84eec8..c6dbf350b6e5fd71c8e9ba28f7e1d41aa01796ed 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -117,8 +117,12 @@ public: QSGContext::AntialiasingMethod antialiasingMethod; bool distanceFieldDisabled; QSGDistanceFieldGlyphNode::AntialiasingMode distanceFieldAntialiasing; + + static QOpenGLContext *sharedOpenGLContext; }; +QOpenGLContext *QSGContextPrivate::sharedOpenGLContext = 0; + class QSGTextureCleanupEvent : public QEvent { public: @@ -170,6 +174,20 @@ QSGContext::~QSGContext() { } +/*! + * This function is used by the Qt WebEngine to set up context sharing + * across multiple windows. Do not use it for any other purpose. + */ +void QSGContext::setSharedOpenGLContext(QOpenGLContext *context) +{ + QSGContextPrivate::sharedOpenGLContext = context; +} + +QOpenGLContext *QSGContext::sharedOpenGLContext() +{ + return QSGContextPrivate::sharedOpenGLContext; +} + void QSGContext::renderContextInitialized(QSGRenderContext *renderContext) { Q_D(QSGContext); diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h index 08fafb071315a39d9de5f0cb5fc8e1f0b4b79a6b..270f1083736397e504d87af840a6254e5569a1da 100644 --- a/src/quick/scenegraph/qsgcontext_p.h +++ b/src/quick/scenegraph/qsgcontext_p.h @@ -162,6 +162,9 @@ public: virtual QSize minimumFBOSize() const; virtual QSurfaceFormat defaultSurfaceFormat() const; + static void setSharedOpenGLContext(QOpenGLContext *context); + static QOpenGLContext *sharedOpenGLContext(); + void setDistanceFieldEnabled(bool enabled); bool isDistanceFieldEnabled() const; diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index fc1e98d87fb97f63ee62b3b8b4b60cc1b10b0fa1..f294cb4a2d1a0316adcc036ffd9cdb7f800a4013 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -264,6 +264,8 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) if (!gl) { gl = new QOpenGLContext(); gl->setFormat(window->requestedFormat()); + if (QSGContext::sharedOpenGLContext()) + gl->setShareContext(QSGContext::sharedOpenGLContext()); if (!gl->create()) { delete gl; gl = 0; diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index bb0bd67d6b3ae1827369050fcbd233e92a07afd4..42c7c9c0ba713127a68d7c4b3ad17ef9c0d5102e 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -889,6 +889,8 @@ void QSGThreadedRenderLoop::handleExposure(Window *w) if (!w->thread->gl) { w->thread->gl = new QOpenGLContext(); + if (QSGContext::sharedOpenGLContext()) + w->thread->gl->setShareContext(QSGContext::sharedOpenGLContext()); w->thread->gl->setFormat(w->window->requestedFormat()); if (!w->thread->gl->create()) { delete w->thread->gl; diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index f1d09c37855e7a947bb69b8400d722a251061767..d5d12bd138199f85dc66a3702c9eee1290f6d8ed 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -178,6 +178,8 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window) RLDEBUG(" - creating GL context"); m_gl = new QOpenGLContext(); m_gl->setFormat(window->requestedFormat()); + if (QSGContext::sharedOpenGLContext()) + m_gl->setShareContext(QSGContext::sharedOpenGLContext()); m_gl->create(); QSG_RENDER_TIMING_SAMPLE(time_created); RLDEBUG(" - making current"); diff --git a/tests/auto/quick/scenegraph/tst_scenegraph.cpp b/tests/auto/quick/scenegraph/tst_scenegraph.cpp index cfa491ce9723f822b51681c04ac8c2194d8157a5..642a238e153846c562362eccb41b0d4dd508b542 100644 --- a/tests/auto/quick/scenegraph/tst_scenegraph.cpp +++ b/tests/auto/quick/scenegraph/tst_scenegraph.cpp @@ -42,8 +42,8 @@ #include <qtest.h> #include <QtQuick> -#include <private/qquickanimator_p.h> +#include <private/qsgcontext_p.h> #include <QtQml> @@ -99,9 +99,13 @@ bool containsSomethingOtherThanWhite(const QImage &image) return false; } -// To compare images, we need a special function with a bit of error -// as glyphs has an invisible, but measurable variance depending -// on where in the glyph cache they end up. +// When running on native Nvidia graphics cards on linux, the +// distance field glyph pixels have a measurable, but not visible +// pixel error. Use a custom compare function to avoid +// +// This was GT-216 with the ubuntu "nvidia-319" driver package. +// llvmpipe does not show the same issue. +// bool compareImages(const QImage &ia, const QImage &ib) { if (ia.size() != ib.size()) @@ -137,21 +141,44 @@ void tst_SceneGraph::manyWindows_data() { QTest::addColumn<QString>("file"); QTest::addColumn<bool>("toplevel"); - - QTest::newRow("image,toplevel") << QStringLiteral("manyWindows_image.qml") << true; - QTest::newRow("image,subwindow") << QStringLiteral("manyWindows_image.qml") << false; - QTest::newRow("dftext,toplevel") << QStringLiteral("manyWindows_dftext.qml") << true; - QTest::newRow("dftext,subwindow") << QStringLiteral("manyWindows_dftext.qml") << false; - QTest::newRow("ntext,toplevel") << QStringLiteral("manyWindows_ntext.qml") << true; - QTest::newRow("ntext,subwindow") << QStringLiteral("manyWindows_ntext.qml") << false; - QTest::newRow("rects,toplevel") << QStringLiteral("manyWindows_rects.qml") << true; - QTest::newRow("rects,subwindow") << QStringLiteral("manyWindows_rects.qml") << false; + QTest::addColumn<bool>("shared"); + + QTest::newRow("image,toplevel") << QStringLiteral("manyWindows_image.qml") << true << false; + QTest::newRow("image,subwindow") << QStringLiteral("manyWindows_image.qml") << false << false; + QTest::newRow("dftext,toplevel") << QStringLiteral("manyWindows_dftext.qml") << true << false; + QTest::newRow("dftext,subwindow") << QStringLiteral("manyWindows_dftext.qml") << false << false; + QTest::newRow("ntext,toplevel") << QStringLiteral("manyWindows_ntext.qml") << true << false; + QTest::newRow("ntext,subwindow") << QStringLiteral("manyWindows_ntext.qml") << false << false; + QTest::newRow("rects,toplevel") << QStringLiteral("manyWindows_rects.qml") << true << false; + QTest::newRow("rects,subwindow") << QStringLiteral("manyWindows_rects.qml") << false << false; + + QTest::newRow("image,toplevel,sharing") << QStringLiteral("manyWindows_image.qml") << true << true; + QTest::newRow("image,subwindow,sharing") << QStringLiteral("manyWindows_image.qml") << false << true; + QTest::newRow("dftext,toplevel,sharing") << QStringLiteral("manyWindows_dftext.qml") << true << true; + QTest::newRow("dftext,subwindow,sharing") << QStringLiteral("manyWindows_dftext.qml") << false << true; + QTest::newRow("ntext,toplevel,sharing") << QStringLiteral("manyWindows_ntext.qml") << true << true; + QTest::newRow("ntext,subwindow,sharing") << QStringLiteral("manyWindows_ntext.qml") << false << true; + QTest::newRow("rects,toplevel,sharing") << QStringLiteral("manyWindows_rects.qml") << true << true; + QTest::newRow("rects,subwindow,sharing") << QStringLiteral("manyWindows_rects.qml") << false << true; } +struct ShareContextResetter { +public: + ~ShareContextResetter() { QSGContext::setSharedOpenGLContext(0); } +}; + void tst_SceneGraph::manyWindows() { QFETCH(QString, file); QFETCH(bool, toplevel); + QFETCH(bool, shared); + + QOpenGLContext sharedGLContext; + ShareContextResetter cleanup; // To avoid dangling pointer in case of test-failure. + if (shared) { + sharedGLContext.create(); + QSGContext::setSharedOpenGLContext(&sharedGLContext); + } QScopedPointer<QWindow> parent; if (!toplevel) {