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