mirror of https://github.com/PCSX2/pcsx2.git
GS: Remove GSWnd and use GL::Context
This commit is contained in:
parent
198fc2629e
commit
5ba70c8c20
|
@ -664,7 +664,6 @@ set(pcsx2GSSources
|
||||||
GS/Renderers/OpenGL/GSTextureCacheOGL.cpp
|
GS/Renderers/OpenGL/GSTextureCacheOGL.cpp
|
||||||
GS/Renderers/OpenGL/GSTextureOGL.cpp
|
GS/Renderers/OpenGL/GSTextureOGL.cpp
|
||||||
GS/Window/GSSetting.cpp
|
GS/Window/GSSetting.cpp
|
||||||
GS/Window/GSWnd.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# GS headers
|
# GS headers
|
||||||
|
@ -734,7 +733,6 @@ set(pcsx2GSHeaders
|
||||||
GS/Window/GSDialog.h
|
GS/Window/GSDialog.h
|
||||||
GS/Window/GSSetting.h
|
GS/Window/GSSetting.h
|
||||||
GS/Window/GSSettingsDlg.h
|
GS/Window/GSSettingsDlg.h
|
||||||
GS/Window/GSWnd.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
@ -807,16 +805,12 @@ if(WIN32)
|
||||||
GS/Window/GSCaptureDlg.cpp
|
GS/Window/GSCaptureDlg.cpp
|
||||||
GS/Window/GSDialog.cpp
|
GS/Window/GSDialog.cpp
|
||||||
GS/Window/GSSettingsDlg.cpp
|
GS/Window/GSSettingsDlg.cpp
|
||||||
GS/Window/GSWndDX.cpp
|
|
||||||
GS/Window/GSWndWGL.cpp
|
|
||||||
)
|
)
|
||||||
list(APPEND pcsx2GSHeaders
|
list(APPEND pcsx2GSHeaders
|
||||||
GS/Renderers/DX11/GSDevice11.h
|
GS/Renderers/DX11/GSDevice11.h
|
||||||
GS/Renderers/DX11/GSRendererDX11.h
|
GS/Renderers/DX11/GSRendererDX11.h
|
||||||
GS/Renderers/DX11/GSTexture11.h
|
GS/Renderers/DX11/GSTexture11.h
|
||||||
GS/Renderers/DX11/GSTextureCache11.h
|
GS/Renderers/DX11/GSTextureCache11.h
|
||||||
GS/Window/GSWndDX.h
|
|
||||||
GS/Window/GSWndWGL.h
|
|
||||||
)
|
)
|
||||||
else(WIN32)
|
else(WIN32)
|
||||||
list(APPEND pcsx2SPU2Sources
|
list(APPEND pcsx2SPU2Sources
|
||||||
|
@ -902,12 +896,10 @@ else(WIN32)
|
||||||
list(APPEND pcsx2GSSources
|
list(APPEND pcsx2GSSources
|
||||||
GS/GS_res.cpp
|
GS/GS_res.cpp
|
||||||
GS/Window/GSLinuxDialog.cpp
|
GS/Window/GSLinuxDialog.cpp
|
||||||
GS/Window/GSWndEGL.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND pcsx2GSHeaders
|
list(APPEND pcsx2GSHeaders
|
||||||
GS/GS_res.h
|
GS/GS_res.h
|
||||||
GS/Window/GSWndEGL.h
|
|
||||||
)
|
)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
|
@ -1394,14 +1386,9 @@ if(Linux)
|
||||||
|
|
||||||
target_link_libraries(PCSX2_FLAGS INTERFACE
|
target_link_libraries(PCSX2_FLAGS INTERFACE
|
||||||
PkgConfig::AIO
|
PkgConfig::AIO
|
||||||
PkgConfig::EGL
|
|
||||||
PkgConfig::LIBUDEV
|
PkgConfig::LIBUDEV
|
||||||
ALSA::ALSA
|
ALSA::ALSA
|
||||||
)
|
)
|
||||||
elseif(UNIX AND NOT APPLE)
|
|
||||||
target_link_libraries(PCSX2_FLAGS INTERFACE
|
|
||||||
PkgConfig::EGL
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
|
100
pcsx2/GS/GS.cpp
100
pcsx2/GS/GS.cpp
|
@ -30,8 +30,6 @@
|
||||||
|
|
||||||
#include "Renderers/DX11/GSRendererDX11.h"
|
#include "Renderers/DX11/GSRendererDX11.h"
|
||||||
#include "Renderers/DX11/GSDevice11.h"
|
#include "Renderers/DX11/GSDevice11.h"
|
||||||
#include "Window/GSWndDX.h"
|
|
||||||
#include "Window/GSWndWGL.h"
|
|
||||||
#include "Window/GSSettingsDlg.h"
|
#include "Window/GSSettingsDlg.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,8 +37,6 @@ static HRESULT s_hr = E_FAIL;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include "GS/Window/GSWndEGL.h"
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
@ -64,6 +60,13 @@ static bool s_exclusive = true;
|
||||||
static std::string s_renderer_name;
|
static std::string s_renderer_name;
|
||||||
bool gsopen_done = false; // crash guard for GSgetTitleInfo2 and GSKeyEvent (replace with lock?)
|
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)
|
void GSsetBaseMem(uint8* mem)
|
||||||
{
|
{
|
||||||
s_basemem = mem;
|
s_basemem = mem;
|
||||||
|
@ -126,6 +129,11 @@ void GSclose()
|
||||||
{
|
{
|
||||||
gsopen_done = false;
|
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)
|
if (s_gs == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -136,11 +144,6 @@ void GSclose()
|
||||||
delete s_gs->m_dev;
|
delete s_gs->m_dev;
|
||||||
|
|
||||||
s_gs->m_dev = NULL;
|
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)
|
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);
|
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;
|
std::string renderer_name;
|
||||||
|
|
||||||
switch (renderer)
|
switch (renderer)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -288,8 +238,6 @@ int _GSopen(const WindowInfo& wi, const char* title, GSRendererType renderer, in
|
||||||
if (s_gs == NULL)
|
if (s_gs == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_gs->m_wnd = window;
|
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
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->SetRegsMem(s_basemem);
|
||||||
s_gs->SetVSync(s_vsync);
|
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
|
// 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
|
// 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, ...)
|
std::string format(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "common/Pcsx2Types.h"
|
#include "common/Pcsx2Types.h"
|
||||||
|
#include "common/WindowInfo.h"
|
||||||
#include "GS_types.h"
|
#include "GS_types.h"
|
||||||
#include "Window/GSSetting.h"
|
#include "Window/GSSetting.h"
|
||||||
#include "SaveState.h"
|
#include "SaveState.h"
|
||||||
|
@ -1794,6 +1795,12 @@ void GSsetFrameSkip(int frameskip);
|
||||||
void GSsetVsync(int vsync);
|
void GSsetVsync(int vsync);
|
||||||
void GSsetExclusive(int enabled);
|
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
|
class GSApp
|
||||||
{
|
{
|
||||||
std::string m_section;
|
std::string m_section;
|
||||||
|
|
|
@ -18,8 +18,7 @@
|
||||||
#include "GSDevice.h"
|
#include "GSDevice.h"
|
||||||
|
|
||||||
GSDevice::GSDevice()
|
GSDevice::GSDevice()
|
||||||
: m_wnd()
|
: m_vsync(false)
|
||||||
, m_vsync(false)
|
|
||||||
, m_rbswapped(false)
|
, m_rbswapped(false)
|
||||||
, m_backbuffer(NULL)
|
, m_backbuffer(NULL)
|
||||||
, m_merge(NULL)
|
, m_merge(NULL)
|
||||||
|
@ -46,10 +45,8 @@ GSDevice::~GSDevice()
|
||||||
delete m_target_tmp;
|
delete m_target_tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSDevice::Create(const std::shared_ptr<GSWnd>& wnd)
|
bool GSDevice::Create(const WindowInfo& wi)
|
||||||
{
|
{
|
||||||
m_wnd = wnd;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,27 +70,19 @@ bool GSDevice::Reset(int w, int h)
|
||||||
m_target_tmp = NULL;
|
m_target_tmp = NULL;
|
||||||
|
|
||||||
m_current = NULL; // current is special, points to other textures, no need to delete
|
m_current = NULL; // current is special, points to other textures, no need to delete
|
||||||
|
return true;
|
||||||
return m_wnd != NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDevice::Present(const GSVector4i& r, int shader)
|
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");
|
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
|
// FIXME is it mandatory, it could be slow
|
||||||
ClearRenderTarget(m_backbuffer, 0);
|
ClearRenderTarget(m_backbuffer, 0);
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/WindowInfo.h"
|
||||||
#include "GSFastList.h"
|
#include "GSFastList.h"
|
||||||
#include "GS/Window/GSWnd.h"
|
|
||||||
#include "GSTexture.h"
|
#include "GSTexture.h"
|
||||||
#include "GSVertex.h"
|
#include "GSVertex.h"
|
||||||
#include "GS/GSAlignedClass.h"
|
#include "GS/GSAlignedClass.h"
|
||||||
|
@ -145,7 +145,6 @@ protected:
|
||||||
static const int m_NO_BLEND = 0;
|
static const int m_NO_BLEND = 0;
|
||||||
static const int m_MERGE_BLEND = m_blendMap.size() - 1;
|
static const int m_MERGE_BLEND = m_blendMap.size() - 1;
|
||||||
|
|
||||||
std::shared_ptr<GSWnd> m_wnd;
|
|
||||||
int m_vsync;
|
int m_vsync;
|
||||||
bool m_rbswapped;
|
bool m_rbswapped;
|
||||||
GSTexture* m_backbuffer;
|
GSTexture* m_backbuffer;
|
||||||
|
@ -190,7 +189,7 @@ public:
|
||||||
DontCare
|
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 Reset(int w, int h);
|
||||||
virtual bool IsLost(bool update = false) { return false; }
|
virtual bool IsLost(bool update = false) { return false; }
|
||||||
virtual void Present(const GSVector4i& r, int shader);
|
virtual void Present(const GSVector4i& r, int shader);
|
||||||
|
@ -247,6 +246,8 @@ public:
|
||||||
bool ResizeTarget(GSTexture** t);
|
bool ResizeTarget(GSTexture** t);
|
||||||
|
|
||||||
bool IsRBSwapped() { return m_rbswapped; }
|
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 AgePool();
|
||||||
void PurgePool();
|
void PurgePool();
|
||||||
|
|
|
@ -31,7 +31,6 @@ GSRenderer::GSRenderer()
|
||||||
, m_control_key(false)
|
, m_control_key(false)
|
||||||
, m_texture_shuffle(false)
|
, m_texture_shuffle(false)
|
||||||
, m_real_size(0, 0)
|
, m_real_size(0, 0)
|
||||||
, m_wnd()
|
|
||||||
, m_dev(NULL)
|
, m_dev(NULL)
|
||||||
{
|
{
|
||||||
m_GStitleInfoBuffer[0] = 0;
|
m_GStitleInfoBuffer[0] = 0;
|
||||||
|
@ -56,12 +55,12 @@ GSRenderer::~GSRenderer()
|
||||||
delete m_dev;
|
delete m_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSRenderer::CreateDevice(GSDevice* dev)
|
bool GSRenderer::CreateDevice(GSDevice* dev, const WindowInfo& wi)
|
||||||
{
|
{
|
||||||
ASSERT(dev);
|
ASSERT(dev);
|
||||||
ASSERT(!m_dev);
|
ASSERT(!m_dev);
|
||||||
|
|
||||||
if (!dev->Create(m_wnd))
|
if (!dev->Create(wi))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -468,7 +467,7 @@ void GSRenderer::VSync(int field)
|
||||||
|
|
||||||
// This will scale the OSD to the window's size.
|
// This will scale the OSD to the window's size.
|
||||||
// Will maintiain the font size no matter what size the window is.
|
// 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.x = window_size.v[2];
|
||||||
m_dev->m_osd.m_real_size.y = window_size.v[3];
|
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)
|
bool GSRenderer::BeginCapture(std::string& filename)
|
||||||
{
|
{
|
||||||
const GSVector4i crect(m_wnd->GetClientRect());
|
GSVector4i disp = ComputeDrawRectangle(m_dev->GetBackbufferWidth(), m_dev->GetBackbufferHeight());
|
||||||
GSVector4i disp = ComputeDrawRectangle(crect.z, crect.w);
|
|
||||||
float aspect = (float)disp.width() / std::max(1, disp.height());
|
float aspect = (float)disp.width() / std::max(1, disp.height());
|
||||||
|
|
||||||
return m_capture.BeginCapture(GetTvRefreshRate(), GetInternalResolution(), aspect, filename);
|
return m_capture.BeginCapture(GetTvRefreshRate(), GetInternalResolution(), aspect, filename);
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GS/GS.h"
|
#include "GS/GS.h"
|
||||||
#include "GS/Window/GSWnd.h"
|
|
||||||
#include "GS/GSState.h"
|
#include "GS/GSState.h"
|
||||||
#include "GS/GSCapture.h"
|
#include "GS/GSCapture.h"
|
||||||
|
|
||||||
|
@ -48,14 +47,13 @@ protected:
|
||||||
virtual GSTexture* GetFeedbackOutput() { return nullptr; }
|
virtual GSTexture* GetFeedbackOutput() { return nullptr; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<GSWnd> m_wnd;
|
|
||||||
GSDevice* m_dev;
|
GSDevice* m_dev;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GSRenderer();
|
GSRenderer();
|
||||||
virtual ~GSRenderer();
|
virtual ~GSRenderer();
|
||||||
|
|
||||||
virtual bool CreateDevice(GSDevice* dev);
|
virtual bool CreateDevice(GSDevice* dev, const WindowInfo& wi);
|
||||||
virtual void ResetDevice();
|
virtual void ResetDevice();
|
||||||
virtual void VSync(int field);
|
virtual void VSync(int field);
|
||||||
virtual bool MakeSnapshot(const std::string& path);
|
virtual bool MakeSnapshot(const std::string& path);
|
||||||
|
|
|
@ -74,11 +74,11 @@ bool GSDevice11::SetFeatureLevel(D3D_FEATURE_LEVEL level, bool compat_mode)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSDevice11::Create(const std::shared_ptr<GSWnd>& wnd)
|
bool GSDevice11::Create(const WindowInfo& wi)
|
||||||
{
|
{
|
||||||
bool nvidia_vendor = false;
|
bool nvidia_vendor = false;
|
||||||
|
|
||||||
if (!__super::Create(wnd))
|
if (!__super::Create(wi))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ bool GSDevice11::Create(const std::shared_ptr<GSWnd>& wnd)
|
||||||
swapchain_description.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
swapchain_description.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
|
||||||
const HRESULT result = factory->CreateSwapChainForHwnd(
|
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());
|
&swapchain_description, nullptr, nullptr, m_swapchain.put());
|
||||||
|
|
||||||
if (FAILED(result))
|
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);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
|
@ -525,7 +525,7 @@ public:
|
||||||
bool SetFeatureLevel(D3D_FEATURE_LEVEL level, bool compat_mode);
|
bool SetFeatureLevel(D3D_FEATURE_LEVEL level, bool compat_mode);
|
||||||
void GetFeatureLevel(D3D_FEATURE_LEVEL& level) const { level = m_shader.level; }
|
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);
|
bool Reset(int w, int h);
|
||||||
void Flip();
|
void Flip();
|
||||||
void SetVSync(int vsync) final;
|
void SetVSync(int vsync) final;
|
||||||
|
|
|
@ -24,11 +24,6 @@ GSRendererDX11::GSRendererDX11()
|
||||||
ResetStates();
|
ResetStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSRendererDX11::CreateDevice(GSDevice* dev)
|
|
||||||
{
|
|
||||||
return GSRenderer::CreateDevice(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSRendererDX11::SetupIA(const float& sx, const float& sy)
|
void GSRendererDX11::SetupIA(const float& sx, const float& sy)
|
||||||
{
|
{
|
||||||
GSDevice11* dev = (GSDevice11*)m_dev;
|
GSDevice11* dev = (GSDevice11*)m_dev;
|
||||||
|
|
|
@ -58,6 +58,4 @@ public:
|
||||||
virtual ~GSRendererDX11() {}
|
virtual ~GSRendererDX11() {}
|
||||||
|
|
||||||
void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) final;
|
void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) final;
|
||||||
|
|
||||||
bool CreateDevice(GSDevice* dev);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "GSDeviceNull.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;
|
return false;
|
||||||
|
|
||||||
Reset(1, 1);
|
Reset(1, 1);
|
||||||
|
|
|
@ -30,6 +30,6 @@ private:
|
||||||
public:
|
public:
|
||||||
GSDeviceNull() {}
|
GSDeviceNull() {}
|
||||||
|
|
||||||
bool Create(const std::shared_ptr<GSWnd>& wnd);
|
bool Create(const WindowInfo& wi);
|
||||||
bool Reset(int w, int h);
|
bool Reset(int w, int h);
|
||||||
};
|
};
|
||||||
|
|
|
@ -305,9 +305,27 @@ GSTexture* GSDeviceOGL::FetchSurface(int type, int w, int h, int format)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSDeviceOGL::Create(const std::shared_ptr<GSWnd>& wnd)
|
bool GSDeviceOGL::Create(const WindowInfo& wi)
|
||||||
{
|
{
|
||||||
std::vector<char> shader;
|
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
|
// Debug helper
|
||||||
// ****************************************************************
|
// ****************************************************************
|
||||||
|
@ -584,11 +602,10 @@ bool GSDeviceOGL::Create(const std::shared_ptr<GSWnd>& wnd)
|
||||||
// ****************************************************************
|
// ****************************************************************
|
||||||
// Finish window setup and backbuffer
|
// Finish window setup and backbuffer
|
||||||
// ****************************************************************
|
// ****************************************************************
|
||||||
if (!GSDevice::Create(wnd))
|
if (!GSDevice::Create(wi))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const GSVector4i rect = wnd->GetClientRect();
|
Reset(wi.surface_width, wi.surface_height);
|
||||||
Reset(rect.z, rect.w);
|
|
||||||
|
|
||||||
// Basic to ensure structures are correctly packed
|
// Basic to ensure structures are correctly packed
|
||||||
static_assert(sizeof(VSSelector) == 4, "Wrong VSSelector size");
|
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
|
// 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
|
// there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done
|
||||||
// in the backbuffer
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceOGL::SetVSync(int vsync)
|
void GSDeviceOGL::SetVSync(int vsync)
|
||||||
{
|
{
|
||||||
m_wnd->SetVSync(vsync);
|
m_gl_context->SetSwapInterval(vsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceOGL::Flip()
|
void GSDeviceOGL::Flip()
|
||||||
{
|
{
|
||||||
m_wnd->Flip();
|
m_gl_context->SwapBuffers();
|
||||||
|
|
||||||
if (GLLoader::in_replayer)
|
if (GLLoader::in_replayer)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/GL/Context.h"
|
||||||
#include "GS/Renderers/Common/GSDevice.h"
|
#include "GS/Renderers/Common/GSDevice.h"
|
||||||
#include "GSTextureOGL.h"
|
#include "GSTextureOGL.h"
|
||||||
#include "GS/GS.h"
|
#include "GS/GS.h"
|
||||||
|
@ -464,6 +465,7 @@ public:
|
||||||
static int m_shader_reg;
|
static int m_shader_reg;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unique_ptr<GL::Context> m_gl_context;
|
||||||
int m_force_texture_clear;
|
int m_force_texture_clear;
|
||||||
int m_mipmap;
|
int m_mipmap;
|
||||||
TriFiltering m_filter;
|
TriFiltering m_filter;
|
||||||
|
@ -581,10 +583,10 @@ public:
|
||||||
// Used by OpenGL, so the same calling convention is required.
|
// 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);
|
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 Create(const WindowInfo& wi) override;
|
||||||
bool Reset(int w, int h);
|
bool Reset(int w, int h) override;
|
||||||
void Flip();
|
void Flip() override;
|
||||||
void SetVSync(int vsync);
|
void SetVSync(int vsync) override;
|
||||||
|
|
||||||
void DrawPrimitive() final;
|
void DrawPrimitive() final;
|
||||||
void DrawPrimitive(int offset, int count);
|
void DrawPrimitive(int offset, int count);
|
||||||
|
|
|
@ -33,11 +33,6 @@ GSRendererOGL::GSRendererOGL()
|
||||||
ResetStates();
|
ResetStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSRendererOGL::CreateDevice(GSDevice* dev)
|
|
||||||
{
|
|
||||||
return GSRenderer::CreateDevice(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GSRendererOGL::SetupIA(const float& sx, const float& sy)
|
void GSRendererOGL::SetupIA(const float& sx, const float& sy)
|
||||||
{
|
{
|
||||||
GL_PUSH("IA");
|
GL_PUSH("IA");
|
||||||
|
|
|
@ -71,8 +71,6 @@ public:
|
||||||
GSRendererOGL();
|
GSRendererOGL();
|
||||||
virtual ~GSRendererOGL() {}
|
virtual ~GSRendererOGL() {}
|
||||||
|
|
||||||
bool CreateDevice(GSDevice* dev);
|
|
||||||
|
|
||||||
void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) final;
|
void DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) final;
|
||||||
|
|
||||||
PRIM_OVERLAP PrimitiveOverlap();
|
PRIM_OVERLAP PrimitiveOverlap();
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
};
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -54,6 +54,10 @@
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
|
#include <gdk/gdkwayland.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Safe to remove these lines when this is handled properly.
|
// Safe to remove these lines when this is handled properly.
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "AppSaveStates.h"
|
#include "AppSaveStates.h"
|
||||||
#include "Counters.h"
|
#include "Counters.h"
|
||||||
#include "GS.h"
|
#include "GS.h"
|
||||||
|
#include "GS/GS.h"
|
||||||
#include "MainFrame.h"
|
#include "MainFrame.h"
|
||||||
#include "MSWstuff.h"
|
#include "MSWstuff.h"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
@ -265,11 +266,6 @@ std::optional<WindowInfo> GSPanel::GetWindowInfo()
|
||||||
{
|
{
|
||||||
WindowInfo ret;
|
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)
|
#if defined(_WIN32)
|
||||||
ret.type = WindowInfo::Type::Win32;
|
ret.type = WindowInfo::Type::Win32;
|
||||||
ret.window_handle = GetHandle();
|
ret.window_handle = GetHandle();
|
||||||
|
@ -327,6 +323,20 @@ std::optional<WindowInfo> GSPanel::GetWindowInfo()
|
||||||
return std::nullopt;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +344,28 @@ void GSPanel::OnResize(wxSizeEvent& event)
|
||||||
{
|
{
|
||||||
if( IsBeingDeleted() ) return;
|
if( IsBeingDeleted() ) return;
|
||||||
event.Skip();
|
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)
|
void GSPanel::OnCloseWindow(wxCloseEvent& evt)
|
||||||
|
@ -578,15 +610,13 @@ void GSPanel::WaylandGlobalRegistryAddHandler(void* data, wl_registry* registry,
|
||||||
|
|
||||||
void GSPanel::WaylandGlobalRegistryRemoveHandler(void* data, wl_registry* registry, uint32_t id)
|
void GSPanel::WaylandGlobalRegistryRemoveHandler(void* data, wl_registry* registry, uint32_t id)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSPanel::WaylandCreateSubsurface(wl_display* display, wl_surface* surface)
|
bool GSPanel::WaylandCreateSubsurface(wl_display* display, wl_surface* surface)
|
||||||
{
|
{
|
||||||
static constexpr wl_registry_listener registry_listener = {
|
static constexpr wl_registry_listener registry_listener = {
|
||||||
&GSPanel::WaylandGlobalRegistryAddHandler,
|
&GSPanel::WaylandGlobalRegistryAddHandler,
|
||||||
&GSPanel::WaylandGlobalRegistryRemoveHandler
|
&GSPanel::WaylandGlobalRegistryRemoveHandler};
|
||||||
};
|
|
||||||
|
|
||||||
wl_registry* registry = wl_display_get_registry(display);
|
wl_registry* registry = wl_display_get_registry(display);
|
||||||
wl_registry_add_listener(registry, ®istry_listener, this);
|
wl_registry_add_listener(registry, ®istry_listener, this);
|
||||||
|
|
|
@ -514,12 +514,6 @@
|
||||||
<ClCompile Include="GS\Renderers\Common\GSVertexList.cpp" />
|
<ClCompile Include="GS\Renderers\Common\GSVertexList.cpp" />
|
||||||
<ClCompile Include="GS\Renderers\SW\GSVertexSW.cpp" />
|
<ClCompile Include="GS\Renderers\SW\GSVertexSW.cpp" />
|
||||||
<ClCompile Include="GS\Renderers\Common\GSVertexTrace.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="Utilities\FileUtils.cpp" />
|
||||||
<ClCompile Include="Dump.cpp" />
|
<ClCompile Include="Dump.cpp" />
|
||||||
<ClCompile Include="x86\iMisc.cpp" />
|
<ClCompile Include="x86\iMisc.cpp" />
|
||||||
|
@ -886,10 +880,6 @@
|
||||||
<ClInclude Include="GS\Renderers\Common\GSVertexList.h" />
|
<ClInclude Include="GS\Renderers\Common\GSVertexList.h" />
|
||||||
<ClInclude Include="GS\Renderers\SW\GSVertexSW.h" />
|
<ClInclude Include="GS\Renderers\SW\GSVertexSW.h" />
|
||||||
<ClInclude Include="GS\Renderers\Common\GSVertexTrace.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="GS\resource.h" />
|
||||||
<ClInclude Include="IPU\IPUdma.h" />
|
<ClInclude Include="IPU\IPUdma.h" />
|
||||||
<ClInclude Include="Mdec.h" />
|
<ClInclude Include="Mdec.h" />
|
||||||
|
|
|
@ -1628,18 +1628,6 @@
|
||||||
<ClCompile Include="GS\Window\GSSettingsDlg.cpp">
|
<ClCompile Include="GS\Window\GSSettingsDlg.cpp">
|
||||||
<Filter>System\Ps2\GS\Window</Filter>
|
<Filter>System\Ps2\GS\Window</Filter>
|
||||||
</ClCompile>
|
</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">
|
<ClCompile Include="gui\wxAppWithHelpers.cpp">
|
||||||
<Filter>AppHost</Filter>
|
<Filter>AppHost</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -2730,18 +2718,6 @@
|
||||||
<ClInclude Include="GS\Window\GSSettingsDlg.h">
|
<ClInclude Include="GS\Window\GSSettingsDlg.h">
|
||||||
<Filter>System\Ps2\GS\Window</Filter>
|
<Filter>System\Ps2\GS\Window</Filter>
|
||||||
</ClInclude>
|
</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">
|
<ClInclude Include="gui\wxAppWithHelpers.h">
|
||||||
<Filter>AppHost</Filter>
|
<Filter>AppHost</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
Loading…
Reference in New Issue