foxygit / doom Log in
commit ad8d7a1efb8c61bb39568f76ab814919895cc501
Author:     Simon Howard <fraggle@gmail.com>
AuthorDate: Tue Aug 3 20:12:36 2010 +0000
Commit:     Simon Howard <fraggle@gmail.com>
CommitDate: Tue Aug 3 20:12:36 2010 +0000

    When in windowed mode, allow the screen size to be dynamically resized
    by dragging the window borders.

    Subversion-branch: /trunk/chocolate-doom
    Subversion-revision: 1949
---
 src/i_scale.c |  14 +++-
 src/i_video.c | 208 ++++++++++++++++++++++++++++++++++++++--------------------
 2 files changed, 150 insertions(+), 72 deletions(-)

diff --git a/src/i_scale.c b/src/i_scale.c
index a022ab15..3f7b3a7d 100644
--- a/src/i_scale.c
+++ b/src/i_scale.c
@@ -53,11 +53,11 @@ static int dest_pitch;
 // stretch_tables[1] : 40% / 60%
 // All other combinations can be reached from these two tables.

-static byte *stretch_tables[2];
+static byte *stretch_tables[2] = { NULL, NULL };

 // 50%/50% stretch table, for 800x600 squash mode

-static byte *half_stretch_table;
+static byte *half_stretch_table = NULL;

 // Called to set the source and destination buffers before doing the
 // scale.
@@ -364,6 +364,11 @@ static byte *GenerateStretchTable(byte *palette, int pct)

 static void I_InitStretchTables(byte *palette)
 {
+    if (stretch_tables[0] != NULL)
+    {
+        return;
+    }
+
     // We only actually need two lookup tables:
     //
     // mix 0%   =  just write line 1
@@ -385,6 +390,11 @@ static void I_InitStretchTables(byte *palette)

 static void I_InitSquashTable(byte *palette)
 {
+    if (half_stretch_table != NULL)
+    {
+        return;
+    }
+
     printf("I_InitSquashTable: Generating lookup table..");
     fflush(stdout);
     half_stretch_table = GenerateStretchTable(palette, 50);
diff --git a/src/i_video.c b/src/i_video.c
index bc3f17cf..91b670b8 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -98,8 +98,6 @@ static SDL_Surface *screen;
 static SDL_Color palette[256];
 static boolean palette_to_set;

-static int windowwidth, windowheight;
-
 // display has been set up?

 static boolean initialized = false;
@@ -160,6 +158,12 @@ static SDL_Cursor *cursors[2];

 static screen_mode_t *screen_mode;

+// Window resize state.
+
+static boolean need_resize = false;
+static unsigned int resize_w, resize_h;
+static unsigned int last_resize_time;
+
 // If true, keyboard mapping is ignored, like in Vanilla Doom.
 // The sensible thing to do is to disable this if you have a non-US
 // keyboard.
@@ -178,6 +182,8 @@ int vanilla_keyboard_mapping = true;
 float mouse_acceleration = 2.0;
 int mouse_threshold = 10;

+static void ApplyWindowResize(unsigned int w, unsigned int h);
+
 static boolean MouseShouldBeGrabbed()
 {
     // never grab the mouse when in screensaver mode
@@ -580,6 +586,13 @@ void I_GetEvent(void)
                 palette_to_set = true;
                 break;

+            case SDL_RESIZABLE:
+                need_resize = true;
+                resize_w = sdlevent.resize.w;
+                resize_h = sdlevent.resize.h;
+                last_resize_time = SDL_GetTicks();
+                break;
+
             default:
                 break;
         }
@@ -815,14 +828,20 @@ void I_FinishUpdate (void)
     static int	lasttic;
     int		tics;
     int		i;
-    // UNUSED static unsigned char *bigscreen=0;

     if (!initialized)
         return;

     if (noblit)
         return;
-
+
+    if (need_resize && SDL_GetTicks() > last_resize_time + 500)
+    {
+        ApplyWindowResize(resize_w, resize_h);
+        need_resize = false;
+        palette_to_set = true;
+    }
+
     UpdateGrab();

     // Don't update the screen if the window isn't visible.
@@ -1492,11 +1511,96 @@ static char *WindowBoxType(screen_mode_t *mode, int w, int h)
     }
 }

