SDL: events: Added SDL_RenderEvent.

From 615c935d114d477649a054ba9921a7d3b6871fdc Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 21 Nov 2024 12:59:41 -0500
Subject: [PATCH] events: Added SDL_RenderEvent.

Fixes #11465.
---
 include/SDL3/SDL_events.h                | 16 ++++++++++++++++
 src/events/SDL_events.c                  | 13 +++++++++----
 src/render/direct3d/SDL_render_d3d.c     |  3 ++-
 src/render/direct3d11/SDL_render_d3d11.c |  3 ++-
 src/render/direct3d12/SDL_render_d3d12.c |  3 ++-
 src/render/vulkan/SDL_render_vulkan.c    |  3 ++-
 src/test/SDL_test_common.c               |  6 +++---
 src/video/android/SDL_androidevents.c    |  5 +++--
 8 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h
index 5b3d475271a20..aa1691b951791 100644
--- a/include/SDL3/SDL_events.h
+++ b/include/SDL3/SDL_events.h
@@ -704,6 +704,21 @@ typedef struct SDL_CameraDeviceEvent
     SDL_CameraID which;       /**< SDL_CameraID for the device being added or removed or changing */
 } SDL_CameraDeviceEvent;
 
+
+/**
+ * Renderer event structure (event.render.*)
+ *
+ * \since This struct is available since SDL 3.1.7.
+ */
+typedef struct SDL_RenderEvent
+{
+    SDL_EventType type; /**< SDL_EVENT_RENDER_TARGETS_RESET, SDL_EVENT_RENDER_DEVICE_RESET, SDL_EVENT_RENDER_DEVICE_LOST */
+    Uint32 reserved;
+    Uint64 timestamp;   /**< In nanoseconds, populated using SDL_GetTicksNS() */
+    SDL_WindowID windowID; /**< The window containing the renderer in question. */
+} SDL_RenderEvent;
+
+
 /**
  * Touch finger event structure (event.tfinger.*)
  *
@@ -980,6 +995,7 @@ typedef union SDL_Event
     SDL_PenMotionEvent pmotion;             /**< Pen motion event data */
     SDL_PenButtonEvent pbutton;             /**< Pen button event data */
     SDL_PenAxisEvent paxis;                 /**< Pen axis event data */
+    SDL_RenderEvent render;                 /**< Render event data */
     SDL_DropEvent drop;                     /**< Drag and drop event data */
     SDL_ClipboardEvent clipboard;           /**< Clipboard event data */
 
diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c
index 55e518382daa2..e6253ff07287f 100644
--- a/src/events/SDL_events.c
+++ b/src/events/SDL_events.c
@@ -450,10 +450,15 @@ static void SDL_LogEvent(const SDL_Event *event)
         break;
         SDL_EVENT_CASE(SDL_EVENT_CLIPBOARD_UPDATE)
         break;
