TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
fg_gm.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : fg_gm.cpp
4 created : Sat Mar 8 14:40:50 CET 2003
5 copyright : (C) 2003 by Eric Espi�
6 email : eric.espie@torcs.org
7 version : $Id$
8
9 ***************************************************************************/
10
11/*
12 * The freeglut library private include file.
13 *
14 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
15 * Written by Pawel W. Olszta, <olszta@sourceforge.net>
16 * Creation date: Thu Dec 2 1999
17 *
18 * Permission is hereby granted, free of charge, to any person obtaining a
19 * copy of this software and associated documentation files (the "Software"),
20 * to deal in the Software without restriction, including without limitation
21 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
22 * and/or sell copies of the Software, and to permit persons to whom the
23 * Software is furnished to do so, subject to the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be included
26 * in all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
31 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
32 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 */
35
40
41/*
42 2004/10/03 Bernhard Wymann: Added Randr support, bugfixes.
43*/
44
45#include <GL/gl.h>
46#include <GL/glu.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <math.h>
50
51#include <tgfclient.h>
52#include "fg_gm.h"
53
54#ifndef WIN32
55
56#include <GL/glx.h>
57#include <X11/Xlib.h>
58#include <X11/Xatom.h>
59#include <X11/keysym.h>
60
61#ifdef USE_RANDR_EXT
62#include <X11/extensions/Xrandr.h>
63#else // USE_RANDR_EXT
64#include <X11/extensions/xf86vmode.h>
65#endif // USE_RANDR_EXT
66
67
68static int fgInitDone = 0;
69
72{
73 Display* display; // The display we are being run in.
74 int Screen; // The screen we are about to use.
75 Window RootWindow; //The screen's root window.
76
77 int ScreenWidth; // The screen's width in pixels.
78 int ScreenHeight; // The screen's height in pixels.
79 int error_base; // Base error number of the extension.
80 int event_base; // Base event number of the extension.
81
82#ifdef USE_RANDR_EXT
83 Rotation rotation; // The rotation mode.
84 short rate; // Display refresh rate.
85#else //USE_RANDR_EXT
86 XF86VidModeModeLine DisplayMode; // Current screen's display settings.
87 int DisplayModeClock; // The display mode's refresh rate.
88#endif //USE_RANDR_EXT
89};
90
91
92/*
93 * A helper structure holding two ints and a boolean
94 */
95typedef struct tagSFG_XYUse SFG_XYUse;
97{
98 int X, Y; /* The two integers... */
99};
100
101/*
102 * This structure holds different freeglut settings
103 */
104typedef struct tagSFG_State SFG_State;
106{
107 SFG_XYUse GameModeSize; // The game mode screen's dimensions.
108 int GameModeDepth; // The pixel depth for game mode.
109 int GameModeRefresh; // The refresh rate for game mode.
110};
111
112/*
113 * A structure pointed by g_pDisplay holds all information
114 * regarding the display, screen, root window etc.
115 */
117
118/*
119 * The settings for the current freeglut session
120 */
122
123
124/*
125 * A call to this function should initialize all the display stuff...
126 */
127static void fgInitialize(void)
128{
129 const char* displayName;
130 displayName = getenv("DISPLAY");
131 if (!displayName) {
132 displayName = ":0.0";
133 }
134
135 // Have the display created.
136 fgDisplay.display = XOpenDisplay(displayName);
137 if(fgDisplay.display == NULL) {
138 // Failed to open a display. That's no good.
139 GfOut( "failed to open display '%s'", XDisplayName( displayName ) );
140 }
141
142 // Grab the default screen for the display we have just opened.
143 fgDisplay.Screen = DefaultScreen(fgDisplay.display);
144
145 // The same applying to the root window
146 fgDisplay.RootWindow = RootWindow(fgDisplay.display, fgDisplay.Screen);
147
148 // Grab the logical screen's geometry.
149 fgDisplay.ScreenWidth = DisplayWidth(fgDisplay.display, fgDisplay.Screen);
150 fgDisplay.ScreenHeight = DisplayHeight(fgDisplay.display, fgDisplay.Screen);
151
152#ifdef USE_RANDR_EXT
153 int major, minor;
154 XRRQueryVersion(fgDisplay.display, &major, &minor);
155 printf("Randr version: %d.%d\n", major, minor);
156 XRRQueryExtension(fgDisplay.display, &fgDisplay.event_base, &fgDisplay.error_base);
157#else //USE_RANDR_EXT
158 int major, minor;
159 XF86VidModeQueryVersion(fgDisplay.display, &major, &minor);
160 printf("Xxf86vm version: %d.%d\n", major, minor);
161 XF86VidModeQueryExtension(fgDisplay.display, &fgDisplay.event_base, &fgDisplay.error_base);
162#endif //USE_RANDR_EXT
163}
164
165/*
166 * Remembers the current visual settings, so that
167 * we can change them and restore later...
168 */
169static void fghRememberState( void )
170{
171 // This highly depends on the XFree86 extensions, not approved as X Consortium standards.
172 if (!fgInitDone) {
173 fgInitialize();
174 fgInitDone = 1;
175
176 // Query the current display settings.
177#ifdef USE_RANDR_EXT
178 XRRScreenConfiguration *screenconfig = XRRGetScreenInfo(fgDisplay.display, fgDisplay.RootWindow);
179 if (screenconfig != NULL) {
180 SizeID size = XRRConfigCurrentConfiguration (screenconfig, &fgDisplay.rotation);
181 int nsize;
182 XRRScreenSize *sizes = XRRConfigSizes(screenconfig, &nsize);
183 fgDisplay.ScreenWidth = sizes[size].width;
184 fgDisplay.ScreenHeight = sizes[size].height;
185 fgDisplay.rate = XRRConfigCurrentRate(screenconfig);
186 //printf("x: %d, y: %d, rate: %d\n", fgDisplay.ScreenWidth, fgDisplay.ScreenHeight, fgDisplay.rate);
187 XRRFreeScreenConfigInfo(screenconfig);
188 } else {
189 // Hmm, what to do here, exit?
190 }
191#else //USE_RANDR_EXT
192 XF86VidModeGetModeLine(
193 fgDisplay.display,
194 fgDisplay.Screen,
195 &fgDisplay.DisplayModeClock,
196 &fgDisplay.DisplayMode
197 );
198#endif //USE_RANDR_EXT
199 }
200}
201
202/*
203 * Restores the previously remembered visual settings
204 */
205static void fghRestoreState( void )
206{
207#ifdef USE_RANDR_EXT
208 XRRScreenConfiguration *screenconfig = XRRGetScreenInfo(fgDisplay.display, fgDisplay.RootWindow);
209 if (screenconfig != NULL) {
210 int nsize;
211 XRRScreenSize *sizes = XRRConfigSizes(screenconfig, &nsize);
212 // Search for the display resolution ID for the old video mode.
213 SizeID size;
214 for (size = 0; size < nsize; size++) {
215 if (sizes[size].width == fgDisplay.ScreenWidth && sizes[size].height == fgDisplay.ScreenHeight)
216 break;
217 }
218
219 XSelectInput(fgDisplay.display, fgDisplay.RootWindow, StructureNotifyMask);
220 XRRSelectInput(fgDisplay.display, fgDisplay.RootWindow, RRScreenChangeNotifyMask);
221 Status status = RRSetConfigFailed;
222 status = XRRSetScreenConfigAndRate(
223 fgDisplay.display,
224 screenconfig,
225 fgDisplay.RootWindow,
226 size,
227 fgDisplay.rotation,
228 fgDisplay.rate,
229 CurrentTime
230 );
231
232 if (status == RRSetConfigSuccess) {
233 XEvent ev;
234 do {
235 XNextEvent(fgDisplay.display, &ev);
236 XRRUpdateConfiguration(&ev);
237 } while ((ev.type != ConfigureNotify) && ((ev.type - fgDisplay.event_base) != RRScreenChangeNotify));
238 XSync(fgDisplay.display, True);
239 }
240 XRRFreeScreenConfigInfo(screenconfig);
241 } else {
242 // Hmm, what to do here, exit?
243 }
244#else //USE_RANDR_EXT
245 /*
246 * This highly depends on the XFree86 extensions, not approved as X Consortium standards
247 */
248 XF86VidModeModeInfo** displayModes;
249 int i, displayModesCount;
250
251 /*
252 * Query for all the display available...
253 */
254 XF86VidModeGetAllModeLines(
255 fgDisplay.display,
256 fgDisplay.Screen,
257 &displayModesCount,
258 &displayModes
259 );
260
261 /*
262 * Check every of the modes looking for one that matches our demands
263 */
264 for( i=0; i<displayModesCount; i++ ) {
265 if( displayModes[ i ]->hdisplay == fgDisplay.DisplayMode.hdisplay &&
266 displayModes[ i ]->vdisplay == fgDisplay.DisplayMode.vdisplay &&
267 displayModes[ i ]->dotclock == (unsigned int)fgDisplay.DisplayModeClock )
268 {
269 /*
270 * OKi, this is the display mode we have been looking for...
271 */
272 XSync(fgDisplay.display, True);
273 XF86VidModeSwitchToMode(fgDisplay.display, fgDisplay.Screen, displayModes[ i ]);
274 // FIXME: usleep: Hack to avoid screen corruption (does not work always). Do you know a clean solution?
275 usleep(100000);
276 XSync(fgDisplay.display, False);
277 XF86VidModeSetViewPort(fgDisplay.display, fgDisplay.Screen, 0, 0);
278 // FIXME: usleep: Hack to avoid screen corruption (does not work always). Do you know a clean solution?
279 usleep(100000);
280 XSync(fgDisplay.display, False);
281 XWarpPointer(
282 fgDisplay.display,
283 None,
284 fgDisplay.RootWindow,
285 0, 0, 0, 0,
286 fgDisplay.ScreenWidth/2,
287 fgDisplay.ScreenHeight/2
288 );
289
290 XFree(displayModes);
291 if (fgDisplay.DisplayMode.privsize > 0) {
292 // Cannot compile with c++! --> private keyword.
293 //XFree(fgDisplay.DisplayMode.private);
294 }
295 XFlush(fgDisplay.display);
296 return;
297 }
298 }
299 XFree(displayModes);
300 XFlush(fgDisplay.display);
301#endif //USE_RANDR_EXT
302}
303
304#ifndef USE_RANDR_EXT
305/*
306 * Checks the display mode settings against user's preferences
307 */
308static int fghCheckDisplayMode( int width, int height, int depth, int refresh )
309{
310 /*
311 * The desired values should be stored in fgState structure...
312 */
313 return( (width == fgState.GameModeSize.X) && (height == fgState.GameModeSize.Y) &&
314 (depth == fgState.GameModeDepth) && (refresh == fgState.GameModeRefresh) );
315}
316#endif //USE_RANDR_EXT
317
318/*
319 * Changes the current display mode to match user's settings
320 */
321static int fghChangeDisplayMode( int /* haveToTest */ )
322{
323#ifdef USE_RANDR_EXT
324 XRRScreenConfiguration *screenconfig = XRRGetScreenInfo(fgDisplay.display, fgDisplay.RootWindow);
325 if (screenconfig != NULL) {
326 int nsize;
327 XRRScreenSize *sizes = XRRConfigSizes(screenconfig, &nsize);
328 // Search for the requested display resolution.
329 SizeID size;
330 for (size = 0; size < nsize; size++) {
331 if (sizes[size].width == fgState.GameModeSize.X && sizes[size].height == fgState.GameModeSize.Y) {
332 break;
333 }
334 }
335
336 if (size >= nsize) {
337 // We did not find a matching resolution.
338 XRRFreeScreenConfigInfo(screenconfig);
339 return FALSE;
340 } else {
341 // Ok, resolution is ok, now check the refresh rate.
342 int nrate;
343 short *rates = XRRConfigRates(screenconfig, size, &nrate);
344 int rate;
345 for (rate = 0; rate < nrate; rate++) {
346 if (rates[rate] == fgState.GameModeRefresh) {
347 break;
348 }
349 }
350
351 if (rate >= nrate) {
352 // We did not find a matching refresh rate.
353 XRRFreeScreenConfigInfo(screenconfig);
354 return FALSE;
355 } else {
356 // We have everything, try to switch.
357 XSelectInput(fgDisplay.display, fgDisplay.RootWindow, StructureNotifyMask);
358 XRRSelectInput(fgDisplay.display, fgDisplay.RootWindow, RRScreenChangeNotifyMask);
359 Status status = RRSetConfigFailed;
360 status = XRRSetScreenConfigAndRate(
361 fgDisplay.display,
362 screenconfig,
363 fgDisplay.RootWindow,
364 size,
365 fgDisplay.rotation,
366 rates[rate],
367 CurrentTime
368 );
369
370 XRRFreeScreenConfigInfo(screenconfig);
371
372 if (status == RRSetConfigSuccess) {
373 XEvent ev;
374 do {
375 XNextEvent(fgDisplay.display, &ev);
376 XRRUpdateConfiguration(&ev);
377 } while ((ev.type != ConfigureNotify) && ((ev.type - fgDisplay.event_base) != RRScreenChangeNotify));
378 XSync(fgDisplay.display, True);
379 return TRUE;
380 } else {
381 return FALSE;
382 }
383 }
384 }
385 }
386
387 return FALSE;
388#else //USE_RANDR_EXT
389 /*
390 * This highly depends on the XFree86 extensions, not approved as X Consortium standards
391 */
392 XF86VidModeModeInfo** displayModes;
393 int i, displayModesCount;
394
395 /*
396 * Query for all the display available...
397 */
398 XF86VidModeGetAllModeLines(
399 fgDisplay.display,
400 fgDisplay.Screen,
401 &displayModesCount,
402 &displayModes
403 );
404
405 /*
406 * Check every of the modes looking for one that matches our demands
407 */
408 for( i=0; i<displayModesCount; i++ )
409 {
410 // Compute the displays refresh rate, dotclock comes in kHz.
411 int refresh = displayModes[ i ]->dotclock*1000/(displayModes[ i ]->htotal*displayModes[ i ]->vtotal);
412
413 if( fghCheckDisplayMode( displayModes[ i ]->hdisplay, displayModes[ i ]->vdisplay,
414 fgState.GameModeDepth, refresh ) )
415 {
416 // Added failure code path, who can guarantee if that works always?
417 // If i == 0, then the videomode we prefer is already set, so the short circuit
418 // "||" does not evaluate the (in this case unnecessary) XF86VidModeSwitchToMode.
419 //XFlush(fgDisplay.display);
420 //XSync(fgDisplay.display, True);
421 if ((i == 0) || (XF86VidModeSwitchToMode(
422 fgDisplay.display,
423 fgDisplay.Screen,
424 displayModes[ i ]) > 0))
425 {
426 XF86VidModeSetViewPort(
427 fgDisplay.display,
428 fgDisplay.Screen,
429 (fgDisplay.ScreenWidth - fgState.GameModeSize.X) / 2,
430 (fgDisplay.ScreenHeight - fgState.GameModeSize.Y) / 2
431 );
432
433 // Move the mouse pointer in the middle of the viewport.
434 XWarpPointer(
435 fgDisplay.display,
436 None,
437 fgDisplay.RootWindow,
438 0, 0, 0, 0,
439 fgDisplay.ScreenWidth/2,
440 fgDisplay.ScreenHeight/2
441 );
442 XFree(displayModes);
443 XFlush(fgDisplay.display);
444 return TRUE;
445 } else {
446 XFree(displayModes);
447 XFlush(fgDisplay.display);
448 return( FALSE );
449 }
450 }
451 }
452
453 /*
454 * Something must have went wrong
455 */
456 XFree(displayModes);
457 XFlush(fgDisplay.display);
458 return( FALSE );
459#endif //USE_RANDR_EXT
460}
461
462#endif /* WIN32 */
463
464/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
465
466/*
467 * Sets the game mode display string
468 */
469void fglutGameModeString( const char* string )
470{
471#ifndef WIN32
472 int width = 640, height = 480, depth = 16, refresh = 72;
473
474 /*
475 * This one seems a bit easier than glutInitDisplayString. The bad thing
476 * about it that I was unable to find the game mode string definition, so
477 * that I assumed it is: "[width]x[height]:[depth]@[refresh rate]", which
478 * appears in all GLUT game mode programs I have seen to date.
479 */
480 if( sscanf( string, "%ix%i:%i@%i", &width, &height, &depth, &refresh ) != 4 )
481 if( sscanf( string, "%ix%i:%i", &width, &height, &depth ) != 3 )
482 if( sscanf( string, "%ix%i@%i", &width, &height, &refresh ) != 3 )
483 if( sscanf( string, "%ix%i", &width, &height ) != 2 )
484 if( sscanf( string, ":%i@%i", &depth, &refresh ) != 2 )
485 if( sscanf( string, ":%i", &depth ) != 1 )
486 if( sscanf( string, "@%i", &refresh ) != 1 )
487 GfOut( "unable to parse game mode string `%s'", string );
488
489 /*
490 * Hopefully it worked, and if not, we still have the default values
491 */
492 fgState.GameModeSize.X = width;
493 fgState.GameModeSize.Y = height;
494 fgState.GameModeDepth = depth;
495 fgState.GameModeRefresh = refresh;
496#endif /* WIN32 */
497}
498
499/*
500 * Enters the game mode
501 */
503{
504#ifndef WIN32
505 /*
506 * Remember the current resolution, etc.
507 */
509 /*
510 * We are ready to change the current screen's resolution now
511 */
512 if( fghChangeDisplayMode( FALSE ) == FALSE )
513 {
514 GfOut( "failed to change screen settings" );
515 return( FALSE );
516 }
517
518 /*
519 * Return successfull
520 */
521 return( TRUE );
522#else /* WIN32 */
523 return( FALSE );
524#endif /* WIN32 */
525}
526
527/*
528 * Leaves the game mode
529 */
531{
532#ifndef WIN32
533 /*
534 * Then, have the desktop visual settings restored
535 */
537#endif /* WIN32 */
538}
@ None
struct tagSFG_XYUse SFG_XYUse
Definition fg_gm.cpp:95
static int fghCheckDisplayMode(int width, int height, int depth, int refresh)
Definition fg_gm.cpp:308
void fglutLeaveGameMode(void)
Definition fg_gm.cpp:530
static SFG_State fgState
Definition fg_gm.cpp:121
struct tagSFG_Display SFG_Display
Definition fg_gm.cpp:70
static void fgInitialize(void)
Definition fg_gm.cpp:127
static SFG_Display fgDisplay
Definition fg_gm.cpp:116
static void fghRememberState(void)
Definition fg_gm.cpp:169
static int fgInitDone
Definition fg_gm.cpp:68
static void fghRestoreState(void)
Definition fg_gm.cpp:205
void fglutGameModeString(const char *string)
Definition fg_gm.cpp:469
struct tagSFG_State SFG_State
Definition fg_gm.cpp:104
static int fghChangeDisplayMode(int)
Definition fg_gm.cpp:321
int fglutEnterGameMode(void)
Definition fg_gm.cpp:502
int refresh(tSituation *s)
Definition grmain.cpp:306
Window RootWindow
Definition fg_gm.cpp:75
Display * display
Definition fg_gm.cpp:73
int ScreenHeight
Definition fg_gm.cpp:78
int DisplayModeClock
Definition fg_gm.cpp:87
XF86VidModeModeLine DisplayMode
Definition fg_gm.cpp:86
int ScreenWidth
Definition fg_gm.cpp:77
SFG_XYUse GameModeSize
Definition fg_gm.cpp:107
int GameModeRefresh
Definition fg_gm.cpp:109
int GameModeDepth
Definition fg_gm.cpp:108
#define GfOut
Definition tgf.h:372
The Gaming Framework API (client part).