Blender V2.61 - r43446

GHOST_DisplayManagerX11.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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Video mode switching
00024  * Copyright (C) 1997-2001 Id Software, Inc.
00025  * Ported from Quake 2 by Alex Fraser <alex@phatcore.com>
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00034 #ifdef WITH_X11_XF86VMODE
00035 #  include <X11/Xlib.h>
00036 #  include <X11/extensions/xf86vmode.h>
00037 #endif
00038 
00039 #include "GHOST_DisplayManagerX11.h"
00040 #include "GHOST_SystemX11.h"
00041 
00042 
00043 
00044 GHOST_DisplayManagerX11::
00045 GHOST_DisplayManagerX11(
00046     GHOST_SystemX11 *system
00047 ) :
00048     GHOST_DisplayManager(),
00049     m_system(system)
00050 {
00051     //nothing to do.
00052 }
00053 
00054     GHOST_TSuccess 
00055 GHOST_DisplayManagerX11::
00056 getNumDisplays(
00057     GHOST_TUns8& numDisplays
00058 ) const{    
00059     numDisplays =  m_system->getNumDisplays();
00060     return GHOST_kSuccess;
00061 }
00062 
00063 
00064     GHOST_TSuccess 
00065 GHOST_DisplayManagerX11::
00066 getNumDisplaySettings(
00067     GHOST_TUns8 display,
00068     GHOST_TInt32& numSettings
00069 ) const{
00070 #ifdef WITH_X11_XF86VMODE
00071     int majorVersion, minorVersion;
00072     XF86VidModeModeInfo **vidmodes;
00073     Display *dpy = m_system->getXDisplay();
00074 
00075     GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
00076 
00077     if (dpy == NULL)
00078         return GHOST_kFailure;
00079 
00080     majorVersion = minorVersion = 0;
00081     if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
00082         fprintf(stderr, "Error: XF86VidMode extension missing!\n");
00083         return GHOST_kFailure;
00084     }
00085 
00086     /* The X11 man page says vidmodes needs to be freed, but doing so causes a
00087      * segfault. - z0r */
00088     XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes);
00089 
00090 #else
00091     // We only have one X11 setting at the moment.
00092     GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");    
00093     numSettings = GHOST_TInt32(1);
00094 #endif
00095 
00096     return GHOST_kSuccess;
00097 }
00098 
00099     GHOST_TSuccess 
00100 GHOST_DisplayManagerX11::
00101 getDisplaySetting(
00102     GHOST_TUns8 display,
00103     GHOST_TInt32 index,
00104     GHOST_DisplaySetting& setting
00105 ) const {
00106 
00107 #ifdef WITH_X11_XF86VMODE
00108     int majorVersion, minorVersion;
00109     XF86VidModeModeInfo **vidmodes;
00110     Display *dpy = m_system->getXDisplay();
00111     int numSettings;
00112 
00113     GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
00114 
00115     if (dpy == NULL)
00116         return GHOST_kFailure;
00117 
00118     majorVersion = minorVersion = 0;
00119     if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
00120         fprintf(stderr, "Error: XF86VidMode extension missing!\n");
00121         return GHOST_kFailure;
00122     }
00123 
00124     /* The X11 man page says vidmodes needs to be freed, but doing so causes a
00125      * segfault. - z0r */
00126     XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes);
00127     GHOST_ASSERT(index < numSettings, "Requested setting outside of valid range.\n");
00128 
00129     setting.xPixels = vidmodes[index]->hdisplay;
00130     setting.yPixels = vidmodes[index]->vdisplay;
00131     setting.bpp = DefaultDepth(dpy,DefaultScreen(dpy));
00132 
00133 #else
00134     GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");    
00135     GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); 
00136     
00137     Display * x_display = m_system->getXDisplay();
00138 
00139     if (x_display == NULL) {
00140         return GHOST_kFailure;
00141     }
00142 
00143     setting.xPixels  = DisplayWidth(x_display, DefaultScreen(x_display));
00144     setting.yPixels = DisplayHeight(x_display, DefaultScreen(x_display));
00145     setting.bpp = DefaultDepth(x_display,DefaultScreen(x_display));
00146 #endif
00147 
00148     // Don't think it's possible to get this value from X!
00149     // So let's guess!!
00150     setting.frequency = 60;
00151 
00152     return GHOST_kSuccess;
00153 }
00154     
00155     GHOST_TSuccess 
00156 GHOST_DisplayManagerX11::
00157 getCurrentDisplaySetting(
00158     GHOST_TUns8 display,
00159     GHOST_DisplaySetting& setting
00160 ) const {
00161     /* According to the xf86vidmodegetallmodelines man page,
00162      * "The first element of the array corresponds to the current video mode."
00163      */
00164     return getDisplaySetting(display,GHOST_TInt32(0),setting);
00165 }
00166 
00167 
00168     GHOST_TSuccess 
00169 GHOST_DisplayManagerX11::
00170 setCurrentDisplaySetting(
00171     GHOST_TUns8 display,
00172     const GHOST_DisplaySetting& setting
00173 ){
00174 #ifdef WITH_X11_XF86VMODE
00175     //
00176     // Mode switching code ported from Quake 2:
00177     // ftp://ftp.idsoftware.com/idstuff/source/q2source-3.21.zip
00178     // See linux/gl_glx.c:GLimp_SetMode
00179     //
00180     int majorVersion, minorVersion;
00181     XF86VidModeModeInfo **vidmodes;
00182     Display *dpy = m_system->getXDisplay();
00183     int scrnum, num_vidmodes;
00184     int best_fit, best_dist, dist, x, y;
00185 
00186     if (dpy == NULL)
00187         return GHOST_kFailure;
00188 
00189     scrnum = DefaultScreen(dpy);
00190 
00191     // Get video mode list
00192     majorVersion = minorVersion = 0;
00193     if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
00194         fprintf(stderr, "Error: XF86VidMode extension missing!\n");
00195         return GHOST_kFailure;
00196     }
00197 #  ifdef _DEBUG
00198     printf("Using XFree86-VidModeExtension Version %d.%d\n",
00199             majorVersion, minorVersion);
00200 #  endif
00201 
00202     /* The X11 man page says vidmodes needs to be freed, but doing so causes a
00203      * segfault. - z0r */
00204     XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
00205 
00206     best_dist = 9999999;
00207     best_fit = -1;
00208 
00209     for (int i = 0; i < num_vidmodes; i++) {
00210         if (setting.xPixels > vidmodes[i]->hdisplay ||
00211             setting.yPixels > vidmodes[i]->vdisplay)
00212             continue;
00213 
00214         x = setting.xPixels - vidmodes[i]->hdisplay;
00215         y = setting.yPixels - vidmodes[i]->vdisplay;
00216         dist = (x * x) + (y * y);
00217         if (dist < best_dist) {
00218             best_dist = dist;
00219             best_fit = i;
00220         }
00221     }
00222 
00223     if (best_fit != -1) {
00224 #  ifdef _DEBUG
00225         int actualWidth, actualHeight;
00226         actualWidth = vidmodes[best_fit]->hdisplay;
00227         actualHeight = vidmodes[best_fit]->vdisplay;
00228         printf("Switching to video mode %dx%d\n",
00229                 actualWidth, actualHeight);
00230 #  endif
00231 
00232         // change to the mode
00233         XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
00234 
00235         // Move the viewport to top left
00236         XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
00237     } else
00238         return GHOST_kFailure;
00239 
00240     XFlush(dpy);
00241     return GHOST_kSuccess;
00242 
00243 #else
00244     // Just pretend the request was successful.
00245     return GHOST_kSuccess;
00246 #endif
00247 }
00248 
00249 
00250 
00251