style cleanup: ghost/x11
[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(GHOST_TUns8& numDisplays) const
57 {
58         numDisplays =  m_system->getNumDisplays();
59         return GHOST_kSuccess;
60 }
61
62
63 GHOST_TSuccess
64 GHOST_DisplayManagerX11::
65 getNumDisplaySettings(
66                 GHOST_TUns8 display,
67                 GHOST_TInt32& numSettings) const
68 {
69 #ifdef WITH_X11_XF86VMODE
70         int majorVersion, minorVersion;
71         XF86VidModeModeInfo **vidmodes;
72         Display *dpy = m_system->getXDisplay();
73
74         GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
75
76         if (dpy == NULL)
77                 return GHOST_kFailure;
78
79         majorVersion = minorVersion = 0;
80         if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
81                 fprintf(stderr, "Error: XF86VidMode extension missing!\n");
82                 return GHOST_kFailure;
83         }
84
85         /* The X11 man page says vidmodes needs to be freed, but doing so causes a
86          * segfault. - z0r */
87         XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes);
88
89 #else
90         // We only have one X11 setting at the moment.
91         GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");    
92         numSettings = GHOST_TInt32(1);
93 #endif
94
95         return GHOST_kSuccess;
96 }
97
98 GHOST_TSuccess
99 GHOST_DisplayManagerX11::
100 getDisplaySetting(
101                 GHOST_TUns8 display,
102                 GHOST_TInt32 index,
103                 GHOST_DisplaySetting& setting) const
104 {
105
106 #ifdef WITH_X11_XF86VMODE
107         int majorVersion, minorVersion;
108         XF86VidModeModeInfo **vidmodes;
109         Display *dpy = m_system->getXDisplay();
110         int numSettings;
111
112         GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
113
114         if (dpy == NULL)
115                 return GHOST_kFailure;
116
117         majorVersion = minorVersion = 0;
118         if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
119                 fprintf(stderr, "Error: XF86VidMode extension missing!\n");
120                 return GHOST_kFailure;
121         }
122
123         /* The X11 man page says vidmodes needs to be freed, but doing so causes a
124          * segfault. - z0r */
125         XF86VidModeGetAllModeLines(dpy, DefaultScreen(dpy), &numSettings, &vidmodes);
126         GHOST_ASSERT(index < numSettings, "Requested setting outside of valid range.\n");
127
128         setting.xPixels = vidmodes[index]->hdisplay;
129         setting.yPixels = vidmodes[index]->vdisplay;
130         setting.bpp = DefaultDepth(dpy, DefaultScreen(dpy));
131
132 #else
133         GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");    
134         GHOST_ASSERT(index < 1, "Requested setting outside of valid range.\n"); 
135         
136         Display *x_display = m_system->getXDisplay();
137
138         if (x_display == NULL) {
139                 return GHOST_kFailure;
140         }
141
142         setting.xPixels  = DisplayWidth(x_display, DefaultScreen(x_display));
143         setting.yPixels = DisplayHeight(x_display, DefaultScreen(x_display));
144         setting.bpp = DefaultDepth(x_display, DefaultScreen(x_display));
145 #endif
146
147         // Don't think it's possible to get this value from X!
148         // So let's guess!!
149         setting.frequency = 60;
150
151         return GHOST_kSuccess;
152 }
153         
154 GHOST_TSuccess
155 GHOST_DisplayManagerX11::
156 getCurrentDisplaySetting(
157                 GHOST_TUns8 display,
158                 GHOST_DisplaySetting& setting) const
159 {
160         /* According to the xf86vidmodegetallmodelines man page,
161          * "The first element of the array corresponds to the current video mode."
162          */
163         return getDisplaySetting(display, GHOST_TInt32(0), setting);
164 }
165
166
167 GHOST_TSuccess
168 GHOST_DisplayManagerX11::
169 setCurrentDisplaySetting(
170                 GHOST_TUns8 display,
171                 const GHOST_DisplaySetting& setting)
172 {
173 #ifdef WITH_X11_XF86VMODE
174         //
175         // Mode switching code ported from Quake 2:
176         // ftp://ftp.idsoftware.com/idstuff/source/q2source-3.21.zip
177         // See linux/gl_glx.c:GLimp_SetMode
178         //
179         int majorVersion, minorVersion;
180         XF86VidModeModeInfo **vidmodes;
181         Display *dpy = m_system->getXDisplay();
182         int scrnum, num_vidmodes;
183         int best_fit, best_dist, dist, x, y;
184
185         if (dpy == NULL)
186                 return GHOST_kFailure;
187
188         scrnum = DefaultScreen(dpy);
189
190         // Get video mode list
191         majorVersion = minorVersion = 0;
192         if (!XF86VidModeQueryVersion(dpy, &majorVersion, &minorVersion)) {
193                 fprintf(stderr, "Error: XF86VidMode extension missing!\n");
194                 return GHOST_kFailure;
195         }
196 #  ifdef _DEBUG
197         printf("Using XFree86-VidModeExtension Version %d.%d\n",
198                majorVersion, minorVersion);
199 #  endif
200
201         /* The X11 man page says vidmodes needs to be freed, but doing so causes a
202          * segfault. - z0r */
203         XF86VidModeGetAllModeLines(dpy, scrnum, &num_vidmodes, &vidmodes);
204
205         best_dist = 9999999;
206         best_fit = -1;
207
208         for (int i = 0; i < num_vidmodes; i++) {
209                 if (setting.xPixels > vidmodes[i]->hdisplay ||
210                     setting.yPixels > vidmodes[i]->vdisplay)
211                         continue;
212
213                 x = setting.xPixels - vidmodes[i]->hdisplay;
214                 y = setting.yPixels - vidmodes[i]->vdisplay;
215                 dist = (x * x) + (y * y);
216                 if (dist < best_dist) {
217                         best_dist = dist;
218                         best_fit = i;
219                 }
220         }
221
222         if (best_fit != -1) {
223 #  ifdef _DEBUG
224                 int actualWidth, actualHeight;
225                 actualWidth = vidmodes[best_fit]->hdisplay;
226                 actualHeight = vidmodes[best_fit]->vdisplay;
227                 printf("Switching to video mode %dx%d\n",
228                        actualWidth, actualHeight);
229 #  endif
230
231                 // change to the mode
232                 XF86VidModeSwitchToMode(dpy, scrnum, vidmodes[best_fit]);
233
234                 // Move the viewport to top left
235                 XF86VidModeSetViewPort(dpy, scrnum, 0, 0);
236         }
237         else
238                 return GHOST_kFailure;
239
240         XFlush(dpy);
241         return GHOST_kSuccess;
242
243 #else
244         // Just pretend the request was successful.
245         return GHOST_kSuccess;
246 #endif
247 }
248
249
250
251