Merge branch '7.8' into master
[mesa.git] / progs / xdemos / glxheads.c
1
2 /*
3 * Exercise multiple GLX connections on multiple X displays.
4 * Direct GLX contexts are attempted first, then indirect.
5 * Each window will display a spinning green triangle.
6 *
7 * Copyright (C) 2000 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28 #include <GL/gl.h>
29 #include <GL/glx.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34
35
36
37 /*
38 * Each display/window/context:
39 */
40 struct head {
41 char DisplayName[1000];
42 Display *Dpy;
43 Window Win;
44 GLXContext Context;
45 float Angle;
46 char Renderer[1000];
47 char Vendor[1000];
48 char Version[1000];
49 };
50
51
52 #define MAX_HEADS 20
53 static struct head Heads[MAX_HEADS];
54 static int NumHeads = 0;
55
56
57 static void
58 Error(const char *display, const char *msg)
59 {
60 fprintf(stderr, "Error on display %s - %s\n", XDisplayName(display), msg);
61 exit(1);
62 }
63
64
65 static struct head *
66 AddHead(const char *displayName)
67 {
68 Display *dpy;
69 Window win;
70 GLXContext ctx;
71 int attrib[] = { GLX_RGBA,
72 GLX_RED_SIZE, 1,
73 GLX_GREEN_SIZE, 1,
74 GLX_BLUE_SIZE, 1,
75 GLX_DOUBLEBUFFER,
76 None };
77 int scrnum;
78 XSetWindowAttributes attr;
79 unsigned long mask;
80 Window root;
81 XVisualInfo *visinfo;
82 int width = 300, height = 300;
83 int xpos = 10, ypos = 10;
84
85 if (NumHeads >= MAX_HEADS)
86 return NULL;
87
88 dpy = XOpenDisplay(displayName);
89 if (!dpy) {
90 Error(displayName, "Unable to open display");
91 return NULL;
92 }
93
94 scrnum = DefaultScreen(dpy);
95 root = RootWindow(dpy, scrnum);
96
97 visinfo = glXChooseVisual(dpy, scrnum, attrib);
98 if (!visinfo) {
99 Error(displayName, "Unable to find RGB, double-buffered visual");
100 return NULL;
101 }
102
103 /* window attributes */
104 attr.background_pixel = 0;
105 attr.border_pixel = 0;
106 attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
107 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
108 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
109
110 win = XCreateWindow(dpy, root, 0, 0, width, height,
111 0, visinfo->depth, InputOutput,
112 visinfo->visual, mask, &attr);
113 if (!win) {
114 Error(displayName, "Couldn't create window");
115 return NULL;
116 }
117
118 {
119 XSizeHints sizehints;
120 sizehints.x = xpos;
121 sizehints.y = ypos;
122 sizehints.width = width;
123 sizehints.height = height;
124 sizehints.flags = USSize | USPosition;
125 XSetNormalHints(dpy, win, &sizehints);
126 XSetStandardProperties(dpy, win, displayName, displayName,
127 None, (char **)NULL, 0, &sizehints);
128 }
129
130
131 ctx = glXCreateContext(dpy, visinfo, NULL, True);
132 if (!ctx) {
133 Error(displayName, "Couldn't create GLX context");
134 return NULL;
135 }
136
137 XMapWindow(dpy, win);
138
139 if (!glXMakeCurrent(dpy, win, ctx)) {
140 Error(displayName, "glXMakeCurrent failed");
141 printf("glXMakeCurrent failed in Redraw()\n");
142 return NULL;
143 }
144
145 /* save the info for this head */
146 {
147 struct head *h = &Heads[NumHeads];
148 const char * tmp;
149
150 if (strlen(displayName) + 1 > sizeof(h->DisplayName)) {
151 Error(displayName, "displayName string length overflow");
152 return NULL;
153 }
154 strcpy(h->DisplayName, displayName);
155
156 h->Dpy = dpy;
157 h->Win = win;
158 h->Context = ctx;
159 h->Angle = 0.0;
160
161 tmp = (char *) glGetString(GL_VERSION);
162 if (strlen(tmp) + 1 > sizeof(h->Version)) {
163 Error(displayName, "GL_VERSION string length overflow");
164 return NULL;
165 }
166 strcpy(h->Version, tmp);
167
168 tmp = (char *) glGetString(GL_VENDOR);
169 if (strlen(tmp) + 1 > sizeof(h->Vendor)) {
170 Error(displayName, "GL_VENDOR string length overflow");
171 return NULL;
172 }
173 strcpy(h->Vendor, tmp);
174
175 tmp = (char *) glGetString(GL_RENDERER);
176 if (strlen(tmp) + 1 > sizeof(h->Renderer)) {
177 Error(displayName, "GL_RENDERER string length overflow");
178 return NULL;
179 }
180 strcpy(h->Renderer, tmp);
181
182 NumHeads++;
183 return &Heads[NumHeads-1];
184 }
185
186 }
187
188
189 static void
190 Redraw(struct head *h)
191 {
192 if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
193 Error(h->DisplayName, "glXMakeCurrent failed");
194 printf("glXMakeCurrent failed in Redraw()\n");
195 return;
196 }
197
198 h->Angle += 1.0;
199
200 glShadeModel(GL_FLAT);
201 glClearColor(0.5, 0.5, 0.5, 1.0);
202 glClear(GL_COLOR_BUFFER_BIT);
203
204 /* draw green triangle */
205 glColor3f(0.0, 1.0, 0.0);
206 glPushMatrix();
207 glRotatef(h->Angle, 0, 0, 1);
208 glBegin(GL_TRIANGLES);
209 glVertex2f(0, 0.8);
210 glVertex2f(-0.8, -0.7);
211 glVertex2f(0.8, -0.7);
212 glEnd();
213 glPopMatrix();
214
215 glXSwapBuffers(h->Dpy, h->Win);
216 }
217
218
219
220 static void
221 Resize(const struct head *h, unsigned int width, unsigned int height)
222 {
223 if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) {
224 Error(h->DisplayName, "glXMakeCurrent failed in Resize()");
225 return;
226 }
227 glFlush();
228 glViewport(0, 0, width, height);
229 glMatrixMode(GL_PROJECTION);
230 glLoadIdentity();
231 glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
232 }
233
234
235
236 static void
237 EventLoop(void)
238 {
239 while (1) {
240 int i;
241 for (i = 0; i < NumHeads; i++) {
242 struct head *h = &Heads[i];
243 while (XPending(h->Dpy) > 0) {
244 XEvent event;
245 XNextEvent(h->Dpy, &event);
246 if (event.xany.window == h->Win) {
247 switch (event.type) {
248 case Expose:
249 Redraw(h);
250 break;
251 case ConfigureNotify:
252 Resize(h, event.xconfigure.width, event.xconfigure.height);
253 break;
254 case KeyPress:
255 return;
256 default:
257 /*no-op*/ ;
258 }
259 }
260 else {
261 printf("window mismatch\n");
262 }
263 }
264 Redraw(h);
265 }
266 usleep(1);
267 }
268 }
269
270
271
272 static void
273 PrintInfo(const struct head *h)
274 {
275 printf("Name: %s\n", h->DisplayName);
276 printf(" Display: %p\n", (void *) h->Dpy);
277 printf(" Window: 0x%x\n", (int) h->Win);
278 printf(" Context: 0x%lx\n", (long) h->Context);
279 printf(" GL_VERSION: %s\n", h->Version);
280 printf(" GL_VENDOR: %s\n", h->Vendor);
281 printf(" GL_RENDERER: %s\n", h->Renderer);
282 }
283
284
285 int
286 main(int argc, char *argv[])
287 {
288 int i;
289 if (argc == 1) {
290 struct head *h;
291 printf("glxheads: exercise multiple GLX connections (any key = exit)\n");
292 printf("Usage:\n");
293 printf(" glxheads xdisplayname ...\n");
294 printf("Example:\n");
295 printf(" glxheads :0 mars:0 venus:1\n");
296
297 h = AddHead(XDisplayName(NULL));
298 if (h)
299 PrintInfo(h);
300 }
301 else {
302 for (i = 1; i < argc; i++) {
303 const char *name = argv[i];
304 struct head *h = AddHead(name);
305 if (h) {
306 PrintInfo(h);
307 }
308 }
309 }
310
311 EventLoop();
312 return 0;
313 }