Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / libs / glut / glutGameMode.cpp
blobdada4212ac444e5ad6149652470337a79ce226cb
1 /*
2 * Copyright 2010, Haiku Inc.
3 * Authors:
4 * Philippe Houdoin <phoudoin %at% haiku-os %dot% org>
6 * Distributed under the terms of the MIT License.
7 */
10 #include "glutGameMode.h"
11 #include "glutint.h"
12 #include "glutState.h"
14 #include <GL/glut.h>
15 #include <String.h>
16 #include <stdio.h>
17 #include <stdlib.h>
20 // GlutGameMode class
22 GlutGameMode::GlutGameMode()
24 fActive(false),
25 fDisplayChanged(false),
26 fWidth(-1),
27 fHeight(-1),
28 fPixelDepth(-1),
29 fRefreshRate(-1),
30 fModesList(NULL),
31 fModesCount(0),
32 fGameModeWorkspace(-1),
33 fGameModeWindow(0),
34 fPreviousWindow(0)
39 GlutGameMode::~GlutGameMode()
41 free(fModesList);
45 status_t
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
54 "%1$ix%2$i", // WxH
55 ":%3$i@%4$i", // :Bpp@Hz
56 ":%3$i", // :Bpp
57 "@%4$i", // @Hz
58 NULL
61 // Find matching string format template, if any
62 for (int i=0; templates[i]; i++) {
63 // count expected arguments in this template
64 int expectedArgs = 0;
65 const char *p = templates[i];
66 while (*p) {
67 if (*p++ == '%')
68 expectedArgs++;
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");
78 return B_OK;
82 return B_BAD_VALUE;
86 bool
87 GlutGameMode::IsPossible()
89 display_mode* mode = _FindMatchingMode();
90 return mode != NULL;
94 status_t
95 GlutGameMode::Enter()
97 display_mode* mode = _FindMatchingMode();
98 if (!mode)
99 return B_BAD_VALUE;
101 BScreen screen;
102 if (!fActive) {
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);
110 if (status != B_OK)
111 return status;
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)
122 return Leave();
123 } else
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)
130 // Hum?!
131 return B_ERROR;
133 // Give it some useless title, except for debugging (thread name).
134 BString 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;
147 fActive = true;
149 return B_OK;
153 status_t
154 GlutGameMode::Leave()
156 if (!fActive)
157 return B_OK;
159 if (fGameModeWorkspace < 0)
160 return B_ERROR;
162 if (fGameModeWindow) {
163 glutDestroyWindow(fGameModeWindow);
164 fGameModeWindow = 0;
165 if (fPreviousWindow)
166 glutSetWindow(fPreviousWindow);
169 if (_CompareModes(&fOriginalMode, &fCurrentMode)) {
170 // Restore original display mode
171 BScreen screen;
172 // Make restored mode the default one,
173 // as it was before entering game mode...
174 screen.SetMode(fGameModeWorkspace, &fOriginalMode, true);
177 fActive = false;
178 return B_OK;
182 display_mode*
183 GlutGameMode::_FindMatchingMode()
185 if (fWidth == -1 && fHeight == -1 && fPixelDepth == -1
186 && fRefreshRate == -1)
187 // nothing to match!
188 return NULL;
190 if (!fModesList) {
191 // Lazy retrieval of supported modes...
192 BScreen screen;
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);
196 } else {
197 // bad luck, no modes can be retrieved!
198 fModesList = NULL;
199 fModesCount = 0;
203 if (!fModesList)
204 return NULL;
206 float bestRefreshDiff = 999999;
207 int bestMode = -1;
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)
216 continue;
218 if (fHeight > 0 && fModesList[i].virtual_height != fHeight)
219 continue;
221 if (fPixelDepth > 0
222 && _GetModePixelDepth(&fModesList[i]) != fPixelDepth)
223 continue;
225 float refreshDiff = fabs(_GetModeRefreshRate(&fModesList[i])
226 - fRefreshRate);
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;
231 bestMode = i;
233 continue;
236 // Hey, this one match everything!
237 return &fModesList[i];
240 if (bestMode == -1)
241 return NULL;
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;
256 default: return 0;
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
292 void APIENTRY
293 glutGameModeString(const char* string)
295 gState.gameMode.Set(string);
299 int APIENTRY
300 glutEnterGameMode(void)
302 return gState.gameMode.Enter() == B_OK;
306 void APIENTRY
307 glutLeaveGameMode(void)
309 gState.gameMode.Leave();
313 int APIENTRY
314 glutGameModeGet(GLenum pname)
316 switch( 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();
338 default:
339 __glutWarning( "Unknown gamemode get: %d", pname );
340 return -1;
345 void APIENTRY
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()
359 // TODO