Skip to content

Commit 8359346

Browse files
committed
GSRunner: Support GNU/Linux
1 parent e550cf9 commit 8359346

File tree

3 files changed

+128
-9
lines changed

3 files changed

+128
-9
lines changed

CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ endif()
6262

6363
# gsrunner
6464
if(ENABLE_GSRUNNER)
65-
if (NOT WIN32 AND NOT APPLE)
66-
message(WARNING "GSRunner is only supported on Windows and macOS and may not build on your system")
67-
endif()
6865
add_subdirectory(pcsx2-gsrunner)
6966
else()
7067
add_subdirectory(pcsx2-gsrunner EXCLUDE_FROM_ALL)

pcsx2-gsrunner/Main.cpp

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@
4747

4848
#include "svnrev.h"
4949

50+
// Down here because X11 has a lot of defines that can conflict
51+
#if defined(__linux__)
52+
#include <SDL2/SDL.h>
53+
#include <X11/Xlib.h>
54+
#include <X11/Xutil.h>
55+
#include <sys/select.h>
56+
#include <unistd.h>
57+
#endif
58+
5059
namespace GSRunner
5160
{
5261
static void InitializeConsole();
@@ -1086,4 +1095,118 @@ void GSRunner::StopPlatformMessagePump()
10861095
CocoaTools::StopMainThreadEventLoop();
10871096
}
10881097

1098+
#elif defined(__linux__)
1099+
static Display* s_display = nullptr;
1100+
static Window s_window = None;
1101+
static WindowInfo s_wi;
1102+
static std::atomic<bool> s_shutdown_requested{false};
1103+
1104+
bool GSRunner::CreatePlatformWindow()
1105+
{
1106+
pxAssertRel(!s_display && s_window == None, "Tried to create window when there already was one!");
1107+
1108+
s_display = XOpenDisplay(nullptr);
1109+
if (!s_display)
1110+
{
1111+
Console.Error("Failed to open X11 display");
1112+
return false;
1113+
}
1114+
1115+
int screen = DefaultScreen(s_display);
1116+
Window root = RootWindow(s_display, screen);
1117+
1118+
s_window = XCreateSimpleWindow(s_display, root, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 1,
1119+
BlackPixel(s_display, screen), WhitePixel(s_display, screen));
1120+
1121+
if (s_window == None)
1122+
{
1123+
Console.Error("Failed to create X11 window");
1124+
XCloseDisplay(s_display);
1125+
s_display = nullptr;
1126+
return false;
1127+
}
1128+
1129+
XStoreName(s_display, s_window, "PCSX2 GS Runner");
1130+
XSelectInput(s_display, s_window, StructureNotifyMask);
1131+
XMapWindow(s_display, s_window);
1132+
1133+
s_wi.type = WindowInfo::Type::X11;
1134+
s_wi.display_connection = s_display;
1135+
s_wi.window_handle = reinterpret_cast<void*>(s_window);
1136+
s_wi.surface_width = WINDOW_WIDTH;
1137+
s_wi.surface_height = WINDOW_HEIGHT;
1138+
s_wi.surface_scale = 1.0f;
1139+
1140+
XFlush(s_display);
1141+
PumpPlatformMessages();
1142+
return true;
1143+
}
1144+
1145+
void GSRunner::DestroyPlatformWindow()
1146+
{
1147+
if (s_display && s_window != None)
1148+
{
1149+
XDestroyWindow(s_display, s_window);
1150+
s_window = None;
1151+
}
1152+
1153+
if (s_display)
1154+
{
1155+
XCloseDisplay(s_display);
1156+
s_display = nullptr;
1157+
}
1158+
}
1159+
1160+
std::optional<WindowInfo> GSRunner::GetPlatformWindowInfo()
1161+
{
1162+
WindowInfo wi;
1163+
if (s_display && s_window != None)
1164+
wi = s_wi;
1165+
else
1166+
wi.type = WindowInfo::Type::Surfaceless;
1167+
return wi;
1168+
}
1169+
1170+
void GSRunner::PumpPlatformMessages(bool forever)
1171+
{
1172+
if (!s_display)
1173+
return;
1174+
1175+
do
1176+
{
1177+
while (XPending(s_display) > 0)
1178+
{
1179+
XEvent event;
1180+
XNextEvent(s_display, &event);
1181+
1182+
switch (event.type)
1183+
{
1184+
case ConfigureNotify:
1185+
{
1186+
const XConfigureEvent& configure = event.xconfigure;
1187+
s_wi.surface_width = static_cast<u32>(configure.width);
1188+
s_wi.surface_height = static_cast<u32>(configure.height);
1189+
break;
1190+
}
1191+
case DestroyNotify:
1192+
return;
1193+
default:
1194+
break;
1195+
}
1196+
}
1197+
1198+
if (s_shutdown_requested.load())
1199+
return;
1200+
1201+
if (forever)
1202+
{
1203+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
1204+
}
1205+
} while (forever && !s_shutdown_requested.load());
1206+
}
1207+
1208+
void GSRunner::StopPlatformMessagePump()
1209+
{
1210+
s_shutdown_requested.store(true);
1211+
}
10891212
#endif // _WIN32 / __APPLE__

pcsx2-gsrunner/test_run_dumps.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ def run_regression_test(runner, dumpdir, renderer, upscale, renderhacks, paralle
7373
#print("Running '%s'" % (" ".join(args)))
7474
subprocess.run(args, env=environ, stdin=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL, creationflags=creationflags)
7575

76-
7776
def run_regression_tests(runner, gsdir, dumpdir, renderer, upscale, renderhacks, parallel=1):
7877
paths = glob.glob(gsdir + "/*.*", recursive=True)
7978
gamepaths = list(filter(lambda x: get_gs_name(x) is not None, paths))
@@ -104,12 +103,12 @@ def run_regression_tests(runner, gsdir, dumpdir, renderer, upscale, renderhacks,
104103

105104
if __name__ == "__main__":
106105
parser = argparse.ArgumentParser(description="Generate frame dump images for regression tests")
107-
parser.add_argument("-runner", action="store", required=True, help="Path to PCSX2 GS runner")
108-
parser.add_argument("-gsdir", action="store", required=True, help="Directory containing GS dumps")
109-
parser.add_argument("-dumpdir", action="store", required=True, help="Base directory to dump frames to")
110-
parser.add_argument("-renderer", action="store", required=False, help="Renderer to use")
106+
parser.add_argument("-runner", action="store", required=True, type=str.strip, help="Path to PCSX2 GS runner")
107+
parser.add_argument("-gsdir", action="store", required=True, type=str.strip, help="Directory containing GS dumps")
108+
parser.add_argument("-dumpdir", action="store", required=True, type=str.strip, help="Base directory to dump frames to")
109+
parser.add_argument("-renderer", action="store", required=False, type=str.strip, help="Renderer to use")
111110
parser.add_argument("-upscale", action="store", type=float, default=1, help="Upscaling multiplier to use")
112-
parser.add_argument("-renderhacks", action="store", required=False, help="Enable HW Rendering hacks")
111+
parser.add_argument("-renderhacks", action="store", required=False, type=str.strip, help="Enable HW Rendering hacks")
113112
parser.add_argument("-parallel", action="store", type=int, default=1, help="Number of processes to run")
114113

115114
args = parser.parse_args()

0 commit comments

Comments
 (0)