foxygit / doom Log in
commit dd9fa2865d5362abf1e0fa8dd15658f91164e26a
Author:     Simon Howard <fraggle@soulsphere.org>
AuthorDate: Sat Feb 27 22:38:55 2016 -0500
Commit:     Simon Howard <fraggle@soulsphere.org>
CommitDate: Sat Feb 27 22:38:55 2016 -0500

    video: Add support for OS X high-DPI rendering.

    This gives extra resolution when using a Mac with a retina display, and
    can actually make a significant difference in terms of quality,
    especially when using small window sizes.
---
 src/i_video.c | 46 ++++++++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/src/i_video.c b/src/i_video.c
index 142e07a5..6a92f337 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -436,14 +436,23 @@ static void UpdateGrab(void)

 }

-static void CreateUpscaledTexture(int w, int h)
+static void CreateUpscaledTexture(void)
 {
     const int actualheight = aspect_ratio_correct ?
                              SCREENHEIGHT_4_3 :
                              SCREENHEIGHT;
+    int w, h;
     int h_upscale, w_upscale;
     static int h_upscale_old, w_upscale_old;

+    // Get the size of the renderer output. The units this gives us will be
+    // real world pixels, which are not necessarily equivalent to the screen's
+    // window size (because of highdpi).
+    if (SDL_GetRendererOutputSize(renderer, &w, &h) != 0)
+    {
+        I_Error("Failed to get renderer output size: %s", SDL_GetError());
+    }
+
     // When the screen or window dimensions do not match the aspect ratio
     // of the texture, the rendered area is scaled down to fit. Calculate
     // the actual dimensions of the rendered area.
@@ -461,34 +470,35 @@ static void CreateUpscaledTexture(int w, int h)
         w = h * SCREENWIDTH / actualheight;
     }

+    // Pick texture size the next integer multiple of the screen dimensions.
     // If one screen dimension matches an integer multiple of the original
     // resolution, there is no need to overscale in this direction.

-    h_upscale = h / SCREENHEIGHT;
+    w_upscale = (w + SCREENWIDTH - 1) / SCREENWIDTH;
+    h_upscale = (h + SCREENHEIGHT - 1) / SCREENHEIGHT;
+
+    // Minimum texture dimensions of 320x200.

-    if (!h || h % SCREENHEIGHT)
+    if (w_upscale < 1)
     {
-        h_upscale++;
+        w_upscale = 1;
     }
-
-    w_upscale = w / SCREENWIDTH;
-
-    if (!w || w % SCREENWIDTH)
+    if (h_upscale < 1)
     {
-        w_upscale++;
+        h_upscale = 1;
     }

     // Limit maximum texture dimensions to 1600x1200.
-
-    if (h_upscale > 6)
-    {
-        h_upscale = 6;
-    }
+    // It's really diminishing returns at this point.

     if (w_upscale > 5)
     {
         w_upscale = 5;
     }
+    if (h_upscale > 6)
+    {
+        h_upscale = 6;
+    }

     // Create a new texture only if the upscale factors have actually changed.

@@ -535,7 +545,7 @@ void I_FinishUpdate (void)

     if (need_resize && SDL_GetTicks() > last_resize_time + 1000/TICRATE)
     {
-        CreateUpscaledTexture(resize_w, resize_h);
+        CreateUpscaledTexture();
         screen_width = resize_w;
         screen_height = resize_h;
         need_resize = false;
@@ -977,6 +987,10 @@ static void SetVideoMode(int w, int h)
         flags |= SDL_WINDOW_RESIZABLE;
     }

+    // Set the highdpi flag - this makes a big difference on Macs with
+    // retina displays, especially when using small window sizes.
+    flags |= SDL_WINDOW_ALLOW_HIGHDPI;
+
     // Create window and renderer contexts. We set the window title
     // later anyway and leave the window position "undefined". If "flags"
     // contains the fullscreen flag (see above), then w and h are ignored.
@@ -1065,7 +1079,7 @@ static void SetVideoMode(int w, int h)

     // Initially create the upscaled texture for rendering to screen

-    CreateUpscaledTexture(w, h);
+    CreateUpscaledTexture();
 }

 void I_InitGraphics(void)