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