GS: Remove GSWnd and use GL::Context

This commit is contained in:
Connor McLaughlin 2021-07-09 00:33:44 +10:00 committed by refractionpcsx2
parent 198fc2629e
commit 5ba70c8c20
29 changed files with 207 additions and 1162 deletions

View File

@ -664,7 +664,6 @@ set(pcsx2GSSources
GS/Renderers/OpenGL/GSTextureCacheOGL.cpp
GS/Renderers/OpenGL/GSTextureOGL.cpp
GS/Window/GSSetting.cpp
GS/Window/GSWnd.cpp
)
# GS headers
@ -734,7 +733,6 @@ set(pcsx2GSHeaders
GS/Window/GSDialog.h
GS/Window/GSSetting.h
GS/Window/GSSettingsDlg.h
GS/Window/GSWnd.h
)
if(WIN32)
@ -807,16 +805,12 @@ if(WIN32)
GS/Window/GSCaptureDlg.cpp
GS/Window/GSDialog.cpp
GS/Window/GSSettingsDlg.cpp
GS/Window/GSWndDX.cpp
GS/Window/GSWndWGL.cpp
)
list(APPEND pcsx2GSHeaders
GS/Renderers/DX11/GSDevice11.h
GS/Renderers/DX11/GSRendererDX11.h
GS/Renderers/DX11/GSTexture11.h
GS/Renderers/DX11/GSTextureCache11.h
GS/Window/GSWndDX.h
GS/Window/GSWndWGL.h
)
else(WIN32)
list(APPEND pcsx2SPU2Sources
@ -902,12 +896,10 @@ else(WIN32)
list(APPEND pcsx2GSSources
GS/GS_res.cpp
GS/Window/GSLinuxDialog.cpp
GS/Window/GSWndEGL.cpp
)
list(APPEND pcsx2GSHeaders
GS/GS_res.h
GS/Window/GSWndEGL.h
)
endif(WIN32)
@ -1394,14 +1386,9 @@ if(Linux)
target_link_libraries(PCSX2_FLAGS INTERFACE
PkgConfig::AIO
PkgConfig::EGL
PkgConfig::LIBUDEV
ALSA::ALSA
)
elseif(UNIX AND NOT APPLE)
target_link_libraries(PCSX2_FLAGS INTERFACE
PkgConfig::EGL
)
endif()
if(UNIX AND NOT APPLE)

View File

@ -30,8 +30,6 @@
#include "Renderers/DX11/GSRendererDX11.h"
#include "Renderers/DX11/GSDevice11.h"
#include "Window/GSWndDX.h"
#include "Window/GSWndWGL.h"
#include "Window/GSSettingsDlg.h"
@ -39,8 +37,6 @@ static HRESULT s_hr = E_FAIL;
#else
#include "GS/Window/GSWndEGL.h"
#ifdef __APPLE__
#include <gtk/gtk.h>
#include <CoreFoundation/CoreFoundation.h>
@ -64,6 +60,13 @@ static bool s_exclusive = true;
static std::string s_renderer_name;
bool gsopen_done = false; // crash guard for GSgetTitleInfo2 and GSKeyEvent (replace with lock?)
#ifndef PCSX2_CORE
static std::atomic_bool s_gs_window_resized{false};
static std::mutex s_gs_window_resized_lock;
static int s_new_gs_window_width = 0;
static int s_new_gs_window_height = 0;
#endif
void GSsetBaseMem(uint8* mem)
{
s_basemem = mem;
@ -126,6 +129,11 @@ void GSclose()
{
gsopen_done = false;
#ifndef PCSX2_CORE
// Make sure we don't have any leftover resize events from our last open.
s_gs_window_resized.store(false);
#endif
if (s_gs == NULL)
return;
@ -136,11 +144,6 @@ void GSclose()
delete s_gs->m_dev;
s_gs->m_dev = NULL;
if (s_gs->m_wnd)
{
s_gs->m_wnd->Detach();
}
}
int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, int threads = -1)
@ -177,60 +180,7 @@ int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, in
theApp.SetCurrentRendererType(renderer);
}
std::shared_ptr<GSWnd> window;
{
// Select the window first to detect the GL requirement
std::vector<std::shared_ptr<GSWnd>> wnds;
switch (renderer)
{
case GSRendererType::OGL_HW:
case GSRendererType::OGL_SW:
#if defined(__unix__)
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
wnds.push_back(std::make_shared<GSWndWGL>());
#endif
break;
default:
#ifdef _WIN32
wnds.push_back(std::make_shared<GSWndDX>());
#elif defined(__APPLE__)
// No windows available for macOS at the moment
#else
wnds.push_back(std::make_shared<GSWndEGL_X11>());
#endif
break;
}
for (auto& wnd : wnds)
{
try
{
if (!wnd->Attach(wi))
continue;
window = wnd; // Previous code will throw if window isn't supported
break;
}
catch (GSRecoverableError)
{
wnd->Detach();
}
}
if (!window)
{
GSclose();
return -1;
}
}
std::string renderer_name;
switch (renderer)
{
default:
@ -288,8 +238,6 @@ int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, in
if (s_gs == NULL)
return -1;
}
s_gs->m_wnd = window;
}
catch (std::exception& ex)
{
@ -300,7 +248,7 @@ int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, in
s_gs->SetRegsMem(s_basemem);
s_gs->SetVSync(s_vsync);
if (!s_gs->CreateDevice(dev))
if (!s_gs->CreateDevice(dev, wi))
{
// This probably means the user has DX11 configured with a video card that is only DX9
// compliant. Cound mean drivr issues of some sort also, but to be sure, that's the most
@ -756,6 +704,28 @@ void GSsetExclusive(int enabled)
}
}
#ifndef PCSX2_CORE
void GSResizeWindow(int width, int height)
{
std::unique_lock lock(s_gs_window_resized_lock);
s_new_gs_window_width = width;
s_new_gs_window_height = height;
s_gs_window_resized.store(true);
}
bool GSCheckForWindowResize(int* new_width, int* new_height)
{
if (!s_gs_window_resized.load())
return false;
std::unique_lock lock(s_gs_window_resized_lock);
*new_width = s_new_gs_window_width;
*new_height = s_new_gs_window_height;
s_gs_window_resized.store(false);
return true;
}
#endif
std::string format(const char* fmt, ...)
{
va_list args;

View File

@ -20,6 +20,7 @@
#include "config.h"
#include "common/Pcsx2Types.h"
#include "common/WindowInfo.h"
#include "GS_types.h"
#include "Window/GSSetting.h"
#include "SaveState.h"
@ -1794,6 +1795,12 @@ void GSsetFrameSkip(int frameskip);
void GSsetVsync(int vsync);
void GSsetExclusive(int enabled);
#ifndef PCSX2_CORE
// Needed for window resizing in wx. Can be safely called from the UI thread.
void GSResizeWindow(int width, int height);
bool GSCheckForWindowResize(int* new_width, int* new_height);
#endif
class GSApp
{
std::string m_section;

View File

@ -18,8 +18,7 @@
#include "GSDevice.h"
GSDevice::GSDevice()
: m_wnd()
, m_vsync(false)
: m_vsync(false)
, m_rbswapped(false)
, m_backbuffer(NULL)
, m_merge(NULL)
@ -46,10 +45,8 @@ GSDevice::~GSDevice()
delete m_target_tmp;
}
bool GSDevice::Create(const std::shared_ptr<GSWnd>& wnd)
bool GSDevice::Create(const WindowInfo& wi)
{
m_wnd = wnd;
return true;
}
@ -73,27 +70,19 @@ bool GSDevice::Reset(int w, int h)
m_target_tmp = NULL;
m_current = NULL; // current is special, points to other textures, no need to delete
return m_wnd != NULL;
return true;
}
void GSDevice::Present(const GSVector4i& r, int shader)
{
const GSVector4i cr = m_wnd->GetClientRect();
const int w = std::max<int>(cr.width(), 1);
const int h = std::max<int>(cr.height(), 1);
if (!m_backbuffer || m_backbuffer->GetWidth() != w || m_backbuffer->GetHeight() != h)
{
if (!Reset(w, h))
{
return;
}
}
GL_PUSH("Present");
#ifndef PCSX2_CORE
int new_width, new_height;
if (GSCheckForWindowResize(&new_width, &new_height) && !Reset(new_width, new_height))
return;
#endif
// FIXME is it mandatory, it could be slow
ClearRenderTarget(m_backbuffer, 0);

View File

@ -15,8 +15,8 @@
#pragma once
#include "common/WindowInfo.h"
#include "GSFastList.h"
#include "GS/Window/GSWnd.h"
#include "GSTexture.h"
#include "GSVertex.h"
#include "GS/GSAlignedClass.h"
@ -145,7 +145,6 @@ protected:
static const int m_NO_BLEND = 0;
static const int m_MERGE_BLEND = m_blendMap.size() - 1;
std::shared_ptr<GSWnd> m_wnd;
int m_vsync;
bool m_rbswapped;
GSTexture* m_backbuffer;
@ -190,7 +189,7 @@ public:
DontCare
};
virtual bool Create(const std::shared_ptr<GSWnd>& wnd);
virtual bool Create(const WindowInfo& wi);
virtual bool Reset(int w, int h);
virtual bool IsLost(bool update = false) { return false; }
virtual void Present(const GSVector4i& r, int shader);
@ -247,6 +246,8 @@ public:
bool ResizeTarget(GSTexture** t);
bool IsRBSwapped() { return m_rbswapped; }
int GetBackbufferWidth() const { return m_backbuffer ? m_backbuffer->GetWidth() : 0; }
int GetBackbufferHeight() const { return m_backbuffer ? m_backbuffer->GetHeight() : 0; }
void AgePool();
void PurgePool();

