SDL: Create dummy PS2 Video driver

From 46f95a7a5fd8274e077e5e2bc2fad68f4e0704f5 Mon Sep 17 00:00:00 2001
From: Francisco Javier Trujillo Mata <[EMAIL REDACTED]>
Date: Fri, 24 Jun 2022 00:20:11 +0200
Subject: [PATCH] Create dummy PS2 Video driver

---
 .github/workflows/ps2.yaml           |   4 +-
 CMakeLists.txt                       |  12 ++-
 include/SDL_config.h.cmake           |   1 +
 src/video/SDL_sysvideo.h             |   1 +
 src/video/SDL_video.c                |   3 +
 src/video/ps2/SDL_ps2events.c        |  41 ++++++++
 src/video/ps2/SDL_ps2events_c.h      |  33 +++++++
 src/video/ps2/SDL_ps2framebuffer.c   |  85 +++++++++++++++++
 src/video/ps2/SDL_ps2framebuffer_c.h |  33 +++++++
 src/video/ps2/SDL_ps2video.c         | 134 +++++++++++++++++++++++++++
 src/video/ps2/SDL_ps2video.h         |  30 ++++++
 test/CMakeLists.txt                  |   2 +
 12 files changed, 376 insertions(+), 3 deletions(-)
 create mode 100644 src/video/ps2/SDL_ps2events.c
 create mode 100644 src/video/ps2/SDL_ps2events_c.h
 create mode 100644 src/video/ps2/SDL_ps2framebuffer.c
 create mode 100644 src/video/ps2/SDL_ps2framebuffer_c.h
 create mode 100644 src/video/ps2/SDL_ps2video.c
 create mode 100644 src/video/ps2/SDL_ps2video.h

diff --git a/.github/workflows/ps2.yaml b/.github/workflows/ps2.yaml
index 4140b09264a..04be4ad108c 100644
--- a/.github/workflows/ps2.yaml
+++ b/.github/workflows/ps2.yaml
@@ -50,12 +50,12 @@ jobs:
       run: |
         export CC=mips64r5900el-ps2-elf-gcc
         export PATH=${{ env.SDL2_DIR }}/bin:$PATH
-        export EXTRA_LDFLAGS="-L$PS2DEV/ps2sdk/ee/lib -L$PS2DEV/ps2sdk/ports/lib"
+        export EXTRA_LDFLAGS="-L$PS2DEV/ps2sdk/ee/lib -L$PS2DEV/gsKit/lib -L$PS2DEV/ps2sdk/ports/lib"
         cmake/test/test_sdlconfig.sh
     - name: Verify sdl2.pc
       run: |
         export CC=mips64r5900el-ps2-elf-gcc
-        export EXTRA_LDFLAGS="-L$PS2DEV/ps2sdk/ee/lib -L$PS2DEV/ps2sdk/ports/lib"
+        export EXTRA_LDFLAGS="-L$PS2DEV/ps2sdk/ee/lib -L$PS2DEV/gsKit/lib -L$PS2DEV/ps2sdk/ports/lib"
         export PKG_CONFIG_PATH=${{ env.SDL2_DIR }}/lib/pkgconfig
         cmake/test/test_pkgconfig.sh
     
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ab62ba097dc..4c9daf3903a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2534,7 +2534,7 @@ elseif(PSP)
   endif(NOT SDL2_DISABLE_SDL2MAIN)
 
 elseif(PS2)
