4 * Various freeglut initialization functions.
6 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
7 * Written by Pawel W. Olszta, <olszta@sourceforge.net>
8 * Creation date: Thu Dec 2 1999
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
24 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #define FREEGLUT_BUILDING_LIB
29 #include <GL/freeglut.h>
30 #include "fg_internal.h"
33 * TODO BEFORE THE STABLE RELEASE:
35 * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific
36 * deinitialization done
37 * glutInitDisplayString() -- display mode string parsing
39 * Wouldn't it be cool to use gettext() for error messages? I just love
40 * bash saying "nie znaleziono pliku" instead of "file not found" :)
41 * Is gettext easily portable?
44 /* -- GLOBAL VARIABLES ----------------------------------------------------- */
47 * A structure pointed by fgDisplay holds all information
48 * regarding the display, screen, root window etc.
50 SFG_Display fgDisplay;
53 * The settings for the current freeglut session
55 SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
56 { 300, 300, GL_TRUE }, /* Size */
57 GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
58 GL_FALSE, /* Initialised */
59 GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */
60 GL_FALSE, /* ForceIconic */
61 GL_FALSE, /* UseCurrentContext */
62 GL_FALSE, /* GLDebugSwitch */
63 GL_FALSE, /* XSyncSwitch */
64 GLUT_KEY_REPEAT_ON, /* KeyRepeat */
65 INVALID_MODIFIERS, /* Modifiers */
70 { NULL, NULL }, /* Timers */
71 { NULL, NULL }, /* FreeTimers */
72 NULL, /* IdleCallback */
74 NULL, /* MenuStateCallback */
75 NULL, /* MenuStatusCallback */
76 { -1, -1, GL_TRUE }, /* GameModeSize */
77 -1, /* GameModeDepth */
78 -1, /* GameModeRefresh */
79 GLUT_ACTION_EXIT, /* ActionOnWindowClose */
80 GLUT_EXEC_STATE_INIT, /* ExecState */
81 NULL, /* ProgramName */
82 GL_FALSE, /* JoysticksInitialised */
83 0, /* NumActiveJoysticks */
84 GL_FALSE, /* InputDevsInitialised */
85 0, /* MouseWheelTicks */
86 1, /* AuxiliaryBufferNumber */
88 GL_FALSE, /* SkipStaleMotion */
89 1, /* OpenGL context MajorVersion */
90 0, /* OpenGL context MinorVersion */
91 0, /* OpenGL ContextFlags */
92 0, /* OpenGL ContextProfile */
95 NULL /* WarningFunc */
99 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
101 extern void fgPlatformInitialize( const char* displayName );
102 extern void fgPlatformDeinitialiseInputDevices ( void );
103 extern void fgPlatformCloseDisplay ( void );
104 extern void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext );
106 void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
109 int i, j, argc = *pargc;
112 /* check if GLUT_FPS env var is set */
113 const char *fps = getenv( "GLUT_FPS" );
118 sscanf( fps, "%d", &interval );
121 fgState.FPSInterval = 5000; /* 5000 millisecond default */
123 fgState.FPSInterval = interval;
127 *pDisplayName = getenv( "DISPLAY" );
129 for( i = 1; i < argc; i++ )
131 if( strcmp( argv[ i ], "-display" ) == 0 )
134 fgError( "-display parameter must be followed by display name" );
136 *pDisplayName = argv[ i ];
138 argv[ i - 1 ] = NULL;
142 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
145 fgError( "-geometry parameter must be followed by window "
146 "geometry settings" );
148 *pGeometry = argv[ i ];
150 argv[ i - 1 ] = NULL;
154 else if( strcmp( argv[ i ], "-direct" ) == 0)
156 if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
157 fgError( "parameters ambiguity, -direct and -indirect "
158 "cannot be both specified" );
160 fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
164 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
166 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
167 fgError( "parameters ambiguity, -direct and -indirect "
168 "cannot be both specified" );
170 fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
174 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
176 fgState.ForceIconic = GL_TRUE;
180 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
182 fgState.GLDebugSwitch = GL_TRUE;
186 else if( strcmp( argv[ i ], "-sync" ) == 0 )
188 fgState.XSyncSwitch = GL_TRUE;
194 /* Compact {argv}. */
195 for( i = j = 1; i < *pargc; i++, j++ )
197 /* Guaranteed to end because there are "*pargc" arguments left */
198 while ( argv[ j ] == NULL )
201 argv[ i ] = argv[ j ];
204 #endif /* _WIN32_WCE */
209 void fghCloseInputDevices ( void )
211 if ( fgState.JoysticksInitialised )
214 if ( fgState.InputDevsInitialised )
215 fgInputDeviceClose( );
220 * Perform the freeglut deinitialization...
222 void fgDeinitialize( void )
226 if( !fgState.Initialised )
231 /* If we're in game mode, we want to leave game mode */
232 if( fgStructure.GameModeWindow ) {
236 /* If there was a menu created, destroy the rendering context */
237 if( fgStructure.MenuContext )
239 fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
240 free( fgStructure.MenuContext );
241 fgStructure.MenuContext = NULL;
244 fgDestroyStructure( );
246 while( ( timer = fgState.Timers.First) )
248 fgListRemove( &fgState.Timers, &timer->Node );
252 while( ( timer = fgState.FreeTimers.First) )
254 fgListRemove( &fgState.FreeTimers, &timer->Node );
258 fgPlatformDeinitialiseInputDevices ();
260 fgState.MouseWheelTicks = 0;
262 fgState.MajorVersion = 1;
263 fgState.MinorVersion = 0;
264 fgState.ContextFlags = 0;
265 fgState.ContextProfile = 0;
267 fgState.Initialised = GL_FALSE;
269 fgState.Position.X = -1;
270 fgState.Position.Y = -1;
271 fgState.Position.Use = GL_FALSE;
273 fgState.Size.X = 300;
274 fgState.Size.Y = 300;
275 fgState.Size.Use = GL_TRUE;
277 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
279 fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
280 fgState.ForceIconic = GL_FALSE;
281 fgState.UseCurrentContext = GL_FALSE;
282 fgState.GLDebugSwitch = GL_FALSE;
283 fgState.XSyncSwitch = GL_FALSE;
284 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
285 fgState.ExecState = GLUT_EXEC_STATE_INIT;
287 fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
288 fgState.Modifiers = INVALID_MODIFIERS;
290 fgState.GameModeSize.X = -1;
291 fgState.GameModeSize.Y = -1;
292 fgState.GameModeDepth = -1;
293 fgState.GameModeRefresh = -1;
295 fgListInit( &fgState.Timers );
296 fgListInit( &fgState.FreeTimers );
298 fgState.IdleCallback = NULL;
299 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
300 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
302 fgState.SwapCount = 0;
303 fgState.SwapTime = 0;
304 fgState.FPSInterval = 0;
306 if( fgState.ProgramName )
308 free( fgState.ProgramName );
309 fgState.ProgramName = NULL;
312 fgPlatformCloseDisplay ();
314 fgState.Initialised = GL_FALSE;
318 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
319 #if defined(NEED_XPARSEGEOMETRY_IMPL)
320 # include "util/xparsegeometry_repl.h"
324 * Perform initialization. This usually happens on the program startup
325 * and restarting after glutMainLoop termination...
327 void FGAPIENTRY glutInit( int* pargc, char** argv )
329 char* displayName = NULL;
330 char* geometry = NULL;
331 if( fgState.Initialised )
332 fgError( "illegal glutInit() reinitialization attempt" );
334 if (pargc && *pargc && argv && *argv && **argv)
336 fgState.ProgramName = strdup (*argv);
338 if( !fgState.ProgramName )
339 fgError ("Could not allocate space for the program's name.");
342 fgCreateStructure( );
345 fgState.Time = fgSystemTime();
347 fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
350 * Have the display created now. If there wasn't a "-display"
351 * in the program arguments, we will use the DISPLAY environment
352 * variable for opening the X display (see code above):
354 fgPlatformInitialize( displayName );
357 * Geometry parsing deferred until here because we may need the screen
363 unsigned int parsedWidth, parsedHeight;
364 int mask = XParseGeometry( geometry,
365 &fgState.Position.X, &fgState.Position.Y,
366 &parsedWidth, &parsedHeight );
367 /* TODO: Check for overflow? */
368 fgState.Size.X = parsedWidth;
369 fgState.Size.Y = parsedHeight;
371 if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
372 fgState.Size.Use = GL_TRUE;
374 if( mask & XNegative )
375 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
377 if( mask & YNegative )
378 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
380 if( (mask & (XValue|YValue)) == (XValue|YValue) )
381 fgState.Position.Use = GL_TRUE;
386 * Undoes all the "glutInit" stuff
388 void FGAPIENTRY glutExit ( void )
394 * Sets the default initial window position for new windows
396 void FGAPIENTRY glutInitWindowPosition( int x, int y )
398 fgState.Position.X = x;
399 fgState.Position.Y = y;
401 if( ( x >= 0 ) && ( y >= 0 ) )
402 fgState.Position.Use = GL_TRUE;
404 fgState.Position.Use = GL_FALSE;
408 * Sets the default initial window size for new windows
410 void FGAPIENTRY glutInitWindowSize( int width, int height )
412 fgState.Size.X = width;
413 fgState.Size.Y = height;
415 if( ( width > 0 ) && ( height > 0 ) )
416 fgState.Size.Use = GL_TRUE;
418 fgState.Size.Use = GL_FALSE;
422 * Sets the default display mode for all new windows
424 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
426 /* We will make use of this value when creating a new OpenGL context... */
427 fgState.DisplayMode = displayMode;
431 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
433 static char* Tokens[] =
435 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
436 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
437 "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
438 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
439 "xtruecolor", "xdirectcolor",
440 "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
441 "xtruecolour", "xdirectcolour", "borderless", "aux"
443 #define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
445 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
447 int glut_state_flag = 0 ;
449 * Unpack a lot of options from a character string. The options are
450 * delimited by blanks or tabs.
453 size_t len = strlen ( displayMode );
454 char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
455 memcpy ( buffer, displayMode, len );
458 token = strtok ( buffer, " \t" );
462 /* Process this token */
465 /* Temporary fix: Ignore any length specifications and at least
466 * process the basic token
467 * TODO: Fix this permanently
469 size_t cleanlength = strcspn ( token, "=<>~!" );
471 for ( i = 0; i < NUM_TOKENS; i++ )
473 if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
478 case 0 : /* "alpha": Alpha color buffer precision in bits */
479 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
482 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
486 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
487 in bits with zero bits alpha */
488 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
491 case 3 : /* "blue": Blue color buffer precision in bits */
494 case 4 : /* "buffer": Number of bits in the color index color buffer
498 case 5 : /* "conformant": Boolean indicating if the frame buffer
499 configuration is conformant or not */
502 case 6 : /* "depth": Number of bits of precision in the depth buffer */
503 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
506 case 7 : /* "double": Boolean indicating if the color buffer is
508 glut_state_flag |= GLUT_DOUBLE ;
511 case 8 : /* "green": Green color buffer precision in bits */
514 case 9 : /* "index": Boolean if the color model is color index or not
516 glut_state_flag |= GLUT_INDEX ;
519 case 10 : /* "num": A special capability name indicating where the
520 value represents the Nth frame buffer configuration
521 matching the description string */
524 case 11 : /* "red": Red color buffer precision in bits */
527 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
528 the RGBA color buffer */
529 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
532 case 13 : /* "rgb": Number of bits of red, green, and blue in the
533 RGBA color buffer with zero bits alpha */
534 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
537 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
538 bits of green, blue (alpha not specified) of color buffer
540 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
543 case 15 : /* "stencil": Number of bits in the stencil buffer */
544 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
547 case 16 : /* "single": Boolean indicate the color buffer is single
549 glut_state_flag |= GLUT_SINGLE ;
552 case 17 : /* "stereo": Boolean indicating the color buffer supports
553 OpenGL-style stereo */
554 glut_state_flag |= GLUT_STEREO ;
557 case 18 : /* "samples": Indicates the number of multisamples to use
558 based on GLX's SGIS_multisample extension (for
560 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
563 case 19 : /* "slow": Boolean indicating if the frame buffer
564 configuration is slow or not */
567 case 20 : /* "win32pdf": (incorrect spelling but was there before */
568 case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
570 #if TARGET_HOST_MS_WINDOWS
574 case 22 : /* "xvisual": matches the X visual ID by number */
575 #if TARGET_HOST_POSIX_X11
579 case 23 : /* "xstaticgray": */
580 case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
581 configuration's X visual is of type StaticGray */
582 #if TARGET_HOST_POSIX_X11
586 case 24 : /* "xgrayscale": */
587 case 30 : /* "xgreyscale": boolean indicating if the frame buffer
588 configuration's X visual is of type GrayScale */
589 #if TARGET_HOST_POSIX_X11
593 case 25 : /* "xstaticcolor": */
594 case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
595 configuration's X visual is of type StaticColor */
596 #if TARGET_HOST_POSIX_X11
600 case 26 : /* "xpseudocolor": */
601 case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
602 configuration's X visual is of type PseudoColor */
603 #if TARGET_HOST_POSIX_X11
607 case 27 : /* "xtruecolor": */
608 case 33 : /* "xtruecolour": boolean indicating if the frame buffer
609 configuration's X visual is of type TrueColor */
610 #if TARGET_HOST_POSIX_X11
614 case 28 : /* "xdirectcolor": */
615 case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
616 configuration's X visual is of type DirectColor */
617 #if TARGET_HOST_POSIX_X11
621 case 35 : /* "borderless": windows should not have borders */
622 glut_state_flag |= GLUT_BORDERLESS;
625 case 36 : /* "aux": some number of aux buffers */
626 glut_state_flag |= GLUT_AUX;
629 case 37 : /* Unrecognized */
630 fgWarning ( "WARNING - Display string token not recognized: %s",
635 token = strtok ( NULL, " \t" );
640 /* We will make use of this value when creating a new OpenGL context... */
641 fgState.DisplayMode = glut_state_flag;
644 /* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
646 void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
648 /* We will make use of these value when creating a new OpenGL context... */
649 fgState.MajorVersion = majorVersion;
650 fgState.MinorVersion = minorVersion;
654 void FGAPIENTRY glutInitContextFlags( int flags )
656 /* We will make use of this value when creating a new OpenGL context... */
657 fgState.ContextFlags = flags;
660 void FGAPIENTRY glutInitContextProfile( int profile )
662 /* We will make use of this value when creating a new OpenGL context... */
663 fgState.ContextProfile = profile;
666 /* -------------- User Defined Error/Warning Handler Support -------------- */
669 * Sets the user error handler (note the use of va_list for the args to the fmt)
671 void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
673 /* This allows user programs to handle freeglut errors */
674 fgState.ErrorFunc = vfgError;
678 * Sets the user warning handler (note the use of va_list for the args to the fmt)
680 void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
682 /* This allows user programs to handle freeglut warnings */
683 fgState.WarningFunc = vfgWarning;
686 /*** END OF FILE ***/