View File

@ -31,7 +31,6 @@ GSRenderer::GSRenderer()
, m_control_key(false)
, m_texture_shuffle(false)
, m_real_size(0, 0)
, m_wnd()
, m_dev(NULL)
{
m_GStitleInfoBuffer[0] = 0;
@ -56,12 +55,12 @@ GSRenderer::~GSRenderer()
delete m_dev;
}
bool GSRenderer::CreateDevice(GSDevice* dev)
bool GSRenderer::CreateDevice(GSDevice* dev, const WindowInfo& wi)
{
ASSERT(dev);
ASSERT(!m_dev);
if (!dev->Create(m_wnd))
if (!dev->Create(wi))
{
return false;
}
@ -468,7 +467,7 @@ void GSRenderer::VSync(int field)
// This will scale the OSD to the window's size.
// Will maintiain the font size no matter what size the window is.
GSVector4i window_size = m_wnd->GetClientRect();
GSVector4i window_size(0, 0, m_dev->GetBackbufferWidth(), m_dev->GetBackbufferHeight());
m_dev->m_osd.m_real_size.x = window_size.v[2];
m_dev->m_osd.m_real_size.y = window_size.v[3];
@ -568,8 +567,7 @@ bool GSRenderer::MakeSnapshot(const std::string& path)
bool GSRenderer::BeginCapture(std::string& filename)
{
const GSVector4i crect(m_wnd->GetClientRect());
GSVector4i disp = ComputeDrawRectangle(crect.z, crect.w);
GSVector4i disp = ComputeDrawRectangle(m_dev->GetBackbufferWidth(), m_dev->GetBackbufferHeight());
float aspect = (float)disp.width() / std::max(1, disp.height());
return m_capture.BeginCapture(GetTvRefreshRate(), GetInternalResolution(), aspect, filename);

View File

@ -16,7 +16,6 @@
#pragma once
#include "GS/GS.h"
#include "GS/Window/GSWnd.h"
#include "GS/GSState.h"
#include "GS/GSCapture.h"
@ -48,14 +47,13 @@ protected:
virtual GSTexture* GetFeedbackOutput() { return nullptr; }
public:
std::shared_ptr<GSWnd> m_wnd;
GSDevice* m_dev;
public:
GSRenderer();
virtual ~GSRenderer();
virtual bool CreateDevice(GSDevice* dev);
virtual bool CreateDevice(GSDevice* dev, const WindowInfo& wi);
virtual void ResetDevice();
virtual void VSync(int field);
virtual bool MakeSnapshot(const std::string& path);

View File

@ -74,11 +74,11 @@ bool GSDevice11::SetFeatureLevel(D3D_FEATURE_LEVEL level, bool compat_mode)
return true;
}
bool GSDevice11::Create(const std::shared_ptr<GSWnd>& wnd)
bool GSDevice11::Create(const WindowInfo& wi)
{
bool nvidia_vendor = false;
if (!__super::Create(wnd))
if (!__super::Create(wi))
{
return false;
}
@ -177,7 +177,7 @@ bool GSDevice11::Create(const std::shared_ptr<GSWnd>& wnd)
swapchain_description.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
const HRESULT result = factory->CreateSwapChainForHwnd(
m_dev.get(), reinterpret_cast<HWND>(m_wnd->GetHandle()),
m_dev.get(), reinterpret_cast<HWND>(wi.window_handle),
&swapchain_description, nullptr, nullptr, m_swapchain.put());
if (FAILED(result))
@ -382,7 +382,7 @@ bool GSDevice11::Create(const std::shared_ptr<GSWnd>& wnd)
//
Reset(1, 1);
Reset(wi.surface_width, wi.surface_height);
//

View File

@ -525,7 +525,7 @@ public:
bool SetFeatureLevel(D3D_FEATURE_LEVEL level, bool compat_mode);
void GetFeatureLevel(D3D_FEATURE_LEVEL& level) const { level = m_shader.level; }
bool Create(const std::shared_ptr<GSWnd>& wnd);
bool Create(const WindowInfo& wi);
bool Reset(int w, int h);
void Flip();
void SetVSync(int vsync) final;

View File

@ -24,11 +24,6 @@ GSRendererDX11::GSRendererDX11()
ResetStates();
}
bool GSRendererDX11::CreateDevice(GSDevice* dev)
{
return GSRenderer::CreateDevice(dev);
}
void GSRendererDX11::SetupIA(const float& sx, const float& sy)
{
GSDevice11* dev = (GSDevice11*)m_dev;

View File

@ -58,6 +58,4 @@ public:
virtual ~GSRendererDX11() {}
void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) final;
bool CreateDevice(GSDevice* dev);
};

