WIP: use Duckstation's context code to directly render into QT Widget from separate thread without two OpenGL contexts

currently only works on Windows
This commit is contained in:
RSDuck
2022-10-04 12:21:16 +02:00
parent ce68e883c4
commit ef763aa569
27 changed files with 9664 additions and 299 deletions

View File

@ -44,9 +44,8 @@
#include <SDL2/SDL.h>
#ifdef OGLRENDERER_ENABLED
#include "OpenGLSupport.h"
#endif
#include "duckstation/gl/context.h"
#include "main.h"
#include "Input.h"
@ -341,52 +340,107 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
connect(this, SIGNAL(screenLayoutChange()), mainWindow->panelWidget, SLOT(onScreenLayoutChanged()));
connect(this, SIGNAL(windowFullscreenToggle()), mainWindow, SLOT(onFullscreenToggled()));
connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger()));
}
if (mainWindow->hasOGL) initOpenGL();
void EmuThread::updateScreenSettings(bool filter, const WindowInfo& windowInfo, int numScreens, int* screenKind, float* screenMatrix)
{
screenSettingsLock.lock();
this->filter = filter;
this->windowInfo = windowInfo;
this->numScreens = numScreens;
memcpy(this->screenKind, screenKind, sizeof(int)*numScreens);
memcpy(this->screenMatrix, screenMatrix, sizeof(float)*numScreens*6);
screenSettingsLock.unlock();
}
void EmuThread::initOpenGL()
{
QOpenGLContext* windowctx = mainWindow->getOGLContext();
QSurfaceFormat format = windowctx->format();
GL::Context* windowctx = mainWindow->getOGLContext();
format.setSwapInterval(0);
oglContext = windowctx;
oglContext->MakeCurrent();
oglSurface = new QOffscreenSurface();
oglSurface->setFormat(format);
oglSurface->create();
if (!oglSurface->isValid())
OpenGL::BuildShaderProgram(kScreenVS, kScreenFS, screenShaderProgram, "ScreenShader");
GLuint pid = screenShaderProgram[2];
glBindAttribLocation(pid, 0, "vPosition");
glBindAttribLocation(pid, 1, "vTexcoord");
glBindFragDataLocation(pid, 0, "oColor");
OpenGL::LinkShaderProgram(screenShaderProgram);
glUseProgram(pid);
glUniform1i(glGetUniformLocation(pid, "ScreenTex"), 0);
screenShaderScreenSizeULoc = glGetUniformLocation(pid, "uScreenSize");
screenShaderScaleFactorULoc = glGetUniformLocation(pid, "uScaleFactor");
screenShaderTransformULoc = glGetUniformLocation(pid, "uTransform");
// to prevent bleeding between both parts of the screen
// with bilinear filtering enabled
const int paddedHeight = 192*2+2;
const float padPixels = 1.f / paddedHeight;
const float vertices[] =
{
// TODO handle this!
printf("oglSurface shat itself :(\n");
delete oglSurface;
return;
}
0.f, 0.f, 0.f, 0.f,
0.f, 192.f, 0.f, 0.5f - padPixels,
256.f, 192.f, 1.f, 0.5f - padPixels,
0.f, 0.f, 0.f, 0.f,
256.f, 192.f, 1.f, 0.5f - padPixels,
256.f, 0.f, 1.f, 0.f,
oglContext = new QOpenGLContext();
oglContext->setFormat(oglSurface->format());
oglContext->setShareContext(windowctx);
if (!oglContext->create())
{
// TODO handle this!
printf("oglContext shat itself :(\n");
delete oglContext;
delete oglSurface;
return;
}
0.f, 0.f, 0.f, 0.5f + padPixels,
0.f, 192.f, 0.f, 1.f,
256.f, 192.f, 1.f, 1.f,
0.f, 0.f, 0.f, 0.5f + padPixels,
256.f, 192.f, 1.f, 1.f,
256.f, 0.f, 1.f, 0.5f + padPixels
};
oglContext->moveToThread(this);
glGenBuffers(1, &screenVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &screenVertexArray);
glBindVertexArray(screenVertexArray);
glEnableVertexAttribArray(0); // position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0));
glEnableVertexAttribArray(1); // texcoord
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4));
glGenTextures(1, &screenTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, screenTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, paddedHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// fill the padding
u8 zeroData[256*4*4];
memset(zeroData, 0, sizeof(zeroData));
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 2, GL_RGBA, GL_UNSIGNED_BYTE, zeroData);
static_cast<ScreenPanelGL*>(mainWindow->panel)->transferLayout(this);
}
void EmuThread::deinitOpenGL()
{
delete oglContext;
delete oglSurface;
glDeleteTextures(1, &screenTexture);
glDeleteVertexArrays(1, &screenVertexArray);
glDeleteBuffers(1, &screenVertexBuffer);
OpenGL::DeleteShaderProgram(screenShaderProgram);
oglContext->DoneCurrent();
oglContext = nullptr;
}
void EmuThread::run()
{
bool hasOGL = mainWindow->hasOGL;
u32 mainScreenPos[3];
NDS::Init();
@ -401,10 +455,11 @@ void EmuThread::run()
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons;
bool hasOGL = mainWindow->hasOGL;
#ifdef OGLRENDERER_ENABLED
if (hasOGL)
{
oglContext->makeCurrent(oglSurface);
initOpenGL();
videoRenderer = Config::_3DRenderer;
}
else
@ -478,15 +533,10 @@ void EmuThread::run()
hasOGL = mainWindow->hasOGL;
#ifdef OGLRENDERER_ENABLED
if (hasOGL)
{
oglContext->makeCurrent(oglSurface);
videoRenderer = Config::_3DRenderer;
}
else
#endif
{
videoRenderer = 0;
}
}
else
videoRenderer = hasOGL ? Config::_3DRenderer : 0;
@ -543,15 +593,6 @@ void EmuThread::run()
}
}
#ifdef OGLRENDERER_ENABLED
if (videoRenderer == 1)
{
FrontBufferLock.lock();
if (FrontBufferReverseSyncs[FrontBuffer ^ 1])
glWaitSync(FrontBufferReverseSyncs[FrontBuffer ^ 1], 0, GL_TIMEOUT_IGNORED);
FrontBufferLock.unlock();
}
#endif
// emulate
u32 nlines = NDS::RunFrame();
@ -562,21 +603,17 @@ void EmuThread::run()
if (ROMManager::GBASave)
ROMManager::GBASave->CheckFlush();
FrontBufferLock.lock();
FrontBuffer = GPU::FrontBuffer;
#ifdef OGLRENDERER_ENABLED
if (videoRenderer == 1)
if (!hasOGL)
{
if (FrontBufferSyncs[FrontBuffer])
glDeleteSync(FrontBufferSyncs[FrontBuffer]);
FrontBufferSyncs[FrontBuffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
// this is hacky but this is the easiest way to call
// this function without dealling with a ton of
// macro mess
epoxy_glFlush();
FrontBufferLock.lock();
FrontBuffer = GPU::FrontBuffer;
FrontBufferLock.unlock();
}
else
{
FrontBuffer = GPU::FrontBuffer;
drawScreenGL();
}
#endif
FrontBufferLock.unlock();
#ifdef MELONCAP
MelonCap::Update();
@ -665,6 +702,21 @@ void EmuThread::run()
changeWindowTitle(melontitle);
SDL_Delay(75);
if (oglContext)
drawScreenGL();
int contextRequest = ContextRequest;
if (contextRequest == 1)
{
initOpenGL();
ContextRequest = 0;
}
else if (contextRequest == 2)
{
deinitOpenGL();
ContextRequest = 0;
}
}
}
@ -675,10 +727,7 @@ void EmuThread::run()
//Platform::LAN_DeInit();
if (hasOGL)
{
oglContext->doneCurrent();
deinitOpenGL();
}
}
void EmuThread::changeWindowTitle(char* title)
@ -698,6 +747,18 @@ void EmuThread::emuRun()
micOpen();
}
void EmuThread::initContext()
{
ContextRequest = 1;
while (ContextRequest != 0);
}
void EmuThread::deinitContext()
{
ContextRequest = 2;
while (ContextRequest != 0);
}
void EmuThread::emuPause()
{
EmuPause++;
@ -749,6 +810,72 @@ bool EmuThread::emuIsActive()
return (RunningSomething == 1);
}
void EmuThread::drawScreenGL()
{
int w = windowInfo.surface_width;
int h = windowInfo.surface_height;
float factor = windowInfo.surface_scale;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, w*factor, h*factor);
glUseProgram(screenShaderProgram[2]);
glUniform2f(screenShaderScreenSizeULoc, w, h);
glUniform1f(screenShaderScaleFactorULoc, factor);
int frontbuf = FrontBuffer;
glActiveTexture(GL_TEXTURE0);
#ifdef OGLRENDERER_ENABLED
if (GPU::Renderer != 0)
{
// hardware-accelerated render
GPU::CurGLCompositor->BindOutputTexture(frontbuf);
}
else
#endif
{
// regular render
glBindTexture(GL_TEXTURE_2D, screenTexture);
if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1])
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA,
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192+2, 256, 192, GL_RGBA,
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
}
}
screenSettingsLock.lock();
GLint filter = filter ? GL_LINEAR : GL_NEAREST;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer);
glBindVertexArray(screenVertexArray);
for (int i = 0; i < numScreens; i++)
{
glUniformMatrix2x3fv(screenShaderTransformULoc, 1, GL_TRUE, screenMatrix[i]);
glDrawArrays(GL_TRIANGLES, screenKind[i] == 0 ? 0 : 2*3, 2*3);
}
screenSettingsLock.unlock();
//OSD::Update(this);
//OSD::DrawGL(this, w*factor, h*factor);
oglContext->SwapBuffers();
}
ScreenHandler::ScreenHandler(QWidget* widget)
{
widget->setMouseTracking(true);
@ -966,12 +1093,12 @@ ScreenPanelNative::ScreenPanelNative(QWidget* parent) : QWidget(parent), ScreenH
screenTrans[0].reset();
screenTrans[1].reset();
OSD::Init(nullptr);
OSD::Init();
}
ScreenPanelNative::~ScreenPanelNative()
{
OSD::DeInit(nullptr);
OSD::DeInit();
}
void ScreenPanelNative::setupScreenLayout()
@ -1022,7 +1149,7 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
}
}
OSD::Update(nullptr);
OSD::Update();
OSD::DrawNative(painter);
}
@ -1070,23 +1197,97 @@ void ScreenPanelNative::onScreenLayoutChanged()
}
ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QOpenGLWidget(parent), ScreenHandler(this)
{}
ScreenPanelGL::ScreenPanelGL(QWidget* parent) : QWidget(parent), ScreenHandler(this)
{
setAutoFillBackground(false);
setAttribute(Qt::WA_NativeWindow, true);
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_PaintOnScreen, true);
setAttribute(Qt::WA_KeyCompression, false);
setFocusPolicy(Qt::StrongFocus);
}
ScreenPanelGL::~ScreenPanelGL()
{}
bool ScreenPanelGL::createContext()
{
makeCurrent();
std::optional<WindowInfo> windowInfo = getWindowInfo();
std::array<GL::Context::Version, 2> versionsToTry = {
GL::Context::Version{GL::Context::Profile::Core, 3, 2},
GL::Context::Version{GL::Context::Profile::Core, 4, 3}};
if (windowInfo.has_value())
{
glContext = GL::Context::Create(*getWindowInfo(), versionsToTry);
glContext->DoneCurrent();
}
OSD::DeInit(this);
return glContext != nullptr;
}
glDeleteTextures(1, &screenTexture);
qreal ScreenPanelGL::devicePixelRatioFromScreen() const
{
const QScreen* screen_for_ratio = screen();
if (!screen_for_ratio)
screen_for_ratio = QGuiApplication::primaryScreen();
glDeleteVertexArrays(1, &screenVertexArray);
glDeleteBuffers(1, &screenVertexBuffer);
return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1);
}
delete screenShader;
int ScreenPanelGL::scaledWindowWidth() const
{
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioFromScreen())), 1);
}
doneCurrent();
int ScreenPanelGL::scaledWindowHeight() const
{
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioFromScreen())), 1);
}
std::optional<WindowInfo> ScreenPanelGL::getWindowInfo()
{
WindowInfo wi;
// Windows and Apple are easy here since there's no display connection.
#if defined(_WIN32)
wi.type = WindowInfo::Type::Win32;
wi.window_handle = reinterpret_cast<void*>(winId());
#elif defined(__APPLE__)
wi.type = WindowInfo::Type::MacOS;
wi.window_handle = reinterpret_cast<void*>(winId());
#else
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
const QString platform_name = QGuiApplication::platformName();
if (platform_name == QStringLiteral("xcb"))
{
wi.type = WindowInfo::Type::X11;
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle());
wi.window_handle = reinterpret_cast<void*>(winId());
}
else if (platform_name == QStringLiteral("wayland"))
{
wi.type = WindowInfo::Type::Wayland;
wi.display_connection = pni->nativeResourceForWindow("display", windowHandle());
wi.window_handle = pni->nativeResourceForWindow("surface", windowHandle());
}
else
{
qCritical() << "Unknown PNI platform " << platform_name;
return std::nullopt;
}
#endif
wi.surface_width = static_cast<u32>(scaledWindowWidth());
wi.surface_height = static_cast<u32>(scaledWindowHeight());
wi.surface_scale = static_cast<float>(devicePixelRatioFromScreen());
return wi;
}
QPaintEngine* ScreenPanelGL::paintEngine() const
{
return nullptr;
}
void ScreenPanelGL::setupScreenLayout()
@ -1095,163 +1296,15 @@ void ScreenPanelGL::setupScreenLayout()
int h = height();
screenSetupLayout(w, h);
}
void ScreenPanelGL::initializeGL()
{
initializeOpenGLFunctions();
const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
const GLubyte* version = glGetString(GL_VERSION); // version as a string
printf("OpenGL: renderer: %s\n", renderer);
printf("OpenGL: version: %s\n", version);
glClearColor(0, 0, 0, 1);
screenShader = new QOpenGLShaderProgram(this);
screenShader->addShaderFromSourceCode(QOpenGLShader::Vertex, kScreenVS);
screenShader->addShaderFromSourceCode(QOpenGLShader::Fragment, kScreenFS);
GLuint pid = screenShader->programId();
glBindAttribLocation(pid, 0, "vPosition");
glBindAttribLocation(pid, 1, "vTexcoord");
glBindFragDataLocation(pid, 0, "oColor");
screenShader->link();
screenShader->bind();
screenShader->setUniformValue("ScreenTex", (GLint)0);
screenShader->release();
// to prevent bleeding between both parts of the screen
// with bilinear filtering enabled
const int paddedHeight = 192*2+2;
const float padPixels = 1.f / paddedHeight;
const float vertices[] =
{
0.f, 0.f, 0.f, 0.f,
0.f, 192.f, 0.f, 0.5f - padPixels,
256.f, 192.f, 1.f, 0.5f - padPixels,
0.f, 0.f, 0.f, 0.f,
256.f, 192.f, 1.f, 0.5f - padPixels,
256.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 0.5f + padPixels,
0.f, 192.f, 0.f, 1.f,
256.f, 192.f, 1.f, 1.f,
0.f, 0.f, 0.f, 0.5f + padPixels,
256.f, 192.f, 1.f, 1.f,
256.f, 0.f, 1.f, 0.5f + padPixels
};
glGenBuffers(1, &screenVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glGenVertexArrays(1, &screenVertexArray);
glBindVertexArray(screenVertexArray);
glEnableVertexAttribArray(0); // position
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0));
glEnableVertexAttribArray(1); // texcoord
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4));
glGenTextures(1, &screenTexture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, screenTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, paddedHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// fill the padding
u8 zeroData[256*4*4];
memset(zeroData, 0, sizeof(zeroData));
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 2, GL_RGBA, GL_UNSIGNED_BYTE, zeroData);
OSD::Init(this);
}
void ScreenPanelGL::paintGL()
{
int w = width();
int h = height();
float factor = devicePixelRatioF();
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, w*factor, h*factor);
if (emuThread)
{
screenShader->bind();
screenShader->setUniformValue("uScreenSize", (float)w, (float)h);
screenShader->setUniformValue("uScaleFactor", factor);
emuThread->FrontBufferLock.lock();
int frontbuf = emuThread->FrontBuffer;
glActiveTexture(GL_TEXTURE0);
#ifdef OGLRENDERER_ENABLED
if (GPU::Renderer != 0)
{
if (emuThread->FrontBufferSyncs[emuThread->FrontBuffer])
glWaitSync(emuThread->FrontBufferSyncs[emuThread->FrontBuffer], 0, GL_TIMEOUT_IGNORED);
// hardware-accelerated render
GPU::CurGLCompositor->BindOutputTexture(frontbuf);
}
else
#endif
{
// regular render
glBindTexture(GL_TEXTURE_2D, screenTexture);
if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1])
{
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA,
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192+2, 256, 192, GL_RGBA,
GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
}
}
GLint filter = Config::ScreenFilter ? GL_LINEAR : GL_NEAREST;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glBindBuffer(GL_ARRAY_BUFFER, screenVertexBuffer);
glBindVertexArray(screenVertexArray);
GLint transloc = screenShader->uniformLocation("uTransform");
for (int i = 0; i < numScreens; i++)
{
glUniformMatrix2x3fv(transloc, 1, GL_TRUE, screenMatrix[i]);
glDrawArrays(GL_TRIANGLES, screenKind[i] == 0 ? 0 : 2*3, 2*3);
}
screenShader->release();
if (emuThread->FrontBufferReverseSyncs[emuThread->FrontBuffer])
glDeleteSync(emuThread->FrontBufferReverseSyncs[emuThread->FrontBuffer]);
emuThread->FrontBufferReverseSyncs[emuThread->FrontBuffer] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
emuThread->FrontBufferLock.unlock();
}
OSD::Update(this);
OSD::DrawGL(this, w*factor, h*factor);
transferLayout(emuThread);
}
void ScreenPanelGL::resizeEvent(QResizeEvent* event)
{
setupScreenLayout();
QOpenGLWidget::resizeEvent(event);
}
void ScreenPanelGL::resizeGL(int w, int h)
{
QWidget::resizeEvent(event);
}
void ScreenPanelGL::mousePressEvent(QMouseEvent* event)
@ -1286,6 +1339,13 @@ bool ScreenPanelGL::event(QEvent* event)
return QWidget::event(event);
}
void ScreenPanelGL::transferLayout(EmuThread* thread)
{
std::optional<WindowInfo> windowInfo = getWindowInfo();
if (windowInfo.has_value())
thread->updateScreenSettings(Config::ScreenFilter, *windowInfo, numScreens, screenKind, &screenMatrix[0][0]);
}
void ScreenPanelGL::onScreenLayoutChanged()
{
setMinimumSize(screenGetMinSize());
@ -1758,17 +1818,7 @@ void MainWindow::createScreenPanel()
panel = panelGL;
panelWidget = panelGL;
if (!panelGL->isValid())
hasOGL = false;
else
{
QSurfaceFormat fmt = panelGL->format();
if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 2))
hasOGL = false;
}
if (!hasOGL)
delete panelGL;
panelGL->createContext();
}
if (!hasOGL)
@ -1784,12 +1834,12 @@ void MainWindow::createScreenPanel()
emit screenLayoutChange();
}
QOpenGLContext* MainWindow::getOGLContext()
GL::Context* MainWindow::getOGLContext()
{
if (!hasOGL) return nullptr;
QOpenGLWidget* glpanel = dynamic_cast<QOpenGLWidget*>(panel);
return glpanel->context();
ScreenPanelGL* glpanel = static_cast<ScreenPanelGL*>(panel);
return glpanel->getContext();
}
void MainWindow::resizeEvent(QResizeEvent* event)
@ -2959,19 +3009,20 @@ void MainWindow::onUpdateVideoSettings(bool glchange)
if (glchange)
{
emuThread->emuPause();
if (hasOGL) emuThread->deinitContext();
if (hasOGL)
emuThread->deinitOpenGL();
delete panel;
createScreenPanel();
connect(emuThread, SIGNAL(windowUpdate()), panelWidget, SLOT(repaint()));
if (hasOGL) emuThread->initOpenGL();
}
videoSettingsDirty = true;
if (glchange)
{
if (hasOGL) emuThread->initContext();
emuThread->emuUnpause();
}
}
@ -3062,14 +3113,6 @@ int main(int argc, char** argv)
SANITIZE(Config::ScreenAspectBot, 0, 4);
#undef SANITIZE
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setVersion(3, 2);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setSwapInterval(0);
QSurfaceFormat::setDefaultFormat(format);
audioSync = SDL_CreateCond();
audioSyncLock = SDL_CreateMutex();