Blender V2.61 - r43446

GHOST_DisplayManagerSDL.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Campbell Barton
00019  *
00020  * Mode switching
00021  * Copyright (C) 1997-2001 Id Software, Inc.
00022  * Copyright (c) 1993-2011 Tim Riker
00023  * Copyright (C) 2012 Alex Fraser
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00032 #include "GHOST_SystemSDL.h"
00033 #include "GHOST_DisplayManagerSDL.h"
00034 
00035 GHOST_DisplayManagerSDL::GHOST_DisplayManagerSDL(GHOST_SystemSDL *system)
00036     :
00037       GHOST_DisplayManager(),
00038       m_system(system)
00039 {
00040     /* do nothing */
00041 }
00042 
00043 GHOST_TSuccess
00044 GHOST_DisplayManagerSDL::getNumDisplays(GHOST_TUns8& numDisplays) const
00045 {
00046     numDisplays=  SDL_GetNumVideoDisplays();
00047     return GHOST_kSuccess;
00048 }
00049 
00050 
00051 GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplaySettings(GHOST_TUns8 display,
00052                                                               GHOST_TInt32& numSettings) const
00053 {
00054     GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
00055     int i;
00056     SDL_Rect **vidmodes;
00057 
00058     vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
00059             SDL_FULLSCREEN | SDL_HWPALETTE);
00060     if (!vidmodes) {
00061         fprintf(stderr, "Could not get available video modes: %s.\n",
00062                 SDL_GetError());
00063         return GHOST_kFailure;
00064     }
00065     for (i = 0; vidmodes[i]; i++);
00066     numSettings = GHOST_TInt32(i);
00067 
00068     return GHOST_kSuccess;
00069 }
00070 
00071 GHOST_TSuccess
00072 GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display,
00073                                            GHOST_TInt32 index,
00074                                            GHOST_DisplaySetting& setting) const
00075 {
00076     GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
00077 
00078     int i;
00079     SDL_Rect **vidmodes;
00080     /* NULL is passed in here to get the modes for the current bit depth.
00081      * Other bit depths may be possible; in that case, an SDL_PixelFormat struct
00082      * should be passed in. To get a complete profile, all possible bit depths
00083      * would need to be iterated over. - z0r */
00084     vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
00085             SDL_FULLSCREEN | SDL_HWPALETTE);
00086     if (!vidmodes) {
00087         fprintf(stderr, "Could not get available video modes: %s.\n",
00088                 SDL_GetError());
00089         return GHOST_kFailure;
00090     }
00091     for (i = 0; vidmodes[i]; i++);
00092     GHOST_ASSERT(index < i, "Requested setting outside of valid range.\n");
00093 
00094     setting.xPixels = vidmodes[index]->w;
00095     setting.yPixels = vidmodes[index]->h;
00096 
00097     SDL_Surface *surf;
00098     surf = SDL_GetVideoSurface();
00099     if (surf == NULL) {
00100         fprintf(stderr, "Getting display setting: %s\n", SDL_GetError());
00101         /* Just guess the bit depth */
00102         setting.bpp = 32;
00103     } else {
00104         setting.bpp = surf->format->BitsPerPixel;
00105     }
00106     /* Just guess the frequency :( */
00107     setting.frequency = 60;
00108 
00109     return GHOST_kSuccess;
00110 }
00111 
00112 GHOST_TSuccess
00113 GHOST_DisplayManagerSDL::getCurrentDisplaySetting(GHOST_TUns8 display,
00114                                                   GHOST_DisplaySetting& setting) const
00115 {
00116     SDL_Surface *surf;
00117     const SDL_VideoInfo *info;
00118 
00119     /* Note: not using SDL_GetDesktopDisplayMode because that does not return
00120      * the current mode. Try to use GetVideoSurface first, as it seems more
00121      * accurate. If that fails, try other methods. - z0r */
00122     surf = SDL_GetVideoSurface();
00123 
00124     if (surf != NULL) {
00125         setting.xPixels = surf->w;
00126         setting.yPixels = surf->h;
00127         setting.bpp = surf->format->BitsPerPixel;
00128         /* Just guess the frequency :( */
00129         setting.frequency = 60;
00130     } else {
00131         /* This may happen if the surface hasn't been created yet, e.g. on
00132          * application startup. */
00133         info = SDL_GetVideoInfo();
00134         setting.xPixels = info->current_w;
00135         setting.yPixels = info->current_h;
00136         setting.bpp = info->vfmt->BitsPerPixel;
00137         /* Just guess the frequency :( */
00138         setting.frequency = 60;
00139     }
00140 
00141     return GHOST_kSuccess;
00142 }
00143 
00144 GHOST_TSuccess
00145 GHOST_DisplayManagerSDL:: setCurrentDisplaySetting(GHOST_TUns8 display,
00146                                                    const GHOST_DisplaySetting& setting)
00147 {
00148 
00149     /*
00150      * Mode switching code ported from Quake 2 version 3.21 and bzflag version
00151      * 2.4.0:
00152      * ftp://ftp.idsoftware.com/idstuff/source/q2source-3.21.zip
00153      * See linux/gl_glx.c:GLimp_SetMode
00154      * http://wiki.bzflag.org/BZFlag_Source
00155      * See src/platform/SDLDisplay.cxx:SDLDisplay and createWindow
00156      */
00157     SDL_Surface *surf;
00158     int best_fit, best_dist, dist, x, y;
00159 
00160     SDL_Rect **vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
00161             SDL_FULLSCREEN | SDL_HWPALETTE);
00162     if (!vidmodes) {
00163         fprintf(stderr, "Could not get available video modes: %s.\n",
00164                 SDL_GetError());
00165     }
00166 
00167     best_dist = 9999999;
00168     best_fit = -1;
00169 
00170     if (vidmodes == (SDL_Rect **) -1) {
00171         /* Any mode is OK. */
00172         x = setting.xPixels;
00173         y = setting.yPixels;
00174     } else {
00175         for (int i = 0; vidmodes[i]; i++) {
00176             if (setting.xPixels > vidmodes[i]->w ||
00177                 setting.yPixels > vidmodes[i]->h)
00178                 continue;
00179 
00180             x = setting.xPixels - vidmodes[i]->w;
00181             y = setting.yPixels - vidmodes[i]->h;
00182             dist = (x * x) + (y * y);
00183             if (dist < best_dist) {
00184                 best_dist = dist;
00185                 best_fit = i;
00186             }
00187         }
00188 
00189         if (best_fit == -1)
00190             return GHOST_kFailure;
00191 
00192         x = vidmodes[best_fit]->w;
00193         y = vidmodes[best_fit]->h;
00194     }
00195 
00196 #  ifdef _DEBUG
00197     printf("Switching to video mode %dx%d\n", x, y);
00198 #  endif
00199 
00200     // limit us to the main display
00201     static char singleDisplayEnv[] = "SDL_SINGLEDISPLAY=1";
00202     putenv(singleDisplayEnv);
00203 
00204     // change to the mode
00205     surf = SDL_SetVideoMode(x, y, setting.bpp, SDL_OPENGL | SDL_FULLSCREEN);
00206     if (surf == NULL) {
00207         fprintf(stderr, "Could not set video mode: %s.\n", SDL_GetError());
00208         return GHOST_kFailure;
00209     }
00210 
00211     return GHOST_kSuccess;
00212 }