View File

@ -16,9 +16,9 @@
#include "PrecompiledHeader.h"
#include "GSDeviceNull.h"
bool GSDeviceNull::Create(const std::shared_ptr<GSWnd>& wnd)
bool GSDeviceNull::Create(const WindowInfo& wi)
{
if (!GSDevice::Create(wnd))
if (!GSDevice::Create(wi))
return false;
Reset(1, 1);

View File

@ -30,6 +30,6 @@ private:
public:
GSDeviceNull() {}
bool Create(const std::shared_ptr<GSWnd>& wnd);
bool Create(const WindowInfo& wi);
bool Reset(int w, int h);
};

View File

@ -305,9 +305,27 @@ GSTexture* GSDeviceOGL::FetchSurface(int type, int w, int h, int format)
return t;
}
bool GSDeviceOGL::Create(const std::shared_ptr<GSWnd>& wnd)
bool GSDeviceOGL::Create(const WindowInfo& wi)
{
std::vector<char> shader;
m_gl_context = GL::Context::Create(wi, GL::Context::GetAllVersionsList());
if (!m_gl_context || !m_gl_context->MakeCurrent())
return false;
// Check openGL requirement as soon as possible so we can switch to another
// renderer/device
try
{
GLLoader::check_gl_requirements();
}
catch (std::exception& ex)
{
printf("GS error: Exception caught in GSDeviceOGL::Create: %s", ex.what());
m_gl_context->DoneCurrent();
return false;
}
// ****************************************************************
// Debug helper
// ****************************************************************
@ -584,11 +602,10 @@ bool GSDeviceOGL::Create(const std::shared_ptr<GSWnd>& wnd)
// ****************************************************************
// Finish window setup and backbuffer
// ****************************************************************
if (!GSDevice::Create(wnd))
if (!GSDevice::Create(wi))
return false;
const GSVector4i rect = wnd->GetClientRect();
Reset(rect.z, rect.w);
Reset(wi.surface_width, wi.surface_height);
// Basic to ensure structures are correctly packed
static_assert(sizeof(VSSelector) == 4, "Wrong VSSelector size");
@ -645,19 +662,20 @@ bool GSDeviceOGL::Reset(int w, int h)
// Opengl allocate the backbuffer with the window. The render is done in the backbuffer when
// there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done
// in the backbuffer
m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, 0, m_fbo_read, false);
m_gl_context->ResizeSurface(w, h);
m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, m_gl_context->GetSurfaceWidth(),
m_gl_context->GetSurfaceHeight(), 0, m_fbo_read, false);
return true;
}
void GSDeviceOGL::SetVSync(int vsync)
{
m_wnd->SetVSync(vsync);
m_gl_context->SetSwapInterval(vsync);
}
void GSDeviceOGL::Flip()
{
m_wnd->Flip();
m_gl_context->SwapBuffers();
if (GLLoader::in_replayer)
{

View File

@ -15,6 +15,7 @@
#pragma once
#include "common/GL/Context.h"
#include "GS/Renderers/Common/GSDevice.h"
#include "GSTextureOGL.h"
#include "GS/GS.h"
@ -464,6 +465,7 @@ public:
static int m_shader_reg;
private:
std::unique_ptr<GL::Context> m_gl_context;
int m_force_texture_clear;
int m_mipmap;
TriFiltering m_filter;
@ -581,10 +583,10 @@ public:
// Used by OpenGL, so the same calling convention is required.
static void APIENTRY DebugOutputToFile(GLenum gl_source, GLenum gl_type, GLuint id, GLenum gl_severity, GLsizei gl_length, const GLchar* gl_message, const void* userParam);
bool Create(const std::shared_ptr<GSWnd>& wnd);
bool Reset(int w, int h);
void Flip();
void SetVSync(int vsync);
bool Create(const WindowInfo& wi) override;
bool Reset(int w, int h) override;
void Flip() override;
void SetVSync(int vsync) override;
void DrawPrimitive() final;
void DrawPrimitive(int offset, int count);

View File

@ -33,11 +33,6 @@ GSRendererOGL::GSRendererOGL()
ResetStates();
}
bool GSRendererOGL::CreateDevice(GSDevice* dev)
{
return GSRenderer::CreateDevice(dev);
}
void GSRendererOGL::SetupIA(const float& sx, const float& sy)
{
GL_PUSH("IA");

View File

@ -71,8 +71,6 @@ public:
GSRendererOGL();
virtual ~GSRendererOGL() {}
bool CreateDevice(GSDevice* dev);
void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) final;
PRIM_OVERLAP PrimitiveOverlap();

View File

@ -1,47 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "GSWnd.h"
void GSWndGL::PopulateGlFunction()
{
if (!gladLoadGL())
throw GSRecoverableError();
// Check openGL requirement as soon as possible so we can switch to another
// renderer/device
GLLoader::check_gl_requirements();
}
void GSWndGL::FullContextInit()
{
CreateContext(3, 3);
AttachContext();
PopulateGlFunction();
PopulateWndGlFunction();
}
void GSWndGL::SetVSync(int vsync)
{
if (!HasLateVsyncSupport() && vsync < 0)
m_vsync = -vsync; // Late vsync not supported, fallback to standard vsync
else
m_vsync = vsync;
// The WGL/GLX/EGL swap interval function must be called on the rendering
// thread or else the change won't be properly applied.
m_vsync_change_requested = true;
}

View File

@ -1,68 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "PrecompiledHeader.h"
#include "common/WindowInfo.h"
#include "GS/GS.h"
#include "GS/GSVector.h"
class GSWnd
{
public:
GSWnd() = default;
virtual ~GSWnd() = default;
virtual bool Attach(const WindowInfo& wi) = 0;
virtual void Detach() = 0;
virtual void* GetHandle() = 0;
virtual GSVector4i GetClientRect() = 0;
virtual void AttachContext() {}
virtual void DetachContext() {}
virtual void Flip() {}
virtual void SetVSync(int vsync) {}
};
class GSWndGL : public GSWnd
{
protected:
bool m_ctx_attached;
std::atomic<bool> m_vsync_change_requested;
std::atomic<int> m_vsync;
bool IsContextAttached() const { return m_ctx_attached; }
void PopulateGlFunction();
virtual void PopulateWndGlFunction() = 0;
void FullContextInit();
virtual void CreateContext(int major, int minor) = 0;
virtual void SetSwapInterval() = 0;
virtual bool HasLateVsyncSupport() = 0;
public:
GSWndGL()
: m_ctx_attached(false)
, m_vsync_change_requested(false)
, m_vsync(0)
{
}
virtual ~GSWndGL() override = default;
void SetVSync(int vsync) final;
};

View File

@ -1,53 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "GSWndDX.h"
#ifdef _WIN32
GSWndDX::GSWndDX()
: m_hWnd(NULL)
{
}
GSWndDX::~GSWndDX()
{
}
bool GSWndDX::Attach(const WindowInfo& wi)
{
if (wi.type != WindowInfo::Type::Win32)
return false;
// TODO: subclass
m_hWnd = static_cast<HWND>(wi.window_handle);
return true;
}
void GSWndDX::Detach()
{
m_hWnd = {};
}
GSVector4i GSWndDX::GetClientRect()
{
GSVector4i r;
::GetClientRect(m_hWnd, r);
return r;
}
#endif

View File

@ -1,34 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "GSWnd.h"
#ifdef _WIN32
class GSWndDX final : public GSWnd
{
HWND m_hWnd;
public:
GSWndDX();
~GSWndDX() override;
bool Attach(const WindowInfo& wi) override;
void Detach() override;
void* GetHandle() override { return m_hWnd; }
GSVector4i GetClientRect() override;
};
#endif

View File

@ -1,313 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "GSWndEGL.h"
#if defined(__unix__)
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 nullptr;
}
fprintf(stdout, "EGL: Supported extensions: %s\n", client_extensions);
// Check platform extensions are supported (Note: there are core in 1.5)
if (!strstr(client_extensions, "EGL_EXT_platform_base"))
{
fprintf(stderr, "EGL: Dynamic platform selection isn't supported\n");
return nullptr;
}
// Finally we can select the platform
#if GS_EGL_X11
if (strstr(client_extensions, "EGL_EXT_platform_x11") && wi.type == WindowInfo::Type::X11)
{
fprintf(stdout, "EGL: select X11 platform\n");
return std::make_shared<GSWndEGL_X11>();
}
#endif
#if GS_EGL_WL
if (strstr(client_extensions, "EGL_EXT_platform_wayland") && wi.type == WindowInfo::Type::Wayland)
{
fprintf(stdout, "EGL: select Wayland platform\n");
return std::make_shared<GSWndEGL_WL>();
}
#endif
fprintf(stderr, "EGL: no compatible platform found for wintype %u\n", static_cast<unsigned>(wi.type));
return nullptr;
}
GSWndEGL::GSWndEGL(int platform)
: m_native_window(nullptr), m_platform(platform)
{
}
void GSWndEGL::CreateContext(int major, int minor)
{
EGLConfig eglConfig;
EGLint numConfigs = 0;
EGLint contextAttribs[] =
{
EGL_CONTEXT_MAJOR_VERSION_KHR, major,
EGL_CONTEXT_MINOR_VERSION_KHR, minor,
#ifdef ENABLE_OGL_DEBUG
EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR,
#else
// Open Source isn't happy with an unsupported flags...
//EGL_CONTEXT_FLAGS_KHR, GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR,
#endif
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
EGL_NONE
};
EGLint NullContextAttribs[] = {EGL_NONE};
EGLint attrList[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
BindAPI();
eglChooseConfig(m_eglDisplay, attrList, &eglConfig, 1, &numConfigs);
if (numConfigs == 0)
{
fprintf(stderr, "EGL: Failed to get a frame buffer config! (0x%x)\n", eglGetError());
throw GSRecoverableError();
}
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 (0x%x)\n", eglGetError());
throw GSRecoverableError();
}
m_eglContext = eglCreateContext(m_eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs);
EGLint status = eglGetError();
if (status == EGL_BAD_ATTRIBUTE || status == EGL_BAD_MATCH)
{
// Radeon/Gallium don't support advance attribute. Fallback to random value
// Note: Intel gives an EGL_BAD_MATCH. I don't know why but let's by stubborn and retry.
fprintf(stderr, "EGL: warning your driver doesn't support advance openGL context attributes\n");
m_eglContext = eglCreateContext(m_eglDisplay, eglConfig, EGL_NO_CONTEXT, NullContextAttribs);
status = eglGetError();
}
if (m_eglContext == EGL_NO_CONTEXT)
{
fprintf(stderr, "EGL: Failed to create the context\n");
fprintf(stderr, "EGL STATUS: %x\n", status);
throw GSRecoverableError();
}
if (!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
{
throw GSRecoverableError();
}
}
void GSWndEGL::AttachContext()
{
if (!IsContextAttached())
{
// The setting of the API is local to a thread. This function
// can be called from 2 threads.
BindAPI();
//fprintf(stderr, "Attach the context\n");
eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
m_ctx_attached = true;
}
}
void GSWndEGL::DetachContext()
{
if (IsContextAttached())
{
//fprintf(stderr, "Detach the context\n");
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
m_ctx_attached = false;
}
}
void GSWndEGL::PopulateWndGlFunction()
{
}
void GSWndEGL::BindAPI()
{
eglBindAPI(EGL_OPENGL_API);
EGLenum api = eglQueryAPI();
if (api != EGL_OPENGL_API)
{
fprintf(stderr, "EGL: Failed to bind the OpenGL API got 0x%x instead\n", api);
throw GSRecoverableError();
}
}
bool GSWndEGL::Attach(const WindowInfo& wi)
{
m_native_window = AttachNativeWindow(wi);
if (!m_native_window)
return false;
OpenEGLDisplay();
FullContextInit();
return true;
}
void GSWndEGL::Detach()
{
// Actually the destructor is not called when there is only a GSclose/GSshutdown
// The window still need to be closed
DetachContext();
eglDestroyContext(m_eglDisplay, m_eglContext);
m_eglContext = nullptr;
eglDestroySurface(m_eglDisplay, m_eglSurface);
m_eglSurface = nullptr;
CloseEGLDisplay();
DestroyNativeResources();
}
GSVector4i GSWndEGL::GetClientRect()
{
EGLint h = 0;
EGLint w = 0;
eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &h);
eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH, &w);
return GSVector4i(0, 0, w, h);
}
void GSWndEGL::SetSwapInterval()
{
// 0 -> disable vsync
// n -> wait n frame
eglSwapInterval(m_eglDisplay, m_vsync);
}
void GSWndEGL::Flip()
{
if (m_vsync_change_requested.exchange(false))
SetSwapInterval();
eglSwapBuffers(m_eglDisplay, m_eglSurface);
}
void GSWndEGL::CloseEGLDisplay()
{
eglReleaseThread();
eglTerminate(m_eglDisplay);
}
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 = nullptr;
m_eglDisplay = eglGetPlatformDisplay(m_platform, native_display, nullptr);
if (m_eglDisplay == EGL_NO_DISPLAY)
{
fprintf(stderr, "EGL: Failed to open a display! (0x%x)\n", eglGetError());
throw GSRecoverableError();
}
if (!eglInitialize(m_eglDisplay, nullptr, nullptr))
{
fprintf(stderr, "EGL: Failed to initialize the display! (0x%x)\n", eglGetError());
throw GSRecoverableError();
}
}
//////////////////////////////////////////////////////////////////////
// X11 platform
//////////////////////////////////////////////////////////////////////
#if GS_EGL_X11
GSWndEGL_X11::GSWndEGL_X11()
: GSWndEGL(EGL_PLATFORM_X11_KHR), m_NativeWindow(0)
{
}
void* GSWndEGL_X11::AttachNativeWindow(const WindowInfo& wi)
{
if (wi.type != WindowInfo::Type::X11)
return nullptr;
m_NativeWindow = reinterpret_cast<Window>(wi.window_handle);
return &m_NativeWindow;
}
void GSWndEGL_X11::DestroyNativeResources()
{
}
#endif
//////////////////////////////////////////////////////////////////////
// Wayland platform (just a place holder)
//////////////////////////////////////////////////////////////////////
#if GS_EGL_WL
GSWndEGL_WL::GSWndEGL_WL()
: GSWndEGL(EGL_PLATFORM_WAYLAND_KHR), m_NativeWindow(nullptr)
{
}
void* GSWndEGL_WL::AttachNativeWindow(const WindowInfo& wi)
{
if (wi.type != WindowInfo::Type::Wayland)
return nullptr;
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;
}
return m_NativeWindow;
}
void GSWndEGL_WL::DestroyNativeResources()
{
if (m_NativeWindow)
{
wl_egl_window_destroy(m_NativeWindow);
m_NativeWindow = nullptr;
}
}
#endif
#endif

