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.
32 #include "../include/GL/freeglut.h"
33 #include "freeglut_internal.h"
36 * TODO BEFORE THE STABLE RELEASE:
38 * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific
39 * deinitialization done
40 * glutInitDisplayString() -- display mode string parsing
42 * Wouldn't it be cool to use gettext() for error messages? I just love
43 * bash saying "nie znaleziono pliku" instead of "file not found" :)
44 * Is gettext easily portable?
47 /* -- GLOBAL VARIABLES ----------------------------------------------------- */
50 * A structure pointed by g_pDisplay holds all information
51 * regarding the display, screen, root window etc.
53 SFG_Display fgDisplay;
56 * The settings for the current freeglut session
58 SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
59 { 300, 300, GL_TRUE }, /* Size */
60 GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
61 GL_FALSE, /* Initalized */
62 GL_FALSE, /* ForceDirectContext */
63 GL_TRUE, /* TryDirectContext */
64 GL_FALSE, /* ForceIconic */
65 GL_FALSE, /* UseCurrentContext */
66 GL_FALSE, /* GLDebugSwitch */
67 GL_FALSE, /* XSyncSwitch */
68 GL_TRUE, /* IgnoreKeyRepeat */
69 0xffffffff, /* Modifiers */
74 { 0, GL_FALSE }, /* Time */
76 { { 0, 0 }, GL_FALSE },
78 { NULL, NULL }, /* Timers */
79 NULL, /* IdleCallback */
81 NULL, /* MenuStateCallback */
82 NULL, /* MenuStatusCallback */
83 { 640, 480, GL_TRUE }, /* GameModeSize */
84 16, /* GameModeDepth */
85 72, /* GameModeRefresh */
86 GLUT_ACTION_EXIT, /* ActionOnWindowClose */
87 GLUT_EXEC_STATE_INIT /* ExecState */
88 NULL, /* ProgramName */
92 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
95 * A call to this function should initialize all the display stuff...
97 void fgInitialize( const char* displayName )
99 #if TARGET_HOST_UNIX_X11
100 fgDisplay.Display = XOpenDisplay( displayName );
102 if( fgDisplay.Display == NULL )
103 fgError( "failed to open display '%s'", XDisplayName( displayName ) );
105 if( !glXQueryExtension( fgDisplay.Display, NULL, NULL ) )
106 fgError( "OpenGL GLX extension not supported by display '%s'",
107 XDisplayName( displayName ) );
109 fgDisplay.Screen = DefaultScreen( fgDisplay.Display );
110 fgDisplay.RootWindow = RootWindow(
115 fgDisplay.ScreenWidth = DisplayWidth(
119 fgDisplay.ScreenHeight = DisplayHeight(
124 fgDisplay.ScreenWidthMM = DisplayWidthMM(
128 fgDisplay.ScreenHeightMM = DisplayHeightMM(
133 fgDisplay.Connection = ConnectionNumber( fgDisplay.Display );
136 * Create the window deletion atom
138 fgDisplay.DeleteWindow = XInternAtom(
144 #elif TARGET_HOST_WIN32
150 * What we need to do is to initialize the fgDisplay global structure here...
152 fgDisplay.Instance = GetModuleHandle( NULL );
154 atom = GetClassInfo( fgDisplay.Instance, "FREEGLUT", &wc );
157 ZeroMemory( &wc, sizeof(WNDCLASS) );
160 * Each of the windows should have its own device context...
163 wc.lpfnWndProc = fgWindowProc;
166 wc.hInstance = fgDisplay.Instance;
167 wc.hIcon = LoadIcon( fgDisplay.Instance, "GLUT_ICON" );
169 wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
171 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
172 wc.hbrBackground = NULL;
173 wc.lpszMenuName = NULL;
174 wc.lpszClassName = "FREEGLUT";
177 * Register the window class
179 atom = RegisterClass( &wc );
184 * The screen dimensions can be obtained via GetSystemMetrics() calls
186 fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXSCREEN );
187 fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );
190 HWND desktop = GetDesktopWindow( );
191 HDC context = GetDC( desktop );
193 fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
194 fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
196 ReleaseDC( desktop, context );
203 fgState.Initalized = GL_TRUE;
207 * Perform the freeglut deinitialization...
209 void fgDeinitialize( void )
213 if( !fgState.Initalized )
215 fgWarning( "fgDeinitialize(): "
216 "no valid initialization has been performed" );
220 /* fgState.Initalized = GL_FALSE; */
223 * If there was a menu created, destroy the rendering context
225 if( fgStructure.MenuContext )
227 free( fgStructure.MenuContext );
228 fgStructure.MenuContext = NULL;
231 fgDestroyStructure( );
233 while( timer = ( SFG_Timer * )fgState.Timers.First )
235 fgListRemove ( &fgState.Timers, &timer->Node );
241 fgState.Initalized = GL_FALSE;
243 fgState.Position.X = -1;
244 fgState.Position.Y = -1;
245 fgState.Position.Use = GL_FALSE;
247 fgState.Size.X = 300;
248 fgState.Size.Y = 300;
249 fgState.Size.Use = GL_TRUE;
251 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
253 fgState.ForceDirectContext = GL_FALSE;
254 fgState.TryDirectContext = GL_TRUE;
255 fgState.ForceIconic = GL_FALSE;
256 fgState.UseCurrentContext = GL_FALSE;
257 fgState.GLDebugSwitch = GL_FALSE;
258 fgState.XSyncSwitch = GL_FALSE;
259 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
260 fgState.ExecState = GLUT_EXEC_STATE_INIT;
262 fgState.IgnoreKeyRepeat = GL_TRUE;
263 fgState.Modifiers = 0xffffffff;
265 fgState.GameModeSize.X = 640;
266 fgState.GameModeSize.Y = 480;
267 fgState.GameModeDepth = 16;
268 fgState.GameModeRefresh = 72;
270 fgState.Time.Set = GL_FALSE;
272 fgState.Timers.First = fgState.Timers.Last = NULL;
273 fgState.IdleCallback = NULL;
274 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
275 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
277 fgState.SwapCount = 0;
278 fgState.SwapTime = 0;
279 fgState.FPSInterval = 0;
281 if( fgState.ProgramName )
283 free( fgState.ProgramName );
284 fgState.ProgramName = NULL;
288 #if TARGET_HOST_UNIX_X11
291 * Make sure all X-client data we have created will be destroyed on
294 XSetCloseDownMode( fgDisplay.Display, DestroyAll );
297 * Close the display connection, destroying all windows we have
300 XCloseDisplay( fgDisplay.Display );
306 * Everything inside the following #ifndef is copied from the X sources.
309 #ifndef TARGET_HOST_UNIX_X11
311 #define NoValue 0x0000
312 #define XValue 0x0001
313 #define YValue 0x0002
314 #define WidthValue 0x0004
315 #define HeightValue 0x0008
316 #define AllValues 0x000F
317 #define XNegative 0x0010
318 #define YNegative 0x0020
321 * XParseGeometry parses strings of the form
322 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
323 * width, height, xoffset, and yoffset are unsigned integers.
324 * Example: "=80x24+300-49"
325 * The equal sign is optional.
326 * It returns a bitmask that indicates which of the four values
327 * were actually found in the string. For each value found,
328 * the corresponding argument is updated; for each value
329 * not found, the corresponding argument is left unchanged.
333 ReadInteger(char *string, char **NextString)
335 register int Result = 0;
340 else if (*string == '-')
345 for (; (*string >= '0') && (*string <= '9'); string++)
347 Result = (Result * 10) + (*string - '0');
349 *NextString = string;
356 static int XParseGeometry (
357 _Xconst char *string,
360 unsigned int *width, /* RETURN */
361 unsigned int *height) /* RETURN */
364 register char *strind;
365 unsigned int tempWidth = 0, tempHeight = 0;
366 int tempX = 0, tempY = 0;
369 if ( (string == NULL) || (*string == '\0')) return(mask);
371 string++; /* ignore possible '=' at beg of geometry spec */
373 strind = (char *)string;
374 if (*strind != '+' && *strind != '-' && *strind != 'x') {
375 tempWidth = ReadInteger(strind, &nextCharacter);
376 if (strind == nextCharacter)
378 strind = nextCharacter;
382 if (*strind == 'x' || *strind == 'X') {
384 tempHeight = ReadInteger(strind, &nextCharacter);
385 if (strind == nextCharacter)
387 strind = nextCharacter;
391 if ((*strind == '+') || (*strind == '-')) {
392 if (*strind == '-') {
394 tempX = -ReadInteger(strind, &nextCharacter);
395 if (strind == nextCharacter)
397 strind = nextCharacter;
403 tempX = ReadInteger(strind, &nextCharacter);
404 if (strind == nextCharacter)
406 strind = nextCharacter;
409 if ((*strind == '+') || (*strind == '-')) {
410 if (*strind == '-') {
412 tempY = -ReadInteger(strind, &nextCharacter);
413 if (strind == nextCharacter)
415 strind = nextCharacter;
421 tempY = ReadInteger(strind, &nextCharacter);
422 if (strind == nextCharacter)
424 strind = nextCharacter;
430 /* If strind isn't at the end of the string the it's an invalid
431 geometry specification. */
433 if (*strind != '\0') return (0);
439 if (mask & WidthValue)
441 if (mask & HeightValue)
442 *height = tempHeight;
447 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
450 * Perform initialization. This usually happens on the program startup
451 * and restarting after glutMainLoop termination...
453 void FGAPIENTRY glutInit( int* pargc, char** argv )
455 char* displayName = NULL;
456 char* geometry = NULL;
457 int i, j, argc = *pargc;
459 if( fgState.Initalized )
460 fgError( "illegal glutInit() reinitialization attemp" );
462 if (pargc && *pargc && argv && *argv && **argv)
464 fgState.ProgramName = strdup (*argv);
466 if( !fgState.ProgramName )
467 fgError ("Could not allocate space for the program's name.");
470 fgCreateStructure( );
474 /* check if GLUT_FPS env var is set */
476 const char *fps = getenv( "GLUT_FPS" );
479 sscanf( fps, "%d", &fgState.FPSInterval );
480 if( fgState.FPSInterval <= 0 )
481 fgState.FPSInterval = 5000; /* 5000 milliseconds */
485 displayName = getenv( "DISPLAY");
487 for( i = 1; i < argc; i++ )
489 if( strcmp( argv[ i ], "-display" ) == 0 )
492 fgError( "-display parameter must be followed by display name" );
494 displayName = argv[ i ];
496 argv[ i - 1 ] = NULL;
500 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
503 fgError( "-geometry parameter must be followed by window "
504 "geometry settings" );
506 geometry = argv[ i ];
508 argv[ i - 1 ] = NULL;
512 else if( strcmp( argv[ i ], "-direct" ) == 0)
514 if( ! fgState.TryDirectContext )
515 fgError( "parameters ambiguity, -direct and -indirect "
516 "cannot be both specified" );
518 fgState.ForceDirectContext = GL_TRUE;
522 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
524 if( fgState.ForceDirectContext )
525 fgError( "parameters ambiguity, -direct and -indirect "
526 "cannot be both specified" );
528 fgState.TryDirectContext = GL_FALSE;
532 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
534 fgState.ForceIconic = GL_TRUE;
538 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
540 fgState.GLDebugSwitch = GL_TRUE;
544 else if( strcmp( argv[ i ], "-sync" ) == 0 )
546 fgState.XSyncSwitch = GL_TRUE;
556 for( i = 1; i < *pargc; i++, j++ )
558 if( argv[ i ] == NULL )
560 /* Guaranteed to end because there are "*pargc" arguments left */
561 while ( argv[ j ] == NULL )
563 argv[ i ] = argv[ j ];
568 * Have the display created now. As I am too lazy to implement
569 * the program arguments parsing, we will have the DISPLAY
570 * environment variable used for opening the X display:
572 * XXX The above comment is rather unclear. We have just
573 * XXX completed parsing of the program arguments for GLUT
574 * XXX parameters. We obviously canNOT parse the application-
575 * XXX specific parameters. Can someone re-write the above
578 fgInitialize( displayName );
581 * Geometry parsing deffered until here because we may need the screen
587 int mask = XParseGeometry( geometry,
588 &fgState.Position.X, &fgState.Position.Y,
589 &fgState.Size.X, &fgState.Size.Y );
591 if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
592 fgState.Size.Use = GL_TRUE;
594 if( mask & XNegative )
595 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
597 if( mask & YNegative )
598 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
600 if( (mask & (XValue|YValue)) == (XValue|YValue) )
601 fgState.Position.Use = GL_TRUE;
606 * Sets the default initial window position for new windows
608 void FGAPIENTRY glutInitWindowPosition( int x, int y )
610 fgState.Position.X = x;
611 fgState.Position.Y = y;
613 if( ( x >= 0 ) && ( y >= 0 ) )
614 fgState.Position.Use = GL_TRUE;
616 fgState.Position.Use = GL_FALSE;
620 * Sets the default initial window size for new windows
622 void FGAPIENTRY glutInitWindowSize( int width, int height )
624 fgState.Size.X = width;
625 fgState.Size.Y = height;
627 if( ( width > 0 ) && ( height > 0 ) )
628 fgState.Size.Use = GL_TRUE;
630 fgState.Size.Use = GL_FALSE;
634 * Sets the default display mode for all new windows
636 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
639 * We will make use of this value when creating a new OpenGL context...
641 fgState.DisplayMode = displayMode;
645 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
647 #define NUM_TOKENS 28
648 static char* Tokens[] =
650 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
651 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
652 "single", "stereo", "samples", "slow", "win32pdf", "xvisual",
653 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
654 "xtruecolor", "xdirectcolor"
657 static int TokenLengths[] =
659 5, 4, 3, 4, 6, 10, 5, 6,
660 5, 5, 3, 3, 4, 3, 9, 7,
666 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
668 int glut_state_flag = 0 ;
670 * Unpack a lot of options from a character string. The options are
671 * delimited by blanks or tabs.
674 int len = strlen ( displayMode ) ;
675 char *buffer = (char *)malloc ( (len+1) * sizeof(char) ) ;
676 memcpy ( buffer, displayMode, len ) ;
679 token = strtok ( buffer, " \t" ) ;
686 for ( i = 0; i < NUM_TOKENS; i++ )
688 if ( strncmp ( token, Tokens[i], TokenLengths[i] ) == 0 ) break ;
693 case 0 : /* "alpha": Alpha color buffer precision in bits */
694 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
697 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
701 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
702 in bits with zero bits alpha */
703 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
706 case 3 : /* "blue": Blue color buffer precision in bits */
709 case 4 : /* "buffer": Number of bits in the color index color buffer
713 case 5 : /* "conformant": Boolean indicating if the frame buffer
714 configuration is conformant or not */
717 case 6 : /* "depth": Number of bits of precsion in the depth buffer */
718 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
721 case 7 : /* "double": Boolean indicating if the color buffer is
723 glut_state_flag |= GLUT_DOUBLE ;
726 case 8 : /* "green": Green color buffer precision in bits */
729 case 9 : /* "index": Boolean if the color model is color index or not
731 glut_state_flag |= GLUT_INDEX ;
734 case 10 : /* "num": A special capability name indicating where the
735 value represents the Nth frame buffer configuration
736 matching the description string */
739 case 11 : /* "red": Red color buffer precision in bits */
742 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
743 the RGBA color buffer */
744 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
747 case 13 : /* "rgb": Number of bits of red, green, and blue in the
748 RGBA color buffer with zero bits alpha */
749 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
752 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
753 bits of green, blue (alpha not specified) of color buffer
755 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
758 case 15 : /* "stencil": Number of bits in the stencil buffer */
759 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
762 case 16 : /* "single": Boolean indicate the color buffer is single
764 glut_state_flag |= GLUT_SINGLE ;
767 case 17 : /* "stereo": Boolean indicating the color buffer supports
768 OpenGL-style stereo */
769 glut_state_flag |= GLUT_STEREO ;
772 case 18 : /* "samples": Indicates the number of multisamples to use
773 based on GLX's SGIS_multisample extension (for
775 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
778 case 19 : /* "slow": Boolean indicating if the frame buffer
779 configuration is slow or not */
782 case 20 : /* "win32pdf": matches the Win32 Pixel Format Descriptor by
784 #if TARGET_HOST_WIN32
788 case 21 : /* "xvisual": matches the X visual ID by number */
789 #if TARGET_HOST_UNIX_X11
793 case 22 : /* "xstaticgray": boolean indicating if the frame buffer
794 configuration's X visual is of type StaticGray */
795 #if TARGET_HOST_UNIX_X11
799 case 23 : /* "xgrayscale": boolean indicating if the frame buffer
800 configuration's X visual is of type GrayScale */
801 #if TARGET_HOST_UNIX_X11
805 case 24 : /* "xstaticcolor": boolean indicating if the frame buffer
806 configuration's X visual is of type StaticColor */
807 #if TARGET_HOST_UNIX_X11
811 case 25 : /* "xpseudocolor": boolean indicating if the frame buffer
812 configuration's X visual is of type PseudoColor */
813 #if TARGET_HOST_UNIX_X11
817 case 26 : /* "xtruecolor": boolean indicating if the frame buffer
818 configuration's X visual is of type TrueColor */
819 #if TARGET_HOST_UNIX_X11
823 case 27 : /* "xdirectcolor": boolean indicating if the frame buffer
824 configuration's X visual is of type DirectColor */
825 #if TARGET_HOST_UNIX_X11
829 case 28 : /* Unrecognized */
830 printf ( "WARNING - Display string token not recognized: %s\n",
835 token = strtok ( NULL, " \t" ) ;
841 * We will make use of this value when creating a new OpenGL context...
843 fgState.DisplayMode = glut_state_flag;
846 /*** END OF FILE ***/