Committing in .
[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 __glutInitTime(struct timeval *beginning)
158 {
159 static int beenhere = 0;
160 static struct timeval genesis;
161
162 if (!beenhere) {
163 GETTIMEOFDAY(&genesis);
164 beenhere = 1;
165 }
166 *beginning = genesis;
167 }
168
169 static void
170 removeArgs(int *argcp, char **argv, int numToRemove)
171 {
172 int i, j;
173
174 for (i = 0, j = numToRemove; argv[j]; i++, j++) {
175 argv[i] = argv[j];
176 }
177 argv[i] = NULL;
178 *argcp -= numToRemove;
179 }
180
181 void APIENTRY
182 glutInit(int *argcp, char **argv)
183 {
184 char *display = NULL;
185 char *str, *geometry = NULL;
186 struct timeval unused;
187 int i;
188
189 if (__glutDisplay) {
190 __glutWarning("glutInit being called a second time.");
191 return;
192 }
193 /* Determine temporary program name. */
194 str = strrchr(argv[0], '/');
195 if (str == NULL) {
196 __glutProgramName = argv[0];
197 } else {
198 __glutProgramName = str + 1;
199 }
200
201 /* Make private copy of command line arguments. */
202 __glutArgc = *argcp;
203 __glutArgv = (char **) malloc(__glutArgc * sizeof(char *));
204 if (!__glutArgv)
205 __glutFatalError("out of memory.");
206 for (i = 0; i < __glutArgc; i++) {
207 __glutArgv[i] = __glutStrdup(argv[i]);
208 if (!__glutArgv[i])
209 __glutFatalError("out of memory.");
210 }
211
212 /* determine permanent program name */
213 str = strrchr(__glutArgv[0], '/');
214 if (str == NULL) {
215 __glutProgramName = __glutArgv[0];
216 } else {
217 __glutProgramName = str + 1;
218 }
219
220 /* parse arguments for standard options */
221 for (i = 1; i < __glutArgc; i++) {
222 if (!strcmp(__glutArgv[i], "-display")) {
223 #if defined(_WIN32)
224 __glutWarning("-display option not supported by Win32 GLUT.");
225 #endif
226 if (++i >= __glutArgc) {
227 __glutFatalError(
228 "follow -display option with X display name.");
229 }
230 display = __glutArgv[i];
231 removeArgs(argcp, &argv[1], 2);
232 } else if (!strcmp(__glutArgv[i], "-geometry")) {
233 if (++i >= __glutArgc) {
234 __glutFatalError(
235 "follow -geometry option with geometry parameter.");
236 }
237 geometry = __glutArgv[i];
238 removeArgs(argcp, &argv[1], 2);
239 } else if (!strcmp(__glutArgv[i], "-direct")) {
240 #if defined(_WIN32)
241 __glutWarning("-direct option not supported by Win32 GLUT.");
242 #endif
243 if (!__glutTryDirect)
244 __glutFatalError(
245 "cannot force both direct and indirect rendering.");
246 __glutForceDirect = GL_TRUE;
247 removeArgs(argcp, &argv[1], 1);
248 } else if (!strcmp(__glutArgv[i], "-indirect")) {
249 #if defined(_WIN32)
250 __glutWarning("-indirect option not supported by Win32 GLUT.");
251 #endif
252 if (__glutForceDirect)
253 __glutFatalError(
254 "cannot force both direct and indirect rendering.");
255 __glutTryDirect = GL_FALSE;
256 removeArgs(argcp, &argv[1], 1);
257 } else if (!strcmp(__glutArgv[i], "-iconic")) {
258 __glutIconic = GL_TRUE;
259 removeArgs(argcp, &argv[1], 1);
260 } else if (!strcmp(__glutArgv[i], "-gldebug")) {
261 __glutDebug = GL_TRUE;
262 removeArgs(argcp, &argv[1], 1);
263 } else if (!strcmp(__glutArgv[i], "-sync")) {
264 #if defined(_WIN32)
265 __glutWarning("-sync option not supported by Win32 GLUT.");
266 #endif
267 synchronize = GL_TRUE;
268 removeArgs(argcp, &argv[1], 1);
269 } else {
270 /* Once unknown option encountered, stop command line
271 processing. */
272 break;
273 }
274 }
275 #if defined(_WIN32)
276 __glutOpenWin32Connection(display);
277 #else
278 __glutOpenXConnection(display);
279 #endif
280 if (geometry) {
281 int flags, x, y, width, height;
282
283 /* Fix bogus "{width|height} may be used before set"
284 warning */
285 width = 0;
286 height = 0;
287
288 flags = XParseGeometry(geometry, &x, &y,
289 (unsigned int *) &width, (unsigned int *) &height);
290 if (WidthValue & flags) {
291 /* Careful because X does not allow zero or negative
292 width windows */
293 if (width > 0)
294 __glutInitWidth = width;
295 }
296 if (HeightValue & flags) {
297 /* Careful because X does not allow zero or negative
298 height windows */
299 if (height > 0)
300 __glutInitHeight = height;
301 }
302 glutInitWindowSize(__glutInitWidth, __glutInitHeight);
303 if (XValue & flags) {
304 if (XNegative & flags)
305 x = DisplayWidth(__glutDisplay, __glutScreen) +
306 x - __glutSizeHints.width;
307 /* Play safe: reject negative X locations */
308 if (x >= 0)
309 __glutInitX = x;
310 }
311 if (YValue & flags) {
312 if (YNegative & flags)
313 y = DisplayHeight(__glutDisplay, __glutScreen) +
314 y - __glutSizeHints.height;
315 /* Play safe: reject negative Y locations */
316 if (y >= 0)
317 __glutInitY = y;
318 }
319 glutInitWindowPosition(__glutInitX, __glutInitY);
320 }
321 __glutInitTime(&unused);
322 }
323
324 #ifdef _WIN32
325 void APIENTRY
326 __glutInitWithExit(int *argcp, char **argv, void (__cdecl *exitfunc)(int))
327 {
328 __glutExitFunc = exitfunc;
329 glutInit(argcp, argv);
330 }
331 #endif
332
333 /* CENTRY */
334 void APIENTRY
335 glutInitWindowPosition(int x, int y)
336 {
337 __glutInitX = x;
338 __glutInitY = y;
339 if (x >= 0 && y >= 0) {
340 __glutSizeHints.x = x;
341 __glutSizeHints.y = y;
342 __glutSizeHints.flags |= USPosition;
343 } else {
344 __glutSizeHints.flags &= ~USPosition;
345 }
346 }
347
348 void APIENTRY
349 glutInitWindowSize(int width, int height)
350 {
351 __glutInitWidth = width;
352 __glutInitHeight = height;
353 if (width > 0 && height > 0) {
354 __glutSizeHints.width = width;
355 __glutSizeHints.height = height;
356 __glutSizeHints.flags |= USSize;
357 } else {
358 __glutSizeHints.flags &= ~USSize;
359 }
360 }
361
362 void APIENTRY
363 glutInitDisplayMode(unsigned int mask)
364 {
365 __glutDisplayMode = mask;
366 }
367
368 /* ENDCENTRY */