View File

@ -1,111 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "GSWnd.h"
#if defined(__unix__)
#include <EGL/egl.h>
#include <EGL/eglext.h>
#define GS_EGL_X11 1
#define GS_EGL_WL 0
class GSWndEGL : public GSWndGL
{
void* m_native_window;
EGLDisplay m_eglDisplay;
EGLSurface m_eglSurface;
EGLContext m_eglContext;
int m_platform;
void PopulateWndGlFunction();
void CreateContext(int major, int minor);
void BindAPI();
void SetSwapInterval() final;
bool HasLateVsyncSupport() final { return false; }
void OpenEGLDisplay();
void CloseEGLDisplay();
public:
GSWndEGL(int platform);
virtual ~GSWndEGL(){};
static std::shared_ptr<GSWndEGL> CreateForPlatform(const WindowInfo& wi);
bool Attach(const WindowInfo& wi) final;
void Detach() final;
virtual void* AttachNativeWindow(const WindowInfo& wi) = 0;
virtual void DestroyNativeResources() = 0;
GSVector4i GetClientRect();
void AttachContext() final;
void DetachContext() final;
void Flip() final;
};
#if GS_EGL_X11
#include <xcb/xcb.h>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
class GSWndEGL_X11 final : public GSWndEGL
{
Window m_NativeWindow;
public:
GSWndEGL_X11();
virtual ~GSWndEGL_X11() final = default;
void* GetHandle() final { return reinterpret_cast<void*>(m_NativeWindow); }
void* AttachNativeWindow(const WindowInfo& wi) final;
void DestroyNativeResources() final;
};
#endif
#if GS_EGL_WL
// Which include ?
#include <wayland-client.h>
#include <wayland-server.h>
#include <wayland-client-protocol.h>
#include <wayland-egl.h>
class GSWndEGL_WL final : public GSWndEGL
{
wl_egl_window* m_NativeWindow;
public:
GSWndEGL_WL();
virtual ~GSWndEGL_WL() final = default;
void* GetHandle() final { return reinterpret_cast<void*>(m_NativeWindow); }
void* AttachNativeWindow(const WindowInfo& wi) final;
void DestroyNativeResources() final;
};
#endif
#endif

