rnd-20140114-1-src
[rocksndiamonds.git] / src / libgame / sdl.c
index 734307d55709d84060e2894492bb298b7eacd81d..4fd21a304494c6fda4b4e5d63135da4644f41430 100644 (file)
@@ -30,7 +30,7 @@ static SDL_Window *sdl_window = NULL;
 static SDL_Renderer *sdl_renderer = NULL;
 static SDL_Texture *sdl_texture = NULL;
 
-#define USE_RENDERER   1
+#define USE_RENDERER   TRUE
 #endif
 
 /* stuff needed to work around SDL/Windows fullscreen drawing bug */
@@ -197,6 +197,7 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
   };
 #endif
   SDL_Rect **modes = NULL;
+  boolean hardware_fullscreen_available = TRUE;
   int i, j;
 
   /* default: normal game window size */
@@ -206,6 +207,7 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
   fullscreen_yoffset = 0;
 
 #if !defined(TARGET_SDL2)
+  /* determine required standard fullscreen mode for game screen size */
   for (i = 0; screen_xy[i][0] != -1; i++)
   {
     if (screen_xy[i][0] >= video.width && screen_xy[i][1] >= video.height)
@@ -228,6 +230,8 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
   video.fullscreen_mode_current = NULL;
 #endif
 
+  video.window_scaling_percent = setup.window_scaling_percent;
+
 #if defined(TARGET_SDL2)
   int num_displays = SDL_GetNumVideoDisplays();
 
@@ -254,17 +258,16 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
       }
     }
   }
-
 #else
-
   /* get available hardware supported fullscreen modes */
   modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
 #endif
 
   if (modes == NULL)
   {
-    /* no screen modes available => no fullscreen mode support */
-    video.fullscreen_available = FALSE;
+    /* no hardware screen modes available => no fullscreen mode support */
+    // video.fullscreen_available = FALSE;
+    hardware_fullscreen_available = FALSE;
   }
   else if (modes == (SDL_Rect **)-1)
   {
@@ -318,10 +321,19 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
     if (num_modes == 0)
     {
       /* no appropriate screen modes available => no fullscreen mode support */
-      video.fullscreen_available = FALSE;
+      // video.fullscreen_available = FALSE;
+      hardware_fullscreen_available = FALSE;
     }
   }
 
