2
* Example of cooperative rendering into one window by two processes.
3
* The first instance of the program creates the GLX window.
4
* The second instance of the program gets the window ID from the first
6
* Socket IPC is used for synchronization.
10
* 2. run 'corender 2' (any arg will do)
23
#include <X11/keysym.h>
29
#define M_PI 3.14159265358979323846
32
static int MyID = 0; /* 0 or 1 */
33
static int WindowID = 0;
34
static GLXContext Context = 0;
35
static int Width = 700, Height = 350;
39
static GLfloat Red[4] = {1.0, 0.2, 0.2, 1.0};
40
static GLfloat Blue[4] = {0.2, 0.2, 1.0, 1.0};
42
static int Sync = 1; /** synchronized rendering? */
51
/* I'm the first one, wait for connection from second */
52
k = CreatePort(&port);
55
printf("Waiting for connection from another 'corender'\n");
56
Sock = AcceptConnection(k);
59
printf("Got connection, sending windowID\n");
62
SendData(Sock, &WindowID, sizeof(WindowID));
65
/* I'm the second one, connect to first */
68
MyHostName(hostname, 1000);
69
Sock = Connect(hostname, port);
73
ReceiveData(Sock, &WindowID, sizeof(WindowID));
74
printf("Contacted first 'corender', getting WindowID\n");
82
doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
85
GLfloat theta, phi, theta1;
86
GLfloat cosTheta, sinTheta;
87
GLfloat cosTheta1, sinTheta1;
88
GLfloat ringDelta, sideDelta;
90
ringDelta = 2.0 * M_PI / rings;
91
sideDelta = 2.0 * M_PI / nsides;
96
for (i = rings - 1; i >= 0; i--) {
97
theta1 = theta + ringDelta;
98
cosTheta1 = cos(theta1);
99
sinTheta1 = sin(theta1);
100
glBegin(GL_QUAD_STRIP);
102
for (j = nsides; j >= 0; j--) {
103
GLfloat cosPhi, sinPhi, dist;
108
dist = R + r * cosPhi;
110
glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
111
glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
112
glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
113
glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
117
cosTheta = cosTheta1;
118
sinTheta = sinTheta1;
128
glXMakeCurrent(dpy, WindowID, Context);
129
glEnable(GL_LIGHTING);
131
glEnable(GL_DEPTH_TEST);
132
glClearColor(0.5, 0.5, 0.5, 0.0);
137
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
140
glTranslatef(-1, 0, 0);
141
glRotatef(Rot, 1, 0, 0);
142
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red);
143
doughnut(0.5, 2.0, 20, 30);
151
/* signal second process to render */
154
if (dbg) printf("0: send signal\n");
155
SendData(Sock, &code, sizeof(code));
156
SendData(Sock, &Rot, sizeof(Rot));
159
/* wait for second process to finish rendering */
162
if (dbg) printf("0: wait signal\n");
163
ReceiveData(Sock, &code, sizeof(code));
164
if (dbg) printf("0: got signal\n");
172
/* wait for first process's signal for me to render */
175
if (dbg) printf("1: wait signal\n");
176
ReceiveData(Sock, &code, sizeof(code));
177
ReceiveData(Sock, &Rot, sizeof(Rot));
179
if (dbg) printf("1: got signal\n");
183
/* XXX this clear should not be here, but for some reason, it
184
* makes things _mostly_ work correctly w/ NVIDIA's driver.
185
* There's only occasional glitches.
186
* Without this glClear(), depth buffer for the second process
187
* is pretty much broken.
189
/* glClear(GL_DEPTH_BUFFER_BIT); */
192
glTranslatef(1, 0, 0);
193
glRotatef(Rot + 90 , 1, 0, 0);
194
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue);
195
doughnut(0.5, 2.0, 20, 30);
199
glXSwapBuffers(dpy, WindowID);
202
/* signal first process that I'm done rendering */
205
if (dbg) printf("1: send signal\n");
206
SendData(Sock, &code, sizeof(code));
213
resize(Display *dpy, int width, int height)
215
float ar = (float) width / height;
217
glXMakeCurrent(dpy, WindowID, Context);
219
glViewport(0, 0, width, height);
220
glMatrixMode(GL_PROJECTION);
222
glFrustum(-ar, ar, 1.0, -1.0, 5.0, 200.0);
223
glMatrixMode(GL_MODELVIEW);
225
glTranslatef(0, 0, -15);
234
set_window_title(Display *dpy, Window win, const char *title)
236
XSizeHints sizehints;
238
XSetStandardProperties(dpy, win, title, title,
239
None, (char **)NULL, 0, &sizehints);
244
make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height)
247
XSetWindowAttributes attr;
254
scrnum = DefaultScreen( dpy );
255
root = RootWindow( dpy, scrnum );
257
/* window attributes */
258
attr.background_pixel = 0;
259
attr.border_pixel = 0;
260
attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
261
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
262
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
264
win = XCreateWindow( dpy, root, x, y, width, height,
265
0, visinfo->depth, InputOutput,
266
visinfo->visual, mask, &attr );
268
/* set hints and properties */
270
XSizeHints sizehints;
273
sizehints.width = width;
274
sizehints.height = height;
275
sizehints.flags = USSize | USPosition;
276
XSetNormalHints(dpy, win, &sizehints);
277
XSetStandardProperties(dpy, win, name, name,
278
None, (char **)NULL, 0, &sizehints);
286
set_event_mask(Display *dpy, Window win)
288
XSetWindowAttributes attr;
289
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
290
XChangeWindowAttributes(dpy, win, CWEventMask, &attr);
295
event_loop(Display *dpy)
298
while (XPending(dpy) > 0) {
300
XNextEvent(dpy, &event);
302
switch (event.type) {
306
case ConfigureNotify:
307
resize(dpy, event.xconfigure.width, event.xconfigure.height);
313
code = XLookupKeysym(&event.xkey, 0);
314
if (code == XK_Left) {
317
r = XLookupString(&event.xkey, buffer, sizeof(buffer),
319
if (buffer[0] == 27) {
330
if (MyID == 0 || !Sync)
338
choose_visual(Display *dpy)
340
int attribs[] = { GLX_RGBA,
347
int scrnum = DefaultScreen( dpy );
348
return glXChooseVisual(dpy, scrnum, attribs);
353
parse_opts(int argc, char *argv[])
362
main( int argc, char *argv[] )
365
XVisualInfo *visinfo;
367
parse_opts(argc, argv);
369
dpy = XOpenDisplay(NULL);
371
visinfo = choose_visual(dpy);
373
Context = glXCreateContext( dpy, visinfo, NULL, True );
375
printf("Error: glXCreateContext failed\n");
380
WindowID = make_gl_window(dpy, visinfo, Width, Height);
381
set_window_title(dpy, WindowID, "corender");
382
XMapWindow(dpy, WindowID);
383
/*printf("WindowID 0x%x\n", (int) WindowID);*/
386
/* do ipc hand-shake here */
392
set_event_mask(dpy, WindowID);
395
resize(dpy, Width, Height);