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 "freeglut_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 g_pDisplay 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 { 640, 480, GL_TRUE }, /* GameModeSize */
77 16, /* GameModeDepth */
78 72, /* 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 */
91 0, /* ContextProfile */
93 NULL /* WarningFunc */
97 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
99 extern void fgPlatformInitialize( const char* displayName );
100 extern void fgPlatformDeinitialiseInputDevices ( void );
101 extern void fgPlatformCloseDisplay ( void );
102 extern void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext );
105 void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
108 int i, j, argc = *pargc;
111 /* check if GLUT_FPS env var is set */
112 const char *fps = getenv( "GLUT_FPS" );
117 sscanf( fps, "%d", &interval );
120 fgState.FPSInterval = 5000; /* 5000 millisecond default */
122 fgState.FPSInterval = interval;
126 *pDisplayName = getenv( "DISPLAY" );
128 for( i = 1; i < argc; i++ )
130 if( strcmp( argv[ i ], "-display" ) == 0 )
133 fgError( "-display parameter must be followed by display name" );
135 *pDisplayName = argv[ i ];
137 argv[ i - 1 ] = NULL;
141 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
144 fgError( "-geometry parameter must be followed by window "
145 "geometry settings" );
147 *pGeometry = argv[ i ];
149 argv[ i - 1 ] = NULL;
153 else if( strcmp( argv[ i ], "-direct" ) == 0)
155 if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
156 fgError( "parameters ambiguity, -direct and -indirect "
157 "cannot be both specified" );
159 fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
163 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
165 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
166 fgError( "parameters ambiguity, -direct and -indirect "
167 "cannot be both specified" );
169 fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
173 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
175 fgState.ForceIconic = GL_TRUE;
179 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
181 fgState.GLDebugSwitch = GL_TRUE;
185 else if( strcmp( argv[ i ], "-sync" ) == 0 )
187 fgState.XSyncSwitch = GL_TRUE;
193 /* Compact {argv}. */
194 for( i = j = 1; i < *pargc; i++, j++ )
196 /* Guaranteed to end because there are "*pargc" arguments left */
197 while ( argv[ j ] == NULL )
200 argv[ i ] = argv[ j ];
203 #endif /* _WIN32_WCE */
208 void fghCloseInputDevices ( void )
210 if ( fgState.JoysticksInitialised )
213 if ( fgState.InputDevsInitialised )
214 fgInputDeviceClose( );
219 * Perform the freeglut deinitialization...
221 void fgDeinitialize( void )
225 if( !fgState.Initialised )
230 /* If we're in game mode, we want to leave game mode */
231 if( fgStructure.GameModeWindow ) {
235 /* If there was a menu created, destroy the rendering context */
236 if( fgStructure.MenuContext )
238 fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
239 free( fgStructure.MenuContext );
240 fgStructure.MenuContext = NULL;
243 fgDestroyStructure( );
245 while( ( timer = fgState.Timers.First) )
247 fgListRemove( &fgState.Timers, &timer->Node );
251 while( ( timer = fgState.FreeTimers.First) )
253 fgListRemove( &fgState.FreeTimers, &timer->Node );
257 fgPlatformDeinitialiseInputDevices ();
259 fgState.MouseWheelTicks = 0;
261 fgState.MajorVersion = 1;
262 fgState.MinorVersion = 0;
263 fgState.ContextFlags = 0;
264 fgState.ContextProfile = 0;
266 fgState.Initialised = GL_FALSE;
268 fgState.Position.X = -1;
269 fgState.Position.Y = -1;
270 fgState.Position.Use = GL_FALSE;
272 fgState.Size.X = 300;
273 fgState.Size.Y = 300;
274 fgState.Size.Use = GL_TRUE;
276 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
278 fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
279 fgState.ForceIconic = GL_FALSE;
280 fgState.UseCurrentContext = GL_FALSE;
281 fgState.GLDebugSwitch = GL_FALSE;
282 fgState.XSyncSwitch = GL_FALSE;
283 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
284 fgState.ExecState = GLUT_EXEC_STATE_INIT;
286 fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
287 fgState.Modifiers = INVALID_MODIFIERS;
289 fgState.GameModeSize.X = 640;
290 fgState.GameModeSize.Y = 480;
291 fgState.GameModeDepth = 16;
292 fgState.GameModeRefresh = 72;
294 fgListInit( &fgState.Timers );
295 fgListInit( &fgState.FreeTimers );
297 fgState.IdleCallback = NULL;
298 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
299 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
301 fgState.SwapCount = 0;
302 fgState.SwapTime = 0;
303 fgState.FPSInterval = 0;
305 if( fgState.ProgramName )
307 free( fgState.ProgramName );
308 fgState.ProgramName = NULL;
311 fgPlatformCloseDisplay ();
313 fgState.Initialised = GL_FALSE;
317 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
320 * Perform initialization. This usually happens on the program startup
321 * and restarting after glutMainLoop termination...
323 void FGAPIENTRY glutInit( int* pargc, char** argv )
325 char* displayName = NULL;
326 char* geometry = NULL;
327 if( fgState.Initialised )
328 fgError( "illegal glutInit() reinitialization attempt" );
330 if (pargc && *pargc && argv && *argv && **argv)
332 fgState.ProgramName = strdup (*argv);
334 if( !fgState.ProgramName )
335 fgError ("Could not allocate space for the program's name.");
338 fgCreateStructure( );
341 fgState.Time = fgSystemTime();
343 fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
346 * Have the display created now. If there wasn't a "-display"
347 * in the program arguments, we will use the DISPLAY environment
348 * variable for opening the X display (see code above):
350 fgPlatformInitialize( displayName );
353 * Geometry parsing deffered until here because we may need the screen
359 unsigned int parsedWidth, parsedHeight;
360 int mask = XParseGeometry( geometry,
361 &fgState.Position.X, &fgState.Position.Y,
362 &parsedWidth, &parsedHeight );
363 /* TODO: Check for overflow? */
364 fgState.Size.X = parsedWidth;
365 fgState.Size.Y = parsedHeight;
367 if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
368 fgState.Size.Use = GL_TRUE;
370 if( mask & XNegative )
371 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
373 if( mask & YNegative )
374 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
376 if( (mask & (XValue|YValue)) == (XValue|YValue) )
377 fgState.Position.Use = GL_TRUE;
382 * Undoes all the "glutInit" stuff
384 void FGAPIENTRY glutExit ( void )
390 * Sets the default initial window position for new windows
392 void FGAPIENTRY glutInitWindowPosition( int x, int y )
394 fgState.Position.X = x;
395 fgState.Position.Y = y;
397 if( ( x >= 0 ) && ( y >= 0 ) )
398 fgState.Position.Use = GL_TRUE;
400 fgState.Position.Use = GL_FALSE;
404 * Sets the default initial window size for new windows
406 void FGAPIENTRY glutInitWindowSize( int width, int height )
408 fgState.Size.X = width;
409 fgState.Size.Y = height;
411 if( ( width > 0 ) && ( height > 0 ) )
412 fgState.Size.Use = GL_TRUE;
414 fgState.Size.Use = GL_FALSE;
418 * Sets the default display mode for all new windows
420 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
422 /* We will make use of this value when creating a new OpenGL context... */
423 fgState.DisplayMode = displayMode;
427 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
429 static char* Tokens[] =
431 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
432 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
433 "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
434 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
435 "xtruecolor", "xdirectcolor",
436 "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
437 "xtruecolour", "xdirectcolour", "borderless", "aux"
439 #define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
441 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
443 int glut_state_flag = 0 ;
445 * Unpack a lot of options from a character string. The options are
446 * delimited by blanks or tabs.
449 size_t len = strlen ( displayMode );
450 char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
451 memcpy ( buffer, displayMode, len );
454 token = strtok ( buffer, " \t" );
458 /* Process this token */
461 /* Temporary fix: Ignore any length specifications and at least
462 * process the basic token
463 * TODO: Fix this permanently
465 size_t cleanlength = strcspn ( token, "=<>~!" );
467 for ( i = 0; i < NUM_TOKENS; i++ )
469 if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
474 case 0 : /* "alpha": Alpha color buffer precision in bits */
475 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
478 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
482 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
483 in bits with zero bits alpha */
484 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
487 case 3 : /* "blue": Blue color buffer precision in bits */
490 case 4 : /* "buffer": Number of bits in the color index color buffer
494 case 5 : /* "conformant": Boolean indicating if the frame buffer
495 configuration is conformant or not */
498 case 6 : /* "depth": Number of bits of precsion in the depth buffer */
499 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
502 case 7 : /* "double": Boolean indicating if the color buffer is
504 glut_state_flag |= GLUT_DOUBLE ;
507 case 8 : /* "green": Green color buffer precision in bits */
510 case 9 : /* "index": Boolean if the color model is color index or not
512 glut_state_flag |= GLUT_INDEX ;
515 case 10 : /* "num": A special capability name indicating where the
516 value represents the Nth frame buffer configuration
517 matching the description string */
520 case 11 : /* "red": Red color buffer precision in bits */
523 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
524 the RGBA color buffer */
525 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
528 case 13 : /* "rgb": Number of bits of red, green, and blue in the
529 RGBA color buffer with zero bits alpha */
530 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
533 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
534 bits of green, blue (alpha not specified) of color buffer
536 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
539 case 15 : /* "stencil": Number of bits in the stencil buffer */
540 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
543 case 16 : /* "single": Boolean indicate the color buffer is single
545 glut_state_flag |= GLUT_SINGLE ;
548 case 17 : /* "stereo": Boolean indicating the color buffer supports
549 OpenGL-style stereo */
550 glut_state_flag |= GLUT_STEREO ;
553 case 18 : /* "samples": Indicates the number of multisamples to use
554 based on GLX's SGIS_multisample extension (for
556 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
559 case 19 : /* "slow": Boolean indicating if the frame buffer
560 configuration is slow or not */
563 case 20 : /* "win32pdf": (incorrect spelling but was there before */
564 case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
566 #if TARGET_HOST_MS_WINDOWS
570 case 22 : /* "xvisual": matches the X visual ID by number */
571 #if TARGET_HOST_POSIX_X11
575 case 23 : /* "xstaticgray": */
576 case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
577 configuration's X visual is of type StaticGray */
578 #if TARGET_HOST_POSIX_X11
582 case 24 : /* "xgrayscale": */
583 case 30 : /* "xgreyscale": boolean indicating if the frame buffer
584 configuration's X visual is of type GrayScale */
585 #if TARGET_HOST_POSIX_X11
589 case 25 : /* "xstaticcolor": */
590 case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
591 configuration's X visual is of type StaticColor */
592 #if TARGET_HOST_POSIX_X11
596 case 26 : /* "xpseudocolor": */
597 case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
598 configuration's X visual is of type PseudoColor */
599 #if TARGET_HOST_POSIX_X11
603 case 27 : /* "xtruecolor": */
604 case 33 : /* "xtruecolour": boolean indicating if the frame buffer
605 configuration's X visual is of type TrueColor */
606 #if TARGET_HOST_POSIX_X11
610 case 28 : /* "xdirectcolor": */
611 case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
612 configuration's X visual is of type DirectColor */
613 #if TARGET_HOST_POSIX_X11
617 case 35 : /* "borderless": windows should not have borders */
618 #if TARGET_HOST_POSIX_X11
622 case 36 : /* "aux": some number of aux buffers */
623 glut_state_flag |= GLUT_AUX;
626 case 37 : /* Unrecognized */
627 fgWarning ( "WARNING - Display string token not recognized: %s",
632 token = strtok ( NULL, " \t" );
637 /* We will make use of this value when creating a new OpenGL context... */
638 fgState.DisplayMode = glut_state_flag;
641 /* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
643 void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
645 /* We will make use of these valuse when creating a new OpenGL context... */
646 fgState.MajorVersion = majorVersion;
647 fgState.MinorVersion = minorVersion;
651 void FGAPIENTRY glutInitContextFlags( int flags )
653 /* We will make use of this value when creating a new OpenGL context... */
654 fgState.ContextFlags = flags;
657 void FGAPIENTRY glutInitContextProfile( int profile )
659 /* We will make use of this value when creating a new OpenGL context... */
660 fgState.ContextProfile = profile;
663 /* -------------- User Defined Error/Warning Handler Support -------------- */
666 * Sets the user error handler (note the use of va_list for the args to the fmt)
668 void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
670 /* This allows user programs to handle freeglut errors */
671 fgState.ErrorFunc = vfgError;
675 * Sets the user warning handler (note the use of va_list for the args to the fmt)
677 void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
679 /* This allows user programs to handle freeglut warnings */
680 fgState.WarningFunc = vfgWarning;
683 /*** END OF FILE ***/