From 7ab71cafd3032c8025495249a1a18c7e39648431 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Mon, 4 Jul 2022 01:50:42 +0600 Subject: [PATCH] Working multimonitor --- src/config.c | 6 +++ src/include/86box/plat.h | 2 +- src/include/86box/ui.h | 2 + src/include/86box/vid_hercules.h | 5 +++ src/include/86box/video.h | 3 ++ src/qt/qt_d3d9renderer.cpp | 13 ++++--- src/qt/qt_d3d9renderer.hpp | 3 +- src/qt/qt_main.cpp | 16 +++++--- src/qt/qt_mainwindow.cpp | 64 ++++++++++++++++++++++++++------ src/qt/qt_mainwindow.hpp | 10 ++++- src/qt/qt_platform.cpp | 2 +- src/qt/qt_rendererstack.cpp | 23 ++++++++---- src/qt/qt_rendererstack.hpp | 9 +---- src/qt/qt_ui.cpp | 18 ++++++++- src/qt/wl_mouse.cpp | 18 +++++---- src/video/vid_hercules.c | 6 +++ src/video/vid_table.c | 12 ++++++ src/video/video.c | 5 +++ 18 files changed, 165 insertions(+), 52 deletions(-) diff --git a/src/config.c b/src/config.c index ca14b567a..a1f0916e2 100644 --- a/src/config.c +++ b/src/config.c @@ -932,6 +932,7 @@ load_video(void) voodoo_enabled = !!config_get_int(cat, "voodoo", 0); ibm8514_enabled = !!config_get_int(cat, "8514a", 0); xga_enabled = !!config_get_int(cat, "xga", 0); + herc_enabled = !!config_get_int(cat, "herc_enabled", 0); } @@ -2480,6 +2481,11 @@ save_video(void) else config_set_int(cat, "xga", xga_enabled); + if (herc_enabled == 0) + config_delete_var(cat, "herc_enabled"); + else + config_set_int(cat, "herc_enabled", herc_enabled); + delete_section_if_empty(cat); } diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 2c0ad054a..36c9a9d80 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -117,7 +117,7 @@ extern char *plat_vidapi_name(int api); extern int plat_setvid(int api); extern void plat_vidsize(int x, int y); extern void plat_setfullscreen(int on); -extern void plat_resize(int x, int y); +extern void plat_resize_monitor(int x, int y, int monitor_index); extern void plat_vidapi_enable(int enabled); extern void plat_vidapi_reload(void); extern void plat_vid_reload_options(void); diff --git a/src/include/86box/ui.h b/src/include/86box/ui.h index 6d3946d1c..847b8c706 100644 --- a/src/include/86box/ui.h +++ b/src/include/86box/ui.h @@ -62,6 +62,8 @@ extern void ui_check_menu_item(int id, int checked); extern wchar_t *ui_window_title(wchar_t *s); extern void ui_status_update(void); +extern void ui_init_monitor(int monitor_index); +extern void ui_deinit_monitor(int monitor_index); extern int ui_sb_find_part(int tag); extern void ui_sb_set_ready(int ready); extern void ui_sb_update_panes(void); diff --git a/src/include/86box/vid_hercules.h b/src/include/86box/vid_hercules.h index 53f45dd27..93785d9be 100644 --- a/src/include/86box/vid_hercules.h +++ b/src/include/86box/vid_hercules.h @@ -56,8 +56,13 @@ typedef struct { int cols[256][2][2]; uint8_t *vram; + int monitor_index; + int prev_monitor_index; } hercules_t; +#define VIDEO_MONITOR_PROLOGUE() { dev->prev_monitor_index = monitor_index_global; monitor_index_global = dev->monitor_index; } +#define VIDEO_MONITOR_EPILOGUE() { monitor_index_global = dev->prev_monitor_index; } + static void *hercules_init(const device_t *info); #endif /*VIDEO_HERCULES_H*/ diff --git a/src/include/86box/video.h b/src/include/86box/video.h index e6b1645a4..a26567eae 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -126,6 +126,7 @@ typedef struct monitor_t #define MONITORS_NUM 8 extern monitor_t monitors[MONITORS_NUM]; extern int monitor_index_global; +extern int herc_enabled; typedef rgb_t PALETTE[256]; @@ -239,6 +240,8 @@ extern void cgapal_rebuild(void); extern void hline(bitmap_t *b, int x1, int y, int x2, uint32_t col); extern void updatewindowsize(int x, int y); +extern void video_monitor_init(int); +extern void video_monitor_close(int); extern void video_init(void); extern void video_close(void); extern void video_reset_close(void); diff --git a/src/qt/qt_d3d9renderer.cpp b/src/qt/qt_d3d9renderer.cpp index ae322de8d..551b4d8ac 100644 --- a/src/qt/qt_d3d9renderer.cpp +++ b/src/qt/qt_d3d9renderer.cpp @@ -8,7 +8,7 @@ extern "C" #include <86box/video.h> } -D3D9Renderer::D3D9Renderer(QWidget *parent) +D3D9Renderer::D3D9Renderer(QWidget *parent, int monitor_index) : QWidget{parent}, RendererCommon() { QPalette pal = palette(); @@ -27,6 +27,7 @@ D3D9Renderer::D3D9Renderer(QWidget *parent) RendererCommon::parentWidget = parent; this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + this->m_monitor_index = monitor_index; } D3D9Renderer::~D3D9Renderer() @@ -138,8 +139,8 @@ void D3D9Renderer::resizeEvent(QResizeEvent *event) void D3D9Renderer::blit(int x, int y, int w, int h) { - if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || surfaceInUse) { - video_blit_complete(); + if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || surfaceInUse) { + video_blit_complete_monitor(m_monitor_index); return; } surfaceInUse = true; @@ -156,12 +157,12 @@ void D3D9Renderer::blit(int x, int y, int w, int h) } if (SUCCEEDED(d3d9surface->LockRect(&lockRect, &srcRect, 0))) { for (int y1 = 0; y1 < h; y1++) { - video_copy(((uint8_t*)lockRect.pBits) + (y1 * lockRect.Pitch), &(buffer32->line[y + y1][x]), w * 4); + video_copy(((uint8_t*)lockRect.pBits) + (y1 * lockRect.Pitch), &(monitors[m_monitor_index].target_buffer->line[y + y1][x]), w * 4); } - video_blit_complete(); + video_blit_complete_monitor(m_monitor_index); d3d9surface->UnlockRect(); } - else video_blit_complete(); + else video_blit_complete_monitor(m_monitor_index); surfaceInUse = false; QTimer::singleShot(0, this, [this] { this->update(); }); } diff --git a/src/qt/qt_d3d9renderer.hpp b/src/qt/qt_d3d9renderer.hpp index 21ef0ac59..d93781236 100644 --- a/src/qt/qt_d3d9renderer.hpp +++ b/src/qt/qt_d3d9renderer.hpp @@ -12,7 +12,7 @@ class D3D9Renderer : public QWidget, public RendererCommon { Q_OBJECT public: - explicit D3D9Renderer(QWidget *parent = nullptr); + explicit D3D9Renderer(QWidget *parent = nullptr, int monitor_index = 0); ~D3D9Renderer(); bool hasBlitFunc() override { return true; } void blit(int x, int y, int w, int h) override; @@ -39,6 +39,7 @@ private: std::atomic surfaceInUse{false}, finalized{false}; bool alreadyInitialized = false; + int m_monitor_index = 0; }; #endif // D3D9RENDERER_HPP diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 30e3df2ee..8700cd643 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -126,15 +126,17 @@ main_thread_fn() /* If needed, handle a screen resize. */ if (!atomic_flag_test_and_set(&doresize) && !video_fullscreen && !is_quit) { if (vid_resize & 2) - plat_resize(fixed_size_x, fixed_size_y); + plat_resize_monitor(fixed_size_x, fixed_size_y, 0); else - plat_resize(scrnsz_x, scrnsz_y); + plat_resize_monitor(scrnsz_x, scrnsz_y, 0); } } is_quit = 1; } +static std::thread* main_thread; + int main(int argc, char* argv[]) { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, false); @@ -258,7 +260,7 @@ int main(int argc, char* argv[]) { main_window->installEventFilter(&socket); socket.connectToServer(qgetenv("86BOX_MANAGER_SOCKET")); } - pc_reset_hard_init(); + //pc_reset_hard_init(); /* Set the PAUSE mode depending on the renderer. */ // plat_pause(0); @@ -284,13 +286,15 @@ int main(int argc, char* argv[]) { } /* Initialize the rendering window, or fullscreen. */ - auto main_thread = std::thread([] { - main_thread_fn(); + QTimer::singleShot(0, &app, [] + { + pc_reset_hard_init(); + main_thread = new std::thread(main_thread_fn); }); auto ret = app.exec(); cpu_thread_run = 0; - main_thread.join(); + main_thread->join(); socket.close(); return ret; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index c81540d7e..57725e866 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -139,7 +139,7 @@ MainWindow::MainWindow(QWidget *parent) : statusBar()->setVisible(!hide_status_bar); statusBar()->setStyleSheet("QStatusBar::item {border: None; } QStatusBar QLabel { margin-right: 2px; margin-bottom: 1px; }"); ui->toolBar->setVisible(!hide_tool_bar); - + renderers[0].reset(nullptr); auto toolbar_spacer = new QWidget(); toolbar_spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); ui->toolBar->addWidget(toolbar_spacer); @@ -494,6 +494,11 @@ MainWindow::MainWindow(QWidget *parent) : #endif setContextMenuPolicy(Qt::PreventContextMenu); + + connect(this, &MainWindow::initRendererMonitor, this, &MainWindow::initRendererMonitorSlot); + connect(this, &MainWindow::initRendererMonitorForNonQtThread, this, &MainWindow::initRendererMonitorSlot, Qt::BlockingQueuedConnection); + connect(this, &MainWindow::destroyRendererMonitor, this, &MainWindow::destroyRendererMonitorSlot); + connect(this, &MainWindow::destroyRendererMonitorForNonQtThread, this, &MainWindow::destroyRendererMonitorSlot, Qt::BlockingQueuedConnection); } void MainWindow::closeEvent(QCloseEvent *event) { @@ -534,10 +539,41 @@ void MainWindow::closeEvent(QCloseEvent *event) { ui->stackedWidget->mouse_exit_func(); ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software); + for (int i = 1; i < MONITORS_NUM; i++) { + if (renderers[i]) renderers[i]->close(); + } QApplication::processEvents(); event->accept(); } +void MainWindow::initRendererMonitorSlot(int monitor_index) +{ + auto& secondaryRenderer = this->renderers[monitor_index]; + secondaryRenderer.reset(new RendererStack(nullptr, monitor_index)); + if (secondaryRenderer) { + connect(this, &MainWindow::pollMouse, secondaryRenderer.get(), &RendererStack::mousePoll, Qt::DirectConnection); + connect(secondaryRenderer.get(), &RendererStack::rendererChanged, this, [this, monitor_index] + { + this->renderers[monitor_index]->show(); + }); + secondaryRenderer->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint); + secondaryRenderer->setWindowTitle(QObject::tr("86Box Monitor #") + QString::number(monitor_index + 1)); + if (vid_resize == 2) { + secondaryRenderer->setFixedSize(fixed_size_x, fixed_size_y); + } + secondaryRenderer->show(); + secondaryRenderer->switchRenderer((RendererStack::Renderer)vid_api); + secondaryRenderer->setWindowIcon(this->windowIcon()); + } +} + +void MainWindow::destroyRendererMonitorSlot(int monitor_index) +{ + if (this->renderers[monitor_index]) { + this->renderers[monitor_index].release()->deleteLater(); + } +} + MainWindow::~MainWindow() { delete ui; } @@ -554,15 +590,15 @@ void MainWindow::showEvent(QShowEvent *event) { + (hide_status_bar ? 0 : statusBar()->height()) + (hide_tool_bar ? 0 : ui->toolBar->height())); - scrnsz_x = fixed_size_x; - scrnsz_y = fixed_size_y; + monitors[0].mon_scrnsz_x = fixed_size_x; + monitors[0].mon_scrnsz_y = fixed_size_y; } else if (window_remember && vid_resize == 1) { ui->stackedWidget->setFixedSize(window_w, window_h); adjustSize(); ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); - scrnsz_x = window_w; - scrnsz_y = window_h; + monitors[0].mon_scrnsz_x = window_w; + monitors[0].mon_scrnsz_y = window_h; } } @@ -1360,7 +1396,7 @@ void MainWindow::on_actionFullscreen_triggered() { + (!hide_status_bar ? statusBar()->height() : 0) + (!hide_tool_bar ? ui->toolBar->height() : 0)); - emit resizeContents(scrnsz_x, scrnsz_y); + emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); } } else { if (video_fullscreen_first) @@ -1487,9 +1523,13 @@ void MainWindow::keyPressEvent(QKeyEvent* event) event->accept(); } -void MainWindow::blitToWidget(int x, int y, int w, int h) +void MainWindow::blitToWidget(int x, int y, int w, int h, int monitor_index) { - ui->stackedWidget->blit(x, y, w, h); + if (monitor_index >= 1) { + if (renderers[monitor_index]) renderers[monitor_index]->blit(x, y, w, h); + else video_blit_complete_monitor(monitor_index); + } + else ui->stackedWidget->blit(x, y, w, h); } void MainWindow::keyReleaseEvent(QKeyEvent* event) @@ -1537,7 +1577,7 @@ void MainWindow::on_actionResizable_window_triggered(bool checked) { ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api); ui->menuWindow_scale_factor->setEnabled(! checked); - emit resizeContents(scrnsz_x, scrnsz_y); + emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); } static void @@ -1770,7 +1810,7 @@ void MainWindow::on_actionHiDPI_scaling_triggered() { dpi_scale ^= 1; ui->actionHiDPI_scaling->setChecked(dpi_scale); - emit resizeContents(scrnsz_x, scrnsz_y); + emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); } void MainWindow::on_actionHide_status_bar_triggered() @@ -1786,7 +1826,7 @@ void MainWindow::on_actionHide_status_bar_triggered() } else { int vid_resize_orig = vid_resize; vid_resize = 0; - emit resizeContents(scrnsz_x, scrnsz_y); + emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); vid_resize = vid_resize_orig; } } @@ -1804,7 +1844,7 @@ void MainWindow::on_actionHide_tool_bar_triggered() } else { int vid_resize_orig = vid_resize; vid_resize = 0; - emit resizeContents(scrnsz_x, scrnsz_y); + emit resizeContents(monitors[0].mon_scrnsz_x, monitors[0].mon_scrnsz_y); vid_resize = vid_resize_orig; } } diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index ffecdd773..026d86802 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -9,6 +9,7 @@ #include class MediaMenu; +class RendererStack; namespace Ui { class MainWindow; @@ -26,7 +27,7 @@ public: void showMessage(const QString& header, const QString& message); void getTitle(wchar_t* title); - void blitToWidget(int x, int y, int w, int h); + void blitToWidget(int x, int y, int w, int h, int monitor_index); QSize getRenderWidgetSize(); void setSendKeyboardInput(bool enabled); signals: @@ -40,6 +41,10 @@ signals: void updateStatusBarTip(int tag); void updateMenuResizeOptions(); void updateWindowRememberOption(); + void initRendererMonitor(int monitor_index); + void destroyRendererMonitor(int monitor_index); + void initRendererMonitorForNonQtThread(int monitor_index); + void destroyRendererMonitorForNonQtThread(int monitor_index); void setTitle(const QString& title); void setFullscreen(bool state); @@ -51,6 +56,8 @@ public slots: void showSettings(); void hardReset(); void togglePause(); + void initRendererMonitorSlot(int monitor_index); + void destroyRendererMonitorSlot(int monitor_index); private slots: void on_actionFullscreen_triggered(); void on_actionSettings_triggered(); @@ -118,6 +125,7 @@ protected: private: Ui::MainWindow *ui; std::unique_ptr status; + std::array, 8> renderers; std::shared_ptr mm; #ifdef Q_OS_MACOS diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 2bca0248e..42d839ecf 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -52,7 +52,7 @@ extern MainWindow* main_window; QElapsedTimer elapsed_timer; static std::atomic_int blitmx_contention = 0; -static std::mutex blitmx; +static std::recursive_mutex blitmx; class CharPointer { public: diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index c7f1984a7..fd477416b 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -51,14 +51,21 @@ extern "C" { double mouse_sensitivity = 1.0; } +struct mouseinputdata { + int deltax, deltay, deltaz; + int mousebuttons; +}; +static mouseinputdata mousedata; + extern "C" void macos_poll_mouse(); extern MainWindow *main_window; -RendererStack::RendererStack(QWidget *parent) +RendererStack::RendererStack(QWidget *parent, int monitor_index) : QStackedWidget(parent) , ui(new Ui::RendererStack) { ui->setupUi(this); + m_monitor_index = monitor_index; #if defined __unix__ && !defined __HAIKU__ char *mouse_type = getenv("EMU86BOX_MOUSE"), auto_mouse_type[16]; if (!mouse_type || (mouse_type[0] == '\0') || !stricmp(mouse_type, "auto")) { @@ -313,7 +320,7 @@ RendererStack::createRenderer(Renderer renderer) case Renderer::Direct3D9: { this->createWinId(); - auto hw = new D3D9Renderer(this); + auto hw = new D3D9Renderer(this, m_monitor_index); rendererWindow = hw; connect(hw, &D3D9Renderer::error, this, [this](QString str) { @@ -398,14 +405,14 @@ RendererStack::createRenderer(Renderer renderer) void RendererStack::blitDummy(int x, int y, int w, int h) { - video_blit_complete(); + video_blit_complete_monitor(m_monitor_index); blitDummied = true; } void RendererStack::blitRenderer(int x, int y, int w, int h) { - if (blitDummied) { blitDummied = false; video_blit_complete(); return; } + if (blitDummied) { blitDummied = false; video_blit_complete_monitor(m_monitor_index); return; } directBlitting = true; rendererWindow->blit(x, y, w, h); directBlitting = false; @@ -415,8 +422,8 @@ RendererStack::blitRenderer(int x, int y, int w, int h) void RendererStack::blitCommon(int x, int y, int w, int h) { - if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || imagebufs.empty() || std::get(imagebufs[currentBuf])->test_and_set() || blitDummied) { - video_blit_complete(); + if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (monitors[m_monitor_index].target_buffer == NULL) || imagebufs.empty() || std::get(imagebufs[currentBuf])->test_and_set() || blitDummied) { + video_blit_complete_monitor(m_monitor_index); return; } sx = x; @@ -426,13 +433,13 @@ RendererStack::blitCommon(int x, int y, int w, int h) uint8_t *imagebits = std::get(imagebufs[currentBuf]); for (int y1 = y; y1 < (y + h); y1++) { auto scanline = imagebits + (y1 * rendererWindow->getBytesPerRow()) + (x * 4); - video_copy(scanline, &(buffer32->line[y1][x]), w * 4); + video_copy(scanline, &(monitors[m_monitor_index].target_buffer->line[y1][x]), w * 4); } if (screenshots) { video_screenshot((uint32_t *) imagebits, x, y, 2048); } - video_blit_complete(); + video_blit_complete_monitor(m_monitor_index); emit blitToRenderer(currentBuf, sx, sy, sw, sh); currentBuf = (currentBuf + 1) % imagebufs.size(); } diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index ab8e160ec..bc6895f15 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -23,7 +23,7 @@ class RendererStack : public QStackedWidget { Q_OBJECT public: - explicit RendererStack(QWidget *parent = nullptr); + explicit RendererStack(QWidget *parent = nullptr, int monitor_index = 0); ~RendererStack(); void mousePressEvent(QMouseEvent *event) override; @@ -87,16 +87,11 @@ private: Ui::RendererStack *ui; - struct mouseinputdata { - int deltax, deltay, deltaz; - int mousebuttons; - }; - mouseinputdata mousedata; - int x, y, w, h, sx, sy, sw, sh; int currentBuf = 0; int isMouseDown = 0; + int m_monitor_index = 0; std::vector> imagebufs; diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index 207e57655..329132557 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -57,14 +57,14 @@ wchar_t* ui_window_title(wchar_t* str) extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index) { - main_window->blitToWidget(x, y, w, h); + main_window->blitToWidget(x, y, w, h, monitor_index); } void mouse_poll() { main_window->pollMouse(); } -void plat_resize(int w, int h) { +void plat_resize_monitor(int w, int h, int monitor_index) { main_window->resizeContents(w, h); } @@ -98,6 +98,20 @@ int ui_msgbox_header(int flags, void *header, void* message) { return 0; } +void ui_init_monitor(int monitor_index) { + if (QThread::currentThread() == main_window->thread()) { + emit main_window->initRendererMonitor(monitor_index); + } + else emit main_window->initRendererMonitorForNonQtThread(monitor_index); +} + +void ui_deinit_monitor(int monitor_index) { + if (QThread::currentThread() == main_window->thread()) { + emit main_window->destroyRendererMonitor(monitor_index); + } + else emit main_window->destroyRendererMonitorForNonQtThread(monitor_index); +} + int ui_msgbox(int flags, void *message) { return ui_msgbox_header(flags, nullptr, message); } diff --git a/src/qt/wl_mouse.cpp b/src/qt/wl_mouse.cpp index 916fe2338..9e487cde3 100644 --- a/src/qt/wl_mouse.cpp +++ b/src/qt/wl_mouse.cpp @@ -36,6 +36,7 @@ static zwp_pointer_constraints_v1* conf_pointer_interface = nullptr; static zwp_locked_pointer_v1* conf_pointer = nullptr; static int rel_mouse_x = 0, rel_mouse_y = 0; +static bool wl_init_ok = false; void rel_mouse_event(void* data, zwp_relative_pointer_v1* zwp_relative_pointer_v1, uint32_t tstmp, uint32_t tstmpl, wl_fixed_t dx, wl_fixed_t dy, wl_fixed_t dx_real, wl_fixed_t dy_real) { @@ -92,15 +93,18 @@ static const struct wl_registry_listener registry_listener = { void wl_init() { - wl_display* display = (wl_display*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display"); - if (display) - { - auto registry = wl_display_get_registry(display); - if (registry) + if (!wl_init_ok) { + wl_display* display = (wl_display*)QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display"); + if (display) { - wl_registry_add_listener(registry, ®istry_listener, nullptr); - wl_display_roundtrip(display); + auto registry = wl_display_get_registry(display); + if (registry) + { + wl_registry_add_listener(registry, ®istry_listener, nullptr); + wl_display_roundtrip(display); + } } + wl_init_ok = true; } } diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index df21c47f3..8e1ab4f8b 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -66,6 +66,7 @@ hercules_out(uint16_t addr, uint8_t val, void *priv) hercules_t *dev = (hercules_t *)priv; uint8_t old; + VIDEO_MONITOR_PROLOGUE() switch (addr) { case 0x03b0: case 0x03b2: @@ -146,6 +147,8 @@ hercules_out(uint16_t addr, uint8_t val, void *priv) default: break; } + + VIDEO_MONITOR_EPILOGUE() } @@ -295,6 +298,7 @@ hercules_poll(void *priv) int drawcursor; uint32_t *p; + VIDEO_MONITOR_PROLOGUE() ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff; if (! dev->linepos) { @@ -516,6 +520,7 @@ hercules_poll(void *priv) } } } + VIDEO_MONITOR_EPILOGUE() } @@ -527,6 +532,7 @@ hercules_init(const device_t *info) dev = (hercules_t *)malloc(sizeof(hercules_t)); memset(dev, 0x00, sizeof(hercules_t)); + dev->monitor_index = monitor_index_global; overscan_x = 16; overscan_y = 28; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index c38154388..68822679d 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -275,6 +275,10 @@ vid_table_log(const char *fmt, ...) void video_reset_close(void) { + for (int i = 1; i < MONITORS_NUM; i++) + video_monitor_close(i); + + monitor_index_global = 0; video_inform(VIDEO_FLAG_TYPE_NONE, &timing_default); was_reset = 0; } @@ -321,6 +325,7 @@ video_reset(int card) vid_table_log("VIDEO: reset (gfxcard=%d, internal=%d)\n", card, machine_has_flags(machine, MACHINE_VIDEO) ? 1 : 0); + monitor_index_global = 0; loadfont("roms/video/mda/mda.rom", 0); /* Do not initialize internal cards here. */ @@ -332,6 +337,13 @@ video_reset(int card) /* Initialize the video card. */ device_add(video_cards[card].device); + + if (herc_enabled) { + video_monitor_init(1); + monitor_index_global = 1; + device_add(&hercules_device); + monitor_index_global = 0; + } } /* Enable the Voodoo if configured. */ diff --git a/src/video/video.c b/src/video/video.c index efedfbb09..419b9b82a 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -68,6 +68,7 @@ #include <86box/timer.h> #include <86box/path.h> #include <86box/plat.h> +#include <86box/ui.h> #include <86box/thread.h> #include <86box/video.h> #include <86box/vid_svga.h> @@ -101,6 +102,7 @@ static uint32_t cga_2_table[16]; static uint8_t thread_run = 0; monitor_t monitors[MONITORS_NUM]; int monitor_index_global = 0; +int herc_enabled = 0; #ifdef _WIN32 void * __cdecl (*video_copy)(void *_Dst, const void *_Src, size_t _Size) = memcpy; @@ -926,8 +928,10 @@ video_monitor_init(int index) monitors[index].mon_blit_data_ptr->blit_complete = thread_create_event(); monitors[index].mon_blit_data_ptr->buffer_not_in_use = thread_create_event(); monitors[index].mon_blit_data_ptr->thread_run = 1; + monitors[index].mon_blit_data_ptr->monitor_index = index; monitors[index].mon_pal_lookup = calloc(sizeof(uint32_t), 256); monitors[index].mon_cga_palette = calloc(1, sizeof(int)); + if (index >= 1) ui_init_monitor(index); thread_create(blit_thread, monitors[index].mon_blit_data_ptr); } @@ -938,6 +942,7 @@ video_monitor_close(int monitor_index) monitors[monitor_index].mon_blit_data_ptr->thread_run = 0; thread_set_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread); thread_wait(monitors[monitor_index].mon_blit_data_ptr->blit_thread); + if (monitor_index >= 1) ui_deinit_monitor(monitor_index); thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->buffer_not_in_use); thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->blit_complete); thread_destroy_event(monitors[monitor_index].mon_blit_data_ptr->wake_blit_thread);