View File

@ -1,231 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "GSWndWGL.h"
#ifdef _WIN32
static void win_error(const wchar_t* msg, bool fatal = true)
{
DWORD errorID = ::GetLastError();
if (errorID)
fprintf(stderr, "WIN API ERROR:%ld\t", errorID);
if (fatal)
{
MessageBox(NULL, msg, L"ERROR", MB_OK | MB_ICONEXCLAMATION);
throw GSRecoverableError();
}
else
{
fprintf(stderr, "ERROR:%ls\n", msg);
}
}
GSWndWGL::GSWndWGL()
: m_NativeWindow(nullptr), m_NativeDisplay(nullptr), m_context(nullptr), m_has_late_vsync(false)
{
}
void GSWndWGL::CreateContext(int major, int minor)
{
if (!m_NativeDisplay || !m_NativeWindow)
{
win_error(L"Wrong display/window", false);
exit(1);
}
ASSERT(major >= 3);
// GL2 context are quite easy but we need GL3 which is another painful story...
m_context = wglCreateContext(m_NativeDisplay);
if (!m_context)
win_error(L"Failed to create a 2.0 context");
// FIXME test it
// Note: albeit every tutorial said that we need an opengl context to use the GL function wglCreateContextAttribsARB
// On linux it works without the extra temporary context, not sure the limitation still applied
AttachContext();
if (!gladLoadWGLLoader([](const char* name) { return static_cast<void*>(wglGetProcAddress(name)); }, m_NativeDisplay))
win_error(L"Failed to load WGL");
// Create a context
int context_attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, major,
WGL_CONTEXT_MINOR_VERSION_ARB, minor,
// FIXME : Request a debug context to ease opengl development
// Note: don't support deprecated feature (pre openg 3.1)
//GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB | GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
#ifdef ENABLE_OGL_DEBUG
| WGL_CONTEXT_DEBUG_BIT_ARB
#else
| GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR
#endif
,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
HGLRC context30 = wglCreateContextAttribsARB(m_NativeDisplay, NULL, context_attribs);
if (!context30)
{
win_error(L"Failed to create a 3.x context with standard flags", false);
// retry with more compatible option for (Mesa on Windows, OpenGL on WINE)
context_attribs[2 * 2 + 1] = 0;
context30 = wglCreateContextAttribsARB(m_NativeDisplay, NULL, context_attribs);
}
DetachContext();
wglDeleteContext(m_context);
if (!context30)
win_error(L"Failed to create a 3.x context with compatible flags");
m_context = context30;
fprintf(stdout, "3.x GL context successfully created\n");
}
void GSWndWGL::AttachContext()
{
if (!IsContextAttached())
{
wglMakeCurrent(m_NativeDisplay, m_context);
m_ctx_attached = true;
}
}
void GSWndWGL::DetachContext()
{
if (IsContextAttached())
{
wglMakeCurrent(NULL, NULL);
m_ctx_attached = false;
}
}
void GSWndWGL::PopulateWndGlFunction()
{
m_has_late_vsync = GLAD_WGL_EXT_swap_control_tear;
}
bool GSWndWGL::Attach(const WindowInfo& wi)
{
if (wi.type != WindowInfo::Type::Win32)
return false;
m_NativeWindow = static_cast<HWND>(wi.window_handle);
OpenWGLDisplay();
FullContextInit();
UpdateWindow(m_NativeWindow);
return true;
}
void GSWndWGL::Detach()
{
// Actually the destructor is not called when there is only a GSclose/GSshutdown
// The window still need to be closed
DetachContext();
if (m_context)
wglDeleteContext(m_context);
m_context = NULL;
CloseWGLDisplay();
}
void GSWndWGL::OpenWGLDisplay()
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
32, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // 8bit Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
0, // 24Bit Z-Buffer (Depth Buffer)
8, // 8bit Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
m_NativeDisplay = GetDC(m_NativeWindow);
if (!m_NativeDisplay)
win_error(L"(1) Can't Create A GL Device Context.");
PixelFormat = ChoosePixelFormat(m_NativeDisplay, &pfd);
if (!PixelFormat)
win_error(L"(2) Can't Find A Suitable PixelFormat.");
if (!SetPixelFormat(m_NativeDisplay, PixelFormat, &pfd))
win_error(L"(3) Can't Set The PixelFormat.", false);
}
void GSWndWGL::CloseWGLDisplay()
{
if (m_NativeDisplay && !ReleaseDC(m_NativeWindow, m_NativeDisplay))
win_error(L"Release Device Context Failed.");
m_NativeDisplay = NULL;
}
//Same as DX
GSVector4i GSWndWGL::GetClientRect()
{
GSVector4i r;
::GetClientRect(m_NativeWindow, r);
return r;
}
//TODO: check extensions supported or not
//FIXME : extension allocation
void GSWndWGL::SetSwapInterval()
{
// m_swapinterval uses an integer as parameter
// 0 -> disable vsync
// n -> wait n frame
if (GLAD_WGL_EXT_swap_control)
wglSwapIntervalEXT(m_vsync);
}
void GSWndWGL::Flip()
{
if (m_vsync_change_requested.exchange(false))
SetSwapInterval();
SwapBuffers(m_NativeDisplay);
}
#endif

