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