slouken@1950
|
1 |
/*
|
slouken@1950
|
2 |
SDL - Simple DirectMedia Layer
|
slouken@2859
|
3 |
Copyright (C) 1997-2009 Sam Lantinga
|
slouken@1950
|
4 |
|
slouken@1950
|
5 |
This library is free software; you can redistribute it and/or
|
slouken@1950
|
6 |
modify it under the terms of the GNU Lesser General Public
|
slouken@1950
|
7 |
License as published by the Free Software Foundation; either
|
slouken@1950
|
8 |
version 2.1 of the License, or (at your option) any later version.
|
slouken@1950
|
9 |
|
slouken@1950
|
10 |
This library is distributed in the hope that it will be useful,
|
slouken@1950
|
11 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
slouken@1950
|
12 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
slouken@1950
|
13 |
Lesser General Public License for more details.
|
slouken@1950
|
14 |
|
slouken@1950
|
15 |
You should have received a copy of the GNU Lesser General Public
|
slouken@1950
|
16 |
License along with this library; if not, write to the Free Software
|
slouken@1950
|
17 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
slouken@1950
|
18 |
|
slouken@1950
|
19 |
Sam Lantinga
|
slouken@1950
|
20 |
slouken@libsdl.org
|
slouken@1950
|
21 |
*/
|
slouken@1950
|
22 |
#include "SDL_config.h"
|
slouken@1950
|
23 |
|
slouken@1950
|
24 |
#include "SDL_x11video.h"
|
slouken@1950
|
25 |
|
slouken@2873
|
26 |
//#define X11MODES_DEBUG
|
slouken@2873
|
27 |
#undef SDL_VIDEO_DRIVER_X11_XINERAMA
|
slouken@2873
|
28 |
#undef SDL_VIDEO_DRIVER_X11_XRANDR
|
slouken@2873
|
29 |
#undef SDL_VIDEO_DRIVER_X11_VIDMODE
|
slouken@1950
|
30 |
|
slouken@1950
|
31 |
static int
|
slouken@1950
|
32 |
get_visualinfo(Display * display, int screen, XVisualInfo * vinfo)
|
slouken@1950
|
33 |
{
|
slouken@1950
|
34 |
const char *visual_id = SDL_getenv("SDL_VIDEO_X11_VISUALID");
|
slouken@1950
|
35 |
int depth;
|
slouken@1950
|
36 |
|
slouken@1950
|
37 |
/* Look for an exact visual, if requested */
|
slouken@1950
|
38 |
if (visual_id) {
|
slouken@1950
|
39 |
XVisualInfo *vi, template;
|
slouken@1950
|
40 |
int nvis;
|
slouken@1950
|
41 |
|
slouken@1950
|
42 |
SDL_zero(template);
|
slouken@1950
|
43 |
template.visualid = SDL_strtol(visual_id, NULL, 0);
|
slouken@1950
|
44 |
vi = XGetVisualInfo(display, VisualIDMask, &template, &nvis);
|
slouken@1950
|
45 |
if (vi) {
|
slouken@1950
|
46 |
*vinfo = *vi;
|
slouken@1950
|
47 |
XFree(vi);
|
slouken@1950
|
48 |
return 0;
|
slouken@1950
|
49 |
}
|
slouken@1950
|
50 |
}
|
slouken@1950
|
51 |
|
slouken@1950
|
52 |
depth = DefaultDepth(display, screen);
|
slouken@2963
|
53 |
if ((X11_UseDirectColorVisuals() &&
|
slouken@1950
|
54 |
XMatchVisualInfo(display, screen, depth, DirectColor, vinfo)) ||
|
slouken@1950
|
55 |
XMatchVisualInfo(display, screen, depth, TrueColor, vinfo) ||
|
slouken@1950
|
56 |
XMatchVisualInfo(display, screen, depth, PseudoColor, vinfo) ||
|
slouken@1950
|
57 |
XMatchVisualInfo(display, screen, depth, StaticColor, vinfo)) {
|
slouken@1950
|
58 |
return 0;
|
slouken@1950
|
59 |
}
|
slouken@1950
|
60 |
return -1;
|
slouken@1950
|
61 |
}
|
slouken@1950
|
62 |
|
slouken@2870
|
63 |
static Uint32
|
slouken@2874
|
64 |
X11_GetPixelFormatFromVisualInfo(Display * display, XVisualInfo * vinfo)
|
slouken@2870
|
65 |
{
|
slouken@2870
|
66 |
if (vinfo->class == DirectColor || vinfo->class == TrueColor) {
|
slouken@2870
|
67 |
int bpp;
|
slouken@2870
|
68 |
Uint32 Rmask, Gmask, Bmask, Amask;
|
slouken@2870
|
69 |
|
slouken@2870
|
70 |
Rmask = vinfo->visual->red_mask;
|
slouken@2870
|
71 |
Gmask = vinfo->visual->green_mask;
|
slouken@2870
|
72 |
Bmask = vinfo->visual->blue_mask;
|
slouken@2870
|
73 |
if (vinfo->depth == 32) {
|
slouken@2870
|
74 |
Amask = (0xFFFFFFFF & ~(Rmask | Gmask | Bmask));
|
slouken@2870
|
75 |
} else {
|
slouken@2870
|
76 |
Amask = 0;
|
slouken@2870
|
77 |
}
|
slouken@2870
|
78 |
|
slouken@2870
|
79 |
bpp = vinfo->depth;
|
slouken@2870
|
80 |
if (bpp == 24) {
|
slouken@2870
|
81 |
int i, n;
|
slouken@2870
|
82 |
XPixmapFormatValues *p = XListPixmapFormats(display, &n);
|
slouken@2870
|
83 |
if (p) {
|
slouken@2870
|
84 |
for (i = 0; i < n; ++i) {
|
slouken@2870
|
85 |
if (p[i].depth == 24) {
|
slouken@2870
|
86 |
bpp = p[i].bits_per_pixel;
|
slouken@2870
|
87 |
break;
|
slouken@2870
|
88 |
}
|
slouken@2870
|
89 |
}
|
slouken@2870
|
90 |
XFree(p);
|
slouken@2870
|
91 |
}
|
slouken@2870
|
92 |
}
|
slouken@2870
|
93 |
|
slouken@2870
|
94 |
return SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
|
slouken@2870
|
95 |
}
|
slouken@2870
|
96 |
|
slouken@2870
|
97 |
if (vinfo->class == PseudoColor || vinfo->class == StaticColor) {
|
slouken@2870
|
98 |
switch (vinfo->depth) {
|
slouken@2870
|
99 |
case 8:
|
slouken@2870
|
100 |
return SDL_PIXELTYPE_INDEX8;
|
slouken@2870
|
101 |
case 4:
|
slouken@2870
|
102 |
if (BitmapBitOrder(display) == LSBFirst) {
|
slouken@2870
|
103 |
return SDL_PIXELFORMAT_INDEX4LSB;
|
slouken@2870
|
104 |
} else {
|
slouken@2870
|
105 |
return SDL_PIXELFORMAT_INDEX4MSB;
|
slouken@2870
|
106 |
}
|
slouken@2870
|
107 |
break;
|
slouken@2870
|
108 |
case 1:
|
slouken@2870
|
109 |
if (BitmapBitOrder(display) == LSBFirst) {
|
slouken@2870
|
110 |
return SDL_PIXELFORMAT_INDEX1LSB;
|
slouken@2870
|
111 |
} else {
|
slouken@2870
|
112 |
return SDL_PIXELFORMAT_INDEX1MSB;
|
slouken@2870
|
113 |
}
|
slouken@2870
|
114 |
break;
|
slouken@2870
|
115 |
}
|
slouken@2870
|
116 |
}
|
slouken@2870
|
117 |
|
slouken@2870
|
118 |
return SDL_PIXELFORMAT_UNKNOWN;
|
slouken@2870
|
119 |
}
|
slouken@2870
|
120 |
|
slouken@3521
|
121 |
int
|
slouken@1950
|
122 |
X11_InitModes(_THIS)
|
slouken@1950
|
123 |
{
|
slouken@1950
|
124 |
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
slouken@1950
|
125 |
int screen;
|
slouken@1950
|
126 |
|
slouken@1950
|
127 |
for (screen = 0; screen < ScreenCount(data->display); ++screen) {
|
slouken@1950
|
128 |
XVisualInfo vinfo;
|
slouken@1950
|
129 |
SDL_VideoDisplay display;
|
slouken@1950
|
130 |
SDL_DisplayData *displaydata;
|
slouken@1950
|
131 |
SDL_DisplayMode mode;
|
slouken@2916
|
132 |
XPixmapFormatValues *pixmapFormats;
|
slouken@2916
|
133 |
int i, n;
|
slouken@1950
|
134 |
|
slouken@1950
|
135 |
if (get_visualinfo(data->display, screen, &vinfo) < 0) {
|
slouken@1950
|
136 |
continue;
|
slouken@1950
|
137 |
}
|
slouken@1950
|
138 |
|
slouken@2870
|
139 |
mode.format = X11_GetPixelFormatFromVisualInfo(data->display, &vinfo);
|
slouken@1950
|
140 |
mode.w = DisplayWidth(data->display, screen);
|
slouken@1950
|
141 |
mode.h = DisplayHeight(data->display, screen);
|
slouken@1950
|
142 |
mode.refresh_rate = 0;
|
slouken@1950
|
143 |
mode.driverdata = NULL;
|
slouken@1950
|
144 |
|
slouken@1950
|
145 |
displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
|
slouken@1950
|
146 |
if (!displaydata) {
|
slouken@1950
|
147 |
continue;
|
slouken@1950
|
148 |
}
|
slouken@1950
|
149 |
displaydata->screen = screen;
|
slouken@1950
|
150 |
displaydata->visual = vinfo.visual;
|
slouken@1951
|
151 |
displaydata->depth = vinfo.depth;
|
slouken@1950
|
152 |
|
slouken@2920
|
153 |
displaydata->scanline_pad = SDL_BYTESPERPIXEL(mode.format) * 8;
|
slouken@2916
|
154 |
pixmapFormats = XListPixmapFormats(data->display, &n);
|
slouken@2916
|
155 |
if (pixmapFormats) {
|
slouken@2916
|
156 |
for (i = 0; i < n; ++i) {
|
slouken@2916
|
157 |
if (pixmapFormats[i].depth == displaydata->depth) {
|
slouken@2916
|
158 |
displaydata->scanline_pad = pixmapFormats[i].scanline_pad;
|
slouken@2916
|
159 |
break;
|
slouken@2916
|
160 |
}
|
slouken@2916
|
161 |
}
|
slouken@2916
|
162 |
XFree(pixmapFormats);
|
slouken@2916
|
163 |
}
|
slouken@2916
|
164 |
|
slouken@1950
|
165 |
SDL_zero(display);
|
slouken@1950
|
166 |
display.desktop_mode = mode;
|
slouken@1950
|
167 |
display.current_mode = mode;
|
slouken@1950
|
168 |
display.driverdata = displaydata;
|
slouken@1950
|
169 |
SDL_AddVideoDisplay(&display);
|
slouken@1950
|
170 |
}
|
slouken@3521
|
171 |
if (_this->num_displays == 0) {
|
slouken@3521
|
172 |
SDL_SetError("No available displays");
|
slouken@3521
|
173 |
return -1;
|
slouken@3521
|
174 |
}
|
slouken@3521
|
175 |
return 0;
|
slouken@1950
|
176 |
}
|
slouken@1950
|
177 |
|
slouken@2873
|
178 |
/* Global for the error handler */
|
slouken@2873
|
179 |
int vm_event, vm_error = -1;
|
slouken@2873
|
180 |
|
slouken@2873
|
181 |
#if SDL_VIDEO_DRIVER_X11_XINERAMA
|
slouken@2873
|
182 |
static SDL_bool
|
slouken@2874
|
183 |
CheckXinerama(Display * display, int *major, int *minor)
|
slouken@2873
|
184 |
{
|
slouken@2873
|
185 |
const char *env;
|
slouken@2873
|
186 |
|
slouken@2873
|
187 |
/* Default the extension not available */
|
slouken@2873
|
188 |
*major = *minor = 0;
|
slouken@2873
|
189 |
|
slouken@2873
|
190 |
/* Allow environment override */
|
slouken@2873
|
191 |
env = getenv("SDL_VIDEO_X11_XINERAMA");
|
slouken@2873
|
192 |
if (env && !SDL_atoi(env)) {
|
slouken@2873
|
193 |
return SDL_FALSE;
|
slouken@2873
|
194 |
}
|
slouken@2873
|
195 |
|
slouken@2873
|
196 |
/* Query the extension version */
|
slouken@2874
|
197 |
if (!SDL_NAME(XineramaQueryExtension) (display, major, minor) ||
|
slouken@2874
|
198 |
!SDL_NAME(XineramaIsActive) (display)) {
|
slouken@2873
|
199 |
return SDL_FALSE;
|
slouken@2873
|
200 |
}
|
slouken@2873
|
201 |
return SDL_TRUE;
|
slouken@2873
|
202 |
}
|
slouken@2873
|
203 |
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
|
slouken@2873
|
204 |
|
slouken@2873
|
205 |
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
slouken@2873
|
206 |
static SDL_bool
|
slouken@2874
|
207 |
CheckXRandR(Display * display, int *major, int *minor)
|
slouken@2873
|
208 |
{
|
slouken@2873
|
209 |
const char *env;
|
slouken@2873
|
210 |
|
slouken@2873
|
211 |
/* Default the extension not available */
|
slouken@2873
|
212 |
*major = *minor = 0;
|
slouken@2873
|
213 |
|
slouken@2873
|
214 |
/* Allow environment override */
|
slouken@2873
|
215 |
env = getenv("SDL_VIDEO_X11_XRANDR");
|
slouken@2873
|
216 |
if (env && !SDL_atoi(env)) {
|
slouken@2873
|
217 |
return SDL_FALSE;
|
slouken@2873
|
218 |
}
|
slouken@2873
|
219 |
|
slouken@2873
|
220 |
if (!SDL_X11_HAVE_XRANDR) {
|
slouken@2873
|
221 |
return SDL_FALSE;
|
slouken@2873
|
222 |
}
|
slouken@2873
|
223 |
|
slouken@2873
|
224 |
/* Query the extension version */
|
slouken@2873
|
225 |
if (!XRRQueryVersion(display, major, minor)) {
|
slouken@2873
|
226 |
return SDL_FALSE;
|
slouken@2873
|
227 |
}
|
slouken@2873
|
228 |
return SDL_TRUE;
|
slouken@2873
|
229 |
}
|
slouken@2873
|
230 |
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
|
slouken@2873
|
231 |
|
slouken@2873
|
232 |
#if SDL_VIDEO_DRIVER_X11_VIDMODE
|
slouken@2873
|
233 |
static SDL_bool
|
slouken@2874
|
234 |
CheckVidMode(Display * display, int *major, int *minor)
|
slouken@2873
|
235 |
{
|
slouken@2873
|
236 |
const char *env;
|
slouken@2873
|
237 |
|
slouken@2873
|
238 |
/* Default the extension not available */
|
slouken@2873
|
239 |
*major = *minor = 0;
|
slouken@2873
|
240 |
|
slouken@2873
|
241 |
/* Allow environment override */
|
slouken@2873
|
242 |
env = getenv("SDL_VIDEO_X11_VIDMODE");
|
slouken@2873
|
243 |
if (env && !SDL_atoi(env)) {
|
slouken@2873
|
244 |
return SDL_FALSE;
|
slouken@2873
|
245 |
}
|
slouken@2874
|
246 |
|
slouken@2873
|
247 |
/* Query the extension version */
|
slouken@2873
|
248 |
vm_error = -1;
|
slouken@2874
|
249 |
if (!SDL_NAME(XF86VidModeQueryExtension) (display, &vm_event, &vm_error)
|
slouken@2874
|
250 |
|| !SDL_NAME(XF86VidModeQueryVersion) (display, major, minor)) {
|
slouken@2873
|
251 |
return SDL_FALSE;
|
slouken@2873
|
252 |
}
|
slouken@2873
|
253 |
return SDL_TRUE;
|
slouken@2873
|
254 |
}
|
slouken@2873
|
255 |
|
slouken@2874
|
256 |
Bool SDL_NAME(XF86VidModeGetModeInfo) (Display * dpy, int scr,
|
slouken@2874
|
257 |
SDL_NAME(XF86VidModeModeInfo) * info)
|
slouken@2873
|
258 |
{
|
slouken@2873
|
259 |
Bool retval;
|
slouken@2873
|
260 |
int dotclock;
|
slouken@2873
|
261 |
SDL_NAME(XF86VidModeModeLine) l;
|
slouken@2873
|
262 |
SDL_zerop(info);
|
slouken@2873
|
263 |
SDL_zero(l);
|
slouken@2874
|
264 |
retval = SDL_NAME(XF86VidModeGetModeLine) (dpy, scr, &dotclock, &l);
|
slouken@2873
|
265 |
info->dotclock = dotclock;
|
slouken@2873
|
266 |
info->hdisplay = l.hdisplay;
|
slouken@2873
|
267 |
info->hsyncstart = l.hsyncstart;
|
slouken@2873
|
268 |
info->hsyncend = l.hsyncend;
|
slouken@2873
|
269 |
info->htotal = l.htotal;
|
slouken@2873
|
270 |
info->hskew = l.hskew;
|
slouken@2873
|
271 |
info->vdisplay = l.vdisplay;
|
slouken@2873
|
272 |
info->vsyncstart = l.vsyncstart;
|
slouken@2873
|
273 |
info->vsyncend = l.vsyncend;
|
slouken@2873
|
274 |
info->vtotal = l.vtotal;
|
slouken@2873
|
275 |
info->flags = l.flags;
|
slouken@2873
|
276 |
info->privsize = l.privsize;
|
slouken@2873
|
277 |
info->private = l.private;
|
slouken@2873
|
278 |
return retval;
|
slouken@2873
|
279 |
}
|
slouken@2873
|
280 |
|
slouken@2873
|
281 |
static int
|
slouken@2874
|
282 |
calculate_rate(SDL_NAME(XF86VidModeModeInfo) * info)
|
slouken@2873
|
283 |
{
|
slouken@2874
|
284 |
return (info->htotal
|
slouken@2874
|
285 |
&& info->vtotal) ? (1000 * info->dotclock / (info->htotal *
|
slouken@2874
|
286 |
info->vtotal)) : 0;
|
slouken@2873
|
287 |
}
|
slouken@2873
|
288 |
|
slouken@2873
|
289 |
static void
|
slouken@2874
|
290 |
save_mode(Display * display, SDL_DisplayData * data)
|
slouken@2873
|
291 |
{
|
slouken@2874
|
292 |
SDL_NAME(XF86VidModeGetModeInfo) (display, data->screen,
|
slouken@2874
|
293 |
&data->saved_mode);
|
slouken@2874
|
294 |
SDL_NAME(XF86VidModeGetViewPort) (display, data->screen,
|
slouken@2874
|
295 |
&data->saved_view.x,
|
slouken@2874
|
296 |
&data->saved_view.y);
|
slouken@2873
|
297 |
}
|
slouken@2873
|
298 |
|
slouken@2873
|
299 |
static void
|
slouken@2874
|
300 |
restore_mode(Display * display, SDL_DisplayData * data)
|
slouken@2873
|
301 |
{
|
slouken@2873
|
302 |
SDL_NAME(XF86VidModeModeInfo) mode;
|
slouken@2873
|
303 |
|
slouken@2874
|
304 |
if (SDL_NAME(XF86VidModeGetModeInfo) (display, data->screen, &mode)) {
|
slouken@2873
|
305 |
if (SDL_memcmp(&mode, &data->saved_mode, sizeof(mode)) != 0) {
|
slouken@2874
|
306 |
SDL_NAME(XF86VidModeSwitchToMode) (display, data->screen,
|
slouken@2874
|
307 |
&data->saved_mode);
|
slouken@2873
|
308 |
}
|
slouken@2873
|
309 |
}
|
slouken@2873
|
310 |
if ((data->saved_view.x != 0) || (data->saved_view.y != 0)) {
|
slouken@2874
|
311 |
SDL_NAME(XF86VidModeSetViewPort) (display, data->screen,
|
slouken@2874
|
312 |
data->saved_view.x,
|
slouken@2874
|
313 |
data->saved_view.y);
|
slouken@2873
|
314 |
}
|
slouken@2873
|
315 |
}
|
slouken@2873
|
316 |
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
|
slouken@2873
|
317 |
|
slouken@1950
|
318 |
void
|
slouken@3500
|
319 |
X11_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display)
|
slouken@1950
|
320 |
{
|
slouken@2870
|
321 |
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
|
slouken@3500
|
322 |
SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
|
slouken@2873
|
323 |
#if SDL_VIDEO_DRIVER_X11_XINERAMA
|
slouken@2873
|
324 |
int xinerama_major, xinerama_minor;
|
slouken@2873
|
325 |
int screens;
|
slouken@2874
|
326 |
SDL_NAME(XineramaScreenInfo) * xinerama;
|
slouken@2873
|
327 |
#endif
|
slouken@2873
|
328 |
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
slouken@2873
|
329 |
int xrandr_major, xrandr_minor;
|
slouken@2873
|
330 |
int nsizes, nrates;
|
slouken@2873
|
331 |
XRRScreenSize *sizes;
|
slouken@2873
|
332 |
short *rates;
|
slouken@2873
|
333 |
#endif
|
slouken@2873
|
334 |
#if SDL_VIDEO_DRIVER_X11_VIDMODE
|
slouken@2873
|
335 |
int vm_major, vm_minor;
|
slouken@2873
|
336 |
int nmodes;
|
slouken@2874
|
337 |
SDL_NAME(XF86VidModeModeInfo) ** modes;
|
slouken@2873
|
338 |
#endif
|
slouken@2873
|
339 |
int screen_w;
|
slouken@2873
|
340 |
int screen_h;
|
slouken@1950
|
341 |
SDL_DisplayMode mode;
|
slouken@2870
|
342 |
|
slouken@2873
|
343 |
/* Unfortunately X11 requires the window to be created with the correct
|
slouken@2873
|
344 |
* visual and depth ahead of time, but the SDL API allows you to create
|
slouken@2873
|
345 |
* a window before setting the fullscreen display mode. This means that
|
slouken@2873
|
346 |
* we have to use the same format for all windows and all display modes.
|
slouken@2873
|
347 |
* (or support recreating the window with a new visual behind the scenes)
|
slouken@2873
|
348 |
*/
|
slouken@3500
|
349 |
mode.format = sdl_display->current_mode.format;
|
slouken@2873
|
350 |
mode.driverdata = NULL;
|
slouken@2873
|
351 |
|
slouken@2873
|
352 |
data->use_xinerama = 0;
|
slouken@2873
|
353 |
data->use_xrandr = 0;
|
slouken@2873
|
354 |
data->use_vidmode = 0;
|
slouken@2873
|
355 |
screen_w = DisplayWidth(display, data->screen);
|
slouken@2873
|
356 |
screen_h = DisplayHeight(display, data->screen);
|
slouken@2873
|
357 |
|
slouken@2873
|
358 |
#if SDL_VIDEO_DRIVER_X11_XINERAMA
|
slouken@2873
|
359 |
/* Query Xinerama extention */
|
slouken@2873
|
360 |
if (CheckXinerama(display, &xinerama_major, &xinerama_minor)) {
|
slouken@2873
|
361 |
#ifdef X11MODES_DEBUG
|
slouken@2873
|
362 |
printf("X11 detected Xinerama:\n");
|
slouken@2873
|
363 |
#endif
|
slouken@2874
|
364 |
xinerama = SDL_NAME(XineramaQueryScreens) (display, &screens);
|
slouken@2873
|
365 |
if (xinerama) {
|
slouken@2873
|
366 |
int i;
|
slouken@2873
|
367 |
for (i = 0; i < screens; i++) {
|
slouken@2873
|
368 |
#ifdef X11MODES_DEBUG
|
slouken@2873
|
369 |
printf("xinerama %d: %dx%d+%d+%d\n",
|
slouken@2874
|
370 |
xinerama[i].screen_number,
|
slouken@2874
|
371 |
xinerama[i].width, xinerama[i].height,
|
slouken@2874
|
372 |
xinerama[i].x_org, xinerama[i].y_org);
|
slouken@2873
|
373 |
#endif
|
slouken@2873
|
374 |
if (xinerama[i].screen_number == data->screen) {
|
slouken@2874
|
375 |
data->use_xinerama =
|
slouken@2874
|
376 |
xinerama_major * 100 + xinerama_minor;
|
slouken@2873
|
377 |
data->xinerama_info = xinerama[i];
|
slouken@2873
|
378 |
}
|
slouken@2873
|
379 |
}
|
slouken@2873
|
380 |
XFree(xinerama);
|
slouken@2873
|
381 |
}
|
slouken@2873
|
382 |
|
slouken@2873
|
383 |
if (data->use_xinerama) {
|
slouken@2873
|
384 |
/* Add the full xinerama mode */
|
slouken@2873
|
385 |
if (screen_w > data->xinerama_info.width ||
|
slouken@2873
|
386 |
screen_h > data->xinerama_info.height) {
|
slouken@2873
|
387 |
mode.w = screen_w;
|
slouken@2873
|
388 |
mode.h = screen_h;
|
slouken@2873
|
389 |
mode.refresh_rate = 0;
|
slouken@3500
|
390 |
SDL_AddDisplayMode(sdl_display, &mode);
|
slouken@2873
|
391 |
}
|
slouken@2873
|
392 |
|
slouken@2873
|
393 |
/* Add the head xinerama mode */
|
slouken@2873
|
394 |
mode.w = data->xinerama_info.width;
|
slouken@2873
|
395 |
mode.h = data->xinerama_info.height;
|
slouken@2873
|
396 |
mode.refresh_rate = 0;
|
slouken@3500
|
397 |
SDL_AddDisplayMode(sdl_display, &mode);
|
slouken@2873
|
398 |
}
|
slouken@2873
|
399 |
}
|
slouken@2873
|
400 |
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
|
slouken@2873
|
401 |
|
slouken@2873
|
402 |
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
slouken@2873
|
403 |
/* XRandR */
|
slouken@2873
|
404 |
/* require at least XRandR v1.0 (arbitrary) */
|
slouken@2874
|
405 |
if (CheckXRandR(display, &xrandr_major, &xrandr_minor)
|
slouken@2874
|
406 |
&& xrandr_major >= 1) {
|
slouken@2873
|
407 |
#ifdef X11MODES_DEBUG
|
slouken@2873
|
408 |
fprintf(stderr, "XRANDR: XRRQueryVersion: V%d.%d\n",
|
slouken@2873
|
409 |
xrandr_major, xrandr_minor);
|
slouken@2873
|
410 |
#endif
|
slouken@2873
|
411 |
|
slouken@2873
|
412 |
/* save the screen configuration since we must reference it
|
slouken@2873
|
413 |
each time we toggle modes.
|
slouken@2874
|
414 |
*/
|
slouken@2874
|
415 |
data->screen_config =
|
slouken@2874
|
416 |
XRRGetScreenInfo(display, RootWindow(display, data->screen));
|
slouken@2873
|
417 |
|
slouken@2873
|
418 |
/* retrieve the list of resolution */
|
slouken@2873
|
419 |
sizes = XRRConfigSizes(data->screen_config, &nsizes);
|
slouken@2873
|
420 |
if (nsizes > 0) {
|
slouken@2873
|
421 |
int i, j;
|
slouken@2874
|
422 |
for (i = 0; i < nsizes; i++) {
|
slouken@2873
|
423 |
mode.w = sizes[i].width;
|
slouken@2873
|
424 |
mode.h = sizes[i].height;
|
slouken@2873
|
425 |
|
slouken@2873
|
426 |
rates = XRRConfigRates(data->screen_config, i, &nrates);
|
slouken@2873
|
427 |
for (j = 0; j < nrates; ++j) {
|
slouken@2873
|
428 |
mode.refresh_rate = rates[j];
|
slouken@2873
|
429 |
#ifdef X11MODES_DEBUG
|
slouken@2874
|
430 |
fprintf(stderr,
|
slouken@2874
|
431 |
"XRANDR: mode = %4d[%d], w = %4d, h = %4d, rate = %4d\n",
|
slouken@2873
|
432 |
i, j, mode.w, mode.h, mode.refresh_rate);
|
slouken@2873
|
433 |
#endif
|
slouken@3500
|
434 |
SDL_AddDisplayMode(sdl_display, &mode);
|
slouken@2873
|
435 |
}
|
slouken@2873
|
436 |
}
|
slouken@2873
|
437 |
|
slouken@2873
|
438 |
data->use_xrandr = xrandr_major * 100 + xrandr_minor;
|
slouken@2874
|
439 |
data->saved_size =
|
slouken@2874
|
440 |
XRRConfigCurrentConfiguration(data->screen_config,
|
slouken@2874
|
441 |
&data->saved_rotation);
|
slouken@2873
|
442 |
data->saved_rate = XRRConfigCurrentRate(data->screen_config);
|
slouken@2873
|
443 |
}
|
slouken@2873
|
444 |
}
|
slouken@2873
|
445 |
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
|
slouken@2873
|
446 |
|
slouken@2873
|
447 |
#if SDL_VIDEO_DRIVER_X11_VIDMODE
|
slouken@2873
|
448 |
/* XVidMode */
|
slouken@2873
|
449 |
if (!data->use_xrandr &&
|
slouken@2873
|
450 |
#if SDL_VIDEO_DRIVER_X11_XINERAMA
|
slouken@2873
|
451 |
(!data->use_xinerama || data->xinerama_info.screen_number == 0) &&
|
slouken@2873
|
452 |
#endif
|
slouken@2873
|
453 |
CheckVidMode(display, &vm_major, &vm_minor) &&
|
slouken@2874
|
454 |
SDL_NAME(XF86VidModeGetAllModeLines) (display, data->screen, &nmodes,
|
slouken@2874
|
455 |
&modes)) {
|
slouken@2873
|
456 |
int i;
|
slouken@2873
|
457 |
|
slouken@2873
|
458 |
#ifdef X11MODES_DEBUG
|
slouken@2873
|
459 |
printf("VidMode modes: (unsorted)\n");
|
slouken@2873
|
460 |
for (i = 0; i < nmodes; ++i) {
|
slouken@2873
|
461 |
printf("Mode %d: %d x %d @ %d\n", i,
|
slouken@2874
|
462 |
modes[i]->hdisplay, modes[i]->vdisplay,
|
slouken@2874
|
463 |
calculate_rate(modes[i]));
|
slouken@2873
|
464 |
}
|
slouken@2873
|
465 |
#endif
|
slouken@2873
|
466 |
for (i = 0; i < nmodes; ++i) {
|
slouken@2873
|
467 |
mode.w = modes[i]->hdisplay;
|
slouken@2873
|
468 |
mode.h = modes[i]->vdisplay;
|
slouken@2873
|
469 |
mode.refresh_rate = calculate_rate(modes[i]);
|
slouken@3500
|
470 |
SDL_AddDisplayMode(sdl_display, &mode);
|
slouken@2873
|
471 |
}
|
slouken@2873
|
472 |
XFree(modes);
|
slouken@2873
|
473 |
|
slouken@2873
|
474 |
data->use_vidmode = vm_major * 100 + vm_minor;
|
slouken@2873
|
475 |
save_mode(display, data);
|
slouken@2873
|
476 |
}
|
slouken@2873
|
477 |
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
|
slouken@2873
|
478 |
|
slouken@2873
|
479 |
if (!data->use_xrandr && !data->use_vidmode) {
|
slouken@2873
|
480 |
mode.w = screen_w;
|
slouken@2873
|
481 |
mode.h = screen_h;
|
slouken@2873
|
482 |
mode.refresh_rate = 0;
|
slouken@3500
|
483 |
SDL_AddDisplayMode(sdl_display, &mode);
|
slouken@2874
|
484 |
}
|
slouken@2873
|
485 |
#ifdef X11MODES_DEBUG
|
slouken@2873
|
486 |
if (data->use_xinerama) {
|
slouken@2873
|
487 |
printf("Xinerama is enabled\n");
|
slouken@2873
|
488 |
}
|
slouken@2873
|
489 |
|
slouken@2873
|
490 |
if (data->use_xrandr) {
|
slouken@2873
|
491 |
printf("XRandR is enabled\n");
|
slouken@2873
|
492 |
}
|
slouken@2873
|
493 |
|
slouken@2873
|
494 |
if (data->use_vidmode) {
|
slouken@2873
|
495 |
printf("VidMode is enabled\n");
|
slouken@2873
|
496 |
}
|
slouken@2873
|
497 |
#endif /* X11MODES_DEBUG */
|
slouken@2873
|
498 |
}
|
slouken@2873
|
499 |
|
slouken@2873
|
500 |
static void
|
slouken@2874
|
501 |
get_real_resolution(Display * display, SDL_DisplayData * data, int *w, int *h,
|
slouken@2874
|
502 |
int *rate)
|
slouken@2873
|
503 |
{
|
slouken@2873
|
504 |
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
slouken@2873
|
505 |
if (data->use_xrandr) {
|
slouken@2873
|
506 |
int nsizes;
|
slouken@2873
|
507 |
XRRScreenSize *sizes;
|
slouken@2874
|
508 |
|
slouken@2873
|
509 |
sizes = XRRConfigSizes(data->screen_config, &nsizes);
|
slouken@2873
|
510 |
if (nsizes > 0) {
|
slouken@2873
|
511 |
int cur_size;
|
slouken@2873
|
512 |
Rotation cur_rotation;
|
slouken@2873
|
513 |
|
slouken@2874
|
514 |
cur_size =
|
slouken@2874
|
515 |
XRRConfigCurrentConfiguration(data->screen_config,
|
slouken@2874
|
516 |
&cur_rotation);
|
slouken@2873
|
517 |
*w = sizes[cur_size].width;
|
slouken@2873
|
518 |
*h = sizes[cur_size].height;
|
slouken@2873
|
519 |
*rate = XRRConfigCurrentRate(data->screen_config);
|
slouken@2873
|
520 |
#ifdef X11MODES_DEBUG
|
slouken@2874
|
521 |
fprintf(stderr,
|
slouken@2874
|
522 |
"XRANDR: get_real_resolution: w = %d, h = %d, rate = %d\n",
|
slouken@2874
|
523 |
*w, *h, *rate);
|
slouken@2873
|
524 |
#endif
|
slouken@2873
|
525 |
return;
|
slouken@2873
|
526 |
}
|
slouken@2873
|
527 |
}
|
slouken@2873
|
528 |
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
|
slouken@2873
|
529 |
|
slouken@2873
|
530 |
#if SDL_VIDEO_DRIVER_X11_VIDMODE
|
slouken@2873
|
531 |
if (data->use_vidmode) {
|
slouken@2873
|
532 |
SDL_NAME(XF86VidModeModeInfo) mode;
|
slouken@2873
|
533 |
|
slouken@2874
|
534 |
if (SDL_NAME(XF86VidModeGetModeInfo) (display, data->screen, &mode)) {
|
slouken@2873
|
535 |
*w = mode.hdisplay;
|
slouken@2873
|
536 |
*h = mode.vdisplay;
|
slouken@2873
|
537 |
*rate = calculate_rate(&mode);
|
slouken@2873
|
538 |
return;
|
slouken@2873
|
539 |
}
|
slouken@2873
|
540 |
}
|
slouken@2873
|
541 |
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
|
slouken@2873
|
542 |
|
slouken@2873
|
543 |
#if SDL_VIDEO_DRIVER_X11_XINERAMA
|
slouken@2873
|
544 |
if (data->use_xinerama) {
|
slouken@2873
|
545 |
*w = data->xinerama_info.width;
|
slouken@2873
|
546 |
*h = data->xinerama_info.height;
|
slouken@2873
|
547 |
*rate = 0;
|
slouken@2873
|
548 |
return;
|
slouken@2873
|
549 |
}
|
slouken@2873
|
550 |
#endif /* SDL_VIDEO_DRIVER_X11_XINERAMA */
|
slouken@2873
|
551 |
|
slouken@2873
|
552 |
*w = DisplayWidth(display, data->screen);
|
slouken@2873
|
553 |
*h = DisplayHeight(display, data->screen);
|
slouken@2873
|
554 |
*rate = 0;
|
slouken@2873
|
555 |
}
|
slouken@2873
|
556 |
|
slouken@2873
|
557 |
static void
|
slouken@2874
|
558 |
set_best_resolution(Display * display, SDL_DisplayData * data, int w, int h,
|
slouken@2874
|
559 |
int rate)
|
slouken@2873
|
560 |
{
|
slouken@2873
|
561 |
int real_w, real_h, real_rate;
|
slouken@2873
|
562 |
|
slouken@2873
|
563 |
/* check current mode so we can avoid uneccessary mode changes */
|
slouken@2873
|
564 |
get_real_resolution(display, data, &real_w, &real_h, &real_rate);
|
slouken@2873
|
565 |
if (w == real_w && h == real_h && (!rate || rate == real_rate)) {
|
slouken@2873
|
566 |
return;
|
slouken@2873
|
567 |
}
|
slouken@2873
|
568 |
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
slouken@2873
|
569 |
if (data->use_xrandr) {
|
slouken@2873
|
570 |
#ifdef X11MODES_DEBUG
|
slouken@2873
|
571 |
fprintf(stderr, "XRANDR: set_best_resolution(): w = %d, h = %d\n",
|
slouken@2873
|
572 |
w, h);
|
slouken@2873
|
573 |
#endif
|
slouken@2873
|
574 |
int i, nsizes, nrates;
|
slouken@2873
|
575 |
int best;
|
slouken@2873
|
576 |
int best_rate;
|
slouken@2873
|
577 |
XRRScreenSize *sizes;
|
slouken@2873
|
578 |
short *rates;
|
slouken@2873
|
579 |
|
slouken@2873
|
580 |
/* find the smallest resolution that is at least as big as the user requested */
|
slouken@2873
|
581 |
best = -1;
|
slouken@2873
|
582 |
sizes = XRRConfigSizes(data->screen_config, &nsizes);
|
slouken@2873
|
583 |
for (i = 0; i < nsizes; ++i) {
|
slouken@2873
|
584 |
if (sizes[i].width < w || sizes[i].height < h) {
|
slouken@2873
|
585 |
continue;
|
slouken@2873
|
586 |
}
|
slouken@2873
|
587 |
if (sizes[i].width == w && sizes[i].height == h) {
|
slouken@2873
|
588 |
best = i;
|
slouken@2873
|
589 |
break;
|
slouken@2873
|
590 |
}
|
slouken@2873
|
591 |
if (best == -1 ||
|
slouken@2873
|
592 |
(sizes[i].width < sizes[best].width) ||
|
slouken@2874
|
593 |
(sizes[i].width == sizes[best].width
|
slouken@2874
|
594 |
&& sizes[i].height < sizes[best].height)) {
|
slouken@2873
|
595 |
best = i;
|
slouken@2873
|
596 |
}
|
slouken@2873
|
597 |
}
|
slouken@2873
|
598 |
|
slouken@2873
|
599 |
if (best >= 0) {
|
slouken@2873
|
600 |
best_rate = 0;
|
slouken@2873
|
601 |
rates = XRRConfigRates(data->screen_config, best, &nrates);
|
slouken@2873
|
602 |
for (i = 0; i < nrates; ++i) {
|
slouken@2873
|
603 |
if (rates[i] == rate) {
|
slouken@2873
|
604 |
best_rate = rate;
|
slouken@2873
|
605 |
break;
|
slouken@2873
|
606 |
}
|
slouken@2873
|
607 |
if (!rate) {
|
slouken@2873
|
608 |
/* Higher is better, right? */
|
slouken@2873
|
609 |
if (rates[i] > best_rate) {
|
slouken@2873
|
610 |
best_rate = rates[i];
|
slouken@2873
|
611 |
}
|
slouken@2873
|
612 |
} else {
|
slouken@2874
|
613 |
if (SDL_abs(rates[i] - rate) < SDL_abs(best_rate - rate)) {
|
slouken@2873
|
614 |
best_rate = rates[i];
|
slouken@2873
|
615 |
}
|
slouken@2873
|
616 |
}
|
slouken@2873
|
617 |
}
|
slouken@2874
|
618 |
XRRSetScreenConfigAndRate(display, data->screen_config,
|
slouken@2874
|
619 |
RootWindow(display, data->screen), best,
|
slouken@2874
|
620 |
data->saved_rotation, best_rate,
|
slouken@2874
|
621 |
CurrentTime);
|
slouken@2873
|
622 |
}
|
slouken@2873
|
623 |
return;
|
slouken@2873
|
624 |
}
|
slouken@2873
|
625 |
#endif /* SDL_VIDEO_DRIVER_X11_XRANDR */
|
slouken@2873
|
626 |
|
slouken@2873
|
627 |
#if SDL_VIDEO_DRIVER_X11_VIDMODE
|
slouken@2873
|
628 |
if (data->use_vidmode) {
|
slouken@2874
|
629 |
SDL_NAME(XF86VidModeModeInfo) ** modes;
|
slouken@2873
|
630 |
int i, nmodes;
|
slouken@2873
|
631 |
int best;
|
slouken@2873
|
632 |
|
slouken@2874
|
633 |
if (SDL_NAME(XF86VidModeGetAllModeLines)
|
slouken@2874
|
634 |
(display, data->screen, &nmodes, &modes)) {
|
slouken@2873
|
635 |
best = -1;
|
slouken@2873
|
636 |
for (i = 0; i < nmodes; ++i) {
|
slouken@2873
|
637 |
if (modes[i]->hdisplay < w || modes[i]->vdisplay < h) {
|
slouken@2873
|
638 |
continue;
|
slouken@2873
|
639 |
}
|
slouken@2873
|
640 |
if (best == -1 ||
|
slouken@2873
|
641 |
(modes[i]->hdisplay < modes[best]->hdisplay) ||
|
slouken@2874
|
642 |
(modes[i]->hdisplay == modes[best]->hdisplay
|
slouken@2874
|
643 |
&& modes[i]->vdisplay < modes[best]->vdisplay)) {
|
slouken@2873
|
644 |
best = i;
|
slouken@2873
|
645 |
continue;
|
slouken@2873
|
646 |
}
|
slouken@2873
|
647 |
if ((modes[i]->hdisplay == modes[best]->hdisplay) &&
|
slouken@2873
|
648 |
(modes[i]->vdisplay == modes[best]->vdisplay)) {
|
slouken@2873
|
649 |
if (!rate) {
|
slouken@2873
|
650 |
/* Higher is better, right? */
|
slouken@2874
|
651 |
if (calculate_rate(modes[i]) >
|
slouken@2874
|
652 |
calculate_rate(modes[best])) {
|
slouken@2873
|
653 |
best = i;
|
slouken@2873
|
654 |
}
|
slouken@2873
|
655 |
} else {
|
slouken@2874
|
656 |
if (SDL_abs(calculate_rate(modes[i]) - rate) <
|
slouken@2874
|
657 |
SDL_abs(calculate_rate(modes[best]) - rate)) {
|
slouken@2873
|
658 |
best = i;
|
slouken@2873
|
659 |
}
|
slouken@2873
|
660 |
}
|
slouken@2873
|
661 |
}
|
slouken@2873
|
662 |
}
|
slouken@2873
|
663 |
if (best >= 0) {
|
slouken@2873
|
664 |
#ifdef X11MODES_DEBUG
|
slouken@2873
|
665 |
printf("Best Mode %d: %d x %d @ %d\n", best,
|
slouken@2874
|
666 |
modes[best]->hdisplay, modes[best]->vdisplay,
|
slouken@2874
|
667 |
calculate_rate(modes[best]));
|
slouken@2873
|
668 |
#endif
|
slouken@2874
|
669 |
SDL_NAME(XF86VidModeSwitchToMode) (display, data->screen,
|
slouken@2874
|
670 |
modes[best]);
|
slouken@2873
|
671 |
}
|
slouken@2873
|
672 |
XFree(modes);
|
slouken@2873
|
673 |
}
|
slouken@2873
|
674 |
return;
|
slouken@2873
|
675 |
}
|
slouken@2873
|
676 |
#endif /* SDL_VIDEO_DRIVER_X11_VIDMODE */
|
slouken@1950
|
677 |
}
|
slouken@1950
|
678 |
|
slouken@1950
|
679 |
int
|
slouken@3500
|
680 |
X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode)
|
slouken@1950
|
681 |
{
|
slouken@2873
|
682 |
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
|
slouken@3500
|
683 |
SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
|
slouken@2873
|
684 |
|
slouken@2873
|
685 |
set_best_resolution(display, data, mode->w, mode->h, mode->refresh_rate);
|
slouken@2873
|
686 |
return 0;
|
slouken@1950
|
687 |
}
|
slouken@1950
|
688 |
|
slouken@1950
|
689 |
void
|
slouken@1950
|
690 |
X11_QuitModes(_THIS)
|
slouken@1950
|
691 |
{
|
slouken@1950
|
692 |
}
|
slouken@1950
|
693 |
|
slouken@1950
|
694 |
/* vi: set ts=4 sw=4 expandtab: */
|