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 */
73 NULL, /* IdleCallbackData */
75 NULL, /* MenuStateCallback */
76 NULL, /* MenuStatusCallback */
78 { -1, -1, GL_TRUE }, /* GameModeSize */
79 -1, /* GameModeDepth */
80 -1, /* GameModeRefresh */
81 GLUT_ACTION_EXIT, /* ActionOnWindowClose */
82 GLUT_EXEC_STATE_INIT, /* ExecState */
83 NULL, /* ProgramName */
84 GL_FALSE, /* JoysticksInitialised */
85 0, /* NumActiveJoysticks */
86 GL_FALSE, /* InputDevsInitialised */
87 0, /* MouseWheelTicks */
88 1, /* AuxiliaryBufferNumber */
90 GL_FALSE, /* SkipStaleMotion */
91 GL_FALSE, /* StrokeFontDrawJoinDots */
92 GL_FALSE, /* AllowNegativeWindowPosition */
93 1, /* OpenGL context MajorVersion */
94 0, /* OpenGL context MinorVersion */
95 0, /* OpenGL ContextFlags */
96 0, /* OpenGL ContextProfile */
99 NULL /* WarningFunc */
103 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
105 extern void fgPlatformInitialize( const char* displayName );
106 extern void fgPlatformDeinitialiseInputDevices ( void );
107 extern void fgPlatformCloseDisplay ( void );
108 extern void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext );
110 void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
113 int i, j, argc = *pargc;
116 /* check if GLUT_FPS env var is set */
117 const char *fps = getenv( "GLUT_FPS" );
122 sscanf( fps, "%d", &interval );
125 fgState.FPSInterval = 5000; /* 5000 millisecond default */
127 fgState.FPSInterval = interval;
131 *pDisplayName = getenv( "DISPLAY" );
133 for( i = 1; i < argc; i++ )
135 if( strcmp( argv[ i ], "-display" ) == 0 )
138 fgError( "-display parameter must be followed by display name" );
140 *pDisplayName = argv[ i ];
142 argv[ i - 1 ] = NULL;
146 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
149 fgError( "-geometry parameter must be followed by window "
150 "geometry settings" );
152 *pGeometry = argv[ i ];
154 argv[ i - 1 ] = NULL;
158 else if( strcmp( argv[ i ], "-direct" ) == 0)
160 if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
161 fgError( "parameters ambiguity, -direct and -indirect "
162 "cannot be both specified" );
164 fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
168 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
170 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
171 fgError( "parameters ambiguity, -direct and -indirect "
172 "cannot be both specified" );
174 fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
178 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
180 fgState.ForceIconic = GL_TRUE;
184 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
186 fgState.GLDebugSwitch = GL_TRUE;
190 else if( strcmp( argv[ i ], "-sync" ) == 0 )
192 fgState.XSyncSwitch = GL_TRUE;
198 /* Compact {argv}. */
199 for( i = j = 1; i < *pargc; i++, j++ )
201 /* Guaranteed to end because there are "*pargc" arguments left */
202 while ( argv[ j ] == NULL )
205 argv[ i ] = argv[ j ];
208 #endif /* _WIN32_WCE */
213 void fghCloseInputDevices ( void )
215 if ( fgState.JoysticksInitialised )
218 if ( fgState.InputDevsInitialised )
219 fgInputDeviceClose( );
224 * Perform the freeglut deinitialization...
226 void fgDeinitialize( void )
230 if( !fgState.Initialised )
235 /* If we're in game mode, we want to leave game mode */
236 if( fgStructure.GameModeWindow ) {
240 /* If there was a menu created, destroy the rendering context */
241 if( fgStructure.MenuContext )
243 fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
244 free( fgStructure.MenuContext );
245 fgStructure.MenuContext = NULL;
248 fgDestroyStructure( );
250 while( ( timer = fgState.Timers.First) )
252 fgListRemove( &fgState.Timers, &timer->Node );
256 while( ( timer = fgState.FreeTimers.First) )
258 fgListRemove( &fgState.FreeTimers, &timer->Node );
262 fgPlatformDeinitialiseInputDevices ();
264 fgState.MouseWheelTicks = 0;
266 fgState.MajorVersion = 1;
267 fgState.MinorVersion = 0;
268 fgState.ContextFlags = 0;
269 fgState.ContextProfile = 0;
271 fgState.Initialised = GL_FALSE;
273 fgState.Position.X = -1;
274 fgState.Position.Y = -1;
275 fgState.Position.Use = GL_FALSE;
277 fgState.Size.X = 300;
278 fgState.Size.Y = 300;
279 fgState.Size.Use = GL_TRUE;
281 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
283 fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
284 fgState.ForceIconic = GL_FALSE;
285 fgState.UseCurrentContext = GL_FALSE;
286 fgState.GLDebugSwitch = GL_FALSE;
287 fgState.XSyncSwitch = GL_FALSE;
288 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
289 fgState.ExecState = GLUT_EXEC_STATE_INIT;
291 fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
292 fgState.Modifiers = INVALID_MODIFIERS;
294 fgState.GameModeSize.X = -1;
295 fgState.GameModeSize.Y = -1;
296 fgState.GameModeDepth = -1;
297 fgState.GameModeRefresh = -1;
299 fgListInit( &fgState.Timers );
300 fgListInit( &fgState.FreeTimers );
302 fgState.IdleCallback = NULL;
303 fgState.IdleCallbackData = NULL;
304 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
305 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
307 fgState.SwapCount = 0;
308 fgState.SwapTime = 0;
309 fgState.FPSInterval = 0;
311 if( fgState.ProgramName )
313 free( fgState.ProgramName );
314 fgState.ProgramName = NULL;
317 fgPlatformCloseDisplay ();
319 fgState.Initialised = GL_FALSE;
323 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
324 #if defined(NEED_XPARSEGEOMETRY_IMPL) || defined(TARGET_HOST_MS_WINDOWS)
325 # include "util/xparsegeometry_repl.h"
329 * Perform initialization. This usually happens on the program startup
330 * and restarting after glutMainLoop termination...
332 void FGAPIENTRY glutInit( int* pargc, char** argv )
334 char* displayName = NULL;
335 char* geometry = NULL;
336 if( fgState.Initialised )
337 fgError( "illegal glutInit() reinitialization attempt" );
339 if (pargc && *pargc && argv && *argv && **argv)
341 fgState.ProgramName = strdup (*argv);
343 if( !fgState.ProgramName )
344 fgError ("Could not allocate space for the program's name.");
347 fgCreateStructure( );
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 ) && !fgState.AllowNegativeWindowPosition )
377 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
379 if( ( mask & YNegative ) && !fgState.AllowNegativeWindowPosition )
380 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
382 if( (mask & (XValue|YValue)) == (XValue|YValue) )
383 fgState.Position.Use = GL_TRUE;
388 * Undoes all the "glutInit" stuff
390 void FGAPIENTRY glutExit ( void )
396 * Sets the default initial window position for new windows
398 void FGAPIENTRY glutInitWindowPosition( int x, int y )
400 fgState.Position.X = x;
401 fgState.Position.Y = y;
403 if( ( ( x >= 0 ) && ( y >= 0 ) ) || fgState.AllowNegativeWindowPosition )
404 fgState.Position.Use = GL_TRUE;
406 fgState.Position.Use = GL_FALSE;
410 * Sets the default initial window size for new windows
412 void FGAPIENTRY glutInitWindowSize( int width, int height )
414 fgState.Size.X = width;
415 fgState.Size.Y = height;
417 if( ( width > 0 ) && ( height > 0 ) )
418 fgState.Size.Use = GL_TRUE;
420 fgState.Size.Use = GL_FALSE;
424 * Sets the default display mode for all new windows
426 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
428 /* We will make use of this value when creating a new OpenGL context... */
429 fgState.DisplayMode = displayMode;
433 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
435 static char* Tokens[] =
437 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
438 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
439 "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
440 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
441 "xtruecolor", "xdirectcolor",
442 "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
443 "xtruecolour", "xdirectcolour", "borderless", "aux"
445 #define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
447 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
449 int glut_state_flag = 0 ;
451 * Unpack a lot of options from a character string. The options are
452 * delimited by blanks or tabs.
455 size_t len = strlen ( displayMode );
456 char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
457 memcpy ( buffer, displayMode, len );
460 token = strtok ( buffer, " \t" );
464 /* Process this token */
467 /* Temporary fix: Ignore any length specifications and at least
468 * process the basic token
469 * TODO: Fix this permanently
471 size_t cleanlength = strcspn ( token, "=<>~!" );
473 for ( i = 0; i < NUM_TOKENS; i++ )
475 if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
480 case 0 : /* "alpha": Alpha color buffer precision in bits */
481 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
484 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
488 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
489 in bits with zero bits alpha */
490 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
493 case 3 : /* "blue": Blue color buffer precision in bits */
496 case 4 : /* "buffer": Number of bits in the color index color buffer
500 case 5 : /* "conformant": Boolean indicating if the frame buffer
501 configuration is conformant or not */
504 case 6 : /* "depth": Number of bits of precision in the depth buffer */
505 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
508 case 7 : /* "double": Boolean indicating if the color buffer is
510 glut_state_flag |= GLUT_DOUBLE ;
513 case 8 : /* "green": Green color buffer precision in bits */
516 case 9 : /* "index": Boolean if the color model is color index or not
518 glut_state_flag |= GLUT_INDEX ;
521 case 10 : /* "num": A special capability name indicating where the
522 value represents the Nth frame buffer configuration
523 matching the description string */
526 case 11 : /* "red": Red color buffer precision in bits */
529 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
530 the RGBA color buffer */
531 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
534 case 13 : /* "rgb": Number of bits of red, green, and blue in the
535 RGBA color buffer with zero bits alpha */
536 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
539 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
540 bits of green, blue (alpha not specified) of color buffer
542 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
545 case 15 : /* "stencil": Number of bits in the stencil buffer */
546 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
549 case 16 : /* "single": Boolean indicate the color buffer is single
551 glut_state_flag |= GLUT_SINGLE ;
554 case 17 : /* "stereo": Boolean indicating the color buffer supports
555 OpenGL-style stereo */
556 glut_state_flag |= GLUT_STEREO ;
559 case 18 : /* "samples": Indicates the number of multisamples to use
560 based on GLX's SGIS_multisample extension (for
562 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
565 case 19 : /* "slow": Boolean indicating if the frame buffer
566 configuration is slow or not */
569 case 20 : /* "win32pdf": (incorrect spelling but was there before */
570 case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
572 #if TARGET_HOST_MS_WINDOWS
576 case 22 : /* "xvisual": matches the X visual ID by number */
577 #if TARGET_HOST_POSIX_X11
581 case 23 : /* "xstaticgray": */
582 case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
583 configuration's X visual is of type StaticGray */
584 #if TARGET_HOST_POSIX_X11
588 case 24 : /* "xgrayscale": */
589 case 30 : /* "xgreyscale": boolean indicating if the frame buffer
590 configuration's X visual is of type GrayScale */
591 #if TARGET_HOST_POSIX_X11
595 case 25 : /* "xstaticcolor": */
596 case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
597 configuration's X visual is of type StaticColor */
598 #if TARGET_HOST_POSIX_X11
602 case 26 : /* "xpseudocolor": */
603 case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
604 configuration's X visual is of type PseudoColor */
605 #if TARGET_HOST_POSIX_X11
609 case 27 : /* "xtruecolor": */
610 case 33 : /* "xtruecolour": boolean indicating if the frame buffer
611 configuration's X visual is of type TrueColor */
612 #if TARGET_HOST_POSIX_X11
616 case 28 : /* "xdirectcolor": */
617 case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
618 configuration's X visual is of type DirectColor */
619 #if TARGET_HOST_POSIX_X11
623 case 35 : /* "borderless": windows should not have borders */
624 glut_state_flag |= GLUT_BORDERLESS;
627 case 36 : /* "aux": some number of aux buffers */
628 glut_state_flag |= GLUT_AUX;
631 case 37 : /* Unrecognized */
632 fgWarning ( "WARNING - Display string token not recognized: %s",
637 token = strtok ( NULL, " \t" );
642 /* We will make use of this value when creating a new OpenGL context... */
643 fgState.DisplayMode = glut_state_flag;
646 /* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
648 void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
650 /* We will make use of these value when creating a new OpenGL context... */
651 fgState.MajorVersion = majorVersion;
652 fgState.MinorVersion = minorVersion;
656 void FGAPIENTRY glutInitContextFlags( int flags )
658 /* We will make use of this value when creating a new OpenGL context... */
659 fgState.ContextFlags = flags;
662 void FGAPIENTRY glutInitContextProfile( int profile )
664 /* We will make use of this value when creating a new OpenGL context... */
665 fgState.ContextProfile = profile;
668 /* -------------- User Defined Error/Warning Handler Support -------------- */
671 * Sets the user error handler (note the use of va_list for the args to the fmt)
673 void FGAPIENTRY glutInitErrorFunc( FGError callback )
675 /* This allows user programs to handle freeglut errors */
676 fgState.ErrorFunc = callback;
680 * Sets the user warning handler (note the use of va_list for the args to the fmt)
682 void FGAPIENTRY glutInitWarningFunc( FGWarning callback )
684 /* This allows user programs to handle freeglut warnings */
685 fgState.WarningFunc = callback;
688 /*** END OF FILE ***/