-  list(APPEND EXTRA_CFLAGS "-DPS2" "-D__PS2__" "-I$ENV{PS2SDK}/ports/include")
+  list(APPEND EXTRA_CFLAGS "-DPS2" "-D__PS2__" "-I$ENV{PS2SDK}/ports/include" "-I$ENV{PS2DEV}/gsKit/include")
 
   file(GLOB PS2_MAIN_SOURCES ${SDL2_SOURCE_DIR}/src/main/ps2/*.c)
   set(SDLMAIN_SOURCES ${SDLMAIN_SOURCES} ${PS2_MAIN_SOURCES})
@@ -2569,9 +2569,19 @@ elseif(PS2)
     list(APPEND SOURCE_FILES ${PS2_TIMER_SOURCES})
     set(HAVE_SDL_TIMERS TRUE)
   endif()
+  if(SDL_VIDEO)
+    set(SDL_VIDEO_DRIVER_PS2 1)
+    set(SDL_VIDEO_RENDER_PS2 1)
+    file(GLOB PS2_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/ps2/*.c)
+    set(SOURCE_FILES ${SOURCE_FILES} ${PS2_VIDEO_SOURCES})
+    set(SDL_VIDEO_OPENGL 0)
+    set(HAVE_SDL_VIDEO TRUE)
+  endif()
 
   list(APPEND EXTRA_LIBS
     patches
+    gskit
+    dmakit
     ps2_drivers
   )
 
diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake
index 3c8edffec83..61b320f4f6d 100644
--- a/include/SDL_config.h.cmake
+++ b/include/SDL_config.h.cmake
@@ -414,6 +414,7 @@
 #cmakedefine SDL_VIDEO_DRIVER_QNX @SDL_VIDEO_DRIVER_QNX@
 #cmakedefine SDL_VIDEO_DRIVER_RISCOS @SDL_VIDEO_DRIVER_RISCOS@
 #cmakedefine SDL_VIDEO_DRIVER_PSP @SDL_VIDEO_DRIVER_PSP@
+#cmakedefine SDL_VIDEO_DRIVER_PS2 @SDL_VIDEO_DRIVER_PS2@
 
 #cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@
 #cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@
diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h
index fe643a4437d..fdaf1adf115 100644
--- a/src/video/SDL_sysvideo.h
+++ b/src/video/SDL_sysvideo.h
@@ -445,6 +445,7 @@ extern VideoBootStrap HAIKU_bootstrap;
 extern VideoBootStrap PND_bootstrap;
 extern VideoBootStrap UIKIT_bootstrap;
 extern VideoBootStrap Android_bootstrap;
+extern VideoBootStrap PS2_bootstrap;
 extern VideoBootStrap PSP_bootstrap;
 extern VideoBootStrap VITA_bootstrap;
 extern VideoBootStrap RISCOS_bootstrap;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index d1ce9d45f23..2ce99c9210d 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -91,6 +91,9 @@ static VideoBootStrap *bootstrap[] = {
 #if SDL_VIDEO_DRIVER_ANDROID
     &Android_bootstrap,
 #endif
+#if SDL_VIDEO_DRIVER_PS2
+    &PS2_bootstrap,
+#endif
 #if SDL_VIDEO_DRIVER_PSP
     &PSP_bootstrap,
 #endif
diff --git a/src/video/ps2/SDL_ps2events.c b/src/video/ps2/SDL_ps2events.c
new file mode 100644
index 00000000000..725ebc3e6b5
--- /dev/null
+++ b/src/video/ps2/SDL_ps2events.c
@@ -0,0 +1,41 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_PS2
+
+/* Being a ps2 driver, there's no event stream. We just define stubs for
+   most of the API. */
+
+#include "../../events/SDL_events_c.h"
+
+#include "SDL_ps2video.h"
+#include "SDL_ps2events_c.h"
+
+void
+PS2_PumpEvents(_THIS)
+{
+    /* do nothing. */
+}
+
+#endif /* SDL_VIDEO_DRIVER_PS2 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/ps2/SDL_ps2events_c.h b/src/video/ps2/SDL_ps2events_c.h
new file mode 100644
index 00000000000..b683d263124
--- /dev/null
+++ b/src/video/ps2/SDL_ps2events_c.h
@@ -0,0 +1,33 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_ps2events_c_h_
+#define SDL_ps2events_c_h_
+
+#include "../../SDL_internal.h"
+
+#include "SDL_ps2video.h"
+
+extern void PS2_PumpEvents(_THIS);
+
+#endif /* SDL_ps2events_c_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/ps2/SDL_ps2framebuffer.c b/src/video/ps2/SDL_ps2framebuffer.c
new file mode 100644
index 00000000000..34d6771cc96
--- /dev/null
+++ b/src/video/ps2/SDL_ps2framebuffer.c
@@ -0,0 +1,85 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_PS2
+
+#include "../SDL_sysvideo.h"
+#include "SDL_ps2framebuffer_c.h"
+
+
+#define PS2_SURFACE   "_SDL_PS2Surface"
+
+int SDL_PS2_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
+{
+    SDL_Surface *surface;
+    const Uint32 surface_format = SDL_PIXELFORMAT_RGB888;
+    int w, h;
+
+    /* Free the old framebuffer surface */
+    SDL_PS2_DestroyWindowFramebuffer(_this, window);
+
+    /* Create a new one */
+    SDL_GetWindowSize(window, &w, &h);
+    surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, surface_format);
+    if (!surface) {
+        return -1;
+    }
+
+    /* Save the info and return! */
+    SDL_SetWindowData(window, PS2_SURFACE, surface);
+    *format = surface_format;
+    *pixels = surface->pixels;
+    *pitch = surface->pitch;
+    return 0;
+}
+
+int SDL_PS2_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+{
+    static int frame_number;
+    SDL_Surface *surface;
+
+    surface = (SDL_Surface *) SDL_GetWindowData(window, PS2_SURFACE);
+    if (!surface) {
+        return SDL_SetError("Couldn't find ps2 surface for window");
+    }
+
+    /* Send the data to the display */
+    if (SDL_getenv("SDL_VIDEO_PS2_SAVE_FRAMES")) {
+        char file[128];
+        SDL_snprintf(file, sizeof(file), "SDL_window%" SDL_PRIu32 "-%8.8d.bmp",
+                     SDL_GetWindowID(window), ++frame_number);
+        SDL_SaveBMP(surface, file);
+    }
+    return 0;
+}
+
+void SDL_PS2_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
+{
+    SDL_Surface *surface;
+
+    surface = (SDL_Surface *) SDL_SetWindowData(window, PS2_SURFACE, NULL);
+    SDL_FreeSurface(surface);
+}
+
+#endif /* SDL_VIDEO_DRIVER_PS2 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/ps2/SDL_ps2framebuffer_c.h b/src/video/ps2/SDL_ps2framebuffer_c.h
new file mode 100644
index 00000000000..771425faa55
--- /dev/null
+++ b/src/video/ps2/SDL_ps2framebuffer_c.h
@@ -0,0 +1,33 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_ps2framebuffer_c_h_
+#define SDL_ps2framebuffer_c_h_
+
+#include "../../SDL_internal.h"
+
+extern int SDL_PS2_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
+extern int SDL_PS2_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
+extern void SDL_PS2_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
+
+#endif /* SDL_ps2framebuffer_c_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/ps2/SDL_ps2video.c b/src/video/ps2/SDL_ps2video.c
new file mode 100644
index 00000000000..3546d8d08e0
--- /dev/null
+++ b/src/video/ps2/SDL_ps2video.c
@@ -0,0 +1,134 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_PS2
+
+/* PS2 SDL video driver implementation; this is just enough to make an
+ *  SDL-based application THINK it's got a working video driver, for
+ *  applications that call SDL_Init(SDL_INIT_VIDEO) when they don't need it,
+ *  and also for use as a collection of stubs when porting SDL to a new
+ *  platform for which you haven't yet written a valid video driver.
+ *
+ * This is also a great way to determine bottlenecks: if you think that SDL
+ *  is a performance problem for a given platform, enable this driver, and
+ *  then see if your application runs faster without video overhead.
+ *
+ * Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion
+ *  of this was cut-and-pasted from Stephane Peter's work in the AAlib
+ *  SDL video driver.  Renamed to "PS2" by Sam Lantinga.
+ */
+
+#include "SDL_video.h"
+#include "SDL_mouse.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_pixels_c.h"
+#include "../../events/SDL_events_c.h"
+
+#include "SDL_ps2video.h"
+#include "SDL_ps2events_c.h"
+#include "SDL_ps2framebuffer_c.h"
+#include "SDL_hints.h"
+
+#define PS2VID_DRIVER_NAME "ps2"
+
+/* Initialization/Query functions */
+static int PS2_VideoInit(_THIS);
+static int PS2_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
+static void PS2_VideoQuit(_THIS);
+
+/* PS2 driver bootstrap functions */
+
+static void
+PS2_DeleteDevice(SDL_VideoDevice * device)
+{
+    SDL_free(device);
+}
+
+static SDL_VideoDevice *
+PS2_CreateDevice(int devindex)
+{
+    SDL_VideoDevice *device;
+
+    /* Initialize all variables that we clean on shutdown */
+    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+    if (!device) {
+        SDL_OutOfMemory();
+        return (0);
+    }
+    device->is_dummy = SDL_TRUE;
+
+    /* Set the function pointers */
+    device->VideoInit = PS2_VideoInit;
+    device->VideoQuit = PS2_VideoQuit;
+    device->SetDisplayMode = PS2_SetDisplayMode;
+    device->PumpEvents = PS2_PumpEvents;
+    device->CreateWindowFramebuffer = SDL_PS2_CreateWindowFramebuffer;
+    device->UpdateWindowFramebuffer = SDL_PS2_UpdateWindowFramebuffer;
+    device->DestroyWindowFramebuffer = SDL_PS2_DestroyWindowFramebuffer;
+
+    device->free = PS2_DeleteDevice;
+
+    return device;
+}
+
+VideoBootStrap PS2_bootstrap = {
+    PS2VID_DRIVER_NAME, "SDL PS2 video driver",
+    PS2_CreateDevice
+};
+
+
+int
+PS2_VideoInit(_THIS)
+{
+    SDL_DisplayMode mode;
+
+    /* Use a fake 32-bpp desktop mode */
+    SDL_zero(mode);
+    mode.format = SDL_PIXELFORMAT_RGB888;
+    mode.w = 1024;
+    mode.h = 768;
+    mode.refresh_rate = 0;
+    mode.driverdata = NULL;
+    if (SDL_AddBasicVideoDisplay(&mode) < 0) {
+        return -1;
+    }
+
+    SDL_AddDisplayMode(&_this->displays[0], &mode);
+
+    /* We're done! */
+    return 0;
+}
+
+static int
+PS2_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
+{
+    return 0;
+}
+
+void
+PS2_VideoQuit(_THIS)
+{
+}
+
+#endif /* SDL_VIDEO_DRIVER_PS2 */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/ps2/SDL_ps2video.h b/src/video/ps2/SDL_ps2video.h
new file mode 100644
index 00000000000..59fd8835ed3
--- /dev/null
+++ b/src/video/ps2/SDL_ps2video.h
@@ -0,0 +1,30 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_ps2video_h_
+#define SDL_ps2video_h_
+
+#include "../SDL_sysvideo.h"
+
+#endif /* SDL_ps2video_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 9415c83fe68..9639b60489a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -33,6 +33,8 @@ link_libraries(
         SDL2_test
         SDL2-static
         patches
+        gskit
+        dmakit
         ps2_drivers
 )
 else()