+static void SetVideoMode(screen_mode_t *mode, int w, int h)
+{
+    byte *doompal;
+    int flags = 0;
+
+    doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE);
+
+    // Generate lookup tables before setting the video mode.
+
+    if (mode != NULL && mode->InitMode != NULL)
+    {
+        mode->InitMode(doompal);
+    }
+
+    // Set the video mode.
+
+    flags |= SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
+
+    if (fullscreen)
+    {
+        flags |= SDL_FULLSCREEN;
+    }
+    else
+    {
+        flags |= SDL_RESIZABLE;
+    }
+
+    screen = SDL_SetVideoMode(w, h, 8, flags);
+
+    if (screen == NULL)
+    {
+        I_Error("Error setting video mode: %s\n", SDL_GetError());
+    }
+
+    // If mode was not set, it must be set now that we know the
+    // screen size.
+
+    if (mode == NULL)
+    {
+        mode = I_FindScreenMode(screen->w, screen->h);
+
+        if (mode == NULL)
+        {
+            I_Error("I_InitGraphics: Unable to find a screen mode small "
+                    "enough for %ix%i", screen->w, screen->h);
+        }
+
+        // Generate lookup tables before setting the video mode.
+
+        if (mode->InitMode != NULL)
+        {
+            mode->InitMode(doompal);
+        }
+    }
+
+    // Save screen mode.
+
+    screen_mode = mode;
+}
+
+static void ApplyWindowResize(unsigned int w, unsigned int h)
+{
+    screen_mode_t *mode;
+
+    // Find the biggest screen mode that will fall within these
+    // dimensions, falling back to the smallest mode possible if
+    // none is found.
+
+    mode = I_FindScreenMode(w, h);
+
+    if (mode == NULL)
+    {
+        mode = I_FindScreenMode(SCREENWIDTH, SCREENHEIGHT);
+    }
+
+    // Reset mode to resize window.
+
+    printf("Resize to %ix%i\n", mode->width, mode->height);
+    SetVideoMode(mode, mode->width, mode->height);
+
+    // Save settings.
+
+    screen_width = mode->width;
+    screen_height = mode->height;
+}
+
 void I_InitGraphics(void)
 {
     SDL_Event dummy;
     byte *doompal;
-    int flags = 0;
     char *env;

     // Pass through the XSCREENSAVER_WINDOW environment variable to
@@ -1527,70 +1631,53 @@ void I_InitGraphics(void)

     CheckCommandLine();

-    doompal = W_CacheLumpName (DEH_String("PLAYPAL"),PU_CACHE);
+    // Set up title and icon.  Windows cares about the ordering; this
+    // has to be done before the call to SDL_SetVideoMode.
+
+    I_SetWindowCaption();
+#if !SDL_VERSION_ATLEAST(1, 3, 0)
+    I_SetWindowIcon();
+#endif
+
+    //
+    // Enter into graphics mode.
+    //
+    // When in screensaver mode, run full screen and auto detect
+    // screen dimensions (don't change video mode)
+    //

     if (screensaver_mode)
     {
-        windowwidth = 0;
-        windowheight = 0;
+        SetVideoMode(NULL, 0, 0);
     }
     else
     {
+        int w, h;
+
         if (autoadjust_video_settings)
         {
             I_AutoAdjustSettings();
         }

-        windowwidth = screen_width;
-        windowheight = screen_height;
+        w = screen_width;
+        h = screen_height;

-        screen_mode = I_FindScreenMode(windowwidth, windowheight);
+        screen_mode = I_FindScreenMode(w, h);

         if (screen_mode == NULL)
         {
             I_Error("I_InitGraphics: Unable to find a screen mode small "
-                    "enough for %ix%i", windowwidth, windowheight);
+                    "enough for %ix%i", w, h);
         }

-        if (windowwidth != screen_mode->width
-         || windowheight != screen_mode->height)
+        if (w != screen_mode->width || h != screen_mode->height)
         {
             printf("I_InitGraphics: %s (%ix%i within %ix%i)\n",
-                   WindowBoxType(screen_mode, windowwidth, windowheight),
-                   screen_mode->width, screen_mode->height,
-                   windowwidth, windowheight);
-        }
-
-        // Generate lookup tables before setting the video mode.
-
-        if (screen_mode->InitMode != NULL)
-        {
-            screen_mode->InitMode(doompal);
+                   WindowBoxType(screen_mode, w, h),
+                   screen_mode->width, screen_mode->height, w, h);
         }
