SDL: N3DS: Deduce screen from window's display.

From f9785702a687b2f1b726517209c2360996d8f460 Mon Sep 17 00:00:00 2001
From: Pierre Wendling <[EMAIL REDACTED]>
Date: Sun, 18 Sep 2022 13:22:07 -0400
Subject: [PATCH] N3DS: Deduce screen from window's display.

This removes the need for a dedicated window creation flag.
---
 include/SDL_video.h            |  1 -
 src/video/SDL_video.c          |  2 +-
 src/video/n3ds/SDL_n3dsvideo.c | 48 ++++++++++++++++++++++++++--------
 3 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/include/SDL_video.h b/include/SDL_video.h
index 60afda22a787..d9dce43a96f4 100644
--- a/include/SDL_video.h
+++ b/include/SDL_video.h
@@ -126,7 +126,6 @@ typedef enum
     SDL_WINDOW_KEYBOARD_GRABBED = 0x00100000,   /**< window has grabbed keyboard input */
     SDL_WINDOW_VULKAN           = 0x10000000,   /**< window usable for Vulkan surface */
     SDL_WINDOW_METAL            = 0x20000000,   /**< window usable for Metal view */
-    SDL_WINDOW_N3DS_BOTTOM      = 0x40000000,   /**< window should be on the bottom screen (N3DS only) */
 
     SDL_WINDOW_INPUT_GRABBED = SDL_WINDOW_MOUSE_GRABBED /**< equivalent to SDL_WINDOW_MOUSE_GRABBED for compatibility */
 } SDL_WindowFlags;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index fbeaaaaeee05..bb2036108620 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -1501,7 +1501,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
 }
 
 #define CREATE_FLAGS \
-    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL | SDL_WINDOW_N3DS_BOTTOM)
+    (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP | SDL_WINDOW_VULKAN | SDL_WINDOW_MINIMIZED | SDL_WINDOW_METAL)
 
 static SDL_INLINE SDL_bool
 IsAcceptingDragAndDrop(void)
diff --git a/src/video/n3ds/SDL_n3dsvideo.c b/src/video/n3ds/SDL_n3dsvideo.c
index 6d3babd2dc42..ebcb9de2eec2 100644
--- a/src/video/n3ds/SDL_n3dsvideo.c
+++ b/src/video/n3ds/SDL_n3dsvideo.c
@@ -35,9 +35,15 @@ SDL_FORCE_INLINE void AddN3DSDisplay(gfxScreen_t screen);
 static int N3DS_VideoInit(_THIS);
 static void N3DS_VideoQuit(_THIS);
 static void N3DS_GetDisplayModes(_THIS, SDL_VideoDisplay *display);
+static int N3DS_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect);
 static int N3DS_CreateWindow(_THIS, SDL_Window *window);
 static void N3DS_DestroyWindow(_THIS, SDL_Window *window);
 
+typedef struct
+{
+    gfxScreen_t screen;
+} DisplayDriverData;
+
 /* N3DS driver bootstrap functions */
 
 static void
@@ -61,6 +67,7 @@ N3DS_CreateDevice(void)
     device->VideoQuit = N3DS_VideoQuit;
 
     device->GetDisplayModes = N3DS_GetDisplayModes;
+    device->GetDisplayBounds = N3DS_GetDisplayBounds;
 
     device->CreateSDLWindow = N3DS_CreateWindow;
     device->DestroyWindow = N3DS_DestroyWindow;
@@ -100,19 +107,27 @@ AddN3DSDisplay(gfxScreen_t screen)
 {
     SDL_DisplayMode mode;
     SDL_VideoDisplay display;
+    DisplayDriverData *display_driver_data = SDL_calloc(1, sizeof(DisplayDriverData));
+    if (display_driver_data == NULL) {
+        SDL_OutOfMemory();
+        return;
+    }
 
     SDL_zero(mode);
     SDL_zero(display);
 
+    display_driver_data->screen = screen;
+
     mode.w = (screen == GFX_TOP) ? GSP_SCREEN_HEIGHT_TOP : GSP_SCREEN_HEIGHT_BOTTOM;
     mode.h = GSP_SCREEN_WIDTH;
     mode.refresh_rate = 60;
     mode.format = FRAMEBUFFER_FORMAT;
     mode.driverdata = NULL;
 
+    display.name = (screen == GFX_TOP) ? "N3DS top screen" : "N3DS bottom screen";
     display.desktop_mode = mode;
     display.current_mode = mode;
-    display.driverdata = NULL;
+    display.driverdata = display_driver_data;
 
     SDL_AddVideoDisplay(&display, SDL_FALSE);
 }
@@ -132,20 +147,31 @@ N3DS_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
 }
 
 static int
-N3DS_CreateWindow(_THIS, SDL_Window *window)
+N3DS_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
 {
-    SDL_WindowData *drv_data = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
-    if (drv_data == NULL) {
-        return SDL_OutOfMemory();
+    DisplayDriverData *driver_data = (DisplayDriverData *) display->driverdata;
+    if (driver_data == NULL) {
+        return -1;
     }
+    rect->x = 0;
+    rect->y = (driver_data->screen == GFX_TOP) ? 0 : GSP_SCREEN_WIDTH;
+    rect->w = display->current_mode.w;
+    rect->h = display->current_mode.h;
 
-    if (window->flags & SDL_WINDOW_N3DS_BOTTOM) {
-        drv_data->screen = GFX_BOTTOM;
-    } else {
-        drv_data->screen = GFX_TOP;
-    }
+    return 0;
+}
 
-    window->driverdata = drv_data;
+static int
+N3DS_CreateWindow(_THIS, SDL_Window *window)
+{
+    DisplayDriverData *display_data;
+    SDL_WindowData *window_data = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
+    if (window_data == NULL) {
+        return SDL_OutOfMemory();
+    }
+    display_data = (DisplayDriverData *) SDL_GetDisplayDriverData(window->display_index);
+    window_data->screen = display_data->screen;
+    window->driverdata = window_data;
     return 0;
 }