Avoid crash with EGLFS - #15874
Conversation
|
As we've two implementations for the waveforms (OpenGL and QQuick) would it help to switch from QOpenGLWindow to doc.qt.io/qt-6/qquickwidget.html using the QQuick waveform implementation we use for QML already? |
|
I don't think so. EGLFS is used with a frame buffer device, where no windows manager is available. See https://doc.qt.io/qt-6/embedded-linux.html. I can't test it though. Hope @mirko can confirm. |
|
fb(dev) is legacy from kernel side by now and AFAIK is - if still used - routed via DRM/KMS. |
|
The environment I use for reference: whereas |
There was a problem hiding this comment.
Pull request overview
This pull request addresses issue #15863 where Mixxx crashes on OpenGLES2-only systems using the EGLFS (EGL Full Screen) platform with DRM/KMS backend. The root cause is that EGLFS can only support either QWidgets or OpenGL windows, not both simultaneously. When Mixxx tries to embed OpenGL windows into its QWidgets-based main window on EGLFS, it causes a fatal crash.
Changes:
- Added EGLFS platform detection in both the waveform factory initialization and main window OpenGL initialization
- Modified OpenGL availability flag logic to prevent setting OpenGL as available when running on EGLFS
- Enhanced getSurfaceFormat() to safely handle nullptr config parameter
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/waveform/waveformwidgetfactory.h | Renamed parameter from config to pConfig to follow pointer naming convention |
| src/waveform/waveformwidgetfactory.cpp | Added EGLFS detection logic, prevented OpenGL availability flags from being set on EGLFS, and made getSurfaceFormat() handle nullptr safely |
| src/mixxxmainwindow.cpp | Added EGLFS detection to skip OpenGL window creation, added debug logging for OpenGL context creation, and renamed variables to follow pointer naming convention |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Done |
|
Just came here as I was curious about the Copilot review. Shouldn't the include commit be squashed into the one with the related code change, so every commit can be built and run? |
|
This was on one hand a false positive. It was already included by vinylcontrolmanager.h however that is guarded by |
|
The precommit issue is unrelated, it will be fixed with #16004 |
|
from the dev discussion: we should really get this in |
|
pre-commit fails because of the metafile issue in 2.6 when I have pushed. I have rebased and pushed again. I hope that was OK. |
|
code looks fine to me, do we need someone to test? (and how?) |
| } else if (pContext->isOpenGLES()) { | ||
| m_openGLVersion = "ES "; | ||
| } | ||
|
|
There was a problem hiding this comment.
This used to be init-ed to an empty string if not isOpenGLES. Not sure if there is a risk this strings need to be cleared? Perhaps a DEBUG_ASSERT is enough.
| } else if (pContext->isOpenGLES()) { | |
| m_openGLVersion = "ES "; | |
| } | |
| } else if (pContext->isOpenGLES()) { | |
| m_openGLVersion = "ES "; | |
| } else { | |
| m_openGLVersion = ""; | |
| } |
There was a problem hiding this comment.
We are here in the constructor, the constructor initializes the QString as empty. So nothing to do IMHO, except using QStringLiteral. I will also add a comment.
| if (pContext->isOpenGLES()) { | ||
| if (majorVersion * 100 + minorVersion >= 200) { | ||
| m_openGlesAvailable = true; | ||
| } | ||
| } else { | ||
| if (majorVersion * 100 + minorVersion >= 201) { | ||
| m_openGlAvailable = true; | ||
| } | ||
| } |
There was a problem hiding this comment.
Could we merge this condition to help readability?
| if (pContext->isOpenGLES()) { | |
| if (majorVersion * 100 + minorVersion >= 200) { | |
| m_openGlesAvailable = true; | |
| } | |
| } else { | |
| if (majorVersion * 100 + minorVersion >= 201) { | |
| m_openGlAvailable = true; | |
| } | |
| } | |
| if (pContext->isOpenGLES() && majorVersion * 100 + minorVersion >= 200) { | |
| m_openGlesAvailable = true; | |
| } else if (majorVersion * 100 + minorVersion >= 201) { | |
| m_openGlAvailable = true; | |
| } |
Also wondering if we need to set m_openGlesAvailable and m_openGlAvailable, such as
| if (pContext->isOpenGLES()) { | |
| if (majorVersion * 100 + minorVersion >= 200) { | |
| m_openGlesAvailable = true; | |
| } | |
| } else { | |
| if (majorVersion * 100 + minorVersion >= 201) { | |
| m_openGlAvailable = true; | |
| } | |
| } | |
| m_openGlesAvailable = pContext->isOpenGLES() && majorVersion * 100 + minorVersion >= 200; | |
| m_openGlAvailable = !pContext->isOpenGLES() && majorVersion * 100 + minorVersion >= 201; |
If not, could you please put a comment to highlight that these are expected to be set to false otherwise during another step?
| // With EGLFS there is always exactly one native window and one EGL window surface | ||
| // OpenGL windows cannot be embedded into our QWidgets main window we already have. | ||
| // https://doc.qt.io/qt-6/embedded-linux.html | ||
| bool isEglfs = QGuiApplication::platformName() == "eglfs"; |
There was a problem hiding this comment.
Do we know if this string is normalised? Wondering if somebody passes QT_QPA_PLATFORM=EGLFS, whether the platform name would remain lower cased or ignored, of if we should normalise the output. I am under the impression it should be the doc isn't completely clear about this.
There was a problem hiding this comment.
https://doc.qt.io/qt-6/qguiapplication.html#platformName-prop only one spelling is mentioned. I think we can trust it.
I will add a comment.
Co-authored-by: Antoine Colombier <7086688+acolombier@users.noreply.github.com>
|
Done. |
With EGLFS we can use either QWidgets or OpenGL, not both at the same time.
This is a band aid that shall avoid the fatal abort reported in #15863.
A better fix would be to use only GELS.
This type of refactoring is probably not beneficial because we are already working in a QML GUI which likely works with EGLFS. We need to investigate with this.