From 0f5ed59e50d2aa2553422de9165220efdf71fe67 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Thu, 8 Jul 2021 23:37:13 +1000 Subject: [PATCH] Replace pDsp with WindowInfo --- pcsx2/DEV9/DEV9.cpp | 2 +- pcsx2/DEV9/DEV9.h | 2 +- pcsx2/GS/GS.cpp | 297 +---------------------- pcsx2/GS/GS.h | 5 +- pcsx2/GS/Renderers/Common/GSRenderer.cpp | 34 +-- pcsx2/GS/Window/GSWnd.h | 40 +-- pcsx2/GS/Window/GSWndDX.cpp | 173 +------------ pcsx2/GS/Window/GSWndDX.h | 24 +- pcsx2/GS/Window/GSWndEGL.cpp | 167 +++---------- pcsx2/GS/Window/GSWndEGL.h | 50 +--- pcsx2/GS/Window/GSWndWGL.cpp | 141 +---------- pcsx2/GS/Window/GSWndWGL.h | 28 +-- pcsx2/MTGS.cpp | 4 +- pcsx2/PAD/Linux/PAD.cpp | 7 +- pcsx2/PAD/Linux/PAD.h | 6 +- pcsx2/PAD/Linux/keyboard.cpp | 3 + pcsx2/PAD/Linux/linux.cpp | 13 +- pcsx2/PAD/Windows/PAD.cpp | 96 +++----- pcsx2/PAD/Windows/PAD.h | 5 +- pcsx2/SPU2/Windows/CfgHelpers.cpp | 10 +- pcsx2/SPU2/spu2.cpp | 7 +- pcsx2/SPU2/spu2.h | 2 +- pcsx2/System/SysCoreThread.cpp | 11 +- pcsx2/USB/USB.cpp | 39 +-- pcsx2/USB/USB.h | 4 +- pcsx2/USB/USBNull.cpp | 2 +- pcsx2/gui/App.h | 6 +- pcsx2/gui/AppMain.cpp | 39 +-- pcsx2/gui/Dialogs/GSDumpDialog.cpp | 2 +- pcsx2/gui/FrameForGS.cpp | 183 ++++++++++++++ pcsx2/gui/GSFrame.h | 22 ++ 31 files changed, 424 insertions(+), 1000 deletions(-) diff --git a/pcsx2/DEV9/DEV9.cpp b/pcsx2/DEV9/DEV9.cpp index bfa9a95401..b2fb4e08ea 100644 --- a/pcsx2/DEV9/DEV9.cpp +++ b/pcsx2/DEV9/DEV9.cpp @@ -183,7 +183,7 @@ void DEV9shutdown() delete dev9.ata; } -s32 DEV9open(void* pDsp) +s32 DEV9open() { DevCon.WriteLn("DEV9: DEV9open"); LoadConf(); diff --git a/pcsx2/DEV9/DEV9.h b/pcsx2/DEV9/DEV9.h index a763830fc2..63adf22e20 100644 --- a/pcsx2/DEV9/DEV9.h +++ b/pcsx2/DEV9/DEV9.h @@ -727,7 +727,7 @@ extern void DEV9configure(); void FLASHinit(); s32 DEV9init(); void DEV9close(); -s32 DEV9open(void* pDsp); +s32 DEV9open(); void DEV9shutdown(); u32 FLASHread32(u32 addr, int size); void FLASHwrite32(u32 addr, u32 value, int size); diff --git a/pcsx2/GS/GS.cpp b/pcsx2/GS/GS.cpp index f63ded4fef..edcef7cc23 100644 --- a/pcsx2/GS/GS.cpp +++ b/pcsx2/GS/GS.cpp @@ -143,10 +143,9 @@ void GSclose() } } -int _GSopen(void** dsp, const char* title, GSRendererType renderer, int threads = -1) +int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, int threads = -1) { GSDevice* dev = NULL; - ASSERT(dsp != nullptr); // Fresh start up or config file changed if (renderer == GSRendererType::Undefined) @@ -187,23 +186,8 @@ int _GSopen(void** dsp, const char* title, GSRendererType renderer, int threads case GSRendererType::OGL_HW: case GSRendererType::OGL_SW: #if defined(__unix__) - // Note: EGL code use GLX otherwise maybe it could be also compatible with Windows - // Yes OpenGL code isn't complicated enough ! - switch (GSWndEGL::SelectPlatform()) - { -#if GS_EGL_X11 - case EGL_PLATFORM_X11_KHR: - wnds.push_back(std::make_shared()); - break; -#endif -#if GS_EGL_WL - case EGL_PLATFORM_WAYLAND_KHR: - wnds.push_back(std::make_shared()); - break; -#endif - default: - break; - } + if (std::shared_ptr wnd = GSWndEGL::CreateForPlatform(wi); wnd) + wnds.push_back(std::move(wnd)); #elif defined(__APPLE__) // No windows available for macOS at the moment #else @@ -220,17 +204,14 @@ int _GSopen(void** dsp, const char* title, GSRendererType renderer, int threads #endif break; } -#if defined(__unix__) - void* win_handle = (void*)((uptr*)(dsp) + 1); -#else - void* win_handle = *dsp; -#endif for (auto& wnd : wnds) { try { - wnd->Attach(win_handle, false); + if (!wnd->Attach(wi)) + continue; + window = wnd; // Previous code will throw if window isn't supported break; } @@ -353,7 +334,7 @@ void GSosdMonitor(const char* key, const char* value, uint32 color) s_gs->m_dev->m_osd.Monitor(key, value); } -int GSopen2(void** dsp, uint32 flags) +int GSopen2(const WindowInfo& wi, uint32 flags) { static bool stored_toggle_state = false; const bool toggle_state = !!(flags & 4); @@ -395,7 +376,7 @@ int GSopen2(void** dsp, uint32 flags) } stored_toggle_state = toggle_state; - int retval = _GSopen(dsp, "", current_renderer); + int retval = _GSopen(wi, "", current_renderer); gsopen_done = true; @@ -545,23 +526,6 @@ void GSvsync(int field) { try { -#ifdef _WIN32 - - if (s_gs->m_wnd->IsManaged()) - { - MSG msg; - - memset(&msg, 0, sizeof(msg)); - - while (msg.message != WM_QUIT && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - -#endif - s_gs->VSync(field); } catch (GSRecoverableError) @@ -792,251 +756,6 @@ void GSsetExclusive(int enabled) } } -#if defined(__unix__) || defined(__APPLE__) - -inline unsigned long timeGetTime() -{ - struct timespec t; - clock_gettime(CLOCK_REALTIME, &t); - return (unsigned long)(t.tv_sec * 1000 + t.tv_nsec / 1000000); -} - -// Note -void GSReplay(char* lpszCmdLine, int renderer) -{ - GLLoader::in_replayer = true; - // Required by multithread driver -#ifndef __APPLE__ - XInitThreads(); -#endif - - GSinit(); - - GSRendererType m_renderer; - // Allow to easyly switch between SW/HW renderer -> this effectively removes the ability to select the renderer by function args - m_renderer = static_cast(theApp.GetConfigI("Renderer")); - - if (m_renderer != GSRendererType::OGL_HW && m_renderer != GSRendererType::OGL_SW) - { - fprintf(stderr, "wrong renderer selected %d\n", static_cast(m_renderer)); - return; - } - - struct Packet - { - uint8 type, param; - uint32 size, addr; - std::vector buff; - }; - - std::list packets; - std::vector buff; - uint8 regs[0x2000]; - - GSsetBaseMem(regs); - - s_vsync = theApp.GetConfigI("vsync"); - int finished = theApp.GetConfigI("linux_replay"); - bool repack_dump = (finished < 0); - - if (theApp.GetConfigI("dump")) - { - fprintf(stderr, "Dump is enabled. Replay will be disabled\n"); - finished = 1; - } - - long frame_number = 0; - - void* hWnd = NULL; - int err = _GSopen((void**)&hWnd, "", m_renderer); - if (err != 0) - { - fprintf(stderr, "Error failed to GSopen\n"); - return; - } - if (s_gs->m_wnd == NULL) - return; - - { // Read .gs content - std::string f(lpszCmdLine); - bool is_xz = (f.size() >= 4) && (f.compare(f.size() - 3, 3, ".xz") == 0); - if (is_xz) - f.replace(f.end() - 6, f.end(), "_repack.gs"); - else - f.replace(f.end() - 3, f.end(), "_repack.gs"); - - GSDumpFile* file = is_xz ? (GSDumpFile*)new GSDumpLzma(lpszCmdLine, repack_dump ? f.c_str() : nullptr) : (GSDumpFile*)new GSDumpRaw(lpszCmdLine, repack_dump ? f.c_str() : nullptr); - - uint32 crc; - file->Read(&crc, 4); - GSsetGameCRC(crc, 0); - - freezeData fd; - file->Read(&fd.size, 4); - fd.data = new u8[fd.size]; - file->Read(fd.data, fd.size); - - GSfreeze(FreezeAction::Load, &fd); - delete[] fd.data; - - file->Read(regs, 0x2000); - - uint8 type; - while (file->Read(&type, 1)) - { - Packet* p = new Packet(); - - p->type = type; - - switch (type) - { - case 0: - file->Read(&p->param, 1); - file->Read(&p->size, 4); - - switch (p->param) - { - case 0: - p->buff.resize(0x4000); - p->addr = 0x4000 - p->size; - file->Read(&p->buff[p->addr], p->size); - break; - case 1: - case 2: - case 3: - p->buff.resize(p->size); - file->Read(&p->buff[0], p->size); - break; - } - - break; - - case 1: - file->Read(&p->param, 1); - frame_number++; - - break; - - case 2: - file->Read(&p->size, 4); - - break; - - case 3: - p->buff.resize(0x2000); - - file->Read(&p->buff[0], 0x2000); - - break; - } - - packets.push_back(p); - - if (repack_dump && frame_number > -finished) - break; - } - - delete file; - } - - sleep(2); - - - frame_number = 0; - - // Init vsync stuff - GSvsync(1); - - while (finished > 0) - { - for (auto i = packets.begin(); i != packets.end(); i++) - { - Packet* p = *i; - - switch (p->type) - { - case 0: - - switch (p->param) - { - case 0: - GSgifTransfer1(&p->buff[0], p->addr); - break; - case 1: - GSgifTransfer2(&p->buff[0], p->size / 16); - break; - case 2: - GSgifTransfer3(&p->buff[0], p->size / 16); - break; - case 3: - GSgifTransfer(&p->buff[0], p->size / 16); - break; - } - - break; - - case 1: - - GSvsync(p->param); - frame_number++; - - break; - - case 2: - - if (buff.size() < p->size) - buff.resize(p->size); - - GSreadFIFO2(&buff[0], p->size / 16); - - break; - - case 3: - - memcpy(regs, &p->buff[0], 0x2000); - - break; - } - } - - if (finished >= 200) - { - ; // Nop for Nvidia Profiler - } - else if (finished > 90) - { - sleep(1); - } - else - { - finished--; - } - } - - static_cast(s_gs->m_dev)->GenerateProfilerData(); - -#ifdef ENABLE_OGL_DEBUG_MEM_BW - unsigned long total_frame_nb = std::max(1l, frame_number) << 10; - fprintf(stderr, "memory bandwith. T: %f KB/f. V: %f KB/f. U: %f KB/f\n", - (float)g_real_texture_upload_byte / (float)total_frame_nb, - (float)g_vertex_upload_byte / (float)total_frame_nb, - (float)g_uniform_upload_byte / (float)total_frame_nb); -#endif - - for (auto i = packets.begin(); i != packets.end(); i++) - { - delete *i; - } - - packets.clear(); - - sleep(2); - - GSclose(); - GSshutdown(); -} -#endif - std::string format(const char* fmt, ...) { va_list args; diff --git a/pcsx2/GS/GS.h b/pcsx2/GS/GS.h index be437caee8..f7b595bc14 100644 --- a/pcsx2/GS/GS.h +++ b/pcsx2/GS/GS.h @@ -1765,6 +1765,7 @@ enum class CRCHackLevel : int8 }; struct HostKeyEvent; +struct WindowInfo; #ifdef ENABLE_ACCURATE_BUFFER_EMULATION const GSVector2i default_rt_size(2048, 2048); @@ -1776,10 +1777,10 @@ void GSsetBaseMem(uint8* mem); int GSinit(); void GSshutdown(); void GSclose(); -int _GSopen(void** dsp, const char* title, GSRendererType renderer, int threads); +int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, int threads); void GSosdLog(const char* utf8, uint32 color); void GSosdMonitor(const char* key, const char* value, uint32 color); -int GSopen2(void** dsp, uint32 flags); +int GSopen2(const WindowInfo & wi, uint32 flags); void GSreset(); void GSgifSoftReset(uint32 mask); void GSwriteCSR(uint32 csr); diff --git a/pcsx2/GS/Renderers/Common/GSRenderer.cpp b/pcsx2/GS/Renderers/Common/GSRenderer.cpp index 229cfb7b4e..4c83fb6c2b 100644 --- a/pcsx2/GS/Renderers/Common/GSRenderer.cpp +++ b/pcsx2/GS/Renderers/Common/GSRenderer.cpp @@ -399,10 +399,6 @@ void GSRenderer::VSync(int field) std::string s; #ifdef GSTITLEINFO_API_FORCE_VERBOSE - if (1) //force verbose reply -#else - if (m_wnd->IsManaged()) -#endif { //GS owns the window's title, be verbose. static const char* aspect_ratio_names[static_cast(AspectRatioType::MaxCount)] = { "Stretch", "4:3", "16:9" }; @@ -438,41 +434,29 @@ void GSRenderer::VSync(int field) s += format(" | %d%% CPU", sum); } } - else +#else { // Satisfy PCSX2's request for title info: minimal verbosity due to more external title text s = format("%dx%d | %s", GetInternalResolution().x, GetInternalResolution().y, theApp.m_gs_interlace[m_interlace].name.c_str()); } +#endif if (m_capture.IsCapturing()) { s += " | Recording..."; } - if (m_wnd->IsManaged()) - { - m_wnd->SetWindowText(s.c_str()); - } - else - { - // note: do not use TryEnterCriticalSection. It is unnecessary code complication in - // an area that absolutely does not matter (even if it were 100 times slower, it wouldn't - // be noticeable). Besides, these locks are extremely short -- overhead of conditional - // is way more expensive than just waiting for the CriticalSection in 1 of 10,000,000 tries. --air + // note: do not use TryEnterCriticalSection. It is unnecessary code complication in + // an area that absolutely does not matter (even if it were 100 times slower, it wouldn't + // be noticeable). Besides, these locks are extremely short -- overhead of conditional + // is way more expensive than just waiting for the CriticalSection in 1 of 10,000,000 tries. --air - std::lock_guard lock(m_pGSsetTitle_Crit); + std::lock_guard lock(m_pGSsetTitle_Crit); - strncpy(m_GStitleInfoBuffer, s.c_str(), countof(m_GStitleInfoBuffer) - 1); + strncpy(m_GStitleInfoBuffer, s.c_str(), countof(m_GStitleInfoBuffer) - 1); - m_GStitleInfoBuffer[sizeof(m_GStitleInfoBuffer) - 1] = 0; // make sure null terminated even if text overflows - } - } - else - { - // [TODO] - // We don't have window title rights, or the window has no title, - // so let's use actual OSD! + m_GStitleInfoBuffer[sizeof(m_GStitleInfoBuffer) - 1] = 0; // make sure null terminated even if text overflows } if (m_frameskip) diff --git a/pcsx2/GS/Window/GSWnd.h b/pcsx2/GS/Window/GSWnd.h index 535b6cf99e..65ec8d927c 100644 --- a/pcsx2/GS/Window/GSWnd.h +++ b/pcsx2/GS/Window/GSWnd.h @@ -16,38 +16,25 @@ #pragma once #include "PrecompiledHeader.h" +#include "common/WindowInfo.h" #include "GS/GS.h" #include "GS/GSVector.h" class GSWnd { -protected: - bool m_managed; // set true when we're attached to a 3rdparty window that's amanged by the emulator - public: - GSWnd() - : m_managed(false) - { - } - virtual ~GSWnd() {} + GSWnd() = default; + virtual ~GSWnd() = default; - virtual bool Create(const std::string& title, int w, int h) = 0; - virtual bool Attach(void* handle, bool managed = true) = 0; + virtual bool Attach(const WindowInfo& wi) = 0; virtual void Detach() = 0; - bool IsManaged() const { return m_managed; } - virtual void* GetDisplay() = 0; virtual void* GetHandle() = 0; virtual GSVector4i GetClientRect() = 0; - virtual bool SetWindowText(const char* title) = 0; virtual void AttachContext() {} virtual void DetachContext() {} - virtual void Show() = 0; - virtual void Hide() = 0; - virtual void HideFrame() = 0; - virtual void Flip() {} virtual void SetVSync(int vsync) {} }; @@ -75,24 +62,9 @@ public: , m_vsync(0) { } - virtual ~GSWndGL() {} + virtual ~GSWndGL() override = default; - virtual bool Create(const std::string& title, int w, int h) = 0; - virtual bool Attach(void* handle, bool managed = true) = 0; - virtual void Detach() = 0; - - virtual void* GetDisplay() = 0; - virtual void* GetHandle() = 0; - virtual GSVector4i GetClientRect() = 0; - virtual bool SetWindowText(const char* title) = 0; - - virtual void AttachContext() = 0; - virtual void DetachContext() = 0; virtual void* GetProcAddress(const char* name, bool opt = false) = 0; - virtual void Show() = 0; - virtual void Hide() = 0; - virtual void HideFrame() = 0; - virtual void Flip() = 0; - virtual void SetVSync(int vsync) final; + void SetVSync(int vsync) final; }; diff --git a/pcsx2/GS/Window/GSWndDX.cpp b/pcsx2/GS/Window/GSWndDX.cpp index 6fe4a478e1..19d6857d55 100644 --- a/pcsx2/GS/Window/GSWndDX.cpp +++ b/pcsx2/GS/Window/GSWndDX.cpp @@ -19,7 +19,6 @@ #ifdef _WIN32 GSWndDX::GSWndDX() : m_hWnd(NULL) - , m_frame(true) { } @@ -27,136 +26,20 @@ GSWndDX::~GSWndDX() { } -LRESULT CALLBACK GSWndDX::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +bool GSWndDX::Attach(const WindowInfo& wi) { - GSWndDX* wnd = NULL; + if (wi.type != WindowInfo::Type::Win32) + return false; - if (message == WM_NCCREATE) - { - wnd = (GSWndDX*)((LPCREATESTRUCT)lParam)->lpCreateParams; - - SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)wnd); - - wnd->m_hWnd = hWnd; - } - else - { - wnd = (GSWndDX*)GetWindowLongPtr(hWnd, GWLP_USERDATA); - } - - if (wnd == NULL) - { - return DefWindowProc(hWnd, message, wParam, lParam); - } - - return wnd->OnMessage(message, wParam, lParam); -} - -LRESULT GSWndDX::OnMessage(UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_CLOSE: - Hide(); - // DestroyWindow(m_hWnd); - return 0; - case WM_DESTROY: - // This kills the emulator when GS is closed, which *really* isn't desired behavior, - // especially in STGS mode (worked in MTGS mode since it only quit the thread, but even - // that wasn't needed). - //PostQuitMessage(0); - return 0; - default: - break; - } - - return DefWindowProc((HWND)m_hWnd, message, wParam, lParam); -} - -bool GSWndDX::Create(const std::string& title, int w, int h) -{ - if (m_hWnd) - throw GSRecoverableError(); - - m_managed = true; - - WNDCLASS wc; - - memset(&wc, 0, sizeof(wc)); - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; - wc.lpfnWndProc = WndProc; - wc.hInstance = theApp.GetModuleHandle(); - // TODO: wc.hIcon = ; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - wc.lpszClassName = L"GSWndDX"; - - if (!GetClassInfo(wc.hInstance, wc.lpszClassName, &wc)) - { - if (!RegisterClass(&wc)) - { - throw GSRecoverableError(); - } - } - - DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW | WS_BORDER; - - GSVector4i r; - - GetWindowRect(GetDesktopWindow(), r); - - bool remote = !!GetSystemMetrics(SM_REMOTESESSION); - - if (w <= 0 || h <= 0 || remote) - { - w = r.width() / 3; - h = r.width() / 4; - - if (!remote) - { - w *= 2; - h *= 2; - } - } - - r.left = (r.left + r.right - w) / 2; - r.top = (r.top + r.bottom - h) / 2; - r.right = r.left + w; - r.bottom = r.top + h; - - AdjustWindowRect(r, style, FALSE); - std::wstring tmp = std::wstring(title.begin(), title.end()); - m_hWnd = CreateWindow(wc.lpszClassName, tmp.c_str(), style, r.left, r.top, r.width(), r.height(), NULL, NULL, wc.hInstance, (LPVOID)this); - - if (!m_hWnd) - throw GSRecoverableError(); - - return true; -} - -bool GSWndDX::Attach(void* handle, bool managed) -{ // TODO: subclass - m_hWnd = (HWND)handle; - m_managed = managed; - + m_hWnd = static_cast(wi.window_handle); return true; } void GSWndDX::Detach() { - if (m_hWnd && m_managed) - { - // close the window, since it's under GS care. It's not taking messages anyway, and - // that means its big, ugly, and in the way. - - DestroyWindow(m_hWnd); - } - - m_hWnd = NULL; - m_managed = true; + m_hWnd = {}; } GSVector4i GSWndDX::GetClientRect() @@ -167,50 +50,4 @@ GSVector4i GSWndDX::GetClientRect() return r; } - -// Returns FALSE if the window has no title, or if th window title is under the strict -// management of the emulator. - -bool GSWndDX::SetWindowText(const char* title) -{ - if (!m_managed) - return false; - - const size_t tmp_size = strlen(title) + 1; - std::wstring tmp(tmp_size, L'#'); - mbstowcs(&tmp[0], title, tmp_size); - ::SetWindowText(m_hWnd, tmp.c_str()); - - return m_frame; -} - -void GSWndDX::Show() -{ - if (!m_managed) - return; - - SetForegroundWindow(m_hWnd); - ShowWindow(m_hWnd, SW_SHOWNORMAL); - UpdateWindow(m_hWnd); -} - -void GSWndDX::Hide() -{ - if (!m_managed) - return; - - ShowWindow(m_hWnd, SW_HIDE); -} - -void GSWndDX::HideFrame() -{ - if (!m_managed) - return; - - SetWindowLong(m_hWnd, GWL_STYLE, GetWindowLong(m_hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME)); - SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); - SetMenu(m_hWnd, NULL); - - m_frame = false; -} #endif diff --git a/pcsx2/GS/Window/GSWndDX.h b/pcsx2/GS/Window/GSWndDX.h index 5123274073..c4b11fb31f 100644 --- a/pcsx2/GS/Window/GSWndDX.h +++ b/pcsx2/GS/Window/GSWndDX.h @@ -17,30 +17,18 @@ #include "GSWnd.h" #ifdef _WIN32 -class GSWndDX : public GSWnd +class GSWndDX final : public GSWnd { HWND m_hWnd; - bool m_frame; - - static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - virtual LRESULT OnMessage(UINT message, WPARAM wParam, LPARAM lParam); - public: GSWndDX(); - virtual ~GSWndDX(); + ~GSWndDX() override; - bool Create(const std::string& title, int w, int h); - bool Attach(void* handle, bool managed = true); - void Detach(); + bool Attach(const WindowInfo& wi) override; + void Detach() override; - void* GetDisplay() { return m_hWnd; } - void* GetHandle() { return m_hWnd; } - GSVector4i GetClientRect(); - bool SetWindowText(const char* title); - - void Show(); - void Hide(); - void HideFrame(); + void* GetHandle() override { return m_hWnd; } + GSVector4i GetClientRect() override; }; #endif diff --git a/pcsx2/GS/Window/GSWndEGL.cpp b/pcsx2/GS/Window/GSWndEGL.cpp index 955c9f041b..9b8c1e7993 100644 --- a/pcsx2/GS/Window/GSWndEGL.cpp +++ b/pcsx2/GS/Window/GSWndEGL.cpp @@ -18,15 +18,14 @@ #if defined(__unix__) -// static method -int GSWndEGL::SelectPlatform() +std::shared_ptr GSWndEGL::CreateForPlatform(const WindowInfo& wi) { // Check the supported extension const char* client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); if (!client_extensions) { fprintf(stderr, "EGL: Client extension not supported\n"); - return 0; + return nullptr; } fprintf(stdout, "EGL: Supported extensions: %s\n", client_extensions); @@ -34,28 +33,27 @@ int GSWndEGL::SelectPlatform() if (!strstr(client_extensions, "EGL_EXT_platform_base")) { fprintf(stderr, "EGL: Dynamic platform selection isn't supported\n"); - return 0; + return nullptr; } // Finally we can select the platform #if GS_EGL_X11 - if (strstr(client_extensions, "EGL_EXT_platform_x11")) + if (strstr(client_extensions, "EGL_EXT_platform_x11") && wi.type == WindowInfo::Type::X11) { fprintf(stdout, "EGL: select X11 platform\n"); - return EGL_PLATFORM_X11_KHR; + return std::make_shared(); } #endif #if GS_EGL_WL - if (strstr(client_extensions, "EGL_EXT_platform_wayland")) + if (strstr(client_extensions, "EGL_EXT_platform_wayland") && wi.type == WindowInfo::Type::Wayland) { fprintf(stdout, "EGL: select Wayland platform\n"); - return EGL_PLATFORM_WAYLAND_KHR; + return std::make_shared(); } #endif - fprintf(stderr, "EGL: no compatible platform found\n"); - - return 0; + fprintf(stderr, "EGL: no compatible platform found for wintype %u\n", static_cast(wi.type)); + return nullptr; } @@ -103,7 +101,7 @@ void GSWndEGL::CreateContext(int major, int minor) m_eglSurface = eglCreatePlatformWindowSurface(m_eglDisplay, eglConfig, m_native_window, nullptr); if (m_eglSurface == EGL_NO_SURFACE) { - fprintf(stderr, "EGL: Failed to get a window surface\n"); + fprintf(stderr, "EGL: Failed to get a window surface (0x%x)\n", eglGetError()); throw GSRecoverableError(); } @@ -169,11 +167,11 @@ void GSWndEGL::BindAPI() } } -bool GSWndEGL::Attach(void* handle, bool managed) +bool GSWndEGL::Attach(const WindowInfo& wi) { - m_managed = managed; - - m_native_window = AttachNativeWindow(handle); + m_native_window = AttachNativeWindow(wi); + if (!m_native_window) + return false; OpenEGLDisplay(); @@ -198,25 +196,6 @@ void GSWndEGL::Detach() DestroyNativeResources(); } -bool GSWndEGL::Create(const std::string& title, int w, int h) -{ - if (w <= 0 || h <= 0) - { - w = theApp.GetConfigI("ModeWidth"); - h = theApp.GetConfigI("ModeHeight"); - } - - m_managed = true; - - OpenEGLDisplay(); - - m_native_window = CreateNativeWindow(w, h); - - FullContextInit(); - - return true; -} - void* GSWndEGL::GetProcAddress(const char* name, bool opt) { void* ptr = (void*)eglGetProcAddress(name); @@ -267,9 +246,7 @@ void GSWndEGL::OpenEGLDisplay() // We only need a native display when we manage the window ourself. // By default, EGL will create its own native display. This way the driver knows // that display will be thread safe and so it can enable multithread optimization. - void* native_display = (m_managed) ? CreateNativeDisplay() : nullptr; - - // Create an EGL display from the native display + void* native_display = nullptr; m_eglDisplay = eglGetPlatformDisplay(m_platform, native_display, nullptr); if (m_eglDisplay == EGL_NO_DISPLAY) { @@ -290,84 +267,21 @@ void GSWndEGL::OpenEGLDisplay() #if GS_EGL_X11 GSWndEGL_X11::GSWndEGL_X11() - : GSWndEGL(EGL_PLATFORM_X11_KHR), m_NativeDisplay(nullptr), m_NativeWindow(0) + : GSWndEGL(EGL_PLATFORM_X11_KHR), m_NativeWindow(0) { } -void* GSWndEGL_X11::CreateNativeDisplay() +void* GSWndEGL_X11::AttachNativeWindow(const WindowInfo& wi) { - if (m_NativeDisplay == nullptr) - m_NativeDisplay = XOpenDisplay(nullptr); + if (wi.type != WindowInfo::Type::X11) + return nullptr; - return (void*)m_NativeDisplay; -} - -void* GSWndEGL_X11::CreateNativeWindow(int w, int h) -{ - const int depth = 0, x = 0, y = 0, border_width = 1; -#if 0 - // Old X code in case future code will still require it - m_NativeWindow = XCreateSimpleWindow(m_NativeDisplay, DefaultRootWindow(m_NativeDisplay), 0, 0, w, h, 0, 0, 0); - XMapWindow (m_NativeDisplay, m_NativeWindow); -#endif - - if (m_NativeDisplay == nullptr) - { - fprintf(stderr, "EGL X11: display wasn't created before the window\n"); - throw GSRecoverableError(); - } - - xcb_connection_t* c = XGetXCBConnection(m_NativeDisplay); - - const xcb_setup_t* setup = xcb_get_setup(c); - - xcb_screen_t* screen = (xcb_setup_roots_iterator(setup)).data; - - m_NativeWindow = xcb_generate_id(c); - - if (m_NativeWindow == 0) - { - fprintf(stderr, "EGL X11: failed to create the native window\n"); - throw GSRecoverableError(); - } - - xcb_create_window(c, depth, m_NativeWindow, screen->root, x, y, w, h, - border_width, InputOutput, screen->root_visual, 0, nullptr); - - xcb_map_window(c, m_NativeWindow); - - xcb_flush(c); - - return (void*)&m_NativeWindow; -} - -void* GSWndEGL_X11::AttachNativeWindow(void* handle) -{ - m_NativeWindow = *(Window*)handle; - return handle; + m_NativeWindow = reinterpret_cast(wi.window_handle); + return &m_NativeWindow; } void GSWndEGL_X11::DestroyNativeResources() { - if (m_NativeDisplay) - { - XCloseDisplay(m_NativeDisplay); - m_NativeDisplay = nullptr; - } -} - -bool GSWndEGL_X11::SetWindowText(const char* title) -{ - if (!m_managed) - return true; - - xcb_connection_t* c = XGetXCBConnection(m_NativeDisplay); - - xcb_change_property(c, XCB_PROP_MODE_REPLACE, m_NativeWindow, - XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, - strlen(title), title); - - return true; } #endif @@ -378,43 +292,36 @@ bool GSWndEGL_X11::SetWindowText(const char* title) #if GS_EGL_WL GSWndEGL_WL::GSWndEGL_WL() - : GSWndEGL(EGL_PLATFORM_WAYLAND_KHR), m_NativeDisplay(nullptr), m_NativeWindow(nullptr) + : GSWndEGL(EGL_PLATFORM_WAYLAND_KHR), m_NativeWindow(nullptr) { } -void* GSWndEGL_WL::CreateNativeDisplay() +void* GSWndEGL_WL::AttachNativeWindow(const WindowInfo& wi) { - if (m_NativeDisplay == nullptr) - m_NativeDisplay = wl_display_connect(NULL); + if (wi.type != WindowInfo::Type::Wayland) + return nullptr; - return (void*)m_NativeDisplay; -} + m_NativeWindow = wl_egl_window_create(static_cast(wi.window_handle), + static_cast(wi.surface_width), + static_cast(wi.surface_height)); + if (!m_NativeWindow) + { + std::fprintf(stderr, "Failed to create walyand EGL window\n"); + return nullptr; + } -void* GSWndEGL_WL::CreateNativeWindow(int w, int h) -{ - return nullptr; -} - -void* GSWndEGL_WL::AttachNativeWindow(void* handle) -{ - m_NativeWindow = (wl_egl_window*)handle; - return handle; + return m_NativeWindow; } void GSWndEGL_WL::DestroyNativeResources() { - if (m_NativeDisplay) + if (m_NativeWindow) { - wl_display_disconnect(m_NativeDisplay); - m_NativeDisplay = nullptr; + wl_egl_window_destroy(m_NativeWindow); + m_NativeWindow = nullptr; } } -bool GSWndEGL_WL::SetWindowText(const char* title) -{ - return true; -} - #endif #endif diff --git a/pcsx2/GS/Window/GSWndEGL.h b/pcsx2/GS/Window/GSWndEGL.h index 55d0994d14..5a210c00a4 100644 --- a/pcsx2/GS/Window/GSWndEGL.h +++ b/pcsx2/GS/Window/GSWndEGL.h @@ -46,35 +46,21 @@ public: GSWndEGL(int platform); virtual ~GSWndEGL(){}; - bool Create(const std::string& title, int w, int h) final; - bool Attach(void* handle, bool managed = true) final; + static std::shared_ptr CreateForPlatform(const WindowInfo& wi); + + bool Attach(const WindowInfo& wi) final; void Detach() final; - virtual void* CreateNativeDisplay() = 0; - virtual void* CreateNativeWindow(int w, int h) = 0; // GSopen1/PSX API - virtual void* AttachNativeWindow(void* handle) = 0; + virtual void* AttachNativeWindow(const WindowInfo& wi) = 0; virtual void DestroyNativeResources() = 0; GSVector4i GetClientRect(); - virtual bool SetWindowText(const char* title) = 0; // GSopen1/PSX API void AttachContext() final; void DetachContext() final; void* GetProcAddress(const char* name, bool opt = false) final; void Flip() final; - - // Deprecated API - void Show() final {} - void Hide() final {} - void HideFrame() final {} // DX9 API - - virtual void* GetDisplay() = 0; // GSopen1 API - virtual void* GetHandle() = 0; // DX API - - // Static to allow to query supported the platform - // before object creation - static int SelectPlatform(); }; #if GS_EGL_X11 @@ -83,24 +69,18 @@ public: #include #include -class GSWndEGL_X11 : public GSWndEGL +class GSWndEGL_X11 final : public GSWndEGL { - Display* m_NativeDisplay; Window m_NativeWindow; public: GSWndEGL_X11(); - virtual ~GSWndEGL_X11(){}; + virtual ~GSWndEGL_X11() final = default; - void* GetDisplay() final { return (void*)m_NativeDisplay; } - void* GetHandle() final { return (void*)&m_NativeWindow; } + void* GetHandle() final { return reinterpret_cast(m_NativeWindow); } - void* CreateNativeDisplay() final; - void* CreateNativeWindow(int w, int h) final; - void* AttachNativeWindow(void* handle) final; + void* AttachNativeWindow(const WindowInfo& wi) final; void DestroyNativeResources() final; - - bool SetWindowText(const char* title) final; }; #endif @@ -113,24 +93,18 @@ public: #include #include -class GSWndEGL_WL : public GSWndEGL +class GSWndEGL_WL final : public GSWndEGL { - wl_display* m_NativeDisplay; wl_egl_window* m_NativeWindow; public: GSWndEGL_WL(); - virtual ~GSWndEGL_WL(){}; + virtual ~GSWndEGL_WL() final = default; - void* GetDisplay() final { return (void*)m_NativeDisplay; } - void* GetHandle() final { return (void*)m_NativeWindow; } + void* GetHandle() final { return reinterpret_cast(m_NativeWindow); } - void* CreateNativeDisplay() final; - void* CreateNativeWindow(int w, int h) final; - void* AttachNativeWindow(void* handle) final; + void* AttachNativeWindow(const WindowInfo& wi) final; void DestroyNativeResources() final; - - bool SetWindowText(const char* title) final; }; #endif diff --git a/pcsx2/GS/Window/GSWndWGL.cpp b/pcsx2/GS/Window/GSWndWGL.cpp index 5046886f6f..c3a19e8ed1 100644 --- a/pcsx2/GS/Window/GSWndWGL.cpp +++ b/pcsx2/GS/Window/GSWndWGL.cpp @@ -41,23 +41,6 @@ GSWndWGL::GSWndWGL() { } -// Used by GSReplay. Perhaps the stuff used by GSReplay can be moved out? That way all -// the GSOpen 1 stuff can be removed. But that'll take a bit of thinking. -LRESULT CALLBACK GSWndWGL::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case WM_CLOSE: - // This takes place before GSClose, so don't destroy the Window so we can clean up. - ShowWindow(hWnd, SW_HIDE); - // DestroyWindow(hWnd); - return 0; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } -} - - void GSWndWGL::CreateContext(int major, int minor) { if (!m_NativeDisplay || !m_NativeWindow) @@ -156,10 +139,12 @@ void GSWndWGL::PopulateWndGlFunction() } } -bool GSWndWGL::Attach(void* handle, bool managed) +bool GSWndWGL::Attach(const WindowInfo& wi) { - m_NativeWindow = (HWND)handle; - m_managed = managed; + if (wi.type != WindowInfo::Type::Win32) + return false; + + m_NativeWindow = static_cast(wi.window_handle); OpenWGLDisplay(); @@ -181,13 +166,6 @@ void GSWndWGL::Detach() m_context = NULL; CloseWGLDisplay(); - - // Used by GSReplay. - if (m_NativeWindow && m_managed) - { - DestroyWindow(m_NativeWindow); - m_NativeWindow = NULL; - } } void GSWndWGL::OpenWGLDisplay() @@ -235,77 +213,6 @@ void GSWndWGL::CloseWGLDisplay() m_NativeDisplay = NULL; } -//TODO: GSopen 1 => Drop? -// Used by GSReplay. At least for now. -// More or less copy pasted from GSWndDX::Create and GSWndWGL::Attach with a few -// modifications -bool GSWndWGL::Create(const std::string& title, int w, int h) -{ - if (m_NativeWindow) - return false; - - m_managed = true; - - WNDCLASS wc; - - memset(&wc, 0, sizeof(wc)); - - wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC; - wc.lpfnWndProc = WndProc; - wc.hInstance = theApp.GetModuleHandle(); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - wc.lpszClassName = L"GSWndOGL"; - - if (!GetClassInfo(wc.hInstance, wc.lpszClassName, &wc)) - { - if (!RegisterClass(&wc)) - { - return false; - } - } - - DWORD style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW | WS_BORDER; - - GSVector4i r; - - GetWindowRect(GetDesktopWindow(), r); - - // Old GSOpen ModeWidth and ModeHeight are not necessary with this. - bool remote = !!GetSystemMetrics(SM_REMOTESESSION); - - if (w <= 0 || h <= 0 || remote) - { - w = r.width() / 3; - h = r.width() / 4; - - if (!remote) - { - w *= 2; - h *= 2; - } - } - - r.left = (r.left + r.right - w) / 2; - r.top = (r.top + r.bottom - h) / 2; - r.right = r.left + w; - r.bottom = r.top + h; - - AdjustWindowRect(r, style, FALSE); - - std::wstring tmp = std::wstring(title.begin(), title.end()); - m_NativeWindow = CreateWindow(wc.lpszClassName, tmp.c_str(), style, r.left, r.top, r.width(), r.height(), NULL, NULL, wc.hInstance, (LPVOID)this); - - if (m_NativeWindow == NULL) - return false; - - OpenWGLDisplay(); - - FullContextInit(); - - return true; -} - //Same as DX GSVector4i GSWndWGL::GetClientRect() { @@ -360,42 +267,4 @@ void GSWndWGL::Flip() SwapBuffers(m_NativeDisplay); } - -void GSWndWGL::Show() -{ - if (!m_managed) - return; - - // Used by GSReplay - SetForegroundWindow(m_NativeWindow); - ShowWindow(m_NativeWindow, SW_SHOWNORMAL); - UpdateWindow(m_NativeWindow); -} - -void GSWndWGL::Hide() -{ -} - -void GSWndWGL::HideFrame() -{ -} - -// Returns FALSE if the window has no title, or if th window title is under the strict -// management of the emulator. - -bool GSWndWGL::SetWindowText(const char* title) -{ - if (!m_managed) - return false; - - const size_t tmp_size = strlen(title) + 1; - std::wstring tmp(tmp_size, L'#'); - mbstowcs(&tmp[0], title, tmp_size); - // Used by GSReplay. - ::SetWindowText(m_NativeWindow, tmp.c_str()); - - return true; -} - - #endif diff --git a/pcsx2/GS/Window/GSWndWGL.h b/pcsx2/GS/Window/GSWndWGL.h index 94bec7b41a..702715fd2e 100644 --- a/pcsx2/GS/Window/GSWndWGL.h +++ b/pcsx2/GS/Window/GSWndWGL.h @@ -17,7 +17,7 @@ #ifdef _WIN32 -class GSWndWGL : public GSWndGL +class GSWndWGL final : public GSWndGL { HWND m_NativeWindow; HDC m_NativeDisplay; @@ -35,29 +35,21 @@ class GSWndWGL : public GSWndGL void SetSwapInterval(); bool HasLateVsyncSupport() { return m_has_late_vsync; } - static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - public: GSWndWGL(); - virtual ~GSWndWGL() {} + ~GSWndWGL() override = default; - bool Create(const std::string& title, int w, int h); - bool Attach(void* handle, bool managed = true); - void Detach(); + bool Attach(const WindowInfo& wi) override; + void Detach() override; - void* GetDisplay() { return m_NativeWindow; } - void* GetHandle() { return m_NativeWindow; } - GSVector4i GetClientRect(); - bool SetWindowText(const char* title); + void* GetHandle() override { return m_NativeWindow; } + GSVector4i GetClientRect() override; - void AttachContext(); - void DetachContext(); - void* GetProcAddress(const char* name, bool opt); + void AttachContext() override; + void DetachContext() override; + void* GetProcAddress(const char* name, bool opt) override; - void Show(); - void Hide(); - void HideFrame(); - void Flip(); + void Flip() override; }; #endif diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index cb013ab6b8..847ae8627a 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -25,6 +25,8 @@ #include "Elfheader.h" #include "gui/Dialogs/ModalPopups.h" +#include "common/WindowInfo.h" +extern WindowInfo g_gs_window_info; // Uncomment this to enable profiling of the GS RingBufferCopy function. //#define PCSX2_GSRING_SAMPLING_STATS @@ -237,7 +239,7 @@ void SysMtgsThread::OpenGS() memcpy(RingBuffer.Regs, PS2MEM_GS, sizeof(PS2MEM_GS)); GSsetBaseMem(RingBuffer.Regs); - pxAssertMsg((GSopen2((void**)pDsp, 1 | (renderswitch ? 4 : 0)) == 0), "GS failed to open!"); + pxAssertMsg((GSopen2(g_gs_window_info, 1 | (renderswitch ? 4 : 0)) == 0), "GS failed to open!"); GSsetVsync(EmuConfig.GS.GetVsync()); diff --git a/pcsx2/PAD/Linux/PAD.cpp b/pcsx2/PAD/Linux/PAD.cpp index 6806caaf18..093c4fa844 100644 --- a/pcsx2/PAD/Linux/PAD.cpp +++ b/pcsx2/PAD/Linux/PAD.cpp @@ -18,6 +18,9 @@ #include #include +// NOTE: Must come first because of the None enum +#include "common/WindowInfo.h" + #include "keyboard.h" #include "PAD.h" #include "state_management.h" @@ -109,7 +112,7 @@ void PADshutdown() CloseLogging(); } -s32 PADopen(void* pDsp) +s32 PADopen(const WindowInfo& wi) { memset(&event, 0, sizeof(event)); g_key_status.Init(); @@ -119,7 +122,7 @@ s32 PADopen(void* pDsp) #if defined(__unix__) || defined(__APPLE__) EnumerateDevices(); #endif - return _PADopen(pDsp); + return _PADopen(wi); } void PADsetLogDir(const char* dir) diff --git a/pcsx2/PAD/Linux/PAD.h b/pcsx2/PAD/Linux/PAD.h index ed96008853..2946e153d5 100644 --- a/pcsx2/PAD/Linux/PAD.h +++ b/pcsx2/PAD/Linux/PAD.h @@ -31,13 +31,15 @@ enum PadOptions PADOPTION_MOUSE_R = 0x40, }; +struct WindowInfo; + extern FILE* padLog; extern void initLogging(); extern HostKeyEvent event; extern MtQueue g_ev_fifo; -s32 _PADopen(void* pDsp); +s32 _PADopen(const WindowInfo& wi); void _PADclose(); void PADsetMode(int pad, int mode); @@ -45,7 +47,7 @@ void SysMessage(char* fmt, ...); s32 PADinit(); void PADshutdown(); -s32 PADopen(void* pDsp); +s32 PADopen(const WindowInfo& wi); void PADsetLogDir(const char* dir); void PADclose(); s32 PADsetSlot(u8 port, u8 slot); diff --git a/pcsx2/PAD/Linux/keyboard.cpp b/pcsx2/PAD/Linux/keyboard.cpp index 0339f5e1d1..f5d1f4b588 100644 --- a/pcsx2/PAD/Linux/keyboard.cpp +++ b/pcsx2/PAD/Linux/keyboard.cpp @@ -262,6 +262,9 @@ void UpdateKeyboardInput() g_ev_fifo.consume_all(AnalyzeKeyEvent); // keyboard input + if (!GSdsp) + return; + while (XPending(GSdsp) > 0) { XNextEvent(GSdsp, &E); diff --git a/pcsx2/PAD/Linux/linux.cpp b/pcsx2/PAD/Linux/linux.cpp index 8f3b557ea0..05c5be0c05 100644 --- a/pcsx2/PAD/Linux/linux.cpp +++ b/pcsx2/PAD/Linux/linux.cpp @@ -14,6 +14,8 @@ */ #include "gui/AppCoreThread.h" +#include "common/WindowInfo.h" + #include "Global.h" #include "Device.h" #include "keyboard.h" @@ -42,11 +44,14 @@ static void SysMessage(const char* fmt, ...) dialog.ShowModal(); } -s32 _PADopen(void* pDsp) +s32 _PADopen(const WindowInfo& wi) { #ifndef __APPLE__ - GSdsp = *(Display**)pDsp; - GSwin = (Window) * (((u32*)pDsp) + 1); + if (wi.type != WindowInfo::Type::X11) + return -1; + + GSdsp = static_cast(wi.display_connection); + GSwin = reinterpret_cast(wi.window_handle); #endif return 0; @@ -65,7 +70,7 @@ void PADupdate(int pad) // Emulate an user activity static int count = 0; count++; - if ((count & 0xFFF) == 0) + if ((count & 0xFFF) == 0 && GSdsp) { // 1 call every 4096 Vsync is enough XResetScreenSaver(GSdsp); diff --git a/pcsx2/PAD/Windows/PAD.cpp b/pcsx2/PAD/Windows/PAD.cpp index 2c6e161403..5acb2b463b 100644 --- a/pcsx2/PAD/Windows/PAD.cpp +++ b/pcsx2/PAD/Windows/PAD.cpp @@ -15,6 +15,7 @@ #include "PrecompiledHeader.h" #include "Global.h" +#include "Common/WindowInfo.h" #include #include @@ -34,17 +35,17 @@ #include "KeyboardQueue.h" #include "DualShock3.h" +#ifndef PCSX2_CORE #include "gui/AppCoreThread.h" +#endif #define WMA_FORCE_UPDATE (WM_APP + 0x537) #define FORCE_UPDATE_WPARAM ((WPARAM)0x74328943) #define FORCE_UPDATE_LPARAM ((LPARAM)0x89437437) -#ifdef __linux__ -Display* GSdsp; -Window GSwin; -#else -HWND hWnd; +static WindowInfo s_window_info; + +#ifdef _WIN32 HWND hWndTop; WndProcEater hWndGSProc; @@ -483,7 +484,8 @@ void Update(unsigned int port, unsigned int slot) if (!updateQueued) { updateQueued = 1; - PostMessage(hWnd, WMA_FORCE_UPDATE, FORCE_UPDATE_WPARAM, FORCE_UPDATE_LPARAM); + PostMessage(static_cast(s_window_info.window_handle), + WMA_FORCE_UPDATE, FORCE_UPDATE_WPARAM, FORCE_UPDATE_LPARAM); } } else @@ -963,67 +965,52 @@ ExtraWndProcResult StatusWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa } #endif +#ifndef PCSX2_CORE void PADconfigure() { ScopedCoreThreadPause paused_core(SystemsMask::System_PAD); Configure(); paused_core.AllowResume(); } +#endif -s32 PADopen(void* pDsp) +s32 PADopen(const WindowInfo& wi) { if (openCount++) return 0; miceEnabled = !config.mouseUnfocus; #ifdef _MSC_VER - if (!hWnd) + if (wi.type != WindowInfo::Type::Win32) { - if (IsWindow((HWND)pDsp)) - { - hWnd = (HWND)pDsp; - } - else if (pDsp && !IsBadReadPtr(pDsp, 4) && IsWindow(*(HWND*)pDsp)) - { - hWnd = *(HWND*)pDsp; - } - else - { - openCount = 0; - MessageBoxA(GetActiveWindow(), - "Invalid Window handle passed to PAD.\n" - "\n" - "Either your emulator or gs plugin is buggy,\n" - "Despite the fact the emulator is about to\n" - "blame PAD for failing to initialize.", - "Non-PAD Error", MB_OK | MB_ICONERROR); - return -1; - } - hWndTop = GetAncestor(hWnd, GA_ROOT); - - if (!hWndGSProc.SetWndHandle(hWnd)) - { - openCount = 0; - return -1; - } - - // Implements most hacks, as well as enabling/disabling mouse - // capture when focus changes. - updateQueued = 0; - hWndGSProc.Eat(StatusWndProc, 0); - - if (hWnd != hWndTop) - { - if (!hWndTopProc.SetWndHandle(hWndTop)) - { - openCount = 0; - return -1; - } - } - - windowThreadId = GetWindowThreadProcessId(hWndTop, 0); + openCount = 0; + MessageBoxA(GetActiveWindow(), + "Invalid Window handle passed to PAD.\n" + "\n" + "Either your emulator or gs plugin is buggy,\n" + "Despite the fact the emulator is about to\n" + "blame PAD for failing to initialize.", + "Non-PAD Error", MB_OK | MB_ICONERROR); + return -1; } + const HWND hWnd = static_cast(wi.window_handle); + hWndTop = GetAncestor(hWnd, GA_ROOT); + + if (!hWndGSProc.SetWndHandle(hWnd)) + { + openCount = 0; + return -1; + } + + // Implements most hacks, as well as enabling/disabling mouse + // capture when focus changes. + updateQueued = 0; + hWndGSProc.Eat(StatusWndProc, 0); + + windowThreadId = GetWindowThreadProcessId(hWndTop, 0); + s_window_info = wi; + #endif for (int port = 0; port < 2; port++) { @@ -1049,10 +1036,6 @@ s32 PADopen(void* pDsp) // activeWindow = GetActiveWindow() == hWnd; // activeWindow = (GetAncestor(hWnd, GA_ROOT) == GetAncestor(GetForegroundWindow(), GA_ROOT)); -#else - // Not used so far - GSdsp = *(Display**)pDsp; - GSwin = (Window) * (((uptr*)pDsp) + 1); #endif activeWindow = 1; UpdateEnabledDevices(); @@ -1068,8 +1051,7 @@ void PADclose() hWndGSProc.Release(); hWndTopProc.Release(); dm->ReleaseInput(); - hWnd = 0; - hWndTop = 0; + s_window_info = WindowInfo(); #else R_ClearKeyQueue(); #endif diff --git a/pcsx2/PAD/Windows/PAD.h b/pcsx2/PAD/Windows/PAD.h index 98f1808d64..6a5da04c0e 100644 --- a/pcsx2/PAD/Windows/PAD.h +++ b/pcsx2/PAD/Windows/PAD.h @@ -36,6 +36,7 @@ #include "SaveState.h" struct HostKeyEvent; +struct WindowInfo; struct PadDataS { @@ -49,12 +50,14 @@ struct PadDataS void PADupdate(int pad); void PADshutdown(); s32 PADinit(); -s32 PADopen(void* pDsp); +s32 PADopen(const WindowInfo& wi); void PADclose(); u8 PADstartPoll(int pad); u8 PADpoll(u8 value); HostKeyEvent* PADkeyEvent(); +#ifndef PCSX2_CORE void PADconfigure(); +#endif s32 PADfreeze(FreezeAction mode, freezeData* data); s32 PADsetSlot(u8 port, u8 slot); void PADsetSettingsDir(const char* dir); diff --git a/pcsx2/SPU2/Windows/CfgHelpers.cpp b/pcsx2/SPU2/Windows/CfgHelpers.cpp index 680c40748f..af11b21c03 100644 --- a/pcsx2/SPU2/Windows/CfgHelpers.cpp +++ b/pcsx2/SPU2/Windows/CfgHelpers.cpp @@ -20,8 +20,6 @@ #include "common/StringHelpers.h" -extern uptr gsWindowHandle; - void SysMessage(const char* fmt, ...) { va_list list; @@ -32,8 +30,9 @@ void SysMessage(const char* fmt, ...) vsprintf_s(tmp, fmt, list); va_end(list); swprintf_s(wtmp, L"%S", tmp); - MessageBox((!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp, - L"SPU2 System Message", MB_OK | MB_SETFOREGROUND); + + // TODO: Move this into app/host. + MessageBox(NULL, wtmp, L"SPU2 System Message", MB_OK | MB_SETFOREGROUND); } void SysMessage(const wchar_t* fmt, ...) @@ -43,8 +42,7 @@ void SysMessage(const wchar_t* fmt, ...) wxString wtmp; wtmp.PrintfV(fmt, list); va_end(list); - MessageBox((!!gsWindowHandle) ? (HWND)gsWindowHandle : GetActiveWindow(), wtmp, - L"SPU2 System Message", MB_OK | MB_SETFOREGROUND); + MessageBox(NULL, wtmp, L"SPU2 System Message", MB_OK | MB_SETFOREGROUND); } ////// diff --git a/pcsx2/SPU2/spu2.cpp b/pcsx2/SPU2/spu2.cpp index dd405dd62b..1ee7d2638f 100644 --- a/pcsx2/SPU2/spu2.cpp +++ b/pcsx2/SPU2/spu2.cpp @@ -250,7 +250,7 @@ static INT_PTR CALLBACK DebugProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP #endif uptr gsWindowHandle = 0; -s32 SPU2open(void* pDsp) +s32 SPU2open() { ScopedLock lock(mtx_SPU2Status); if (IsOpened) @@ -258,11 +258,6 @@ s32 SPU2open(void* pDsp) FileLog("[%10d] SPU2 Open\n", Cycles); - if (pDsp != nullptr) - gsWindowHandle = *(uptr*)pDsp; - else - gsWindowHandle = 0; - #ifdef _MSC_VER #ifdef PCSX2_DEVBUILD // Define may not be needed but not tested yet. Better make sure. if (IsDevBuild && VisualDebug()) diff --git a/pcsx2/SPU2/spu2.h b/pcsx2/SPU2/spu2.h index b1790499c6..c8db3bd17a 100644 --- a/pcsx2/SPU2/spu2.h +++ b/pcsx2/SPU2/spu2.h @@ -28,7 +28,7 @@ enum class PS2Modes s32 SPU2init(); s32 SPU2reset(PS2Modes isRunningPSXMode); -s32 SPU2open(void* pDsp); +s32 SPU2open(); void SPU2close(); void SPU2shutdown(); void SPU2write(u32 mem, u16 value); diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp index a9b5dbcda6..db85d59d0f 100644 --- a/pcsx2/System/SysCoreThread.cpp +++ b/pcsx2/System/SysCoreThread.cpp @@ -19,6 +19,9 @@ #include "IopBios.h" #include "R5900.h" +#include "common/WindowInfo.h" +extern WindowInfo g_gs_window_info; + #include "Counters.h" #include "GS.h" #include "Elfheader.h" @@ -323,11 +326,11 @@ void SysCoreThread::TearDownSystems(SystemsMask systemsToTearDown) void SysCoreThread::OnResumeInThread(SystemsMask systemsToReinstate) { GetMTGS().WaitForOpen(); - if (systemsToReinstate & System_DEV9) DEV9open((void*)pDsp); - if (systemsToReinstate & System_USB) USBopen((void*)pDsp); + if (systemsToReinstate & System_DEV9) DEV9open(); + if (systemsToReinstate & System_USB) USBopen(g_gs_window_info); if (systemsToReinstate & System_FW) FWopen(); - if (systemsToReinstate & System_SPU2) SPU2open((void*)pDsp); - if (systemsToReinstate & System_PAD) PADopen((void*)pDsp); + if (systemsToReinstate & System_SPU2) SPU2open(); + if (systemsToReinstate & System_PAD) PADopen(g_gs_window_info); if (systemsToReinstate & System_MCD) FileMcd_EmuOpen(); } diff --git a/pcsx2/USB/USB.cpp b/pcsx2/USB/USB.cpp index 468477d314..4199175ca6 100644 --- a/pcsx2/USB/USB.cpp +++ b/pcsx2/USB/USB.cpp @@ -21,6 +21,7 @@ #include "PrecompiledHeader.h" #include "common/pxStreams.h" +#include "common/WindowInfo.h" #include "USB.h" #include "qemu-usb/USBinternal.h" #include "qemu-usb/desc.h" @@ -67,7 +68,7 @@ int64_t usb_bit_time; s64 clocks = 0; s64 remaining = 0; -#if _WIN32 +#if defined(_WIN32) HWND gsWnd = nullptr; #elif defined(__linux__) #include "gtk.h" @@ -243,7 +244,7 @@ void USBshutdown() usb_opened = false; } -s32 USBopen(void* pDsp) +s32 USBopen(const WindowInfo& wi) { if (conf.Log && !usbLog) @@ -252,29 +253,25 @@ s32 USBopen(void* pDsp) //if(usbLog) setvbuf(usbLog, NULL, _IONBF, 0); } -#if _WIN32 - - HWND hWnd = 0; - if (IsWindow((HWND)pDsp)) + void* window_handle_for_init = nullptr; +#if defined(_WIN32) + if (wi.type == WindowInfo::Type::Win32) { - hWnd = (HWND)pDsp; + gsWnd = static_cast(wi.window_handle); + window_handle_for_init = wi.window_handle; } - else if (pDsp && !IsBadReadPtr(pDsp, 4) && IsWindow(*(HWND*)pDsp)) - { - hWnd = *(HWND*)pDsp; - } - - gsWnd = hWnd; - pDsp = gsWnd; #elif defined(__linux__) - - g_GSdsp = (Display*)((uptr*)pDsp)[0]; - g_GSwin = (Window)((uptr*)pDsp)[1]; + if (wi.type == WindowInfo::Type::X11) + { + g_GSdsp = static_cast(wi.display_connection); + g_GSwin = reinterpret_cast(wi.window_handle); + window_handle_for_init = reinterpret_cast(g_GSwin); + } #endif try { - shared::Initialize(pDsp); + shared::Initialize(window_handle_for_init); } catch (std::runtime_error& e) { @@ -298,6 +295,12 @@ void USBclose() CloseDevice(1); shared::Uninitialize(); usb_opened = false; +#if defined(_WIN32) + gsWnd = {}; +#elif defined(__linux__) + g_GSdsp = nullptr; + g_GSwin = {}; +#endif } u8 USBread8(u32 addr) diff --git a/pcsx2/USB/USB.h b/pcsx2/USB/USB.h index 2c10cecc27..9b5c3e4ab6 100644 --- a/pcsx2/USB/USB.h +++ b/pcsx2/USB/USB.h @@ -22,6 +22,8 @@ #include "SaveState.h" +struct WindowInfo; + // --------------------------------------------------------------------- #define USBdefs @@ -38,7 +40,7 @@ s32 USBinit(); void USBasync(u32 cycles); void USBshutdown(); void USBclose(); -s32 USBopen(void* pDsp); +s32 USBopen(const WindowInfo& wi); s32 USBfreeze(FreezeAction mode, freezeData* data); u8 USBread8(u32 addr); diff --git a/pcsx2/USB/USBNull.cpp b/pcsx2/USB/USBNull.cpp index 3876eb1446..4cdd2cf9b7 100644 --- a/pcsx2/USB/USBNull.cpp +++ b/pcsx2/USB/USBNull.cpp @@ -26,7 +26,7 @@ s32 USBinit() { return 0; } void USBasync(u32 cycles) {} void USBshutdown() {} void USBclose() {} -s32 USBopen(void* pDsp) { return 0; } +s32 USBopen(const WindowInfo& wi) { return 0; } s32 USBfreeze(FreezeAction mode, freezeData* data) { return 0; } u8 USBread8(u32 addr) { return 0; } diff --git a/pcsx2/gui/App.h b/pcsx2/gui/App.h index fd11031761..d9decd77af 100644 --- a/pcsx2/gui/App.h +++ b/pcsx2/gui/App.h @@ -15,7 +15,8 @@ #pragma once -#include "gui/wxAppWithHelpers.h" +#include "wxAppWithHelpers.h" +#include "common/WindowInfo.h" #include #include @@ -39,7 +40,8 @@ struct HostKeyEvent; #include "System.h" #include "System/SysThreads.h" -extern uptr pDsp[2]; +// TODO: Not the best location for this, but it needs to be accessed by MTGS etc. +extern WindowInfo g_gs_window_info; typedef void FnType_OnThreadComplete(const wxCommandEvent& evt); typedef void (Pcsx2App::*FnPtr_Pcsx2App)(); diff --git a/pcsx2/gui/AppMain.cpp b/pcsx2/gui/AppMain.cpp index 9fc15451af..838a02dcfc 100644 --- a/pcsx2/gui/AppMain.cpp +++ b/pcsx2/gui/AppMain.cpp @@ -73,7 +73,7 @@ wxIMPLEMENT_APP(Pcsx2App); std::unique_ptr g_Conf; -uptr pDsp[2]; +WindowInfo g_gs_window_info; // Returns a string message telling the user to consult guides for obtaining a legal BIOS. // This message is in a function because it's used as part of several dialogs in PCSX2 (there @@ -864,39 +864,12 @@ void Pcsx2App::OpenGsPanel() pxAssertDev( !gsopen_done, "GS must be closed prior to opening a new Gs Panel!" ); -#ifdef __WXGTK__ - // The x window/display are actually very deeper in the widget. You need both display and window - // because unlike window there are unrelated. One could think it would be easier to send directly the GdkWindow. - // Unfortunately there is a race condition between gui and gs threads when you called the - // GDK_WINDOW_* macro. To be safe I think it is best to do here. -- Gregory + gsFrame->ShowFullScreen(g_Conf->GSWindow.IsFullscreen); + wxApp::ProcessPendingEvents(); - // GTK_PIZZA is an internal interface of wx, therefore they decide to - // remove it on wx 3. I tryed to replace it with gtk_widget_get_window but - // unfortunately it creates a gray box in the middle of the window on some - // users. - - GtkWidget *child_window = GTK_WIDGET(gsFrame->GetViewport()->GetHandle()); - - gtk_widget_realize(child_window); // create the widget to allow to use GDK_WINDOW_* macro - gtk_widget_set_double_buffered(child_window, false); // Disable the widget double buffer, you will use the opengl one - - GdkWindow* draw_window = gtk_widget_get_window(child_window); - -#if GTK_MAJOR_VERSION < 3 - Window Xwindow = GDK_WINDOW_XWINDOW(draw_window); -#else - Window Xwindow = GDK_WINDOW_XID(draw_window); -#endif - Display* XDisplay = GDK_WINDOW_XDISPLAY(draw_window); - - pDsp[0] = (uptr)XDisplay; - pDsp[1] = (uptr)Xwindow; -#else - pDsp[0] = (uptr)gsFrame->GetViewport()->GetHandle(); - pDsp[1] = NULL; -#endif - - gsFrame->ShowFullScreen( g_Conf->GSWindow.IsFullscreen ); + std::optional wi = gsFrame->GetViewport()->GetWindowInfo(); + pxAssertDev(wi.has_value(), "GS frame has a valid native window"); + g_gs_window_info = std::move(*wi); #ifndef DISABLE_RECORDING // Enable New & Play after the first game load of the session diff --git a/pcsx2/gui/Dialogs/GSDumpDialog.cpp b/pcsx2/gui/Dialogs/GSDumpDialog.cpp index b1cace7932..13e7f1682b 100644 --- a/pcsx2/gui/Dialogs/GSDumpDialog.cpp +++ b/pcsx2/gui/Dialogs/GSDumpDialog.cpp @@ -775,7 +775,7 @@ void Dialogs::GSDumpDialog::GSThread::ExecuteTaskInThread() } GSsetBaseMem((u8*)regs); - if (GSopen2((void**)pDsp, (renderer_override<<24)) != 0) + if (GSopen2(g_gs_window_info, (renderer_override<<24)) != 0) { OnStop(); return; diff --git a/pcsx2/gui/FrameForGS.cpp b/pcsx2/gui/FrameForGS.cpp index 9ec13903bc..b728766c83 100644 --- a/pcsx2/gui/FrameForGS.cpp +++ b/pcsx2/gui/FrameForGS.cpp @@ -43,6 +43,20 @@ #include #include +#ifdef __WXGTK__ +#include +#include + +// Junk X11 macros... +#ifdef DisableScreenSaver +#undef DisableScreenSaver +#endif +#endif + +#ifdef GDK_WINDOWING_WAYLAND +#include +#endif + //#define GSWindowScaleDebug static const KeyAcceleratorCode FULLSCREEN_TOGGLE_ACCELERATOR_GSPANEL=KeyAcceleratorCode( WXK_RETURN ).Alt(); @@ -229,6 +243,10 @@ GSPanel::GSPanel( wxWindow* parent ) GSPanel::~GSPanel() { //CoreThread.Suspend( false ); // Just in case...! + +#ifdef WAYLAND_API + WaylandDestroySubsurface(); +#endif } void GSPanel::DoShowMouse() @@ -243,6 +261,74 @@ void GSPanel::DoShowMouse() m_HideMouseTimer.Start( 1750, true ); } +std::optional GSPanel::GetWindowInfo() +{ + WindowInfo ret; + + const wxSize gs_vp_size(GetClientSize()); + ret.surface_scale = static_cast(GetContentScaleFactor()); + ret.surface_width = static_cast(gs_vp_size.GetWidth()); + ret.surface_height = static_cast(gs_vp_size.GetHeight()); + +#if defined(_WIN32) + ret.type = WindowInfo::Type::Win32; + ret.window_handle = GetHandle(); +#elif defined(__WXGTK__) + GtkWidget* child_window = GTK_WIDGET(GetHandle()); + + // create the widget to allow to use GDK_WINDOW_* macro + gtk_widget_realize(child_window); + + // Disable the widget double buffer, you will use the opengl one + gtk_widget_set_double_buffered(child_window, false); + + GdkWindow* draw_window = gtk_widget_get_window(child_window); + + // TODO: Do we even want to support GTK2? +#if GTK_MAJOR_VERSION < 3 + ret.type = WindowInfo::Type::X11; + ret.display_connection = GDK_WINDOW_XDISPLAY(draw_window); + ret.window_handle = reinterpret_cast(GDK_WINDOW_XWINDOW(draw_window)); +#else +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_WINDOW(draw_window)) + { + ret.type = WindowInfo::Type::X11; + ret.display_connection = GDK_WINDOW_XDISPLAY(draw_window); + ret.window_handle = reinterpret_cast(GDK_WINDOW_XID(draw_window)); + + // GTK/X11 seems to not scale coordinates? + ret.surface_width = static_cast(ret.surface_width * ret.surface_scale); + ret.surface_height = static_cast(ret.surface_height * ret.surface_scale); + } +#endif // GDK_WINDOWING_X11 +#if defined(GDK_WINDOWING_WAYLAND) && defined(WAYLAND_API) + if (GDK_IS_WAYLAND_WINDOW(draw_window)) + { + wl_display* display = gdk_wayland_display_get_wl_display(gdk_window_get_display(draw_window)); + wl_surface* parent_surface = gdk_wayland_window_get_wl_surface(draw_window); + if (!m_wl_child_surface && !WaylandCreateSubsurface(display, parent_surface)) + return std::nullopt; + + ret.type = WindowInfo::Type::Wayland; + ret.display_connection = display; + ret.window_handle = m_wl_child_surface; + } +#endif // GDK_WINDOWING_WAYLAND +#endif // GTK_MAJOR_VERSION >= 3 +#elif defined(__WXOSX__) + ret.type = WindowInfo::Type::MacOS; + ret.window_handle = GetHandle(); +#endif + + if (ret.type == WindowInfo::Type::Surfaceless) + { + Console.Error("Unknown window type for GSFrame."); + return std::nullopt; + } + + return ret; +} void GSPanel::OnResize(wxSizeEvent& event) { @@ -475,6 +561,103 @@ void GSPanel::OnLeftDclick(wxMouseEvent& evt) DirectKeyCommand(FULLSCREEN_TOGGLE_ACCELERATOR_GSPANEL); } +#if defined(__WXGTK__) && defined(GDK_WINDOWING_WAYLAND) && defined(WAYLAND_API) + +void GSPanel::WaylandGlobalRegistryAddHandler(void* data, wl_registry* registry, uint32_t id, const char* interface, uint32_t version) +{ + GSPanel* pnl = static_cast(data); + if (std::strcmp(interface, wl_compositor_interface.name) == 0) + { + pnl->m_wl_compositor = static_cast(wl_registry_bind(registry, id, &wl_compositor_interface, wl_compositor_interface.version)); + } + else if (std::strcmp(interface, wl_subcompositor_interface.name) == 0) + { + pnl->m_wl_subcompositor = static_cast(wl_registry_bind(registry, id, &wl_subcompositor_interface, wl_subcompositor_interface.version)); + } +} + +void GSPanel::WaylandGlobalRegistryRemoveHandler(void* data, wl_registry* registry, uint32_t id) +{ + +} + +bool GSPanel::WaylandCreateSubsurface(wl_display* display, wl_surface* surface) +{ + static constexpr wl_registry_listener registry_listener = { + &GSPanel::WaylandGlobalRegistryAddHandler, + &GSPanel::WaylandGlobalRegistryRemoveHandler + }; + + wl_registry* registry = wl_display_get_registry(display); + wl_registry_add_listener(registry, ®istry_listener, this); + wl_display_flush(display); + wl_display_roundtrip(display); + if (!m_wl_compositor || !m_wl_subcompositor) + { + Console.Error("Missing wl_compositor or wl_subcompositor"); + return false; + } + + wl_registry_destroy(registry); + + m_wl_child_surface = wl_compositor_create_surface(m_wl_compositor); + if (!m_wl_child_surface) + { + Console.Error("Failed to create compositor surface"); + return false; + } + + wl_region* input_region = wl_compositor_create_region(m_wl_compositor); + if (!input_region) + { + Console.Error("Failed to create input region"); + return false; + } + wl_surface_set_input_region(m_wl_child_surface, input_region); + wl_region_destroy(input_region); + + m_wl_child_subsurface = wl_subcompositor_get_subsurface(m_wl_subcompositor, m_wl_child_surface, surface); + if (!m_wl_child_subsurface) + { + Console.Error("Failed to create subsurface"); + return false; + } + + // we want to present asynchronously to the surrounding window + wl_subsurface_set_desync(m_wl_child_subsurface); + return true; +} + +void GSPanel::WaylandDestroySubsurface() +{ + if (m_wl_child_subsurface) + { + wl_subsurface_destroy(m_wl_child_subsurface); + m_wl_child_subsurface = nullptr; + } + + if (m_wl_child_surface) + { + wl_surface_destroy(m_wl_child_surface); + m_wl_child_surface = nullptr; + } + + if (m_wl_subcompositor) + { + wl_subcompositor_destroy(m_wl_subcompositor); + m_wl_subcompositor = nullptr; + } + + if (m_wl_compositor) + { + wl_compositor_destroy(m_wl_compositor); + m_wl_compositor = nullptr; + } +} + +#endif + + // -------------------------------------------------------------------------------------- // GSFrame Implementation // -------------------------------------------------------------------------------------- diff --git a/pcsx2/gui/GSFrame.h b/pcsx2/gui/GSFrame.h index f450dce3b8..e141f53d15 100644 --- a/pcsx2/gui/GSFrame.h +++ b/pcsx2/gui/GSFrame.h @@ -18,7 +18,13 @@ #include "AppCommon.h" #include "CpuUsageProvider.h" +#include "common/WindowInfo.h" #include +#include + +#ifdef WAYLAND_API +#include +#endif // -------------------------------------------------------------------------------------- // GSPanel @@ -41,6 +47,8 @@ public: GSPanel( wxWindow* parent ); virtual ~GSPanel(); + std::optional GetWindowInfo(); + void DoShowMouse(); void DirectKeyCommand( wxKeyEvent& evt ); void DirectKeyCommand( const KeyAcceleratorCode& kac ); @@ -67,6 +75,20 @@ protected: void OnLeftDclick( wxMouseEvent& evt ); void UpdateScreensaver(); + +private: +#ifdef WAYLAND_API + static void WaylandGlobalRegistryAddHandler(void* data, wl_registry* registry, uint32_t id, const char* interface, uint32_t version); + static void WaylandGlobalRegistryRemoveHandler(void* data, wl_registry* registry, uint32_t id); + + bool WaylandCreateSubsurface(wl_display* display, wl_surface* parent_surface); + void WaylandDestroySubsurface(); + + wl_compositor* m_wl_compositor = nullptr; + wl_subcompositor* m_wl_subcompositor = nullptr; + wl_surface* m_wl_child_surface = nullptr; + wl_subsurface* m_wl_child_subsurface = nullptr; +#endif };