2 * Copyright 2010, Haiku Inc.
4 * Philippe Houdoin <phoudoin %at% haiku-os %dot% org>
6 * Distributed under the terms of the MIT License.
10 #include "glutGameMode.h"
12 #include "glutState.h"
22 GlutGameMode::GlutGameMode()
25 fDisplayChanged(false),
32 fGameModeWorkspace(-1),
39 GlutGameMode::~GlutGameMode()
46 GlutGameMode::Set(const char* modeString
)
48 // String format: [WxH][:Bpp][@Hz]
50 const char* templates
[] = {
51 "%1$ix%2$i:%3$i@%4$i", // WxH:Bpp@Hz
52 "%1$ix%2$i:%3$i", // WxH:Bpp
53 "%1$ix%2$i@%4$i", // WxH@Hz
55 ":%3$i@%4$i", // :Bpp@Hz
61 // Find matching string format template, if any
62 for (int i
=0; templates
[i
]; i
++) {
63 // count expected arguments in this template
65 const char *p
= templates
[i
];
71 // printf("Trying %s pattern\n", templates[i]);
73 fWidth
= fHeight
= fPixelDepth
= fRefreshRate
= -1;
75 if (sscanf(modeString
, templates
[i
],
76 &fWidth
, &fHeight
, &fPixelDepth
, &fRefreshRate
) == expectedArgs
) {
77 // printf("match!\n");
87 GlutGameMode::IsPossible()
89 display_mode
* mode
= _FindMatchingMode();
97 display_mode
* mode
= _FindMatchingMode();
103 // First enter: remember this workspace original mode...
104 fGameModeWorkspace
= current_workspace();
105 screen
.GetMode(fGameModeWorkspace
, &fOriginalMode
);
108 // Don't make it new default mode for this workspace...
109 status_t status
= screen
.SetMode(fGameModeWorkspace
, mode
, false);
113 // Retrieve the new active display mode, which could be
114 // a sligth different than the one we asked for...
115 screen
.GetMode(fGameModeWorkspace
, &fCurrentMode
);
117 if (!fGameModeWindow
) {
118 // create a new window
119 fPreviousWindow
= glutGetWindow();
120 fGameModeWindow
= glutCreateWindow("glutGameMode");
121 if (!fGameModeWindow
)
124 // make sure it's the current window
125 glutSetWindow(fGameModeWindow
);
127 BDirectWindow
*directWindow
128 = dynamic_cast<BDirectWindow
*>(gState
.currentWindow
->Window());
129 if (directWindow
== NULL
)
133 // Give it some useless title, except for debugging (thread name).
135 name
<< "Game Mode " << fCurrentMode
.virtual_width
136 << "x" << fCurrentMode
.virtual_height
137 << ":" << _GetModePixelDepth(&fCurrentMode
)
138 << "@" << _GetModeRefreshRate(&fCurrentMode
);
140 // force the game mode window to fullscreen
141 directWindow
->Lock();
142 directWindow
->SetTitle(name
.String());
143 directWindow
->SetFullScreen(true);
144 directWindow
->Unlock();
146 fDisplayChanged
= true;
154 GlutGameMode::Leave()
159 if (fGameModeWorkspace
< 0)
162 if (fGameModeWindow
) {
163 glutDestroyWindow(fGameModeWindow
);
166 glutSetWindow(fPreviousWindow
);
169 if (_CompareModes(&fOriginalMode
, &fCurrentMode
)) {
170 // Restore original display mode
172 // Make restored mode the default one,
173 // as it was before entering game mode...
174 screen
.SetMode(fGameModeWorkspace
, &fOriginalMode
, true);
183 GlutGameMode::_FindMatchingMode()
185 if (fWidth
== -1 && fHeight
== -1 && fPixelDepth
== -1
186 && fRefreshRate
== -1)
191 // Lazy retrieval of supported modes...
193 if (screen
.GetModeList(&fModesList
, &fModesCount
) == B_OK
) {
194 // sort modes in decrease order (resolution, depth, frequency)
195 qsort(fModesList
, fModesCount
, sizeof(display_mode
), _CompareModes
);
197 // bad luck, no modes can be retrieved!
206 float bestRefreshDiff
= 999999;
208 for (uint32 i
=0; i
< fModesCount
; i
++) {
210 printf("[%ld]: %d x %d, %d Bpp, %d Hz\n", i
,
211 fModesList
[i
].virtual_width
, fModesList
[i
].virtual_height
,
212 _GetModePixelDepth(&fModesList
[i
]),
213 _GetModeRefreshRate(&fModesList
[i
]));
215 if (fWidth
> 0 && fModesList
[i
].virtual_width
!= fWidth
)
218 if (fHeight
> 0 && fModesList
[i
].virtual_height
!= fHeight
)
222 && _GetModePixelDepth(&fModesList
[i
]) != fPixelDepth
)
225 float refreshDiff
= fabs(_GetModeRefreshRate(&fModesList
[i
])
227 if (fRefreshRate
> 0 && (refreshDiff
> 0.006 * fRefreshRate
)) {
228 // not exactly the same, but maybe the best similar mode so far?
229 if (refreshDiff
< bestRefreshDiff
) {
230 bestRefreshDiff
= refreshDiff
;
236 // Hey, this one match everything!
237 return &fModesList
[i
];
243 return &fModesList
[bestMode
];
248 GlutGameMode::_GetModePixelDepth(const display_mode
* mode
)
250 switch (mode
->space
) {
251 case B_RGB32
: return 32;
252 case B_RGB24
: return 24;
253 case B_RGB16
: return 16;
254 case B_RGB15
: return 15;
255 case B_CMAP8
: return 8;
262 GlutGameMode::_GetModeRefreshRate(const display_mode
* mode
)
264 // we have to be catious as refresh rate cannot be controlled directly,
265 // so it suffers under rounding errors and hardware restrictions
266 return rint(10 * float(mode
->timing
.pixel_clock
* 1000)
267 / float(mode
->timing
.h_total
* mode
->timing
.v_total
)) / 10.0;
272 GlutGameMode::_CompareModes(const void* _mode1
, const void* _mode2
)
274 display_mode
*mode1
= (display_mode
*)_mode1
;
275 display_mode
*mode2
= (display_mode
*)_mode2
;
277 if (mode1
->virtual_width
!= mode2
->virtual_width
)
278 return mode2
->virtual_width
- mode1
->virtual_width
;
280 if (mode1
->virtual_height
!= mode2
->virtual_height
)
281 return mode2
->virtual_height
- mode1
->virtual_height
;
283 if (mode1
->space
!= mode2
->space
)
284 return _GetModePixelDepth(mode2
) - _GetModePixelDepth(mode1
);
286 return _GetModeRefreshRate(mode2
) - _GetModeRefreshRate(mode1
);
290 // #pragma mark GLUT game mode API
293 glutGameModeString(const char* string
)
295 gState
.gameMode
.Set(string
);
300 glutEnterGameMode(void)
302 return gState
.gameMode
.Enter() == B_OK
;
307 glutLeaveGameMode(void)
309 gState
.gameMode
.Leave();
314 glutGameModeGet(GLenum pname
)
317 case GLUT_GAME_MODE_ACTIVE
:
318 return gState
.gameMode
.IsActive();
320 case GLUT_GAME_MODE_POSSIBLE
:
321 return gState
.gameMode
.IsPossible();
323 case GLUT_GAME_MODE_WIDTH
:
324 return gState
.gameMode
.Width();
326 case GLUT_GAME_MODE_HEIGHT
:
327 return gState
.gameMode
.Height();
329 case GLUT_GAME_MODE_PIXEL_DEPTH
:
330 return gState
.gameMode
.PixelDepth();
332 case GLUT_GAME_MODE_REFRESH_RATE
:
333 return gState
.gameMode
.RefreshRate();
335 case GLUT_GAME_MODE_DISPLAY_CHANGED
:
336 return gState
.gameMode
.HasDisplayChanged();
339 __glutWarning( "Unknown gamemode get: %d", pname
);
346 glutForceJoystickFunc(void)
349 Forces a joystick poll and callback.
351 Forces the OpenGLUT joystick code to poll your
352 joystick(s) and to call your joystick callbacks
353 with the result. The operation completes, including
354 callbacks, before glutForceJoystickFunc() returns.
356 See also glutJoystickFunc()