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: rmcmpmgr.c,v 1.11 2005/06/15 02:10:40 wes Exp $
27 * Version: $Name: OpenRM-1-6-0-2-RC2 $
28 * $Revision: 1.11 $
29 * $Log: rmcmpmgr.c,v $
30 * Revision 1.11 2005/06/15 02:10:40 wes
31 * Added initial support for application-settable defaults. Apps
32 * will use rmSetEnum/rmGetEnum to set or get defaults that are RMenums.
33 * The first round of variables that can be set/get by apps are
34 * RMnode traversal masks assigned to new scene graph nodes by rmNodeNew.
35 *
36 * Revision 1.10 2005/06/06 02:04:29 wes
37 * Lots of small additions to clean up compiler warnings.
38 *
39 * Revision 1.9 2005/03/19 17:18:45 wes
40 * For RM_MARKERS2D primitives, add call to delete prim-specific data.
41 *
42 * Revision 1.8 2005/02/27 19:34:04 wes
43 * Added support for application supplied texture object IDs and display lists.
44 *
45 * Revision 1.7 2005/02/19 16:34:21 wes
46 * Distro sync and consolidation.
47 * Minor code rearrangement, remove dead code.
48 *
49 * Revision 1.6 2005/01/23 17:08:25 wes
50 * Copyright updated to 2005.
51 * Updates to support access and use of extensions; multitexturing on all
52 * platforms, use of 3d texture extension to realize implementation of
53 * volume rendering and related functions on Windows platforms.
54 *
55 * Revision 1.5 2004/01/16 16:43:24 wes
56 * Updated copyright line for 2004.
57 *
58 * Revision 1.4 2003/04/05 13:58:29 wes
59 * Fixed two memory leaks: free CM mutexes upon exit, and free the fbClear struct.
60 *
61 * Revision 1.3 2003/02/02 17:50:57 wes
62 * Added bounding boxes to RMprimitives, as a supplement to node-level bboxes.
63 * The RMprimitive level bboxes are needed for the retained-mode CR work.
64 *
65 * Revision 1.2 2003/02/02 02:07:15 wes
66 * Updated copyright to 2003.
67 *
68 * Revision 1.1.1.1 2003/01/28 02:15:23 wes
69 * Manual rebuild of rm150 repository.
70 *
71 * Revision 1.9 2003/01/16 22:21:17 wes
72 * Updated all source files to reflect new organization of header files:
73 * all header files formerly located in include/rmaux, include/rmi, include/rmv
74 * are now located in include/rm.
75 *
76 * Revision 1.8 2002/09/17 14:20:03 wes
77 * Added new routine rmComponentManagerPrintStatus(). Added code inside
78 * private_rmDeleteComponentManager() that will free all pages of memory
79 * in the object pool - this is needed in conjunction with the new
80 * paging model.
81 *
82 * Revision 1.7 2002/09/05 15:05:03 wes
83 * more thorough debug info on realloc
84 *
85 * Revision 1.6 2002/08/29 22:20:32 wes
86 *
87 * Massive upgrade to accommodate dynamic object reallocation within
88 * the component manager, and within the context cache. Use the
89 * debug #define DEBUG_LEVEL DEBUG_REALLOC_TRACE to get a printf
90 * whenever a realloc occurs. With this upgrade, there are no
91 * OpenRM limits on the size of the scene graph. There will be external
92 * limits, such as the amount of RAM and the amount of space available
93 * to your OpenGL implementation.
94 *
95 * Revision 1.5 2002/08/19 00:54:27 wes
96 * Added API entries for new experiemental routines to get and set
97 * the size of the OpenRM component manager object pool.
98 *
99 * Revision 1.4 2002/04/30 19:30:20 wes
100 * rmImageDelete will automatically call rmImageSetVismap(img, NULL) to
101 * induce release of any memory associated with a vis colormap in an
102 * RMimage.
103 *
104 * Revision 1.3 2001/07/15 17:17:11 wes
105 * Added code to manage "normalizeNormals" render property - fixes a
106 * 4-byte memory leak.
107 *
108 * Revision 1.2 2001/03/31 17:12:38 wes
109 * v1.4.0-alpha-2 checkin.
110 *
111 * Revision 1.1 2000/12/03 22:32:59 wes
112 * Initial entry.
113 *
114 */
115
116 #include <rm/rm.h>
117 #include "rmprivat.h"
118
119 static RMcompList *private_rmInitComponentMetaList(int objCount);
120 static RMenum private_rmReallocComponentMgrListAndPool(RMcompMgrHdr *h);
121 static void private_rmComponentManagerStatus(void);
122
123
124 /*
125 * ----------------------------------------------------
126 * @Name rmComponentManagerPrintStatus
127 @pstart
128 void rmComponentManagerPrintStatus( void )
129 @pend
130
131 @astart
132 none.
133 @aend
134
135 @dstart
136
137 Use this routine to display the current free/alloc status of objects
138 managed by the component manager. This routine will invoke rmNotice() to
139 display the number of allocated and free objects managed by the
140 component manager. This routine is useful in tracking down memory leaks
141 in applications.
142
143 This routine is new, and experimental, in version 1.4.3. It may be
144 subsumed by more general utilities in the future.
145
146 @dend
147 * ----------------------------------------------------
148 */
149 void
rmComponentManagerPrintStatus(void)150 rmComponentManagerPrintStatus(void)
151 {
152 private_rmComponentManagerStatus();
153 }
154
155
156 /* PRIVATE */
157 RMcompMgrHdr *
private_rmInitComponentManager(int objCount,int objSize)158 private_rmInitComponentManager(int objCount,
159 int objSize)
160 {
161 RMcompMgrHdr *t;
162
163 t = (RMcompMgrHdr *)malloc(sizeof(RMcompMgrHdr));
164
165 if (t == NULL)
166 return(NULL);
167
168 t->numPages = 1;
169
170 t->objectPool = (void **)malloc(sizeof(void *));
171 t->objectPool[0] = (void *)malloc(objCount * objSize);
172
173 t->metaListHead = private_rmInitComponentMetaList(objCount);
174
175 t->numAlloc = 0;
176
177 t->startFree = 0;
178 t->startAlloc = -1;
179
180 t->numFree = objCount;
181 t->currentPoolSize = objCount;
182 t->componentSize = objSize;
183
184 /* create a mutex in unlocked state */
185
186 t->guard = rmMutexNew(RM_MUTEX_UNLOCK);
187
188 return(t);
189 }
190
191 /* PRIVATE */
192 static RMcompList *
private_rmInitComponentMetaList(int objCount)193 private_rmInitComponentMetaList(int objCount)
194 {
195 RMcompList *t;
196 int i;
197
198 t = (RMcompList *)malloc(sizeof(RMcompList)*objCount);
199 if (t == NULL)
200 return(NULL);
201
202 for (i=0;i<objCount;i++)
203 {
204 t[i].objIndx = i;
205 t[i].myIndx = i;
206 if (i==0)
207 t[i].prevIndx = -1;
208 else
209 t[i].prevIndx = i-1;
210
211 if (i == objCount-1)
212 t[i].nextIndx = -1;
213 else
214 t[i].nextIndx = i+1;
215 }
216 return(t);
217 }
218
219 /* PRIVATE */
220 static RMenum
private_rmReallocComponentMgrListAndPool(RMcompMgrHdr * h)221 private_rmReallocComponentMgrListAndPool(RMcompMgrHdr *h)
222 {
223 /*
224 * 8/29/02 - wes. implementation of dynamic object pools.
225 * this routine will realloc the MetaList in a component manager,
226 * and will add a page of new memory to the objectPool.
227 */
228 RMcompList *oldList, *t;
229 int i;
230 int newSize;
231 int newPoolSize, oldPoolSize;
232
233 /* first, compute new size of alloc list */
234 newSize = h->currentPoolSize * sizeof(RMcompList);
235 newSize += (NUM_ITEMS_PER_PAGE) * sizeof(RMcompList);
236
237 oldList = h->metaListHead;
238 t = (RMcompList *)realloc((void *)oldList, newSize);
239
240 if (t == NULL)
241 return(RM_WHACKED);
242
243 /* update the pointer in the header */
244 h->metaListHead = t;
245
246 /*
247 * realloc succeeded if we're here. initialize the new hunk of
248 * memory.
249 */
250 oldPoolSize = h->currentPoolSize;
251 newPoolSize = oldPoolSize + NUM_ITEMS_PER_PAGE;
252
253 /*
254 * initialize the new stuff. we don't need to adjust the "pointers"
255 * in any of the old stuff because we are maintaining two virtual
256 * lists within one pile of stuff. because we're here, we're out of
257 * free objects.
258 */
259 for (i=oldPoolSize; i < newPoolSize; i++)
260 {
261 t[i].objIndx = i;
262 t[i].myIndx = i;
263
264 if (i == oldPoolSize)
265 t[i].prevIndx = -1;
266 else
267 t[i].prevIndx = i-1;
268
269 if (i == newPoolSize-1)
270 t[i].nextIndx = -1;
271 else
272 t[i].nextIndx = i+1;
273 }
274
275
276 /*
277 * now, update counters in the RMcompMgrHdr to reflect new values.
278 */
279 h->numFree += NUM_ITEMS_PER_PAGE;
280 h->startFree = oldPoolSize;
281 h->currentPoolSize += NUM_ITEMS_PER_PAGE;
282
283 /*
284 * OK - now we're done futzing with the alloc/free lists. now we
285 * need to actually increase the size of the objectPool. This is
286 * accomplished by adding another "page" of memory. we can't just
287 * blindly realloc the objectPool because the application probably
288 * has object pointers into that hunk of memory, and a realloc
289 * might (probably) causes memory to be moved around, and then the
290 * app's pointers would be stale. we use a paging scheme as a
291 * compromise..application performance isn't affected at all; we
292 * incur only a small amount of additional overhead when the
293 * application invokes a new/delete operation.
294 */
295
296 h->objectPool = (void **)realloc(h->objectPool, sizeof(void *)*(h->numPages + 1));
297 h->objectPool[h->numPages] = (void *)malloc(NUM_ITEMS_PER_PAGE * h->componentSize);
298 memset(h->objectPool[h->numPages], 0, NUM_ITEMS_PER_PAGE * h->componentSize);
299
300 h->numPages += 1;
301
302 return RM_CHILL;
303 }
304
305 /* PRIVATE */
306 static int
private_rmFreeToAlloc(RMcompMgrHdr * h,const char * msg)307 private_rmFreeToAlloc(RMcompMgrHdr *h, /* input - component mgr hdr */
308 const char *msg) /* message to bark upon error */
309 {
310 /*
311 * move an item from the head of the free list to the start
312 * of the alloc list. this routine will take care of all
313 * bookkeeping: updating counter of free and alloc pools,
314 * updating pointers in lists, etc.
315 *
316 * upon successful completion, the index of the moved
317 * entry is returned. upon failure, a -1 is returned. failure
318 * occurs when the list of free objects has been depleted.
319 */
320 int freeIndx;
321 RMcompList *firstFree;
322
323 /*
324 * first, make sure we have exclusive use of this pool.
325 */
326 if (rmMutexLock(h->guard) == RM_WHACKED)
327 {
328 /*
329 * if we arrive here, something is really, really wrong.
330 * the rmMutexLock() call is supposed to do a blocking wait
331 * and then grab the mutex once it's available. If we arrive
332 * here, then there's some type of fatal error deep in
333 * pthreads. To date, this branch of code has never been
334 * executed in millions of program runs (as far as I know).
335 */
336 rmError(" problem locking mutex in component manager. \n");
337 exit(-1);
338 }
339
340 if (h->numAlloc+1 > h->currentPoolSize)
341 {
342 #if (DEBUG_LEVEL & DEBUG_REALLOC_TRACE)
343 printf("component manager execing realloc: %s. oldsize = %d ", msg,h->currentPoolSize);
344 #endif
345 /* execute realloc on metalist */
346 if (private_rmReallocComponentMgrListAndPool(h) != RM_CHILL)
347 {
348 rmError(msg);
349 rmMutexUnlock(h->guard); /* wes 1/21/02 */
350 return(-1);
351 }
352 #if (DEBUG_LEVEL & DEBUG_REALLOC_TRACE)
353 printf("newsize = %d \n", h->currentPoolSize);
354 fflush(stdout);
355 #endif
356 }
357
358 /* take top of free list */
359 /* don't need to update prevIndex in free list */
360 freeIndx = h->startFree;
361 firstFree = h->metaListHead + freeIndx;
362
363 /* update the start of the free list.. */
364 h->startFree = firstFree->nextIndx;
365
366 /* and the count of free items. */
367 h->numFree -= 1;
368
369 /* update the alloc list. when we update the alloc list, we put
370 the newly alloc'ed item at the head of the list. it's next pointer
371 will be the old head of list, and it's prev pointer will be -1. */
372 {
373 RMcompList *oldFirstAlloc, *newAlloc;
374
375 newAlloc = firstFree;
376
377 /* add the newly alloced one to the front of the free list */
378 newAlloc->nextIndx = h->startAlloc;
379 h->startAlloc = newAlloc->myIndx;
380
381 /* so there's no prev index */
382 newAlloc->prevIndx = -1;
383
384 if (newAlloc->nextIndx != -1)
385 {
386 /* something was on the list, update it's prev pointer
387 to point to the newly added thing.*/
388
389 oldFirstAlloc = h->metaListHead + newAlloc->nextIndx;
390 oldFirstAlloc->prevIndx = newAlloc->myIndx;
391 }
392 h->numAlloc += 1;
393 }
394
395 rmMutexUnlock(h->guard);
396
397 return (freeIndx);
398 }
399
400 /* PRIVATE */
401 void
private_rmAllocToFree(RMcompMgrHdr * h,unsigned int indx)402 private_rmAllocToFree(RMcompMgrHdr *h, /* main component mgr to use */
403 unsigned int indx) /* index of item to move from alloc to free */
404 {
405 RMcompList *toFree;
406
407 toFree = h->metaListHead;
408 toFree += indx;
409
410 /* first, fix up the alloc list. */
411
412 /* fix up "next" pointer of previous alloc list item */
413 if (toFree->prevIndx == -1) /* it's at the start of the list */
414 {
415 h->startAlloc = toFree->nextIndx;
416 }
417 else
418 {
419 RMcompList *prev;
420 prev = h->metaListHead + toFree->prevIndx;
421 prev->nextIndx = toFree->nextIndx;
422 }
423
424 /* fix up "prev" pointer of next alloc item list */
425 if (toFree->nextIndx != -1)
426 {
427 RMcompList *next;
428 next = h->metaListHead + toFree->nextIndx;
429 next->prevIndx = toFree->prevIndx;
430 }
431
432 /* now, insert the toFree entry back into the free list - always
433 put it at the top of the free list (no prev pointers) */
434
435 toFree->nextIndx = h->startFree;
436 h->startFree = toFree->myIndx;
437
438 h->numAlloc -= 1;
439 h->numFree += 1;
440
441 }
442
443 /* PRIVATE */
444 RMimage *
private_rmImageNew(void)445 private_rmImageNew(void)
446 {
447 /*
448 *
449 */
450 extern RMcompMgrHdr *global_RMimagePool;
451 int freeIndx;
452 int pageNum, offset;
453 RMimage *t;
454
455 if (RM_ASSERT(global_RMimagePool, "Please call rmInit() prior to creating RMimage objects. \n") == RM_WHACKED)
456 return(NULL);
457
458 freeIndx = private_rmFreeToAlloc(global_RMimagePool,"private_rmImageNew() - all RMimage objects have been used.");
459
460 if (freeIndx == -1)
461 return(NULL);
462
463 pageNum = rmCompManagerGetPage(freeIndx);
464 offset = rmCompManagerGetOffset(freeIndx);
465
466 /* return RMimage handle to caller */
467 t = (RMimage *)(global_RMimagePool->objectPool[pageNum]);
468 t += offset;
469 t->compListIndx = freeIndx;
470
471 #if 0
472 /* pre-paging code */
473 t = (RMimage *)(global_RMimagePool->objectPool);
474 t += freeIndx;
475 t->compListIndx = freeIndx;
476 #endif
477
478 return (t);
479 }
480
481 /* PRIVATE */
482 RMenum
private_rmImageDelete(RMimage * r)483 private_rmImageDelete(RMimage *r)
484 {
485 extern RMcompMgrHdr *global_RMimagePool;
486 int indx;
487
488 /* first, free up any pixel data associated with the RMimage object */
489
490 if (private_rmImageGetCopyFlag(r) == RM_COPY_DATA)
491 free((void *)(r->pixeldata));
492 else
493 {
494 void (*appfunc)(void *);
495
496 appfunc = r->appfreefunc;
497 if (appfunc != NULL)
498 (*appfunc)((void *)(r->pixeldata));
499 }
500
501 /* assign a NULL vismap object to the RMimage - this will free any
502 pre-existing RMvisMap object that may be associated with the RMimage */
503 rmImageSetVismap(r, NULL);
504
505 /* update the free list - the newly freed item goes to the
506 start of the free list */
507 indx = r->compListIndx;
508 /* validity checks on indx? */
509
510 private_rmAllocToFree(global_RMimagePool, indx);
511
512 return(RM_CHILL);
513 }
514
515
516 /* PRIVATE */
517 void
private_rmDeleteComponentManager(RMcompMgrHdr * t)518 private_rmDeleteComponentManager(RMcompMgrHdr *t)
519 {
520 int i;
521
522 if (RM_ASSERT(t,"private_rmDeleteComponentManager error: the input RMcompMgrHdr is NULL! \n") == RM_WHACKED)
523 return;
524
525 for (i=0;i<t->numPages;i++)
526 {
527 if ((t->objectPool[i]) == NULL)
528 rmWarning("private_rmDeleteComponentManager() warning: a page in the objectPool is unexpectedly not NULL!");
529 else
530 {
531 free((void *)(t->objectPool[i]));
532 t->objectPool[i] = NULL;
533 }
534 }
535
536 rmMutexDelete(t->guard);
537
538 free((void *)(t->objectPool));
539 free((void *)(t->metaListHead));
540 free((void *)t);
541 }
542
543 /* PRIVATE */
544 RMnode *
private_rmNodeNew(void)545 private_rmNodeNew(void)
546 {
547 /*
548 *
549 */
550 extern RMcompMgrHdr *global_RMnodePool;
551 int freeIndx;
552 RMnode *t = NULL;
553
554 if (RM_ASSERT(global_RMnodePool, "Please call rmInit() prior to creating RMnode objects. \n") == RM_WHACKED)
555 return(NULL);
556
557 freeIndx = private_rmFreeToAlloc(global_RMnodePool,"private_rmNodeNew() - all RMnode objects have been used.");
558
559 if (freeIndx == -1)
560 return(NULL);
561
562 /* return RMnode handle to caller */
563
564 {
565 int pageNum = rmCompManagerGetPage(freeIndx);
566 int offset = rmCompManagerGetOffset(freeIndx);
567
568 t = (RMnode *)(global_RMnodePool->objectPool[pageNum]);
569 t += offset;
570 t->compListIndx = freeIndx;
571 }
572
573 return (t);
574 }
575
576 /* PRIVATE */
577 RMenum
private_rmNodeDelete(RMnode * r)578 private_rmNodeDelete(RMnode *r)
579 {
580 extern RMcompMgrHdr *global_RMnodePool;
581 int indx;
582
583 /* first, free up any data associated with the RMnode object */
584
585 /* need: check to see if refcount is zero */
586 if (private_rmNodeGetRefcount(r) != 0)
587 return(RM_WHACKED);
588
589 if ((r->clientData) && (r->clientDataFreeFunc))
590 {
591 void (*cfunc)();
592
593 cfunc = r->clientDataFreeFunc;
594 (*cfunc)(r, rmNodeGetClientData(r));
595 }
596
597 if (r->scene_parms != NULL) /* free up scene parms */
598 {
599 int i;
600
601 if (r->scene_parms->viewport)
602 free((void *)(r->scene_parms->viewport));
603
604 if (r->scene_parms->camera3d)
605 rmCamera3DDelete(r->scene_parms->camera3d);
606
607 if (r->scene_parms->camera2d)
608 rmCamera2DDelete(r->scene_parms->camera2d);
609
610 if (r->scene_parms->haveAnyTextures == RM_TRUE)
611 {
612 int i;
613 for (i=0; i <= RM_MAX_MULTITEXTURES; i++)
614 if (r->scene_parms->textures[i] != NULL)
615 rmTextureDelete(r->scene_parms->textures[i],RM_TRUE);
616 }
617
618 if (r->scene_parms->cp0 != NULL)
619 rmClipPlaneDelete(r->scene_parms->cp0);
620
621 if (r->scene_parms->cp1 != NULL)
622 rmClipPlaneDelete(r->scene_parms->cp1);
623
624 if (r->scene_parms->cp2 != NULL)
625 rmClipPlaneDelete(r->scene_parms->cp2);
626
627 if (r->scene_parms->cp3 != NULL)
628 rmClipPlaneDelete(r->scene_parms->cp3);
629
630 if (r->scene_parms->cp4 != NULL)
631 rmClipPlaneDelete(r->scene_parms->cp4);
632
633 if (r->scene_parms->cp5 != NULL)
634 rmClipPlaneDelete(r->scene_parms->cp5);
635
636 if (r->scene_parms->lmodel)
637 rmLightModelDelete(r->scene_parms->lmodel);
638
639 for (i = 0; i < RM_MAX_LIGHTS; i++)
640 if (r->scene_parms->lightSources[i] != NULL)
641 rmLightDelete(r->scene_parms->lightSources[i]);
642
643 if (r->scene_parms->textProps != NULL)
644 rmTextPropsDelete(r->scene_parms->textProps);
645
646 free((void *)(r->scene_parms));
647 }
648 if (r->sprops != NULL) /* free up scene props */
649 {
650 if (r->sprops->ambient_color != NULL)
651 free((void *)(r->sprops->ambient_color));
652
653 if (r->sprops->diffuse_color != NULL)
654 free((void *)(r->sprops->diffuse_color));
655
656 if (r->sprops->specular_color != NULL)
657 free((void *)(r->sprops->specular_color));
658
659 if (r->sprops->unlit_color != NULL)
660 free((void *)(r->sprops->unlit_color));
661
662 if (r->sprops->specular_exponent != NULL)
663 free((void *)(r->sprops->specular_exponent));
664
665 if (r->sprops->opacity != NULL)
666 free((void *)(r->sprops->opacity));
667
668 free((void *)(r->sprops));
669 }
670 if (r->rprops != NULL) /* free up rendermode props */
671 {
672 if (r->rprops->shademodel != NULL)
673 free((void *)(r->rprops->shademodel));
674
675 if (r->rprops->poly_mode_face)
676 free((void *)(r->rprops->poly_mode_face));
677
678 if (r->rprops->poly_mode_drawstyle)
679 free((void *)(r->rprops->poly_mode_drawstyle));
680
681 if (r->rprops->cull_mode)
682 free((void *)(r->rprops->cull_mode));
683
684 if (r->rprops->front_face)
685 free((void *)(r->rprops->front_face));
686
687 if (r->rprops->pointsize)
688 free((void *)(r->rprops->pointsize));
689
690 if (r->rprops->linewidth)
691 free((void *)(r->rprops->linewidth));
692
693 if (r->rprops->linestyle)
694 free((void *)(r->rprops->linestyle));
695
696 if (r->rprops->normalizeNormals)
697 free((void *)(r->rprops->normalizeNormals));
698
699 free((void *)(r->rprops));
700 }
701
702 if (r->fbClear != NULL)
703 {
704 if (r->fbClear->bgColor)
705 free((void *)(r->fbClear->bgColor));
706
707 if (r->fbClear->bgImageTile)
708 rmImageDelete(r->fbClear->bgImageTile);
709
710 if (r->fbClear->depthValue != NULL)
711 free((void *)(r->fbClear->depthValue));
712
713 if (r->fbClear->depthImage != NULL)
714 rmImageDelete(r->fbClear->depthImage);
715
716 free((void *)(r->fbClear));
717 }
718
719 if (r->transforms != NULL)
720 {
721 void private_rmNodeTransformsDelete(internals_RMtransformationStruct *t);
722
723 private_rmNodeTransformsDelete(r->transforms);
724 }
725 {
726 int nprims, i;
727
728 /* now delete all the prims */
729 nprims = rmNodeGetNumPrims(r);
730 for (i=0; i < nprims; i++)
731 rmPrimitiveDelete((RMprimitive *)rmNodeGetPrimitive(r, i));
732 free((void *)r->prims);
733 }
734 if (r->children)
735 free((void *)r->children);
736
737 /* update the free list - the newly freed item goes to the
738 start of the free list */
739 indx = r->compListIndx;
740 /* validity checks on indx? */
741
742 private_rmAllocToFree(global_RMnodePool, indx);
743
744 return(RM_CHILL);
745 }
746
747 /* PRIVATE */
748 RMprimitive *
private_rmPrimitiveNew(void)749 private_rmPrimitiveNew(void)
750 {
751 /*
752 *
753 */
754 extern RMcompMgrHdr *global_RMprimitivePool;
755 int freeIndx;
756 RMprimitive *t;
757
758 if (RM_ASSERT(global_RMprimitivePool, "Please call rmInit() prior to creating RMprimitive objects. \n") == RM_WHACKED)
759 return(NULL);
760
761 freeIndx = private_rmFreeToAlloc(global_RMprimitivePool,"private_rmPrimitiveNew() - all RMprimitive objects have been used.");
762
763 if (freeIndx == -1)
764 return(NULL);
765
766 /* return RMprimitive handle to caller */
767 {
768 int pageNum = rmCompManagerGetPage(freeIndx);
769 int offset = rmCompManagerGetOffset(freeIndx);
770
771 t = (RMprimitive *)(global_RMprimitivePool->objectPool[pageNum]);
772 t += offset;
773 t->compListIndx = freeIndx;
774 }
775
776 t->cacheKey = t->utilCacheKey = RM_CACHEKEY_UNINITIALIZED_VALUE;
777
778 return (t);
779 }
780
781 /* PRIVATE */
782 RMenum
private_rmPrimitiveDelete(RMprimitive * r)783 private_rmPrimitiveDelete(RMprimitive *r)
784 {
785 extern RMcompMgrHdr *global_RMprimitivePool;
786 int indx;
787
788 /* first, free up any data associated with the RMprimitive object */
789
790 if ((r->clientData) && (r->clientDataFreeFunc))
791 {
792 void (*cfunc)();
793
794 cfunc = r->clientDataFreeFunc;
795 (*cfunc)(r, rmPrimitiveGetClientData(r));
796 }
797
798 /* delete the bbox, if present */
799 if (r->bmin)
800 free((void *)(r->bmin));
801
802 if (r->bmax)
803 free((void *)(r->bmax));
804
805 /* free all blobs */
806 {
807 int i;
808 void (*freefunc)();
809 RMprimitiveDataBlob *b;
810
811 for (i = 0; i < RM_MAXBLOBS_PER_PRIMITIVE; i++)
812 {
813 b = &(r->blobs[i]);
814
815 if (b->appfreefunc != NULL)
816 {
817 freefunc = b->appfreefunc;
818 (*freefunc)(b->ptr);
819 }
820 else
821 if (b->ptr != NULL)
822 free(b->ptr);
823 }
824 }
825
826 /* now free the weird stuff that's wedged into the cracks.. */
827 if ((r->type == RM_BITMAP) || (r->type == RM_INDEXED_BITMAP))
828 {
829 int i;
830 RMbitmap **bmp_list, *bmp;
831
832 bmp_list = (RMbitmap **)(r->p1);
833
834 /* flags1 is unsigned */
835 for (i = 0; i < (int)(r->flags1); i++)
836 {
837 bmp = bmp_list[i];
838 rmBitmapDelete(bmp);
839 }
840 free((void *)bmp_list);
841 }
842 else if ((r->type == RM_TEXT) || (r->type == RM_INDEXED_TEXT))
843 {
844 int nstrings, i;
845 RMtextPrim *tp;
846
847 tp = (RMtextPrim *)(r->p1);
848 nstrings = r->flags1;
849
850 for (i = 0; i < nstrings; i++)
851 free((void *)(tp[i].string));
852
853 free((void *)(r->p1));
854 }
855 else if (r->type == RM_SPRITE)
856 {
857 if (r->p1)
858 {
859 int i, n;
860 RMimage *img, **sprite_list;
861
862 private_rmPrimitiveGetItem(r, RM_PRIMITIVE_SPRITES, &n, (void **)&sprite_list);
863
864 for (i = 0; i < n; i++)
865 {
866 img = sprite_list[i];
867 rmImageDelete(img);
868 }
869
870 free((void *)(r->p1));
871 r->flags1 = 0;
872 }
873 }
874 else if (r->type == RM_OCTMESH)
875 {
876 /* free octmesh-specific stuff */
877 private_rmOctmeshPrimitiveFree(r);
878 }
879 else if (r->type == RM_MARKERS2D) /* thanks Alex, 3/2005 */
880 {
881 if (r->p1)
882 rmInternalMarker2DDelete(r->p1);
883 }
884
885 /* delete blobs */
886 free((void *)r->blobs);
887
888 /* update the free list - the newly freed item goes to the
889 start of the free list */
890 indx = r->compListIndx;
891 /* validity checks on indx? */
892
893 private_rmAllocToFree(global_RMprimitivePool, indx);
894
895 return(RM_CHILL);
896 }
897
898 /* PRIVATE */
899 RMtexture *
private_rmTextureNew(void)900 private_rmTextureNew(void)
901 {
902 /*
903 *
904 */
905 extern RMcompMgrHdr *global_RMtexturePool;
906 int freeIndx;
907 RMtexture *t;
908
909 if (RM_ASSERT(global_RMtexturePool, "Please call rmInit() prior to creating RMtexture objects. \n") == RM_WHACKED)
910 return(NULL);
911
912 freeIndx = private_rmFreeToAlloc(global_RMtexturePool,"private_rmTextureNew() - all RMtexture objects have been used.");
913
914 if (freeIndx == -1)
915 return(NULL);
916
917 /* return RMtexture handle to caller */
918 {
919 int pageNum = rmCompManagerGetPage(freeIndx);
920 int offset = rmCompManagerGetOffset(freeIndx);
921
922 t = (RMtexture *)(global_RMtexturePool->objectPool[pageNum]);
923 t += offset;
924 t->compListIndx = freeIndx;
925 }
926
927 return (t);
928 }
929
930 /* PRIVATE */
931 RMenum
private_rmTextureDelete(RMtexture * r)932 private_rmTextureDelete(RMtexture *r)
933 {
934 extern RMcompMgrHdr *global_RMtexturePool;
935 int indx;
936
937 /* update the free list - the newly freed item goes to the
938 start of the free list */
939 indx = r->compListIndx;
940 /* validity checks on indx? */
941
942 private_rmAllocToFree(global_RMtexturePool, indx);
943
944 return(RM_CHILL);
945 }
946
947 /* PRIVATE */
948 void
private_rmPrimitiveSetCacheKey(RMprimitive * p)949 private_rmPrimitiveSetCacheKey(RMprimitive *p)
950 {
951 /* we could put a mutex here to force serial access. 10/2000 */
952 p->cacheKey = private_rmGetNewCacheKey();
953 }
954
955 /* PRIVATE */
956 void
private_rmTextureSetIDCacheKey(RMtexture * t)957 private_rmTextureSetIDCacheKey(RMtexture *t)
958 {
959 /* we could put a mutex here to force serial access. 10/2000 */
960 t->cacheKeyID = private_rmGetNewCacheKey();
961 }
962
963 /* PRIVATE */
964 void
private_rmTextureSetDataCacheKey(RMtexture * t)965 private_rmTextureSetDataCacheKey(RMtexture *t)
966 {
967 /* we could put a mutex here to force serial access. 10/2000 */
968 t->cacheKeyData = private_rmGetNewCacheKey();
969 }
970
971 /* PRIVATE */
972 RMtextProps *
private_rmTextPropsNew(void)973 private_rmTextPropsNew(void)
974 {
975 /*
976 *
977 */
978 extern RMcompMgrHdr *global_RMtextPropsPool;
979 int freeIndx;
980 RMtextProps *t;
981
982 if (RM_ASSERT(global_RMtextPropsPool, "Please call rmInit() prior to creating RMtextProps objects. \n") == RM_WHACKED)
983 return(NULL);
984
985 freeIndx = private_rmFreeToAlloc(global_RMtextPropsPool,"private_rmTextPropsNew() - all RMtextProps objects have been used.");
986
987 if (freeIndx == -1)
988 return(NULL);
989
990 /* return RMtextProps handle to caller */
991
992 {
993 int pageNum = rmCompManagerGetPage(freeIndx);
994 int offset = rmCompManagerGetOffset(freeIndx);
995
996 t = (RMtextProps *)(global_RMtextPropsPool->objectPool[pageNum]);
997 t += offset;
998 t->compListIndx = freeIndx;
999 }
1000 #if 0
1001 t = (RMtextProps *)(global_RMtextPropsPool->objectPool);
1002 t += freeIndx;
1003 t->compListIndx = freeIndx;
1004 #endif
1005 return (t);
1006 }
1007
1008 /* PRIVATE */
1009 RMenum
private_rmTextPropsDelete(RMtextProps * r)1010 private_rmTextPropsDelete(RMtextProps *r)
1011 {
1012 extern RMcompMgrHdr *global_RMtextPropsPool;
1013 int indx;
1014
1015 /* update the free list - the newly freed item goes to the
1016 start of the free list */
1017 indx = r->compListIndx;
1018 /* validity checks on indx? */
1019
1020 private_rmAllocToFree(global_RMtextPropsPool, indx);
1021
1022 return(RM_CHILL);
1023 }
1024
1025 /* PRIVATE */
1026 void
private_rmComponentManagerStatus(void)1027 private_rmComponentManagerStatus(void)
1028 {
1029 extern RMcompMgrHdr *global_RMimagePool;
1030 extern RMcompMgrHdr *global_RMprimitivePool;
1031 extern RMcompMgrHdr *global_RMnodePool;
1032 extern RMcompMgrHdr *global_RMtexturePool;
1033 extern RMcompMgrHdr *global_RMtextPropsPool;
1034 RMcompMgrHdr *t;
1035
1036 char buf[2048], buf2[256];
1037
1038 sprintf(buf,"\tComponent Manager Status \n");
1039 strcat(buf,"\t\tAlloc \tFree \tPoolSize \n");
1040
1041 t = global_RMimagePool;
1042 sprintf(buf2,"RMimages\t%d \t%d \t%d \n",t->numAlloc, t->numFree, t->currentPoolSize);
1043 strcat(buf, buf2);
1044
1045 t = global_RMprimitivePool;
1046 sprintf(buf2,"RMprimitives\t%d \t%d \t%d \n",t->numAlloc, t->numFree, t->currentPoolSize);
1047 strcat(buf, buf2);
1048
1049 t = global_RMnodePool;
1050 sprintf(buf2,"RMnodes \t%d \t%d \t%d \n",t->numAlloc, t->numFree, t->currentPoolSize);
1051 strcat(buf, buf2);
1052
1053 t = global_RMtexturePool;
1054 sprintf(buf2,"RMtextures\t%d \t%d \t%d \n",t->numAlloc, t->numFree, t->currentPoolSize);
1055 strcat(buf, buf2);
1056
1057 t = global_RMtextPropsPool;
1058 sprintf(buf2,"RMtextProps\t%d \t%d \t%d \n",t->numAlloc, t->numFree, t->currentPoolSize);
1059 strcat(buf, buf2);
1060
1061 rmNotice(buf);
1062 }
1063 /* EOF */
1064