diff options
author | Be <be@mixxx.org> | 2020-12-06 03:47:32 -0600 |
---|---|---|
committer | Be <be@mixxx.org> | 2020-12-06 03:49:36 -0600 |
commit | f8fb30ec91dc0faa02d4f148085b8b7d58024cee (patch) | |
tree | ff68caa6019e0b2c72da9dadf5a1f99344d2fa95 /src | |
parent | bf343d2677f19d1886682c4bd15e26f70884ce27 (diff) |
fix initialization of QGLWidget waveform widgets & renderers
QGLWidget documentation says:
The initialization of OpenGL rendering state, etc. should be done by overriding
the initializeGL() function, rather than in the constructor of your QGLWidget
subclass.
Calling QOpenGLFunctions_2_1::initializeOpenGLFunctions in the QGLWidget
constructors crashed on macOS:
https://bugs.launchpad.net/mixxx/+bug/1877487
I am surprised it did not crash on Linux and Windows.
The calls to makeCurrent in the QGLWidget constructors were futile; that
does nothing before Qt calls QGLWidget::initializeGL. This can be verified
by adding:
qDebug() << "Context current" << (QGLContext::currentContext() == context());
after the call to makeCurrent.
Diffstat (limited to 'src')
21 files changed, 76 insertions, 60 deletions
diff --git a/src/waveform/renderers/glslwaveformrenderersignal.cpp b/src/waveform/renderers/glslwaveformrenderersignal.cpp index 8777ff0e5a..c62172a5e1 100644 --- a/src/waveform/renderers/glslwaveformrenderersignal.cpp +++ b/src/waveform/renderers/glslwaveformrenderersignal.cpp @@ -17,7 +17,6 @@ GLSLWaveformRendererSignal::GLSLWaveformRendererSignal(WaveformWidgetRenderer* w m_bDumpPng(false), m_shadersValid(false), m_rgbShader(rgbShader) { - initializeOpenGLFunctions(); } GLSLWaveformRendererSignal::~GLSLWaveformRendererSignal() { @@ -189,7 +188,8 @@ void GLSLWaveformRendererSignal::createFrameBuffers() { } } -bool GLSLWaveformRendererSignal::onInit() { +void GLSLWaveformRendererSignal::onInitializeGL() { + initializeOpenGLFunctions(); m_textureRenderedWaveformCompletion = 0; if (!m_frameShaderProgram) { @@ -197,14 +197,12 @@ bool GLSLWaveformRendererSignal::onInit() { } if (!loadShaders()) { - return false; + return; } createGeometry(); if (!loadTexture()) { - return false; + return; } - - return true; } void GLSLWaveformRendererSignal::onSetup(const QDomNode& node) { diff --git a/src/waveform/renderers/glslwaveformrenderersignal.h b/src/waveform/renderers/glslwaveformrenderersignal.h index 8e5f3ca803..9ebfc7920d 100644 --- a/src/waveform/renderers/glslwaveformrenderersignal.h +++ b/src/waveform/renderers/glslwaveformrenderersignal.h @@ -1,6 +1,5 @@ #pragma once -#include <QOpenGLFunctions_2_1> #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include <QGLFramebufferObject> @@ -11,17 +10,17 @@ #include "util/memory.h" #include "waveform/renderers/waveformrenderersignalbase.h" -class GLSLWaveformRendererSignal: public QObject, - public WaveformRendererSignalBase, - protected QOpenGLFunctions_2_1 { +class GLSLWaveformRendererSignal : public QObject, + public WaveformRendererSignalBase, + public GLWaveformRenderer { Q_OBJECT public: GLSLWaveformRendererSignal(WaveformWidgetRenderer* waveformWidgetRenderer, bool rgbShader); ~GLSLWaveformRendererSignal() override; - bool onInit() override; void onSetup(const QDomNode& node) override; + void onInitializeGL() override; void draw(QPainter* painter, QPaintEvent* event) override; void onSetTrack() override; diff --git a/src/waveform/renderers/glvsynctestrenderer.cpp b/src/waveform/renderers/glvsynctestrenderer.cpp index dc5e42e966..cad6a2205d 100644 --- a/src/waveform/renderers/glvsynctestrenderer.cpp +++ b/src/waveform/renderers/glvsynctestrenderer.cpp @@ -11,7 +11,6 @@ GLVSyncTestRenderer::GLVSyncTestRenderer( WaveformWidgetRenderer* waveformWidgetRenderer) : WaveformRendererSignalBase(waveformWidgetRenderer), m_drawcount(0) { - initializeOpenGLFunctions(); } GLVSyncTestRenderer::~GLVSyncTestRenderer() { diff --git a/src/waveform/renderers/glvsynctestrenderer.h b/src/waveform/renderers/glvsynctestrenderer.h index b9a31049eb..a74ef88e64 100644 --- a/src/waveform/renderers/glvsynctestrenderer.h +++ b/src/waveform/renderers/glvsynctestrenderer.h @@ -1,15 +1,14 @@ #pragma once -#include <QOpenGLFunctions_2_1> #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include "waveformrenderersignalbase.h" class ControlObject; -class GLVSyncTestRenderer: public WaveformRendererSignalBase, - protected QOpenGLFunctions_2_1 { -public: +class GLVSyncTestRenderer : public WaveformRendererSignalBase, + public GLWaveformRenderer { + public: explicit GLVSyncTestRenderer( WaveformWidgetRenderer* waveformWidgetRenderer); virtual ~GLVSyncTestRenderer(); diff --git a/src/waveform/renderers/glwaveformrendererfilteredsignal.cpp b/src/waveform/renderers/glwaveformrendererfilteredsignal.cpp index 8cb59e1e40..9043ee5262 100644 --- a/src/waveform/renderers/glwaveformrendererfilteredsignal.cpp +++ b/src/waveform/renderers/glwaveformrendererfilteredsignal.cpp @@ -12,7 +12,6 @@ GLWaveformRendererFilteredSignal::GLWaveformRendererFilteredSignal( WaveformWidgetRenderer* waveformWidgetRenderer) : WaveformRendererSignalBase(waveformWidgetRenderer) { - initializeOpenGLFunctions(); } GLWaveformRendererFilteredSignal::~GLWaveformRendererFilteredSignal() { diff --git a/src/waveform/renderers/glwaveformrendererfilteredsignal.h b/src/waveform/renderers/glwaveformrendererfilteredsignal.h index 807ee928ea..be4b30780b 100644 --- a/src/waveform/renderers/glwaveformrendererfilteredsignal.h +++ b/src/waveform/renderers/glwaveformrendererfilteredsignal.h @@ -1,6 +1,5 @@ #pragma once -#include <QOpenGLFunctions_2_1> #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include <QDomNode> @@ -9,9 +8,9 @@ class ControlObject; -class GLWaveformRendererFilteredSignal: public WaveformRendererSignalBase, - protected QOpenGLFunctions_2_1 { -public: +class GLWaveformRendererFilteredSignal : public WaveformRendererSignalBase, + public GLWaveformRenderer { + public: explicit GLWaveformRendererFilteredSignal( WaveformWidgetRenderer* waveformWidgetRenderer); virtual ~GLWaveformRendererFilteredSignal(); diff --git a/src/waveform/renderers/glwaveformrendererrgb.cpp b/src/waveform/renderers/glwaveformrendererrgb.cpp index 8bfac3f5f4..50ac786781 100644 --- a/src/waveform/renderers/glwaveformrendererrgb.cpp +++ b/src/waveform/renderers/glwaveformrendererrgb.cpp @@ -16,7 +16,6 @@ const float kHeightScaleFactor = 255.0f / sqrtf(255 * 255 * 3); GLWaveformRendererRGB::GLWaveformRendererRGB( WaveformWidgetRenderer* waveformWidgetRenderer) : WaveformRendererSignalBase(waveformWidgetRenderer) { - initializeOpenGLFunctions(); } GLWaveformRendererRGB::~GLWaveformRendererRGB() { diff --git a/src/waveform/renderers/glwaveformrendererrgb.h b/src/waveform/renderers/glwaveformrendererrgb.h index 4b435d6746..8bbfd7fd93 100644 --- a/src/waveform/renderers/glwaveformrendererrgb.h +++ b/src/waveform/renderers/glwaveformrendererrgb.h @@ -1,14 +1,13 @@ #pragma once -#include <QOpenGLFunctions_2_1> #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include "waveformrenderersignalbase.h" class ControlObject; -class GLWaveformRendererRGB: public WaveformRendererSignalBase, - protected QOpenGLFunctions_2_1 { +class GLWaveformRendererRGB : public WaveformRendererSignalBase, + public GLWaveformRenderer { public: explicit GLWaveformRendererRGB( WaveformWidgetRenderer* waveformWidgetRenderer); diff --git a/src/waveform/renderers/glwaveformrenderersimplesignal.cpp b/src/waveform/renderers/glwaveformrenderersimplesignal.cpp index d9651356bf..56d9f5448e 100644 --- a/src/waveform/renderers/glwaveformrenderersimplesignal.cpp +++ b/src/waveform/renderers/glwaveformrenderersimplesignal.cpp @@ -10,7 +10,6 @@ GLWaveformRendererSimpleSignal::GLWaveformRendererSimpleSignal( WaveformWidgetRenderer* waveformWidgetRenderer) : WaveformRendererSignalBase(waveformWidgetRenderer) { - initializeOpenGLFunctions(); } GLWaveformRendererSimpleSignal::~GLWaveformRendererSimpleSignal() { diff --git a/src/waveform/renderers/glwaveformrenderersimplesignal.h b/src/waveform/renderers/glwaveformrenderersimplesignal.h index 48e698803d..ae3aae6111 100644 --- a/src/waveform/renderers/glwaveformrenderersimplesignal.h +++ b/src/waveform/renderers/glwaveformrenderersimplesignal.h @@ -1,14 +1,14 @@ #pragma once -#include <QOpenGLFunctions_2_1> #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include "waveformrenderersignalbase.h" class ControlObject; -class GLWaveformRendererSimpleSignal : public WaveformRendererSignalBase, protected QOpenGLFunctions_2_1 { -public: +class GLWaveformRendererSimpleSignal : public WaveformRendererSignalBase, + public GLWaveformRenderer { + public: explicit GLWaveformRendererSimpleSignal(WaveformWidgetRenderer* waveformWidgetRenderer); virtual ~GLWaveformRendererSimpleSignal(); diff --git a/src/waveform/renderers/waveformrendererabstract.h b/src/waveform/renderers/waveformrendererabstract.h index efb0a7a507..6a1bba6f6d 100644 --- a/src/waveform/renderers/waveformrendererabstract.h +++ b/src/waveform/renderers/waveformrendererabstract.h @@ -2,6 +2,7 @@ #define WAVEFORMRENDERERABSTRACT_H #include <QDomNode> +#include <QOpenGLFunctions_2_1> #include <QPaintEvent> #include <QPainter> @@ -47,4 +48,16 @@ class WaveformRendererAbstract { friend class WaveformWidgetRenderer; }; +/// GLWaveformRenderer is a WaveformRendererAbstract which directly calls OpenGL functions. +/// +/// Note that the Qt OpenGL WaveformRendererAbstracts are not GLWaveformRenderers because +/// they do not call OpenGL functions directly. Instead, they inherit QGLWidget and use the +/// QPainter API which Qt translates to OpenGL under the hood. +class GLWaveformRenderer : protected QOpenGLFunctions_2_1 { + public: + virtual void onInitializeGL() { + initializeOpenGLFunctions(); + } +}; + #endif // WAVEFORMRENDERERABSTRACT_H diff --git a/src/waveform/widgets/glrgbwaveformwidget.cpp b/src/waveform/widgets/glrgbwaveformwidget.cpp index 271b5cb6f1..f3d6e82ce2 100644 --- a/src/waveform/widgets/glrgbwaveformwidget.cpp +++ b/src/waveform/widgets/glrgbwaveformwidget.cpp @@ -13,21 +13,17 @@ #include "util/performancetimer.h" GLRGBWaveformWidget::GLRGBWaveformWidget(const QString& group, QWidget* parent) - : QGLWidget(parent, SharedGLContext::getWidget()), - WaveformWidgetAbstract(group) { + : GLWaveformWidgetAbstract(group, parent) { qDebug() << "Created QGLWidget. Context" << "Valid:" << context()->isValid() << "Sharing:" << context()->isSharing(); - if (QGLContext::currentContext() != context()) { - makeCurrent(); - } addRenderer<WaveformRenderBackground>(); addRenderer<WaveformRendererEndOfTrack>(); addRenderer<WaveformRendererPreroll>(); addRenderer<WaveformRenderMarkRange>(); #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) - addRenderer<GLWaveformRendererRGB>(); + m_pGlRenderer = addRenderer<GLWaveformRendererRGB>(); #endif // !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) addRenderer<WaveformRenderBeat>(); addRenderer<WaveformRenderMark>(); diff --git a/src/waveform/widgets/glrgbwaveformwidget.h b/src/waveform/widgets/glrgbwaveformwidget.h index d479c22d95..96bd8c166d 100644 --- a/src/waveform/widgets/glrgbwaveformwidget.h +++ b/src/waveform/widgets/glrgbwaveformwidget.h @@ -5,7 +5,7 @@ #include "waveformwidgetabstract.h" -class GLRGBWaveformWidget : public QGLWidget, public WaveformWidgetAbstract { +class GLRGBWaveformWidget : public GLWaveformWidgetAbstract { Q_OBJECT public: GLRGBWaveformWidget(const QString& group, QWidget* parent); diff --git a/src/waveform/widgets/glsimplewaveformwidget.cpp b/src/waveform/widgets/glsimplewaveformwidget.cpp index b36dc23ed2..1d6a10dcd2 100644 --- a/src/waveform/widgets/glsimplewaveformwidget.cpp +++ b/src/waveform/widgets/glsimplewaveformwidget.cpp @@ -16,21 +16,17 @@ #include "util/performancetimer.h" GLSimpleWaveformWidget::GLSimpleWaveformWidget(const QString& group, QWidget* parent) - : QGLWidget(parent, SharedGLContext::getWidget()), - WaveformWidgetAbstract(group) { + : GLWaveformWidgetAbstract(group, parent) { qDebug() << "Created QGLWidget. Context" << "Valid:" << context()->isValid() << "Sharing:" << context()->isSharing(); - if (QGLContext::currentContext() != context()) { - makeCurrent(); - } addRenderer<WaveformRenderBackground>(); addRenderer<WaveformRendererEndOfTrack>(); addRenderer<WaveformRendererPreroll>(); addRenderer<WaveformRenderMarkRange>(); #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) - addRenderer<GLWaveformRendererSimpleSignal>(); + m_pGlRenderer = addRenderer<GLWaveformRendererSimpleSignal>(); #endif // !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) addRenderer<WaveformRenderBeat>(); addRenderer<WaveformRenderMark>(); diff --git a/src/waveform/widgets/glsimplewaveformwidget.h b/src/waveform/widgets/glsimplewaveformwidget.h index 7cc3ddfc7c..00c20bfdf3 100644 --- a/src/waveform/widgets/glsimplewaveformwidget.h +++ b/src/waveform/widgets/glsimplewaveformwidget.h @@ -5,7 +5,7 @@ #include "waveformwidgetabstract.h" -class GLSimpleWaveformWidget : public QGLWidget, public WaveformWidgetAbstract { +class GLSimpleWaveformWidget : public GLWaveformWidgetAbstract { Q_OBJECT public: GLSimpleWaveformWidget(const QString& group, QWidget* parent); diff --git a/src/waveform/widgets/glslwaveformwidget.cpp b/src/waveform/widgets/glslwaveformwidget.cpp index 6c8c22fc7b..152b710ea9 100644 --- a/src/waveform/widgets/glslwaveformwidget.cpp +++ b/src/waveform/widgets/glslwaveformwidget.cpp @@ -31,8 +31,7 @@ GLSLWaveformWidget::GLSLWaveformWidget( const QString& group, QWidget* parent, bool rgbRenderer) - : QGLWidget(parent, SharedGLContext::getWidget()), - WaveformWidgetAbstract(group) { + : GLWaveformWidgetAbstract(group, parent) { qDebug() << "Created QGLWidget. Context" << "Valid:" << context()->isValid() << "Sharing:" << context()->isSharing(); @@ -46,9 +45,9 @@ GLSLWaveformWidget::GLSLWaveformWidget( addRenderer<WaveformRenderMarkRange>(); #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) if (rgbRenderer) { - m_signalRenderer = addRenderer<GLSLWaveformRendererRGBSignal>(); + m_pGlRenderer = addRenderer<GLSLWaveformRendererRGBSignal>(); } else { - m_signalRenderer = addRenderer<GLSLWaveformRendererFilteredSignal>(); + m_pGlRenderer = addRenderer<GLSLWaveformRendererFilteredSignal>(); } #else Q_UNUSED(rgbRenderer); diff --git a/src/waveform/widgets/glslwaveformwidget.h b/src/waveform/widgets/glslwaveformwidget.h index 85baf50dcd..229bbc2fca 100644 --- a/src/waveform/widgets/glslwaveformwidget.h +++ b/src/waveform/widgets/glslwaveformwidget.h @@ -6,7 +6,7 @@ class GLSLWaveformRendererSignal; -class GLSLWaveformWidget : public QGLWidget, public WaveformWidgetAbstract { +class GLSLWaveformWidget : public GLWaveformWidgetAbstract { Q_OBJECT public: GLSLWaveformWidget( diff --git a/src/waveform/widgets/glwaveformwidget.cpp b/src/waveform/widgets/glwaveformwidget.cpp index 071f476dcd..14cc8b97c5 100644 --- a/src/waveform/widgets/glwaveformwidget.cpp +++ b/src/waveform/widgets/glwaveformwidget.cpp @@ -16,21 +16,17 @@ #include "util/performancetimer.h" GLWaveformWidget::GLWaveformWidget(const QString& group, QWidget* parent) - : QGLWidget(parent, SharedGLContext::getWidget()), - WaveformWidgetAbstract(group) { + : GLWaveformWidgetAbstract(group, parent) { qDebug() << "Created QGLWidget. Context" << "Valid:" << context()->isValid() << "Sharing:" << context()->isSharing(); - if (QGLContext::currentContext() != context()) { - makeCurrent(); - } addRenderer<WaveformRenderBackground>(); addRenderer<WaveformRendererEndOfTrack>(); addRenderer<WaveformRendererPreroll>(); addRenderer<WaveformRenderMarkRange>(); #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) - addRenderer<GLWaveformRendererFilteredSignal>(); + m_pGlRenderer = addRenderer<GLWaveformRendererFilteredSignal>(); #endif // !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) addRenderer<WaveformRenderBeat>(); addRenderer<WaveformRenderMark>(); diff --git a/src/waveform/widgets/glwaveformwidget.h b/src/waveform/widgets/glwaveformwidget.h index ea81612bca..63e186d4f4 100644 --- a/src/waveform/widgets/glwaveformwidget.h +++ b/src/waveform/widgets/glwaveformwidget.h @@ -5,7 +5,7 @@ #include "waveformwidgetabstract.h" -class GLWaveformWidget : public QGLWidget, public WaveformWidgetAbstract { +class GLWaveformWidget : public GLWaveformWidgetAbstract { Q_OBJECT public: GLWaveformWidget(const QString& group, QWidget* parent); diff --git a/src/waveform/widgets/waveformwidgetabstract.cpp b/src/waveform/widgets/waveformwidgetabstract.cpp index 7dc1d995e0..bec1e190a3 100644 --- a/src/waveform/widgets/waveformwidgetabstract.cpp +++ b/src/waveform/widgets/waveformwidgetabstract.cpp @@ -1,9 +1,11 @@ #include "waveformwidgetabstract.h" -#include "waveform/renderers/waveformwidgetrenderer.h" -#include "util/compatibility.h" -#include <QtDebug> #include <QWidget> +#include <QtDebug> + +#include "util/compatibility.h" +#include "waveform/renderers/waveformwidgetrenderer.h" +#include "waveform/sharedglcontext.h" WaveformWidgetAbstract::WaveformWidgetAbstract(const QString& group) : WaveformWidgetRenderer(group), @@ -46,3 +48,8 @@ void WaveformWidgetAbstract::resize(int width, int height) { } WaveformWidgetRenderer::resize(width, height, static_cast<float>(devicePixelRatio)); } + +GLWaveformWidgetAbstract::GLWaveformWidgetAbstract(const QString& group, QWidget* parent) + : WaveformWidgetAbstract(group), + QGLWidget(parent, SharedGLContext::getWidget()) { +} diff --git a/src/waveform/widgets/waveformwidgetabstract.h b/src/waveform/widgets/waveformwidgetabstract.h index 5f79f2f69c..cc6df485cd 100644 --- a/src/waveform/widgets/waveformwidgetabstract.h +++ b/src/waveform/widgets/waveformwidgetabstract.h @@ -1,12 +1,13 @@ #ifndef WAVEFORMWIDGETABSTRACT_H #define WAVEFORMWIDGETABSTRACT_H -#include <QWidget> +#include <QGLWidget> #include <QString> +#include <QWidget> +#include "util/duration.h" #include "waveform/renderers/waveformwidgetrenderer.h" #include "waveformwidgettype.h" -#include "util/duration.h" class VSyncThread; @@ -43,4 +44,22 @@ class WaveformWidgetAbstract : public WaveformWidgetRenderer { friend class WaveformWidgetFactory; }; +/// GLWaveformWidgetAbstract is a WaveformWidgetAbstract & QGLWidget that has +/// a GLWaveformRenderer member which requires initialization that must be +/// deferred until Qt calls QGLWidget::initializeGL and cannot be done in the +/// constructor. +class GLWaveformWidgetAbstract : public WaveformWidgetAbstract, public QGLWidget { + public: + GLWaveformWidgetAbstract(const QString& group, QWidget* parent); + + protected: + void initializeGL() override { + if (m_pGlRenderer) { + m_pGlRenderer->onInitializeGL(); + } + } + + GLWaveformRenderer* m_pGlRenderer; +}; + #endif // WAVEFORMWIDGETABSTRACT_H |