-/*\r
- * freeglut_init.c\r
- *\r
- * Various freeglut initialization functions.\r
- *\r
- * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.\r
- * Written by Pawel W. Olszta, <olszta@sourceforge.net>\r
- * Creation date: Thu Dec 2 1999\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
- * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-#define FREEGLUT_BUILDING_LIB\r
-#include <GL/freeglut.h>\r
-#include "freeglut_internal.h"\r
-\r
-/*\r
- * TODO BEFORE THE STABLE RELEASE:\r
- *\r
- * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific\r
- * deinitialization done\r
- * glutInitDisplayString() -- display mode string parsing\r
- *\r
- * Wouldn't it be cool to use gettext() for error messages? I just love\r
- * bash saying "nie znaleziono pliku" instead of "file not found" :)\r
- * Is gettext easily portable?\r
- */\r
-\r
-/* -- GLOBAL VARIABLES ----------------------------------------------------- */\r
-\r
-/*\r
- * A structure pointed by g_pDisplay holds all information\r
- * regarding the display, screen, root window etc.\r
- */\r
-SFG_Display fgDisplay;\r
-\r
-/*\r
- * The settings for the current freeglut session\r
- */\r
-SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */\r
- { 300, 300, GL_TRUE }, /* Size */\r
- GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */\r
- GL_FALSE, /* Initialised */\r
- GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */\r
- GL_FALSE, /* ForceIconic */\r
- GL_FALSE, /* UseCurrentContext */\r
- GL_FALSE, /* GLDebugSwitch */\r
- GL_FALSE, /* XSyncSwitch */\r
- GLUT_KEY_REPEAT_ON, /* KeyRepeat */\r
- INVALID_MODIFIERS, /* Modifiers */\r
- 0, /* FPSInterval */\r
- 0, /* SwapCount */\r
- 0, /* SwapTime */\r
- 0, /* Time */\r
- { NULL, NULL }, /* Timers */\r
- { NULL, NULL }, /* FreeTimers */\r
- NULL, /* IdleCallback */\r
- 0, /* ActiveMenus */\r
- NULL, /* MenuStateCallback */\r
- NULL, /* MenuStatusCallback */\r
- { 640, 480, GL_TRUE }, /* GameModeSize */\r
- 16, /* GameModeDepth */\r
- 72, /* GameModeRefresh */\r
- GLUT_ACTION_EXIT, /* ActionOnWindowClose */\r
- GLUT_EXEC_STATE_INIT, /* ExecState */\r
- NULL, /* ProgramName */\r
- GL_FALSE, /* JoysticksInitialised */\r
- 0, /* NumActiveJoysticks */\r
- GL_FALSE, /* InputDevsInitialised */\r
- 0, /* MouseWheelTicks */\r
- 1, /* AuxiliaryBufferNumber */\r
- 4, /* SampleNumber */\r
- 1, /* MajorVersion */\r
- 0, /* MinorVersion */\r
- 0, /* ContextFlags */\r
- 0, /* ContextProfile */\r
- NULL, /* ErrorFunc */\r
- NULL /* WarningFunc */\r
-};\r
-\r
-\r
-/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */\r
-\r
-extern void fgPlatformInitialize( const char* displayName );\r
-extern void fgPlatformDeinitialiseInputDevices ( void );\r
-extern void fgPlatformCloseDisplay ( void );\r
-\r
-\r
-void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )\r
-{\r
-#ifndef _WIN32_WCE\r
- int i, j, argc = *pargc;\r
-\r
- {\r
- /* check if GLUT_FPS env var is set */\r
- const char *fps = getenv( "GLUT_FPS" );\r
-\r
- if( fps )\r
- {\r
- int interval;\r
- sscanf( fps, "%d", &interval );\r
-\r
- if( interval <= 0 )\r
- fgState.FPSInterval = 5000; /* 5000 millisecond default */\r
- else\r
- fgState.FPSInterval = interval;\r
- }\r
- }\r
-\r
- *pDisplayName = getenv( "DISPLAY" );\r
-\r
- for( i = 1; i < argc; i++ )\r
- {\r
- if( strcmp( argv[ i ], "-display" ) == 0 )\r
- {\r
- if( ++i >= argc )\r
- fgError( "-display parameter must be followed by display name" );\r
-\r
- *pDisplayName = argv[ i ];\r
-\r
- argv[ i - 1 ] = NULL;\r
- argv[ i ] = NULL;\r
- ( *pargc ) -= 2;\r
- }\r
- else if( strcmp( argv[ i ], "-geometry" ) == 0 )\r
- {\r
- if( ++i >= argc )\r
- fgError( "-geometry parameter must be followed by window "\r
- "geometry settings" );\r
-\r
- *pGeometry = argv[ i ];\r
-\r
- argv[ i - 1 ] = NULL;\r
- argv[ i ] = NULL;\r
- ( *pargc ) -= 2;\r
- }\r
- else if( strcmp( argv[ i ], "-direct" ) == 0)\r
- {\r
- if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )\r
- fgError( "parameters ambiguity, -direct and -indirect "\r
- "cannot be both specified" );\r
-\r
- fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;\r
- argv[ i ] = NULL;\r
- ( *pargc )--;\r
- }\r
- else if( strcmp( argv[ i ], "-indirect" ) == 0 )\r
- {\r
- if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )\r
- fgError( "parameters ambiguity, -direct and -indirect "\r
- "cannot be both specified" );\r
-\r
- fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;\r
- argv[ i ] = NULL;\r
- (*pargc)--;\r
- }\r
- else if( strcmp( argv[ i ], "-iconic" ) == 0 )\r
- {\r
- fgState.ForceIconic = GL_TRUE;\r
- argv[ i ] = NULL;\r
- ( *pargc )--;\r
- }\r
- else if( strcmp( argv[ i ], "-gldebug" ) == 0 )\r
- {\r
- fgState.GLDebugSwitch = GL_TRUE;\r
- argv[ i ] = NULL;\r
- ( *pargc )--;\r
- }\r
- else if( strcmp( argv[ i ], "-sync" ) == 0 )\r
- {\r
- fgState.XSyncSwitch = GL_TRUE;\r
- argv[ i ] = NULL;\r
- ( *pargc )--;\r
- }\r
- }\r
-\r
- /* Compact {argv}. */\r
- for( i = j = 1; i < *pargc; i++, j++ )\r
- {\r
- /* Guaranteed to end because there are "*pargc" arguments left */\r
- while ( argv[ j ] == NULL )\r
- j++;\r
- if ( i != j )\r
- argv[ i ] = argv[ j ];\r
- }\r
-\r
-#endif /* _WIN32_WCE */\r
-\r
-}\r
-\r
-\r
-void fghCloseInputDevices ( void )\r
-{\r
- if ( fgState.JoysticksInitialised )\r
- fgJoystickClose( );\r
-\r
- if ( fgState.InputDevsInitialised )\r
- fgInputDeviceClose( );\r
-}\r
-\r
-\r
-/*\r
- * Perform the freeglut deinitialization...\r
- */\r
-void fgDeinitialize( void )\r
-{\r
- SFG_Timer *timer;\r
-\r
- if( !fgState.Initialised )\r
- {\r
- return;\r
- }\r
-\r
- /* If we're in game mode, we want to leave game mode */\r
- if( fgStructure.GameModeWindow ) {\r
- glutLeaveGameMode();\r
- }\r
-\r
- /* If there was a menu created, destroy the rendering context */\r
- if( fgStructure.MenuContext )\r
- {\r
-#if TARGET_HOST_POSIX_X11\r
- /* Note that the MVisualInfo is not owned by the MenuContext! */\r
- glXDestroyContext( fgDisplay.pDisplay.Display, fgStructure.MenuContext->MContext );\r
-#endif\r
- free( fgStructure.MenuContext );\r
- fgStructure.MenuContext = NULL;\r
- }\r
-\r
- fgDestroyStructure( );\r
-\r
- while( ( timer = fgState.Timers.First) )\r
- {\r
- fgListRemove( &fgState.Timers, &timer->Node );\r
- free( timer );\r
- }\r
-\r
- while( ( timer = fgState.FreeTimers.First) )\r
- {\r
- fgListRemove( &fgState.FreeTimers, &timer->Node );\r
- free( timer );\r
- }\r
-\r
- fgPlatformDeinitialiseInputDevices ();\r
-\r
- fgState.MouseWheelTicks = 0;\r
-\r
- fgState.MajorVersion = 1;\r
- fgState.MinorVersion = 0;\r
- fgState.ContextFlags = 0;\r
- fgState.ContextProfile = 0;\r
-\r
- fgState.Initialised = GL_FALSE;\r
-\r
- fgState.Position.X = -1;\r
- fgState.Position.Y = -1;\r
- fgState.Position.Use = GL_FALSE;\r
-\r
- fgState.Size.X = 300;\r
- fgState.Size.Y = 300;\r
- fgState.Size.Use = GL_TRUE;\r
-\r
- fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;\r
-\r
- fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;\r
- fgState.ForceIconic = GL_FALSE;\r
- fgState.UseCurrentContext = GL_FALSE;\r
- fgState.GLDebugSwitch = GL_FALSE;\r
- fgState.XSyncSwitch = GL_FALSE;\r
- fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;\r
- fgState.ExecState = GLUT_EXEC_STATE_INIT;\r
-\r
- fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;\r
- fgState.Modifiers = INVALID_MODIFIERS;\r
-\r
- fgState.GameModeSize.X = 640;\r
- fgState.GameModeSize.Y = 480;\r
- fgState.GameModeDepth = 16;\r
- fgState.GameModeRefresh = 72;\r
-\r
- fgListInit( &fgState.Timers );\r
- fgListInit( &fgState.FreeTimers );\r
-\r
- fgState.IdleCallback = NULL;\r
- fgState.MenuStateCallback = ( FGCBMenuState )NULL;\r
- fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;\r
-\r
- fgState.SwapCount = 0;\r
- fgState.SwapTime = 0;\r
- fgState.FPSInterval = 0;\r
-\r
- if( fgState.ProgramName )\r
- {\r
- free( fgState.ProgramName );\r
- fgState.ProgramName = NULL;\r
- }\r
-\r
- fgPlatformCloseDisplay ();\r
-\r
- fgState.Initialised = GL_FALSE;\r
-}\r
-\r
-\r
-#if TARGET_HOST_MS_WINDOWS\r
-#define NoValue 0x0000\r
-#define XValue 0x0001\r
-#define YValue 0x0002\r
-#define WidthValue 0x0004\r
-#define HeightValue 0x0008\r
-#define AllValues 0x000F\r
-#define XNegative 0x0010\r
-#define YNegative 0x0020\r
-\r
-extern int XParseGeometry (\r
- const char *string,\r
- int *x,\r
- int *y,\r
- unsigned int *width, /* RETURN */\r
- unsigned int *height); /* RETURN */\r
-#endif\r
-\r
-/* -- INTERFACE FUNCTIONS -------------------------------------------------- */\r
-\r
-/*\r
- * Perform initialization. This usually happens on the program startup\r
- * and restarting after glutMainLoop termination...\r
- */\r
-void FGAPIENTRY glutInit( int* pargc, char** argv )\r
-{\r
- char* displayName = NULL;\r
- char* geometry = NULL;\r
- if( fgState.Initialised )\r
- fgError( "illegal glutInit() reinitialization attempt" );\r
-\r
- if (pargc && *pargc && argv && *argv && **argv)\r
- {\r
- fgState.ProgramName = strdup (*argv);\r
-\r
- if( !fgState.ProgramName )\r
- fgError ("Could not allocate space for the program's name.");\r
- }\r
-\r
- fgCreateStructure( );\r
-\r
- /* Get start time */\r
- fgState.Time = fgSystemTime();\r
-\r
- fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );\r
-\r
- /*\r
- * Have the display created now. If there wasn't a "-display"\r
- * in the program arguments, we will use the DISPLAY environment\r
- * variable for opening the X display (see code above):\r
- */\r
- fgPlatformInitialize( displayName );\r
-\r
- /*\r
- * Geometry parsing deffered until here because we may need the screen\r
- * size.\r
- */\r
-\r
- if (geometry )\r
- {\r
- unsigned int parsedWidth, parsedHeight;\r
- int mask = XParseGeometry( geometry,\r
- &fgState.Position.X, &fgState.Position.Y,\r
- &parsedWidth, &parsedHeight );\r
- /* TODO: Check for overflow? */\r
- fgState.Size.X = parsedWidth;\r
- fgState.Size.Y = parsedHeight;\r
-\r
- if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )\r
- fgState.Size.Use = GL_TRUE;\r
-\r
- if( mask & XNegative )\r
- fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;\r
-\r
- if( mask & YNegative )\r
- fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;\r
-\r
- if( (mask & (XValue|YValue)) == (XValue|YValue) )\r
- fgState.Position.Use = GL_TRUE;\r
- }\r
-}\r
-\r
-/*\r
- * Undoes all the "glutInit" stuff\r
- */\r
-void FGAPIENTRY glutExit ( void )\r
-{\r
- fgDeinitialize ();\r
-}\r
-\r
-/*\r
- * Sets the default initial window position for new windows\r
- */\r
-void FGAPIENTRY glutInitWindowPosition( int x, int y )\r
-{\r
- fgState.Position.X = x;\r
- fgState.Position.Y = y;\r
-\r
- if( ( x >= 0 ) && ( y >= 0 ) )\r
- fgState.Position.Use = GL_TRUE;\r
- else\r
- fgState.Position.Use = GL_FALSE;\r
-}\r
-\r
-/*\r
- * Sets the default initial window size for new windows\r
- */\r
-void FGAPIENTRY glutInitWindowSize( int width, int height )\r
-{\r
- fgState.Size.X = width;\r
- fgState.Size.Y = height;\r
-\r
- if( ( width > 0 ) && ( height > 0 ) )\r
- fgState.Size.Use = GL_TRUE;\r
- else\r
- fgState.Size.Use = GL_FALSE;\r
-}\r
-\r
-/*\r
- * Sets the default display mode for all new windows\r
- */\r
-void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )\r
-{\r
- /* We will make use of this value when creating a new OpenGL context... */\r
- fgState.DisplayMode = displayMode;\r
-}\r
-\r
-\r
-/* -- INIT DISPLAY STRING PARSING ------------------------------------------ */\r
-\r
-static char* Tokens[] =\r
-{\r
- "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",\r
- "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",\r
- "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",\r
- "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",\r
- "xtruecolor", "xdirectcolor",\r
- "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",\r
- "xtruecolour", "xdirectcolour", "borderless", "aux"\r
-};\r
-#define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))\r
-\r
-void FGAPIENTRY glutInitDisplayString( const char* displayMode )\r
-{\r
- int glut_state_flag = 0 ;\r
- /*\r
- * Unpack a lot of options from a character string. The options are\r
- * delimited by blanks or tabs.\r
- */\r
- char *token ;\r
- size_t len = strlen ( displayMode );\r
- char *buffer = (char *)malloc ( (len+1) * sizeof(char) );\r
- memcpy ( buffer, displayMode, len );\r
- buffer[len] = '\0';\r
-\r
- token = strtok ( buffer, " \t" );\r
-\r
- while ( token )\r
- {\r
- /* Process this token */\r
- int i ;\r
-\r
- /* Temporary fix: Ignore any length specifications and at least\r
- * process the basic token\r
- * TODO: Fix this permanently\r
- */\r
- size_t cleanlength = strcspn ( token, "=<>~!" );\r
-\r
- for ( i = 0; i < NUM_TOKENS; i++ )\r
- {\r
- if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;\r
- }\r
-\r
- switch ( i )\r
- {\r
- case 0 : /* "alpha": Alpha color buffer precision in bits */\r
- glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer\r
- precision in bits */\r
- break ;\r
-\r
- case 2 : /* "acc": Red, green, and blue accumulation buffer precision\r
- in bits with zero bits alpha */\r
- glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 3 : /* "blue": Blue color buffer precision in bits */\r
- break ;\r
-\r
- case 4 : /* "buffer": Number of bits in the color index color buffer\r
- */\r
- break ;\r
-\r
- case 5 : /* "conformant": Boolean indicating if the frame buffer\r
- configuration is conformant or not */\r
- break ;\r
-\r
- case 6 : /* "depth": Number of bits of precsion in the depth buffer */\r
- glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 7 : /* "double": Boolean indicating if the color buffer is\r
- double buffered */\r
- glut_state_flag |= GLUT_DOUBLE ;\r
- break ;\r
-\r
- case 8 : /* "green": Green color buffer precision in bits */\r
- break ;\r
-\r
- case 9 : /* "index": Boolean if the color model is color index or not\r
- */\r
- glut_state_flag |= GLUT_INDEX ;\r
- break ;\r
-\r
- case 10 : /* "num": A special capability name indicating where the\r
- value represents the Nth frame buffer configuration\r
- matching the description string */\r
- break ;\r
-\r
- case 11 : /* "red": Red color buffer precision in bits */\r
- break ;\r
-\r
- case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in\r
- the RGBA color buffer */\r
- glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 13 : /* "rgb": Number of bits of red, green, and blue in the\r
- RGBA color buffer with zero bits alpha */\r
- glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 14 : /* "luminance": Number of bits of red in the RGBA and zero\r
- bits of green, blue (alpha not specified) of color buffer\r
- precision */\r
- glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 15 : /* "stencil": Number of bits in the stencil buffer */\r
- glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */\r
- break ;\r
-\r
- case 16 : /* "single": Boolean indicate the color buffer is single\r
- buffered */\r
- glut_state_flag |= GLUT_SINGLE ;\r
- break ;\r
-\r
- case 17 : /* "stereo": Boolean indicating the color buffer supports\r
- OpenGL-style stereo */\r
- glut_state_flag |= GLUT_STEREO ;\r
- break ;\r
-\r
- case 18 : /* "samples": Indicates the number of multisamples to use\r
- based on GLX's SGIS_multisample extension (for\r
- antialiasing) */\r
- glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/\r
- break ;\r
-\r
- case 19 : /* "slow": Boolean indicating if the frame buffer\r
- configuration is slow or not */\r
- break ;\r
-\r
- case 20 : /* "win32pdf": (incorrect spelling but was there before */\r
- case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by\r
- number */\r
-#if TARGET_HOST_MS_WINDOWS\r
-#endif\r
- break ;\r
-\r
- case 22 : /* "xvisual": matches the X visual ID by number */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 23 : /* "xstaticgray": */\r
- case 29 : /* "xstaticgrey": boolean indicating if the frame buffer\r
- configuration's X visual is of type StaticGray */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 24 : /* "xgrayscale": */\r
- case 30 : /* "xgreyscale": boolean indicating if the frame buffer\r
- configuration's X visual is of type GrayScale */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 25 : /* "xstaticcolor": */\r
- case 31 : /* "xstaticcolour": boolean indicating if the frame buffer\r
- configuration's X visual is of type StaticColor */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 26 : /* "xpseudocolor": */\r
- case 32 : /* "xpseudocolour": boolean indicating if the frame buffer\r
- configuration's X visual is of type PseudoColor */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 27 : /* "xtruecolor": */\r
- case 33 : /* "xtruecolour": boolean indicating if the frame buffer\r
- configuration's X visual is of type TrueColor */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 28 : /* "xdirectcolor": */\r
- case 34 : /* "xdirectcolour": boolean indicating if the frame buffer\r
- configuration's X visual is of type DirectColor */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 35 : /* "borderless": windows should not have borders */\r
-#if TARGET_HOST_POSIX_X11\r
-#endif\r
- break ;\r
-\r
- case 36 : /* "aux": some number of aux buffers */\r
- glut_state_flag |= GLUT_AUX;\r
- break ;\r
-\r
- case 37 : /* Unrecognized */\r
- fgWarning ( "WARNING - Display string token not recognized: %s",\r
- token );\r
- break ;\r
- }\r
-\r
- token = strtok ( NULL, " \t" );\r
- }\r
-\r
- free ( buffer );\r
-\r
- /* We will make use of this value when creating a new OpenGL context... */\r
- fgState.DisplayMode = glut_state_flag;\r
-}\r
-\r
-/* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */\r
-\r
-void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )\r
-{\r
- /* We will make use of these valuse when creating a new OpenGL context... */\r
- fgState.MajorVersion = majorVersion;\r
- fgState.MinorVersion = minorVersion;\r
-}\r
-\r
-\r
-void FGAPIENTRY glutInitContextFlags( int flags )\r
-{\r
- /* We will make use of this value when creating a new OpenGL context... */\r
- fgState.ContextFlags = flags;\r
-}\r
-\r
-void FGAPIENTRY glutInitContextProfile( int profile )\r
-{\r
- /* We will make use of this value when creating a new OpenGL context... */\r
- fgState.ContextProfile = profile;\r
-}\r
-\r
-/* -------------- User Defined Error/Warning Handler Support -------------- */\r
-\r
-/*\r
- * Sets the user error handler (note the use of va_list for the args to the fmt)\r
- */\r
-void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )\r
-{\r
- /* This allows user programs to handle freeglut errors */\r
- fgState.ErrorFunc = vfgError;\r
-}\r
-\r
-/*\r
- * Sets the user warning handler (note the use of va_list for the args to the fmt)\r
- */\r
-void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )\r
-{\r
- /* This allows user programs to handle freeglut warnings */\r
- fgState.WarningFunc = vfgWarning;\r
-}\r
-\r
-/*** END OF FILE ***/\r
+/*
+ * freeglut_init.c
+ *
+ * Various freeglut initialization functions.
+ *
+ * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
+ * Written by Pawel W. Olszta, <olszta@sourceforge.net>
+ * Creation date: Thu Dec 2 1999
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#define FREEGLUT_BUILDING_LIB
+#include <GL/freeglut.h>
+#include "freeglut_internal.h"
+
+/*
+ * TODO BEFORE THE STABLE RELEASE:
+ *
+ * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific
+ * deinitialization done
+ * glutInitDisplayString() -- display mode string parsing
+ *
+ * Wouldn't it be cool to use gettext() for error messages? I just love
+ * bash saying "nie znaleziono pliku" instead of "file not found" :)
+ * Is gettext easily portable?
+ */
+
+/* -- GLOBAL VARIABLES ----------------------------------------------------- */
+
+/*
+ * A structure pointed by fgDisplay holds all information
+ * regarding the display, screen, root window etc.
+ */
+SFG_Display fgDisplay;
+
+/*
+ * The settings for the current freeglut session
+ */
+SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
+ { 300, 300, GL_TRUE }, /* Size */
+ GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
+ GL_FALSE, /* Initialised */
+ GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */
+ GL_FALSE, /* ForceIconic */
+ GL_FALSE, /* UseCurrentContext */
+ GL_FALSE, /* GLDebugSwitch */
+ GL_FALSE, /* XSyncSwitch */
+ GLUT_KEY_REPEAT_ON, /* KeyRepeat */
+ INVALID_MODIFIERS, /* Modifiers */
+ 0, /* FPSInterval */
+ 0, /* SwapCount */
+ 0, /* SwapTime */
+ 0, /* Time */
+ { NULL, NULL }, /* Timers */
+ { NULL, NULL }, /* FreeTimers */
+ NULL, /* IdleCallback */
+ 0, /* ActiveMenus */
+ NULL, /* MenuStateCallback */
+ NULL, /* MenuStatusCallback */
+ { 640, 480, GL_TRUE }, /* GameModeSize */
+ 16, /* GameModeDepth */
+ 72, /* GameModeRefresh */
+ GLUT_ACTION_EXIT, /* ActionOnWindowClose */
+ GLUT_EXEC_STATE_INIT, /* ExecState */
+ NULL, /* ProgramName */
+ GL_FALSE, /* JoysticksInitialised */
+ 0, /* NumActiveJoysticks */
+ GL_FALSE, /* InputDevsInitialised */
+ 0, /* MouseWheelTicks */
+ 1, /* AuxiliaryBufferNumber */
+ 4, /* SampleNumber */
+ 1, /* MajorVersion */
+ 0, /* MinorVersion */
+ 0, /* ContextFlags */
+ 0, /* ContextProfile */
+ NULL, /* ErrorFunc */
+ NULL /* WarningFunc */
+};
+
+
+/* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
+
+extern void fgPlatformInitialize( const char* displayName );
+extern void fgPlatformDeinitialiseInputDevices ( void );
+extern void fgPlatformCloseDisplay ( void );
+extern void fgPlatformDestroyContext ( SFG_PlatformDisplay pDisplay, SFG_WindowContextType MContext );
+
+
+void fghParseCommandLineArguments ( int* pargc, char** argv, char **pDisplayName, char **pGeometry )
+{
+#ifndef _WIN32_WCE
+ int i, j, argc = *pargc;
+
+ {
+ /* check if GLUT_FPS env var is set */
+ const char *fps = getenv( "GLUT_FPS" );
+
+ if( fps )
+ {
+ int interval;
+ sscanf( fps, "%d", &interval );
+
+ if( interval <= 0 )
+ fgState.FPSInterval = 5000; /* 5000 millisecond default */
+ else
+ fgState.FPSInterval = interval;
+ }
+ }
+
+ *pDisplayName = getenv( "DISPLAY" );
+
+ for( i = 1; i < argc; i++ )
+ {
+ if( strcmp( argv[ i ], "-display" ) == 0 )
+ {
+ if( ++i >= argc )
+ fgError( "-display parameter must be followed by display name" );
+
+ *pDisplayName = argv[ i ];
+
+ argv[ i - 1 ] = NULL;
+ argv[ i ] = NULL;
+ ( *pargc ) -= 2;
+ }
+ else if( strcmp( argv[ i ], "-geometry" ) == 0 )
+ {
+ if( ++i >= argc )
+ fgError( "-geometry parameter must be followed by window "
+ "geometry settings" );
+
+ *pGeometry = argv[ i ];
+
+ argv[ i - 1 ] = NULL;
+ argv[ i ] = NULL;
+ ( *pargc ) -= 2;
+ }
+ else if( strcmp( argv[ i ], "-direct" ) == 0)
+ {
+ if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
+ fgError( "parameters ambiguity, -direct and -indirect "
+ "cannot be both specified" );
+
+ fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-indirect" ) == 0 )
+ {
+ if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
+ fgError( "parameters ambiguity, -direct and -indirect "
+ "cannot be both specified" );
+
+ fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
+ argv[ i ] = NULL;
+ (*pargc)--;
+ }
+ else if( strcmp( argv[ i ], "-iconic" ) == 0 )
+ {
+ fgState.ForceIconic = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
+ {
+ fgState.GLDebugSwitch = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ else if( strcmp( argv[ i ], "-sync" ) == 0 )
+ {
+ fgState.XSyncSwitch = GL_TRUE;
+ argv[ i ] = NULL;
+ ( *pargc )--;
+ }
+ }
+
+ /* Compact {argv}. */
+ for( i = j = 1; i < *pargc; i++, j++ )
+ {
+ /* Guaranteed to end because there are "*pargc" arguments left */
+ while ( argv[ j ] == NULL )
+ j++;
+ if ( i != j )
+ argv[ i ] = argv[ j ];
+ }
+
+#endif /* _WIN32_WCE */
+
+}
+
+
+void fghCloseInputDevices ( void )
+{
+ if ( fgState.JoysticksInitialised )
+ fgJoystickClose( );
+
+ if ( fgState.InputDevsInitialised )
+ fgInputDeviceClose( );
+}
+
+
+/*
+ * Perform the freeglut deinitialization...
+ */
+void fgDeinitialize( void )
+{
+ SFG_Timer *timer;
+
+ if( !fgState.Initialised )
+ {
+ return;
+ }
+
+ /* If we're in game mode, we want to leave game mode */
+ if( fgStructure.GameModeWindow ) {
+ glutLeaveGameMode();
+ }
+
+ /* If there was a menu created, destroy the rendering context */
+ if( fgStructure.MenuContext )
+ {
+ fgPlatformDestroyContext (fgDisplay.pDisplay, fgStructure.MenuContext->MContext );
+ free( fgStructure.MenuContext );
+ fgStructure.MenuContext = NULL;
+ }
+
+ fgDestroyStructure( );
+
+ while( ( timer = fgState.Timers.First) )
+ {
+ fgListRemove( &fgState.Timers, &timer->Node );
+ free( timer );
+ }
+
+ while( ( timer = fgState.FreeTimers.First) )
+ {
+ fgListRemove( &fgState.FreeTimers, &timer->Node );
+ free( timer );
+ }
+
+ fgPlatformDeinitialiseInputDevices ();
+
+ fgState.MouseWheelTicks = 0;
+
+ fgState.MajorVersion = 1;
+ fgState.MinorVersion = 0;
+ fgState.ContextFlags = 0;
+ fgState.ContextProfile = 0;
+
+ fgState.Initialised = GL_FALSE;
+
+ fgState.Position.X = -1;
+ fgState.Position.Y = -1;
+ fgState.Position.Use = GL_FALSE;
+
+ fgState.Size.X = 300;
+ fgState.Size.Y = 300;
+ fgState.Size.Use = GL_TRUE;
+
+ fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
+
+ fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
+ fgState.ForceIconic = GL_FALSE;
+ fgState.UseCurrentContext = GL_FALSE;
+ fgState.GLDebugSwitch = GL_FALSE;
+ fgState.XSyncSwitch = GL_FALSE;
+ fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
+ fgState.ExecState = GLUT_EXEC_STATE_INIT;
+
+ fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
+ fgState.Modifiers = INVALID_MODIFIERS;
+
+ fgState.GameModeSize.X = 640;
+ fgState.GameModeSize.Y = 480;
+ fgState.GameModeDepth = 16;
+ fgState.GameModeRefresh = 72;
+
+ fgListInit( &fgState.Timers );
+ fgListInit( &fgState.FreeTimers );
+
+ fgState.IdleCallback = NULL;
+ fgState.MenuStateCallback = ( FGCBMenuState )NULL;
+ fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
+
+ fgState.SwapCount = 0;
+ fgState.SwapTime = 0;
+ fgState.FPSInterval = 0;
+
+ if( fgState.ProgramName )
+ {
+ free( fgState.ProgramName );
+ fgState.ProgramName = NULL;
+ }
+
+ fgPlatformCloseDisplay ();
+
+ fgState.Initialised = GL_FALSE;
+}
+
+
+/* -- INTERFACE FUNCTIONS -------------------------------------------------- */
+
+/*
+ * Perform initialization. This usually happens on the program startup
+ * and restarting after glutMainLoop termination...
+ */
+void FGAPIENTRY glutInit( int* pargc, char** argv )
+{
+ char* displayName = NULL;
+ char* geometry = NULL;
+ if( fgState.Initialised )
+ fgError( "illegal glutInit() reinitialization attempt" );
+
+ if (pargc && *pargc && argv && *argv && **argv)
+ {
+ fgState.ProgramName = strdup (*argv);
+
+ if( !fgState.ProgramName )
+ fgError ("Could not allocate space for the program's name.");
+ }
+
+ fgCreateStructure( );
+
+ /* Get start time */
+ fgState.Time = fgSystemTime();
+
+ fghParseCommandLineArguments ( pargc, argv, &displayName, &geometry );
+
+ /*
+ * Have the display created now. If there wasn't a "-display"
+ * in the program arguments, we will use the DISPLAY environment
+ * variable for opening the X display (see code above):
+ */
+ fgPlatformInitialize( displayName );
+
+ /*
+ * Geometry parsing deferred until here because we may need the screen
+ * size.
+ */
+
+ if (geometry )
+ {
+ unsigned int parsedWidth, parsedHeight;
+ int mask = XParseGeometry( geometry,
+ &fgState.Position.X, &fgState.Position.Y,
+ &parsedWidth, &parsedHeight );
+ /* TODO: Check for overflow? */
+ fgState.Size.X = parsedWidth;
+ fgState.Size.Y = parsedHeight;
+
+ if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
+ fgState.Size.Use = GL_TRUE;
+
+ if( mask & XNegative )
+ fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
+
+ if( mask & YNegative )
+ fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
+
+ if( (mask & (XValue|YValue)) == (XValue|YValue) )
+ fgState.Position.Use = GL_TRUE;
+ }
+}
+
+/*
+ * Undoes all the "glutInit" stuff
+ */
+void FGAPIENTRY glutExit ( void )
+{
+ fgDeinitialize ();
+}
+
+/*
+ * Sets the default initial window position for new windows
+ */
+void FGAPIENTRY glutInitWindowPosition( int x, int y )
+{
+ fgState.Position.X = x;
+ fgState.Position.Y = y;
+
+ if( ( x >= 0 ) && ( y >= 0 ) )
+ fgState.Position.Use = GL_TRUE;
+ else
+ fgState.Position.Use = GL_FALSE;
+}
+
+/*
+ * Sets the default initial window size for new windows
+ */
+void FGAPIENTRY glutInitWindowSize( int width, int height )
+{
+ fgState.Size.X = width;
+ fgState.Size.Y = height;
+
+ if( ( width > 0 ) && ( height > 0 ) )
+ fgState.Size.Use = GL_TRUE;
+ else
+ fgState.Size.Use = GL_FALSE;
+}
+
+/*
+ * Sets the default display mode for all new windows
+ */
+void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
+{
+ /* We will make use of this value when creating a new OpenGL context... */
+ fgState.DisplayMode = displayMode;
+}
+
+
+/* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
+
+static char* Tokens[] =
+{
+ "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
+ "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
+ "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
+ "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
+ "xtruecolor", "xdirectcolor",
+ "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
+ "xtruecolour", "xdirectcolour", "borderless", "aux"
+};
+#define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
+
+void FGAPIENTRY glutInitDisplayString( const char* displayMode )
+{
+ int glut_state_flag = 0 ;
+ /*
+ * Unpack a lot of options from a character string. The options are
+ * delimited by blanks or tabs.
+ */
+ char *token ;
+ size_t len = strlen ( displayMode );
+ char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
+ memcpy ( buffer, displayMode, len );
+ buffer[len] = '\0';
+
+ token = strtok ( buffer, " \t" );
+
+ while ( token )
+ {
+ /* Process this token */
+ int i ;
+
+ /* Temporary fix: Ignore any length specifications and at least
+ * process the basic token
+ * TODO: Fix this permanently
+ */
+ size_t cleanlength = strcspn ( token, "=<>~!" );
+
+ for ( i = 0; i < NUM_TOKENS; i++ )
+ {
+ if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
+ }
+
+ switch ( i )
+ {
+ case 0 : /* "alpha": Alpha color buffer precision in bits */
+ glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
+ break ;
+
+ case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
+ precision in bits */
+ break ;
+
+ case 2 : /* "acc": Red, green, and blue accumulation buffer precision
+ in bits with zero bits alpha */
+ glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
+ break ;
+
+ case 3 : /* "blue": Blue color buffer precision in bits */
+ break ;
+
+ case 4 : /* "buffer": Number of bits in the color index color buffer
+ */
+ break ;
+
+ case 5 : /* "conformant": Boolean indicating if the frame buffer
+ configuration is conformant or not */
+ break ;
+
+ case 6 : /* "depth": Number of bits of precsion in the depth buffer */
+ glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
+ break ;
+
+ case 7 : /* "double": Boolean indicating if the color buffer is
+ double buffered */
+ glut_state_flag |= GLUT_DOUBLE ;
+ break ;
+
+ case 8 : /* "green": Green color buffer precision in bits */
+ break ;
+
+ case 9 : /* "index": Boolean if the color model is color index or not
+ */
+ glut_state_flag |= GLUT_INDEX ;
+ break ;
+
+ case 10 : /* "num": A special capability name indicating where the
+ value represents the Nth frame buffer configuration
+ matching the description string */
+ break ;
+
+ case 11 : /* "red": Red color buffer precision in bits */
+ break ;
+
+ case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
+ the RGBA color buffer */
+ glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
+ break ;
+
+ case 13 : /* "rgb": Number of bits of red, green, and blue in the
+ RGBA color buffer with zero bits alpha */
+ glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
+ break ;
+
+ case 14 : /* "luminance": Number of bits of red in the RGBA and zero
+ bits of green, blue (alpha not specified) of color buffer
+ precision */
+ glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
+ break ;
+
+ case 15 : /* "stencil": Number of bits in the stencil buffer */
+ glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
+ break ;
+
+ case 16 : /* "single": Boolean indicate the color buffer is single
+ buffered */
+ glut_state_flag |= GLUT_SINGLE ;
+ break ;
+
+ case 17 : /* "stereo": Boolean indicating the color buffer supports
+ OpenGL-style stereo */
+ glut_state_flag |= GLUT_STEREO ;
+ break ;
+
+ case 18 : /* "samples": Indicates the number of multisamples to use
+ based on GLX's SGIS_multisample extension (for
+ antialiasing) */
+ glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
+ break ;
+
+ case 19 : /* "slow": Boolean indicating if the frame buffer
+ configuration is slow or not */
+ break ;
+
+ case 20 : /* "win32pdf": (incorrect spelling but was there before */
+ case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
+ number */
+#if TARGET_HOST_MS_WINDOWS
+#endif
+ break ;
+
+ case 22 : /* "xvisual": matches the X visual ID by number */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 23 : /* "xstaticgray": */
+ case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
+ configuration's X visual is of type StaticGray */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 24 : /* "xgrayscale": */
+ case 30 : /* "xgreyscale": boolean indicating if the frame buffer
+ configuration's X visual is of type GrayScale */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 25 : /* "xstaticcolor": */
+ case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
+ configuration's X visual is of type StaticColor */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 26 : /* "xpseudocolor": */
+ case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
+ configuration's X visual is of type PseudoColor */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 27 : /* "xtruecolor": */
+ case 33 : /* "xtruecolour": boolean indicating if the frame buffer
+ configuration's X visual is of type TrueColor */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 28 : /* "xdirectcolor": */
+ case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
+ configuration's X visual is of type DirectColor */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 35 : /* "borderless": windows should not have borders */
+#if TARGET_HOST_POSIX_X11
+#endif
+ break ;
+
+ case 36 : /* "aux": some number of aux buffers */
+ glut_state_flag |= GLUT_AUX;
+ break ;
+
+ case 37 : /* Unrecognized */
+ fgWarning ( "WARNING - Display string token not recognized: %s",
+ token );
+ break ;
+ }
+
+ token = strtok ( NULL, " \t" );
+ }
+
+ free ( buffer );
+
+ /* We will make use of this value when creating a new OpenGL context... */
+ fgState.DisplayMode = glut_state_flag;
+}
+
+/* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
+
+void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
+{
+ /* We will make use of these valuse when creating a new OpenGL context... */
+ fgState.MajorVersion = majorVersion;
+ fgState.MinorVersion = minorVersion;
+}
+
+
+void FGAPIENTRY glutInitContextFlags( int flags )
+{
+ /* We will make use of this value when creating a new OpenGL context... */
+ fgState.ContextFlags = flags;
+}
+
+void FGAPIENTRY glutInitContextProfile( int profile )
+{
+ /* We will make use of this value when creating a new OpenGL context... */
+ fgState.ContextProfile = profile;
+}
+
+/* -------------- User Defined Error/Warning Handler Support -------------- */
+
+/*
+ * Sets the user error handler (note the use of va_list for the args to the fmt)
+ */
+void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
+{
+ /* This allows user programs to handle freeglut errors */
+ fgState.ErrorFunc = vfgError;
+}
+
+/*
+ * Sets the user warning handler (note the use of va_list for the args to the fmt)
+ */
+void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
+{
+ /* This allows user programs to handle freeglut warnings */
+ fgState.WarningFunc = vfgWarning;
+}
+
+/*** END OF FILE ***/