diff options
author | Jüri Valdmann <juri.valdmann@qt.io> | 2018-11-27 09:20:46 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-11-27 15:06:33 +0000 |
commit | bbee17d60ae390a8c2c53d429cfa552f726a6d45 (patch) | |
tree | 0ac2d18d1d41a9b1a2fb829e5a2c05076b2a8184 | |
parent | cfef46154053b1c53a879e19f0e8c76db2182976 (diff) |
Fix GL context tracking when running in GPU-on-UI mode
Both Qt and Chromium keep track of the current GL context by using thread-local
variables, and naturally they are completely unaware of each other. As a result,
when a QOpenGLContext is made current, the previous gl::GLContext is not
released, and vice-versa. This is fine as long as each thread uses exclusively
either Qt or Chromium GL bindings, which is usually the case.
The only exception is when the GL driver is considered thread-unsafe
(QOpenGLContext::supportsThreadedOpenGL() is false), in which case we have to
run all GL operations, including Chromium's GPU service, on the UI thread. Now
the bindings are being mixed and both Qt and Chromium get quite confused
regarding the current state of the surface.
To get this to work we have to release the current QOpenGLContext before
executing any tasks from Chromium's GPU service and the gl::GLContext
afterwards. Since GPU service just posts tasks to the UI thread task runner,
we'll have to instrument the entire UI thread message pump.
Fixes: QTBUG-72017
Change-Id: Ibd72e3041d213217fd097dfb4272e49243e31e67
Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Reviewed-by: Liang Qi <liang.qi@qt.io>
-rw-r--r-- | src/core/browser_main_parts_qt.cpp | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp index 38e048470..1cb1ae5a2 100644 --- a/src/core/browser_main_parts_qt.cpp +++ b/src/core/browser_main_parts_qt.cpp @@ -59,6 +59,12 @@ #include <QEventLoop> #include <QObject> #include <QTimerEvent> +#include <QtGui/qtgui-config.h> + +#if QT_CONFIG(opengl) +#include "ui/gl/gl_context.h" +#include <QOpenGLContext> +#endif #if defined(Q_OS_WIN) #include "ui/display/win/screen_win.h" @@ -152,8 +158,55 @@ protected: } private: + // Both Qt and Chromium keep track of the current GL context by using + // thread-local variables, and naturally they are completely unaware of each + // other. As a result, when a QOpenGLContext is made current, the previous + // gl::GLContext is not released, and vice-versa. This is fine as long as + // each thread uses exclusively either Qt or Chromium GL bindings, which is + // usually the case. + // + // The only exception is when the GL driver is considered thread-unsafe + // (QOpenGLContext::supportsThreadedOpenGL() is false), in which case we + // have to run all GL operations, including Chromium's GPU service, on the + // UI thread. Now the bindings are being mixed and both Qt and Chromium get + // quite confused regarding the current state of the surface. + // + // To get this to work we have to release the current QOpenGLContext before + // executing any tasks from Chromium's GPU service and the gl::GLContext + // afterwards. Since GPU service just posts tasks to the UI thread task + // runner, we'll have to instrument the entire UI thread message pump. + class ScopedGLContextChecker + { +#if QT_CONFIG(opengl) + public: + ScopedGLContextChecker() + { + if (!m_enabled) + return; + + if (QOpenGLContext *context = QOpenGLContext::currentContext()) + context->doneCurrent(); + } + + ~ScopedGLContextChecker() + { + if (!m_enabled) + return; + + if (gl::GLContext *context = gl::GLContext::GetCurrent()) + context->ReleaseCurrent(nullptr); + } + + private: + bool m_enabled = !QOpenGLContext::supportsThreadedOpenGL(); +#endif // QT_CONFIG(opengl) + }; + + void handleScheduledWork() { + ScopedGLContextChecker glContextChecker; + bool more_work_is_plausible = m_delegate->DoWork(); base::TimeTicks delayed_work_time; |