-    }
-
-    // Set up title and icon.  Windows cares about the ordering; this
-    // has to be done before the call to SDL_SetVideoMode.
-
-    I_SetWindowCaption();
-#if !SDL_VERSION_ATLEAST(1, 3, 0)
-    I_SetWindowIcon();
-#endif
-
-    // Set the video mode.
-
-    flags |= SDL_SWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF;
-
-    if (fullscreen)
-    {
-        flags |= SDL_FULLSCREEN;
-    }
-
-    screen = SDL_SetVideoMode(windowwidth, windowheight, 8, flags);

-    if (screen == NULL)
-    {
-        I_Error("Error setting video mode: %s\n", SDL_GetError());
+        SetVideoMode(screen_mode, w, h);
     }

     // Start with a clear black screen
@@ -1611,6 +1698,7 @@ void I_InitGraphics(void)

     // Set the palette

+    doompal = W_CacheLumpName(DEH_String("PLAYPAL"), PU_CACHE);
     I_SetPalette(doompal);
     SDL_SetColors(screen, palette, 0, 256);

@@ -1619,26 +1707,6 @@ void I_InitGraphics(void)
     UpdateFocus();
     UpdateGrab();

-    // In screensaver mode, now find a screen_mode to use.
-
-    if (screensaver_mode)
-    {
-        screen_mode = I_FindScreenMode(screen->w, screen->h);
-
-        if (screen_mode == NULL)
-        {
-            I_Error("I_InitGraphics: Unable to find a screen mode small "
-                    "enough for %ix%i", screen->w, screen->h);
-        }
-
-        // Generate lookup tables before setting the video mode.
-
-        if (screen_mode->InitMode != NULL)
-        {
-            screen_mode->InitMode(doompal);
-        }
-    }
-
     // On some systems, it takes a second or so for the screen to settle
     // after changing modes.  We include the option to add a delay when
     // setting the screen mode, so that the game doesn't start immediately
@@ -1654,12 +1722,12 @@ void I_InitGraphics(void)
     // Likewise if the screen pitch is not the same as the width
     // If we have to multiply, drawing is done to a separate 320x200 buf

-    native_surface = !SDL_MUSTLOCK(screen)
+    native_surface = !SDL_MUSTLOCK(screen)
                   && screen_mode == &mode_scale_1x
                   && screen->pitch == SCREENWIDTH
                   && aspect_ratio_correct;

-    // If not, allocate a buffer and copy from that buffer to the
+    // If not, allocate a buffer and copy from that buffer to the
     // screen when we do an update

     if (native_surface)
@@ -1670,7 +1738,7 @@ void I_InitGraphics(void)
     }
     else
     {
-	screens[0] = (unsigned char *) Z_Malloc (SCREENWIDTH * SCREENHEIGHT,
+	screens[0] = (unsigned char *) Z_Malloc (SCREENWIDTH * SCREENHEIGHT,
                                                  PU_STATIC, NULL);
     }