mirror of https://github.com/snes9xgit/snes9x.git
Qt: Handle failed context creation better.
This commit is contained in:
parent
cf49325555
commit
d96b2a711b
|
@ -14,7 +14,7 @@ class EmuCanvas : public QWidget
|
||||||
virtual void deinit() = 0;
|
virtual void deinit() = 0;
|
||||||
virtual void draw() = 0;
|
virtual void draw() = 0;
|
||||||
void paintEvent(QPaintEvent *) override = 0;
|
void paintEvent(QPaintEvent *) override = 0;
|
||||||
virtual void createContext() {}
|
virtual bool createContext() { return false; }
|
||||||
virtual void recreateUIAssets() {}
|
virtual void recreateUIAssets() {}
|
||||||
void output(uint8_t *buffer, int width, int height, QImage::Format format, int bytes_per_line, double frame_rate);
|
void output(uint8_t *buffer, int width, int height, QImage::Format format, int bytes_per_line, double frame_rate);
|
||||||
void throttle();
|
void throttle();
|
||||||
|
|
|
@ -122,10 +122,10 @@ void EmuCanvasOpenGL::customShaderDraw()
|
||||||
shader->render(texture, output_data.width, output_data.height, viewport.x(), viewport.y(), viewport.width(), viewport.height(), S9xViewportCallback);
|
shader->render(texture, output_data.width, output_data.height, viewport.x(), viewport.y(), viewport.width(), viewport.height(), S9xViewportCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuCanvasOpenGL::createContext()
|
bool EmuCanvasOpenGL::createContext()
|
||||||
{
|
{
|
||||||
if (context)
|
if (context)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
auto platform = QGuiApplication::platformName();
|
auto platform = QGuiApplication::platformName();
|
||||||
auto pni = QGuiApplication::platformNativeInterface();
|
auto pni = QGuiApplication::platformNativeInterface();
|
||||||
|
@ -139,7 +139,11 @@ void EmuCanvasOpenGL::createContext()
|
||||||
int s = devicePixelRatio();
|
int s = devicePixelRatio();
|
||||||
|
|
||||||
if (!wayland_egl_context->attach(display, surface, { parent->x(), parent->y(), parent->width(), parent->height(), s }))
|
if (!wayland_egl_context->attach(display, surface, { parent->x(), parent->y(), parent->width(), parent->height(), s }))
|
||||||
|
{
|
||||||
printf("Couldn't attach context to wayland surface.\n");
|
printf("Couldn't attach context to wayland surface.\n");
|
||||||
|
context.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
context.reset(wayland_egl_context);
|
context.reset(wayland_egl_context);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +154,11 @@ void EmuCanvasOpenGL::createContext()
|
||||||
|
|
||||||
auto glx_context = new GTKGLXContext();
|
auto glx_context = new GTKGLXContext();
|
||||||
if (!glx_context->attach(display, xid))
|
if (!glx_context->attach(display, xid))
|
||||||
|
{
|
||||||
printf("Couldn't attach to X11 window.\n");
|
printf("Couldn't attach to X11 window.\n");
|
||||||
|
context.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
context.reset(glx_context);
|
context.reset(glx_context);
|
||||||
}
|
}
|
||||||
|
@ -160,7 +168,8 @@ void EmuCanvasOpenGL::createContext()
|
||||||
if (!wgl_context->attach((HWND)hwnd))
|
if (!wgl_context->attach((HWND)hwnd))
|
||||||
{
|
{
|
||||||
printf("Couldn't attach to context\n");
|
printf("Couldn't attach to context\n");
|
||||||
return;
|
context.reset();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
context.reset(wgl_context);
|
context.reset(wgl_context);
|
||||||
#endif
|
#endif
|
||||||
|
@ -194,6 +203,8 @@ void EmuCanvasOpenGL::createContext()
|
||||||
context->swap_interval(config->enable_vsync ? 1 : 0);
|
context->swap_interval(config->enable_vsync ? 1 : 0);
|
||||||
QGuiApplication::sync();
|
QGuiApplication::sync();
|
||||||
paintEvent(nullptr);
|
paintEvent(nullptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuCanvasOpenGL::loadShaders()
|
void EmuCanvasOpenGL::loadShaders()
|
||||||
|
|
|
@ -14,7 +14,7 @@ class EmuCanvasOpenGL : public EmuCanvas
|
||||||
EmuCanvasOpenGL(EmuConfig *config, QWidget *parent, QWidget *main_window);
|
EmuCanvasOpenGL(EmuConfig *config, QWidget *parent, QWidget *main_window);
|
||||||
~EmuCanvasOpenGL();
|
~EmuCanvasOpenGL();
|
||||||
|
|
||||||
void createContext() override;
|
bool createContext() override;
|
||||||
void deinit() override;
|
void deinit() override;
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
|
@ -75,10 +75,10 @@ bool EmuCanvasVulkan::initImGui()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuCanvasVulkan::createContext()
|
bool EmuCanvasVulkan::createContext()
|
||||||
{
|
{
|
||||||
if (simple_output)
|
if (context)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
platform = QGuiApplication::platformName();
|
platform = QGuiApplication::platformName();
|
||||||
auto pni = QGuiApplication::platformNativeInterface();
|
auto pni = QGuiApplication::platformNativeInterface();
|
||||||
|
@ -89,7 +89,11 @@ void EmuCanvasVulkan::createContext()
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
auto hwnd = (HWND)winId();
|
auto hwnd = (HWND)winId();
|
||||||
context->init_win32(nullptr, hwnd, config->display_device_index);
|
if (!context->init_win32(nullptr, hwnd, config->display_device_index))
|
||||||
|
{
|
||||||
|
context.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (platform == "wayland")
|
if (platform == "wayland")
|
||||||
{
|
{
|
||||||
|
@ -98,14 +102,21 @@ void EmuCanvasVulkan::createContext()
|
||||||
auto surface = (wl_surface *)pni->nativeResourceForWindow("surface", main_window->windowHandle());
|
auto surface = (wl_surface *)pni->nativeResourceForWindow("surface", main_window->windowHandle());
|
||||||
wayland_surface->attach(display, surface, { parent->x(), parent->y(), width(), height(), static_cast<int>(devicePixelRatio()) });
|
wayland_surface->attach(display, surface, { parent->x(), parent->y(), width(), height(), static_cast<int>(devicePixelRatio()) });
|
||||||
auto [scaled_width, scaled_height] = wayland_surface->get_size();
|
auto [scaled_width, scaled_height] = wayland_surface->get_size();
|
||||||
context->init_wayland(display, wayland_surface->child, scaled_width, scaled_height, config->display_device_index);
|
if (!context->init_wayland(display, wayland_surface->child, scaled_width, scaled_height, config->display_device_index))
|
||||||
|
{
|
||||||
|
context.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (platform == "xcb")
|
else if (platform == "xcb")
|
||||||
{
|
{
|
||||||
auto display = (Display *)pni->nativeResourceForWindow("display", window);
|
auto display = (Display *)pni->nativeResourceForWindow("display", window);
|
||||||
auto xid = (Window)winId();
|
auto xid = (Window)winId();
|
||||||
|
if (!context->init_Xlib(display, xid, config->display_device_index))
|
||||||
context->init_Xlib(display, xid, config->display_device_index);
|
{
|
||||||
|
context.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -116,10 +127,15 @@ void EmuCanvasVulkan::createContext()
|
||||||
|
|
||||||
QGuiApplication::sync();
|
QGuiApplication::sync();
|
||||||
paintEvent(nullptr);
|
paintEvent(nullptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuCanvasVulkan::tryLoadShader()
|
void EmuCanvasVulkan::tryLoadShader()
|
||||||
{
|
{
|
||||||
|
if (!context)
|
||||||
|
return;
|
||||||
|
|
||||||
simple_output.reset();
|
simple_output.reset();
|
||||||
shader_chain.reset();
|
shader_chain.reset();
|
||||||
shader_parameters_dialog.reset();
|
shader_parameters_dialog.reset();
|
||||||
|
@ -143,6 +159,9 @@ void EmuCanvasVulkan::tryLoadShader()
|
||||||
|
|
||||||
void EmuCanvasVulkan::shaderChanged()
|
void EmuCanvasVulkan::shaderChanged()
|
||||||
{
|
{
|
||||||
|
if (!context)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!config->use_shader)
|
if (!config->use_shader)
|
||||||
current_shader.clear();
|
current_shader.clear();
|
||||||
|
|
||||||
|
@ -248,7 +267,8 @@ void EmuCanvasVulkan::deinit()
|
||||||
|
|
||||||
if (ImGui::GetCurrentContext())
|
if (ImGui::GetCurrentContext())
|
||||||
{
|
{
|
||||||
context->wait_idle();
|
if (context)
|
||||||
|
context->wait_idle();
|
||||||
imgui_descriptor_pool.reset();
|
imgui_descriptor_pool.reset();
|
||||||
imgui_render_pass.reset();
|
imgui_render_pass.reset();
|
||||||
ImGui_ImplVulkan_Shutdown();
|
ImGui_ImplVulkan_Shutdown();
|
||||||
|
@ -305,6 +325,9 @@ void EmuCanvasVulkan::saveParameters(std::string filename)
|
||||||
|
|
||||||
void EmuCanvasVulkan::recreateUIAssets()
|
void EmuCanvasVulkan::recreateUIAssets()
|
||||||
{
|
{
|
||||||
|
if (!context)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ImGui::GetCurrentContext())
|
if (ImGui::GetCurrentContext())
|
||||||
{
|
{
|
||||||
context->wait_idle();
|
context->wait_idle();
|
||||||
|
|
|
@ -16,7 +16,7 @@ class EmuCanvasVulkan : public EmuCanvas
|
||||||
EmuCanvasVulkan(EmuConfig *config, QWidget *parent, QWidget *main_window);
|
EmuCanvasVulkan(EmuConfig *config, QWidget *parent, QWidget *main_window);
|
||||||
~EmuCanvasVulkan();
|
~EmuCanvasVulkan();
|
||||||
|
|
||||||
void createContext() override;
|
bool createContext() override;
|
||||||
void deinit() override;
|
void deinit() override;
|
||||||
void paintEvent(QPaintEvent *event) override;
|
void paintEvent(QPaintEvent *event) override;
|
||||||
void resizeEvent(QResizeEvent *event) override;
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
|
@ -73,7 +73,7 @@ void EmuMainWindow::destroyCanvas()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuMainWindow::createCanvas()
|
bool EmuMainWindow::createCanvas()
|
||||||
{
|
{
|
||||||
if (app->config->display_driver != "vulkan" &&
|
if (app->config->display_driver != "vulkan" &&
|
||||||
app->config->display_driver != "opengl" &&
|
app->config->display_driver != "opengl" &&
|
||||||
|
@ -91,8 +91,12 @@ void EmuMainWindow::createCanvas()
|
||||||
{
|
{
|
||||||
canvas = new EmuCanvasVulkan(app->config.get(), central_widget, this);
|
canvas = new EmuCanvasVulkan(app->config.get(), central_widget, this);
|
||||||
QGuiApplication::processEvents();
|
QGuiApplication::processEvents();
|
||||||
canvas->createContext();
|
if (!canvas->createContext())
|
||||||
}
|
{
|
||||||
|
delete canvas;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (app->config->display_driver == "opengl")
|
else if (app->config->display_driver == "opengl")
|
||||||
{
|
{
|
||||||
canvas = new EmuCanvasOpenGL(app->config.get(), central_widget, this);
|
canvas = new EmuCanvasOpenGL(app->config.get(), central_widget, this);
|
||||||
|
@ -106,7 +110,7 @@ void EmuMainWindow::createCanvas()
|
||||||
using_stacked_widget = true;
|
using_stacked_widget = true;
|
||||||
QGuiApplication::processEvents();
|
QGuiApplication::processEvents();
|
||||||
|
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -114,26 +118,41 @@ void EmuMainWindow::createCanvas()
|
||||||
{
|
{
|
||||||
canvas = new EmuCanvasVulkan(app->config.get(), this, this);
|
canvas = new EmuCanvasVulkan(app->config.get(), this, this);
|
||||||
QGuiApplication::processEvents();
|
QGuiApplication::processEvents();
|
||||||
canvas->createContext();
|
if (!canvas->createContext())
|
||||||
|
{
|
||||||
|
delete canvas;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (app->config->display_driver == "opengl")
|
else if (app->config->display_driver == "opengl")
|
||||||
{
|
{
|
||||||
canvas = new EmuCanvasOpenGL(app->config.get(), this, this);
|
canvas = new EmuCanvasOpenGL(app->config.get(), this, this);
|
||||||
QGuiApplication::processEvents();
|
QGuiApplication::processEvents();
|
||||||
app->emu_thread->runOnThread([&] { canvas->createContext(); }, true);
|
app->emu_thread->runOnThread([&] { canvas->createContext(); }, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
canvas = new EmuCanvasQt(app->config.get(), this, this);
|
canvas = new EmuCanvasQt(app->config.get(), this, this);
|
||||||
|
|
||||||
setCentralWidget(canvas);
|
setCentralWidget(canvas);
|
||||||
using_stacked_widget = false;
|
using_stacked_widget = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuMainWindow::recreateCanvas()
|
void EmuMainWindow::recreateCanvas()
|
||||||
{
|
{
|
||||||
app->suspendThread();
|
app->suspendThread();
|
||||||
destroyCanvas();
|
destroyCanvas();
|
||||||
createCanvas();
|
|
||||||
|
if (!createCanvas())
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this,
|
||||||
|
tr("Unable to Start Display Driver"),
|
||||||
|
tr("Unable to create a %1 context. Attempting to use qt.").arg(QString::fromUtf8(app->config->display_driver)));
|
||||||
|
app->config->display_driver = "qt";
|
||||||
|
createCanvas();
|
||||||
|
}
|
||||||
|
|
||||||
app->unsuspendThread();
|
app->unsuspendThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +545,7 @@ bool EmuMainWindow::event(QEvent *event)
|
||||||
minimized_pause = false;
|
minimized_pause = false;
|
||||||
app->unpause();
|
app->unpause();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case QEvent::MouseMove:
|
case QEvent::MouseMove:
|
||||||
|
@ -570,9 +589,9 @@ void EmuMainWindow::toggleFullscreen()
|
||||||
|
|
||||||
bool EmuMainWindow::eventFilter(QObject *watched, QEvent *event)
|
bool EmuMainWindow::eventFilter(QObject *watched, QEvent *event)
|
||||||
{
|
{
|
||||||
if (watched == canvas)
|
if (watched == canvas)
|
||||||
{
|
{
|
||||||
if (event->type() == QEvent::Resize)
|
if (event->type() == QEvent::Resize)
|
||||||
{
|
{
|
||||||
app->emu_thread->runOnThread([&] {
|
app->emu_thread->runOnThread([&] {
|
||||||
canvas->resizeEvent((QResizeEvent *)event);
|
canvas->resizeEvent((QResizeEvent *)event);
|
||||||
|
|
|
@ -20,7 +20,7 @@ class EmuMainWindow : public QMainWindow
|
||||||
~EmuMainWindow();
|
~EmuMainWindow();
|
||||||
|
|
||||||
void toggleFullscreen();
|
void toggleFullscreen();
|
||||||
void createCanvas();
|
bool createCanvas();
|
||||||
void destroyCanvas();
|
void destroyCanvas();
|
||||||
void recreateCanvas();
|
void recreateCanvas();
|
||||||
void setBypassCompositor(bool);
|
void setBypassCompositor(bool);
|
||||||
|
|
Loading…
Reference in New Issue