2
/* Copyright (c) Mark J. Kilgard, 1998. */
4
/* This program is freely distributable without licensing fees
5
and is provided without guarantee or warrantee expressed or
6
implied. This program is -not- in the public domain. */
16
#if !defined(_WIN32) && !defined(__OS2__)
18
#include <X11/Xatom.h>
20
/* SGI optimization introduced in IRIX 6.3 to avoid X server
21
round trips for interning common X atoms. */
22
#if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS)
23
#include <X11/SGIFastAtom.h>
25
#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how)
27
#endif /* not _WIN32 */
29
int __glutDisplaySettingsChanged = 0;
30
static DisplayMode *dmodes, *currentDm = NULL;
31
static int ndmodes = -1;
32
GLUTwindow *__glutGameModeWindow = NULL;
35
static char *compstr[] =
37
"none", "=", "!=", "<=", ">=", ">", "<", "~"
39
static char *capstr[] =
41
"width", "height", "bpp", "hertz", "num"
50
__glutCloseDownGameMode(void)
52
if (__glutDisplaySettingsChanged) {
54
/* Assumes that display settings have been changed, that
55
is __glutDisplaySettingsChanged is true. */
56
ChangeDisplaySettings(NULL, 0);
58
__glutDisplaySettingsChanged = 0;
60
__glutGameModeWindow = NULL;
64
glutLeaveGameMode(void)
66
if (__glutGameModeWindow == NULL) {
67
__glutWarning("not in game mode so cannot leave game mode");
70
__glutDestroyWindow(__glutGameModeWindow,
71
__glutGameModeWindow);
72
XFlush(__glutDisplay);
73
__glutGameModeWindow = NULL;
78
/* Same values as from MSDN's SetDisp.c example. */
80
#define MIN_FREQUENCY 60
83
initGameModeSupport(void)
90
/* ndmodes is initially -1 to indicate no
91
dmodes allocated yet. */
95
/* Determine how many display modes there are. */
98
while (EnumDisplaySettings(NULL, mode, &dm)) {
99
if (dm.dmPelsWidth >= MIN_WIDTH &&
100
(dm.dmDisplayFrequency == 0 ||
101
dm.dmDisplayFrequency >= MIN_FREQUENCY)) {
107
/* Allocate memory for a list of all the display modes. */
108
dmodes = (DisplayMode*)
109
malloc(ndmodes * sizeof(DisplayMode));
111
/* Now that we know how many display modes to expect,
112
enumerate them again and save the information in
113
the list we allocated above. */
116
while (EnumDisplaySettings(NULL, mode, &dm)) {
117
/* Try to reject any display settings that seem unplausible. */
118
if (dm.dmPelsWidth >= MIN_WIDTH &&
119
(dm.dmDisplayFrequency == 0 ||
120
dm.dmDisplayFrequency >= MIN_FREQUENCY)) {
121
dmodes[i].devmode = dm;
122
dmodes[i].valid = 1; /* XXX Not used for now. */
123
dmodes[i].cap[DM_WIDTH] = dm.dmPelsWidth;
124
dmodes[i].cap[DM_HEIGHT] = dm.dmPelsHeight;
125
dmodes[i].cap[DM_PIXEL_DEPTH] = dm.dmBitsPerPel;
126
if (dm.dmDisplayFrequency == 0) {
127
/* Guess a reasonable guess. */
128
/* Lame Windows 95 version of EnumDisplaySettings. */
129
dmodes[i].cap[DM_HERTZ] = 60;
131
dmodes[i].cap[DM_HERTZ] = dm.dmDisplayFrequency;
138
assert(i == ndmodes);
143
/* X Windows version of initGameModeSupport. */
145
initGameModeSupport(void)
148
/* ndmodes is initially -1 to indicate no
149
dmodes allocated yet. */
153
/* Determine how many display modes there are. */
159
/* This routine is based on similiar code in glut_dstr.c */
161
findMatch(DisplayMode * dmodes, int ndmodes,
162
Criterion * criteria, int ncriteria)
165
int *bestScore, *thisScore;
166
int i, j, numok, result = 0, worse, better;
169
numok = 1; /* "num" capability is indexed from 1,
172
/* XXX alloca canidate. */
173
bestScore = (int *) malloc(ncriteria * sizeof(int));
175
__glutFatalError("out of memory.");
177
for (j = 0; j < ncriteria; j++) {
178
/* Very negative number. */
179
bestScore[j] = -32768;
182
/* XXX alloca canidate. */
183
thisScore = (int *) malloc(ncriteria * sizeof(int));
185
__glutFatalError("out of memory.");
188
for (i = 0; i < ndmodes; i++) {
189
if (dmodes[i].valid) {
193
for (j = 0; j < ncriteria; j++) {
194
int cap, cvalue, dvalue;
196
cap = criteria[j].capability;
197
cvalue = criteria[j].value;
201
dvalue = dmodes[i].cap[cap];
205
printf(" %s %s %d to %d\n",
206
capstr[cap], compstr[criteria[j].comparison], cvalue, dvalue);
208
switch (criteria[j].comparison) {
210
result = cvalue == dvalue;
214
result = cvalue != dvalue;
218
result = dvalue < cvalue;
219
thisScore[j] = dvalue - cvalue;
222
result = dvalue > cvalue;
223
thisScore[j] = dvalue - cvalue;
226
result = dvalue <= cvalue;
227
thisScore[j] = dvalue - cvalue;
230
result = (dvalue >= cvalue);
231
thisScore[j] = dvalue - cvalue;
234
result = dvalue >= cvalue;
235
thisScore[j] = cvalue - dvalue;
241
printf(" result=%d score=%d bestScore=%d\n", result, thisScore[j], bestScore[j]);
245
if (better || thisScore[j] > bestScore[j]) {
247
} else if (thisScore[j] == bestScore[j]) {
262
if (better && !worse) {
264
for (j = 0; j < ncriteria; j++) {
265
bestScore[j] = thisScore[j];
280
* Parses strings in the form of:
288
* NOTE that @ before : is not parsed.
291
specialCaseParse(char *word, Criterion * criterion, int mask)
293
char *xstr, *response;
295
int width, height, bpp, hertz;
308
/* The WWWxHHH case. */
309
if (mask & (1 << DM_WIDTH)) {
312
xstr = strpbrk(&word[1], "x");
314
width = (int) strtol(word, &response, 0);
315
if (response == word || response[0] != 'x') {
316
/* Not a valid number OR needs to be followed by 'x'. */
319
height = (int) strtol(&xstr[1], &response, 0);
320
if (response == &xstr[1]) {
321
/* Not a valid number. */
324
criterion[0].capability = DM_WIDTH;
325
criterion[0].comparison = EQ;
326
criterion[0].value = width;
327
criterion[1].capability = DM_HEIGHT;
328
criterion[1].comparison = EQ;
329
criterion[1].value = height;
330
got = specialCaseParse(response,
331
&criterion[2], 1 << DM_WIDTH);
341
if (mask & (1 << DM_PIXEL_DEPTH)) {
344
bpp = (int) strtol(&word[1], &response, 0);
345
if (response == &word[1]) {
346
/* Not a valid number. */
349
criterion[0].capability = DM_PIXEL_DEPTH;
350
criterion[0].comparison = EQ;
351
criterion[0].value = bpp;
352
got = specialCaseParse(response,
353
&criterion[1], (1 << DM_WIDTH) | (1 << DM_PIXEL_DEPTH));
361
if (mask & (1 << DM_HERTZ)) {
364
hertz = (int) strtol(&word[1], &response, 0);
365
if (response == &word[1]) {
366
/* Not a valid number. */
369
criterion[0].capability = DM_HERTZ;
370
criterion[0].comparison = EQ;
371
criterion[0].value = hertz;
372
got = specialCaseParse(response,
373
&criterion[1], ~DM_HERTZ);
385
/* This routine is based on similiar code in glut_dstr.c */
387
parseCriteria(char *word, Criterion * criterion)
389
char *cstr, *vstr, *response;
390
int comparator, value = 0;
392
cstr = strpbrk(word, "=><!~");
404
if (cstr[1] == '=') {
413
if (cstr[1] == '=') {
422
if (cstr[1] == '=') {
432
value = (int) strtol(vstr, &response, 0);
433
if (response == vstr) {
434
/* Not a valid number. */
443
if (!strcmp(word, "bpp")) {
444
criterion[0].capability = DM_PIXEL_DEPTH;
445
if (comparator == NONE) {
448
criterion[0].comparison = comparator;
449
criterion[0].value = value;
455
if (!strcmp(word, "height")) {
456
criterion[0].capability = DM_HEIGHT;
457
if (comparator == NONE) {
460
criterion[0].comparison = comparator;
461
criterion[0].value = value;
465
if (!strcmp(word, "hertz")) {
466
criterion[0].capability = DM_HERTZ;
467
if (comparator == NONE) {
470
criterion[0].comparison = comparator;
471
criterion[0].value = value;
477
if (!strcmp(word, "num")) {
478
criterion[0].capability = DM_NUM;
479
if (comparator == NONE) {
482
criterion[0].comparison = comparator;
483
criterion[0].value = value;
489
if (!strcmp(word, "width")) {
490
criterion[0].capability = DM_WIDTH;
491
if (comparator == NONE) {
494
criterion[0].comparison = comparator;
495
criterion[0].value = value;
501
if (comparator == NONE) {
502
return specialCaseParse(word, criterion, 0);
507
/* This routine is based on similiar code in glut_dstr.c */
509
parseDisplayString(const char *display, int *ncriteria)
511
Criterion *criteria = NULL;
515
copy = __glutStrdup(display);
516
/* Attempt to estimate how many criteria entries should be
519
word = strtok(copy, " \t");
522
word = strtok(NULL, " \t");
524
/* Allocate number of words of criteria. A word
525
could contain as many as four criteria in the
526
worst case. Example: 800x600:16@60 */
527
criteria = (Criterion *) malloc(4 * n * sizeof(Criterion));
529
__glutFatalError("out of memory.");
532
/* Re-copy the copy of the display string. */
533
strcpy(copy, display);
536
word = strtok(copy, " \t");
538
parsed = parseCriteria(word, &criteria[n]);
542
__glutWarning("Unrecognized game mode string word: %s (ignoring)\n", word);
544
word = strtok(NULL, " \t");
553
glutGameModeString(const char *string)
558
initGameModeSupport();
559
criteria = parseDisplayString(string, &ncriteria);
560
currentDm = findMatch(dmodes, ndmodes, criteria, ncriteria);
565
glutEnterGameMode(void)
571
if (__glutMappedMenu) {
572
__glutFatalUsage("entering game mode not allowed while menus in use");
574
if (__glutGameModeWindow) {
575
/* Already in game mode, so blow away game mode
576
window so apps can change resolutions. */
577
window = __glutGameModeWindow;
578
/* Setting the game mode window to NULL tricks
579
the window destroy code into not undoing the
580
screen display change since we plan on immediately
581
doing another mode change. */
582
__glutGameModeWindow = NULL;
583
__glutDestroyWindow(window, window);
586
/* Assume default screen size until we find out if we
587
can actually change the display settings. */
588
width = __glutScreenWidth;
589
height = __glutScreenHeight;
594
static int registered = 0;
596
status = ChangeDisplaySettings(¤tDm->devmode,
598
if (status == DISP_CHANGE_SUCCESSFUL) {
599
__glutDisplaySettingsChanged = 1;
600
width = currentDm->cap[DM_WIDTH];
601
height = currentDm->cap[DM_HEIGHT];
603
atexit(__glutCloseDownGameMode);
607
/* Switch back to default resolution. */
608
ChangeDisplaySettings(NULL, 0);
613
window = __glutCreateWindow(NULL, 0, 0,
614
width, height, /* game mode */ 1);
617
#if !defined(_WIN32) && !defined(__OS2__)
618
if (__glutMotifHints == None) {
619
__glutMotifHints = XSGIFastInternAtom(__glutDisplay, "_MOTIF_WM_HINTS",
620
SGI_XA__MOTIF_WM_HINTS, 0);
621
if (__glutMotifHints == None) {
622
__glutWarning("Could not intern X atom for _MOTIF_WM_HINTS.");
626
/* Game mode window is a toplevel window. */
627
XSetWMProtocols(__glutDisplay, win, &__glutWMDeleteWindow, 1);
630
/* Schedule the fullscreen property to be added and to
631
make sure the window is configured right. Win32
632
doesn't need this. */
633
window->desiredX = 0;
634
window->desiredY = 0;
635
window->desiredWidth = width;
636
window->desiredHeight = height;
637
window->desiredConfMask |= CWX | CWY | CWWidth | CWHeight;
639
/* Win32 does not want to use GLUT_FULL_SCREEN_WORK
640
for game mode because we need to be maximizing
641
the window in game mode, not just sizing it to
642
take up the full screen. The Win32-ness of game
643
mode happens when you pass 1 in the gameMode parameter
644
to __glutCreateWindow above. A gameMode of creates
645
a WS_POPUP window, not a standard WS_OVERLAPPEDWINDOW
646
window. WS_POPUP ensures the taskbar is hidden. */
647
__glutPutOnWorkList(window,
648
GLUT_CONFIGURE_WORK);
650
__glutPutOnWorkList(window,
651
GLUT_CONFIGURE_WORK | GLUT_FULL_SCREEN_WORK);
654
__glutGameModeWindow = window;
655
return window->num + 1;
659
glutGameModeGet(GLenum mode)
662
case GLUT_GAME_MODE_ACTIVE:
663
return __glutGameModeWindow != NULL;
664
case GLUT_GAME_MODE_POSSIBLE:
665
return currentDm != NULL;
666
case GLUT_GAME_MODE_WIDTH:
667
return currentDm ? currentDm->cap[DM_WIDTH] : -1;
668
case GLUT_GAME_MODE_HEIGHT:
669
return currentDm ? currentDm->cap[DM_HEIGHT] : -1;
670
case GLUT_GAME_MODE_PIXEL_DEPTH:
671
return currentDm ? currentDm->cap[DM_PIXEL_DEPTH] : -1;
672
case GLUT_GAME_MODE_REFRESH_RATE:
673
return currentDm ? currentDm->cap[DM_HERTZ] : -1;
674
case GLUT_GAME_MODE_DISPLAY_CHANGED:
675
return __glutDisplaySettingsChanged;
b'\\ No newline at end of file'