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: rmmtdraw.c,v 1.11 2005/09/12 04:03:51 wes Exp $
27  * Version: $Name: OpenRM-1-6-0-2-RC2 $
28  * $Revision: 1.11 $
29  * $Log: rmmtdraw.c,v $
30  * Revision 1.11  2005/09/12 04:03:51  wes
31  * Minor documentation updates.
32  *
33  * Revision 1.10  2005/06/26 18:53:48  wes
34  * Consolidated opcode to capture both local state push/pop and OpenGL
35  * attrib stack push/pop. This move helps streamline state tracking and
36  * makes it possible to better track OpenGL state.
37  *
38  * Revision 1.9  2005/06/06 02:04:29  wes
39  * Lots of small additions to clean up compiler warnings.
40  *
41  * Revision 1.8  2005/03/16 16:40:00  wes
42  * Added more detailed information to be printed when DEBUG_LEVEL is
43  * set to DEBUG_TRACE. Fixed a text attributes state manipulation bug
44  * that was causing a stack underflow in OpenGL.
45  *
46  * Revision 1.7  2005/02/24 16:17:25  wes
47  * Added support for fbClears to be set at the RMpipe level. Apps can
48  * still set them at the RMnode level if desired for fine-grained control.
49  *
50  * Revision 1.6  2005/02/19 16:28:54  wes
51  * Distro sync and consolidation.
52  * Fixes for a number of state tracking buglets.
53  *
54  * Revision 1.5  2005/01/23 17:08:25  wes
55  * Copyright updated to 2005.
56  * Updates to support access and use of extensions; multitexturing on all
57  * platforms, use of 3d texture extension to realize implementation of
58  * volume rendering and related functions on Windows platforms.
59  *
60  * Revision 1.4  2004/09/28 00:48:57  wes
61  * Added render state cache as a parameter to routines that may modify
62  * lighting state to fix a lighting state tracking problem.
63  *
64  * Revision 1.3  2004/01/16 16:46:09  wes
65  * Updated copyright line for 2004.
66  *
67  * Revision 1.2  2003/02/02 02:07:15  wes
68  * Updated copyright to 2003.
69  *
70  * Revision 1.1.1.1  2003/01/28 02:15:23  wes
71  * Manual rebuild of rm150 repository.
72  *
73  * Revision 1.13  2003/01/20 05:39:49  wes
74  * Rewrote texture state handling code.
75  *
76  * Revision 1.12  2003/01/16 22:21:17  wes
77  * Updated all source files to reflect new organization of header files:
78  * all header files formerly located in include/rmaux, include/rmi, include/rmv
79  * are now located in include/rm.
80  *
81  * Revision 1.11  2002/12/31 00:54:31  wes
82  * Added check for post-rendering, pre-swapbuffers barrier function.
83  * Added as part of Chromium work.
84  *
85  * Revision 1.10  2002/11/14 15:34:51  wes
86  * Minor editing for beautification.
87  *
88  * Revision 1.9  2002/09/23 15:21:58  wes
89  * Fixed a small memory leak inside the render traversal code.
90  *
91  * Revision 1.8  2002/09/17 14:13:49  wes
92  * Removed code that tries to obtain an RMnode handle when a POP opcode
93  * is encountered. The view traversal pushes a -1 index, which was making
94  * the new component manager paging code ill. We don't need the node
95  * handle anyway for pop operations.
96  *
97  * Revision 1.7  2002/08/29 22:20:32  wes
98  *
99  * Massive upgrade to accommodate dynamic object reallocation within
100  * the component manager, and within the context cache. Use the
101  * debug #define DEBUG_LEVEL DEBUG_REALLOC_TRACE to get a printf
102  * whenever a realloc occurs. With this upgrade, there are no
103  * OpenRM limits on the size of the scene graph. There will be external
104  * limits, such as the amount of RAM and the amount of space available
105  * to your OpenGL implementation.
106  *
107  * Revision 1.6  2002/08/17 15:11:14  wes
108  * Added machinery to invoke user-defined pre- and post-traversal callbacks
109  * in the render stage. At this time, the return value from the
110  * pre-traversal callback is ignored. Effective early termination of
111  * SG traversal with a pre-traversal callback should be done in the
112  * view traversal.
113  *
114  * Revision 1.5  2002/06/30 21:41:31  wes
115  * Added code that reinitializes the render state cache during multipass
116  * stereo rendering. There was a lingering bug in which drawing that occurs
117  * during the right channel was wrong because of a cache sync problem.
118  *
119  * Revision 1.4  2002/06/02 15:15:34  wes
120  * Added RMstateCache code to help eliminate the number of state changes
121  * made during the render traversal. The RMstateCache tracks
122  * the actual OpenGL rendering state w/o the need for querying OpenGL
123  * directly, and  is queried by draw code that then decides if any
124  * real state changes are required given the configuration of data
125  * within an RMprimitive.
126  *
127  * Revision 1.3  2002/04/30 19:32:22  wes
128  * Updated copyright dates.
129  *
130  * Revision 1.2  2001/06/03 20:47:03  wes
131  * Removed unused vars to remove compile warnings.
132  *
133  * Revision 1.1  2001/03/31 17:12:39  wes
134  * v1.4.0-alpha-2 checkin.
135  *
136  */
137 
138 #include <rm/rm.h>
139 #include "rmmultis.h"
140 #include "rmprivat.h"
141 
142 /*
143  * table of functions used to process opcodes. need to have one
144  * function per opcode
145  */
146 
147 void private_mtNoOp MTWORKPARMS();
148 
149 void private_mtPushAttrib MTWORKPARMS();
150 void private_mtPopAttrib MTWORKPARMS();
151 
152 void private_mtPushModelViewMatrix MTWORKPARMS();
153 void private_mtPopModelViewMatrix MTWORKPARMS();
154 
155 void private_mtPushProjMatrix MTWORKPARMS();
156 void private_mtPopProjMatrix MTWORKPARMS();
157 
158 void private_mtPushTextureMatrix MTWORKPARMS();
159 void private_mtPopTextureMatrix MTWORKPARMS();
160 
161 void private_mtDraw MTWORKPARMS();
162 
163 void private_mtFBclear MTWORKPARMS();
164 
165 void private_mtPushTextProps MTWORKPARMS();
166 void private_mtPopTextProps MTWORKPARMS();
167 
168 void private_mtPushState MTWORKPARMS();
169 void private_mtPopState MTWORKPARMS();
170 
171 void private_mtPreTraverseCallback MTWORKPARMS();
172 void private_mtPostTraverseCallback MTWORKPARMS();
173 
174 void private_mtPushAttribAndState MTWORKPARMS();
175 void private_mtPopAttribAndState MTWORKPARMS();
176 
177 void (*mtRenderFuncs[]) MTWORKPARMS() =
178 {
179     private_mtNoOp,
180     private_mtPushAttrib,
181     private_mtPopAttrib,
182     private_mtPushModelViewMatrix, /* could be no-op */
183     private_mtPopModelViewMatrix, /* could be no-op */
184     private_mtPushProjMatrix,	/* could be no-op */
185     private_mtPopProjMatrix,	/* could be no-op */
186     private_mtPushTextureMatrix, /* could be no-op */
187     private_mtPopTextureMatrix, /* could be no-op */
188     private_mtDraw,
189     private_mtFBclear,
190     private_mtPushTextProps,
191     private_mtPopTextProps,
192     private_mtPushState,
193     private_mtPopState,
194     private_mtPreTraverseCallback,
195     private_mtPostTraverseCallback,
196     private_mtPushAttribAndState,
197     private_mtPopAttribAndState
198 };
199 
200 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
201 void
myGlPushMatrix(GLenum matrixStack)202 myGlPushMatrix(GLenum matrixStack)
203 {
204     int depth;
205     if (matrixStack == GL_MODELVIEW)
206     {
207 	glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
208 	fprintf(stderr," prior to ModelView push, depth=%d \n",depth);
209     }
210     else if (matrixStack == GL_PROJECTION)
211     {
212 	glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &depth);
213 	fprintf(stderr," prior to Projection push, depth=%d \n",depth);
214     }
215     glPushMatrix();
216 }
217 #else
218 #define myGlPushMatrix(a) glPushMatrix()
219 #endif
220 
221 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
222 void
myGlPopMatrix(GLenum matrixStack)223 myGlPopMatrix(GLenum matrixStack)
224 {
225     int depth;
226     if (matrixStack == GL_MODELVIEW)
227     {
228 	glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
229 	fprintf(stderr," prior to ModelView pop, depth=%d \n",depth);
230     }
231     else if (matrixStack == GL_PROJECTION)
232     {
233 	glGetIntegerv(GL_PROJECTION_STACK_DEPTH, &depth);
234 	fprintf(stderr," prior to Projection pop, depth=%d \n",depth);
235     }
236     glPopMatrix();
237 }
238 #else
239 #define myGlPopMatrix(a) glPopMatrix()
240 #endif
241 
242 int
mtUpdateSceneParms(const RMnode * r,RMstate * rState,RMpipe * renderPipe,RMstateCache * rsc)243 mtUpdateSceneParms (const RMnode *r,
244 		    RMstate *rState,
245 		    RMpipe *renderPipe,
246 		    RMstateCache *rsc)
247 {
248     /*
249      * this routine updates the scene parameters in rState to
250      * reflect the changes requested by the input RMnode "r".
251      *
252      * cameras and viewports are processed prior to this routine.
253      *
254      * the rState parm is always updated, although not all scene
255      * parameters cause a change to rState.
256      *
257      * when "applyGL" is set to RM_TRUE, the appropriate OpenGL
258      * calls are made that have the scene parameters take effect.
259      *
260      * this routine returns a 1 if any changes were made to rState,
261      * otherwise a 0 is returned. (June 3, 2001 - the return status
262      * is not used by any consumers at this time - to avoid compile
263      * warnings, we'll always return a 0 for now).
264      *
265      * the routines preCamFunc and perObjFunc are hooks used when
266      * rendermode is GL_SELECT to drop bread crumbs so that cameras
267      * generate feedback tokens, otherwise they are not used.
268      */
269 
270     /*
271      * do background fill operations after the viewport is set.
272      * note that we can't do BOTH background color AND a background image.
273      *
274      * don't draw tiles when we're in select mode.  although the spec
275      * seems to indicate that no select events are generated for
276      * drawpixels calls, i've had problems in mesa with them being
277      * generated. (don't draw tiles in feedback mode. this is handled
278      * as a modeling step when the PS file is created)
279      */
280     GLenum renderMode;
281 
282     renderMode = rState->rendermode;
283 
284 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
285     {
286 	char buf[64];
287 	sprintf(buf, " mtUpdateSceneParms - before update ");
288 	rmGLGetError(buf);
289     }
290 #endif
291     if (r->scene_parms && r->scene_parms->textProps != NULL)
292     {
293 	/*
294 	 * text props don't do anything to OpenGL.
295 	 * can we copy the pointer from the RMnode over rather
296 	 * than creating a new one?
297 	 * let's try doing that: 7/8/99
298 	 */
299 	rState->textProps = r->scene_parms->textProps;
300 
301 #if 0
302 	/*
303 	 * a change of text props is otherwise significant (but not to
304 	 * OpenGL). if we've not already done a state push, we'll
305 	 * push something small on the stack.
306 	 *
307 	 * the issue is that a change in RMstate is bound to a change
308 	 * in OpenGL attribute stack depth
309 	 */
310 	if (push_attrib_enable != 1)
311 	{
312 	    if (applyGL == RM_TRUE)
313 		private_rmGLPushAttrib(r, GL_ACCUM_BUFFER_BIT); /* something small */
314 
315 	    push_attrib_enable = 1;
316 	}
317 #endif
318     }
319 
320     /* viewport in state needed for pick matrix */
321     if (r->scene_parms && r->scene_parms->viewport)	/* do viewport */
322 	private_setViewport(r, rState, RM_FALSE, RM_TRUE);
323 
324 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
325     {
326 	char buf[64];
327 	sprintf(buf, " mtUpdateSceneParms - after viewport ");
328 	rmGLGetError(buf);
329     }
330 #endif
331 
332     /* do the lights */
333     process_scene_lights(r, 1, rState, RM_TRUE, rsc);
334 
335 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
336     {
337 	char buf[64];
338 	sprintf(buf, " mtUpdateSceneParms - after light ");
339 	rmGLGetError(buf);
340     }
341 #endif
342     /* do clipping planes if present */
343     private_setClipPlanes(r, 1, rState, RM_TRUE);
344 
345     /* do fog if present */
346     private_setFog(r, 1, rState, RM_TRUE);
347 
348     /* do texture if present */
349     if ((r->scene_parms != NULL) && (r->scene_parms->haveAnyTextures == RM_TRUE))
350     {
351 	/*	RMtexture *t = r->scene_parms->texture; */
352 	int i;
353 
354 	for (i=0; i <= RM_MAX_MULTITEXTURES; i++)
355 	    if (r->scene_parms->textures[i] != NULL)
356 		private_manageTextureState(r->scene_parms->textures[i],rState,renderPipe, 1, i);
357     }
358 
359 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
360     {
361 	char buf[64];
362 	sprintf(buf, " mtUpdateSceneParms - after texture update ");
363 	rmGLGetError(buf);
364     }
365 #endif
366 
367     return 0;
368 }
369 
370 void
mtUpdateSurfaceProps(const RMnode * r,RMstate * rState)371 mtUpdateSurfaceProps(const RMnode *r,
372 		     RMstate *rState)
373 {
374     /* assume r->sprops is != NULL */
375     /* update surface properties if present */
376     private_setSurfaceProps(r, 1, rState, RM_TRUE);
377 
378     /* 8/8/04 - move from mtUpdateRenderProps to here because the
379        unlit_color attrib is set in private_setSurfaceProps. */
380     glColor4fv((GLfloat *)&(rState->unlit_color));
381 }
382 
383 void
mtUpdateRenderProps(const RMnode * r,RMstate * rState,RMstateCache * rsc)384 mtUpdateRenderProps(const RMnode *r,
385 		    RMstate *rState,
386 		    RMstateCache *rsc)
387 {
388     /* assume r->rprops != NULL */
389     /* update rendering properties if present */
390 
391     /* 6/2/05 - why are we not passing rsc to private_setRenderProps? */
392     /*    private_setRenderProps(r, 1, rState, RM_TRUE, NULL); */
393 
394     private_setRenderProps(r, 1, rState, RM_TRUE, rsc);
395 }
396 
397 
398 void
MTWORKPARMS()399 private_mtNoOp MTWORKPARMS()
400 {
401     /* foil compiler warnings */
402     p = NULL;
403     n = NULL;
404     s = NULL;
405     rsc = NULL;
406     indx = 0;
407 }
408 
409 void
MTWORKPARMS()410 private_mtPushAttribAndState MTWORKPARMS()
411 {
412     GLuint mask = private_rmNodeGetAttribMask(n);
413 
414     if (mask != 0)
415 	private_rmGLPushAttrib(p, n, mask);
416 
417     if (n->scene_parms != NULL)
418 	mtUpdateSceneParms(n, s, p, rsc);
419 
420     if (n->rprops != NULL)
421 	mtUpdateRenderProps(n, s, rsc);
422 
423     if (n->sprops != NULL)
424 	mtUpdateSurfaceProps(n, s);
425 
426     /* is it enough to do this just here? can we avoid this call in some cases?*/
427     private_rmStateCacheSync(s, rsc);
428 
429     /* foil compiler warnings */
430     indx = 0;
431 }
432 
433 void
MTWORKPARMS()434 private_mtPopAttribAndState MTWORKPARMS()
435 {
436     private_rmGLPopAttrib(p, s, rsc);
437     private_rmStateCacheSync(s, rsc);
438 
439     /* foil compiler warnings */
440     p = NULL;
441     n = NULL;
442     indx = 0;
443 }
444 
445 void
MTWORKPARMS()446 private_mtPushAttrib MTWORKPARMS()
447 {
448     GLuint mask = private_rmNodeGetAttribMask(n);
449 
450     if (mask != 0)
451 	private_rmGLPushAttrib(p, n, mask);
452 
453     if (n->scene_parms != NULL)
454 	mtUpdateSceneParms(n, s, p, rsc);
455 
456     if (n->rprops != NULL)
457 	mtUpdateRenderProps(n, s, rsc);
458 
459     if (n->sprops != NULL)
460 	mtUpdateSurfaceProps(n, s);
461 
462     /* is it enough to do this just here? can we avoid this call in some cases?*/
463     private_rmStateCacheSync(s, rsc);
464 
465     /* foil compiler warnings */
466     indx = 0;
467 }
468 
469 void
MTWORKPARMS()470 private_mtPushState MTWORKPARMS()
471 {
472     /* foil compiler warnings */
473     p = NULL;
474     n = NULL;
475     s = NULL;
476     rsc = NULL;
477     indx = 0;
478 }
479 
480 void
MTWORKPARMS()481 private_mtPopState MTWORKPARMS()
482 {
483     /*
484      * synchronize the RMstateCache with the working RMstate
485      */
486     /*    private_rmStateCacheSync(s, rsc); */
487     private_rmSyncStateToCache(rsc, s);
488 
489     /* foil compiler warnings */
490     p = NULL;
491     n = NULL;
492     indx = 0;
493 }
494 
495 void
MTWORKPARMS()496 private_mtPostTraverseCallback MTWORKPARMS()
497 {
498     int (*afunc)(const RMnode *, const RMstate *);
499     int rstat;
500 
501     if (n->renderPosttraverseCallback == NULL)
502     {
503 	rmError(" private_mtPostTraverseCallback() inconsistency check fails: a node's render-stage post traversal callback was scheduled for invocation by view for render, but the func callback is NULL in the node!! Cannot invoke the post-traversal callback during the render stage.");
504 	return;
505     }
506 
507     afunc = n->renderPosttraverseCallback;
508     rstat = (*afunc)((const RMnode *)n, (const RMstate *)s);
509 
510     /* foil compiler warnings */
511     p = NULL;
512     indx = 0;
513     rsc = NULL;
514 }
515 
516 void
MTWORKPARMS()517 private_mtPreTraverseCallback MTWORKPARMS()
518 {
519     int (*afunc)(const RMnode *, const RMstate *);
520     int rstat;
521 
522     if (n->renderPretraverseCallback == NULL)
523     {
524 	rmError(" private_mtPreTraverseCallback() inconsistency check fails: a node's render-stage post traversal callback was scheduled for invocation by view for render, but the func callback is NULL in the node!! Cannot invoke the post-traversal callback during the render stage.");
525 	return;
526     }
527 
528     afunc = n->renderPretraverseCallback;
529     rstat = (*afunc)((const RMnode *)n, (const RMstate *)s);
530 
531     /* foil compiler warnings */
532     p = NULL;
533     indx = 0;
534     rsc = NULL;
535 }
536 
537 void
MTWORKPARMS()538 private_mtPushTextProps MTWORKPARMS()
539 {
540     /* update state with new textprops */
541     /* tmp */
542     s->textProps = n->scene_parms->textProps;
543 
544     /* foil compiler warnings */
545     p = NULL;
546     n = NULL;
547     indx = 0;
548     rsc = NULL;
549 }
550 
551 void
MTWORKPARMS()552 private_mtPopTextProps MTWORKPARMS()
553 {
554     /* reinstate text props */
555 #if 0
556     /* 3/16/05 - how to reinstate RMstate-level textprops? Using
557      gl's push/pop attrib is not the right way to go. The following
558     line of code was removed 3/16/05 due to stack underflow errors. */
559     my_glPopAttrib(); 		/* 8/8/04 wes tmp test */
560 #endif
561     /* foil compiler warnings */
562     p = NULL;
563     n = NULL;
564     s = NULL;
565     indx = 0;
566     rsc = NULL;
567 }
568 
MTWORKPARMS()569 void private_mtPopAttrib MTWORKPARMS()
570 {
571     private_rmGLPopAttrib(p, s, rsc);
572     private_rmStateCacheSync(s, rsc);
573 
574     /* foil compiler warnings */
575     p = NULL;
576     n = NULL;
577     indx = 0;
578 }
579 
580 void
MTWORKPARMS()581 private_mtPushModelViewMatrix MTWORKPARMS()
582 {
583 #if 0
584     glMatrixMode(GL_MODELVIEW);
585     glPushMatrix();
586     glLoadMatrixf(&(s->modelView.m[0][0]));
587 #endif
588     /* foil compiler warnings */
589     p = NULL;
590     n = NULL;
591     s = NULL;
592     indx = 0;
593     rsc = NULL;
594 }
595 
596 void
MTWORKPARMS()597 private_mtPopModelViewMatrix MTWORKPARMS()
598 {
599     glMatrixMode(GL_MODELVIEW);
600     myGlPopMatrix(GL_MODELVIEW);
601 
602     /* foil compiler warnings */
603     p = NULL;
604     n = NULL;
605     s = NULL;
606     indx = 0;
607     rsc = NULL;
608 }
609 
610 void
MTWORKPARMS()611 private_mtPushProjMatrix MTWORKPARMS()
612 {
613 #if 0
614     glMatrixMode(GL_PROJECTION);
615     glPushMatrix();
616     glLoadMatrixf(&(s->projection.m[0][0]));
617 #endif
618     /* foil compiler warnings */
619     p = NULL;
620     n = NULL;
621     s = NULL;
622     indx = 0;
623     rsc = NULL;
624 }
625 
626 void
MTWORKPARMS()627 private_mtPopProjMatrix MTWORKPARMS()
628 {
629     glMatrixMode(GL_PROJECTION);
630     myGlPopMatrix(GL_PROJECTION);
631 
632     /* foil compiler warnings */
633     p = NULL;
634     n = NULL;
635     s = NULL;
636     indx = 0;
637     rsc = NULL;
638 }
639 
640 void
MTWORKPARMS()641 private_mtPushTextureMatrix MTWORKPARMS()
642 {
643 #if 0
644     glMatrixMode(GL_TEXTURE);
645     glPushMatrix();
646     glLoadMatrixf(&(s->textureMatrix.m[0][0]));
647 #endif
648     /* foil compiler warnings */
649     p = NULL;
650     n = NULL;
651     s = NULL;
652     indx = 0;
653     rsc = NULL;
654 }
655 
656 void
MTWORKPARMS()657 private_mtPopTextureMatrix MTWORKPARMS()
658 {
659     glMatrixMode(GL_TEXTURE);
660     glPopMatrix();
661 
662     /* foil compiler warnings */
663     p = NULL;
664     n = NULL;
665     s = NULL;
666     indx = 0;
667     rsc = NULL;
668 }
669 
670 void
MTWORKPARMS()671 private_mtDraw MTWORKPARMS()
672 {
673     RMprimitive *prim;
674     int i, nprims;
675 
676     nprims = rmNodeGetNumPrims(n);
677     for (i=0;i<nprims;i++)
678     {
679 	void (*renderfunc)  OGLPRIMPARMLIST() ;
680 	prim = n->prims[i];
681 
682 	if (p != NULL)
683 	{
684 	    renderfunc = prim->renderfunc;
685 	    (*renderfunc)(prim, n, s, p, rsc);
686 	}
687     }
688 
689     /* foil compiler warnings */
690     indx = 0;
691 }
692 
693 void
MTWORKPARMS()694 private_mtFBclear MTWORKPARMS()
695 {
696     GLint renderMode = s->rendermode;
697     int backgroundSceneEnable = 1; /* tmp hack */
698 
699     if ((n->fbClear && n->fbClear->bgImageTile) && (backgroundSceneEnable)
700 	&& (renderMode != GL_SELECT) && (renderMode != GL_FEEDBACK))
701     {
702 	private_setBackgroundTile(n->fbClear, s, 1, RM_TRUE);
703     }
704     else if ((n->fbClear && n->fbClear->bgColor) && (backgroundSceneEnable))
705     {
706 	private_setBackgroundColor(n->fbClear, s, 1, RM_TRUE);
707     }
708 
709     /* check depth value or image parms */
710     if (n->fbClear && (n->fbClear->depthValue != NULL) && (backgroundSceneEnable))
711 	private_setBackgroundDepthValue(n->fbClear, s, RM_TRUE);
712 
713     if ((n->fbClear && n->fbClear->depthImage != NULL) && (backgroundSceneEnable))
714 	private_setBackgroundDepthImage(n->fbClear, s, 1, RM_TRUE);
715 
716     /* 9/7/05 - the following is not present in the serial rendering code!! */
717     if (p->postFBClearBarrierFunc != NULL)
718 	p->postFBClearBarrierFunc(p);
719 
720     /* foil compiler warnings */
721     indx = 0;
722     rsc = NULL;
723 }
724 
725 /*#define GETNODE(a,b) ((RMnode *)(a->objectPool) + b) */
726 RMnode *
GETNODE(RMcompMgrHdr * a,int indx)727 GETNODE(RMcompMgrHdr *a,
728 	int indx)
729 {
730     RMnode *r;
731     int pageNum = rmCompManagerGetPage(indx);
732     int offset = rmCompManagerGetOffset(indx);
733 
734     r = (RMnode *)(a->objectPool[pageNum]);
735     r += offset;
736     return r;
737 }
738 
739 /* 8/8/04 - temp for debugging */
740 void
private_rmLightStateConsistencyCheck(char * buf,RMstate * s,RMstateCache * rsc)741 private_rmLightStateConsistencyCheck(char *buf,
742 				     RMstate *s,
743 				     RMstateCache *rsc)
744 {
745     int glLightsEnabled = glIsEnabled(GL_LIGHTING);
746     int stateLightsEnabled = s->lightingActive == RM_TRUE ? 1 : 0;
747     int cacheLightsEnabled = rsc->lightingActive == RM_TRUE ? 1 : 0;
748     int agree;
749 
750     if (glLightsEnabled)
751 	agree = stateLightsEnabled && cacheLightsEnabled && glLightsEnabled;
752     else 			/* glLights not enabled */
753 	agree = (!stateLightsEnabled) && (!cacheLightsEnabled) && (!glLightsEnabled);
754 
755     fprintf(stderr,"%s ", buf);
756     if ( agree )
757 	fprintf(stderr,"LIGHTs check: agreement. ");
758     else
759 	fprintf(stderr,"LIGHTs check: DISAGREEMENT!! ");
760 
761     fprintf(stderr," OpenGL = %d, RMstate = %d, RMstateCache = %d \n", glIsEnabled(GL_LIGHTING), (s->lightingActive == RM_TRUE) ? 1 : 0, (rsc->lightingActive == RM_TRUE) ? 1 : 0);
762 }
763 
764 
765 void
private_rmPipeDrawDisplayList(RMpipe * p,RMdisplayList * t,RMstate * s,RMstateCache * rsc)766 private_rmPipeDrawDisplayList(RMpipe *p,
767 			      RMdisplayList *t,
768 			      RMstate *s,
769 			      RMstateCache *rsc)
770 {
771     int i;
772     extern RMcompMgrHdr *global_RMnodePool;
773     RMnode *n=NULL;
774     RMstate stateStack[MT_MAX_STATE_STACK_SIZE];
775     int stateStackIndx = 0;
776 
777     stateStack[stateStackIndx] = *s;
778 
779     for (i=0;i< t->nOpCodes; i++)
780     {
781 	RMdisplayListOpcode op;
782 	int indx;
783 	extern void (*mtRenderFuncs[]) MTWORKPARMS();
784 	void (*funcPtr) MTWORKPARMS();
785 
786 	op = (RMdisplayListOpcode)(t->opCodes[i]);
787 	indx = t->indices[i];
788 
789 	funcPtr = mtRenderFuncs[(int)op];
790 
791 	switch (op)
792 	{
793 	case MT_PRETRAVERSAL_FUNC:
794 	    n = GETNODE(global_RMnodePool, indx);
795 #if (DEBUG_LEVEL & DEBUG_TRACE)
796 	    fprintf(stderr,"MT_PRETRAVERSAL_FUNC %s\n", private_rmNodeGetName(n));
797 #endif
798 	    break;
799 
800 	case MT_POSTTRAVERSAL_FUNC:
801 	    n = GETNODE(global_RMnodePool, indx);
802 #if (DEBUG_LEVEL & DEBUG_TRACE)
803 	    fprintf(stderr,"MT_POSTTRAVERSAL_FUNC %s\n", private_rmNodeGetName(n));
804 #endif
805 	    break;
806 
807 	case MT_PUSHATTRIB:
808 	    n = GETNODE(global_RMnodePool, indx);
809 #if (DEBUG_LEVEL & DEBUG_TRACE)
810 	    fprintf(stderr,"MT_PUSHATTRIB %s\n", private_rmNodeGetName(n));
811 #endif
812 	    break;
813 
814 	case MT_POPATTRIB:
815 	    /* 8/2002 - no node really needed here */
816 	    n = NULL;
817 #if (DEBUG_LEVEL & DEBUG_TRACE)
818 	    n = GETNODE(global_RMnodePool, indx);
819 	    fprintf(stderr,"MT_POPATTRIB %s \n", private_rmNodeGetName(n));
820 #endif
821 	    break;
822 
823 	case MT_DRAW:
824 	    n = GETNODE(global_RMnodePool, indx);
825 #if (DEBUG_LEVEL & DEBUG_TRACE)
826 	    fprintf(stderr,"MT_DRAW %s\n", private_rmNodeGetName(n));
827 #endif
828 	    break;
829 
830 	case MT_PUSHLOAD_TEXTURE_MATRIX:
831 #if (DEBUG_LEVEL & DEBUG_TRACE)
832 	    n = GETNODE(global_RMnodePool, indx);
833 	    fprintf(stderr,"MT_PUSHLOAD_TEXTURE_MATRIX %s\n", private_rmNodeGetName(n));
834 #endif
835 	    rmMatrixCopy((RMmatrix *)&stateStack[stateStackIndx].texture,
836 			 (RMmatrix *)&(t->matrices[indx].m));
837 	    glMatrixMode(GL_TEXTURE);
838  	    myGlPushMatrix(GL_TEXTURE);
839 	    glLoadMatrixf(&(t->matrices[indx].m[0][0]));
840 
841 	    break;
842 
843 	case MT_PUSHLOAD_PROJ_MATRIX:
844 #if (DEBUG_LEVEL & DEBUG_TRACE)
845 	    fprintf(stderr,"MT_PUSHLOAD_PROJ_MATRIX \n" );
846 #endif
847 	    rmMatrixCopy((RMmatrix *)&stateStack[stateStackIndx].projection,
848 			 (RMmatrix *)&(t->matrices[indx].m));
849 	    glMatrixMode(GL_PROJECTION);
850  	    myGlPushMatrix(GL_PROJECTION);
851 	    glLoadMatrixf(&(t->matrices[indx].m[0][0]));
852 
853 	    break;
854 
855 	case MT_PUSHLOAD_MODELVIEW_MATRIX:
856 #if (DEBUG_LEVEL & DEBUG_TRACE)
857 	    n = GETNODE(global_RMnodePool, indx);
858 	    fprintf(stderr,"MT_PUSHLOAD_MODELVIEW_MATRIX \n");
859 #endif
860 
861 	    rmMatrixCopy((RMmatrix *)&stateStack[stateStackIndx].modelView,
862 			 (RMmatrix *)&(t->matrices[indx].m));
863 	    glMatrixMode(GL_MODELVIEW);
864 	    myGlPushMatrix(GL_MODELVIEW);
865 	    glLoadMatrixf(&(t->matrices[indx].m[0][0]));
866 
867 	    break;
868 
869 	case MT_POP_PROJ_MATRIX:
870 	    n = NULL;
871 #if (DEBUG_LEVEL & DEBUG_TRACE)
872 	    fprintf(stderr,"MT_POP_PROJ_MATRIX \n");
873 #endif
874 	    break;
875 
876 	case MT_POP_MODELVIEW_MATRIX:
877 	    n = NULL;
878 #if (DEBUG_LEVEL & DEBUG_TRACE)
879 	    fprintf(stderr,"MT_POP_MODELVIEW_MATRIX \n");
880 #endif
881 	    break;
882 
883 	case MT_POP_TEXTURE_MATRIX:
884 	    n = NULL;
885 #if (DEBUG_LEVEL & DEBUG_TRACE)
886 	    fprintf(stderr,"MT_POP_TEXTURE_MATRIX \n");
887 #endif
888 	    break;
889 
890 	case MT_FBCLEAR:
891 	    n = GETNODE(global_RMnodePool, indx);
892 #if (DEBUG_LEVEL & DEBUG_TRACE)
893 	    fprintf(stderr,"MT_FBCLEAR %s\n",private_rmNodeGetName(n));
894 #endif
895 	    break;
896 
897 	case MT_PUSH_TEXTPROPS:
898 	    n = GETNODE(global_RMnodePool, indx);
899 #if (DEBUG_LEVEL & DEBUG_TRACE)
900 	    fprintf(stderr,"MT_PUSH_TEXTPROPS %s\n", private_rmNodeGetName(n));
901 #endif
902 	    break;
903 
904 	case MT_POP_TEXTPROPS:
905 /*	    n = GETNODE(global_RMnodePool, indx); */
906 	    n = NULL; /* no node needed */
907 #if (DEBUG_LEVEL & DEBUG_TRACE)
908 	    n = GETNODE(global_RMnodePool, indx);
909 	    fprintf(stderr,"MT_POP_TEXTPROPS %s\n", private_rmNodeGetName(n));
910 #endif
911 	    break;
912 
913 	case MT_PUSH_STATE:
914 	    stateStack[stateStackIndx+1] = stateStack[stateStackIndx];
915 	    stateStackIndx++;
916 #if (DEBUG_LEVEL & DEBUG_TRACE)
917 	    n = GETNODE(global_RMnodePool, indx);
918 	    fprintf(stderr,"MT_PUSH_STATE %s\n", private_rmNodeGetName(n));
919 #endif
920 	    break;
921 
922 	case MT_POP_STATE:
923 	    stateStackIndx--;
924 #if (DEBUG_LEVEL & DEBUG_TRACE)
925 	    n = GETNODE(global_RMnodePool, indx);
926 	    fprintf(stderr,"MT_POP_STATE %s\n", private_rmNodeGetName(n));
927 #endif
928 	    break;
929 
930 	case MT_PUSH_STATE_ATTRIB:
931 	    stateStack[stateStackIndx+1] = stateStack[stateStackIndx];
932 	    stateStackIndx++;
933 	    n = GETNODE(global_RMnodePool, indx);
934 #if (DEBUG_LEVEL & DEBUG_TRACE)
935 	    fprintf(stderr,"MT_PUSH_STATE_ATTRIB %s\n", private_rmNodeGetName(n));
936 #endif
937 	    break;
938 
939 	case MT_POP_STATE_ATTRIB:
940 	    stateStackIndx--;
941 #if (DEBUG_LEVEL & DEBUG_TRACE)
942 	    n = GETNODE(global_RMnodePool, indx);
943 	    fprintf(stderr,"MT_POP_STATE_ATTRIB %s\n", private_rmNodeGetName(n));
944 #endif
945 	    break;
946 
947 	default:
948 #if (DEBUG_LEVEL & DEBUG_TRACE)
949 	    fprintf(stderr,"default \n");
950 #endif
951 	    break;
952 	}
953 
954 	if (funcPtr != NULL)
955 	    (*funcPtr)(p, n, stateStack + stateStackIndx, i, rsc);
956 	    /* 	    (*funcPtr)(p, n, stateStack + stateStackIndx, t, i, rsc); */
957 
958 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
959 	private_rmLightStateConsistencyCheck("private_rmPipeDrawDisplayList",stateStack+stateStackIndx, rsc);
960 #endif
961 
962 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
963 	{
964 	    char buf[64];
965 	    sprintf(buf, " private_rmDraw OpenGL error ");
966 	    rmGLGetError(buf);
967 	}
968 #endif
969 
970     }
971 }
972 
973 static void
private_setupLeftStereoChannel(RMenum channelFormat)974 private_setupLeftStereoChannel(RMenum channelFormat)
975 {
976     if (channelFormat == RM_MBUF_STEREO_CHANNEL)
977 	glDrawBuffer(GL_BACK_LEFT);
978     else if (channelFormat == RM_REDBLUE_STEREO_CHANNEL)
979 	glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
980     else		/* assume BLUERED */
981 	glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
982 }
983 
984 static void
private_setupRightStereoChannel(RMenum channelFormat)985 private_setupRightStereoChannel(RMenum channelFormat)
986 {
987     if (channelFormat == RM_MBUF_STEREO_CHANNEL)
988 	glDrawBuffer(GL_BACK_RIGHT);
989     else if (channelFormat == RM_REDBLUE_STEREO_CHANNEL)
990 	glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
991     else		/* assume BLUERED */
992 	glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
993 }
994 
995 
996 void
private_rmRender(RMpipe * p,int frameNumber)997 private_rmRender (RMpipe *p,
998 		  int frameNumber)
999 {
1000     RMstateCache *rsc = private_rmStateCacheNew();
1001     RMstate rState;
1002     RMenum render3DOpaqueEnable, render3DTransparentEnable, render2DOpaqueEnable;
1003     RMmultipassDisplayList *mp;
1004     RMdisplayList *t;
1005 /*     int initMatrixStack = rmPipeGetInitMatrixStackMode(p); not used 6/3/01 wes */
1006     int dlIndx;
1007     RMenum channelFormat = rmPipeGetChannelFormat(p);
1008 
1009     /* select even or odd multipass display list as a function of framenum */
1010     dlIndx = private_rmSelectEvenOddBuffer(frameNumber);
1011 
1012     mp = (RMmultipassDisplayList *)(p->displayLists);
1013 
1014     private_rmStateInit(p, &rState, (RMenum)GL_RENDER, NULL, NULL, NULL, NULL);
1015 
1016     rmPipeGetRenderPassEnable(p, &render3DOpaqueEnable, &render3DTransparentEnable, &render2DOpaqueEnable);
1017 
1018     glDisable(GL_DITHER); /* tmp wes 7/28/02 */
1019 
1020 #if (DEBUG_LEVEL & DEBUG_GLERRORCHECK)
1021     rmGLGetError("private_rmRender");
1022 #endif
1023 
1024     /* take care of global stuff */
1025     {
1026 	glDisable(GL_BLEND);	/* make sure it's turned off */
1027 	glDisable(GL_DEPTH_TEST);
1028 	glDepthMask(GL_TRUE);
1029 	glDisable(GL_LIGHTING);
1030 
1031 	rState.lightingActive = RM_FALSE;
1032 	rsc->lightingActive = RM_FALSE;
1033 	private_rmColorMaterial(&rState, rsc, RM_FALSE);
1034 
1035 #if (DEBUG_LEVEL & DEBUG_TRACE)
1036 	fprintf(stderr, "private_mtRender: private_mtRender: RMpipe fbclears \n");
1037 #endif
1038 	rState.renderpass = RM_RENDERPASS_ALL;
1039 	rState.renderPassDims = RM_RENDERPASS_ALL;
1040 
1041 	t = mp->globals[dlIndx];
1042 	rState.which_channel = RM_ALL_CHANNELS;
1043 	private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1044     }
1045 
1046     if (render3DOpaqueEnable == RM_TRUE)
1047     {
1048 	glDisable(GL_BLEND);	/* make sure it's turned off */
1049 	glEnable(GL_DEPTH_TEST);
1050 	glDepthMask(GL_TRUE);
1051 
1052 	glDisable(GL_LIGHTING);
1053 	rState.lightingActive = RM_FALSE;
1054 	rsc->lightingActive = RM_FALSE;
1055 	private_rmColorMaterial(&rState, rsc, RM_FALSE);
1056 
1057 #if (DEBUG_LEVEL & DEBUG_TRACE)
1058 	fprintf(stderr, "private_mtRender: start of 3D opaque pass \n");
1059 #endif
1060 	rState.renderpass = RM_RENDERPASS_OPAQUE;
1061 	rState.renderPassDims = RM_RENDERPASS_3D;
1062 
1063 	if ((channelFormat == RM_MONO_CHANNEL) ||
1064 	    (channelFormat == RM_OFFSCREEN_MONO_CHANNEL))
1065 	{
1066 	    t = mp->opaque3D[dlIndx];
1067 	    rState.which_channel = RM_ALL_CHANNELS;
1068 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1069 	}
1070 	else			/* assume a stereo format */
1071 	{
1072 	    private_setupLeftStereoChannel(channelFormat);
1073 
1074 	    rState.which_channel = RM_LEFT_CHANNEL;
1075 	    t = mp->opaque3D[dlIndx];
1076 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1077 
1078 #if (DEBUG_LEVEL & DEBUG_TRACE)
1079 	    fprintf(stderr, "private_mtRender: start of right-channel, 3D opaque pass \n");
1080 #endif
1081 
1082 	    /* re-initialize for drawing the other channel */
1083 	    glDisable(GL_LIGHTING);
1084 	    rState.lightingActive = RM_FALSE;
1085 	    rsc->lightingActive = RM_FALSE;
1086 	    private_rmColorMaterial(&rState, rsc, RM_FALSE);
1087 
1088 	    private_setupRightStereoChannel(channelFormat);
1089 
1090 	    rState.which_channel = RM_RIGHT_CHANNEL;
1091 	    t = mp->rightOpaque3D[dlIndx];
1092 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1093 
1094 	}
1095     }
1096 
1097     if (render3DTransparentEnable == RM_TRUE)
1098     {
1099 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1100 	glEnable(GL_BLEND);
1101 
1102 	glEnable(GL_DEPTH_TEST);
1103 	glDepthMask(GL_FALSE);
1104 
1105 	glDisable(GL_LIGHTING);
1106 	rState.lightingActive = RM_FALSE;
1107 	rsc->lightingActive = RM_FALSE;
1108 	private_rmColorMaterial(&rState, rsc, RM_FALSE);
1109 
1110 	rState.renderpass = RM_RENDERPASS_TRANSPARENT;
1111 	rState.renderPassDims = RM_RENDERPASS_3D;
1112 
1113 #if (DEBUG_LEVEL & DEBUG_TRACE)
1114 	fprintf(stderr, "private_mtRender: start of 3D transparent pass \n");
1115 #endif
1116 
1117 	if ((channelFormat == RM_MONO_CHANNEL) ||
1118 	    (channelFormat == RM_OFFSCREEN_MONO_CHANNEL))
1119 	{
1120 	    rState.which_channel = RM_ALL_CHANNELS;
1121 	    t = mp->transparent3D[dlIndx];
1122 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1123 	}
1124 	else
1125 	{
1126 	    private_setupLeftStereoChannel(channelFormat);
1127 
1128 	    rState.which_channel = RM_LEFT_CHANNEL;
1129 
1130 	    t = mp->transparent3D[dlIndx];
1131 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1132 
1133 #if (DEBUG_LEVEL & DEBUG_TRACE)
1134 	    fprintf(stderr, "private_mtRender: start of right-channel, 3D transparent pass \n");
1135 #endif
1136 	    /* re-initialize for drawing the other channel */
1137 	    glDisable(GL_LIGHTING);
1138 	    rState.lightingActive = RM_FALSE;
1139 	    rsc->lightingActive = RM_FALSE;
1140 	    private_rmColorMaterial(&rState, rsc, RM_FALSE);
1141 
1142 	    private_setupRightStereoChannel(channelFormat);
1143 	    t = mp->rightTransparent3D[dlIndx];
1144 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1145 	}
1146 	glDisable(GL_BLEND);
1147     }
1148 
1149     if (render2DOpaqueEnable == RM_TRUE)
1150     {
1151 	glDisable(GL_DEPTH_TEST);
1152 	/* 5/11/02 - make sure actual state is same as in RMstate */
1153 	glDisable(GL_LIGHTING);
1154 	rState.lightingActive = RM_FALSE;
1155 	rsc->lightingActive = RM_FALSE;
1156 	private_rmColorMaterial(&rState, rsc, RM_FALSE);
1157 
1158 	rState.renderpass = RM_RENDERPASS_OPAQUE;
1159 	rState.renderPassDims = RM_RENDERPASS_2D;
1160 
1161 #if (DEBUG_LEVEL & DEBUG_TRACE)
1162 	fprintf(stderr, "private_mtRender: start of 2D opaque pass \n");
1163 #endif
1164 	if ((channelFormat == RM_MONO_CHANNEL) ||
1165 	    (channelFormat == RM_OFFSCREEN_MONO_CHANNEL))
1166 	{
1167 	    rState.which_channel = RM_ALL_CHANNELS;
1168 	    t = mp->opaque2D[dlIndx];
1169 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1170 	}
1171 	else
1172 	{
1173 	    private_setupLeftStereoChannel(channelFormat);
1174 
1175 	    rState.which_channel = RM_LEFT_CHANNEL;
1176 	    t = mp->opaque2D[dlIndx];
1177 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1178 
1179 #if (DEBUG_LEVEL & DEBUG_TRACE)
1180 	    fprintf(stderr, "private_mtRender: start of right-channel, 2D opaque pass \n");
1181 #endif
1182 	    private_setupRightStereoChannel(channelFormat);
1183 
1184 	    rState.which_channel = RM_RIGHT_CHANNEL;
1185 	    t = mp->rightOpaque2D[dlIndx];
1186 
1187 	    /* re-initialize for drawing the other channel */
1188 	    glDisable(GL_LIGHTING);
1189 	    rState.lightingActive = RM_FALSE;
1190 	    rsc->lightingActive = RM_FALSE;
1191 	    private_rmColorMaterial(&rState, rsc, RM_FALSE);
1192 
1193 	    private_rmPipeDrawDisplayList(p, t, &rState, rsc);
1194 	}
1195     }
1196     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1197 
1198     free((void *)rsc);
1199 }
1200 
1201 /* EOF */
1202