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
);
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
);