-        SDL_EVENT_CASE(SDL_EVENT_RENDER_TARGETS_RESET)
-        break;
-        SDL_EVENT_CASE(SDL_EVENT_RENDER_DEVICE_RESET)
-        break;
+
+#define SDL_RENDEREVENT_CASE(x)                \
+    case x:                                    \
+        SDL_strlcpy(name, #x, sizeof(name));   \
+        (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u event=%s windowid=%u)", \
+                           (uint)event->display.timestamp, name, (uint)event->render.windowID); \
+        break
+        SDL_RENDEREVENT_CASE(SDL_EVENT_RENDER_TARGETS_RESET);
+        SDL_RENDEREVENT_CASE(SDL_EVENT_RENDER_DEVICE_RESET);
 
 #define SDL_DISPLAYEVENT_CASE(x)               \
     case x:                                    \
diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c
index e757de082a9ff..ec79455b79c01 100644
--- a/src/render/direct3d/SDL_render_d3d.c
+++ b/src/render/direct3d/SDL_render_d3d.c
@@ -1559,8 +1559,9 @@ static bool D3D_Reset(SDL_Renderer *renderer)
     // Let the application know that render targets were reset
     {
         SDL_Event event;
+        SDL_zero(event);
         event.type = SDL_EVENT_RENDER_TARGETS_RESET;
-        event.common.timestamp = 0;
+        event.render.windowID = SDL_GetWindowID(SDL_GetRenderWindow(renderer));
         SDL_PushEvent(&event);
     }
 
diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c
index c14346ff3f5f3..5c2b5419b9f3b 100644
--- a/src/render/direct3d11/SDL_render_d3d11.c
+++ b/src/render/direct3d11/SDL_render_d3d11.c
@@ -1084,8 +1084,9 @@ static bool D3D11_HandleDeviceLost(SDL_Renderer *renderer)
 
     // Let the application know that the device has been reset or lost
     SDL_Event event;
+    SDL_zero(event);
     event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
-    event.common.timestamp = 0;
+    event.render.windowID = SDL_GetWindowID(SDL_GetRenderWindow(renderer));
     SDL_PushEvent(&event);
 
     return recovered;
diff --git a/src/render/direct3d12/SDL_render_d3d12.c b/src/render/direct3d12/SDL_render_d3d12.c
index 55114335048cd..7e0d846c83dc4 100644
--- a/src/render/direct3d12/SDL_render_d3d12.c
+++ b/src/render/direct3d12/SDL_render_d3d12.c
@@ -1459,8 +1459,9 @@ static bool D3D12_HandleDeviceLost(SDL_Renderer *renderer)
 
     // Let the application know that the device has been reset or lost
     SDL_Event event;
+    SDL_zero(event);
     event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
-    event.common.timestamp = 0;
+    event.render.windowID = SDL_GetWindowID(SDL_GetRenderWindow(renderer));
     SDL_PushEvent(&event);
 
     return recovered;
diff --git a/src/render/vulkan/SDL_render_vulkan.c b/src/render/vulkan/SDL_render_vulkan.c
index 2ccad3e080baa..c1cc521e72792 100644
--- a/src/render/vulkan/SDL_render_vulkan.c
+++ b/src/render/vulkan/SDL_render_vulkan.c
@@ -2519,8 +2519,9 @@ static bool VULKAN_HandleDeviceLost(SDL_Renderer *renderer)
 
     // Let the application know that the device has been reset or lost
     SDL_Event event;
+    SDL_zero(event);
     event.type = recovered ? SDL_EVENT_RENDER_DEVICE_RESET : SDL_EVENT_RENDER_DEVICE_LOST;
-    event.common.timestamp = 0;
+    event.render.windowID = SDL_GetWindowID(SDL_GetRenderWindow(renderer));
     SDL_PushEvent(&event);
 
     return recovered;
diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c
index b434be4949989..ffa417bec9a87 100644
--- a/src/test/SDL_test_common.c
+++ b/src/test/SDL_test_common.c
@@ -1899,13 +1899,13 @@ void SDLTest_PrintEvent(const SDL_Event *event)
         break;
 
     case SDL_EVENT_RENDER_TARGETS_RESET:
-        SDL_Log("SDL EVENT: render targets reset");
+        SDL_Log("SDL EVENT: render targets reset in window %" SDL_PRIu32, event->render.windowID);
         break;
     case SDL_EVENT_RENDER_DEVICE_RESET:
-        SDL_Log("SDL EVENT: render device reset");
+        SDL_Log("SDL EVENT: render device reset in window %" SDL_PRIu32, event->render.windowID);
         break;
     case SDL_EVENT_RENDER_DEVICE_LOST:
-        SDL_Log("SDL EVENT: render device lost");
+        SDL_Log("SDL EVENT: render device lost in window %" SDL_PRIu32, event->render.windowID);
         break;
 
     case SDL_EVENT_TERMINATING:
diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c
index 0ffe38f6f801b..40511bc34acaa 100644
--- a/src/video/android/SDL_androidevents.c
+++ b/src/video/android/SDL_androidevents.c
@@ -36,15 +36,16 @@
 static void android_egl_context_restore(SDL_Window *window)
 {
     if (window) {
-        SDL_Event event;
         SDL_WindowData *data = window->internal;
         SDL_GL_MakeCurrent(window, NULL);
         if (!SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context)) {
             // The context is no longer valid, create a new one
             data->egl_context = (EGLContext)SDL_GL_CreateContext(window);
             SDL_GL_MakeCurrent(window, (SDL_GLContext)data->egl_context);
+            SDL_Event event;
+            SDL_zero(event);
             event.type = SDL_EVENT_RENDER_DEVICE_RESET;
-            event.common.timestamp = 0;
+            event.render.windowID = SDL_GetWindowID(SDL_GetRenderWindow(renderer));
             SDL_PushEvent(&event);
         }
         data->backup_done = false;