View File

@ -1,54 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "GSWnd.h"
#ifdef _WIN32
#include "glad_wgl.h"
class GSWndWGL final : public GSWndGL
{
HWND m_NativeWindow;
HDC m_NativeDisplay;
HGLRC m_context;
bool m_has_late_vsync;
void PopulateWndGlFunction();
void CreateContext(int major, int minor);
void CloseWGLDisplay();
void OpenWGLDisplay();
void SetSwapInterval();
bool HasLateVsyncSupport() { return m_has_late_vsync; }
public:
GSWndWGL();
~GSWndWGL() override = default;
bool Attach(const WindowInfo& wi) override;
void Detach() override;
void* GetHandle() override { return m_NativeWindow; }
GSVector4i GetClientRect() override;
void AttachContext() override;
void DetachContext() override;
void Flip() override;
};
#endif

View File

@ -54,6 +54,10 @@
#ifdef __WXGTK__
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif
#endif
// Safe to remove these lines when this is handled properly.

View File

@ -20,6 +20,7 @@
#include "AppSaveStates.h"
#include "Counters.h"
#include "GS.h"
#include "GS/GS.h"
#include "MainFrame.h"
#include "MSWstuff.h"
#ifdef _WIN32
@ -245,7 +246,7 @@ GSPanel::~GSPanel()
//CoreThread.Suspend( false ); // Just in case...!
#ifdef WAYLAND_API
WaylandDestroySubsurface();
WaylandDestroySubsurface();
#endif
}
@ -265,11 +266,6 @@ 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();
@ -327,6 +323,20 @@ std::optional<WindowInfo> GSPanel::GetWindowInfo()
return std::nullopt;
}
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());
#ifdef __WXGTK__
// GTK seems to not scale coordinates?
if (ret.type == WindowInfo::Type::X11)
{
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
return ret;
}
@ -334,6 +344,28 @@ void GSPanel::OnResize(wxSizeEvent& event)
{
if( IsBeingDeleted() ) return;
event.Skip();
if (g_gs_window_info.type == WindowInfo::Type::Surfaceless)
return;
const wxSize gs_vp_size(GetClientSize());
const float scale = GetContentScaleFactor();
int width = gs_vp_size.GetWidth();
int height = gs_vp_size.GetHeight();
#ifdef __WXGTK__
if (g_gs_window_info.type == WindowInfo::Type::X11)
{
width = static_cast<int>(width * scale);
height = static_cast<int>(height * scale);
}
#endif
g_gs_window_info.surface_width = width;
g_gs_window_info.surface_height = height;
g_gs_window_info.surface_scale = scale;
GSResizeWindow(width, height);
}
void GSPanel::OnCloseWindow(wxCloseEvent& evt)
@ -565,94 +597,92 @@ void GSPanel::OnLeftDclick(wxMouseEvent& evt)
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));
}
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
};
static constexpr wl_registry_listener registry_listener = {
&GSPanel::WaylandGlobalRegistryAddHandler,
&GSPanel::WaylandGlobalRegistryRemoveHandler};
wl_registry* registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_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* registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_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);
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;
}
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);
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;
}
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;
// 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_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_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_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;
}
if (m_wl_compositor)
{
wl_compositor_destroy(m_wl_compositor);
m_wl_compositor = nullptr;
}
}
#endif

