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)
24 #include <X11/keysym.h>
30 #define M_PI 3.14159265358979323846
33 static int MyID
= 0; /* 0 or 1 */
34 static int WindowID
= 0;
35 static GLXContext Context
= 0;
36 static int Width
= 700, Height
= 350;
40 static GLfloat Red
[4] = {1.0, 0.2, 0.2, 1.0};
41 static GLfloat Blue
[4] = {0.2, 0.2, 1.0, 1.0};
43 static int Sync
= 1; /** synchronized rendering? */
52 /* I'm the first one, wait for connection from second */
53 k
= CreatePort(&port
);
56 printf("Waiting for connection from another 'corender'\n");
57 Sock
= AcceptConnection(k
);
60 printf("Got connection, sending windowID\n");
63 SendData(Sock
, &WindowID
, sizeof(WindowID
));
66 /* I'm the second one, connect to first */
69 MyHostName(hostname
, 1000);
70 Sock
= Connect(hostname
, port
);
74 ReceiveData(Sock
, &WindowID
, sizeof(WindowID
));
75 printf("Contacted first 'corender', getting WindowID\n");
83 doughnut(GLfloat r
, GLfloat R
, GLint nsides
, GLint rings
)
86 GLfloat theta
, phi
, theta1
;
87 GLfloat cosTheta
, sinTheta
;
88 GLfloat cosTheta1
, sinTheta1
;
89 GLfloat ringDelta
, sideDelta
;
91 ringDelta
= 2.0 * M_PI
/ rings
;
92 sideDelta
= 2.0 * M_PI
/ nsides
;
97 for (i
= rings
- 1; i
>= 0; i
--) {
98 theta1
= theta
+ ringDelta
;
99 cosTheta1
= cos(theta1
);
100 sinTheta1
= sin(theta1
);
101 glBegin(GL_QUAD_STRIP
);
103 for (j
= nsides
; j
>= 0; j
--) {
104 GLfloat cosPhi
, sinPhi
, dist
;
109 dist
= R
+ r
* cosPhi
;
111 glNormal3f(cosTheta1
* cosPhi
, -sinTheta1
* cosPhi
, sinPhi
);
112 glVertex3f(cosTheta1
* dist
, -sinTheta1
* dist
, r
* sinPhi
);
113 glNormal3f(cosTheta
* cosPhi
, -sinTheta
* cosPhi
, sinPhi
);
114 glVertex3f(cosTheta
* dist
, -sinTheta
* dist
, r
* sinPhi
);
118 cosTheta
= cosTheta1
;
119 sinTheta
= sinTheta1
;
129 glXMakeCurrent(dpy
, WindowID
, Context
);
130 glEnable(GL_LIGHTING
);
132 glEnable(GL_DEPTH_TEST
);
133 glClearColor(0.5, 0.5, 0.5, 0.0);
138 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
141 glTranslatef(-1, 0, 0);
142 glRotatef(Rot
, 1, 0, 0);
143 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, Red
);
144 doughnut(0.5, 2.0, 20, 30);
152 /* signal second process to render */
155 if (dbg
) printf("0: send signal\n");
156 SendData(Sock
, &code
, sizeof(code
));
157 SendData(Sock
, &Rot
, sizeof(Rot
));
160 /* wait for second process to finish rendering */
163 if (dbg
) printf("0: wait signal\n");
164 ReceiveData(Sock
, &code
, sizeof(code
));
165 if (dbg
) printf("0: got signal\n");
173 /* wait for first process's signal for me to render */
176 if (dbg
) printf("1: wait signal\n");
177 ReceiveData(Sock
, &code
, sizeof(code
));
178 ReceiveData(Sock
, &Rot
, sizeof(Rot
));
180 if (dbg
) printf("1: got signal\n");
184 /* XXX this clear should not be here, but for some reason, it
185 * makes things _mostly_ work correctly w/ NVIDIA's driver.
186 * There's only occasional glitches.
187 * Without this glClear(), depth buffer for the second process
188 * is pretty much broken.
190 /* glClear(GL_DEPTH_BUFFER_BIT); */
193 glTranslatef(1, 0, 0);
194 glRotatef(Rot
+ 90 , 1, 0, 0);
195 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT_AND_DIFFUSE
, Blue
);
196 doughnut(0.5, 2.0, 20, 30);
200 glXSwapBuffers(dpy
, WindowID
);
203 /* signal first process that I'm done rendering */
206 if (dbg
) printf("1: send signal\n");
207 SendData(Sock
, &code
, sizeof(code
));
214 resize(Display
*dpy
, int width
, int height
)
216 float ar
= (float) width
/ height
;
218 glXMakeCurrent(dpy
, WindowID
, Context
);
220 glViewport(0, 0, width
, height
);
221 glMatrixMode(GL_PROJECTION
);
223 glFrustum(-ar
, ar
, 1.0, -1.0, 5.0, 200.0);
224 glMatrixMode(GL_MODELVIEW
);
226 glTranslatef(0, 0, -15);
235 set_window_title(Display
*dpy
, Window win
, const char *title
)
237 XSizeHints sizehints
;
239 XSetStandardProperties(dpy
, win
, title
, title
,
240 None
, (char **)NULL
, 0, &sizehints
);
245 make_gl_window(Display
*dpy
, XVisualInfo
*visinfo
, int width
, int height
)
248 XSetWindowAttributes attr
;
255 scrnum
= DefaultScreen( dpy
);
256 root
= RootWindow( dpy
, scrnum
);
258 /* window attributes */
259 attr
.background_pixel
= 0;
260 attr
.border_pixel
= 0;
261 attr
.colormap
= XCreateColormap( dpy
, root
, visinfo
->visual
, AllocNone
);
262 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
263 mask
= CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
265 win
= XCreateWindow( dpy
, root
, x
, y
, width
, height
,
266 0, visinfo
->depth
, InputOutput
,
267 visinfo
->visual
, mask
, &attr
);
269 /* set hints and properties */
271 XSizeHints sizehints
;
274 sizehints
.width
= width
;
275 sizehints
.height
= height
;
276 sizehints
.flags
= USSize
| USPosition
;
277 XSetNormalHints(dpy
, win
, &sizehints
);
278 XSetStandardProperties(dpy
, win
, name
, name
,
279 None
, (char **)NULL
, 0, &sizehints
);
287 set_event_mask(Display
*dpy
, Window win
)
289 XSetWindowAttributes attr
;
290 attr
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
291 XChangeWindowAttributes(dpy
, win
, CWEventMask
, &attr
);
296 event_loop(Display
*dpy
)
299 while (XPending(dpy
) > 0) {
301 XNextEvent(dpy
, &event
);
303 switch (event
.type
) {
307 case ConfigureNotify
:
308 resize(dpy
, event
.xconfigure
.width
, event
.xconfigure
.height
);
314 code
= XLookupKeysym(&event
.xkey
, 0);
315 if (code
== XK_Left
) {
318 r
= XLookupString(&event
.xkey
, buffer
, sizeof(buffer
),
320 if (buffer
[0] == 27) {
331 if (MyID
== 0 || !Sync
)
339 choose_visual(Display
*dpy
)
341 int attribs
[] = { GLX_RGBA
,
348 int scrnum
= DefaultScreen( dpy
);
349 return glXChooseVisual(dpy
, scrnum
, attribs
);
354 parse_opts(int argc
, char *argv
[])
363 main( int argc
, char *argv
[] )
366 XVisualInfo
*visinfo
;
368 parse_opts(argc
, argv
);
370 dpy
= XOpenDisplay(NULL
);
372 visinfo
= choose_visual(dpy
);
374 Context
= glXCreateContext( dpy
, visinfo
, NULL
, True
);
376 printf("Error: glXCreateContext failed\n");
381 WindowID
= make_gl_window(dpy
, visinfo
, Width
, Height
);
382 set_window_title(dpy
, WindowID
, "corender");
383 XMapWindow(dpy
, WindowID
);
384 /*printf("WindowID 0x%x\n", (int) WindowID);*/
387 /* do ipc hand-shake here */
393 set_event_mask(dpy
, WindowID
);
396 resize(dpy
, Width
, Height
);