DEADSOFTWARE

menu: change videomode at runtime
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 10 Apr 2020 11:48:42 +0000 (15:48 +0400)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 10 Apr 2020 11:48:42 +0000 (15:48 +0400)
src/gl/render.c
src/sdl/main.c
src/sdl2/main.c
src/system.h

index 2b5d53192a42af7ec6f697de90ac85dcace088d8..c057b90e4fa84bc6d0d1a7d3647089995c33c047 100644 (file)
@@ -1837,18 +1837,7 @@ void R_set_videomode (int w, int h, int fullscreen) {
     if (was == 0) {
       ERR_failinit("Unable to set video mode\n");
     }
-  } else {
-    Y_get_videomode(&SCRW, &SCRH);
-    root = R_cache_new();
-    assert(root);
-    R_alloc();
-    R_reload_textures();
   }
-}
-
-static void R_fullscreen (int yes) {
-  R_cache_free(root, 0);
-  Y_set_fullscreen(yes);
   Y_get_videomode(&SCRW, &SCRH);
   root = R_cache_new();
   assert(root);
@@ -1857,23 +1846,57 @@ static void R_fullscreen (int yes) {
 }
 
 static int R_video_menu_handler (new_msg_t *msg, const new_menu_t *m, void *data) {
+  const videomode_t *v;
   intptr_t i = (intptr_t)data;
+  static int w, h;
+  static int vmode;
   static int fullscreen;
+  static char str[16];
   switch (i) {
     case -1:
       switch (msg->type) {
-        case GM_ENTER: fullscreen = Y_get_fullscreen(); return 1;
+        case GM_ENTER:
+          Y_get_videomode(&w, &h);
+          fullscreen = Y_get_fullscreen();
+          v = Y_get_videomode_list_opengl(fullscreen);
+          vmode = 0;
+          while (vmode < v->n && v->modes[vmode].w != w && v->modes[vmode].h != h) {
+            vmode += 1;
+          }
+          if (vmode < v->n) {
+            w = v->modes[vmode].w;
+            h = v->modes[vmode].h;
+          }
+          snprintf(str, 16, "%ix%i", w, h);
+          return 1;
       }
       break;
     case 0:
+      switch (msg->type) {
+        case GM_SELECT:
+          v = Y_get_videomode_list_opengl(fullscreen);
+          vmode = vmode + 1 >= v->n ? 0 : vmode + 1;
+          if (v->n > 0) {
+            w = v->modes[vmode].w;
+            h = v->modes[vmode].h;
+          } else {
+            Y_get_videomode(&w, &h);
+          }
+          snprintf(str, 16, "%ix%i", w, h);
+          return 1;
+        case GM_GETSTR:
+          return GM_init_str(msg, str, 16);
+      }
+      break;
+    case 1:
       switch (msg->type) {
         case GM_SELECT: fullscreen = !fullscreen; return 1;
         case GM_GETSTR: return GM_init_str(msg, fullscreen ? "Yes" : "No", 3);
       }
       break;
-    case 1:
+    case 2:
       switch (msg->type) {
-        case GM_SELECT: R_fullscreen(fullscreen); return 1;
+        case GM_SELECT: R_set_videomode(w, h, fullscreen); return 1;
       }
   }
   return 0;
@@ -1882,8 +1905,9 @@ static int R_video_menu_handler (new_msg_t *msg, const new_menu_t *m, void *data
 static const new_menu_t video_menu = {
   GM_BIG, "Video", (void*)-1, &R_video_menu_handler,
   {
-    { GM_BUTTON, "Fullscreen: ", (void*)0, &R_video_menu_handler, NULL },
-    { GM_BUTTON, "Apply", (void*)1, &R_video_menu_handler, NULL },
+    { GM_BUTTON, "Videomode: ", (void*)0, &R_video_menu_handler, NULL },
+    { GM_BUTTON, "Fullscreen: ", (void*)1, &R_video_menu_handler, NULL },
+    { GM_BUTTON, "Apply", (void*)2, &R_video_menu_handler, NULL },
     { 0, NULL, NULL, NULL, NULL } // end
   }
 };
index 36b32798913dd64aa89f179ecec0dee2a9c80a8e..9227725c9876a90f48dd1c9380ab3695acda90ae 100644 (file)
@@ -56,6 +56,7 @@ static int quit = 0;
 static SDL_Surface *surf = NULL;
 static int mode = MODE_NONE;
 static int text_input;
+static videomode_t vlist;
 
 /* --- error.h --- */
 
@@ -151,6 +152,47 @@ int Y_set_videomode_software (int w, int h, int fullscreen) {
   return s != NULL;
 }
 
+static void init_videomode_list (Uint32 flags) {
+  int i, n;
+  SDL_Rect **r;
+  if (vlist.modes != NULL) {
+    free(vlist.modes);
+    vlist.modes = NULL;
+    vlist.n = 0;
+  }
+  r = SDL_ListModes(NULL, flags);
+  if (r == (SDL_Rect **)-1) {
+    if ((flags & SDL_FULLSCREEN) == 0) {
+      init_videomode_list(flags | SDL_FULLSCREEN);
+    }
+  } else if (r != (SDL_Rect**)0) {
+    n = 0;
+    while (r[n] != NULL) {
+      n++;
+    }
+    vlist.modes = malloc(n * sizeof(videomode_size_t));
+    if (vlist.modes != NULL) {
+      vlist.n = n;
+      for (i = 0; i < n; i++) {
+        vlist.modes[i] = (videomode_size_t) {
+          .w = r[i]->w,
+          .h = r[i]->h
+        };
+      }
+    }
+  }
+}
+
+const videomode_t *Y_get_videomode_list_opengl (int fullscreen) {
+  init_videomode_list(SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0));
+  return &vlist;
+}
+
+const videomode_t *Y_get_videomode_list_software (int fullscreen) {
+  init_videomode_list(SDL_SWSURFACE | SDL_HWPALETTE | (fullscreen ? SDL_FULLSCREEN : 0));
+  return &vlist;
+}
+
 void Y_get_videomode (int *w, int *h) {
   if (mode != MODE_NONE) {
     *w = surf->w;
index a6b98d6813f6020130572574a6ea010cc6025694..1a25886799791e976727ca56a7a36e381f97ef7f 100644 (file)
@@ -31,6 +31,7 @@ static int quit = 0;
 static SDL_Window *window;
 static SDL_GLContext context;
 static SDL_Surface *surf;
+static videomode_t vlist;
 
 /* --- error.h --- */
 
@@ -201,6 +202,48 @@ void Y_unset_videomode (void) {
   }
 }
 
+static void init_videomode_list (void) {
+  int i, j, k;
+  SDL_DisplayMode m;
+  int n = SDL_GetNumDisplayModes(0);
+  if (vlist.modes != NULL) {
+    free(vlist.modes);
+    vlist.modes = NULL;
+    vlist.n = 0;
+  }
+  if (n > 0) {
+    vlist.modes = malloc(n * sizeof(videomode_size_t));
+    if (vlist.modes != NULL) {
+      j = 0;
+      for (i = 0; i < n; i++) {
+        SDL_GetDisplayMode(0, i, &m);
+        k = 0;
+        while (k < j && (m.w != vlist.modes[k].w || m.h != vlist.modes[k].h)) {
+          k++;
+        }
+        if (k >= j) {
+          vlist.modes[j] = (videomode_size_t) {
+            .w = m.w,
+            .h = m.h
+          };
+          j++;
+        }
+      }
+      vlist.n = j;
+    }
+  }
+}
+
+const videomode_t *Y_get_videomode_list_opengl (int fullscreen) {
+  init_videomode_list();
+  return &vlist;
+}
+
+const videomode_t *Y_get_videomode_list_software (int fullscreen) {
+  init_videomode_list();
+  return &vlist;
+}
+
 void Y_set_fullscreen (int yes) {
   if (window != NULL) {
     SDL_SetWindowFullscreen(window, yes ? SDL_WINDOW_FULLSCREEN : 0);
index 41cf079fe2ae3fb518f6325e3eb9b39ff1905498..0de8d42ef9e216cb22c6d87f371dd5b5361b49a3 100644 (file)
@@ -3,8 +3,14 @@
 
 #include "glob.h"
 
-#define SYSTEM_USE_OPENGL (1 << 0)
-#define SYSTEM_USE_FULLSCREEN (1 << 1)
+typedef struct videomode_size_t {
+  int w, h, r;
+} videomode_size_t;
+
+typedef struct videomode_t {
+  int n;
+  videomode_size_t *modes;
+} videomode_t;
 
 /* common video subsystem routines */
 void Y_get_videomode (int *w, int *h);
@@ -15,10 +21,12 @@ int Y_get_fullscreen (void);
 
 /* hardware specific rendering */
 int Y_set_videomode_opengl (int w, int h, int fullscreen);
+const videomode_t *Y_get_videomode_list_opengl (int fullscreen);
 void Y_swap_buffers (void);
 
 /* software specific rendering */
 int Y_set_videomode_software (int w, int h, int fullscreen);
+const videomode_t *Y_get_videomode_list_software (int fullscreen);
 void Y_get_buffer (byte **buf, int *w, int *h, int *pitch);
 void Y_set_vga_palette (byte *vgapal);
 void Y_repaint_rect (int x, int y, int w, int h);