View File

@ -514,12 +514,6 @@
<ClCompile Include="GS\Renderers\Common\GSVertexList.cpp" />
<ClCompile Include="GS\Renderers\SW\GSVertexSW.cpp" />
<ClCompile Include="GS\Renderers\Common\GSVertexTrace.cpp" />
<ClCompile Include="GS\Window\GSWnd.cpp" />
<ClCompile Include="GS\Window\GSWndDX.cpp" />
<ClCompile Include="GS\Window\GSWndEGL.cpp">
<ExcludedFromBuild>true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="GS\Window\GSWndWGL.cpp" />
<ClCompile Include="Utilities\FileUtils.cpp" />
<ClCompile Include="Dump.cpp" />
<ClCompile Include="x86\iMisc.cpp" />
@ -886,10 +880,6 @@
<ClInclude Include="GS\Renderers\Common\GSVertexList.h" />
<ClInclude Include="GS\Renderers\SW\GSVertexSW.h" />
<ClInclude Include="GS\Renderers\Common\GSVertexTrace.h" />
<ClInclude Include="GS\Window\GSWnd.h" />
<ClInclude Include="GS\Window\GSWndDX.h" />
<ClInclude Include="GS\Window\GSWndEGL.h" />
<ClInclude Include="GS\Window\GSWndWGL.h" />
<ClInclude Include="GS\resource.h" />
<ClInclude Include="IPU\IPUdma.h" />
<ClInclude Include="Mdec.h" />

