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