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 );
105 extern void fgInitGL2();
108 void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
111 int i, j, argc = *pargc;
114 /* check if GLUT_FPS env var is set */
115 const char *fps = getenv( "GLUT_FPS" );
120 sscanf( fps, "%d", &interval );
123 fgState.FPSInterval = 5000; /* 5000 millisecond default */
125 fgState.FPSInterval = interval;
129 *pDisplayName = getenv( "DISPLAY" );
131 for( i = 1; i < argc; i++ )
133 if( strcmp( argv[ i ], "-display" ) == 0 )
136 fgError( "-display parameter must be followed by display name" );
138 *pDisplayName = argv[ i ];
140 argv[ i - 1 ] = NULL;
144 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
147 fgError( "-geometry parameter must be followed by window "
148 "geometry settings" );
150 *pGeometry = argv[ i ];
152 argv[ i - 1 ] = NULL;
156 else if( strcmp( argv[ i ], "-direct" ) == 0)
158 if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
159 fgError( "parameters ambiguity, -direct and -indirect "
160 "cannot be both specified" );
162 fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
166 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
168 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
169 fgError( "parameters ambiguity, -direct and -indirect "
170 "cannot be both specified" );
172 fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
176 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
178 fgState.ForceIconic = GL_TRUE;
182 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
184 fgState.GLDebugSwitch = GL_TRUE;
188 else if( strcmp( argv[ i ], "-sync" ) == 0 )
190 fgState.XSyncSwitch = GL_TRUE;
196 /* Compact {argv}. */
197 for( i = j = 1; i < *pargc; i++, j++ )
199 /* Guaranteed to end because there are "*pargc" arguments left */
200 while ( argv[ j ] == NULL )
203 argv[ i ] = argv[ j ];
206 #endif /* _WIN32_WCE */
211 void fghCloseInputDevices ( void )
213 if ( fgState.JoysticksInitialised )
216 if ( fgState.InputDevsInitialised )
217 fgInputDeviceClose( );
222 * Perform the freeglut deinitialization...
224 void fgDeinitialize( void )
228 if( !fgState.Initialised )
233 /* If we're in game mode, we want to leave game mode */
234 if( fgStructure.GameModeWindow ) {
238 /* If there was a menu created, destroy the rendering context */
239 if( fgStructure.MenuContext )
241 fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
242 free( fgStructure.MenuContext );
243 fgStructure.MenuContext = NULL;
246 fgDestroyStructure( );
248 while( ( timer = fgState.Timers.First) )
250 fgListRemove( &fgState.Timers, &timer->Node );
254 while( ( timer = fgState.FreeTimers.First) )
256 fgListRemove( &fgState.FreeTimers, &timer->Node );
260 fgPlatformDeinitialiseInputDevices ();
262 fgState.MouseWheelTicks = 0;
264 fgState.MajorVersion = 1;
265 fgState.MinorVersion = 0;
266 fgState.ContextFlags = 0;
267 fgState.ContextProfile = 0;
269 fgState.Initialised = GL_FALSE;
271 fgState.Position.X = -1;
272 fgState.Position.Y = -1;
273 fgState.Position.Use = GL_FALSE;
275 fgState.Size.X = 300;
276 fgState.Size.Y = 300;
277 fgState.Size.Use = GL_TRUE;
279 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
281 fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
282 fgState.ForceIconic = GL_FALSE;
283 fgState.UseCurrentContext = GL_FALSE;
284 fgState.GLDebugSwitch = GL_FALSE;
285 fgState.XSyncSwitch = GL_FALSE;
286 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
287 fgState.ExecState = GLUT_EXEC_STATE_INIT;
289 fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
290 fgState.Modifiers = INVALID_MODIFIERS;
292 fgState.GameModeSize.X = -1;
293 fgState.GameModeSize.Y = -1;
294 fgState.GameModeDepth = -1;
295 fgState.GameModeRefresh = -1;
297 fgListInit( &fgState.Timers );
298 fgListInit( &fgState.FreeTimers );
300 fgState.IdleCallback = NULL;
301 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
302 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
304 fgState.SwapCount = 0;
305 fgState.SwapTime = 0;
306 fgState.FPSInterval = 0;
308 if( fgState.ProgramName )
310 free( fgState.ProgramName );
311 fgState.ProgramName = NULL;
314 fgPlatformCloseDisplay ();
316 fgState.Initialised = GL_FALSE;
320 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
321 #if defined(NEED_XPARSEGEOMETRY_IMPL)
322 # include "util/xparsegeometry_repl.h"
326 * Perform initialization. This usually happens on the program startup
327 * and restarting after glutMainLoop termination...
329 void FGAPIENTRY glutInit( int* pargc, char** argv )
331 char* displayName = NULL;
332 char* geometry = NULL;
333 if( fgState.Initialised )
334 fgError( "illegal glutInit() reinitialization attempt" );
336 if (pargc && *pargc && argv && *argv && **argv)
338 fgState.ProgramName = strdup (*argv);
340 if( !fgState.ProgramName )
341 fgError ("Could not allocate space for the program's name.");
344 fgCreateStructure( );
347 fgState.Time = fgSystemTime();
349 fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
352 * Have the display created now. If there wasn't a "-display"
353 * in the program arguments, we will use the DISPLAY environment
354 * variable for opening the X display (see code above):
356 fgPlatformInitialize( displayName );
359 * Geometry parsing deferred until here because we may need the screen
365 unsigned int parsedWidth, parsedHeight;
366 int mask = XParseGeometry( geometry,
367 &fgState.Position.X, &fgState.Position.Y,
368 &parsedWidth, &parsedHeight );
369 /* TODO: Check for overflow? */
370 fgState.Size.X = parsedWidth;
371 fgState.Size.Y = parsedHeight;
373 if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
374 fgState.Size.Use = GL_TRUE;
376 if( mask & XNegative )
377 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
379 if( mask & YNegative )
380 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
382 if( (mask & (XValue|YValue)) == (XValue|YValue) )
383 fgState.Position.Use = GL_TRUE;
390 * Undoes all the "glutInit" stuff
392 void FGAPIENTRY glutExit ( void )
398 * Sets the default initial window position for new windows
400 void FGAPIENTRY glutInitWindowPosition( int x, int y )
402 fgState.Position.X = x;
403 fgState.Position.Y = y;
405 if( ( x >= 0 ) && ( y >= 0 ) )
406 fgState.Position.Use = GL_TRUE;
408 fgState.Position.Use = GL_FALSE;
412 * Sets the default initial window size for new windows
414 void FGAPIENTRY glutInitWindowSize( int width, int height )
416 fgState.Size.X = width;
417 fgState.Size.Y = height;
419 if( ( width > 0 ) && ( height > 0 ) )
420 fgState.Size.Use = GL_TRUE;
422 fgState.Size.Use = GL_FALSE;
426 * Sets the default display mode for all new windows
428 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
430 /* We will make use of this value when creating a new OpenGL context... */
431 fgState.DisplayMode = displayMode;
435 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
437 static char* Tokens[] =
439 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
440 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
441 "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
442 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
443 "xtruecolor", "xdirectcolor",
444 "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
445 "xtruecolour", "xdirectcolour", "borderless", "aux"
447 #define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
449 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
451 int glut_state_flag = 0 ;
453 * Unpack a lot of options from a character string. The options are
454 * delimited by blanks or tabs.
457 size_t len = strlen ( displayMode );
458 char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
459 memcpy ( buffer, displayMode, len );
462 token = strtok ( buffer, " \t" );
466 /* Process this token */
469 /* Temporary fix: Ignore any length specifications and at least
470 * process the basic token
471 * TODO: Fix this permanently
473 size_t cleanlength = strcspn ( token, "=<>~!" );
475 for ( i = 0; i < NUM_TOKENS; i++ )
477 if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
482 case 0 : /* "alpha": Alpha color buffer precision in bits */
483 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
486 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
490 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
491 in bits with zero bits alpha */
492 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
495 case 3 : /* "blue": Blue color buffer precision in bits */
498 case 4 : /* "buffer": Number of bits in the color index color buffer
502 case 5 : /* "conformant": Boolean indicating if the frame buffer
503 configuration is conformant or not */
506 case 6 : /* "depth": Number of bits of precision in the depth buffer */
507 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
510 case 7 : /* "double": Boolean indicating if the color buffer is
512 glut_state_flag |= GLUT_DOUBLE ;
515 case 8 : /* "green": Green color buffer precision in bits */
518 case 9 : /* "index": Boolean if the color model is color index or not
520 glut_state_flag |= GLUT_INDEX ;
523 case 10 : /* "num": A special capability name indicating where the
524 value represents the Nth frame buffer configuration
525 matching the description string */
528 case 11 : /* "red": Red color buffer precision in bits */
531 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
532 the RGBA color buffer */
533 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
536 case 13 : /* "rgb": Number of bits of red, green, and blue in the
537 RGBA color buffer with zero bits alpha */
538 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
541 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
542 bits of green, blue (alpha not specified) of color buffer
544 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
547 case 15 : /* "stencil": Number of bits in the stencil buffer */
548 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
551 case 16 : /* "single": Boolean indicate the color buffer is single
553 glut_state_flag |= GLUT_SINGLE ;
556 case 17 : /* "stereo": Boolean indicating the color buffer supports
557 OpenGL-style stereo */
558 glut_state_flag |= GLUT_STEREO ;
561 case 18 : /* "samples": Indicates the number of multisamples to use
562 based on GLX's SGIS_multisample extension (for
564 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
567 case 19 : /* "slow": Boolean indicating if the frame buffer
568 configuration is slow or not */
571 case 20 : /* "win32pdf": (incorrect spelling but was there before */
572 case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
574 #if TARGET_HOST_MS_WINDOWS
578 case 22 : /* "xvisual": matches the X visual ID by number */
579 #if TARGET_HOST_POSIX_X11
583 case 23 : /* "xstaticgray": */
584 case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
585 configuration's X visual is of type StaticGray */
586 #if TARGET_HOST_POSIX_X11
590 case 24 : /* "xgrayscale": */
591 case 30 : /* "xgreyscale": boolean indicating if the frame buffer
592 configuration's X visual is of type GrayScale */
593 #if TARGET_HOST_POSIX_X11
597 case 25 : /* "xstaticcolor": */
598 case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
599 configuration's X visual is of type StaticColor */
600 #if TARGET_HOST_POSIX_X11
604 case 26 : /* "xpseudocolor": */
605 case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
606 configuration's X visual is of type PseudoColor */
607 #if TARGET_HOST_POSIX_X11
611 case 27 : /* "xtruecolor": */
612 case 33 : /* "xtruecolour": boolean indicating if the frame buffer
613 configuration's X visual is of type TrueColor */
614 #if TARGET_HOST_POSIX_X11
618 case 28 : /* "xdirectcolor": */
619 case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
620 configuration's X visual is of type DirectColor */
621 #if TARGET_HOST_POSIX_X11
625 case 35 : /* "borderless": windows should not have borders */
626 glut_state_flag |= GLUT_BORDERLESS;
629 case 36 : /* "aux": some number of aux buffers */
630 glut_state_flag |= GLUT_AUX;
633 case 37 : /* Unrecognized */
634 fgWarning ( "WARNING - Display string token not recognized: %s",
639 token = strtok ( NULL, " \t" );
644 /* We will make use of this value when creating a new OpenGL context... */
645 fgState.DisplayMode = glut_state_flag;
648 /* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
650 void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
652 /* We will make use of these value when creating a new OpenGL context... */
653 fgState.MajorVersion = majorVersion;
654 fgState.MinorVersion = minorVersion;
658 void FGAPIENTRY glutInitContextFlags( int flags )
660 /* We will make use of this value when creating a new OpenGL context... */
661 fgState.ContextFlags = flags;
664 void FGAPIENTRY glutInitContextProfile( int profile )
666 /* We will make use of this value when creating a new OpenGL context... */
667 fgState.ContextProfile = profile;
670 /* -------------- User Defined Error/Warning Handler Support -------------- */
673 * Sets the user error handler (note the use of va_list for the args to the fmt)
675 void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
677 /* This allows user programs to handle freeglut errors */
678 fgState.ErrorFunc = vfgError;
682 * Sets the user warning handler (note the use of va_list for the args to the fmt)
684 void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
686 /* This allows user programs to handle freeglut warnings */
687 fgState.WarningFunc = vfgWarning;
690 /*** END OF FILE ***/