View File

@ -1628,18 +1628,6 @@
<ClCompile Include="GS\Window\GSSettingsDlg.cpp">
<Filter>System\Ps2\GS\Window</Filter>
</ClCompile>
<ClCompile Include="GS\Window\GSWndDX.cpp">
<Filter>System\Ps2\GS\Window</Filter>
</ClCompile>
<ClCompile Include="GS\Window\GSWndEGL.cpp">
<Filter>System\Ps2\GS\Window</Filter>
</ClCompile>
<ClCompile Include="GS\Window\GSWndWGL.cpp">
<Filter>System\Ps2\GS\Window</Filter>
</ClCompile>
<ClCompile Include="GS\Window\GSWnd.cpp">
<Filter>System\Ps2\GS\Window</Filter>
</ClCompile>
<ClCompile Include="gui\wxAppWithHelpers.cpp">
<Filter>AppHost</Filter>
</ClCompile>
@ -2730,18 +2718,6 @@
<ClInclude Include="GS\Window\GSSettingsDlg.h">
<Filter>System\Ps2\GS\Window</Filter>
</ClInclude>
<ClInclude Include="GS\Window\GSWndDX.h">
<Filter>System\Ps2\GS\Window</Filter>
</ClInclude>
<ClInclude Include="GS\Window\GSWndEGL.h">
<Filter>System\Ps2\GS\Window</Filter>
</ClInclude>
<ClInclude Include="GS\Window\GSWndWGL.h">
<Filter>System\Ps2\GS\Window</Filter>
</ClInclude>
<ClInclude Include="GS\Window\GSWnd.h">
<Filter>System\Ps2\GS\Window</Filter>
</ClInclude>
<ClInclude Include="gui\wxAppWithHelpers.h">
<Filter>AppHost</Filter>
</ClInclude>