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 #define G_LOG_DOMAIN "freeglut-init"
34 #include "../include/GL/freeglut.h"
35 #include "freeglut_internal.h"
38 * TODO BEFORE THE STABLE RELEASE:
40 * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific deinitialization done
41 * glutInitDisplayString() -- display mode string parsing
43 * Wouldn't it be cool to use gettext() for error messages? I just love bash saying
44 * "nie znaleziono pliku" instead of "file not found" :) 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, FALSE }, /* Position */
59 { 300, 300, TRUE }, /* Size */
60 GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
61 FALSE, /* ForceDirectContext */
62 TRUE, /* TryDirectContext */
63 FALSE, /* ForceIconic */
64 FALSE, /* UseCurrentContext */
65 FALSE, /* GLDebugSwitch */
66 FALSE, /* XSyncSwitch */
67 TRUE, /* IgnoreKeyRepeat */
72 { 0, FALSE }, /* Time */
76 { NULL, NULL }, /* Timers */
77 NULL, /* IdleCallback */
78 FALSE, /* BuildingAMenu */
80 NULL, /* MenuStateCallback */
81 NULL, /* MenuStatusCallback */
82 { 640, 480, TRUE }, /* GameModeSize */
83 16, /* GameModeDepth */
84 72, /* GameModeRefresh */
85 GLUT_ACTION_EXIT, /* ActionOnWindowClose */
86 GLUT_EXEC_STATE_INIT /* ExecState */
90 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
93 * A call to this function should initialize all the display stuff...
95 void fgInitialize( const char* displayName )
97 #if TARGET_HOST_UNIX_X11
99 * Have the display created
101 fgDisplay.Display = XOpenDisplay( displayName );
103 if( fgDisplay.Display == NULL )
106 * Failed to open a display. That's no good.
108 fgError( "failed to open display '%s'", XDisplayName( displayName ) );
112 * Check for the OpenGL GLX extension availability:
114 if( !glXQueryExtension( fgDisplay.Display, NULL, NULL ) )
117 * GLX extensions have not been found...
119 fgError( "OpenGL GLX extension not supported by display '%s'", XDisplayName( displayName ) );
123 * Grab the default screen for the display we have just opened
125 fgDisplay.Screen = DefaultScreen( fgDisplay.Display );
128 * The same applying to the root window
130 fgDisplay.RootWindow = RootWindow(
136 * Grab the logical screen's geometry
138 fgDisplay.ScreenWidth = DisplayWidth(
143 fgDisplay.ScreenHeight = DisplayHeight(
149 * Grab the physical screen's geometry
151 fgDisplay.ScreenWidthMM = DisplayWidthMM(
156 fgDisplay.ScreenHeightMM = DisplayHeightMM(
162 * The display's connection number
164 fgDisplay.Connection = ConnectionNumber( fgDisplay.Display );
167 * Create the window deletion atom
169 fgDisplay.DeleteWindow = XInternAtom(
175 #elif TARGET_HOST_WIN32
181 * What we need to do is to initialize the fgDisplay global structure here...
183 fgDisplay.Instance = GetModuleHandle( NULL );
186 * Check if the freeglut window class has been registered before...
188 atom = GetClassInfo( fgDisplay.Instance, "FREEGLUT", &wc );
191 * ...nope, it has not, and we have to do it right now:
196 * Make sure the unitialized fields are reset to zero
198 ZeroMemory( &wc, sizeof(WNDCLASS) );
201 * Each of the windows should have its own device context...
204 wc.lpfnWndProc = fgWindowProc;
207 wc.hInstance = fgDisplay.Instance;
208 wc.hIcon = LoadIcon( fgDisplay.Instance, "GLUT_ICON" );
210 wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
212 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
213 wc.hbrBackground = NULL;
214 wc.lpszMenuName = NULL;
215 wc.lpszClassName = "FREEGLUT";
218 * Register the window class
220 atom = RegisterClass( &wc );
225 * The screen dimensions can be obtained via GetSystemMetrics() calls
227 fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXSCREEN );
228 fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );
232 * Checking the display's size in millimeters isn't too hard, too:
234 HWND desktop = GetDesktopWindow();
235 HDC context = GetDC( desktop );
238 * Grab the appropriate values now (HORZSIZE and VERTSIZE respectably):
240 fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
241 fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
244 * Whoops, forgot to release the device context :)
246 ReleaseDC( desktop, context );
252 * Have the joystick device initialized now
258 * Perform the freeglut deinitialization...
260 void fgDeinitialize( void )
265 * Check if initialization has been performed before
267 if( !fgState.Time.Set )
269 fgWarning( "fgDeinitialize(): fgState.Timer is null => no valid initialization has been performed" );
274 * If there was a menu created, destroy the rendering context
276 if ( fgStructure.MenuContext )
278 free ( fgStructure.MenuContext ) ;
279 fgStructure.MenuContext = NULL ;
283 * Perform the freeglut structure deinitialization
285 fgDestroyStructure();
288 * Delete all the timers and their storage list
290 while ( (timer = (SFG_Timer *)fgState.Timers.First) != NULL )
292 fgListRemove ( &fgState.Timers, &timer->Node ) ;
297 * Deinitialize the joystick device
302 * Reset the state structure
305 fgState.Position.X = -1 ;
306 fgState.Position.Y = -1 ;
307 fgState.Position.Use = FALSE ;
309 fgState.Size.X = 300 ;
310 fgState.Size.Y = 300 ;
311 fgState.Size.Use = TRUE ;
314 * The default display mode to be used
316 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
318 fgState.ForceDirectContext = FALSE;
319 fgState.TryDirectContext = TRUE;
320 fgState.ForceIconic = FALSE;
321 fgState.UseCurrentContext = FALSE;
322 fgState.GLDebugSwitch = FALSE;
323 fgState.XSyncSwitch = FALSE;
324 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT ;
325 fgState.ExecState = GLUT_EXEC_STATE_INIT ;
328 * Assume we want to ignore the automatic key repeat
330 fgState.IgnoreKeyRepeat = TRUE;
333 * Set the default game mode settings
335 fgState.GameModeSize.X = 640;
336 fgState.GameModeSize.Y = 480;
337 fgState.GameModeDepth = 16;
338 fgState.GameModeRefresh = 72;
340 fgState.Time.Set = FALSE ;
342 fgState.Timers.First = fgState.Timers.Last = NULL ;
343 fgState.IdleCallback = NULL ;
344 fgState.MenuStateCallback = (FGCBmenuState)NULL ;
345 fgState.MenuStatusCallback = (FGCBmenuStatus)NULL ;
350 fgState.SwapCount = 0;
351 fgState.SwapTime = 0;
352 fgState.FPSInterval = 0;
355 #if TARGET_HOST_UNIX_X11
358 * Make sure all X-client data we have created will be destroyed on display closing
360 XSetCloseDownMode( fgDisplay.Display, DestroyAll );
363 * Close the display connection, destroying all windows we have created so far
365 XCloseDisplay( fgDisplay.Display );
371 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
374 * Perform initialization. This usually happens on the program startup
375 * and restarting after glutMainLoop termination...
377 void FGAPIENTRY glutInit( int* pargc, char** argv )
379 char* displayName = NULL;
380 int i, j, argc = *pargc;
382 if (pargc && *pargc && argv && *argv && **argv)
383 fgState.ProgramName = strdup (*argv);
385 fgState.ProgramName = strdup ("");
387 * Do not allow multiple initialization of the library
389 if( fgState.Time.Set )
392 * We can't have multiple initialization performed
394 fgError( "illegal glutInit() reinitialization attemp" );
398 * Have the internal freeglut structure initialized now
403 * Remember the function's call time
405 #if TARGET_HOST_UNIX_X11
406 gettimeofday(&fgState.Time.Value, NULL);
407 #elif TARGET_HOST_WIN32
408 fgState.Time.Value = timeGetTime();
410 fgState.Time.Set = TRUE;
412 /* check if GLUT_FPS env var is set */
414 const char *fps = getenv ( "GLUT_FPS" );
417 sscanf ( fps, "%d", &fgState.FPSInterval ) ;
418 if ( fgState.FPSInterval <= 0 )
419 fgState.FPSInterval = 5000 ; /* 5000 milliseconds */
424 * Grab the environment variable indicating the X display to use.
425 * This is harmless under Win32, so let's let it stay here...
427 #if TARGET_HOST_WIN32
428 if ( !getenv ( "DISPLAY" ) )
429 displayName = strdup ( "" ) ;
432 displayName = strdup( getenv( "DISPLAY" ) );
435 * Have the program arguments parsed.
437 for( i=1; i<argc; i++ )
440 * The X display name settings
442 if( strcmp( argv[ i ], "-display" ) == 0 )
445 * Check for possible lack of the next argument
448 fgError( "-display parameter must be followed by display name" );
451 * Release the previous display name (the one from app's environment)
456 * Make a working copy of the name for us to use
458 displayName = strdup( argv[ i ] );
461 * Have both arguments removed
463 argv[ i - 1 ] = NULL;
469 * The geometry settings
471 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
477 * Again, check if there is at least one more argument
480 fgError( "-geometry parameter must be followed by window geometry settings" );
483 * Otherwise scan the geometry settings...
485 result = sscanf ( argv[i], "%dx%d+%d+%d", &x, &y, &w, &h );
488 * Check what we have been supplied with...
499 fgState.Position.Y = fgDisplay.ScreenHeight + y - fgState.Size.Y;
501 fgState.Position.Y = y;
507 fgState.Position.X = fgDisplay.ScreenWidth + x - fgState.Size.X;
509 fgState.Position.X = x;
513 * Have both arguments removed
515 argv[ i - 1 ] = NULL;
521 * The direct/indirect OpenGL contexts settings
523 else if( strcmp( argv[ i ], "-direct" ) == 0)
526 * We try to force direct rendering...
528 if( fgState.TryDirectContext == FALSE )
529 fgError( "parameters ambiguity, -direct and -indirect cannot be both specified" );
531 fgState.ForceDirectContext = TRUE;
535 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
538 * We try to force indirect rendering...
540 if( fgState.ForceDirectContext == TRUE )
541 fgError( "parameters ambiguity, -direct and -indirect cannot be both specified" );
543 fgState.TryDirectContext = FALSE;
549 * The '-iconic' parameter makes all new top-level
550 * windows created in iconified state...
552 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
554 fgState.ForceIconic = TRUE;
560 * The '-gldebug' option activates some OpenGL state debugging features
562 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
564 fgState.GLDebugSwitch = TRUE;
570 * The '-sync' option activates X protocol synchronization (for debugging purposes)
572 else if( strcmp( argv[ i ], "-sync" ) == 0 )
574 fgState.XSyncSwitch = TRUE;
581 * Have the arguments list compacted now
584 for( i = 1; i < *pargc; i++, j++ )
586 if( argv[ i ] == NULL )
588 while ( argv[j] == NULL ) j++ ; /* Guaranteed to end because there are "*pargc" arguments left */
594 * Have the display created now. As I am too lazy to implement
595 * the program arguments parsing, we will have the DISPLAY
596 * environment variable used for opening the X display:
598 fgInitialize( displayName );
601 * Check for the minus one settings for both position and size...
603 if( fgState.Position.X < 0 || fgState.Position.Y < 0 )
604 fgState.Position.Use = FALSE;
606 if( fgState.Size.X < 0 || fgState.Size.Y < 0 )
607 fgState.Size.Use = FALSE;
610 * Do not forget about releasing the display name string
616 * Sets the default initial window position for new windows
618 void FGAPIENTRY glutInitWindowPosition( int x, int y )
621 * The settings can be disables when both coordinates are negative
623 if( (x >= 0) && (y >= 0) )
626 * We want to specify the initial position of each of the windows
628 fgState.Position.X = x;
629 fgState.Position.Y = y;
630 fgState.Position.Use = TRUE;
635 * The initial position of each of the windows is specified by the wm
637 fgState.Position.X = -1;
638 fgState.Position.Y = -1;
639 fgState.Position.Use = FALSE;
644 * Sets the default initial window size for new windows
646 void FGAPIENTRY glutInitWindowSize( int width, int height )
649 * The settings can be disables when both values are negative
651 if( (width > 0) && (height > 0) )
654 * We want to specify the initial size of each of the windows
656 fgState.Size.X = width;
657 fgState.Size.Y = height;
658 fgState.Size.Use = TRUE;
663 * The initial size of each of the windows is specified by the wm (officially this is an error condition)
667 fgState.Size.Use = FALSE;
672 * Sets the default display mode for all new windows
674 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
677 * We will make use of this value when creating a new OpenGL context...
679 fgState.DisplayMode = displayMode;
683 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
685 #if 0 /* FIXME: CJP */
687 * There is a discrete number of comparison operators we can encounter:
689 * comparison ::= "=" | "!=" | "<" | ">" | "<=" | ">=" | "~"
691 #define FG_NONE 0x0000
692 #define FG_EQUAL 0x0001
693 #define FG_NOT_EQUAL 0x0002
694 #define FG_LESS 0x0003
695 #define FG_MORE 0x0004
696 #define FG_LESS_OR_EQUAL 0x0005
697 #define FG_MORE_OR_EQUAL 0x0006
698 #define FG_CLOSEST 0x0007
701 * The caller can feed us with a number of capability tokens:
703 * capability ::= "alpha" | "acca" | "acc" | "blue" | "buffer" | "conformant" | "depth" | "double" |
704 * "green" | "index" | "num" | "red" | "rgba" | "rgb" | "luminance" | "stencil" |
705 * "single" | "stereo" | "samples" | "slow" | "win32pdf" | "xvisual" | "xstaticgray" |
706 * "xgrayscale" | "xstaticcolor" | "xpseudocolor" | "xtruecolor" | "xdirectcolor"
708 static gchar* g_Tokens[] =
710 "none", "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double", "green",
711 "index", "num", "red", "rgba", "rgb", "luminance", "stencil", "single", "stereo", "samples",
712 "slow", "win32pdf", "xvisual", "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
713 "xtruecolor", "xdirectcolor", NULL
717 * The structure to hold the parsed display string tokens
719 typedef struct tagSFG_Capability SFG_Capability;
720 struct tagSFG_Capability
722 gint capability; /* the capability token enumerator */
723 gint comparison; /* the comparison operator used */
724 gint value; /* the value we're comparing to */
728 * The scanner configuration for the init display string
730 static GScannerConfig fgInitDisplayStringScannerConfig =
732 ( " \t\r\n" ) /* cset_skip_characters */,
737 ) /* cset_identifier_first */,
745 ) /* cset_identifier_nth */,
746 ( "#\n" ) /* cpair_comment_single */,
747 FALSE /* case_sensitive */,
748 TRUE /* skip_comment_multi */,
749 TRUE /* skip_comment_single */,
750 TRUE /* scan_comment_multi */,
751 TRUE /* scan_identifier */,
752 FALSE /* scan_identifier_1char */,
753 FALSE /* scan_identifier_NULL */,
754 TRUE /* scan_symbols */,
755 FALSE /* scan_binary */,
756 TRUE /* scan_octal */,
757 TRUE /* scan_float */,
759 FALSE /* scan_hex_dollar */,
760 TRUE /* scan_string_sq */,
761 TRUE /* scan_string_dq */,
762 TRUE /* numbers_2_int */,
763 FALSE /* int_2_float */,
764 FALSE /* identifier_2_string */,
765 TRUE /* char_2_token */,
766 FALSE /* symbol_2_token */,
767 FALSE /* scope_0_fallback */,
771 * Sets the default display mode for all new windows using a string
773 void FGAPIENTRY glutInitDisplayString( char* displayMode )
776 * display_string ::= (switch)
777 * switch ::= capability [comparison value]
778 * comparison ::= "=" | "!=" | "<" | ">" | "<=" | ">=" | "~"
779 * capability ::= "alpha" | "acca" | "acc" | "blue" | "buffer" | "conformant" |
780 * "depth" | "double" | "green" | "index" | "num" | "red" | "rgba" |
781 * "rgb" | "luminance" | "stencil" | "single" | "stereo" |
782 * "samples" | "slow" | "win32pdf" | "xvisual" | "xstaticgray" |
783 * "xgrayscale" | "xstaticcolor" | "xpseudocolor" |
784 * "xtruecolor" | "xdirectcolor"
785 * value ::= 0..9 [value]
787 * The display string grammar. This should be EBNF, but I couldn't find the definitions so, to
788 * clarify: (expr) means 0 or more times the expression, [expr] means 0 or 1 times expr.
790 * Create a new GLib lexical analyzer to process the display mode string
792 GScanner* scanner = g_scanner_new( &fgInitDisplayStringScannerConfig );
797 * Fail if the display mode string is empty or the scanner failed to initialize
799 freeglut_return_if_fail( (scanner != NULL) && (strlen( displayMode ) > 0) );
802 * Set the scanner's input name (for debugging)
804 scanner->input_name = "glutInitDisplayString";
807 * Start the lexical analysis of the extensions string
809 g_scanner_input_text( scanner, displayMode, strlen( displayMode ) );
812 * While there are any more tokens to be checked...
814 while( !g_scanner_eof( scanner ) )
817 * Actually we're expecting only string tokens
819 GTokenType tokenType = g_scanner_get_next_token( scanner );
822 * We are looking for identifiers
824 if( tokenType == G_TOKEN_IDENTIFIER )
826 gchar* capability = NULL; /* the capability identifier string (always present) */
827 gint capID = 0; /* the capability identifier value (from g_Tokens) */
828 gint comparison = 0; /* the comparison operator value, see definitions */
829 gchar* valueString = NULL; /* if the previous one is present, this is needed */
830 gint value = 0; /* the integer value converted using a strtol call */
831 SFG_Capability* capStruct; /* the capability description structure */
834 * OK. The general rule of thumb that we always should be getting a capability identifier
835 * string (see the grammar description). If it is followed by a comparison identifier, then
836 * there must follow an integer value we're comparing the capability to...
838 * Have the current token analyzed with that in mind...
840 for( i=0; i<(gint) strlen( scanner->value.v_identifier ); i++ )
842 gchar c = scanner->value.v_identifier[ i ];
844 if( (c == '=') || (c == '!') || (c == '<') || (c == '>') || (c == '~') )
849 * Here we go with the length of the capability identifier string.
850 * In the worst of cases, it is as long as the token identifier.
852 capability = g_strndup( scanner->value.v_identifier, i );
855 * OK. Is there a chance for comparison and value identifiers to follow?
856 * Note: checking against i+1 as this handles two cases: single character
857 * comparison operator and first of value's digits, which must always be
858 * there, or the two-character comparison operators.
860 if( (i + 1) < (gint) strlen( scanner->value.v_identifier ) )
863 * Yeah, indeed, it is the i-th character to start the identifier, then.
865 gchar c1 = scanner->value.v_identifier[ i + 0 ];
866 gchar c2 = scanner->value.v_identifier[ i + 1 ];
868 if( (c1 == '=') ) { i += 1; comparison = FG_EQUAL; } else
869 if( (c1 == '!') && (c2 == '=') ) { i += 2; comparison = FG_NOT_EQUAL; } else
870 if( (c1 == '<') && (c2 == '=') ) { i += 2; comparison = FG_LESS_OR_EQUAL; } else
871 if( (c1 == '>') && (c2 == '=') ) { i += 2; comparison = FG_MORE_OR_EQUAL; } else
872 if( (c1 == '<') ) { i += 1; comparison = FG_LESS; } else
873 if( (c1 == '>') ) { i += 1; comparison = FG_MORE; } else
874 if( (c1 == '~') ) { i += 1; comparison = FG_CLOSEST; } else
875 g_warning( "invalid comparison operator in token `%s'", scanner->value.v_identifier );
879 * Grab the value string that must follow the comparison operator...
881 if( comparison != FG_NONE && i < (gint) strlen( scanner->value.v_identifier ) )
882 valueString = strdup( scanner->value.v_identifier + i );
885 * If there was a value string, convert it to integer...
887 if( comparison != FG_NONE && strlen( valueString ) > 0 )
888 value = strtol( valueString, NULL, 0 );
891 * Now we need to match the capability string and its ID
893 for( i=0; g_Tokens[ i ]!=NULL; i++ )
895 if( strcmp( capability, g_Tokens[ i ] ) == 0 )
898 * Looks like we've found the one we were looking for
906 * Create a new capability description structure
908 capStruct = g_new0( SFG_Capability, 1 );
911 * Fill in the cap's values, as we have parsed it:
913 capStruct->capability = capID;
914 capStruct->comparison = comparison;
915 capStruct->value = value;
918 * Add the new capabaility to the caps list
920 caps = g_list_append( caps, capStruct );
923 * Clean up the local mess and keep rolling on
925 g_free( valueString );
926 g_free( capability );
931 * Now that we have converted the string into somewhat more machine-friendly
932 * form, proceed with matching the frame buffer configuration...
934 * The caps list could be passed to a function that would try finding the closest
935 * matching pixel format, visual, frame buffer configuration or whatever. It would
936 * be good to convert the glutInitDisplayMode() to use the same method.
939 g_message( "found %i capability preferences", g_list_length( caps ) );
941 g_message( "token `%s': cap: %i, com: %i, val: %i",
942 scanner->value.v_identifier,
943 capStruct->capability,
944 capStruct->comparison,
950 * Free the capabilities we have parsed
952 for( i=0; i<(gint) g_list_length( caps ); i++ )
953 g_free( g_list_nth( caps, i )->data );
956 * Destroy the capabilities list itself
961 * Free the lexical scanner now...
963 g_scanner_destroy( scanner );
967 #define NUM_TOKENS 28
968 static char* Tokens[] =
970 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double", "green",
971 "index", "num", "red", "rgba", "rgb", "luminance", "stencil", "single", "stereo", "samples",
972 "slow", "win32pdf", "xvisual", "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
973 "xtruecolor", "xdirectcolor"
976 static int TokenLengths[] =
978 5, 4, 3, 4, 6, 10, 5, 6, 5,
979 5, 3, 3, 4, 3, 9, 7, 6, 6, 7,
980 4, 8, 7, 11, 10, 12, 12,
984 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
986 int glut_state_flag = 0 ;
988 * Unpack a lot of options from a character string. The options are delimited by blanks or tabs.
991 int len = strlen ( displayMode ) ;
992 char *buffer = (char *)malloc ( (len+1) * sizeof(char) ) ;
993 memcpy ( buffer, displayMode, len ) ;
996 token = strtok ( buffer, " \t" ) ;
1000 * Process this token
1003 for ( i = 0; i < NUM_TOKENS; i++ )
1005 if ( strncmp ( token, Tokens[i], TokenLengths[i] ) == 0 ) break ;
1010 case 0 : /* "alpha": Alpha color buffer precision in bits */
1011 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
1014 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer precision in bits */
1017 case 2 : /* "acc": Red, green, and blue accumulation buffer precision in bits with zero bits alpha */
1018 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
1021 case 3 : /* "blue": Blue color buffer precision in bits */
1024 case 4 : /* "buffer": Number of bits in the color index color buffer */
1027 case 5 : /* "conformant": Boolean indicating if the frame buffer configuration is conformant or not */
1030 case 6 : /* "depth": Number of bits of precsion in the depth buffer */
1031 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
1034 case 7 : /* "double": Boolean indicating if the color buffer is double buffered */
1035 glut_state_flag |= GLUT_DOUBLE ;
1038 case 8 : /* "green": Green color buffer precision in bits */
1041 case 9 : /* "index": Boolean if the color model is color index or not */
1042 glut_state_flag |= GLUT_INDEX ;
1045 case 10 : /* "num": A special capability name indicating where the value represents the Nth frame buffer configuration matching the description string */
1048 case 11 : /* "red": Red color buffer precision in bits */
1051 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in the RGBA color buffer */
1052 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
1055 case 13 : /* "rgb": Number of bits of red, green, and blue in the RGBA color buffer with zero bits alpha */
1056 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
1059 case 14 : /* "luminance": Number of bits of red in the RGBA and zero bits of green, blue (alpha not specified) of color buffer precision */
1060 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
1063 case 15 : /* "stencil": Number of bits in the stencil buffer */
1064 glut_state_flag |= GLUT_STENCIL ; /* Somebody fix this for me! */
1067 case 16 : /* "single": Boolean indicate the color buffer is single buffered */
1068 glut_state_flag |= GLUT_SINGLE ;
1071 case 17 : /* "stereo": Boolean indicating the color buffer supports OpenGL-style stereo */
1072 glut_state_flag |= GLUT_STEREO ;
1075 case 18 : /* "samples": Indicates the number of multisamples to use based on GLX's SGIS_multisample extension (for antialiasing) */
1076 glut_state_flag |= GLUT_MULTISAMPLE ; /* Somebody fix this for me! */
1079 case 19 : /* "slow": Boolean indicating if the frame buffer configuration is slow or not */
1082 case 20 : /* "win32pdf": matches the Win32 Pixel Format Descriptor by number */
1083 #if TARGET_HOST_WIN32
1087 case 21 : /* "xvisual": matches the X visual ID by number */
1088 #if TARGET_HOST_UNIX_X11
1092 case 22 : /* "xstaticgray": boolean indicating if the frame buffer configuration's X visual is of type StaticGray */
1093 #if TARGET_HOST_UNIX_X11
1097 case 23 : /* "xgrayscale": boolean indicating if the frame buffer configuration's X visual is of type GrayScale */
1098 #if TARGET_HOST_UNIX_X11
1102 case 24 : /* "xstaticcolor": boolean indicating if the frame buffer configuration's X visual is of type StaticColor */
1103 #if TARGET_HOST_UNIX_X11
1107 case 25 : /* "xpseudocolor": boolean indicating if the frame buffer configuration's X visual is of type PseudoColor */
1108 #if TARGET_HOST_UNIX_X11
1112 case 26 : /* "xtruecolor": boolean indicating if the frame buffer configuration's X visual is of type TrueColor */
1113 #if TARGET_HOST_UNIX_X11
1117 case 27 : /* "xdirectcolor": boolean indicating if the frame buffer configuration's X visual is of type DirectColor */
1118 #if TARGET_HOST_UNIX_X11
1122 case 28 : /* Unrecognized */
1123 printf ( "WARNING - Display string token not recognized: %s\n", token ) ;
1127 token = strtok ( NULL, " \t" ) ;
1133 * We will make use of this value when creating a new OpenGL context...
1135 fgState.DisplayMode = glut_state_flag;
1138 /*** END OF FILE ***/