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 draw() = 0;
|
||||
void paintEvent(QPaintEvent *) override = 0;
|
||||
virtual void createContext() {}
|
||||
virtual bool createContext() { return false; }
|
||||
virtual void recreateUIAssets() {}
|
||||
void output(uint8_t *buffer, int width, int height, QImage::Format format, int bytes_per_line, double frame_rate);
|
||||
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);
|
||||
}
|
||||
|
||||
void EmuCanvasOpenGL::createContext()
|
||||
bool EmuCanvasOpenGL::createContext()
|
||||
{
|
||||
if (context)
|
||||
return;
|
||||
return true;
|
||||
|
||||
auto platform = QGuiApplication::platformName();
|
||||
auto pni = QGuiApplication::platformNativeInterface();
|
||||
|
@ -139,7 +139,11 @@ void EmuCanvasOpenGL::createContext()
|
|||
int s = devicePixelRatio();
|
||||
|
||||
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");
|
||||
context.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
context.reset(wayland_egl_context);
|
||||
}
|
||||
|
@ -150,7 +154,11 @@ void EmuCanvasOpenGL::createContext()
|
|||
|
||||
auto glx_context = new GTKGLXContext();
|
||||
if (!glx_context->attach(display, xid))
|
||||
{
|
||||
printf("Couldn't attach to X11 window.\n");
|
||||
context.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
context.reset(glx_context);
|
||||
}
|
||||
|
@ -160,7 +168,8 @@ void EmuCanvasOpenGL::createContext()
|
|||
if (!wgl_context->attach((HWND)hwnd))
|
||||
{
|
||||
printf("Couldn't attach to context\n");
|
||||
return;
|
||||
context.reset();
|
||||
return false;
|
||||
}
|
||||
context.reset(wgl_context);
|
||||
#endif
|
||||
|
@ -194,6 +203,8 @@ void EmuCanvasOpenGL::createContext()
|
|||
context->swap_interval(config->enable_vsync ? 1 : 0);
|
||||
QGuiApplication::sync();
|
||||
paintEvent(nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EmuCanvasOpenGL::loadShaders()
|
||||
|
|
|
@ -14,7 +14,7 @@ class EmuCanvasOpenGL : public EmuCanvas
|
|||
EmuCanvasOpenGL(EmuConfig *config, QWidget *parent, QWidget *main_window);
|
||||
~EmuCanvasOpenGL();
|
||||
|
||||
void createContext() override;
|
||||
bool createContext() override;
|
||||
void deinit() override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
|
|
|
@ -75,10 +75,10 @@ bool EmuCanvasVulkan::initImGui()
|
|||
return true;
|
||||
}
|
||||
|
||||
void EmuCanvasVulkan::createContext()
|
||||
bool EmuCanvasVulkan::createContext()
|
||||
{
|
||||
if (simple_output)
|
||||
return;
|
||||
if (context)
|
||||
return true;
|
||||
|
||||
platform = QGuiApplication::platformName();
|
||||
auto pni = QGuiApplication::platformNativeInterface();
|
||||
|
@ -89,7 +89,11 @@ void EmuCanvasVulkan::createContext()
|
|||
|
||||
#ifdef _WIN32
|
||||
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
|
||||
if (platform == "wayland")
|
||||
{
|
||||
|
@ -98,14 +102,21 @@ void EmuCanvasVulkan::createContext()
|
|||
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()) });
|
||||
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")
|
||||
{
|
||||
auto display = (Display *)pni->nativeResourceForWindow("display", window);
|
||||
auto xid = (Window)winId();
|
||||
|
||||
context->init_Xlib(display, xid, config->display_device_index);
|
||||
if (!context->init_Xlib(display, xid, config->display_device_index))
|
||||
{
|
||||
context.reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -116,10 +127,15 @@ void EmuCanvasVulkan::createContext()
|
|||
|
||||
QGuiApplication::sync();
|
||||
paintEvent(nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EmuCanvasVulkan::tryLoadShader()
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
simple_output.reset();
|
||||
shader_chain.reset();
|
||||
shader_parameters_dialog.reset();
|
||||
|
@ -143,6 +159,9 @@ void EmuCanvasVulkan::tryLoadShader()
|
|||
|
||||
void EmuCanvasVulkan::shaderChanged()
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
if (!config->use_shader)
|
||||
current_shader.clear();
|
||||
|
||||
|
@ -248,7 +267,8 @@ void EmuCanvasVulkan::deinit()
|
|||
|
||||
if (ImGui::GetCurrentContext())
|
||||
{
|
||||
context->wait_idle();
|
||||
if (context)
|
||||
context->wait_idle();
|
||||
imgui_descriptor_pool.reset();
|
||||
imgui_render_pass.reset();
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
|
@ -305,6 +325,9 @@ void EmuCanvasVulkan::saveParameters(std::string filename)
|
|||
|
||||
void EmuCanvasVulkan::recreateUIAssets()
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
if (ImGui::GetCurrentContext())
|
||||
{
|
||||
context->wait_idle();
|
||||
|
|
|
@ -16,7 +16,7 @@ class EmuCanvasVulkan : public EmuCanvas
|
|||
EmuCanvasVulkan(EmuConfig *config, QWidget *parent, QWidget *main_window);
|
||||
~EmuCanvasVulkan();
|
||||
|
||||
void createContext() override;
|
||||
bool createContext() override;
|
||||
void deinit() override;
|
||||
void paintEvent(QPaintEvent *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" &&
|
||||
app->config->display_driver != "opengl" &&
|
||||
|
@ -91,8 +91,12 @@ void EmuMainWindow::createCanvas()
|
|||
{
|
||||
canvas = new EmuCanvasVulkan(app->config.get(), central_widget, this);
|
||||
QGuiApplication::processEvents();
|
||||
canvas->createContext();
|
||||
}
|
||||
if (!canvas->createContext())
|
||||
{
|
||||
delete canvas;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (app->config->display_driver == "opengl")
|
||||
{
|
||||
canvas = new EmuCanvasOpenGL(app->config.get(), central_widget, this);
|
||||
|
@ -106,7 +110,7 @@ void EmuMainWindow::createCanvas()
|
|||
using_stacked_widget = true;
|
||||
QGuiApplication::processEvents();
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -114,26 +118,41 @@ void EmuMainWindow::createCanvas()
|
|||
{
|
||||
canvas = new EmuCanvasVulkan(app->config.get(), this, this);
|
||||
QGuiApplication::processEvents();
|
||||
canvas->createContext();
|
||||
if (!canvas->createContext())
|
||||
{
|
||||
delete canvas;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (app->config->display_driver == "opengl")
|
||||
{
|
||||
canvas = new EmuCanvasOpenGL(app->config.get(), this, this);
|
||||
QGuiApplication::processEvents();
|
||||
app->emu_thread->runOnThread([&] { canvas->createContext(); }, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
canvas = new EmuCanvasQt(app->config.get(), this, this);
|
||||
|
||||
setCentralWidget(canvas);
|
||||
using_stacked_widget = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EmuMainWindow::recreateCanvas()
|
||||
{
|
||||
app->suspendThread();
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -526,7 +545,7 @@ bool EmuMainWindow::event(QEvent *event)
|
|||
minimized_pause = false;
|
||||
app->unpause();
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
|
@ -570,9 +589,9 @@ void EmuMainWindow::toggleFullscreen()
|
|||
|
||||
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([&] {
|
||||
canvas->resizeEvent((QResizeEvent *)event);
|
||||
|
|
|
@ -20,7 +20,7 @@ class EmuMainWindow : public QMainWindow
|
|||
~EmuMainWindow();
|
||||
|
||||
void toggleFullscreen();
|
||||
void createCanvas();
|
||||
bool createCanvas();
|
||||
void destroyCanvas();
|
||||
void recreateCanvas();
|
||||
void setBypassCompositor(bool);
|
||||
|
|
Loading…
Reference in New Issue