svn merge ^/trunk/blender -r43062:43085
[blender.git] / intern / ghost / intern / GHOST_DisplayManagerX11.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Video mode switching
24  * Copyright (C) 1997-2001 Id Software, Inc.
25  * Ported from Quake 2 by Alex Fraser <alex@phatcore.com>
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file ghost/intern/GHOST_DisplayManagerX11.cpp
31  *  \ingroup GHOST
32  */
33
34 #ifdef WITH_X11_XF86VMODE
35 #  include <X11/Xlib.h>
36 #  include <X11/extensions/xf86vmode.h>
37 #endif
38
39 #include "GHOST_DisplayManagerX11.h"
40 #include "GHOST_SystemX11.h"
41
42
43
44 GHOST_DisplayManagerX11::
45 GHOST_DisplayManagerX11(
46         GHOST_SystemX11 *system
47 ) :
48         GHOST_DisplayManager(),
49         m_system(system)
50 {
51         //nothing to do.
52 }
53
54         GHOST_TSuccess 
55 GHOST_DisplayManagerX11::
56 getNumDisplays(
57         GHOST_TUns8& numDisplays
58 ) const{        
59         numDisplays =  m_system->getNumDisplays();
60         return GHOST_kSuccess;
61 }
62
63
64         GHOST_TSuccess 
65 GHOST_DisplayManagerX11::
66 getNumDisplaySettings(
67         GHOST_TUns8 display,
68         GHOST_TInt32& numSettings
69 ) const{
70         
71         // We only have one X11 setting at the moment.
72         GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");    
73         numSettings = GHOST_TInt32(1);
74         return GHOST_kSuccess;
75 }
76
77         GHOST_TSuccess 
78 GHOST_DisplayManagerX11::
79 getDisplaySetting(
80         GHOST_TUns8 display,
81         GHOST_TInt32 index,
82         GHOST_DisplaySetting& setting
83 ) const {
84         
85         GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");    
86         GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); 
87         
88         Display * x_display = m_system->getXDisplay();
89
90         if (x_display == NULL) {
91                 return GHOST_kFailure;
92         }
93
94         setting.xPixels  = DisplayWidth(x_display, DefaultScreen(x_display));
95         setting.yPixels = DisplayHeight(x_display, DefaultScreen(x_display));
96         setting.bpp = DefaultDepth(x_display,DefaultScreen(x_display));
97
98         // Don't think it's possible to get this value from X!
99         // So let's guess!!
100         setting.frequency = 60;
101
102         return GHOST_kSuccess;
103 }
104         
105         GHOST_TSuccess 
106 GHOST_DisplayManagerX11::
107 getCurrentDisplaySetting(
108         GHOST_TUns8 display,
109         GHOST_DisplaySetting& setting
110 ) const {
111         return getDisplaySetting(display,GHOST_TInt32(0),setting);
112 }
113
114
115         GHOST_TSuccess 
116 GHOST_DisplayManagerX11::
117 setCurrentDisplaySetting(
118         GHOST_TUns8 display,
119         const GHOST_DisplaySetting& setting
120 ){
121 #ifdef WITH_X11_XF86VMODE
122         //
123         // Mode switching code ported from Quake 2:
124         // ftp://ftp.idsoftware.com/idstuff/source/q2source-3.21.zip
125         // See linux/gl_glx.c:GLimp_SetMode
126         //
127         int majorVersion, minorVersion;
128         XF86VidModeModeInfo **vidmodes;
129         Display *dpy = m_system->getXDisplay();
130         int scrnum, num_vidmodes;
131         int best_fit, best_dist, dist, x, y;
132
133         scrnum = DefaultScreen(dpy);
134
135         // Get video mode list
136         majorVersion = minorVersion = 0;
137         if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
138                 fprintf(stderr, "Error: XF86VidMode extension missing!\n");
139                 return GHOST_kFailure;
140         }
141 #  ifdef _DEBUG
142         printf("Using XFree86-VidModeExtension Version %d.%d\n",
143                         majorVersion, minorVersion);
144 #  endif
145
146         XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
147
148         best_dist = 9999999;
149         best_fit = -1;
150
151         for (int i = 0; i < num_vidmodes; i++) {
152                 if (setting.xPixels > vidmodes[i]->hdisplay ||
153                         setting.yPixels > vidmodes[i]->vdisplay)
154                         continue;
155
156                 x = setting.xPixels - vidmodes[i]->hdisplay;
157                 y = setting.yPixels - vidmodes[i]->vdisplay;
158                 dist = (x * x) + (y * y);
159                 if (dist < best_dist) {
160                         best_dist = dist;
161                         best_fit = i;
162                 }
163         }
164
165         if (best_fit != -1) {
166 #  ifdef _DEBUG
167                 int actualWidth, actualHeight;
168                 actualWidth = vidmodes[best_fit]->hdisplay;
169                 actualHeight = vidmodes[best_fit]->vdisplay;
170                 printf("Switching to video mode %dx%d\n",
171                                 actualWidth, actualHeight);
172 #  endif
173
174                 // change to the mode
175                 XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
176
177                 // Move the viewport to top left
178                 XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
179         } else
180                 return GHOST_kFailure;
181
182         XFlush(dpy);
183         return GHOST_kSuccess;
184
185 #else
186         // Just pretend the request was successful.
187         return GHOST_kSuccess;
188 #endif
189 }
190
191
192
193