4 * Various freeglut initialization functions.
\r
6 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
\r
7 * Written by Pawel W. Olszta, <olszta@sourceforge.net>
\r
8 * Creation date: Thu Dec 2 1999
\r
10 * Permission is hereby granted, free of charge, to any person obtaining a
\r
11 * copy of this software and associated documentation files (the "Software"),
\r
12 * to deal in the Software without restriction, including without limitation
\r
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
\r
14 * and/or sell copies of the Software, and to permit persons to whom the
\r
15 * Software is furnished to do so, subject to the following conditions:
\r
17 * The above copyright notice and this permission notice shall be included
\r
18 * in all copies or substantial portions of the Software.
\r
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
\r
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
\r
23 * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
24 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
28 #define FREEGLUT_BUILDING_LIB
\r
29 #include <GL/freeglut.h>
\r
30 #include "freeglut_internal.h"
\r
33 * TODO BEFORE THE STABLE RELEASE:
\r
35 * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific
\r
36 * deinitialization done
\r
37 * glutInitDisplayString() -- display mode string parsing
\r
39 * Wouldn't it be cool to use gettext() for error messages? I just love
\r
40 * bash saying "nie znaleziono pliku" instead of "file not found" :)
\r
41 * Is gettext easily portable?
\r
44 /* -- GLOBAL VARIABLES ----------------------------------------------------- */
\r
47 * A structure pointed by g_pDisplay holds all information
\r
48 * regarding the display, screen, root window etc.
\r
50 SFG_Display fgDisplay;
\r
53 * The settings for the current freeglut session
\r
55 SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
\r
56 { 300, 300, GL_TRUE }, /* Size */
\r
57 GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
\r
58 GL_FALSE, /* Initialised */
\r
59 GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */
\r
60 GL_FALSE, /* ForceIconic */
\r
61 GL_FALSE, /* UseCurrentContext */
\r
62 GL_FALSE, /* GLDebugSwitch */
\r
63 GL_FALSE, /* XSyncSwitch */
\r
64 GLUT_KEY_REPEAT_ON, /* KeyRepeat */
\r
65 INVALID_MODIFIERS, /* Modifiers */
\r
66 0, /* FPSInterval */
\r
70 { NULL, NULL }, /* Timers */
\r
71 { NULL, NULL }, /* FreeTimers */
\r
72 NULL, /* IdleCallback */
\r
73 0, /* ActiveMenus */
\r
74 NULL, /* MenuStateCallback */
\r
75 NULL, /* MenuStatusCallback */
\r
76 { 640, 480, GL_TRUE }, /* GameModeSize */
\r
77 16, /* GameModeDepth */
\r
78 72, /* GameModeRefresh */
\r
79 GLUT_ACTION_EXIT, /* ActionOnWindowClose */
\r
80 GLUT_EXEC_STATE_INIT, /* ExecState */
\r
81 NULL, /* ProgramName */
\r
82 GL_FALSE, /* JoysticksInitialised */
\r
83 0, /* NumActiveJoysticks */
\r
84 GL_FALSE, /* InputDevsInitialised */
\r
85 0, /* MouseWheelTicks */
\r
86 1, /* AuxiliaryBufferNumber */
\r
87 4, /* SampleNumber */
\r
88 1, /* MajorVersion */
\r
89 0, /* MinorVersion */
\r
90 0, /* ContextFlags */
\r
91 0, /* ContextProfile */
\r
92 NULL, /* ErrorFunc */
\r
93 NULL /* WarningFunc */
\r
97 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
\r
99 extern void fgPlatformInitialize( const char* displayName );
\r
100 extern void fgPlatformDeinitialiseInputDevices ( void );
\r
101 extern void fgPlatformCloseDisplay ( void );
\r
104 void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
\r
107 int i, j, argc = *pargc;
\r
110 /* check if GLUT_FPS env var is set */
\r
111 const char *fps = getenv( "GLUT_FPS" );
\r
116 sscanf( fps, "%d", &interval );
\r
118 if( interval <= 0 )
\r
119 fgState.FPSInterval = 5000; /* 5000 millisecond default */
\r
121 fgState.FPSInterval = interval;
\r
125 *pDisplayName = getenv( "DISPLAY" );
\r
127 for( i = 1; i < argc; i++ )
\r
129 if( strcmp( argv[ i ], "-display" ) == 0 )
\r
132 fgError( "-display parameter must be followed by display name" );
\r
134 *pDisplayName = argv[ i ];
\r
136 argv[ i - 1 ] = NULL;
\r
140 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
\r
143 fgError( "-geometry parameter must be followed by window "
\r
144 "geometry settings" );
\r
146 *pGeometry = argv[ i ];
\r
148 argv[ i - 1 ] = NULL;
\r
152 else if( strcmp( argv[ i ], "-direct" ) == 0)
\r
154 if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
\r
155 fgError( "parameters ambiguity, -direct and -indirect "
\r
156 "cannot be both specified" );
\r
158 fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
\r
162 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
\r
164 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
\r
165 fgError( "parameters ambiguity, -direct and -indirect "
\r
166 "cannot be both specified" );
\r
168 fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
\r
172 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
\r
174 fgState.ForceIconic = GL_TRUE;
\r
178 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
\r
180 fgState.GLDebugSwitch = GL_TRUE;
\r
184 else if( strcmp( argv[ i ], "-sync" ) == 0 )
\r
186 fgState.XSyncSwitch = GL_TRUE;
\r
192 /* Compact {argv}. */
\r
193 for( i = j = 1; i < *pargc; i++, j++ )
\r
195 /* Guaranteed to end because there are "*pargc" arguments left */
\r
196 while ( argv[ j ] == NULL )
\r
199 argv[ i ] = argv[ j ];
\r
202 #endif /* _WIN32_WCE */
\r
207 void fghCloseInputDevices ( void )
\r
209 if ( fgState.JoysticksInitialised )
\r
210 fgJoystickClose( );
\r
212 if ( fgState.InputDevsInitialised )
\r
213 fgInputDeviceClose( );
\r
218 * Perform the freeglut deinitialization...
\r
220 void fgDeinitialize( void )
\r
224 if( !fgState.Initialised )
\r
229 /* If we're in game mode, we want to leave game mode */
\r
230 if( fgStructure.GameModeWindow ) {
\r
231 glutLeaveGameMode();
\r
234 /* If there was a menu created, destroy the rendering context */
\r
235 if( fgStructure.MenuContext )
\r
237 #if TARGET_HOST_POSIX_X11
\r
238 /* Note that the MVisualInfo is not owned by the MenuContext! */
\r
239 glXDestroyContext( fgDisplay.pDisplay.Display, fgStructure.MenuContext->MContext );
\r
241 free( fgStructure.MenuContext );
\r
242 fgStructure.MenuContext = NULL;
\r
245 fgDestroyStructure( );
\r
247 while( ( timer = fgState.Timers.First) )
\r
249 fgListRemove( &fgState.Timers, &timer->Node );
\r
253 while( ( timer = fgState.FreeTimers.First) )
\r
255 fgListRemove( &fgState.FreeTimers, &timer->Node );
\r
259 fgPlatformDeinitialiseInputDevices ();
\r
261 fgState.MouseWheelTicks = 0;
\r
263 fgState.MajorVersion = 1;
\r
264 fgState.MinorVersion = 0;
\r
265 fgState.ContextFlags = 0;
\r
266 fgState.ContextProfile = 0;
\r
268 fgState.Initialised = GL_FALSE;
\r
270 fgState.Position.X = -1;
\r
271 fgState.Position.Y = -1;
\r
272 fgState.Position.Use = GL_FALSE;
\r
274 fgState.Size.X = 300;
\r
275 fgState.Size.Y = 300;
\r
276 fgState.Size.Use = GL_TRUE;
\r
278 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
\r
280 fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
\r
281 fgState.ForceIconic = GL_FALSE;
\r
282 fgState.UseCurrentContext = GL_FALSE;
\r
283 fgState.GLDebugSwitch = GL_FALSE;
\r
284 fgState.XSyncSwitch = GL_FALSE;
\r
285 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
\r
286 fgState.ExecState = GLUT_EXEC_STATE_INIT;
\r
288 fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
\r
289 fgState.Modifiers = INVALID_MODIFIERS;
\r
291 fgState.GameModeSize.X = 640;
\r
292 fgState.GameModeSize.Y = 480;
\r
293 fgState.GameModeDepth = 16;
\r
294 fgState.GameModeRefresh = 72;
\r
296 fgListInit( &fgState.Timers );
\r
297 fgListInit( &fgState.FreeTimers );
\r
299 fgState.IdleCallback = NULL;
\r
300 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
\r
301 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
\r
303 fgState.SwapCount = 0;
\r
304 fgState.SwapTime = 0;
\r
305 fgState.FPSInterval = 0;
\r
307 if( fgState.ProgramName )
\r
309 free( fgState.ProgramName );
\r
310 fgState.ProgramName = NULL;
\r
313 fgPlatformCloseDisplay ();
\r
315 fgState.Initialised = GL_FALSE;
\r
319 #if TARGET_HOST_MS_WINDOWS
\r
320 #define NoValue 0x0000
\r
321 #define XValue 0x0001
\r
322 #define YValue 0x0002
\r
323 #define WidthValue 0x0004
\r
324 #define HeightValue 0x0008
\r
325 #define AllValues 0x000F
\r
326 #define XNegative 0x0010
\r
327 #define YNegative 0x0020
\r
329 extern int XParseGeometry (
\r
330 const char *string,
\r
333 unsigned int *width, /* RETURN */
\r
334 unsigned int *height); /* RETURN */
\r
337 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
\r
340 * Perform initialization. This usually happens on the program startup
\r
341 * and restarting after glutMainLoop termination...
\r
343 void FGAPIENTRY glutInit( int* pargc, char** argv )
\r
345 char* displayName = NULL;
\r
346 char* geometry = NULL;
\r
347 if( fgState.Initialised )
\r
348 fgError( "illegal glutInit() reinitialization attempt" );
\r
350 if (pargc && *pargc && argv && *argv && **argv)
\r
352 fgState.ProgramName = strdup (*argv);
\r
354 if( !fgState.ProgramName )
\r
355 fgError ("Could not allocate space for the program's name.");
\r
358 fgCreateStructure( );
\r
360 /* Get start time */
\r
361 fgState.Time = fgSystemTime();
\r
363 fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
\r
366 * Have the display created now. If there wasn't a "-display"
\r
367 * in the program arguments, we will use the DISPLAY environment
\r
368 * variable for opening the X display (see code above):
\r
370 fgPlatformInitialize( displayName );
\r
373 * Geometry parsing deffered until here because we may need the screen
\r
379 unsigned int parsedWidth, parsedHeight;
\r
380 int mask = XParseGeometry( geometry,
\r
381 &fgState.Position.X, &fgState.Position.Y,
\r
382 &parsedWidth, &parsedHeight );
\r
383 /* TODO: Check for overflow? */
\r
384 fgState.Size.X = parsedWidth;
\r
385 fgState.Size.Y = parsedHeight;
\r
387 if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
\r
388 fgState.Size.Use = GL_TRUE;
\r
390 if( mask & XNegative )
\r
391 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
\r
393 if( mask & YNegative )
\r
394 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
\r
396 if( (mask & (XValue|YValue)) == (XValue|YValue) )
\r
397 fgState.Position.Use = GL_TRUE;
\r
402 * Undoes all the "glutInit" stuff
\r
404 void FGAPIENTRY glutExit ( void )
\r
410 * Sets the default initial window position for new windows
\r
412 void FGAPIENTRY glutInitWindowPosition( int x, int y )
\r
414 fgState.Position.X = x;
\r
415 fgState.Position.Y = y;
\r
417 if( ( x >= 0 ) && ( y >= 0 ) )
\r
418 fgState.Position.Use = GL_TRUE;
\r
420 fgState.Position.Use = GL_FALSE;
\r
424 * Sets the default initial window size for new windows
\r
426 void FGAPIENTRY glutInitWindowSize( int width, int height )
\r
428 fgState.Size.X = width;
\r
429 fgState.Size.Y = height;
\r
431 if( ( width > 0 ) && ( height > 0 ) )
\r
432 fgState.Size.Use = GL_TRUE;
\r
434 fgState.Size.Use = GL_FALSE;
\r
438 * Sets the default display mode for all new windows
\r
440 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
\r
442 /* We will make use of this value when creating a new OpenGL context... */
\r
443 fgState.DisplayMode = displayMode;
\r
447 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
\r
449 static char* Tokens[] =
\r
451 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
\r
452 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
\r
453 "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
\r
454 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
\r
455 "xtruecolor", "xdirectcolor",
\r
456 "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
\r
457 "xtruecolour", "xdirectcolour", "borderless", "aux"
\r
459 #define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
\r
461 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
\r
463 int glut_state_flag = 0 ;
\r
465 * Unpack a lot of options from a character string. The options are
\r
466 * delimited by blanks or tabs.
\r
469 size_t len = strlen ( displayMode );
\r
470 char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
\r
471 memcpy ( buffer, displayMode, len );
\r
472 buffer[len] = '\0';
\r
474 token = strtok ( buffer, " \t" );
\r
478 /* Process this token */
\r
481 /* Temporary fix: Ignore any length specifications and at least
\r
482 * process the basic token
\r
483 * TODO: Fix this permanently
\r
485 size_t cleanlength = strcspn ( token, "=<>~!" );
\r
487 for ( i = 0; i < NUM_TOKENS; i++ )
\r
489 if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
\r
494 case 0 : /* "alpha": Alpha color buffer precision in bits */
\r
495 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
\r
498 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
\r
499 precision in bits */
\r
502 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
\r
503 in bits with zero bits alpha */
\r
504 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
\r
507 case 3 : /* "blue": Blue color buffer precision in bits */
\r
510 case 4 : /* "buffer": Number of bits in the color index color buffer
\r
514 case 5 : /* "conformant": Boolean indicating if the frame buffer
\r
515 configuration is conformant or not */
\r
518 case 6 : /* "depth": Number of bits of precsion in the depth buffer */
\r
519 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
\r
522 case 7 : /* "double": Boolean indicating if the color buffer is
\r
524 glut_state_flag |= GLUT_DOUBLE ;
\r
527 case 8 : /* "green": Green color buffer precision in bits */
\r
530 case 9 : /* "index": Boolean if the color model is color index or not
\r
532 glut_state_flag |= GLUT_INDEX ;
\r
535 case 10 : /* "num": A special capability name indicating where the
\r
536 value represents the Nth frame buffer configuration
\r
537 matching the description string */
\r
540 case 11 : /* "red": Red color buffer precision in bits */
\r
543 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
\r
544 the RGBA color buffer */
\r
545 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
\r
548 case 13 : /* "rgb": Number of bits of red, green, and blue in the
\r
549 RGBA color buffer with zero bits alpha */
\r
550 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
\r
553 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
\r
554 bits of green, blue (alpha not specified) of color buffer
\r
556 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
\r
559 case 15 : /* "stencil": Number of bits in the stencil buffer */
\r
560 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
\r
563 case 16 : /* "single": Boolean indicate the color buffer is single
\r
565 glut_state_flag |= GLUT_SINGLE ;
\r
568 case 17 : /* "stereo": Boolean indicating the color buffer supports
\r
569 OpenGL-style stereo */
\r
570 glut_state_flag |= GLUT_STEREO ;
\r
573 case 18 : /* "samples": Indicates the number of multisamples to use
\r
574 based on GLX's SGIS_multisample extension (for
\r
576 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
\r
579 case 19 : /* "slow": Boolean indicating if the frame buffer
\r
580 configuration is slow or not */
\r
583 case 20 : /* "win32pdf": (incorrect spelling but was there before */
\r
584 case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
\r
586 #if TARGET_HOST_MS_WINDOWS
\r
590 case 22 : /* "xvisual": matches the X visual ID by number */
\r
591 #if TARGET_HOST_POSIX_X11
\r
595 case 23 : /* "xstaticgray": */
\r
596 case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
\r
597 configuration's X visual is of type StaticGray */
\r
598 #if TARGET_HOST_POSIX_X11
\r
602 case 24 : /* "xgrayscale": */
\r
603 case 30 : /* "xgreyscale": boolean indicating if the frame buffer
\r
604 configuration's X visual is of type GrayScale */
\r
605 #if TARGET_HOST_POSIX_X11
\r
609 case 25 : /* "xstaticcolor": */
\r
610 case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
\r
611 configuration's X visual is of type StaticColor */
\r
612 #if TARGET_HOST_POSIX_X11
\r
616 case 26 : /* "xpseudocolor": */
\r
617 case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
\r
618 configuration's X visual is of type PseudoColor */
\r
619 #if TARGET_HOST_POSIX_X11
\r
623 case 27 : /* "xtruecolor": */
\r
624 case 33 : /* "xtruecolour": boolean indicating if the frame buffer
\r
625 configuration's X visual is of type TrueColor */
\r
626 #if TARGET_HOST_POSIX_X11
\r
630 case 28 : /* "xdirectcolor": */
\r
631 case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
\r
632 configuration's X visual is of type DirectColor */
\r
633 #if TARGET_HOST_POSIX_X11
\r
637 case 35 : /* "borderless": windows should not have borders */
\r
638 #if TARGET_HOST_POSIX_X11
\r
642 case 36 : /* "aux": some number of aux buffers */
\r
643 glut_state_flag |= GLUT_AUX;
\r
646 case 37 : /* Unrecognized */
\r
647 fgWarning ( "WARNING - Display string token not recognized: %s",
\r
652 token = strtok ( NULL, " \t" );
\r
657 /* We will make use of this value when creating a new OpenGL context... */
\r
658 fgState.DisplayMode = glut_state_flag;
\r
661 /* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
\r
663 void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
\r
665 /* We will make use of these valuse when creating a new OpenGL context... */
\r
666 fgState.MajorVersion = majorVersion;
\r
667 fgState.MinorVersion = minorVersion;
\r
671 void FGAPIENTRY glutInitContextFlags( int flags )
\r
673 /* We will make use of this value when creating a new OpenGL context... */
\r
674 fgState.ContextFlags = flags;
\r
677 void FGAPIENTRY glutInitContextProfile( int profile )
\r
679 /* We will make use of this value when creating a new OpenGL context... */
\r
680 fgState.ContextProfile = profile;
\r
683 /* -------------- User Defined Error/Warning Handler Support -------------- */
\r
686 * Sets the user error handler (note the use of va_list for the args to the fmt)
\r
688 void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
\r
690 /* This allows user programs to handle freeglut errors */
\r
691 fgState.ErrorFunc = vfgError;
\r
695 * Sets the user warning handler (note the use of va_list for the args to the fmt)
\r
697 void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
\r
699 /* This allows user programs to handle freeglut warnings */
\r
700 fgState.WarningFunc = vfgWarning;
\r
703 /*** END OF FILE ***/
\r