Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Fraser <alex@phatcore.com>2012-01-11 15:59:57 +0400
committerAlex Fraser <alex@phatcore.com>2012-01-11 15:59:57 +0400
commit37fc8b4dbbe2cb4b38c9c000834f0b10e1bf1ff0 (patch)
tree04101a0e40c154d8c1893ceb7a54cad4e285c66a /intern/ghost
parent535d27eb4923d5582ff16b4016344e8f712608d7 (diff)
This patch implements mode switching (resolution changing) for full-screen games.
Hopefully, this should be platform agnostic. Requires WITH_GHOST_SDL. This patch contains code from Quake 2 and bzflag. Tracker: [#29839]
Diffstat (limited to 'intern/ghost')
-rw-r--r--intern/ghost/intern/GHOST_DisplayManagerSDL.cpp148
1 files changed, 134 insertions, 14 deletions
diff --git a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
index 4c67616a4c4..1b875e657d9 100644
--- a/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
+++ b/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
@@ -17,6 +17,11 @@
*
* Contributor(s): Campbell Barton
*
+ * Mode switching
+ * Copyright (C) 1997-2001 Id Software, Inc.
+ * Copyright (c) 1993-2011 Tim Riker
+ * Copyright (C) 2012 Alex Fraser
+ *
* ***** END GPL LICENSE BLOCK *****
*/
@@ -47,7 +52,19 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplaySettings(GHOST_TUns8 displa
GHOST_TInt32& numSettings) const
{
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
- numSettings= GHOST_TInt32(1);
+ int i;
+ SDL_Rect **vidmodes;
+
+ vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
+ SDL_FULLSCREEN | SDL_HWPALETTE);
+ if (!vidmodes) {
+ fprintf(stderr, "Could not get available video modes: %s.\n",
+ SDL_GetError());
+ return GHOST_kFailure;
+ }
+ for (i = 0; vidmodes[i]; i++);
+ numSettings = GHOST_TInt32(i);
+
return GHOST_kSuccess;
}
@@ -56,18 +73,38 @@ GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display,
GHOST_TInt32 index,
GHOST_DisplaySetting& setting) const
{
-
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
- GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n");
- SDL_DisplayMode mode;
- SDL_GetDesktopDisplayMode(display, &mode);
+ int i;
+ SDL_Rect **vidmodes;
+ /* NULL is passed in here to get the modes for the current bit depth.
+ * Other bit depths may be possible; in that case, an SDL_PixelFormat struct
+ * should be passed in. To get a complete profile, all possible bit depths
+ * would need to be iterated over. - z0r */
+ vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
+ SDL_FULLSCREEN | SDL_HWPALETTE);
+ if (!vidmodes) {
+ fprintf(stderr, "Could not get available video modes: %s.\n",
+ SDL_GetError());
+ return GHOST_kFailure;
+ }
+ for (i = 0; vidmodes[i]; i++);
+ GHOST_ASSERT(index < i, "Requested setting outside of valid range.\n");
+
+ setting.xPixels = vidmodes[index]->w;
+ setting.yPixels = vidmodes[index]->h;
- setting.xPixels= mode.w;
- setting.yPixels= mode.h;
- setting.bpp= SDL_BYTESPERPIXEL(mode.format);
- /* assume 60 when unset */
- setting.frequency= mode.refresh_rate ? mode.refresh_rate : 60;
+ SDL_Surface *surf;
+ surf = SDL_GetVideoSurface();
+ if (surf == NULL) {
+ fprintf(stderr, "Getting display setting: %s\n", SDL_GetError());
+ /* Just guess the bit depth */
+ setting.bpp = 32;
+ } else {
+ setting.bpp = surf->format->BitsPerPixel;
+ }
+ /* Just guess the frequency :( */
+ setting.frequency = 60;
return GHOST_kSuccess;
}
@@ -76,17 +113,100 @@ GHOST_TSuccess
GHOST_DisplayManagerSDL::getCurrentDisplaySetting(GHOST_TUns8 display,
GHOST_DisplaySetting& setting) const
{
- return getDisplaySetting(display,GHOST_TInt32(0),setting);
+ SDL_Surface *surf;
+ const SDL_VideoInfo *info;
+
+ /* Note: not using SDL_GetDesktopDisplayMode because that does not return
+ * the current mode. Try to use GetVideoSurface first, as it seems more
+ * accurate. If that fails, try other methods. - z0r */
+ surf = SDL_GetVideoSurface();
+
+ if (surf != NULL) {
+ setting.xPixels = surf->w;
+ setting.yPixels = surf->h;
+ setting.bpp = surf->format->BitsPerPixel;
+ /* Just guess the frequency :( */
+ setting.frequency = 60;
+ } else {
+ /* This may happen if the surface hasn't been created yet, e.g. on
+ * application startup. */
+ info = SDL_GetVideoInfo();
+ setting.xPixels = info->current_w;
+ setting.yPixels = info->current_h;
+ setting.bpp = info->vfmt->BitsPerPixel;
+ /* Just guess the frequency :( */
+ setting.frequency = 60;
+ }
+
+ return GHOST_kSuccess;
}
GHOST_TSuccess
GHOST_DisplayManagerSDL:: setCurrentDisplaySetting(GHOST_TUns8 display,
const GHOST_DisplaySetting& setting)
{
- // This is never going to work robustly in X
- // but it's currently part of the full screen interface
- // we fudge it for now.
+ /*
+ * Mode switching code ported from Quake 2 version 3.21 and bzflag version
+ * 2.4.0:
+ * ftp://ftp.idsoftware.com/idstuff/source/q2source-3.21.zip
+ * See linux/gl_glx.c:GLimp_SetMode
+ * http://wiki.bzflag.org/BZFlag_Source
+ * See src/platform/SDLDisplay.cxx:SDLDisplay and createWindow
+ */
+ SDL_Surface *surf;
+ int best_fit, best_dist, dist, x, y;
+
+ SDL_Rect **vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
+ SDL_FULLSCREEN | SDL_HWPALETTE);
+ if (!vidmodes) {
+ fprintf(stderr, "Could not get available video modes: %s.\n",
+ SDL_GetError());
+ }
+
+ best_dist = 9999999;
+ best_fit = -1;
+
+ if (vidmodes == (SDL_Rect **) -1) {
+ /* Any mode is OK. */
+ x = setting.xPixels;
+ y = setting.yPixels;
+ } else {
+ for (int i = 0; vidmodes[i]; i++) {
+ if (setting.xPixels > vidmodes[i]->w ||
+ setting.yPixels > vidmodes[i]->h)
+ continue;
+
+ x = setting.xPixels - vidmodes[i]->w;
+ y = setting.yPixels - vidmodes[i]->h;
+ dist = (x * x) + (y * y);
+ if (dist < best_dist) {
+ best_dist = dist;
+ best_fit = i;
+ }
+ }
+
+ if (best_fit == -1)
+ return GHOST_kFailure;
+
+ x = vidmodes[best_fit]->w;
+ y = vidmodes[best_fit]->h;
+ }
+
+# ifdef _DEBUG
+ printf("Switching to video mode %dx%d\n", x, y);
+# endif
+
+ // limit us to the main display
+ static char singleDisplayEnv[] = "SDL_SINGLEDISPLAY=1";
+ putenv(singleDisplayEnv);
+
+ // change to the mode
+ surf = SDL_SetVideoMode(x, y, setting.bpp, SDL_OPENGL | SDL_FULLSCREEN);
+ if (surf == NULL) {
+ fprintf(stderr, "Could not set video mode: %s.\n", SDL_GetError());
+ return GHOST_kFailure;
+ }
return GHOST_kSuccess;
}