1 /* $Id: manywin.c,v 1.5 2001/11/26 17:21:46 brianp Exp $ */
4 * Create N GLX windows/contexts and render to them in round-robin
7 * Copyright (C) 2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 * Each display/window/context:
40 char DisplayName
[1000];
52 static struct head Heads
[MAX_HEADS
];
53 static int NumHeads
= 0;
54 static GLboolean SwapSeparate
= GL_TRUE
;
59 Error(const char *display
, const char *msg
)
61 fprintf(stderr
, "Error on display %s - %s\n", display
, msg
);
67 AddHead(const char *displayName
, const char *name
)
72 int attrib
[] = { GLX_RGBA
,
79 XSetWindowAttributes attr
;
83 int width
= 90, height
= 90;
84 int xpos
= 0, ypos
= 0;
86 if (NumHeads
>= MAX_HEADS
)
89 dpy
= XOpenDisplay(displayName
);
91 Error(displayName
, "Unable to open display");
95 scrnum
= DefaultScreen(dpy
);
96 root
= RootWindow(dpy
, scrnum
);
98 visinfo
= glXChooseVisual(dpy
, scrnum
, attrib
);
100 Error(displayName
, "Unable to find RGB, double-buffered visual");
104 /* window attributes */
105 xpos
= (NumHeads
% 10) * 100;
106 ypos
= (NumHeads
/ 10) * 100;
107 printf("%d, %d\n", xpos
, ypos
);
108 attr
.background_pixel
= 0;
109 attr
.border_pixel
= 0;
110 attr
.colormap
= XCreateColormap(dpy
, root
, visinfo
->visual
, AllocNone
);
111 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
112 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
114 win
= XCreateWindow(dpy
, root
, xpos
, ypos
, width
, height
,
115 0, visinfo
->depth
, InputOutput
,
116 visinfo
->visual
, mask
, &attr
);
118 Error(displayName
, "Couldn't create window");
123 XSizeHints sizehints
;
126 sizehints
.width
= width
;
127 sizehints
.height
= height
;
128 sizehints
.flags
= USSize
| USPosition
;
129 XSetNormalHints(dpy
, win
, &sizehints
);
130 XSetStandardProperties(dpy
, win
, name
, name
,
131 None
, (char **)NULL
, 0, &sizehints
);
135 ctx
= glXCreateContext(dpy
, visinfo
, NULL
, True
);
137 Error(displayName
, "Couldn't create GLX context");
141 XMapWindow(dpy
, win
);
143 if (!glXMakeCurrent(dpy
, win
, ctx
)) {
144 Error(displayName
, "glXMakeCurrent failed");
145 printf("glXMakeCurrent failed in Redraw()\n");
149 /* save the info for this head */
151 struct head
*h
= &Heads
[NumHeads
];
152 strcpy(h
->DisplayName
, name
);
157 strcpy(h
->Version
, (char *) glGetString(GL_VERSION
));
158 strcpy(h
->Vendor
, (char *) glGetString(GL_VENDOR
));
159 strcpy(h
->Renderer
, (char *) glGetString(GL_RENDERER
));
161 return &Heads
[NumHeads
-1];
171 for (i
= 0; i
< NumHeads
; i
++) {
172 XDestroyWindow(Heads
[i
].Dpy
, Heads
[i
].Win
);
173 glXDestroyContext(Heads
[i
].Dpy
, Heads
[i
].Context
);
174 XCloseDisplay(Heads
[i
].Dpy
);
180 Redraw(struct head
*h
)
182 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
183 Error(h
->DisplayName
, "glXMakeCurrent failed");
184 printf("glXMakeCurrent failed in Redraw()\n");
190 glShadeModel(GL_FLAT
);
191 glClearColor(0.5, 0.5, 0.5, 1.0);
192 glClear(GL_COLOR_BUFFER_BIT
);
194 /* draw green triangle */
195 glColor3f(0.0, 1.0, 0.0);
197 glRotatef(h
->Angle
, 0, 0, 1);
198 glBegin(GL_TRIANGLES
);
200 glVertex2f(-0.8, -0.7);
201 glVertex2f(0.8, -0.7);
206 glXSwapBuffers(h
->Dpy
, h
->Win
);
213 glXSwapBuffers(h
->Dpy
, h
->Win
);
218 Resize(const struct head
*h
, unsigned int width
, unsigned int height
)
220 if (!glXMakeCurrent(h
->Dpy
, h
->Win
, h
->Context
)) {
221 Error(h
->DisplayName
, "glXMakeCurrent failed in Resize()");
225 glViewport(0, 0, width
, height
);
226 glMatrixMode(GL_PROJECTION
);
228 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
238 for (i
= 0; i
< NumHeads
; i
++) {
239 struct head
*h
= &Heads
[i
];
240 while (XPending(h
->Dpy
) > 0) {
242 XNextEvent(h
->Dpy
, &event
);
243 if (event
.xany
.window
== h
->Win
) {
244 switch (event
.type
) {
250 case ConfigureNotify
:
251 Resize(h
, event
.xconfigure
.width
, event
.xconfigure
.height
);
260 printf("window mismatch\n");
265 /* redraw all windows */
266 for (i
= 0; i
< NumHeads
; i
++) {
269 /* swapbuffers on all windows, if not already done */
271 for (i
= 0; i
< NumHeads
; i
++) {
282 PrintInfo(const struct head
*h
)
284 printf("Name: %s\n", h
->DisplayName
);
285 printf(" Display: %p\n", (void *) h
->Dpy
);
286 printf(" Window: 0x%x\n", (int) h
->Win
);
287 printf(" Context: 0x%x\n", (int) h
->Context
);
288 printf(" GL_VERSION: %s\n", h
->Version
);
289 printf(" GL_VENDOR: %s\n", h
->Vendor
);
290 printf(" GL_RENDERER: %s\n", h
->Renderer
);
295 main(int argc
, char *argv
[])
297 char *dpyName
= NULL
;
301 printf("manywin: open N simultaneous glx windows\n");
303 printf(" manywin [-s] numWindows\n");
304 printf("Options:\n");
305 printf(" -s = swap immediately after drawing (see src code)\n");
306 printf("Example:\n");
307 printf(" manywin 10\n");
312 for (i
= 1; i
< argc
; i
++) {
313 if (strcmp(argv
[i
], "-s") == 0) {
314 SwapSeparate
= GL_FALSE
;
316 else if (strcmp(argv
[i
], "-display") == 0 && i
< argc
) {
327 printf("%d windows\n", n
);
328 for (i
= 0; i
< n
; i
++) {
331 sprintf(name
, "%d", i
);
332 h
= AddHead(dpyName
, name
);