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"
34 * TODO BEFORE THE STABLE RELEASE:
36 * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific
37 * deinitialization done
38 * glutInitDisplayString() -- display mode string parsing
40 * Wouldn't it be cool to use gettext() for error messages? I just love
41 * bash saying "nie znaleziono pliku" instead of "file not found" :)
42 * Is gettext easily portable?
45 /* -- GLOBAL VARIABLES ----------------------------------------------------- */
48 * A structure pointed by fgDisplay holds all information
49 * regarding the display, screen, root window etc.
51 SFG_Display fgDisplay;
54 * The settings for the current freeglut session
56 SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
57 { 300, 300, GL_TRUE }, /* Size */
58 GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
59 GL_FALSE, /* Initialised */
60 GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */
61 GL_FALSE, /* ForceIconic */
62 GL_FALSE, /* UseCurrentContext */
63 GL_FALSE, /* GLDebugSwitch */
64 GL_FALSE, /* XSyncSwitch */
65 GLUT_KEY_REPEAT_ON, /* KeyRepeat */
66 INVALID_MODIFIERS, /* Modifiers */
71 { NULL, NULL }, /* Timers */
72 { NULL, NULL }, /* FreeTimers */
73 NULL, /* IdleCallback */
75 NULL, /* MenuStateCallback */
76 NULL, /* MenuStatusCallback */
77 { -1, -1, GL_TRUE }, /* GameModeSize */
78 -1, /* GameModeDepth */
79 -1, /* GameModeRefresh */
80 GLUT_ACTION_EXIT, /* ActionOnWindowClose */
81 GLUT_EXEC_STATE_INIT, /* ExecState */
82 NULL, /* ProgramName */
83 GL_FALSE, /* JoysticksInitialised */
84 0, /* NumActiveJoysticks */
85 GL_FALSE, /* InputDevsInitialised */
86 0, /* MouseWheelTicks */
87 1, /* AuxiliaryBufferNumber */
89 GL_FALSE, /* SkipStaleMotion */
90 1, /* OpenGL context MajorVersion */
91 0, /* OpenGL context MinorVersion */
92 0, /* OpenGL ContextFlags */
93 0, /* OpenGL ContextProfile */
96 NULL /* WarningFunc */
100 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
102 extern void fgPlatformInitialize( const char* displayName );
103 extern void fgPlatformDeinitialiseInputDevices ( void );
104 extern void fgPlatformCloseDisplay ( void );
105 extern void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext );
107 void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
110 int i, j, argc = *pargc;
113 /* check if GLUT_FPS env var is set */
114 const char *fps = getenv( "GLUT_FPS" );
119 sscanf( fps, "%d", &interval );
122 fgState.FPSInterval = 5000; /* 5000 millisecond default */
124 fgState.FPSInterval = interval;
128 *pDisplayName = getenv( "DISPLAY" );
130 for( i = 1; i < argc; i++ )
132 if( strcmp( argv[ i ], "-display" ) == 0 )
135 fgError( "-display parameter must be followed by display name" );
137 *pDisplayName = argv[ i ];
139 argv[ i - 1 ] = NULL;
143 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
146 fgError( "-geometry parameter must be followed by window "
147 "geometry settings" );
149 *pGeometry = argv[ i ];
151 argv[ i - 1 ] = NULL;
155 else if( strcmp( argv[ i ], "-direct" ) == 0)
157 if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
158 fgError( "parameters ambiguity, -direct and -indirect "
159 "cannot be both specified" );
161 fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
165 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
167 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
168 fgError( "parameters ambiguity, -direct and -indirect "
169 "cannot be both specified" );
171 fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
175 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
177 fgState.ForceIconic = GL_TRUE;
181 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
183 fgState.GLDebugSwitch = GL_TRUE;
187 else if( strcmp( argv[ i ], "-sync" ) == 0 )
189 fgState.XSyncSwitch = GL_TRUE;
195 /* Compact {argv}. */
196 for( i = j = 1; i < *pargc; i++, j++ )
198 /* Guaranteed to end because there are "*pargc" arguments left */
199 while ( argv[ j ] == NULL )
202 argv[ i ] = argv[ j ];
205 #endif /* _WIN32_WCE */
210 void fghCloseInputDevices ( void )
212 if ( fgState.JoysticksInitialised )
215 if ( fgState.InputDevsInitialised )
216 fgInputDeviceClose( );
221 * Perform the freeglut deinitialization...
223 void fgDeinitialize( void )
227 if( !fgState.Initialised )
232 /* If we're in game mode, we want to leave game mode */
233 if( fgStructure.GameModeWindow ) {
237 /* If there was a menu created, destroy the rendering context */
238 if( fgStructure.MenuContext )
240 fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
241 free( fgStructure.MenuContext );
242 fgStructure.MenuContext = NULL;
245 fgDestroyStructure( );
247 while( ( timer = fgState.Timers.First) )
249 fgListRemove( &fgState.Timers, &timer->Node );
253 while( ( timer = fgState.FreeTimers.First) )
255 fgListRemove( &fgState.FreeTimers, &timer->Node );
259 fgPlatformDeinitialiseInputDevices ();
261 fgState.MouseWheelTicks = 0;
263 fgState.MajorVersion = 1;
264 fgState.MinorVersion = 0;
265 fgState.ContextFlags = 0;
266 fgState.ContextProfile = 0;
268 fgState.Initialised = GL_FALSE;
270 fgState.Position.X = -1;
271 fgState.Position.Y = -1;
272 fgState.Position.Use = GL_FALSE;
274 fgState.Size.X = 300;
275 fgState.Size.Y = 300;
276 fgState.Size.Use = GL_TRUE;
278 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
280 fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
281 fgState.ForceIconic = GL_FALSE;
282 fgState.UseCurrentContext = GL_FALSE;
283 fgState.GLDebugSwitch = GL_FALSE;
284 fgState.XSyncSwitch = GL_FALSE;
285 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
286 fgState.ExecState = GLUT_EXEC_STATE_INIT;
288 fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
289 fgState.Modifiers = INVALID_MODIFIERS;
291 fgState.GameModeSize.X = -1;
292 fgState.GameModeSize.Y = -1;
293 fgState.GameModeDepth = -1;
294 fgState.GameModeRefresh = -1;
296 fgListInit( &fgState.Timers );
297 fgListInit( &fgState.FreeTimers );
299 fgState.IdleCallback = NULL;
300 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
301 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
303 fgState.SwapCount = 0;
304 fgState.SwapTime = 0;
305 fgState.FPSInterval = 0;
307 if( fgState.ProgramName )
309 free( fgState.ProgramName );
310 fgState.ProgramName = NULL;
313 fgPlatformCloseDisplay ();
315 fgState.Initialised = GL_FALSE;
319 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
320 #if defined(NEED_XPARSEGEOMETRY_IMPL)
321 # include "util/xparsegeometry_repl.h"
325 * Perform initialization. This usually happens on the program startup
326 * and restarting after glutMainLoop termination...
328 void FGAPIENTRY glutInit( int* pargc, char** argv )
330 char* displayName = NULL;
331 char* geometry = NULL;
332 if( fgState.Initialised )
333 fgError( "illegal glutInit() reinitialization attempt" );
335 if (pargc && *pargc && argv && *argv && **argv)
337 fgState.ProgramName = strdup (*argv);
339 if( !fgState.ProgramName )
340 fgError ("Could not allocate space for the program's name.");
343 fgCreateStructure( );
346 fgState.Time = fgSystemTime();
348 fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
351 * Have the display created now. If there wasn't a "-display"
352 * in the program arguments, we will use the DISPLAY environment
353 * variable for opening the X display (see code above):
355 fgPlatformInitialize( displayName );
358 * Geometry parsing deferred until here because we may need the screen
364 unsigned int parsedWidth, parsedHeight;
365 int mask = XParseGeometry( geometry,
366 &fgState.Position.X, &fgState.Position.Y,
367 &parsedWidth, &parsedHeight );
368 /* TODO: Check for overflow? */
369 fgState.Size.X = parsedWidth;
370 fgState.Size.Y = parsedHeight;
372 if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
373 fgState.Size.Use = GL_TRUE;
375 if( mask & XNegative )
376 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
378 if( mask & YNegative )
379 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
381 if( (mask & (XValue|YValue)) == (XValue|YValue) )
382 fgState.Position.Use = GL_TRUE;
389 * Undoes all the "glutInit" stuff
391 void FGAPIENTRY glutExit ( void )
397 * Sets the default initial window position for new windows
399 void FGAPIENTRY glutInitWindowPosition( int x, int y )
401 fgState.Position.X = x;
402 fgState.Position.Y = y;
404 if( ( x >= 0 ) && ( y >= 0 ) )
405 fgState.Position.Use = GL_TRUE;
407 fgState.Position.Use = GL_FALSE;
411 * Sets the default initial window size for new windows
413 void FGAPIENTRY glutInitWindowSize( int width, int height )
415 fgState.Size.X = width;
416 fgState.Size.Y = height;
418 if( ( width > 0 ) && ( height > 0 ) )
419 fgState.Size.Use = GL_TRUE;
421 fgState.Size.Use = GL_FALSE;
425 * Sets the default display mode for all new windows
427 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
429 /* We will make use of this value when creating a new OpenGL context... */
430 fgState.DisplayMode = displayMode;
434 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
436 static char* Tokens[] =
438 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
439 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
440 "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
441 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
442 "xtruecolor", "xdirectcolor",
443 "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
444 "xtruecolour", "xdirectcolour", "borderless", "aux"
446 #define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
448 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
450 int glut_state_flag = 0 ;
452 * Unpack a lot of options from a character string. The options are
453 * delimited by blanks or tabs.
456 size_t len = strlen ( displayMode );
457 char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
458 memcpy ( buffer, displayMode, len );
461 token = strtok ( buffer, " \t" );
465 /* Process this token */
468 /* Temporary fix: Ignore any length specifications and at least
469 * process the basic token
470 * TODO: Fix this permanently
472 size_t cleanlength = strcspn ( token, "=<>~!" );
474 for ( i = 0; i < NUM_TOKENS; i++ )
476 if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
481 case 0 : /* "alpha": Alpha color buffer precision in bits */
482 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
485 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
489 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
490 in bits with zero bits alpha */
491 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
494 case 3 : /* "blue": Blue color buffer precision in bits */
497 case 4 : /* "buffer": Number of bits in the color index color buffer
501 case 5 : /* "conformant": Boolean indicating if the frame buffer
502 configuration is conformant or not */
505 case 6 : /* "depth": Number of bits of precision in the depth buffer */
506 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
509 case 7 : /* "double": Boolean indicating if the color buffer is
511 glut_state_flag |= GLUT_DOUBLE ;
514 case 8 : /* "green": Green color buffer precision in bits */
517 case 9 : /* "index": Boolean if the color model is color index or not
519 glut_state_flag |= GLUT_INDEX ;
522 case 10 : /* "num": A special capability name indicating where the
523 value represents the Nth frame buffer configuration
524 matching the description string */
527 case 11 : /* "red": Red color buffer precision in bits */
530 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
531 the RGBA color buffer */
532 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
535 case 13 : /* "rgb": Number of bits of red, green, and blue in the
536 RGBA color buffer with zero bits alpha */
537 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
540 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
541 bits of green, blue (alpha not specified) of color buffer
543 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
546 case 15 : /* "stencil": Number of bits in the stencil buffer */
547 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
550 case 16 : /* "single": Boolean indicate the color buffer is single
552 glut_state_flag |= GLUT_SINGLE ;
555 case 17 : /* "stereo": Boolean indicating the color buffer supports
556 OpenGL-style stereo */
557 glut_state_flag |= GLUT_STEREO ;
560 case 18 : /* "samples": Indicates the number of multisamples to use
561 based on GLX's SGIS_multisample extension (for
563 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
566 case 19 : /* "slow": Boolean indicating if the frame buffer
567 configuration is slow or not */
570 case 20 : /* "win32pdf": (incorrect spelling but was there before */
571 case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
573 #if TARGET_HOST_MS_WINDOWS
577 case 22 : /* "xvisual": matches the X visual ID by number */
578 #if TARGET_HOST_POSIX_X11
582 case 23 : /* "xstaticgray": */
583 case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
584 configuration's X visual is of type StaticGray */
585 #if TARGET_HOST_POSIX_X11
589 case 24 : /* "xgrayscale": */
590 case 30 : /* "xgreyscale": boolean indicating if the frame buffer
591 configuration's X visual is of type GrayScale */
592 #if TARGET_HOST_POSIX_X11
596 case 25 : /* "xstaticcolor": */
597 case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
598 configuration's X visual is of type StaticColor */
599 #if TARGET_HOST_POSIX_X11
603 case 26 : /* "xpseudocolor": */
604 case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
605 configuration's X visual is of type PseudoColor */
606 #if TARGET_HOST_POSIX_X11
610 case 27 : /* "xtruecolor": */
611 case 33 : /* "xtruecolour": boolean indicating if the frame buffer
612 configuration's X visual is of type TrueColor */
613 #if TARGET_HOST_POSIX_X11
617 case 28 : /* "xdirectcolor": */
618 case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
619 configuration's X visual is of type DirectColor */
620 #if TARGET_HOST_POSIX_X11
624 case 35 : /* "borderless": windows should not have borders */
625 glut_state_flag |= GLUT_BORDERLESS;
628 case 36 : /* "aux": some number of aux buffers */
629 glut_state_flag |= GLUT_AUX;
632 case 37 : /* Unrecognized */
633 fgWarning ( "WARNING - Display string token not recognized: %s",
638 token = strtok ( NULL, " \t" );
643 /* We will make use of this value when creating a new OpenGL context... */
644 fgState.DisplayMode = glut_state_flag;
647 /* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
649 void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
651 /* We will make use of these value when creating a new OpenGL context... */
652 fgState.MajorVersion = majorVersion;
653 fgState.MinorVersion = minorVersion;
657 void FGAPIENTRY glutInitContextFlags( int flags )
659 /* We will make use of this value when creating a new OpenGL context... */
660 fgState.ContextFlags = flags;
663 void FGAPIENTRY glutInitContextProfile( int profile )
665 /* We will make use of this value when creating a new OpenGL context... */
666 fgState.ContextProfile = profile;
669 /* -------------- User Defined Error/Warning Handler Support -------------- */
672 * Sets the user error handler (note the use of va_list for the args to the fmt)
674 void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
676 /* This allows user programs to handle freeglut errors */
677 fgState.ErrorFunc = vfgError;
681 * Sets the user warning handler (note the use of va_list for the args to the fmt)
683 void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
685 /* This allows user programs to handle freeglut warnings */
686 fgState.WarningFunc = vfgWarning;
689 /*** END OF FILE ***/