mirror of https://github.com/PCSX2/pcsx2.git
Replace pDsp with WindowInfo
This commit is contained in:
parent
114d78d378
commit
0f5ed59e50
|
@ -183,7 +183,7 @@ void DEV9shutdown()
|
|||
delete dev9.ata;
|
||||
}
|
||||
|
||||
s32 DEV9open(void* pDsp)
|
||||
s32 DEV9open()
|
||||
{
|
||||
DevCon.WriteLn("DEV9: DEV9open");
|
||||
LoadConf();
|
||||
|
|
|
@ -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);
|
||||
|
|
297
pcsx2/GS/GS.cpp
297
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<GSWndEGL_X11>());
|
||||
break;
|
||||
#endif
|
||||
#if GS_EGL_WL
|
||||
case EGL_PLATFORM_WAYLAND_KHR:
|
||||
wnds.push_back(std::make_shared<GSWndEGL_WL>());
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (std::shared_ptr<GSWndEGL> 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<GSRendererType>(theApp.GetConfigI("Renderer"));
|
||||
|
||||
if (m_renderer != GSRendererType::OGL_HW && m_renderer != GSRendererType::OGL_SW)
|
||||
{
|
||||
fprintf(stderr, "wrong renderer selected %d\n", static_cast<int>(m_renderer));
|
||||
return;
|
||||
}
|
||||
|
||||
struct Packet
|
||||
{
|
||||
uint8 type, param;
|
||||
uint32 size, addr;
|
||||
std::vector<uint8> buff;
|
||||
};
|
||||
|
||||
std::list<Packet*> packets;
|
||||
std::vector<uint8> 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<GSDeviceOGL*>(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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<int>(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<std::mutex> lock(m_pGSsetTitle_Crit);
|
||||
std::lock_guard<std::mutex> 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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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<HWND>(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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -18,15 +18,14 @@
|
|||
|
||||
#if defined(__unix__)
|
||||
|
||||
// static method
|
||||
int GSWndEGL::SelectPlatform()
|
||||
std::shared_ptr<GSWndEGL> 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<GSWndEGL_X11>();
|
||||
}
|
||||
#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<GSWndEGL_WL>();
|
||||
}
|
||||
#endif
|
||||
|
||||
fprintf(stderr, "EGL: no compatible platform found\n");
|
||||
|
||||
return 0;
|
||||
fprintf(stderr, "EGL: no compatible platform found for wintype %u\n", static_cast<unsigned>(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<Window>(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<wl_surface*>(wi.window_handle),
|
||||
static_cast<int>(wi.surface_width),
|
||||
static_cast<int>(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
|
||||
|
|
|
@ -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<GSWndEGL> 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 <X11/Xlib.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
|
||||
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<void*>(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 <wayland-client-protocol.h>
|
||||
#include <wayland-egl.h>
|
||||
|
||||
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<void*>(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
|
||||
|
|
|
@ -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<HWND>(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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// 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)
|
||||
|
|
|
@ -31,13 +31,15 @@ enum PadOptions
|
|||
PADOPTION_MOUSE_R = 0x40,
|
||||
};
|
||||
|
||||
struct WindowInfo;
|
||||
|
||||
extern FILE* padLog;
|
||||
extern void initLogging();
|
||||
|
||||
extern HostKeyEvent event;
|
||||
extern MtQueue<HostKeyEvent> 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);
|
||||
|
|
|
@ -262,6 +262,9 @@ void UpdateKeyboardInput()
|
|||
g_ev_fifo.consume_all(AnalyzeKeyEvent);
|
||||
|
||||
// keyboard input
|
||||
if (!GSdsp)
|
||||
return;
|
||||
|
||||
while (XPending(GSdsp) > 0)
|
||||
{
|
||||
XNextEvent(GSdsp, &E);
|
||||
|
|
|
@ -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<Display*>(wi.display_connection);
|
||||
GSwin = reinterpret_cast<Window>(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);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Global.h"
|
||||
#include "Common/WindowInfo.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
|
@ -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<HWND>(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<HWND>(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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//////
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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<HWND>(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<Display*>(wi.display_connection);
|
||||
g_GSwin = reinterpret_cast<Window>(wi.window_handle);
|
||||
window_handle_for_init = reinterpret_cast<void*>(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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "gui/wxAppWithHelpers.h"
|
||||
#include "wxAppWithHelpers.h"
|
||||
#include "common/WindowInfo.h"
|
||||
|
||||
#include <wx/fileconf.h>
|
||||
#include <wx/apptrait.h>
|
||||
|
@ -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)();
|
||||
|
|
|
@ -73,7 +73,7 @@ wxIMPLEMENT_APP(Pcsx2App);
|
|||
|
||||
std::unique_ptr<AppConfig> 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<WindowInfo> 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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -43,6 +43,20 @@
|
|||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#ifdef __WXGTK__
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
// Junk X11 macros...
|
||||
#ifdef DisableScreenSaver
|
||||
#undef DisableScreenSaver
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include <gdk/gdkwayland.h>
|
||||
#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<WindowInfo> GSPanel::GetWindowInfo()
|
||||
{
|
||||
WindowInfo ret;
|
||||
|
||||
const wxSize gs_vp_size(GetClientSize());
|
||||
ret.surface_scale = static_cast<float>(GetContentScaleFactor());
|
||||
ret.surface_width = static_cast<u32>(gs_vp_size.GetWidth());
|
||||
ret.surface_height = static_cast<u32>(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<void*>(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<void*>(GDK_WINDOW_XID(draw_window));
|
||||
|
||||
// GTK/X11 seems to not scale coordinates?
|
||||
ret.surface_width = static_cast<u32>(ret.surface_width * ret.surface_scale);
|
||||
ret.surface_height = static_cast<u32>(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<GSPanel*>(data);
|
||||
if (std::strcmp(interface, wl_compositor_interface.name) == 0)
|
||||
{
|
||||
pnl->m_wl_compositor = static_cast<wl_compositor*>(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_subcompositor*>(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
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
|
@ -18,7 +18,13 @@
|
|||
|
||||
#include "AppCommon.h"
|
||||
#include "CpuUsageProvider.h"
|
||||
#include "common/WindowInfo.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#ifdef WAYLAND_API
|
||||
#include <wayland-client.h>
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// GSPanel
|
||||
|
@ -41,6 +47,8 @@ public:
|
|||
GSPanel( wxWindow* parent );
|
||||
virtual ~GSPanel();
|
||||
|
||||
std::optional<WindowInfo> 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
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue