glut_init.c revision b3dfa806
1 2/* Copyright (c) Mark J. Kilgard, 1994, 1997. */ 3 4/* This program is freely distributable without licensing fees 5 and is provided without guarantee or warrantee expressed or 6 implied. This program is -not- in the public domain. */ 7 8#ifdef __VMS 9#include <GL/vms_x_fix.h> 10#endif 11 12#include <stdlib.h> 13#include <string.h> 14#include <stdio.h> 15 16#if !defined(_WIN32) 17#include <X11/Xlib.h> 18#include <X11/Xatom.h> 19#endif 20 21/* SGI optimization introduced in IRIX 6.3 to avoid X server 22 round trips for interning common X atoms. */ 23#if defined(_SGI_EXTRA_PREDEFINES) && !defined(NO_FAST_ATOMS) 24#include <X11/SGIFastAtom.h> 25#else 26#define XSGIFastInternAtom(dpy,string,fast_name,how) XInternAtom(dpy,string,how) 27#endif 28 29#include "glutint.h" 30 31/* GLUT inter-file variables */ 32/* *INDENT-OFF* */ 33char *__glutProgramName = NULL; 34int __glutArgc = 0; 35char **__glutArgv = NULL; 36char *__glutGeometry = NULL; 37Display *__glutDisplay = NULL; 38int __glutScreen; 39Window __glutRoot; 40int __glutScreenHeight; 41int __glutScreenWidth; 42GLboolean __glutIconic = GL_FALSE; 43GLboolean __glutDebug = GL_FALSE; 44unsigned int __glutDisplayMode = 45 GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH; 46char *__glutDisplayString = NULL; 47int __glutConnectionFD; 48XSizeHints __glutSizeHints = {0}; 49int __glutInitWidth = 300, __glutInitHeight = 300; 50int __glutInitX = -1, __glutInitY = -1; 51GLboolean __glutForceDirect = GL_FALSE, 52 __glutTryDirect = GL_TRUE; 53Atom __glutWMDeleteWindow; 54char *__glutPPMFile = NULL; 55/* *INDENT-ON* */ 56 57#ifdef _WIN32 58void (__cdecl *__glutExitFunc)(int retval) = NULL; 59#endif 60 61static Bool synchronize = False; 62 63#if defined(_WIN32) 64 65#ifdef __BORLANDC__ 66#include <float.h> /* For masking floating point exceptions. */ 67#endif 68 69void 70__glutOpenWin32Connection(char* display) 71{ 72 static char *classname; 73 WNDCLASS wc; 74 HINSTANCE hInstance = GetModuleHandle(NULL); 75 76 /* Make sure we register the window only once. */ 77 if(classname) 78 return; 79 80#ifdef __BORLANDC__ 81 /* Under certain conditions (e.g. while rendering solid surfaces with 82 lighting enabled) Microsoft OpenGL libraries cause some illegal 83 operations like floating point overflow or division by zero. The 84 default behaviour of Microsoft compilers is to mask (ignore) 85 floating point exceptions, while Borland compilers do not. The 86 following function of Borland RTL allows to mask exceptions. 87 Advice from Pier Giorgio Esposito (mc2172@mclink.it). */ 88 _control87(MCW_EM,MCW_EM); 89#endif 90 91 classname = "GLUT"; 92 93 /* Clear (important!) and then fill in the window class structure. */ 94 memset(&wc, 0, sizeof(WNDCLASS)); 95 wc.style = CS_OWNDC; 96 wc.lpfnWndProc = (WNDPROC)__glutWindowProc; 97 wc.hInstance = hInstance; 98 wc.hIcon = LoadIcon(hInstance, "GLUT_ICON"); 99 wc.hCursor = LoadCursor(hInstance, IDC_ARROW); 100 wc.hbrBackground = NULL; 101 wc.lpszMenuName = NULL; 102 wc.lpszClassName = classname; 103 104 /* Fill in a default icon if one isn't specified as a resource. */ 105 if(!wc.hIcon) 106 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); 107 108 if(!RegisterClass(&wc)) { 109 __glutFatalError("RegisterClass() failed:" 110 "Cannot register GLUT window class."); 111 } 112 113 __glutScreenWidth = GetSystemMetrics(SM_CXSCREEN); 114 __glutScreenHeight = GetSystemMetrics(SM_CYSCREEN); 115 116 /* Set the root window to NULL because windows creates a top-level 117 window when the parent is NULL. X creates a top-level window 118 when the parent is the root window. */ 119 __glutRoot = NULL; 120 121 /* Set the display to 1 -- we shouldn't be using this anywhere 122 (except as an argument to X calls). */ 123 __glutDisplay = (Display*)1; 124 125 /* There isn't any concept of multiple screens in Win32, therefore, 126 we don't need to keep track of the screen we're on... it's always 127 the same one. */ 128 __glutScreen = 0; 129} 130#else /* !_WIN32 */ 131void 132__glutOpenXConnection(char *display) 133{ 134 int errorBase, eventBase; 135 136 __glutDisplay = XOpenDisplay(display); 137 if (!__glutDisplay) 138 __glutFatalError("could not open display: %s", 139 XDisplayName(display)); 140 if (synchronize) 141 XSynchronize(__glutDisplay, True); 142 if (!glXQueryExtension(__glutDisplay, &errorBase, &eventBase)) 143 __glutFatalError( 144 "OpenGL GLX extension not supported by display: %s", 145 XDisplayName(display)); 146 __glutScreen = DefaultScreen(__glutDisplay); 147 __glutRoot = RootWindow(__glutDisplay, __glutScreen); 148 __glutScreenWidth = DisplayWidth(__glutDisplay, __glutScreen); 149 __glutScreenHeight = DisplayHeight(__glutDisplay, 150 __glutScreen); 151 __glutConnectionFD = ConnectionNumber(__glutDisplay); 152 __glutWMDeleteWindow = XSGIFastInternAtom(__glutDisplay, 153 "WM_DELETE_WINDOW", SGI_XA_WM_DELETE_WINDOW, False); 154} 155#endif /* _WIN32 */ 156 157void 158#ifdef OLD_VMS 159 __glutInitTime(struct timeval6 *beginning) 160#else 161 __glutInitTime(struct timeval *beginning) 162#endif 163{ 164 static int beenhere = 0; 165#ifdef OLD_VMS 166 static struct timeval6 genesis; 167#else 168 static struct timeval genesis; 169#endif 170 171 if (!beenhere) { 172 GETTIMEOFDAY(&genesis); 173 beenhere = 1; 174 } 175 *beginning = genesis; 176} 177 178static void 179removeArgs(int *argcp, char **argv, int numToRemove) 180{ 181 int i, j; 182 183 for (i = 0, j = numToRemove; argv[j]; i++, j++) { 184 argv[i] = argv[j]; 185 } 186 argv[i] = NULL; 187 *argcp -= numToRemove; 188} 189 190void GLUTAPIENTRY 191glutInit(int *argcp, char **argv) 192{ 193 char *display = NULL; 194 char *str, *geometry = NULL; 195#ifdef OLD_VMS 196 struct timeval6 unused; 197#else 198 struct timeval unused; 199#endif 200 int i; 201 202 if (__glutDisplay) { 203 __glutWarning("glutInit being called a second time."); 204 return; 205 } 206 /* Determine temporary program name. */ 207 str = strrchr(argv[0], '/'); 208 if (str == NULL) { 209 __glutProgramName = argv[0]; 210 } else { 211 __glutProgramName = str + 1; 212 } 213 214 /* Make private copy of command line arguments. */ 215 __glutArgc = *argcp; 216 __glutArgv = (char **) malloc(__glutArgc * sizeof(char *)); 217 if (!__glutArgv) 218 __glutFatalError("out of memory."); 219 for (i = 0; i < __glutArgc; i++) { 220 __glutArgv[i] = __glutStrdup(argv[i]); 221 if (!__glutArgv[i]) 222 __glutFatalError("out of memory."); 223 } 224 225 /* determine permanent program name */ 226 str = strrchr(__glutArgv[0], '/'); 227 if (str == NULL) { 228 __glutProgramName = __glutArgv[0]; 229 } else { 230 __glutProgramName = str + 1; 231 } 232 233 /* parse arguments for standard options */ 234 for (i = 1; i < __glutArgc; i++) { 235 if (!strcmp(__glutArgv[i], "-display")) { 236#if defined(_WIN32) 237 __glutWarning("-display option not supported by Win32 GLUT."); 238#endif 239 if (++i >= __glutArgc) { 240 __glutFatalError( 241 "follow -display option with X display name."); 242 } 243 display = __glutArgv[i]; 244 removeArgs(argcp, &argv[1], 2); 245 } else if (!strcmp(__glutArgv[i], "-geometry")) { 246 if (++i >= __glutArgc) { 247 __glutFatalError( 248 "follow -geometry option with geometry parameter."); 249 } 250 geometry = __glutArgv[i]; 251 removeArgs(argcp, &argv[1], 2); 252 } else if (!strcmp(__glutArgv[i], "-direct")) { 253#if defined(_WIN32) 254 __glutWarning("-direct option not supported by Win32 GLUT."); 255#endif 256 if (!__glutTryDirect) 257 __glutFatalError( 258 "cannot force both direct and indirect rendering."); 259 __glutForceDirect = GL_TRUE; 260 removeArgs(argcp, &argv[1], 1); 261 } else if (!strcmp(__glutArgv[i], "-indirect")) { 262#if defined(_WIN32) 263 __glutWarning("-indirect option not supported by Win32 GLUT."); 264#endif 265 if (__glutForceDirect) 266 __glutFatalError( 267 "cannot force both direct and indirect rendering."); 268 __glutTryDirect = GL_FALSE; 269 removeArgs(argcp, &argv[1], 1); 270 } else if (!strcmp(__glutArgv[i], "-iconic")) { 271 __glutIconic = GL_TRUE; 272 removeArgs(argcp, &argv[1], 1); 273 } else if (!strcmp(__glutArgv[i], "-gldebug")) { 274 __glutDebug = GL_TRUE; 275 removeArgs(argcp, &argv[1], 1); 276 } else if (!strcmp(__glutArgv[i], "-sync")) { 277#if defined(_WIN32) 278 __glutWarning("-sync option not supported by Win32 GLUT."); 279#endif 280 synchronize = GL_TRUE; 281 removeArgs(argcp, &argv[1], 1); 282 } else { 283 /* Once unknown option encountered, stop command line 284 processing. */ 285 break; 286 } 287 } 288#if defined(_WIN32) 289 __glutOpenWin32Connection(display); 290#else 291 __glutOpenXConnection(display); 292#endif 293 if (geometry) { 294 int flags, x, y, width, height; 295 296 /* Fix bogus "{width|height} may be used before set" 297 warning */ 298 width = 0; 299 height = 0; 300 301 flags = XParseGeometry(geometry, &x, &y, 302 (unsigned int *) &width, (unsigned int *) &height); 303 if (WidthValue & flags) { 304 /* Careful because X does not allow zero or negative 305 width windows */ 306 if (width > 0) 307 __glutInitWidth = width; 308 } 309 if (HeightValue & flags) { 310 /* Careful because X does not allow zero or negative 311 height windows */ 312 if (height > 0) 313 __glutInitHeight = height; 314 } 315 glutInitWindowSize(__glutInitWidth, __glutInitHeight); 316 if (XValue & flags) { 317 if (XNegative & flags) 318 x = DisplayWidth(__glutDisplay, __glutScreen) + 319 x - __glutSizeHints.width; 320 /* Play safe: reject negative X locations */ 321 if (x >= 0) 322 __glutInitX = x; 323 } 324 if (YValue & flags) { 325 if (YNegative & flags) 326 y = DisplayHeight(__glutDisplay, __glutScreen) + 327 y - __glutSizeHints.height; 328 /* Play safe: reject negative Y locations */ 329 if (y >= 0) 330 __glutInitY = y; 331 } 332 glutInitWindowPosition(__glutInitX, __glutInitY); 333 } 334 __glutInitTime(&unused); 335 336 /* check if GLUT_FPS env var is set */ 337 { 338 const char *fps = getenv("GLUT_FPS"); 339 if (fps) { 340 sscanf(fps, "%d", &__glutFPS); 341 if (__glutFPS <= 0) 342 __glutFPS = 5000; /* 5000 milliseconds */ 343 } 344 } 345 346 /* check if GLUT_PPM_FILE env var is set */ 347 __glutPPMFile = getenv("GLUT_PPM_FILE"); 348} 349 350#ifdef _WIN32 351void GLUTAPIENTRY 352__glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int)) 353{ 354 __glutExitFunc = exitfunc; 355 glutInit(argcp, argv); 356} 357#endif 358 359/* CENTRY */ 360void GLUTAPIENTRY 361glutInitWindowPosition(int x, int y) 362{ 363 __glutInitX = x; 364 __glutInitY = y; 365 if (x >= 0 && y >= 0) { 366 __glutSizeHints.x = x; 367 __glutSizeHints.y = y; 368 __glutSizeHints.flags |= USPosition; 369 } else { 370 __glutSizeHints.flags &= ~USPosition; 371 } 372} 373 374void GLUTAPIENTRY 375glutInitWindowSize(int width, int height) 376{ 377 __glutInitWidth = width; 378 __glutInitHeight = height; 379 if (width > 0 && height > 0) { 380 __glutSizeHints.width = width; 381 __glutSizeHints.height = height; 382 __glutSizeHints.flags |= USSize; 383 } else { 384 __glutSizeHints.flags &= ~USSize; 385 } 386} 387 388void GLUTAPIENTRY 389glutInitDisplayMode(unsigned int mask) 390{ 391 __glutDisplayMode = mask; 392} 393 394/* ENDCENTRY */ 395