Game Mode
Prev: The Code So Far V | Next: The Code So Far VI |
According to the man pages for the GLUT distribution, the GLUT game mode is designed to enable high-performance full screen rendering. However there is always a catch: some GLUT functionality, such as pop-up menus and subwindows, is disabled to increase performance. In this section an introduction to GLUT’s gamemode is provided. My source of information for this tutorial were available examples, the man pages, and GLUT’s source font. Since I found no official documentation, nor another tutorial covering the subject I do not guarantee that everything in here is 100% correct. I did build a set of working demos that provided me with some insight on how the game mode works, but due to limited testing on different hardware configurations there may be some imprecise or incorrect statements in here. If you run into problems when applying the concepts in this tutorial please give me a description of the problem so that I can look into it. If you’re alread familiar with GLUT’s game mode and find something in here which is not right I would appreciate a comment so that I can fix the problem.
OK, now that I have done my little “disclaimer”, we might as well start this tutorial. The first thing we have to do is to define the settings for the game mode, i.e. full screen. These settings may include the screen resolution, the pixel depth and the refresh frequency. To put it in other words, we can set whatever resolution we want (within the limits imposed by the hardware), i.e. we are not limited to set the full screen mode at the current resolution.
These settings for full screen mode are specified on a string. The format is as follows
“WxH:Bpp@Rr”
Parameters:
- W – the screen width in pixels
- H – the screen height in pixels
- Bpp – the number of bits per pixel
- Rr – the vertical refresh rate in hertz
Before we go any further, note that these settings are only a request to the hardware. If the specified mode is unavailable then the settings are ignored.
Examples:
- “800×600:32@100” – screen size 800×600; true color (32 bits); 100Hz vertical
- “640×480:16@75” – screen size 640×480; high color (16 bits); 75 hertz
Specifying all the components is a little bit stressfull. Although we usually have a clear idea of the screen resolution, and sometimes we may require a particular color mode, the refresh rate may be trickier. Fortunately we don’t have to specify everything. We can leave some bits out and let GLUT fill in the blanks. The following template strings for partially specifying the desired full screen settings are allowed:
- “WxH”
- “WxH:Bpp”
- “WxH@Rr”
- “@Rr”
- “:Bpp”
- “Bpp:@Rr”
Basically GLUT can handle all combinations as long as the order between them is preserved. So for instance specifying the refresh rate before the number of bits per pixel is not allowed.
Suppose that we wanted to set the screen resolution but didn’t care about the pixel depth or refresh rate, then we can write something like “800×600”.
If on the other hand we wanted just to set the full screen mode at the current resolution but with a pixel depth of 32 bits, we could write “:32”.
These few examples do not show the full capabilities of the full screen settings string. We can use any of the string templates presented above.
Ready to move on? OK. First we must provide GLUT with the requested settings for the full screen mode. The GLUT’s function to set the game mode is glutGameModeString. The syntax is as follows:
void glutGameModeString(const char *string);
Parameters:
- string – a string containing the desired settings as specified above
GLUT does validate the argument of glutGameModeString. Although the function doesn’t return an error code, we can check if the mode specified is OK. GLUT provides a function that, amongst other possibilities, allows us to check if the specified mode is valid. The syntax of the function is:
int glutGameModeGet(GLenum info);
Parameters:
- info – the requested information
In order to check if the supplied mode is valid, info takes the value of a GLUTs pre defined constant: GLUT_GAME_MODE_POSSIBLE.
In this case, the return value indicates if the mode specified is valid, a non-zero value means OK. However note that in GLUTs man pages there is a warning stating that even if the mode is possible there is no guarantee that the screen settings will be successfully updated.
Assuming that we got a non-zero value as a return value then we can enter, or at least attempt to enter, the game mode with glutEnterGameMode. This function actually sets the screen to the requested settings if they are valid. The syntax is as follows:
void glutEnterGameMode(void);
The main function to initialize a GLUT application in game mode at 800 by 600 could be something like this:
int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); /* glutInitWindowPosition(100,100); glutInitWindowSize(640,360); glutCreateWindow("SnowMen from Lighthouse3D"); */ // setting the game mode replaces the above // calls to set the window size and position. glutGameModeString("800x600:32"); // enter full screen if (glutGameModeGet(GLUT_GAME_MODE_POSSIBLE)) glutEnterGameMode(); else { printf("The select mode is not available\n"); exit(1); } // register all callbacks init(); glutMainLoop(); return 1; }}
The function init should register all the necessary callbacks as well as perform the openGL required initializations, for instance we could write something like this:
void init() { // register callbacks glutDisplayFunc(renderScene); glutReshapeFunc(changeSize); glutIdleFunc(renderScene); glutIgnoreKeyRepeat(1); glutKeyboardFunc(processNormalKeys); glutSpecialFunc(pressKey); glutSpecialUpFunc(releaseKey); glutMouseFunc(mouseButton); glutMotionFunc(mouseMove); // OpenGL init glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); }
It may be the case that we want to be able to switch between game mode and window mode during the application. The following piece of code assumes that we’re starting in window mode. The user can then press F1 to switch to game mode. F6 brings the user back to window mode. In this case the main function must define the window properties, register the callbacks, and enter the main loop.
Before we look at the code here goes the function that tells glut to leave game mode.
void glutLeaveGameMode(void);
The function that will process the special keys is the one that will perform the mode switch. The following function performs the required operations:
void pressKey(int key, int x, int y) { switch (key) { ... case GLUT_KEY_F1: // define resolution, color depth glutGameModeString("640x480:32"); // enter full screen if (glutGameModeGet(GLUT_GAME_MODE_POSSIBLE)) { glutEnterGameMode(); // register callbacks again init(); } break; case GLUT_KEY_F6: // return to default window glutLeaveGameMode(); break; } }
There is a detail which is very important in the function above, when we enter the game mode with glutEnterGameMode we must register the callbacks again, and redefine the OpenGL context. The game mode is just like a new window, with a different OpenGL and GLUT context. This implies that the callbacks for the window mode will have no effect in game mode. In order to use callback functions we must register them again. Furthermore, the OpenGL context needs to be defined again. For instance display lists created for the window mode need to be defined again when entering the game mode.
GLUT is an excellent API, and as such it also gives the programmer ways to query the current state of affairs. GLUT has a special function for querying the state settings for the game mode, glutGameModeGet. The syntax for this function was already introduced above when we mentioned that one possible value for the argument was GLUT_GAME_MODE_POSSIBLE.
There are several possibilities for the argument of glutGameModeGet that cover all the needs for correct game mode programming. The return values for each case are presented bellow:
- GLUT_GAME_MODE_ACTIVE – If the app is running in game mode then glutGameModeGet will return a non-zero value, if in window mode it will return zero.
- GLUT_GAME_MODE_POSSIBLE – As mentioned before this can be used to test the string which specifies the game mode setings. It is good policy to call glutGameModeGet with this value before entering game mode.
- GLUT_GAME_MODE_DISPLAY_CHANGED – As mentioned before when entering the game mode there is no guarantee that the display mode is indeed changed. This value can be used to test if the game mode was really entered. If we were previously already in game mode then this value can be used to test if the settings were changed.
- GLUT_GAME_MODE_WIDTH – returns the width of the screen
- GLUT_GAME_MODE_HEIGHT – returns the height of the screen.
- GLUT_GAME_MODE_PIXEL_DEPTH – returns the bits per pixel of the current mode.
- GLUT_GAME_MODE_REFRESH – the actual refresh rate in hertz.
The last four options are meaningful only if we are in game mode. These options will cause glutGameModeGet to return -1 if the latest string specifying the game mode settings is not valid, even if we are already in game mode. So for instance if we’re runnig an app in game mode at 640 by 480 and requested a change to 1600 by 1200, and the mode is not valid for the actual hardware configuration, then GLUT does not change the resolution and the game mode stays at 640 by 480. However when asking for the current height we’ll get -1 and not 480, although the actual height is 480.
The following code excert exemplifies the usage of glutGameModeGet.
if (glutGameModeGet(GLUT_GAME_MODE_ACTIVE) == 0) sprintf(currentMode,"Current Mode: Window"); else sprintf(currentMode, "Current Mode: Game Mode %dx%d at %d hertz, %d bpp", glutGameModeGet(GLUT_GAME_MODE_WIDTH), glutGameModeGet(GLUT_GAME_MODE_HEIGHT), glutGameModeGet(GLUT_GAME_MODE_REFRESH_RATE), glutGameModeGet(GLUT_GAME_MODE_PIXEL_DEPTH));
On the next page the source code for a complete example is provided.
Prev: The Code So Far V | Next: The Code So Far VI |
One Response to “Game Mode”
Leave a Reply Cancel reply
This site uses Akismet to reduce spam. Learn how your comment data is processed.
my glutGameModeGet(GLUT_GAME_MODE_POSSIBLE) returns true,
but it crashes at glutEnterGameMode();
maybe you know what happened?