1 /*
2 * Copyright (C) 1997-2005, R3vis Corporation.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 * USA, or visit http://www.gnu.org/copyleft/lgpl.html.
18 *
19 * Original Contributor:
20 * Wes Bethel, R3vis Corporation, Marin County, California
21 * Additional Contributor(s):
22 *
23 * The OpenRM project is located at http://openrm.sourceforge.net/.
24 */
25 /*
26 * $Id: rmcr.c,v 1.13 2005/08/09 14:43:43 wes Exp $
27 * Version: $Name: OpenRM-1-6-0-2-RC2 $
28 * $Revision: 1.13 $
29 * $Log: rmcr.c,v $
30 * Revision 1.13 2005/08/09 14:43:43 wes
31 * Added error checking code to confirm presence of CR-specific structure
32 * in the RMpipe before performing CR-specific operations.
33 *
34 * Revision 1.12 2005/06/06 02:04:29 wes
35 * Lots of small additions to clean up compiler warnings.
36 *
37 * Revision 1.11 2005/05/16 01:00:51 wes
38 * Minor code rearrangement to better accommodate RM_X and RM_CR compile
39 * definitions (both might be used at once).
40 *
41 * Revision 1.10 2005/02/19 16:22:50 wes
42 * Distro sync and consolidation.
43 *
44 * Revision 1.9 2005/01/23 17:00:22 wes
45 * Copyright updated to 2005.
46 *
47 * Revision 1.8 2004/01/16 17:18:34 wes
48 * Updated copyright line. Added more error testing to the Chromium-specific
49 * RMpipe initialization sequence to help diagnose Chromium configuration
50 * problems (there were a lot of questions related to CR config during
51 * early field tests).
52 *
53 * Revision 1.7 2003/08/14 13:47:22 wes
54 * Enclosed some debugging printf's inside conditional compilation directives.
55 *
56 * Revision 1.6 2003/07/27 15:37:37 wes
57 * Fixed minor problems with in-line documentation.
58 *
59 * Revision 1.5 2003/04/05 13:58:52 wes
60 * Remove dead code.
61 *
62 * Revision 1.4 2003/03/16 21:56:16 wes
63 * Documentation updates.
64 *
65 * Revision 1.3 2003/02/18 15:40:40 wes
66 * Added RMpipe wrapper functions for CR barrier creation and execution.
67 *
68 * Revision 1.2 2003/02/14 00:16:39 wes
69 * Use of new CR-specific struct in the RMpipe, rather than a static struct.
70 *
71 * Revision 1.1.1.1 2003/01/28 02:15:23 wes
72 * Manual rebuild of rm150 repository.
73 *
74 * Revision 1.7 2003/01/27 05:04:42 wes
75 * Changes to RMpipe API and initialization sequence to unify GLX, WGL and CR
76 * platforms w/o too much disruption to existing apps.
77 *
78 * Revision 1.6 2003/01/20 05:39:49 wes
79 * Rewrote texture state handling code.
80 *
81 * Revision 1.5 2003/01/16 22:21:17 wes
82 * Updated all source files to reflect new organization of header files:
83 * all header files formerly located in include/rmaux, include/rmi, include/rmv
84 * are now located in include/rm.
85 *
86 * Revision 1.4 2003/01/15 16:11:24 wes
87 * Migrate setting of parms asking for shared display lists and texture objects
88 * into the CR .conf files, rather than setting during RMpipe intialization. This
89 * policy may change in the future.
90 *
91 * Revision 1.3 2003/01/14 05:28:57 wes
92 * Added calls to CR extensions that enable shared display lists,
93 * and texture object IDs.
94 *
95 * Revision 1.2 2003/01/09 16:58:59 wes
96 * Removed c++'isms that lingered from a previous c++ version. These c++'isms
97 * work OK in C sources in gcc 3.2, but not in earlier versions.
98 *
99 * Revision 1.1 2002/12/31 00:51:51 wes
100 * Initial entry.
101 *
102 */
103
104
105 #include <rm/rm.h>
106 #include "rmprivat.h"
107
108 #ifdef RM_CR
109 #include <rm/rmcr.h>
110 #define CR_REASONABLE_MURALSIZE(a) (((a) > 1) && ((a) < 32768))
111 #endif
112
113
114 /*
115 * ----------------------------------------------------
116 * @Name rmPipeBarrierCreateCR
117 @pstart
118 RMenum rmPipeBarrierCreateCR (RMpipe *toModify, int barrierNumber)
119 @pend
120
121 @astart
122 RMpipe *toModify - a handle to an RMpipe to be modified.
123 int barrierNumber - an integer value specifying a barrier number.
124 @aend
125
126 @dstart
127
128 (For use with Chromium only)
129 Use this routine to create a named barrier. The barrier is executed by
130 calling rmPipeBarrierExecCR(). Chromium barriers are intended to be used to
131 synchronize execution of OpenGL streams on crservers.
132
133 Chromium barriers, when created, require an integer value indicating the
134 number of streams that will be participating in the barrier. This integer
135 value is provided automatically by this routine. Use the routine
136 rmPipeSetCommSize(), prior to calling rmPipeCreateBarrierCR(), to set
137 the number of crservers that will be participating in execution of the
138 barrier.
139
140 Chromium barriers, when executed, synchronize execution of OpenGL code
141 in the crservers. They do not block the application code.
142
143 This routine returns RM_CHILL upon success. This routine will return
144 RM_WHACKED if the input RMpipe is NULL, or if the size of the communication
145 collective is zero (use rmPipeSetCommSize to set the size of the collective).
146 This routine does not check for creation of duplicate barriers.
147
148 @dend
149 * ----------------------------------------------------
150 */
151 RMenum
rmPipeBarrierCreateCR(RMpipe * toModify,int barrierNumber)152 rmPipeBarrierCreateCR (RMpipe *toModify,
153 int barrierNumber)
154 {
155 if (RM_ASSERT(toModify, "rmPipeBarrierCreateCR() error: the input RMpipe is NULL") == RM_WHACKED)
156 return(RM_WHACKED);
157
158 if (toModify->globalNPE == 0)
159 {
160 rmError("rmPipeBarrierCreateCR() error - the size of the communination collective is zero. Use rmPipeSetCommSize() to set a non-zero collective size prior to calling rmPipeBarrierCreateCR.");
161 return RM_WHACKED;
162 }
163
164 #ifdef RM_CR
165 if (toModify->crStuff != NULL)
166 toModify->crStuff->glBarrierCreateCR(barrierNumber, toModify->globalNPE);
167 else
168 rmError("rmPipeBarrierCreateCR error: the input RMpipe does not appear to be configured for use with Chromium. Please create the RMpipe using the parameter RM_PIPE_CR to rmPipeNew()");
169 #else
170 {
171 barrierNumber++; /* foil compiler warning */
172 rmWarning("rmPipeBarrierCreateCR() is effectively disabled. Build OpenRM/RM using the -DRM_CR compile flag to fully enable Chromium constructs.");
173 }
174 #endif
175 return RM_CHILL;
176 }
177
178 /*
179 * ----------------------------------------------------
180 * @Name rmPipeBarrierExecCR
181 @pstart
182 RMenum rmPipeBarrierExecCR (RMpipe *toUse, int barrierNumber)
183 @pend
184
185 @astart
186 RMpipe *toUse - a handle to an RMpipe to be used.
187 int barrierNumber - an integer value specifying a barrier number.
188 @aend
189
190 @dstart
191
192 (For use with Chromium only)
193 Use this routine to issue a "barrier execute" command to Chromium.
194 Chromium barriers are intended to be used to synchronize execution of
195 OpenGL streams on crservers.
196
197 Chromium barriers, when created, require an integer value indicating the
198 number of streams that will be participating in the barrier. This integer
199 value is provided automatically by this routine. Use the routine
200 rmPipeSetCommSize(), prior to calling rmPipeBarrierCreateCR(), to set
201 the number of crservers that will be participating in execution of the
202 barrier.
203
204 Chromium barriers, when executed, synchronize execution of OpenGL code
205 in the crservers. They do not block the application code.
206
207 This routine returns RM_CHILL upon success, or RM_WHACKED if the input
208 RMpipe is NULL. This routine does not check for creation of duplicate
209 barriers.
210
211 @dend
212 * ----------------------------------------------------
213 */
214 RMenum
rmPipeBarrierExecCR(RMpipe * toUse,int barrierNumber)215 rmPipeBarrierExecCR (RMpipe *toUse,
216 int barrierNumber)
217 {
218 if (RM_ASSERT(toUse, "rmPipeBarrierExecCR() error: the input RMpipe is NULL") == RM_WHACKED)
219 return(RM_WHACKED);
220
221 #ifdef RM_CR
222 if (toUse->crStuff != NULL)
223 toUse->crStuff->glBarrierExecCR(barrierNumber);
224 else
225 rmError("rmPipeBarrierExecCR error: the input RMpipe does not appear to be configured for use with Chromium. Please create the RMpipe using the parameter RM_PIPE_CR to rmPipeNew()");
226
227 #else
228 barrierNumber++; /* foil compiler warning */
229 rmWarning("rmPipeBarrierExecCR() is effectively disabled. Build OpenRM/RM using the -DRM_CR compile flag to fully enable Chromium constructs.");
230 #endif
231 return RM_CHILL;
232 }
233
234
235 RMenum
rmPipeSwapBuffersCR(const RMpipe * p)236 rmPipeSwapBuffersCR(const RMpipe *p)
237 {
238 #ifdef RM_CR
239 int ival = (p->myRank == 0); /* only PE 0 does "real" swapbuffers */
240
241 #if (DEBUG_LEVEL & DEBUG_TRACE)
242 fprintf(stderr," PE %d entering rmPipeSwapBuffersCR \n", p->myRank);
243 fflush(stderr);
244 #endif
245
246 if (p->crStuff != NULL)
247 p->crStuff->glBarrierExecCR( RM_CR_PRE_SWAPBUFFERS_BARRIER );
248 else
249 {
250 rmError("rmPipeSwapBuffersCR error: the input RMpipe does not appear to be configured for use with Chromium. Please create the RMpipe using the parameter RM_PIPE_CR to rmPipeNew()");
251 return RM_WHACKED;
252 }
253
254 if (ival == 1)
255 p->crStuff->glSwapBuffersCR( 0, 0);
256 else
257 p->crStuff->glSwapBuffersCR( 0, CR_SUPPRESS_SWAP_BIT);
258
259 p->crStuff->glBarrierExecCR( RM_CR_POST_SWAPBUFFERS_BARRIER );
260 #else
261 p = NULL; /* foil compiler warnings */
262 rmWarning("rmPipeSwapBuffersCR() is effectively disabled. Build OpenRM/RM using the -DRM_CR compile flag to fully enable Chromium constructs.");
263 #endif
264
265 #if (DEBUG_LEVEL & DEBUG_TRACE)
266 fprintf(stderr," PE %d leaving rmPipeSwapBuffersCR \n", p->myRank);
267 fflush(stderr);
268 #endif
269
270 return RM_CHILL;
271 }
272
273 RMenum
rmPipeCreateContextCR(RMpipe * pipe)274 rmPipeCreateContextCR(RMpipe *pipe)
275 {
276 #ifdef RM_CR
277 int ivisual = CR_RGB_BIT | CR_DEPTH_BIT | CR_DOUBLE_BIT ;
278 int ictx;
279
280 if (pipe->crStuff != NULL)
281 ictx = pipe->crStuff->glCreateContextCR(getenv("DISPLAY"), ivisual);
282 else
283 {
284 rmError("rmPipeCreateContextCR error: the input RMpipe does not appear to be configured for use with Chromium. Please create the RMpipe using the parameter RM_PIPE_CR to rmPipeNew()");
285 return RM_WHACKED;
286 }
287
288 if (ictx < 0)
289 {
290 rmError("rmPipeInitCR(), glCreateContextCR() call failed!\n");
291 return RM_WHACKED;
292 }
293 pipe->contextCR = ictx;
294 #else
295 pipe = NULL; /* foil compiler warning */
296 rmWarning("rmPipeCreateContextCR() is effectively disabled. Build OpenRM/RM using the -DRM_CR compile flag to fully enable Chromium constructs.");
297 #endif
298 return RM_CHILL;
299 }
300
301 RMenum
rmPipeMakeCurrentCR(RMpipe * pipe)302 rmPipeMakeCurrentCR(RMpipe *pipe)
303 {
304 RMenum stat = RM_TRUE;
305
306 /* 5/1/05 - we note there really is no error checking in this routine */
307 #ifdef RM_CR
308 int muralSize[2];
309 char buf[1024];
310
311 #if (DEBUG_LEVEL & DEBUG_TRACE)
312 fprintf(stderr, "rmPipeMakeCurrentCR() - need to add code to honor stereo vs. not before context creation. get rid of viewport setting? \n");
313 fflush(stderr);
314 #endif
315
316 sprintf(buf,"CR_APPLICATION_ID_NUMBER=%d",pipe->myRank);
317 putenv(buf);
318
319 if (pipe->crStuff != NULL)
320 pipe->crStuff->glMakeCurrentCR(0, pipe->contextCR);
321 else
322 {
323 rmError("rmPipeMakeCurrentCR error: the input RMpipe does not appear to be configured for use with Chromium. Please create the RMpipe using the parameter RM_PIPE_CR to rmPipeNew()");
324 return RM_WHACKED;
325 }
326
327 pipe->crStuff->glGetChromiumParametervCR(GL_MURAL_SIZE_CR, 0, GL_INT, 2, muralSize );
328
329 /* deal with the case when there's no mothership */
330 /*
331 * before Cr 1.8, if there was no mothership, the default muralsize was
332 * set to zero, which we could detect and set to 256x256 since that is the
333 * default "fake render window" size used by Cr. In Cr 1.8, the behavior
334 * appears to have been changed so that the default mural size is 1x1
335 * when there is no mothership. Ugh!
336 */
337 if ((muralSize[0] == 0 || muralSize[0] == 1) &&
338 (muralSize[1] == 0 || muralSize[1] == 1))
339 muralSize[0] = muralSize[1] = 256;
340
341 fprintf(stderr,"rmPipeInitCR(): PE %d thinks the mural size is %d,%d \n", pipe->myRank, muralSize[0], muralSize[1]);
342 fflush(stderr);
343
344 if (CR_REASONABLE_MURALSIZE(muralSize[0]) && CR_REASONABLE_MURALSIZE(muralSize[1]))
345 rmPipeSetWindowSize(pipe, muralSize[0], muralSize[1]);
346 else
347 {
348 char buf[512];
349 sprintf(buf,"rmPipeInitCR(): PE %d: since the mural size is not reasonable, I'm setting the mural size to (256,256) because those are the values used by CR for a render spu with no mothership. \n", pipe->myRank);
350 rmWarning(buf);
351
352 rmPipeSetWindowSize(pipe, 256, 256);
353 }
354
355 {
356 float vp[4] = {0., 0., 1., 1.};
357
358 rmNodeSetSceneViewport(rmRootNode(), vp);
359 }
360
361
362 /* Chromium-specific stuff:
363 1. create a barrier that will be called by all PEs prior to swapbuff.
364 2. create a barrier to sync up fbclears */
365
366 pipe->myRank = pipe->myRank;
367 pipe->globalNPE = pipe->globalNPE;
368
369 pipe->crStuff->glBarrierCreateCR(RM_CR_PRE_SWAPBUFFERS_BARRIER, pipe->globalNPE);
370 pipe->crStuff->glBarrierCreateCR(RM_CR_POST_SWAPBUFFERS_BARRIER, pipe->globalNPE);
371 pipe->crStuff->glBarrierCreateCR(RM_CR_POST_FBCLEAR_BARRIER, pipe->globalNPE);
372 pipe->postFBClearBarrierFunc = private_rmPipePostFBClearBarrierCR;
373
374 #else
375 pipe = NULL; /* foil compiler warning */
376 rmWarning("rmPipeMakeCurrentCR() is effectively disabled. Build OpenRM/RM using the -DRM_CR compile flag to fully enable Chromium constructs.");
377 #endif
378
379
380 return(stat);
381 }
382
383 /* private */
384 void
private_rmPipePostFBClearBarrierCR(const RMpipe * p)385 private_rmPipePostFBClearBarrierCR(const RMpipe *p)
386 {
387 #ifdef RM_CR
388 if (p->crStuff != NULL)
389 p->crStuff->glBarrierExecCR(RM_CR_POST_FBCLEAR_BARRIER);
390 else
391 rmError("private_rmPipePostFBClearBarrierCR error: the input RMpipe does not appear to be configured for use with Chromium. Please create the RMpipe using the parameter RM_PIPE_CR to rmPipeNew()");
392
393 #else
394 p = NULL; /* foil compiler warnings */
395 rmWarning("private_rmPipePostFBClearBarrierCR() is effectively disabled. Build OpenRM/RM using the -DRM_CR compile flag to fully enable Chromium constructs.");
396 #endif
397 }
398
399 /* private */
400 void
private_rmPipeInitCR(RMpipe * p)401 private_rmPipeInitCR(RMpipe *p)
402 {
403 #ifdef RM_CR
404 RMpipeCRvariables *lCR=NULL;
405
406 lCR = (RMpipeCRvariables *)malloc(sizeof(RMpipeCRvariables));
407 p->crStuff = (void *)lCR;
408
409 rmPipeSetSwapBuffersFunc(p, rmPipeSwapBuffersCR);
410
411
412 lCR->glCreateContextCR = (crCreateContextProc)crGetProcAddress("crCreateContext");
413 lCR->glMakeCurrentCR = (crMakeCurrentProc)crGetProcAddress("crMakeCurrent");
414 lCR->glSwapBuffersCR = (crSwapBuffersProc)crGetProcAddress("crSwapBuffers");
415
416 lCR->glChromiumParametervCR = (glChromiumParametervCRProc)GET_PROC("glChromiumParametervCR");
417
418 lCR->glGetChromiumParametervCR = (glGetChromiumParametervCRProc) GET_PROC("glGetChromiumParametervCR");
419
420 lCR->glBarrierCreateCR = (glBarrierCreateCRProc)GET_PROC("glBarrierCreateCR");
421 lCR->glBarrierExecCR = (glBarrierExecCRProc)GET_PROC("glBarrierExecCR");
422
423 lCR->glChromiumParametervCR = (glChromiumParametervCRProc) GET_PROC("glChromiumParametervCR");
424 lCR->glChromiumParameteriCR = (glChromiumParameteriCRProc) GET_PROC("glChromiumParameteriCR");
425
426 /*
427 * check to see if all the GET_PROC's succeeded. We cannot continue if
428 * any of them failed.
429 */
430
431 if ((lCR->glCreateContextCR == NULL) ||
432 (lCR->glMakeCurrentCR == NULL) ||
433 (lCR->glSwapBuffersCR == NULL) ||
434 (lCR->glChromiumParametervCR == NULL) ||
435 (lCR->glGetChromiumParametervCR == NULL) ||
436 (lCR->glBarrierCreateCR == NULL) ||
437 (lCR->glBarrierExecCR == NULL) ||
438 (lCR->glChromiumParametervCR == NULL) ||
439 (lCR->glChromiumParameteriCR == NULL))
440 {
441 rmError("\n\n \
442 \tDuring intialization of a Chromium-enabled RMpipe, we encountered \n\
443 \tfatal error - some of the Chromium-specific routines loaded with \n\
444 \t'GET_PROC' could not be found. This condition most often happens \n\
445 \twhen you forget to have the symlinks in /usr/local/cr/lib/Linux \n\
446 \tthat point from libGL.so and libGL.so.1 to libcrfaker.so. The \n\
447 \tapplication fatally cripped, and will segfault in a short time. \n\n");
448 }
449
450 #else
451 p = NULL; /* foil compiler warning */
452 rmWarning("private_rmPipeInitCR() is effectively disabled. Build OpenRM/RM using the -DRM_CR compile flag to fully enable Chromium constructs.");
453 #endif
454 }
455
456 /* private */
457 void
private_rmPipeCloseContextCR(RMpipe * p)458 private_rmPipeCloseContextCR (RMpipe *p)
459 {
460 p = NULL; /* foil compiler warning */
461 rmWarning("rmcr.c:private_rmPipeCloseContextCR() - need to write CR-specific context-closing routines. ");
462 }
463
464 /* EOF */
465