mirror of https://github.com/mgba-emu/mgba.git
Qt: Add checking and downgrading OpenGL support outside of the painter
This commit is contained in:
parent
e31de6b470
commit
a8a7372083
1
CHANGES
1
CHANGES
|
@ -78,6 +78,7 @@ Other fixes:
|
|||
- Qt: Fix gamepad event dispatching (fixes mgba.io/i/1922)
|
||||
- Qt: Pre-attach GDB stub when launching with -g (fixes mgba.io/i/1950)
|
||||
- Qt: Fix crash when editing shortcuts with none selected (fixes mgba.io/i/1964)
|
||||
- Qt: Fix crashing when no OpenGL context can be obtained
|
||||
- SM83: Simplify register pair access on big endian
|
||||
- SM83: Disassemble STOP as one byte
|
||||
- Wii: Fix crash on unloading irregularly sized GBA ROMs
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "DisplayGL.h"
|
||||
#include "DisplayQt.h"
|
||||
#include "LogController.h"
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
|
@ -27,16 +28,31 @@ Display* Display::create(QWidget* parent) {
|
|||
#if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(USE_EPOXY)
|
||||
case Driver::OPENGL:
|
||||
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
|
||||
format.setVersion(3, 0);
|
||||
format.setVersion(2, 0);
|
||||
} else {
|
||||
format.setVersion(3, 2);
|
||||
}
|
||||
format.setProfile(QSurfaceFormat::CoreProfile);
|
||||
if (!DisplayGL::supportsFormat(format)) {
|
||||
#ifdef BUILD_GL
|
||||
LOG(QT, WARN) << ("Failed to create an OpenGL Core context, trying old-style...");
|
||||
format.setVersion(1, 4);
|
||||
format.setOption(QSurfaceFormat::DeprecatedFunctions);
|
||||
if (!DisplayGL::supportsFormat(format)) {
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
return new DisplayGL(format, parent);
|
||||
#endif
|
||||
#ifdef BUILD_GL
|
||||
case Driver::OPENGL1:
|
||||
format.setVersion(1, 4);
|
||||
if (!DisplayGL::supportsFormat(format)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new DisplayGL(format, parent);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
#include "CoreController.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMutexLocker>
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLContext>
|
||||
#include <QOpenGLPaintDevice>
|
||||
#include <QMutexLocker>
|
||||
#include <QResizeEvent>
|
||||
#include <QScreen>
|
||||
#include <QTimer>
|
||||
|
@ -34,6 +35,15 @@
|
|||
|
||||
using namespace QGBA;
|
||||
|
||||
QHash<QSurfaceFormat, bool> DisplayGL::s_supports;
|
||||
|
||||
uint qHash(const QSurfaceFormat& format, uint seed) {
|
||||
QByteArray representation;
|
||||
QDataStream stream(&representation, QIODevice::WriteOnly);
|
||||
stream << format.version() << format.renderableType() << format.profile();
|
||||
return qHash(representation, seed);
|
||||
}
|
||||
|
||||
DisplayGL::DisplayGL(const QSurfaceFormat& format, QWidget* parent)
|
||||
: Display(parent)
|
||||
{
|
||||
|
@ -98,6 +108,44 @@ void DisplayGL::startDrawing(std::shared_ptr<CoreController> controller) {
|
|||
setUpdatesEnabled(false);
|
||||
}
|
||||
|
||||
bool DisplayGL::supportsFormat(const QSurfaceFormat& format) {
|
||||
if (!s_supports.contains(format)) {
|
||||
QOpenGLContext context;
|
||||
context.setFormat(format);
|
||||
if (!context.create()) {
|
||||
s_supports[format] = false;
|
||||
return false;
|
||||
}
|
||||
auto foundVersion = context.format().version();
|
||||
if (foundVersion == format.version()) {
|
||||
// Match!
|
||||
s_supports[format] = true;
|
||||
} else if (format.version() >= qMakePair(3, 2) && foundVersion > format.version()) {
|
||||
// At least as good
|
||||
s_supports[format] = true;
|
||||
} else if (format.majorVersion() == 1 && (foundVersion < qMakePair(3, 0) ||
|
||||
context.format().profile() == QSurfaceFormat::CompatibilityProfile ||
|
||||
context.format().testOption(QSurfaceFormat::DeprecatedFunctions))) {
|
||||
// Supports the old stuff
|
||||
s_supports[format] = true;
|
||||
} else if (!context.isOpenGLES() && format.version() >= qMakePair(2, 1) && foundVersion < qMakePair(3, 0) && foundVersion >= qMakePair(2, 1)) {
|
||||
// Weird edge case we support if ARB_framebuffer_object is present
|
||||
QOffscreenSurface surface;
|
||||
surface.create();
|
||||
if (!context.makeCurrent(&surface)) {
|
||||
s_supports[format] = false;
|
||||
return false;
|
||||
}
|
||||
s_supports[format] = context.hasExtension("GL_ARB_framebuffer_object");
|
||||
context.doneCurrent();
|
||||
} else {
|
||||
// No match
|
||||
s_supports[format] = false;
|
||||
}
|
||||
}
|
||||
return s_supports[format];
|
||||
}
|
||||
|
||||
void DisplayGL::stopDrawing() {
|
||||
if (m_drawThread) {
|
||||
m_isDrawing = false;
|
||||
|
@ -236,6 +284,7 @@ PainterGL::PainterGL(QWindow* surface, const QSurfaceFormat& format)
|
|||
: m_surface(surface)
|
||||
, m_format(format)
|
||||
{
|
||||
m_supportsShaders = m_format.version() >= qMakePair(2, 0);
|
||||
for (auto& buf : m_buffers) {
|
||||
m_free.append(&buf.front());
|
||||
}
|
||||
|
@ -260,24 +309,6 @@ void PainterGL::create() {
|
|||
m_gl->create();
|
||||
makeCurrent();
|
||||
|
||||
auto version = m_gl->format().version();
|
||||
QStringList extensions = QString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))).split(' ');
|
||||
|
||||
int forceVersion = 0;
|
||||
if (m_format.majorVersion() < 2) {
|
||||
forceVersion = 1;
|
||||
}
|
||||
|
||||
if ((version == qMakePair(2, 1) && !extensions.contains("GL_ARB_framebuffer_object")) || version == qMakePair(2, 0)) {
|
||||
QSurfaceFormat newFormat(m_format);
|
||||
newFormat.setVersion(1, 4);
|
||||
forceVersion = 1;
|
||||
m_gl->doneCurrent();
|
||||
m_gl->setFormat(newFormat);
|
||||
m_gl->create();
|
||||
makeCurrent();
|
||||
}
|
||||
|
||||
#ifdef BUILD_GL
|
||||
mGLContext* glBackend;
|
||||
#endif
|
||||
|
@ -288,13 +319,11 @@ void PainterGL::create() {
|
|||
m_window = std::make_unique<QOpenGLPaintDevice>();
|
||||
|
||||
#ifdef BUILD_GLES2
|
||||
version = m_gl->format().version();
|
||||
extensions = QString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))).split(' ');
|
||||
if (forceVersion != 1 && ((version == qMakePair(2, 1) && extensions.contains("GL_ARB_framebuffer_object")) || version.first > 2)) {
|
||||
auto version = m_format.version();
|
||||
if (version >= qMakePair(2, 0)) {
|
||||
gl2Backend = static_cast<mGLES2Context*>(malloc(sizeof(mGLES2Context)));
|
||||
mGLES2ContextCreate(gl2Backend);
|
||||
m_backend = &gl2Backend->d;
|
||||
m_supportsShaders = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -303,7 +332,6 @@ void PainterGL::create() {
|
|||
glBackend = static_cast<mGLContext*>(malloc(sizeof(mGLContext)));
|
||||
mGLContextCreate(glBackend);
|
||||
m_backend = &glBackend->d;
|
||||
m_supportsShaders = false;
|
||||
}
|
||||
#endif
|
||||
m_backend->swap = [](VideoBackend* v) {
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
|
||||
#include <QAtomicInt>
|
||||
#include <QElapsedTimer>
|
||||
#include <QOpenGLContext>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QMouseEvent>
|
||||
#include <QOpenGLContext>
|
||||
#include <QPainter>
|
||||
#include <QQueue>
|
||||
#include <QThread>
|
||||
|
@ -34,6 +35,8 @@
|
|||
|
||||
class QOpenGLPaintDevice;
|
||||
|
||||
uint qHash(const QSurfaceFormat&, uint seed = 0);
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class PainterGL;
|
||||
|
@ -51,6 +54,8 @@ public:
|
|||
void setVideoProxy(std::shared_ptr<VideoProxy>) override;
|
||||
int framebufferHandle() override;
|
||||
|
||||
static bool supportsFormat(const QSurfaceFormat&);
|
||||
|
||||
public slots:
|
||||
void stopDrawing() override;
|
||||
void pauseDrawing() override;
|
||||
|
@ -74,6 +79,8 @@ protected:
|
|||
private:
|
||||
void resizePainter();
|
||||
|
||||
static QHash<QSurfaceFormat, bool> s_supports;
|
||||
|
||||
bool m_isDrawing = false;
|
||||
bool m_hasStarted = false;
|
||||
std::unique_ptr<PainterGL> m_painter;
|
||||
|
|
|
@ -884,6 +884,12 @@ void Window::reloadDisplayDriver() {
|
|||
detachWidget(m_display.get());
|
||||
}
|
||||
m_display = std::unique_ptr<Display>(Display::create(this));
|
||||
if (!m_display) {
|
||||
LOG(QT, ERROR) << tr("Failed to create an appropriate display device, falling back to software display. "
|
||||
"Games may run slowly, especially with larger windows.");
|
||||
Display::setDriver(Display::Driver::QT);
|
||||
m_display = std::unique_ptr<Display>(Display::create(this));
|
||||
}
|
||||
#if defined(BUILD_GL) || defined(BUILD_GLES2)
|
||||
m_shaderView.reset();
|
||||
m_shaderView = std::make_unique<ShaderSelector>(m_display.get(), m_config);
|
||||
|
|
Loading…
Reference in New Issue