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
102 extern void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext );
\r
105 void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
\r
108 int i, j, argc = *pargc;
\r
111 /* check if GLUT_FPS env var is set */
\r
112 const char *fps = getenv( "GLUT_FPS" );
\r
117 sscanf( fps, "%d", &interval );
\r
119 if( interval <= 0 )
\r
120 fgState.FPSInterval = 5000; /* 5000 millisecond default */
\r
122 fgState.FPSInterval = interval;
\r
126 *pDisplayName = getenv( "DISPLAY" );
\r
128 for( i = 1; i < argc; i++ )
\r
130 if( strcmp( argv[ i ], "-display" ) == 0 )
\r
133 fgError( "-display parameter must be followed by display name" );
\r
135 *pDisplayName = argv[ i ];
\r
137 argv[ i - 1 ] = NULL;
\r
141 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
\r
144 fgError( "-geometry parameter must be followed by window "
\r
145 "geometry settings" );
\r
147 *pGeometry = argv[ i ];
\r
149 argv[ i - 1 ] = NULL;
\r
153 else if( strcmp( argv[ i ], "-direct" ) == 0)
\r
155 if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
\r
156 fgError( "parameters ambiguity, -direct and -indirect "
\r
157 "cannot be both specified" );
\r
159 fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
\r
163 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
\r
165 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
\r
166 fgError( "parameters ambiguity, -direct and -indirect "
\r
167 "cannot be both specified" );
\r
169 fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
\r
173 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
\r
175 fgState.ForceIconic = GL_TRUE;
\r
179 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
\r
181 fgState.GLDebugSwitch = GL_TRUE;
\r
185 else if( strcmp( argv[ i ], "-sync" ) == 0 )
\r
187 fgState.XSyncSwitch = GL_TRUE;
\r
193 /* Compact {argv}. */
\r
194 for( i = j = 1; i < *pargc; i++, j++ )
\r
196 /* Guaranteed to end because there are "*pargc" arguments left */
\r
197 while ( argv[ j ] == NULL )
\r
200 argv[ i ] = argv[ j ];
\r
203 #endif /* _WIN32_WCE */
\r
208 void fghCloseInputDevices ( void )
\r
210 if ( fgState.JoysticksInitialised )
\r
211 fgJoystickClose( );
\r
213 if ( fgState.InputDevsInitialised )
\r
214 fgInputDeviceClose( );
\r
219 * Perform the freeglut deinitialization...
\r
221 void fgDeinitialize( void )
\r
225 if( !fgState.Initialised )
\r
230 /* If we're in game mode, we want to leave game mode */
\r
231 if( fgStructure.GameModeWindow ) {
\r
232 glutLeaveGameMode();
\r
235 /* If there was a menu created, destroy the rendering context */
\r
236 if( fgStructure.MenuContext )
\r
238 fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
\r
239 free( fgStructure.MenuContext );
\r
240 fgStructure.MenuContext = NULL;
\r
243 fgDestroyStructure( );
\r
245 while( ( timer = fgState.Timers.First) )
\r
247 fgListRemove( &fgState.Timers, &timer->Node );
\r
251 while( ( timer = fgState.FreeTimers.First) )
\r
253 fgListRemove( &fgState.FreeTimers, &timer->Node );
\r
257 fgPlatformDeinitialiseInputDevices ();
\r
259 fgState.MouseWheelTicks = 0;
\r
261 fgState.MajorVersion = 1;
\r
262 fgState.MinorVersion = 0;
\r
263 fgState.ContextFlags = 0;
\r
264 fgState.ContextProfile = 0;
\r
266 fgState.Initialised = GL_FALSE;
\r
268 fgState.Position.X = -1;
\r
269 fgState.Position.Y = -1;
\r
270 fgState.Position.Use = GL_FALSE;
\r
272 fgState.Size.X = 300;
\r
273 fgState.Size.Y = 300;
\r
274 fgState.Size.Use = GL_TRUE;
\r
276 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
\r
278 fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
\r
279 fgState.ForceIconic = GL_FALSE;
\r
280 fgState.UseCurrentContext = GL_FALSE;
\r
281 fgState.GLDebugSwitch = GL_FALSE;
\r
282 fgState.XSyncSwitch = GL_FALSE;
\r
283 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
\r
284 fgState.ExecState = GLUT_EXEC_STATE_INIT;
\r
286 fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
\r
287 fgState.Modifiers = INVALID_MODIFIERS;
\r
289 fgState.GameModeSize.X = 640;
\r
290 fgState.GameModeSize.Y = 480;
\r
291 fgState.GameModeDepth = 16;
\r
292 fgState.GameModeRefresh = 72;
\r
294 fgListInit( &fgState.Timers );
\r
295 fgListInit( &fgState.FreeTimers );
\r
297 fgState.IdleCallback = NULL;
\r
298 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
\r
299 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
\r
301 fgState.SwapCount = 0;
\r
302 fgState.SwapTime = 0;
\r
303 fgState.FPSInterval = 0;
\r
305 if( fgState.ProgramName )
\r
307 free( fgState.ProgramName );
\r
308 fgState.ProgramName = NULL;
\r
311 fgPlatformCloseDisplay ();
\r
313 fgState.Initialised = GL_FALSE;
\r
317 #if TARGET_HOST_MS_WINDOWS
\r
318 #define NoValue 0x0000
\r
319 #define XValue 0x0001
\r
320 #define YValue 0x0002
\r
321 #define WidthValue 0x0004
\r
322 #define HeightValue 0x0008
\r
323 #define AllValues 0x000F
\r
324 #define XNegative 0x0010
\r
325 #define YNegative 0x0020
\r
327 extern int XParseGeometry (
\r
328 const char *string,
\r
331 unsigned int *width, /* RETURN */
\r
332 unsigned int *height); /* RETURN */
\r
335 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
\r
338 * Perform initialization. This usually happens on the program startup
\r
339 * and restarting after glutMainLoop termination...
\r
341 void FGAPIENTRY glutInit( int* pargc, char** argv )
\r
343 char* displayName = NULL;
\r
344 char* geometry = NULL;
\r
345 if( fgState.Initialised )
\r
346 fgError( "illegal glutInit() reinitialization attempt" );
\r
348 if (pargc && *pargc && argv && *argv && **argv)
\r
350 fgState.ProgramName = strdup (*argv);
\r
352 if( !fgState.ProgramName )
\r
353 fgError ("Could not allocate space for the program's name.");
\r
356 fgCreateStructure( );
\r
358 /* Get start time */
\r
359 fgState.Time = fgSystemTime();
\r
361 fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
\r
364 * Have the display created now. If there wasn't a "-display"
\r
365 * in the program arguments, we will use the DISPLAY environment
\r
366 * variable for opening the X display (see code above):
\r
368 fgPlatformInitialize( displayName );
\r
371 * Geometry parsing deffered until here because we may need the screen
\r
377 unsigned int parsedWidth, parsedHeight;
\r
378 int mask = XParseGeometry( geometry,
\r
379 &fgState.Position.X, &fgState.Position.Y,
\r
380 &parsedWidth, &parsedHeight );
\r
381 /* TODO: Check for overflow? */
\r
382 fgState.Size.X = parsedWidth;
\r
383 fgState.Size.Y = parsedHeight;
\r
385 if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
\r
386 fgState.Size.Use = GL_TRUE;
\r
388 if( mask & XNegative )
\r
389 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
\r
391 if( mask & YNegative )
\r
392 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
\r
394 if( (mask & (XValue|YValue)) == (XValue|YValue) )
\r
395 fgState.Position.Use = GL_TRUE;
\r
400 * Undoes all the "glutInit" stuff
\r
402 void FGAPIENTRY glutExit ( void )
\r
408 * Sets the default initial window position for new windows
\r
410 void FGAPIENTRY glutInitWindowPosition( int x, int y )
\r
412 fgState.Position.X = x;
\r
413 fgState.Position.Y = y;
\r
415 if( ( x >= 0 ) && ( y >= 0 ) )
\r
416 fgState.Position.Use = GL_TRUE;
\r
418 fgState.Position.Use = GL_FALSE;
\r
422 * Sets the default initial window size for new windows
\r
424 void FGAPIENTRY glutInitWindowSize( int width, int height )
\r
426 fgState.Size.X = width;
\r
427 fgState.Size.Y = height;
\r
429 if( ( width > 0 ) && ( height > 0 ) )
\r
430 fgState.Size.Use = GL_TRUE;
\r
432 fgState.Size.Use = GL_FALSE;
\r
436 * Sets the default display mode for all new windows
\r
438 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
\r
440 /* We will make use of this value when creating a new OpenGL context... */
\r
441 fgState.DisplayMode = displayMode;
\r
445 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
\r
447 static char* Tokens[] =
\r
449 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
\r
450 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
\r
451 "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
\r
452 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
\r
453 "xtruecolor", "xdirectcolor",
\r
454 "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
\r
455 "xtruecolour", "xdirectcolour", "borderless", "aux"
\r
457 #define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
\r
459 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
\r
461 int glut_state_flag = 0 ;
\r
463 * Unpack a lot of options from a character string. The options are
\r
464 * delimited by blanks or tabs.
\r
467 size_t len = strlen ( displayMode );
\r
468 char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
\r
469 memcpy ( buffer, displayMode, len );
\r
470 buffer[len] = '\0';
\r
472 token = strtok ( buffer, " \t" );
\r
476 /* Process this token */
\r
479 /* Temporary fix: Ignore any length specifications and at least
\r
480 * process the basic token
\r
481 * TODO: Fix this permanently
\r
483 size_t cleanlength = strcspn ( token, "=<>~!" );
\r
485 for ( i = 0; i < NUM_TOKENS; i++ )
\r
487 if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
\r
492 case 0 : /* "alpha": Alpha color buffer precision in bits */
\r
493 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
\r
496 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
\r
497 precision in bits */
\r
500 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
\r
501 in bits with zero bits alpha */
\r
502 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
\r
505 case 3 : /* "blue": Blue color buffer precision in bits */
\r
508 case 4 : /* "buffer": Number of bits in the color index color buffer
\r
512 case 5 : /* "conformant": Boolean indicating if the frame buffer
\r
513 configuration is conformant or not */
\r
516 case 6 : /* "depth": Number of bits of precsion in the depth buffer */
\r
517 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
\r
520 case 7 : /* "double": Boolean indicating if the color buffer is
\r
522 glut_state_flag |= GLUT_DOUBLE ;
\r
525 case 8 : /* "green": Green color buffer precision in bits */
\r
528 case 9 : /* "index": Boolean if the color model is color index or not
\r
530 glut_state_flag |= GLUT_INDEX ;
\r
533 case 10 : /* "num": A special capability name indicating where the
\r
534 value represents the Nth frame buffer configuration
\r
535 matching the description string */
\r
538 case 11 : /* "red": Red color buffer precision in bits */
\r
541 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
\r
542 the RGBA color buffer */
\r
543 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
\r
546 case 13 : /* "rgb": Number of bits of red, green, and blue in the
\r
547 RGBA color buffer with zero bits alpha */
\r
548 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
\r
551 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
\r
552 bits of green, blue (alpha not specified) of color buffer
\r
554 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
\r
557 case 15 : /* "stencil": Number of bits in the stencil buffer */
\r
558 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
\r
561 case 16 : /* "single": Boolean indicate the color buffer is single
\r
563 glut_state_flag |= GLUT_SINGLE ;
\r
566 case 17 : /* "stereo": Boolean indicating the color buffer supports
\r
567 OpenGL-style stereo */
\r
568 glut_state_flag |= GLUT_STEREO ;
\r
571 case 18 : /* "samples": Indicates the number of multisamples to use
\r
572 based on GLX's SGIS_multisample extension (for
\r
574 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
\r
577 case 19 : /* "slow": Boolean indicating if the frame buffer
\r
578 configuration is slow or not */
\r
581 case 20 : /* "win32pdf": (incorrect spelling but was there before */
\r
582 case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
\r
584 #if TARGET_HOST_MS_WINDOWS
\r
588 case 22 : /* "xvisual": matches the X visual ID by number */
\r
589 #if TARGET_HOST_POSIX_X11
\r
593 case 23 : /* "xstaticgray": */
\r
594 case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
\r
595 configuration's X visual is of type StaticGray */
\r
596 #if TARGET_HOST_POSIX_X11
\r
600 case 24 : /* "xgrayscale": */
\r
601 case 30 : /* "xgreyscale": boolean indicating if the frame buffer
\r
602 configuration's X visual is of type GrayScale */
\r
603 #if TARGET_HOST_POSIX_X11
\r
607 case 25 : /* "xstaticcolor": */
\r
608 case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
\r
609 configuration's X visual is of type StaticColor */
\r
610 #if TARGET_HOST_POSIX_X11
\r
614 case 26 : /* "xpseudocolor": */
\r
615 case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
\r
616 configuration's X visual is of type PseudoColor */
\r
617 #if TARGET_HOST_POSIX_X11
\r
621 case 27 : /* "xtruecolor": */
\r
622 case 33 : /* "xtruecolour": boolean indicating if the frame buffer
\r
623 configuration's X visual is of type TrueColor */
\r
624 #if TARGET_HOST_POSIX_X11
\r
628 case 28 : /* "xdirectcolor": */
\r
629 case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
\r
630 configuration's X visual is of type DirectColor */
\r
631 #if TARGET_HOST_POSIX_X11
\r
635 case 35 : /* "borderless": windows should not have borders */
\r
636 #if TARGET_HOST_POSIX_X11
\r
640 case 36 : /* "aux": some number of aux buffers */
\r
641 glut_state_flag |= GLUT_AUX;
\r
644 case 37 : /* Unrecognized */
\r
645 fgWarning ( "WARNING - Display string token not recognized: %s",
\r
650 token = strtok ( NULL, " \t" );
\r
655 /* We will make use of this value when creating a new OpenGL context... */
\r
656 fgState.DisplayMode = glut_state_flag;
\r
659 /* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
\r
661 void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
\r
663 /* We will make use of these valuse when creating a new OpenGL context... */
\r
664 fgState.MajorVersion = majorVersion;
\r
665 fgState.MinorVersion = minorVersion;
\r
669 void FGAPIENTRY glutInitContextFlags( int flags )
\r
671 /* We will make use of this value when creating a new OpenGL context... */
\r
672 fgState.ContextFlags = flags;
\r
675 void FGAPIENTRY glutInitContextProfile( int profile )
\r
677 /* We will make use of this value when creating a new OpenGL context... */
\r
678 fgState.ContextProfile = profile;
\r
681 /* -------------- User Defined Error/Warning Handler Support -------------- */
\r
684 * Sets the user error handler (note the use of va_list for the args to the fmt)
\r
686 void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
\r
688 /* This allows user programs to handle freeglut errors */
\r
689 fgState.ErrorFunc = vfgError;
\r
693 * Sets the user warning handler (note the use of va_list for the args to the fmt)
\r
695 void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
\r
697 /* This allows user programs to handle freeglut warnings */
\r
698 fgState.WarningFunc = vfgWarning;
\r
701 /*** END OF FILE ***/
\r