+  video.fullscreen_available = hardware_fullscreen_available;
+
+#if USE_DESKTOP_FULLSCREEN
+  // in SDL 2.0, there is always support for desktop fullscreen mode
+  // (in SDL 1.2, there is only support for "real" fullscreen mode)
+  video.fullscreen_available = TRUE;
+#endif
+
 #if defined(TARGET_SDL2)
   if (modes)
   {
@@ -379,18 +391,18 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
                                    boolean fullscreen)
 {
   SDL_Surface *new_surface = NULL;
+  static boolean fullscreen_enabled = FALSE;
 
-  int surface_flags_window = SURFACE_FLAGS;
 #if defined(TARGET_SDL2)
-
-#if 1
+  int surface_flags_window = SURFACE_FLAGS | SDL_WINDOW_RESIZABLE;
+#if USE_DESKTOP_FULLSCREEN
   int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN_DESKTOP;
 #else
-  // (never used with SDL2 now)
   int surface_flags_fullscreen = SURFACE_FLAGS | SDL_WINDOW_FULLSCREEN;
 #endif
 
 #else
+  int surface_flags_window = SURFACE_FLAGS;
   int surface_flags_fullscreen = SURFACE_FLAGS | SDL_FULLSCREEN;
 #endif
 
@@ -399,33 +411,87 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
   int surface_flags = (fullscreen ? surface_flags_fullscreen :
                       surface_flags_window);
 
+  // default window size is unscaled
+  video.window_width  = video.width;
+  video.window_height = video.height;
+
 #if defined(TARGET_SDL2)
 
+  // store if initial screen mode on game start is fullscreen mode
+  if (sdl_window == NULL)
+  {
+#if 0
+    printf("::: GAME STARTS WITH FULLSCREEN %d\n", fullscreen);
+#endif
+
+    video.fullscreen_initial = fullscreen;
+  }
+
 #if USE_RENDERER
-  float scale_factor = 1.2;
+  float window_scaling_factor = (float)setup.window_scaling_percent / 100;
+#if !USE_DESKTOP_FULLSCREEN
+  float screen_scaling_factor = (fullscreen ? 1 : window_scaling_factor);
+#endif
+
+  video.window_width  = window_scaling_factor * width;
+  video.window_height = window_scaling_factor * height;
+
+#if 0
+  printf("::: use window scaling factor %f\n", screen_scaling_factor);
+#endif
 
   if ((*backbuffer)->surface)
+  {
     SDL_FreeSurface((*backbuffer)->surface);
+    (*backbuffer)->surface = NULL;
+  }
 
   if (sdl_texture)
+  {
     SDL_DestroyTexture(sdl_texture);
+    sdl_texture = NULL;
+  }
 
-  if (sdl_renderer)
-    SDL_DestroyRenderer(sdl_renderer);
+  if (!(fullscreen && fullscreen_enabled))
+  {
+    if (sdl_renderer)
+    {
+      SDL_DestroyRenderer(sdl_renderer);
+      sdl_renderer = NULL;
+    }
 
-  if (sdl_window)
-    SDL_DestroyWindow(sdl_window);
+    if (sdl_window)
+    {
+      SDL_DestroyWindow(sdl_window);
+      sdl_window = NULL;
+    }
+  }
 
-  sdl_window = SDL_CreateWindow(program.window_title,
-                               SDL_WINDOWPOS_CENTERED,
-                               SDL_WINDOWPOS_CENTERED,
-                               (int)(scale_factor * width),
-                               (int)(scale_factor * height),
-                               surface_flags);
+#if 0
+  Error(ERR_INFO, "::: checking 'sdl_window' ...");
+
+  if (sdl_window == NULL)
+    Error(ERR_INFO, "::: calling SDL_CreateWindow() [%d, %d, %d] ...",
+         setup.fullscreen, fullscreen, fullscreen_enabled);
+#endif
+
+  if (sdl_window == NULL)
+    sdl_window = SDL_CreateWindow(program.window_title,
+                                 SDL_WINDOWPOS_CENTERED,
+                                 SDL_WINDOWPOS_CENTERED,
+#if USE_DESKTOP_FULLSCREEN
+                                 video.window_width,
+                                 video.window_height,
+#else
+                                 (int)(screen_scaling_factor * width),
+                                 (int)(screen_scaling_factor * height),
+#endif
+                                 surface_flags);
 
   if (sdl_window != NULL)
   {
-    sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
+    if (sdl_renderer == NULL)
+      sdl_renderer = SDL_CreateRenderer(sdl_window, -1, 0);
 
     if (sdl_renderer != NULL)
     {
@@ -493,6 +559,10 @@ static SDL_Surface *SDLCreateScreen(DrawBuffer **backbuffer,
   new_surface = SDL_SetVideoMode(width, height, video.depth, surface_flags);
 #endif
 
+  // store fullscreen state ("video.fullscreen_enabled" may not reflect this!)
+  if (new_surface != NULL)
+    fullscreen_enabled = fullscreen;
+
   return new_surface;
 }
 
@@ -584,7 +654,7 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
 #if defined(TARGET_SDL2)
 
 #if USE_RENDERER
-    float scale_factor = 1.2;
+    float screen_scaling_factor = 1.2;
     int test_fullscreen = 0;
     int surface_flags = (test_fullscreen ? surface_flags_fullscreen :
                         surface_flags_window);
@@ -604,8 +674,8 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
     sdl_window = SDL_CreateWindow(program.window_title,
                                  SDL_WINDOWPOS_CENTERED,
                                  SDL_WINDOWPOS_CENTERED,
-                                 (int)(scale_factor * video.width),
-                                 (int)(scale_factor * video.height),
+                                 (int)(screen_scaling_factor * video.width),
+                                 (int)(screen_scaling_factor * video.height),
                                  surface_flags);
 
     if (sdl_window != NULL)
@@ -697,13 +767,15 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
       (*backbuffer)->surface = new_surface;
 
       video.fullscreen_enabled = FALSE;
+      video.window_scaling_percent = setup.window_scaling_percent;
 
       success = TRUE;
     }
   }
 
 #if defined(TARGET_SDL2)
-  UpdateScreen(NULL);          // map window
+  SDLRedrawWindow();                   // map window
+  // UpdateScreen(NULL);               // map window
 #endif
 
 #if 1
@@ -727,6 +799,69 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
   return success;
 }
 
+#if defined(TARGET_SDL2)
+void SDLSetWindowScaling(int window_scaling_percent)
+{
+  if (sdl_window == NULL)
+    return;
+
+  float window_scaling_factor = (float)window_scaling_percent / 100;
+  int new_window_width  = (int)(window_scaling_factor * video.width);
+  int new_window_height = (int)(window_scaling_factor * video.height);
+
+#if 0
+  Error(ERR_DEBUG, "::: SDLSetWindowScaling(%d) ...", window_scaling_percent);
+#endif
+
+  SDL_SetWindowSize(sdl_window, new_window_width, new_window_height);
+
+  video.window_scaling_percent = window_scaling_percent;
+  video.window_width  = new_window_width;
+  video.window_height = new_window_height;
+}
+
+void SDLSetWindowFullscreen(boolean fullscreen)
+{
+  if (sdl_window == NULL)
+    return;
+
+#if USE_DESKTOP_FULLSCREEN
+  int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
+#else
+  int flags = (fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
+#endif
+
+#if 0
+  Error(ERR_DEBUG, "::: SDL_SetWindowFullscreen(%d) ...", fullscreen);
+#endif
+
+  if (SDL_SetWindowFullscreen(sdl_window, flags) == 0)
+    video.fullscreen_enabled = fullscreen;
+
+#if 0
+  printf("::: SDLSetWindowFullscreen: %d, %d\n",
+        fullscreen, video.fullscreen_initial);
+#endif
+
+#if 1
+  // if game started in fullscreen mode, window will also get fullscreen size
+  if (!fullscreen && video.fullscreen_initial)
+  {
+    SDLSetWindowScaling(setup.window_scaling_percent);
+    SDL_SetWindowPosition(sdl_window,
+                         SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+
+    video.fullscreen_initial = FALSE;
+  }
+#endif
+}
+
+void SDLRedrawWindow()
+{
+  UpdateScreen(NULL);
+}
+#endif
+
 void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
                            int depth)
 {