shithub: choc

Download patch

ref: 3f2a6fdf8aa5b685927627c0940eb2bd54db0851
parent: 10db74bbd140e5b36e55e9b21df0d6143a95d275
author: Fabian Greffrath <fabian@greffrath.com>
date: Sun Aug 7 14:18:58 EDT 2016

SetVideoMode(): make re-entrant

Well, at least kind of (think of the forks that might want to change
renderer flags in-game). ;)

The SDL_Window *screen and the SDL_Surface *screenbuffer need not get
recreated, it's sufficient to create them once. The same applies to
the SDL_surface *rgbabuffer. Only the SDL_Renderer *renderer needs to
get recreated and the SDL_Texture *texture based on the new renderer.
The SDL_Texture *texture_upscaled needs to get recreated as well with
the new renderer. Else, it is recreated only if the texture scale
factors have changed.

All of this means no functional changes for Chocolate Doom, because it
only runs SetVideoMode() once at start up.

--- a/src/i_video.c
+++ b/src/i_video.c
@@ -523,7 +523,7 @@
 
 }
 
-static void CreateUpscaledTexture(void)
+static void CreateUpscaledTexture(boolean force)
 {
     const int actualheight = EffectiveScreenHeight();
     int w, h;
@@ -587,7 +587,7 @@
 
     // Create a new texture only if the upscale factors have actually changed.
 
-    if (h_upscale == h_upscale_old && w_upscale == w_upscale_old)
+    if (h_upscale == h_upscale_old && w_upscale == w_upscale_old && !force)
     {
         return;
     }
@@ -630,7 +630,7 @@
 
     if (need_resize)
     {
-        CreateUpscaledTexture();
+        CreateUpscaledTexture(false);
         need_resize = false;
         palette_to_set = true;
     }
@@ -1012,23 +1012,6 @@
     int unused_bpp;
     int window_flags = 0, renderer_flags = 0;
 
-    // If we are already running, we need to free the screenbuffer
-    // surface before setting the new mode.
-
-    if (screenbuffer != NULL)
-    {
-        SDL_FreeSurface(screenbuffer);
-        screenbuffer = NULL;
-    }
-
-    // Close the current window.
-
-    if (screen != NULL)
-    {
-        SDL_DestroyWindow(screen);
-        screen = NULL;
-    }
-
     w = window_width;
     h = window_height;
 
@@ -1064,15 +1047,22 @@
     // "window_flags" contains the fullscreen flag (see above), then
     // w and h are ignored.
 
-    screen = SDL_CreateWindow(NULL, x, y, w, h, window_flags);
-
     if (screen == NULL)
     {
-        I_Error("Error creating window for video startup: %s", SDL_GetError());
-    }
+        screen = SDL_CreateWindow(NULL, x, y, w, h, window_flags);
 
-    SDL_SetWindowMinimumSize(screen, SCREENWIDTH, EffectiveScreenHeight());
+        if (screen == NULL)
+        {
+            I_Error("Error creating window for video startup: %s",
+            SDL_GetError());
+        }
 
+        SDL_SetWindowMinimumSize(screen, SCREENWIDTH, EffectiveScreenHeight());
+
+        I_InitWindowTitle();
+        I_InitWindowIcon();
+    }
+
     // The SDL_RENDERER_TARGETTEXTURE flag is required to render the
     // intermediate texture into the upscaled texture.
     renderer_flags = SDL_RENDERER_TARGETTEXTURE;
@@ -1082,6 +1072,11 @@
         renderer_flags |= SDL_RENDERER_SOFTWARE;
     }
 
+    if (renderer != NULL)
+    {
+        SDL_DestroyRenderer(renderer);
+    }
+
     renderer = SDL_CreateRenderer(screen, -1, renderer_flags);
 
     if (renderer == NULL)
@@ -1098,9 +1093,6 @@
                              SCREENWIDTH,
                              EffectiveScreenHeight());
 
-    I_InitWindowTitle();
-    I_InitWindowIcon();
-
     // Blank out the full screen area in case there is any junk in
     // the borders that won't otherwise be overwritten.
 
@@ -1110,20 +1102,31 @@
 
     // Create the 8-bit paletted and the 32-bit RGBA screenbuffer surfaces.
 
-    screenbuffer = SDL_CreateRGBSurface(0,
-                                        SCREENWIDTH, SCREENHEIGHT, 8,
-                                        0, 0, 0, 0);
-    SDL_FillRect(screenbuffer, NULL, 0);
+    if (screenbuffer == NULL)
+    {
+        screenbuffer = SDL_CreateRGBSurface(0,
+                                            SCREENWIDTH, SCREENHEIGHT, 8,
+                                            0, 0, 0, 0);
+        SDL_FillRect(screenbuffer, NULL, 0);
+    }
 
     // Format of rgbabuffer must match the screen pixel format because we
     // import the surface data into the texture.
-    SDL_PixelFormatEnumToMasks(SDL_GetWindowPixelFormat(screen), &unused_bpp,
-                               &rmask, &gmask, &bmask, &amask);
-    rgbabuffer = SDL_CreateRGBSurface(0,
-                                      SCREENWIDTH, SCREENHEIGHT, 32,
-                                      rmask, gmask, bmask, amask);
-    SDL_FillRect(rgbabuffer, NULL, 0);
+    if (rgbabuffer == NULL)
+    {
+        SDL_PixelFormatEnumToMasks(SDL_GetWindowPixelFormat(screen), &unused_bpp,
+                                   &rmask, &gmask, &bmask, &amask);
+        rgbabuffer = SDL_CreateRGBSurface(0,
+                                          SCREENWIDTH, SCREENHEIGHT, 32,
+                                          rmask, gmask, bmask, amask);
+        SDL_FillRect(rgbabuffer, NULL, 0);
+    }
 
+    if (texture != NULL)
+    {
+        SDL_DestroyTexture(texture);
+    }
+
     // Set the scaling quality for rendering the intermediate texture into
     // the upscaled texture to "nearest", which is gritty and pixelated and
     // resembles software scaling pretty well.
@@ -1141,7 +1144,7 @@
 
     // Initially create the upscaled texture for rendering to screen
 
-    CreateUpscaledTexture();
+    CreateUpscaledTexture(true);
 }
 
 static const char *hw_emu_warning =