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
32 #if TARGET_HOST_POSIX_X11
\r
33 #include <limits.h> /* LONG_MAX */
\r
37 * TODO BEFORE THE STABLE RELEASE:
\r
39 * fgDeinitialize() -- Win32's OK, X11 needs the OS-specific
\r
40 * deinitialization done
\r
41 * glutInitDisplayString() -- display mode string parsing
\r
43 * Wouldn't it be cool to use gettext() for error messages? I just love
\r
44 * bash saying "nie znaleziono pliku" instead of "file not found" :)
\r
45 * Is gettext easily portable?
\r
48 /* -- GLOBAL VARIABLES ----------------------------------------------------- */
\r
51 * A structure pointed by g_pDisplay holds all information
\r
52 * regarding the display, screen, root window etc.
\r
54 SFG_Display fgDisplay;
\r
57 * The settings for the current freeglut session
\r
59 SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
\r
60 { 300, 300, GL_TRUE }, /* Size */
\r
61 GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH, /* DisplayMode */
\r
62 GL_FALSE, /* Initialised */
\r
63 GLUT_TRY_DIRECT_CONTEXT, /* DirectContext */
\r
64 GL_FALSE, /* ForceIconic */
\r
65 GL_FALSE, /* UseCurrentContext */
\r
66 GL_FALSE, /* GLDebugSwitch */
\r
67 GL_FALSE, /* XSyncSwitch */
\r
68 GLUT_KEY_REPEAT_ON, /* KeyRepeat */
\r
69 INVALID_MODIFIERS, /* Modifiers */
\r
70 0, /* FPSInterval */
\r
74 { NULL, NULL }, /* Timers */
\r
75 { NULL, NULL }, /* FreeTimers */
\r
76 NULL, /* IdleCallback */
\r
77 0, /* ActiveMenus */
\r
78 NULL, /* MenuStateCallback */
\r
79 NULL, /* MenuStatusCallback */
\r
80 { 640, 480, GL_TRUE }, /* GameModeSize */
\r
81 16, /* GameModeDepth */
\r
82 72, /* GameModeRefresh */
\r
83 GLUT_ACTION_EXIT, /* ActionOnWindowClose */
\r
84 GLUT_EXEC_STATE_INIT, /* ExecState */
\r
85 NULL, /* ProgramName */
\r
86 GL_FALSE, /* JoysticksInitialised */
\r
87 0, /* NumActiveJoysticks */
\r
88 GL_FALSE, /* InputDevsInitialised */
\r
89 0, /* MouseWheelTicks */
\r
90 1, /* AuxiliaryBufferNumber */
\r
91 4, /* SampleNumber */
\r
92 1, /* MajorVersion */
\r
93 0, /* MinorVersion */
\r
94 0, /* ContextFlags */
\r
95 0, /* ContextProfile */
\r
96 NULL, /* ErrorFunc */
\r
97 NULL /* WarningFunc */
\r
101 /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
\r
103 #if TARGET_HOST_POSIX_X11
\r
105 /* Return the atom associated with "name". */
\r
106 static Atom fghGetAtom(const char * name)
\r
108 return XInternAtom(fgDisplay.Display, name, False);
\r
112 * Check if "property" is set on "window". The property's values are returned
\r
113 * through "data". If the property is set and is of type "type", return the
\r
114 * number of elements in "data". Return zero otherwise. In both cases, use
\r
115 * "Xfree()" to free "data".
\r
117 static int fghGetWindowProperty(Window window,
\r
120 unsigned char ** data)
\r
123 * Caller always has to use "Xfree()" to free "data", since
\r
124 * "XGetWindowProperty() always allocates one extra byte in prop_return
\r
125 * [i.e. "data"] (even if the property is zero length) [..]".
\r
128 int status; /* Returned by "XGetWindowProperty". */
\r
130 Atom type_returned;
\r
131 int temp_format; /* Not used. */
\r
132 unsigned long number_of_elements;
\r
133 unsigned long temp_bytes_after; /* Not used. */
\r
136 status = XGetWindowProperty(fgDisplay.Display,
\r
145 &number_of_elements,
\r
149 FREEGLUT_INTERNAL_ERROR_EXIT(status == Success,
\r
150 "XGetWindowProperty failled",
\r
151 "fghGetWindowProperty");
\r
153 if (type_returned != type)
\r
155 number_of_elements = 0;
\r
158 return number_of_elements;
\r
161 /* Check if the window manager is NET WM compliant. */
\r
162 static int fghNetWMSupported(void)
\r
165 Window ** window_ptr_1;
\r
167 int number_of_windows;
\r
168 int net_wm_supported;
\r
171 net_wm_supported = 0;
\r
173 wm_check = fghGetAtom("_NET_SUPPORTING_WM_CHECK");
\r
174 window_ptr_1 = malloc(sizeof(Window *));
\r
177 * Check that the window manager has set this property on the root window.
\r
178 * The property must be the ID of a child window.
\r
180 number_of_windows = fghGetWindowProperty(fgDisplay.RootWindow,
\r
183 (unsigned char **) window_ptr_1);
\r
184 if (number_of_windows == 1)
\r
186 Window ** window_ptr_2;
\r
188 window_ptr_2 = malloc(sizeof(Window *));
\r
190 /* Check that the window has the same property set to the same value. */
\r
191 number_of_windows = fghGetWindowProperty(**window_ptr_1,
\r
194 (unsigned char **) window_ptr_2);
\r
195 if ((number_of_windows == 1) && (**window_ptr_1 == **window_ptr_2))
\r
197 /* NET WM compliant */
\r
198 net_wm_supported = 1;
\r
201 XFree(*window_ptr_2);
\r
202 free(window_ptr_2);
\r
205 XFree(*window_ptr_1);
\r
206 free(window_ptr_1);
\r
208 return net_wm_supported;
\r
211 /* Check if "hint" is present in "property" for "window". */
\r
212 int fgHintPresent(Window window, Atom property, Atom hint)
\r
215 int number_of_atoms;
\r
221 number_of_atoms = fghGetWindowProperty(window,
\r
224 (unsigned char **) &atoms);
\r
225 for (i = 0; i < number_of_atoms; i++)
\r
227 if (atoms[i] == hint)
\r
238 #endif /* TARGET_HOST_POSIX_X11 */
\r
242 * A call to this function should initialize all the display stuff...
\r
244 static void fghInitialize( const char* displayName )
\r
246 #if TARGET_HOST_POSIX_X11
\r
247 fgDisplay.Display = XOpenDisplay( displayName );
\r
249 if( fgDisplay.Display == NULL )
\r
250 fgError( "failed to open display '%s'", XDisplayName( displayName ) );
\r
252 if( !glXQueryExtension( fgDisplay.Display, NULL, NULL ) )
\r
253 fgError( "OpenGL GLX extension not supported by display '%s'",
\r
254 XDisplayName( displayName ) );
\r
256 fgDisplay.Screen = DefaultScreen( fgDisplay.Display );
\r
257 fgDisplay.RootWindow = RootWindow(
\r
262 fgDisplay.ScreenWidth = DisplayWidth(
\r
266 fgDisplay.ScreenHeight = DisplayHeight(
\r
271 fgDisplay.ScreenWidthMM = DisplayWidthMM(
\r
275 fgDisplay.ScreenHeightMM = DisplayHeightMM(
\r
280 fgDisplay.Connection = ConnectionNumber( fgDisplay.Display );
\r
282 /* Create the window deletion atom */
\r
283 fgDisplay.DeleteWindow = fghGetAtom("WM_DELETE_WINDOW");
\r
285 /* Create the state and full screen atoms */
\r
286 fgDisplay.State = None;
\r
287 fgDisplay.StateFullScreen = None;
\r
289 if (fghNetWMSupported())
\r
291 const Atom supported = fghGetAtom("_NET_SUPPORTED");
\r
292 const Atom state = fghGetAtom("_NET_WM_STATE");
\r
294 /* Check if the state hint is supported. */
\r
295 if (fgHintPresent(fgDisplay.RootWindow, supported, state))
\r
297 const Atom full_screen = fghGetAtom("_NET_WM_STATE_FULLSCREEN");
\r
299 fgDisplay.State = state;
\r
301 /* Check if the window manager supports full screen. */
\r
302 /** Check "_NET_WM_ALLOWED_ACTIONS" on our window instead? **/
\r
303 if (fgHintPresent(fgDisplay.RootWindow, supported, full_screen))
\r
305 fgDisplay.StateFullScreen = full_screen;
\r
310 #elif TARGET_HOST_MS_WINDOWS
\r
315 /* What we need to do is to initialize the fgDisplay global structure here. */
\r
316 fgDisplay.Instance = GetModuleHandle( NULL );
\r
317 fgDisplay.DisplayName= displayName ? strdup(displayName) : 0 ;
\r
318 atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc );
\r
322 ZeroMemory( &wc, sizeof(WNDCLASS) );
\r
325 * Each of the windows should have its own device context, and we
\r
326 * want redraw events during Vertical and Horizontal Resizes by
\r
329 * XXX Old code had "| CS_DBCLCKS" commented out. Plans for the
\r
330 * XXX future? Dead-end idea?
\r
332 wc.lpfnWndProc = fgWindowProc;
\r
335 wc.hInstance = fgDisplay.Instance;
\r
336 wc.hIcon = LoadIcon( fgDisplay.Instance, _T("GLUT_ICON") );
\r
338 #if defined(_WIN32_WCE)
\r
339 wc.style = CS_HREDRAW | CS_VREDRAW;
\r
341 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
\r
343 wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
\r
346 wc.hCursor = LoadCursor( NULL, IDC_ARROW );
\r
347 wc.hbrBackground = NULL;
\r
348 wc.lpszMenuName = NULL;
\r
349 wc.lpszClassName = _T("FREEGLUT");
\r
351 /* Register the window class */
\r
352 atom = RegisterClass( &wc );
\r
353 FREEGLUT_INTERNAL_ERROR_EXIT ( atom, "Window Class Not Registered", "fghInitialize" );
\r
356 /* The screen dimensions can be obtained via GetSystemMetrics() calls */
\r
357 fgDisplay.ScreenWidth = GetSystemMetrics( SM_CXSCREEN );
\r
358 fgDisplay.ScreenHeight = GetSystemMetrics( SM_CYSCREEN );
\r
361 HWND desktop = GetDesktopWindow( );
\r
362 HDC context = GetDC( desktop );
\r
364 fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
\r
365 fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
\r
367 ReleaseDC( desktop, context );
\r
369 /* If we have a DisplayName try to use it for metrics */
\r
370 if( fgDisplay.DisplayName )
\r
372 HDC context = CreateDC(fgDisplay.DisplayName,0,0,0);
\r
375 fgDisplay.ScreenWidth = GetDeviceCaps( context, HORZRES );
\r
376 fgDisplay.ScreenHeight = GetDeviceCaps( context, VERTRES );
\r
377 fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE );
\r
378 fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE );
\r
382 fgWarning("fghInitialize: "
\r
383 "CreateDC failed, Screen size info may be incorrect\n"
\r
384 "This is quite likely caused by a bad '-display' parameter");
\r
387 /* Set the timer granularity to 1 ms */
\r
388 timeBeginPeriod ( 1 );
\r
392 fgState.Initialised = GL_TRUE;
\r
394 /* Avoid registering atexit callback on Win32 as it results in an access
\r
395 * violation due to calling into a module which has been unloaded.
\r
396 * Any cleanup isn't needed on Windows anyway, the OS takes care of it.c
\r
397 * see: http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx
\r
399 #if ( TARGET_HOST_MS_WINDOWS == 0 )
\r
400 atexit(fgDeinitialize);
\r
403 /* InputDevice uses GlutTimerFunc(), so fgState.Initialised must be TRUE */
\r
404 fgInitialiseInputDevices();
\r
408 * Perform the freeglut deinitialization...
\r
410 void fgDeinitialize( void )
\r
414 if( !fgState.Initialised )
\r
419 /* If we're in game mode, we want to leave game mode */
\r
420 if( fgStructure.GameModeWindow ) {
\r
421 glutLeaveGameMode();
\r
424 /* If there was a menu created, destroy the rendering context */
\r
425 if( fgStructure.MenuContext )
\r
427 #if TARGET_HOST_POSIX_X11
\r
428 /* Note that the MVisualInfo is not owned by the MenuContext! */
\r
429 glXDestroyContext( fgDisplay.Display, fgStructure.MenuContext->MContext );
\r
431 free( fgStructure.MenuContext );
\r
432 fgStructure.MenuContext = NULL;
\r
435 fgDestroyStructure( );
\r
437 while( ( timer = fgState.Timers.First) )
\r
439 fgListRemove( &fgState.Timers, &timer->Node );
\r
443 while( ( timer = fgState.FreeTimers.First) )
\r
445 fgListRemove( &fgState.FreeTimers, &timer->Node );
\r
449 #if !defined(_WIN32_WCE)
\r
450 if ( fgState.JoysticksInitialised )
\r
451 fgJoystickClose( );
\r
453 if ( fgState.InputDevsInitialised )
\r
454 fgInputDeviceClose( );
\r
455 #endif /* !defined(_WIN32_WCE) */
\r
456 fgState.JoysticksInitialised = GL_FALSE;
\r
457 fgState.InputDevsInitialised = GL_FALSE;
\r
459 fgState.MouseWheelTicks = 0;
\r
461 fgState.MajorVersion = 1;
\r
462 fgState.MinorVersion = 0;
\r
463 fgState.ContextFlags = 0;
\r
464 fgState.ContextProfile = 0;
\r
466 fgState.Initialised = GL_FALSE;
\r
468 fgState.Position.X = -1;
\r
469 fgState.Position.Y = -1;
\r
470 fgState.Position.Use = GL_FALSE;
\r
472 fgState.Size.X = 300;
\r
473 fgState.Size.Y = 300;
\r
474 fgState.Size.Use = GL_TRUE;
\r
476 fgState.DisplayMode = GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH;
\r
478 fgState.DirectContext = GLUT_TRY_DIRECT_CONTEXT;
\r
479 fgState.ForceIconic = GL_FALSE;
\r
480 fgState.UseCurrentContext = GL_FALSE;
\r
481 fgState.GLDebugSwitch = GL_FALSE;
\r
482 fgState.XSyncSwitch = GL_FALSE;
\r
483 fgState.ActionOnWindowClose = GLUT_ACTION_EXIT;
\r
484 fgState.ExecState = GLUT_EXEC_STATE_INIT;
\r
486 fgState.KeyRepeat = GLUT_KEY_REPEAT_ON;
\r
487 fgState.Modifiers = INVALID_MODIFIERS;
\r
489 fgState.GameModeSize.X = 640;
\r
490 fgState.GameModeSize.Y = 480;
\r
491 fgState.GameModeDepth = 16;
\r
492 fgState.GameModeRefresh = 72;
\r
494 fgListInit( &fgState.Timers );
\r
495 fgListInit( &fgState.FreeTimers );
\r
497 fgState.IdleCallback = NULL;
\r
498 fgState.MenuStateCallback = ( FGCBMenuState )NULL;
\r
499 fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
\r
501 fgState.SwapCount = 0;
\r
502 fgState.SwapTime = 0;
\r
503 fgState.FPSInterval = 0;
\r
505 if( fgState.ProgramName )
\r
507 free( fgState.ProgramName );
\r
508 fgState.ProgramName = NULL;
\r
511 #if TARGET_HOST_POSIX_X11
\r
514 * Make sure all X-client data we have created will be destroyed on
\r
517 XSetCloseDownMode( fgDisplay.Display, DestroyAll );
\r
520 * Close the display connection, destroying all windows we have
\r
523 XCloseDisplay( fgDisplay.Display );
\r
525 #elif TARGET_HOST_MS_WINDOWS
\r
526 if( fgDisplay.DisplayName )
\r
528 free( fgDisplay.DisplayName );
\r
529 fgDisplay.DisplayName = NULL;
\r
532 /* Reset the timer granularity */
\r
533 timeEndPeriod ( 1 );
\r
537 fgState.Initialised = GL_FALSE;
\r
541 * Everything inside the following #ifndef is copied from the X sources.
\r
544 #if TARGET_HOST_MS_WINDOWS
\r
548 Copyright 1985, 1986, 1987,1998 The Open Group
\r
550 Permission to use, copy, modify, distribute, and sell this software and its
\r
551 documentation for any purpose is hereby granted without fee, provided that
\r
552 the above copyright notice appear in all copies and that both that
\r
553 copyright notice and this permission notice appear in supporting
\r
556 The above copyright notice and this permission notice shall be included
\r
557 in all copies or substantial portions of the Software.
\r
559 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
\r
560 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
561 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
\r
562 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
\r
563 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
\r
564 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
\r
565 OTHER DEALINGS IN THE SOFTWARE.
\r
567 Except as contained in this notice, the name of The Open Group shall
\r
568 not be used in advertising or otherwise to promote the sale, use or
\r
569 other dealings in this Software without prior written authorization
\r
570 from The Open Group.
\r
574 #define NoValue 0x0000
\r
575 #define XValue 0x0001
\r
576 #define YValue 0x0002
\r
577 #define WidthValue 0x0004
\r
578 #define HeightValue 0x0008
\r
579 #define AllValues 0x000F
\r
580 #define XNegative 0x0010
\r
581 #define YNegative 0x0020
\r
584 * XParseGeometry parses strings of the form
\r
585 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
\r
586 * width, height, xoffset, and yoffset are unsigned integers.
\r
587 * Example: "=80x24+300-49"
\r
588 * The equal sign is optional.
\r
589 * It returns a bitmask that indicates which of the four values
\r
590 * were actually found in the string. For each value found,
\r
591 * the corresponding argument is updated; for each value
\r
592 * not found, the corresponding argument is left unchanged.
\r
596 ReadInteger(char *string, char **NextString)
\r
598 register int Result = 0;
\r
601 if (*string == '+')
\r
603 else if (*string == '-')
\r
608 for (; (*string >= '0') && (*string <= '9'); string++)
\r
610 Result = (Result * 10) + (*string - '0');
\r
612 *NextString = string;
\r
619 static int XParseGeometry (
\r
620 const char *string,
\r
623 unsigned int *width, /* RETURN */
\r
624 unsigned int *height) /* RETURN */
\r
626 int mask = NoValue;
\r
627 register char *strind;
\r
628 unsigned int tempWidth = 0, tempHeight = 0;
\r
629 int tempX = 0, tempY = 0;
\r
630 char *nextCharacter;
\r
632 if ( (string == NULL) || (*string == '\0'))
\r
634 if (*string == '=')
\r
635 string++; /* ignore possible '=' at beg of geometry spec */
\r
637 strind = (char *)string;
\r
638 if (*strind != '+' && *strind != '-' && *strind != 'x') {
\r
639 tempWidth = ReadInteger(strind, &nextCharacter);
\r
640 if (strind == nextCharacter)
\r
642 strind = nextCharacter;
\r
643 mask |= WidthValue;
\r
646 if (*strind == 'x' || *strind == 'X') {
\r
648 tempHeight = ReadInteger(strind, &nextCharacter);
\r
649 if (strind == nextCharacter)
\r
651 strind = nextCharacter;
\r
652 mask |= HeightValue;
\r
655 if ((*strind == '+') || (*strind == '-')) {
\r
656 if (*strind == '-') {
\r
658 tempX = -ReadInteger(strind, &nextCharacter);
\r
659 if (strind == nextCharacter)
\r
661 strind = nextCharacter;
\r
667 tempX = ReadInteger(strind, &nextCharacter);
\r
668 if (strind == nextCharacter)
\r
670 strind = nextCharacter;
\r
673 if ((*strind == '+') || (*strind == '-')) {
\r
674 if (*strind == '-') {
\r
676 tempY = -ReadInteger(strind, &nextCharacter);
\r
677 if (strind == nextCharacter)
\r
679 strind = nextCharacter;
\r
685 tempY = ReadInteger(strind, &nextCharacter);
\r
686 if (strind == nextCharacter)
\r
688 strind = nextCharacter;
\r
694 /* If strind isn't at the end of the string the it's an invalid
\r
695 geometry specification. */
\r
697 if (*strind != '\0') return 0;
\r
703 if (mask & WidthValue)
\r
704 *width = tempWidth;
\r
705 if (mask & HeightValue)
\r
706 *height = tempHeight;
\r
711 /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
\r
714 * Perform initialization. This usually happens on the program startup
\r
715 * and restarting after glutMainLoop termination...
\r
717 void FGAPIENTRY glutInit( int* pargc, char** argv )
\r
719 char* displayName = NULL;
\r
720 char* geometry = NULL;
\r
721 int i, j, argc = *pargc;
\r
723 if( fgState.Initialised )
\r
724 fgError( "illegal glutInit() reinitialization attempt" );
\r
726 if (pargc && *pargc && argv && *argv && **argv)
\r
728 fgState.ProgramName = strdup (*argv);
\r
730 if( !fgState.ProgramName )
\r
731 fgError ("Could not allocate space for the program's name.");
\r
734 fgCreateStructure( );
\r
736 /* Get start time */
\r
737 fgState.Time = fgSystemTime();
\r
739 /* check if GLUT_FPS env var is set */
\r
742 const char *fps = getenv( "GLUT_FPS" );
\r
747 sscanf( fps, "%d", &interval );
\r
749 if( interval <= 0 )
\r
750 fgState.FPSInterval = 5000; /* 5000 millisecond default */
\r
752 fgState.FPSInterval = interval;
\r
756 displayName = getenv( "DISPLAY" );
\r
758 for( i = 1; i < argc; i++ )
\r
760 if( strcmp( argv[ i ], "-display" ) == 0 )
\r
763 fgError( "-display parameter must be followed by display name" );
\r
765 displayName = argv[ i ];
\r
767 argv[ i - 1 ] = NULL;
\r
771 else if( strcmp( argv[ i ], "-geometry" ) == 0 )
\r
774 fgError( "-geometry parameter must be followed by window "
\r
775 "geometry settings" );
\r
777 geometry = argv[ i ];
\r
779 argv[ i - 1 ] = NULL;
\r
783 else if( strcmp( argv[ i ], "-direct" ) == 0)
\r
785 if( fgState.DirectContext == GLUT_FORCE_INDIRECT_CONTEXT )
\r
786 fgError( "parameters ambiguity, -direct and -indirect "
\r
787 "cannot be both specified" );
\r
789 fgState.DirectContext = GLUT_FORCE_DIRECT_CONTEXT;
\r
793 else if( strcmp( argv[ i ], "-indirect" ) == 0 )
\r
795 if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
\r
796 fgError( "parameters ambiguity, -direct and -indirect "
\r
797 "cannot be both specified" );
\r
799 fgState.DirectContext = GLUT_FORCE_INDIRECT_CONTEXT;
\r
803 else if( strcmp( argv[ i ], "-iconic" ) == 0 )
\r
805 fgState.ForceIconic = GL_TRUE;
\r
809 else if( strcmp( argv[ i ], "-gldebug" ) == 0 )
\r
811 fgState.GLDebugSwitch = GL_TRUE;
\r
815 else if( strcmp( argv[ i ], "-sync" ) == 0 )
\r
817 fgState.XSyncSwitch = GL_TRUE;
\r
823 /* Compact {argv}. */
\r
824 for( i = j = 1; i < *pargc; i++, j++ )
\r
826 /* Guaranteed to end because there are "*pargc" arguments left */
\r
827 while ( argv[ j ] == NULL )
\r
830 argv[ i ] = argv[ j ];
\r
833 #endif /* _WIN32_WCE */
\r
836 * Have the display created now. If there wasn't a "-display"
\r
837 * in the program arguments, we will use the DISPLAY environment
\r
838 * variable for opening the X display (see code above):
\r
840 fghInitialize( displayName );
\r
843 * Geometry parsing deffered until here because we may need the screen
\r
849 unsigned int parsedWidth, parsedHeight;
\r
850 int mask = XParseGeometry( geometry,
\r
851 &fgState.Position.X, &fgState.Position.Y,
\r
852 &parsedWidth, &parsedHeight );
\r
853 /* TODO: Check for overflow? */
\r
854 fgState.Size.X = parsedWidth;
\r
855 fgState.Size.Y = parsedHeight;
\r
857 if( (mask & (WidthValue|HeightValue)) == (WidthValue|HeightValue) )
\r
858 fgState.Size.Use = GL_TRUE;
\r
860 if( mask & XNegative )
\r
861 fgState.Position.X += fgDisplay.ScreenWidth - fgState.Size.X;
\r
863 if( mask & YNegative )
\r
864 fgState.Position.Y += fgDisplay.ScreenHeight - fgState.Size.Y;
\r
866 if( (mask & (XValue|YValue)) == (XValue|YValue) )
\r
867 fgState.Position.Use = GL_TRUE;
\r
871 #if TARGET_HOST_MS_WINDOWS
\r
872 void (__cdecl *__glutExitFunc)( int return_value ) = NULL;
\r
874 void FGAPIENTRY __glutInitWithExit( int *pargc, char **argv, void (__cdecl *exit_function)(int) )
\r
876 __glutExitFunc = exit_function;
\r
877 glutInit(pargc, argv);
\r
882 * Undoes all the "glutInit" stuff
\r
884 void FGAPIENTRY glutExit ( void )
\r
890 * Sets the default initial window position for new windows
\r
892 void FGAPIENTRY glutInitWindowPosition( int x, int y )
\r
894 fgState.Position.X = x;
\r
895 fgState.Position.Y = y;
\r
897 if( ( x >= 0 ) && ( y >= 0 ) )
\r
898 fgState.Position.Use = GL_TRUE;
\r
900 fgState.Position.Use = GL_FALSE;
\r
904 * Sets the default initial window size for new windows
\r
906 void FGAPIENTRY glutInitWindowSize( int width, int height )
\r
908 fgState.Size.X = width;
\r
909 fgState.Size.Y = height;
\r
911 if( ( width > 0 ) && ( height > 0 ) )
\r
912 fgState.Size.Use = GL_TRUE;
\r
914 fgState.Size.Use = GL_FALSE;
\r
918 * Sets the default display mode for all new windows
\r
920 void FGAPIENTRY glutInitDisplayMode( unsigned int displayMode )
\r
922 /* We will make use of this value when creating a new OpenGL context... */
\r
923 fgState.DisplayMode = displayMode;
\r
927 /* -- INIT DISPLAY STRING PARSING ------------------------------------------ */
\r
929 static char* Tokens[] =
\r
931 "alpha", "acca", "acc", "blue", "buffer", "conformant", "depth", "double",
\r
932 "green", "index", "num", "red", "rgba", "rgb", "luminance", "stencil",
\r
933 "single", "stereo", "samples", "slow", "win32pdf", "win32pfd", "xvisual",
\r
934 "xstaticgray", "xgrayscale", "xstaticcolor", "xpseudocolor",
\r
935 "xtruecolor", "xdirectcolor",
\r
936 "xstaticgrey", "xgreyscale", "xstaticcolour", "xpseudocolour",
\r
937 "xtruecolour", "xdirectcolour", "borderless", "aux"
\r
939 #define NUM_TOKENS (sizeof(Tokens) / sizeof(*Tokens))
\r
941 void FGAPIENTRY glutInitDisplayString( const char* displayMode )
\r
943 int glut_state_flag = 0 ;
\r
945 * Unpack a lot of options from a character string. The options are
\r
946 * delimited by blanks or tabs.
\r
949 size_t len = strlen ( displayMode );
\r
950 char *buffer = (char *)malloc ( (len+1) * sizeof(char) );
\r
951 memcpy ( buffer, displayMode, len );
\r
952 buffer[len] = '\0';
\r
954 token = strtok ( buffer, " \t" );
\r
958 /* Process this token */
\r
961 /* Temporary fix: Ignore any length specifications and at least
\r
962 * process the basic token
\r
963 * TODO: Fix this permanently
\r
965 size_t cleanlength = strcspn ( token, "=<>~!" );
\r
967 for ( i = 0; i < NUM_TOKENS; i++ )
\r
969 if ( strncmp ( token, Tokens[i], cleanlength ) == 0 ) break ;
\r
974 case 0 : /* "alpha": Alpha color buffer precision in bits */
\r
975 glut_state_flag |= GLUT_ALPHA ; /* Somebody fix this for me! */
\r
978 case 1 : /* "acca": Red, green, blue, and alpha accumulation buffer
\r
979 precision in bits */
\r
982 case 2 : /* "acc": Red, green, and blue accumulation buffer precision
\r
983 in bits with zero bits alpha */
\r
984 glut_state_flag |= GLUT_ACCUM ; /* Somebody fix this for me! */
\r
987 case 3 : /* "blue": Blue color buffer precision in bits */
\r
990 case 4 : /* "buffer": Number of bits in the color index color buffer
\r
994 case 5 : /* "conformant": Boolean indicating if the frame buffer
\r
995 configuration is conformant or not */
\r
998 case 6 : /* "depth": Number of bits of precsion in the depth buffer */
\r
999 glut_state_flag |= GLUT_DEPTH ; /* Somebody fix this for me! */
\r
1002 case 7 : /* "double": Boolean indicating if the color buffer is
\r
1003 double buffered */
\r
1004 glut_state_flag |= GLUT_DOUBLE ;
\r
1007 case 8 : /* "green": Green color buffer precision in bits */
\r
1010 case 9 : /* "index": Boolean if the color model is color index or not
\r
1012 glut_state_flag |= GLUT_INDEX ;
\r
1015 case 10 : /* "num": A special capability name indicating where the
\r
1016 value represents the Nth frame buffer configuration
\r
1017 matching the description string */
\r
1020 case 11 : /* "red": Red color buffer precision in bits */
\r
1023 case 12 : /* "rgba": Number of bits of red, green, blue, and alpha in
\r
1024 the RGBA color buffer */
\r
1025 glut_state_flag |= GLUT_RGBA ; /* Somebody fix this for me! */
\r
1028 case 13 : /* "rgb": Number of bits of red, green, and blue in the
\r
1029 RGBA color buffer with zero bits alpha */
\r
1030 glut_state_flag |= GLUT_RGB ; /* Somebody fix this for me! */
\r
1033 case 14 : /* "luminance": Number of bits of red in the RGBA and zero
\r
1034 bits of green, blue (alpha not specified) of color buffer
\r
1036 glut_state_flag |= GLUT_LUMINANCE ; /* Somebody fix this for me! */
\r
1039 case 15 : /* "stencil": Number of bits in the stencil buffer */
\r
1040 glut_state_flag |= GLUT_STENCIL; /* Somebody fix this for me! */
\r
1043 case 16 : /* "single": Boolean indicate the color buffer is single
\r
1045 glut_state_flag |= GLUT_SINGLE ;
\r
1048 case 17 : /* "stereo": Boolean indicating the color buffer supports
\r
1049 OpenGL-style stereo */
\r
1050 glut_state_flag |= GLUT_STEREO ;
\r
1053 case 18 : /* "samples": Indicates the number of multisamples to use
\r
1054 based on GLX's SGIS_multisample extension (for
\r
1056 glut_state_flag |= GLUT_MULTISAMPLE ; /*Somebody fix this for me!*/
\r
1059 case 19 : /* "slow": Boolean indicating if the frame buffer
\r
1060 configuration is slow or not */
\r
1063 case 20 : /* "win32pdf": (incorrect spelling but was there before */
\r
1064 case 21 : /* "win32pfd": matches the Win32 Pixel Format Descriptor by
\r
1066 #if TARGET_HOST_MS_WINDOWS
\r
1070 case 22 : /* "xvisual": matches the X visual ID by number */
\r
1071 #if TARGET_HOST_POSIX_X11
\r
1075 case 23 : /* "xstaticgray": */
\r
1076 case 29 : /* "xstaticgrey": boolean indicating if the frame buffer
\r
1077 configuration's X visual is of type StaticGray */
\r
1078 #if TARGET_HOST_POSIX_X11
\r
1082 case 24 : /* "xgrayscale": */
\r
1083 case 30 : /* "xgreyscale": boolean indicating if the frame buffer
\r
1084 configuration's X visual is of type GrayScale */
\r
1085 #if TARGET_HOST_POSIX_X11
\r
1089 case 25 : /* "xstaticcolor": */
\r
1090 case 31 : /* "xstaticcolour": boolean indicating if the frame buffer
\r
1091 configuration's X visual is of type StaticColor */
\r
1092 #if TARGET_HOST_POSIX_X11
\r
1096 case 26 : /* "xpseudocolor": */
\r
1097 case 32 : /* "xpseudocolour": boolean indicating if the frame buffer
\r
1098 configuration's X visual is of type PseudoColor */
\r
1099 #if TARGET_HOST_POSIX_X11
\r
1103 case 27 : /* "xtruecolor": */
\r
1104 case 33 : /* "xtruecolour": boolean indicating if the frame buffer
\r
1105 configuration's X visual is of type TrueColor */
\r
1106 #if TARGET_HOST_POSIX_X11
\r
1110 case 28 : /* "xdirectcolor": */
\r
1111 case 34 : /* "xdirectcolour": boolean indicating if the frame buffer
\r
1112 configuration's X visual is of type DirectColor */
\r
1113 #if TARGET_HOST_POSIX_X11
\r
1117 case 35 : /* "borderless": windows should not have borders */
\r
1118 #if TARGET_HOST_POSIX_X11
\r
1122 case 36 : /* "aux": some number of aux buffers */
\r
1123 glut_state_flag |= GLUT_AUX;
\r
1126 case 37 : /* Unrecognized */
\r
1127 fgWarning ( "WARNING - Display string token not recognized: %s",
\r
1132 token = strtok ( NULL, " \t" );
\r
1137 /* We will make use of this value when creating a new OpenGL context... */
\r
1138 fgState.DisplayMode = glut_state_flag;
\r
1141 /* -- SETTING OPENGL 3.0 CONTEXT CREATION PARAMETERS ---------------------- */
\r
1143 void FGAPIENTRY glutInitContextVersion( int majorVersion, int minorVersion )
\r
1145 /* We will make use of these valuse when creating a new OpenGL context... */
\r
1146 fgState.MajorVersion = majorVersion;
\r
1147 fgState.MinorVersion = minorVersion;
\r
1151 void FGAPIENTRY glutInitContextFlags( int flags )
\r
1153 /* We will make use of this value when creating a new OpenGL context... */
\r
1154 fgState.ContextFlags = flags;
\r
1157 void FGAPIENTRY glutInitContextProfile( int profile )
\r
1159 /* We will make use of this value when creating a new OpenGL context... */
\r
1160 fgState.ContextProfile = profile;
\r
1163 /* -------------- User Defined Error/Warning Handler Support -------------- */
\r
1166 * Sets the user error handler (note the use of va_list for the args to the fmt)
\r
1168 void FGAPIENTRY glutInitErrorFunc( void (* vfgError) ( const char *fmt, va_list ap ) )
\r
1170 /* This allows user programs to handle freeglut errors */
\r
1171 fgState.ErrorFunc = vfgError;
\r
1175 * Sets the user warning handler (note the use of va_list for the args to the fmt)
\r
1177 void FGAPIENTRY glutInitWarningFunc( void (* vfgWarning) ( const char *fmt, va_list ap ) )
\r
1179 /* This allows user programs to handle freeglut warnings */
\r
1180 fgState.WarningFunc = vfgWarning;
\r
1183 /*** END OF FILE ***/
\r