SDL: render: SDL_RenderPresent now behaves when a render target is currently set.

From 4c48ff51f8060d3d1b842584b7d3e2c81d999870 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Wed, 25 Sep 2024 12:33:21 -0400
Subject: [PATCH] render: SDL_RenderPresent now behaves when a render target is
 currently set.

It'll temporarily unbind it, draw letterboxing if necessary, present, and
then rebind the previous render target.
---
 include/SDL3/SDL_render.h | 10 ++++++----
 src/render/SDL_render.c   | 10 +++++++---
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h
index 1f90102df09ad..348c0492eab69 100644
--- a/include/SDL3/SDL_render.h
+++ b/include/SDL3/SDL_render.h
@@ -2061,10 +2061,12 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_RenderReadPixels(SDL_Renderer *ren
  * pixel.
  *
  * Please note, that in case of rendering to a texture - there is **no need**
- * to call `SDL_RenderPresent` after drawing needed objects to a texture, you
- * are only required to change back the rendering target to default via
- * `SDL_SetRenderTarget(renderer, NULL)` afterwards, as textures by themselves
- * do not have a concept of backbuffers.
+ * to call `SDL_RenderPresent` after drawing needed objects to a texture, and
+ * should not be done; you are only required to change back the rendering
+ * target to default via `SDL_SetRenderTarget(renderer, NULL)` afterwards, as
+ * textures by themselves do not have a concept of backbuffers. Calling
+ * SDL_RenderPresent while rendering to a texture will still update the
+ * screen with any current drawing that has been done _to the window itself_.
  *
  * \param renderer the rendering context.
  * \returns true on success or false on failure; call SDL_GetError() for more
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 6868611a25f97..d85d85b7123b9 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -4949,9 +4949,9 @@ bool SDL_RenderPresent(SDL_Renderer *renderer)
 
     CHECK_RENDERER_MAGIC(renderer, false);
 
-    // !!! FIXME: fail if using a render target? Or just implicitly set the render target to NULL now?
-    if (renderer->view != &renderer->main_view) {
-        return SDL_SetError("Cannot present a render target");
+    SDL_Texture *target = renderer->target;
+    if (target) {
+        SDL_SetRenderTarget(renderer, NULL);
     }
 
     SDL_RenderLogicalPresentation(renderer);
@@ -4972,6 +4972,10 @@ bool SDL_RenderPresent(SDL_Renderer *renderer)
         presented = false;
     }
 
+    if (target) {
+        SDL_SetRenderTarget(renderer, target);
+    }
+
     if (renderer->simulate_vsync ||
         (!presented && renderer->wanted_vsync)) {
         SDL_SimulateRenderVSync(renderer);