[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [43285] trunk/blender/intern/ghost/intern/ GHOST_DisplayManagerSDL.cpp: This patch implements mode switching ( resolution changing) for full-screen games.

Alex Fraser alex at phatcore.com
Wed Jan 11 13:00:03 CET 2012


Revision: 43285
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=43285
Author:   z0r
Date:     2012-01-11 11:59:57 +0000 (Wed, 11 Jan 2012)
Log Message:
-----------
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]

Modified Paths:
--------------
    trunk/blender/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp

Modified: trunk/blender/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp
===================================================================
--- trunk/blender/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp	2012-01-11 09:33:44 UTC (rev 43284)
+++ trunk/blender/intern/ghost/intern/GHOST_DisplayManagerSDL.cpp	2012-01-11 11:59:57 UTC (rev 43285)
@@ -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_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,19 +73,39 @@
                                            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= 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;
+	setting.xPixels = vidmodes[index]->w;
+	setting.yPixels = vidmodes[index]->h;
 
+	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_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;
 }




More information about the Bf-blender-cvs mailing list