Commit 9288983682cc5cab7f0d7d1da2b837f67b3367a0

Ryan C. Gordon 2017-06-06T14:06:40

Merged Eric Wing's overscan patch. Fixes Bugzilla #2799.

diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 5753276..5f21935 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -119,6 +119,17 @@ extern "C" {
 #define SDL_HINT_RENDER_DIRECT3D11_DEBUG    "SDL_RENDER_DIRECT3D11_DEBUG"
 
 /**
+ *  \brief  A variable controlling the scaling policy for SDL_RenderSetLogicalSize.
+ *
+ *  This variable can be set to the following values:
+ *    "0" or "letterbox" - Uses letterbox/sidebars to fit the entire rendering on screen
+ *    "1" or "overscan"  - Will zoom the rendering so it fills the entire screen, allowing edges to be drawn offscreen
+ *
+ *  By default letterbox is used
+ */
+#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE       "SDL_HINT_RENDER_LOGICAL_SIZE_MODE"
+
+/**
  *  \brief  A variable controlling the scaling quality
  *
  *  This variable can be set to the following values:
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 7cc1324..1068627 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -1156,6 +1156,9 @@ UpdateLogicalSize(SDL_Renderer *renderer)
     float real_aspect;
     float scale;
     SDL_Rect viewport;
+    /* 0 is for letterbox, 1 is for overscan */
+    int scale_policy = 0;
+    const char *hint = SDL_GetHint(SDL_HINT_RENDER_LOGICAL_SIZE_MODE);
 
     if (!renderer->logical_w || !renderer->logical_h) {
         return 0;
@@ -1164,6 +1167,23 @@ UpdateLogicalSize(SDL_Renderer *renderer)
         return -1;
     }
 
+    if (!hint) {
+        scale_policy = 0;
+    } else if ( *hint == '1' || SDL_strcasecmp(hint, "overscan") == 0)  {
+        /* Unfortunately, Direct3D 9 does't support negative viewport numbers
+        which the main overscan implementation relies on.
+        D3D11 does support negative values and uses a different id string
+        so overscan will work for D3D11.
+        */
+        if(SDL_strcasecmp("direct3d", SDL_GetCurrentVideoDriver())) {
+            scale_policy = 0;
+        } else {
+            scale_policy = 1;
+        }
+    } else {
+        scale_policy = 0;
+    }
+    
     want_aspect = (float)renderer->logical_w / renderer->logical_h;
     real_aspect = (float)w / h;
 
@@ -1187,21 +1207,47 @@ UpdateLogicalSize(SDL_Renderer *renderer)
         scale = (float)w / renderer->logical_w;
         SDL_RenderSetViewport(renderer, NULL);
     } else if (want_aspect > real_aspect) {
-        /* We want a wider aspect ratio than is available - letterbox it */
-        scale = (float)w / renderer->logical_w;
-        viewport.x = 0;
-        viewport.w = w;
-        viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
-        viewport.y = (h - viewport.h) / 2;
-        SDL_RenderSetViewport(renderer, &viewport);
+        if (scale_policy == 1) {
+            /* We want a wider aspect ratio than is available - 
+             zoom so logical height matches the real height 
+             and the width will grow off the screen 
+             */
+            scale = (float)h / renderer->logical_h;
+            viewport.y = 0;
+            viewport.h = h;
+            viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
+            viewport.x = (w - viewport.w) / 2;
+            SDL_RenderSetViewport(renderer, &viewport);
+        } else {
+            /* We want a wider aspect ratio than is available - letterbox it */
+            scale = (float)w / renderer->logical_w;
+            viewport.x = 0;
+            viewport.w = w;
+            viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
+            viewport.y = (h - viewport.h) / 2;
+            SDL_RenderSetViewport(renderer, &viewport);
+        }
     } else {
-        /* We want a narrower aspect ratio than is available - use side-bars */
-        scale = (float)h / renderer->logical_h;
-        viewport.y = 0;
-        viewport.h = h;
-        viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
-        viewport.x = (w - viewport.w) / 2;
-        SDL_RenderSetViewport(renderer, &viewport);
+        if (scale_policy == 1) {
+            /* We want a narrower aspect ratio than is available -
+             zoom so logical width matches the real width
+             and the height will grow off the screen
+             */
+            scale = (float)w / renderer->logical_w;
+            viewport.x = 0;
+            viewport.w = w;
+            viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
+            viewport.y = (h - viewport.h) / 2;
+            SDL_RenderSetViewport(renderer, &viewport);
+        } else {
+            /* We want a narrower aspect ratio than is available - use side-bars */
+             scale = (float)h / renderer->logical_h;
+             viewport.y = 0;
+             viewport.h = h;
+             viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
+             viewport.x = (w - viewport.w) / 2;
+             SDL_RenderSetViewport(renderer, &viewport);
+        }
     }
 
     /* Set the new scale */