FreeWRL / FreeX3D 4.3.0
CRoutes.c
1/*
2
3
4???
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28#include <config.h>
29#include <system.h>
30#include <system_threads.h>
31#include <display.h>
32#include <internal.h>
33
34#include <libFreeWRL.h>
35
36
37#include "../vrml_parser/Structs.h"
38#include "../main/headers.h"
39#include "CParseGeneral.h"
40#include "../scenegraph/Vector.h"
41#include "../vrml_parser/CFieldDecls.h"
42#include "../world_script/JScript.h"
43#include "../world_script/CScripts.h"
44#include "../world_script/fieldGet.h"
45#include "../world_script/fieldSet.h"
46#include "CParseParser.h"
47#include "CParseLexer.h"
48#include "../input/SensInterps.h"
49#include "../scenegraph/Component_ProgrammableShaders.h"
50#include "../input/EAIHeaders.h"
51#include "../input/EAIHelpers.h" /* for verify_Uni_String */
52#ifdef HAVE_OPENCL
53#include "../opencl/OpenCL_Utils.h"
54#endif //HAVE_OPENCL
55
56
57#include "CRoutes.h"
58//#define CRVERBOSE 1
59
60/* static void Multimemcpy (struct X3D_Node *toNode, struct X3D_Node *fromNode, void *tn, void *fn, size_t multitype); */
61
62/* fix usage-before-definition for this function */
63#ifdef HAVE_OPENCL
64static bool canRouteOnGPUTo(struct X3D_Node *me);
65#endif
66
68//static int thisIntTimeStamp = 1;
69
70/* declared and defined in fieldGet.c(.h) , do not declare it here */
71/* void setMFElementtype (int num); */
72
73/*****************************************
74C Routing Methodology:
75
76Different nodes produce eventins/eventouts...
77
78 EventOuts only:
79 MovieTexture
80 AudioClip
81 TimeSensor
82 TouchSensor
83 PlaneSensor
84 SphereSensor
85 CylinderSensor
86 VisibilitySensor
87 ProximitySensor
88 GeoProximitySensor
89
90 EventIn/EventOuts:
91 ScalarInterpolator
92 OrientationInterpolator
93 ColorInterpolator
94 PositionInterpolator
95 GeoPositionInterpolator
96 NormalInterpolator
97 CoordinateInterpolator
98 Fog
99 Background
100 Viewpoint
101 NavigationInfo
102 Collision
103
104 EventIns only:
105 Almost everything else...
106
107
108 Nodes with ClockTicks:
109 MovieTexture, AudioClip, TimeSensor,
110 ProximitySensor, Collision, ...?
111
112 Nodes that have the EventsProcessed method:
113 ScalarInterpolator, OrientationInterpolator,
114 ColorInterpolator, PositionInterpolator,
115 NormalInterpolator, (should be all the interpolators)
116 .... ??
117
118
119
120
121 --------------------------------------------------------------------------
122 C Routes are stored in a table with the following entries:
123 Fromnode - the node that created an event address
124 actual ptr - pointer to the exact field within the address
125 Tonode - destination node address
126 actual ptr - pointer to the exact field within the address
127 active - True of False for each iteration
128 length - data field length
129 interpptr - pointer to an interpolator node, if this is one
130
131
132
133 SCRIPTS handled like this:
134
135 1) a call is made to CRoutes_js_new (num,cx,glob,brow);
136 with the script number (0 on up), script context, script globals,
137 and browser data.
138
139 2) Initialize called;
140
141
142 3) scripts that have eventIns have the values copied over and
143 sent to the script by the routine "sendScriptEventIn".
144
145 4) scripts that have eventOuts have the eventOut values copied over
146 and acted upon by the routine "gatherScriptEventOuts".
147
148
149******************************************/
151//struct CRStruct *_CRoutes;
152//static int CRoutes_Initiated = FALSE;
153//int CRoutes_Count;
154//int CRoutes_MAX;
155
156
157
159//struct CRscriptStruct *_ScriptControl = 0; /* global objects and contexts for each script */
160//int *scr_act = 0; /* this script has been sent an eventIn */
161//int max_script_found = -1; /* the maximum script number found */
162//int max_script_found_and_initialized = -1; /* the maximum script number found */
163
164
165/* ClockTick structure for processing all of the initevents - eg, TimeSensors */
167 void * tonode;
168 void (*interpptr)(void *);
169};
170
171
172
173/* We buffer route registrations, JUST in case a registration comes from executing a route; eg,
174from within a Javascript function invocation createVrmlFromURL call that was invoked by a routing
175call */
176
178 int adrem;
179 struct X3D_Node *from;
180 int fromoffset;
181 struct X3D_Node *to;
182 int toOfs;
183 int fieldType;
184 void *intptr;
185 int scrdir;
186 void *extra;
187#ifdef HAVE_OPENCL
188 cl_kernel CL_Interpolator;
189#endif //HAVE_OPENCL
190};
191
192
193//static struct Vector* routesToRegister = NULL;
194
195
196/* if we get mark_events sent, before routing is established, save them and use them
197 as soon as routing is here */
198#define POSSIBLEINITIALROUTES 1000
199//static int initialEventBeforeRoutesCount = 0;
200//static int preRouteTableSize = 0;
202 struct X3D_Node *from;
203 size_t totalptr;
204};
205//static struct initialRouteStruct *preEvents = NULL;
206//pthread_mutex_t preRouteLock = PTHREAD_MUTEX_INITIALIZER;
207#define LOCK_PREROUTETABLE pthread_mutex_lock(&p->preRouteLock);
208#define UNLOCK_PREROUTETABLE pthread_mutex_unlock(&p->preRouteLock);
209
210//pthread_mutex_t insertRouteLock = PTHREAD_MUTEX_INITIALIZER;
211#define MUTEX_LOCK_ROUTING_UPDATES pthread_mutex_lock(&p->insertRouteLock);
212#define MUTEX_FREE_LOCK_ROUTING_UPDATES pthread_mutex_unlock(&p->insertRouteLock);
213
214
215
216
217typedef struct pCRoutes{
218 /* ClockTick structure and counter */
219 struct FirstStruct *ClockEvents;// = NULL;
220 int num_ClockEvents;// = 0;
221 int size_ClockEvents;
222 int CRoutes_Initiated;// = FALSE;
223 int CRoutes_Count;
224 int CRoutes_MAX;
225 int initialEventBeforeRoutesCount;// = 0;
226 int preRouteTableSize;// = 0;
227 struct initialRouteStruct *preEvents;// = NULL;
228 pthread_mutex_t preRouteLock;// = PTHREAD_MUTEX_INITIALIZER;
229 struct Vector* routesToRegister;// = NULL;
230 pthread_mutex_t insertRouteLock;// = PTHREAD_MUTEX_INITIALIZER;
231 /* we count times through the scenegraph; helps to break routing loops */
232 int thisIntTimeStamp;// = 1;
233 /* Routing table */
234 struct CRStruct *CRoutes;
235 /* Structure table */
236 //struct CRscriptStruct *ScriptControl;// = 0; /* global objects and contexts for each script */
237 struct Vector* ScriptControl;
238 //int *scr_act;// = 0; /* this script has been sent an eventIn */
239
240 int JSMaxScript;// = 0;
241 /* Script name/type table */
242 struct CRjsnameStruct *JSparamnames;// = NULL;
243
244
245}* ppCRoutes;
246void *CRoutes_constructor(){
247 void *v = MALLOCV(sizeof(struct pCRoutes));
248 memset(v,0,sizeof(struct pCRoutes));
249 return v;
250}
251void CRoutes_init(struct tCRoutes *t){
252 //public
253 /* EAI needs the extra parameters, so we put it globally when a RegisteredListener is clicked. */
254 t->CRoutesExtra = NULL;
255 //t->scr_act = 0; /* this script has been sent an eventIn */
256 t->max_script_found = -1; /* the maximum script number found */
257 t->max_script_found_and_initialized = -1; /* the maximum script number found */
258 t->jsnameindex = -1;
259 t->MAXJSparamNames = 0;
260
261 //private
262 t->prv = CRoutes_constructor();
263 {
264 ppCRoutes p = (ppCRoutes)t->prv;
265 /* ClockTick structure and counter */
266 p->size_ClockEvents = 1; //pre-allocated size (will be power of 2)
267 p->ClockEvents = MALLOC(struct FirstStruct*, p->size_ClockEvents * sizeof(struct FirstStruct));
268 p->num_ClockEvents = 0;
269 p->CRoutes_Initiated = FALSE;
270 //p->CRoutes_Count;
271 //p->CRoutes_MAX;
272 p->initialEventBeforeRoutesCount = 0;
273 p->preRouteTableSize = 0;
274 p->preEvents = NULL;
275 //pthread_mutex_t preRouteLock = PTHREAD_MUTEX_INITIALIZER;
276 pthread_mutex_init(&(p->preRouteLock), NULL);
277 p->routesToRegister = NULL;
278 //pthread_mutex_t insertRouteLock = PTHREAD_MUTEX_INITIALIZER;
279 pthread_mutex_init(&(p->insertRouteLock), NULL);
280 /* we count times through the scenegraph; helps to break routing loops */
281 p->thisIntTimeStamp = 1;
282 /* Routing table */
283 //p->CRoutes;
284 /* Structure table */
285 //p->ScriptControl = 0; /* global objects and contexts for each script */
286 p->ScriptControl = newVector(struct CRscriptControl*,0);
287 //p->scr_act = NULL;// = 0; /* this script has been sent an eventIn */
288 p->JSMaxScript = 0;
289 /* Script name/type table */
290 p->JSparamnames = NULL;
291
292 }
293}
294
295void lock_and_do_routes_register();
296void free_routes(){
297 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
298
299 //there can be some routes to unregister, on quit
300 lock_and_do_routes_register();
301
302 p->CRoutes_Count = 0;
303 p->CRoutes_MAX = 0;
304 FREE_IF_NZ(p->CRoutes);
305 p->CRoutes = NULL;
306
307}
308void CRoutes_clear(struct tCRoutes *t){
309 if(t){
310 ppCRoutes p = (ppCRoutes)t->prv;
311 free_routes();
312 FREE_IF_NZ(p->ClockEvents);
313 FREE_IF_NZ(p->preEvents);
314 //FREE_IF_NZ(p->ScriptControl);
315 }
316}
317// ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
318struct CRStruct *getCRoutes()
319{
320 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
321 return p->CRoutes;
322}
323int getCRouteCount(){
324 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
325 return p->CRoutes_Count;
326}
327int *getCRouteCounter(){
328 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
329 return &p->CRoutes_Count;
330}
331
332
333
334/* a Script (JavaScript or CLASS) has given us an event, tell the system of this */
335/* tell this node now needs to redraw - but only if it is not a script to
336 script route - see CRoutes_Register here, and check for the MALLOC in that code.
337 You should see that the offset is zero, while in real nodes, the offset of user
338 accessible fields is NEVER zero - check out CFuncs/Structs.h and look at any of
339 the node types, eg, X3D_IndexedFaceSet the first offset is for X3D_Virt :=)
340*/
341
342void markScriptResults(struct X3D_Node * tn, int tptr, int route, void * tonode) {
343 ppCRoutes p;
344 ttglobal tg = gglobal();
345 p = (ppCRoutes)tg->CRoutes.prv;
346
347 if (tptr != 0) {
348 #ifdef CRVERBOSE
349 printf ("markScriptResults: can update this node %p %d\n",tn,tptr);
350 #endif
351 update_node(tn);
352 #ifdef CRVERBOSE
353 } else {
354 printf ("markScriptResults: skipping this node %p %d flag %d\n",tn,tptr,p->CRoutes[route].direction_flag);
355 #endif
356 }
357
358 MARK_EVENT (p->CRoutes[route].routeFromNode,p->CRoutes[route].fnptr);
359
360 /* run an interpolator, if one is attached. */
361 if (p->CRoutes[route].interpptr != 0) {
362 /* this is an interpolator, call it */
363 tg->CRoutes.CRoutesExtra = p->CRoutes[route].extra; /* in case the interp requires it... */
364 #ifdef CRVERBOSE
365 printf ("script propagate_events. index %d is an interpolator\n",route);
366 #endif
367 p->CRoutes[route].interpptr(tonode);
368 }
369}
370
371
372void AddRemoveSFNodeFieldChild(
373 struct X3D_Node *parent,
374 struct X3D_Node **tn, //target SFNode field
375 struct X3D_Node *child, //node to set,add or remove from parent
376 int ar, //0=set,1=add,2=remove
377 char *file,
378 int line) {
379
380/*
381ConsoleMessage ("AddRemoveSFNodeFieldChild called at %s:%d",file,line);
382ConsoleMessage ("AddRemoveSFNodeFieldChild, parent %p, child to add offset %p, child to add %p ar %d",parent,tn,child,ar);
383if (child!=NULL) ConsoleMessage ("AddRemoveSFNodeFieldChild, parent is a %s, child is a %s",stringNodeType(parent->_nodeType), stringNodeType(child->_nodeType));
384if (*tn == NULL) ConsoleMessage ("toNode field is NULL"); else {ConsoleMessage ("tn field is ptr %p",*tn); ConsoleMessage ("and it ias %s",stringNodeType(X3D_NODE(*tn)->_nodeType));}
385*/
386
387 if ((parent==NULL) || (child == NULL)) {
388 //printf ("Freewrl: AddRemoveSFNodeFieldChild, parent and/or child NULL\n");
389 return;
390 }
391
392
393 /* mark the parent changed, eg, rootNode() will not be sorted if this is not marked */
394 parent->_change ++;
395
396 // Note that, with SFNodeFields, either a "set" or an "add" do the same thing, as
397 // we only have 1 child. MFNodes are different, but we keep the same calling conventions
398 // as AddRemoveChildren for simplicity
399
400 if ((ar == 0) || (ar == 1)) {
401 #ifdef CRVERBOSE
402 printf ("we have to perform a \"set_child\" on this field\n");
403 # endif
404
405 /* go to the old child, and tell them that they are no longer wanted here */
406 if (*tn != NULL) remove_parent(*tn,parent);
407
408 /* addChild - now lets add */
409 *tn = child;
410 ADD_PARENT(child,parent);
411 } else {
412 /* this is a removeChild - check to see if child is correct. We might have
413 a removeChild of NULL, for instance */
414
415 if (child != NULL) {
416 if(child == *tn){
417 remove_parent(*tn,parent);
418 *tn = NULL;
419 } else {
420 if ((*tn != NULL) && (child->referenceCount > 0)) {
421 ConsoleMessage (".... ARSF, requested child to remove is %p %s ref %d as a child",child,stringNodeType(child->_nodeType),
422 child->referenceCount);
423 }
424
425 }
426 }
427 }
428 update_node(parent);
429}
430
431/****************************************************************/
432/* Add or Remove a series of children */
433/* */
434/* pass in a pointer to a node, (see Structs.h for defn) */
435/* a pointer to the actual field in that node, */
436/* a list of node pointers, in memory, */
437/* the length of this list, (ptr size, not bytes) */
438/* and a flag for add (1), remove (2) or replace (0) */
439/* */
440/****************************************************************/
441unsigned long upper_power_of_two(unsigned long v)
442{
443 v--;
444 v |= v >> 1;
445 v |= v >> 2;
446 v |= v >> 4;
447 v |= v >> 8;
448 v |= v >> 16;
449 v++;
450 return v;
451
452}
453unsigned long lower_power_of_two(unsigned long v)
454{
455 return upper_power_of_two(v - 1) / 2L;
456}
457
458void AddRemoveChildren (
459 struct X3D_Node *parent,
460 struct Multi_Node *tn,
461 struct X3D_Node * *nodelist,
462 int len,
463 int ar,
464 char *file,
465 int line) {
466 int oldlen;
467 void *newmal, *oldmal;
468 struct X3D_Node * *remchild;
469 struct X3D_Node * *remptr;
470 struct X3D_Node * *tmpptr;
471 int done;
472
473 int counter, c2;
474
475 #ifdef CRVERBOSE
476
477 printf ("\n start of AddRemoveChildren; parent is a %s at %p\n",stringNodeType(parent->_nodeType),parent);
478 printf ("AddRemove Children parent %p tn %p, len %d ar %d\n",parent,tn,len,ar);
479 printf ("called at %s:%d\n",file,line);
480 #endif
481
482 oldmal = NULL;
483
484 /* if no elements, just return */
485 if (len <=0) return;
486 if ((parent==0) || (tn == 0)) {
487 //printf ("Freewrl: AddRemoveChildren, parent and/or field NULL\n");
488 return;
489 }
490
491 /* mark the parent changed, eg, rootNode() will not be sorted if this is not marked */
492 parent->_change ++;
493
494
495 oldlen = tn->n;
496 #ifdef CRVERBOSE
497 printf ("AddRemoveChildren, len %d, oldlen %d ar %d\n",len, oldlen, ar);
498 #endif
499
500 /* to do a "set_children", we remove the children, then do an add */
501 if (ar == 0) {
502 #ifdef CRVERBOSE
503 printf ("we have to perform a \"set_children\" on this field\n");
504 # endif
505
506 /* make it so that we have 0 children */
507 tn->n=0;
508
509 /* go through the children, and tell them that they are no longer wanted here */
510 for (counter=0; counter < oldlen; counter ++) remove_parent(tn->p[counter],parent);
511
512 /* now, totally free the old children array */
513 if (oldlen > 0) {FREE_IF_NZ(tn->p);}
514
515 /* now, make this into an addChildren */
516 oldlen = 0;
517 ar = 1;
518
519 }
520
521
522 if (ar == 1) {
523 /* addChildren - now we know how many SFNodes are in this MFNode, lets MALLOC and add */
524 unsigned long p2new, p2old;
525 unsigned long old_len = (unsigned)(oldlen);
526 unsigned long new_len = (unsigned)(oldlen+len);
527 p2new = upper_power_of_two(new_len);
528 p2old = upper_power_of_two(old_len);
529
530 //if(upper_power_of_two(new_len) > upper_power_of_two(old_len))
531 //if(1)
532 if(p2new > p2old)
533 {
534 //realloc to next power-of-2 and copy over
535 // the power-of-2 strategy means we 'anticipate' storage based on how much we've already used.
536 // if we used 128 already, then we allocate another 128. If we've used 256 we allocate
537 // another 256 - always doubling. That means wasted memory, but fewer reallocs, and
538 // therefore less memory fragmentation than if we right-sized on each realloc.
539 // (there was a dataset at http://r1.3crowd.com/blyon/opte/maps/raw/1069524880.3D.wrl
540 // that was very large and malloc failed not due to absolute out-of-memory,
541 // but rather due to fragmentation in AddRemoveChildren -reallocing for each 1 additional node-
542 // causing malloc to return null after ~35000 of ~78000 children were added one at a time)
543 unsigned long po2 = upper_power_of_two(new_len);
544 /* first, set children to 0, in case render thread comes through here */
545 tn->n = 0;
546 #ifdef CRVERBOSE
547 printf("[%d]{%u}",oldlen,upper_power_of_two(old_len));
548 #endif
549 //newmal = MALLOC (void *, (oldlen+len)*sizeof(struct X3D_Node *));
550#if defined(DEBUG_MALLOC) && defined(DEBUG_MALLOC_LIST)
551 newmal = (void*)freewrlMalloc(line, file, (po2)*sizeof(struct X3D_Node *), FALSE);
552#else
553 newmal = MALLOC (void *, (po2)*sizeof(struct X3D_Node *));
554#endif
555
556 /* copy the old stuff over */
557 if (newmal != NULL && oldlen > 0) memcpy (newmal,tn->p,oldlen*sizeof(void *));
558
559 /* set up the C structures for this new MFNode addition */
560 //if(oldlen > 0) {
561 //FREE_IF_NZ (tn->p); //see bottom of function
562 oldmal = tn->p; //may 2015 - needs to be unconditionally freed, for geoLod which can pull tricks with geoLod.rootNode.p
563 //}
564 tn->n = oldlen;
565 tn->p = newmal;
566 FREE_IF_NZ(oldmal); //ATOMIC OP but if the rendering thread is hanging onto mf->p for a long time, you'll be 'pulling the rug out' here - use addChildren
567 }else{
568 /*already alloced - just add to end*/
569 newmal = tn->p;
570 tn->n = oldlen;
571 }
572
573 /* copy the new stuff over - note, tmpptr changes what it points to */
574 tmpptr = offsetPointer_deref(struct X3D_Node * *,newmal, sizeof(struct X3D_Node *) * oldlen);
575
576 /* tell each node in the nodelist that it has a new parent */
577 for (counter = 0; counter < len; counter++) {
578 #ifdef CRVERBOSE
579 printf ("AddRemove, count %d of %d, node %p parent %p\n",counter, len,nodelist[counter],parent);
580 #endif
581 if (tmpptr != NULL && nodelist[counter] != NULL) {
582 //add a new node to the children list
583 *tmpptr = nodelist[counter];
584 tmpptr ++;
585 tn->n++;
586 //add new parent to new node
587 ADD_PARENT((void *)nodelist[counter],(void *)parent);
588 } else {
589 /* gosh, we are asking to add a NULL node pointer, lets just skip it... */
590 printf ("AddRemoveChildren, Add, but new node is null; ignoring...\n");
591 }
592 }
593 /*
594 for (counter = 0; counter < tn->n; counter++) {
595 printf ("AddRemoveChildren, checking, we have index %d node %p\n",counter,tn->p[counter]);
596 }
597 */
598 } else {
599 int finalLength;
600 int num_removed;
601
602 /* this is a removeChildren */
603
604 /* go through the original array, and "zero" out children that match one of
605 the parameters */
606
607 num_removed = 0;
608 remchild = nodelist;
609 /* printf ("removing, len %d, tn->n %d\n",len,tn->n); */
610 for (c2 = 0; c2 < len; c2++) {
611 remptr = (struct X3D_Node * *) tn->p;
612 done = FALSE;
613
614 for (counter = 0; counter < tn->n; counter ++) {
615 #ifdef CRVERBOSE
616 printf ("remove, comparing %p with %p\n",*remptr, *remchild);
617 #endif
618 if ((*remptr == *remchild) && (!done)) {
619 #ifdef CRVERBOSE
620 printf ("Found it! removing this child from this parent\n");
621 #endif
622
623 remove_parent(X3D_NODE(*remchild),parent);
624 *remptr = NULL; /* "0" can not be a valid memory address */
625 num_removed ++;
626 done = TRUE; /* remove this child ONLY ONCE - in case it has been added
627 more than once. */
628 }
629 remptr ++;
630 }
631 remchild ++;
632 }
633
634
635 finalLength = oldlen - num_removed;
636 #ifdef CRVERBOSE
637 printf ("final length is %d, we have %d in original array\n", finalLength, tn->n);
638 remptr = (struct X3D_Node * *) tn->p;
639 printf ("so, the original array, with zeroed elements is: \n");
640 for (counter = 0; counter < tn->n; counter ++) {
641 printf ("count %d of %d is %p\n",counter,tn->n, *remptr);
642 remptr ++;
643 }
644 #endif
645
646
647 if (num_removed > 0) {
648 if (finalLength > 0) {
649 newmal = MALLOC (void *, finalLength*sizeof(struct X3D_Node * *));
650 bzero (newmal, (size_t)(finalLength*sizeof(struct X3D_Node * *)));
651 tmpptr = (struct X3D_Node * *) newmal;
652 remptr = (struct X3D_Node * *) tn->p;
653
654 /* go through and copy over anything that is not zero */
655 for (counter = 0; counter < tn->n; counter ++) {
656 /* printf ("count %d is %p\n",counter, *remptr); */
657 if (*remptr != NULL) {
658 *tmpptr = *remptr;
659 /* printf ("now, tmpptr is %p\n",*tmpptr); */
660 tmpptr ++;
661 }
662 remptr ++;
663 }
664 /* printf ("done loops, now make data active \n"); */
665
666 /* now, do the move of data */
667 tn->n = 0;
668 FREE_IF_NZ (tn->p);
669 tn->p = newmal;
670 tn->n = finalLength;
671 } else {
672 tn->n = 0;
673 FREE_IF_NZ(tn->p);
674 }
675
676 #ifdef CRVERBOSE
677 printf ("so, we have a final array length of %d\n",tn->n);
678 for (counter =0; counter <tn->n; counter ++) {
679 printf (" element %d is %p\n",counter,tn->p[counter]);
680 }
681 #endif
682
683 }
684
685 }
686
687 update_node(parent);
688 FREE_IF_NZ(oldmal); //ATOMIC OP but if the rendering thread is hanging onto mf->p for a long time, you'll be 'pulling the rug out' here - use addChildren
689
690}
691
692
693/* These events must be run first during the event loop, as they start an event cascade.
694 Regsister them with add_first, then call them during the event loop with do_first. */
695
696void kill_clockEvents() {
697 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
698
699 /* printf ("killing clckevents - was %d\n",num_ClockEvents); */
700 p->num_ClockEvents = 0;
701}
702void do_ColorChaserTick(void * ptr);
703void do_ColorDamperTick(void * ptr);
704void do_CoordinateChaserTick(void * ptr);
705void do_CoordinateDamperTick(void * ptr);
706void do_OrientationChaserTick(void * ptr);
707void do_OrientationDamperTick(void * ptr);
708void do_PositionChaserTick(void * ptr);
709void do_ColorDamperTick(void * ptr);
710void do_PositionChaserTick(void * ptr);
711void do_PositionDamperTick(void * ptr);
712void do_PositionChaser2DTick(void * ptr);
713void do_PositionDamper2DTick(void * ptr);
714void do_ScalarChaserTick(void * ptr);
715void do_ScalarDamperTick(void * ptr);
716void do_TexCoordChaser2DTick(void * ptr);
717void do_TexCoordDamper2DTick(void * ptr);
718void do_CollisionSensorTick(void * ptr);
719
720void add_first(struct X3D_Node * node) {
721 void (*myp)(void *);
722 int clocktype;
723 int count;
724 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
725
726 if (node == 0) {
727 printf ("error in add_first; somehow the node datastructure is zero \n");
728 return;
729 }
730
731 clocktype = node->_nodeType;
732 /* printf ("add_first for %s\n",stringNodeType(clocktype)); */
733 /*
734 if (NODE_TimeSensor == clocktype) { myp = do_TimeSensorTick;
735 } else if (NODE_ProximitySensor == clocktype) { myp = do_ProximitySensorTick;
736 } else if (NODE_Collision == clocktype) { myp = do_CollisionTick;
737 } else if (NODE_MovieTexture == clocktype) { myp = do_MovieTextureTick;
738 } else if (NODE_AudioClip == clocktype) { myp = do_AudioTick;
739 } else if (NODE_VisibilitySensor == clocktype) { myp = do_VisibilitySensorTick;
740 } else if (NODE_MovieTexture == clocktype) { myp = do_MovieTextureTick;
741 } else if (NODE_GeoProximitySensor == clocktype) { myp = do_GeoProximitySensorTick;
742
743 } else {
744 // printf ("this is not a type we need to add_first for %s\n",stringNodeType(clocktype));
745 return;
746 }
747 */
748 switch(clocktype){
749 case NODE_TimeSensor: myp = do_TimeSensorTick; break;
750 case NODE_ProximitySensor: myp = do_ProximitySensorTick; break;
751 case NODE_Collision: myp = do_CollisionTick; break;
752 case NODE_MovieTexture: myp = do_MovieTextureTick; break;
753 case NODE_AudioClip: myp = do_AudioTick; break;
754 case NODE_BufferAudioSource: myp = do_BufferAudioSourceTick; break;
755 case NODE_OscillatorSource: myp = do_OscillatorSourceTick; break;
756 case NODE_VisibilitySensor: myp = do_VisibilitySensorTick; break;
757 case NODE_TransformSensor: myp = do_TransformSensorTick; break;
758 case NODE_GeoProximitySensor: myp = do_GeoProximitySensorTick;break;
759 case NODE_ColorChaser: myp = do_ColorChaserTick; break;
760 case NODE_ColorDamper: myp = do_ColorDamperTick; break;
761 case NODE_CoordinateChaser: myp = do_CoordinateChaserTick; break;
762 case NODE_CoordinateDamper: myp = do_CoordinateDamperTick; break;
763 case NODE_OrientationChaser: myp = do_OrientationChaserTick; break;
764 case NODE_OrientationDamper: myp = do_OrientationDamperTick; break;
765 case NODE_PositionChaser: myp = do_PositionChaserTick; break;
766 case NODE_PositionDamper: myp = do_PositionDamperTick; break;
767 case NODE_PositionChaser2D: myp = do_PositionChaser2DTick; break;
768 case NODE_PositionDamper2D: myp = do_PositionDamper2DTick; break;
769 case NODE_ScalarChaser: myp = do_ScalarChaserTick; break;
770 case NODE_ScalarDamper: myp = do_ScalarDamperTick; break;
771 case NODE_TexCoordChaser2D: myp = do_TexCoordChaser2DTick; break;
772 case NODE_TexCoordDamper2D: myp = do_TexCoordDamper2DTick; break;
773 case NODE_LinePickSensor: myp = do_PickSensorTick; break;
774 case NODE_PointPickSensor: myp = do_PickSensorTick; break;
775 case NODE_PrimitivePickSensor: myp = do_PickSensorTick; break;
776 case NODE_VolumePickSensor: myp = do_PickSensorTick; break;
777 case NODE_CollisionSensor: myp = do_CollisionSensorTick; break;
778 default:
779 // printf ("this is not a type we need to add_first for %s\n",stringNodeType(clocktype));
780 return; //not a clocktype node
781 }
782
783 if (p->num_ClockEvents + 1 > p->size_ClockEvents){
784 //ATOMIC OPS - realloc in parsing thread (here) while display thread is in do_first()
785 //can cause do_first to bomb as it points to abandoned p->
786 //we don't have mutexes here (yet)
787 //so we break realloc into more atomic steps (and reduce frequency of reallocs with pre-allocated size_ )
788 struct FirstStruct *old_ce, *ce;
789 ce = MALLOC(struct FirstStruct *, sizeof (struct FirstStruct) * p->size_ClockEvents * 2);
790 if (ce != NULL)
791 {
792 memcpy(ce, p->ClockEvents, sizeof (struct FirstStruct) * p->num_ClockEvents);
793 }
794 p->size_ClockEvents *= 2; //power-of-two resizing means less memory fragmentation for large counts
795 old_ce = p->ClockEvents;
796 p->ClockEvents = ce;
797 FREE_IF_NZ(old_ce);
798 }
799 // p->ClockEvents = (struct FirstStruct *)REALLOC(p->ClockEvents, sizeof (struct FirstStruct) * (p->num_ClockEvents + 1));
800
801 if (p->ClockEvents == 0) {
802 printf ("can not allocate memory for add_first call\n");
803 p->num_ClockEvents = 0;
804 }
805
806 /* does this event exist? */
807 for (count=0; count < p->num_ClockEvents; count ++) {
808 if (p->ClockEvents[count].tonode == node) {
809 /* printf ("add_first, already have %d\n",node); */
810 return;
811 }
812 }
813
814 /* is there a free slot to slide this into? see delete_first */
815 for (count=0; count < p->num_ClockEvents; count ++) {
816 if (p->ClockEvents[count].tonode == NULL) {
817 /* printf ("add_first, already have %d\n",node); */
818 p->ClockEvents[count].interpptr = myp;
819 p->ClockEvents[count].tonode = node;
820 return;
821 }
822 }
823
824
825 /* now, put the function pointer and data pointer into the structure entry */
826 p->ClockEvents[p->num_ClockEvents].interpptr = myp;
827 p->ClockEvents[p->num_ClockEvents].tonode = node;
828
829 p->num_ClockEvents++;
830}
831
832/* go through, and delete this entry from the do_first list, if it exists */
833void delete_first(struct X3D_Node *node) {
834 int count;
835 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
836
837 if (p->ClockEvents) {
838 for (count=0; count < p->num_ClockEvents; count ++) {
839 if (p->ClockEvents[count].tonode == node) {
840 p->ClockEvents[count].tonode = NULL;
841 return;
842 }
843 }
844 }
845}
846
847
848
849
850
851
852/********************************************************************
853
854Register a route, but with fewer and more expressive parameters than
855CRoutes_Register. Currently a wrapper around that other function.
856
857********************************************************************/
858
859void CRoutes_RegisterSimple(
860 struct X3D_Node* from, int fromOfs,
861 struct X3D_Node* to, int toOfs,
862 int type) {
863 //printf ("CRoutes_RegisterSimple, registering a route of %s\n",stringFieldtypeType(type));
864
865 /* 10+1+3+1=15: Number <5000000000, :, number <999, \0 */
866 void* interpolatorPointer;
867 int dir = 0;
868
869
870 /* get direction flags here */
871 switch (from->_nodeType) {
872 case NODE_Script:
873 case NODE_ComposedShader:
874 case NODE_Effect:
875 case NODE_PackagedShader:
876 //JAS case NODE_ShaderProgram:
877 case NODE_ProgramShader:
878 dir = dir | FROM_SCRIPT; break;
879 default: {}
880 }
881 switch (to->_nodeType) {
882 case NODE_Script:
883 case NODE_ComposedShader:
884 case NODE_Effect:
885 case NODE_PackagedShader:
886 //JAS case NODE_ShaderProgram:
887 case NODE_ProgramShader:
888 dir = dir | TO_SCRIPT; break;
889 default: {}
890 }
891
892 /* check to ensure that we are not doing with a StaticGroup here */
893 if (dir!=SCRIPT_TO_SCRIPT && dir!=TO_SCRIPT) {
894 /* printf ("we are NOT sending to a script, checking for StaticGroup\n"); */
895 if (to->_nodeType == NODE_StaticGroup) {
896 ConsoleMessage ("ROUTE to a StaticGroup not allowed");
897 return;
898 }
899 }
900 /* check to ensure that we are not doing with a StaticGroup here */
901 if (dir!=SCRIPT_TO_SCRIPT && dir!=FROM_SCRIPT) {
902 /* printf ("we are NOT sending from a script, checking for StaticGroup\n"); */
903 if (from->_nodeType == NODE_StaticGroup) {
904 ConsoleMessage ("ROUTE from a StaticGroup not allowed");
905 return;
906 }
907 }
908
909 /* When routing to a script, to is not a node pointer! */
910 if(dir!=SCRIPT_TO_SCRIPT && dir!=TO_SCRIPT)
911 interpolatorPointer=returnInterpolatorPointer(to->_nodeType);
912 else
913 interpolatorPointer=NULL;
914 CRoutes_Register(1, from, fromOfs, to,toOfs, type, interpolatorPointer, dir, NULL);
915}
916int usesBuiltin(struct X3D_Node* node){
917 //builtin 1, user field 0
918 int retval = 1;
919 if(node){
920 switch(node->_nodeType){
921 case NODE_Script:
922 case NODE_ComposedShader:
923 case NODE_Effect:
924 case NODE_ShaderProgram :
925 case NODE_PackagedShader:
926 case NODE_Proto:
927 retval = 0; break;
928 default:
929 retval = 1; break;
930 }
931 }
932 return retval;
933}
934void CRoutes_RegisterSimpleB(
935 struct X3D_Node* from, int fromIndex, int fromBuiltIn,
936 struct X3D_Node* to, int toIndex, int toBuiltIn,
937 int type) {
938 //converts from field indexes to pointer offsets
939 int fromOfs,toOfs;
940
941 if(from && to){
942 fromOfs = fromIndex;
943 if(usesBuiltin(from) != fromBuiltIn)
944 printf("error usesBuiltin(from) != fromBuiltin\n");
945 if(usesBuiltin(to) != toBuiltIn)
946 printf("error usesBuiltin(to) != toBuiltin\n");
947 //if(usesBuiltin(from))
948 if(fromBuiltIn)
949 fromOfs = NODE_OFFSETS[(from)->_nodeType][fromIndex*FIELDOFFSET_LENGTH + 1]; //for builtins, convert from field index to byte offset
950 toOfs = toIndex;
951 //if(usesBuiltin(to))
952 if(toBuiltIn)
953 toOfs = NODE_OFFSETS[(to)->_nodeType][toIndex*FIELDOFFSET_LENGTH + 1]; //for builtins, convert from field index to byte offset
954 CRoutes_RegisterSimple(from,fromOfs,to,toOfs,type);
955 }
956}
957
958/********************************************************************
959
960Remove a route, but with fewer and more expressive parameters than
961CRoutes_Register. Currently a wrapper around that other function.
962
963********************************************************************/
964
965void CRoutes_RemoveSimple(
966 struct X3D_Node* from, int fromOfs,
967 struct X3D_Node* to, int toOfs,
968 int type) {
969
970 /* 10+1+3+1=15: Number <5000000000, :, number <999, \0 */
971 void* interpolatorPointer;
972
973 interpolatorPointer=returnInterpolatorPointer(to->_nodeType);
974
975 CRoutes_Register(0, from, fromOfs, to, toOfs, type,
976 interpolatorPointer, 0, NULL);
977}
978
979void CRoutes_RemoveSimpleB(struct X3D_Node* from, int fromIndex, int fromBuiltIn,
980 struct X3D_Node* to, int toIndex, int toBuiltIn, int len){
981 int fromOfs, toOfs;
982
983 fromOfs = fromIndex;
984 if(from && to){
985 //if(usesBuiltin(from))
986 if(fromBuiltIn)
987 fromOfs = NODE_OFFSETS[(from)->_nodeType][fromIndex*FIELDOFFSET_LENGTH + 1]; //for builtins, convert from field index to byte offset
988 toOfs = toIndex;
989 //if(usesBuiltin(to))
990 if(toBuiltIn)
991 toOfs = NODE_OFFSETS[(to)->_nodeType][toIndex*FIELDOFFSET_LENGTH + 1]; //for builtins, convert from field index to byte offset
992
993 CRoutes_RemoveSimple(from,fromOfs,to,toOfs,len);
994 }
995 }
996/********************************************************************
997
998CRoutes_Register.
999
1000Register a route in the routing table.
1001
1002********************************************************************/
1003
1004
1005void CRoutes_Register(
1006 int adrem,
1007 struct X3D_Node *from,
1008 int fromoffset,
1009 struct X3D_Node *to,
1010 int toOfs,
1011 int type,
1012 void *intptr,
1013 int scrdir,
1014 void *extra) {
1015
1016 struct CR_RegStruct *newEntry;
1017 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1018
1019#ifdef HAVE_OPENCL
1020 cl_kernel CL_Interpolator = NULL;
1021 ConsoleMessage ("CRoutes_Register, being run on :%s:\n",__DATE__);
1022
1023#endif //HAVE_OPENCL
1024
1025
1026
1027/*
1028printf ("Croutes.c, line %d...\n",__LINE__);
1029printf ("CRoutes_Register - adrem %d, from %p fromoffset %d to %p toOfs %d type %d intptr %p scrdir %d extra %d\n",
1030 adrem, from,
1031 fromoffset, to,
1032 toOfs, type, intptr, scrdir, extra);
1033
1034note the following will fail for Interpolators, as toNode will be NULL
1035
1036printf ("CRoutes_Register - adrem %d, from %p (%s) fromoffset %d to %p (%s) toOfs %d type %d intptr %p scrdir %d extra %d\n",
1037 adrem, from,
1038 stringNodeType(from->_nodeType),
1039 fromoffset, to,
1040 stringNodeType(to->_nodeType),
1041 toOfs, type, intptr, scrdir, extra);
1042*/
1043
1044
1045
1046 // do we have an Interpolator running on the GPU?
1047 if (from->_nodeType == NODE_CoordinateInterpolator) {
1048
1049 int incr = adrem;
1050 struct X3D_CoordinateInterpolator *px = (struct X3D_CoordinateInterpolator *) from;
1051 if (incr == 0) incr = -1; // makes easy addition
1052
1053 #ifdef HAVE_OPENCL
1054 if (to->_nodeType == NODE_Coordinate) {
1055
1056 if (canRouteOnGPUTo(to) ) {
1057 ppOpenCL_Utils p;
1058 ttglobal tg = gglobal();
1059 p = (ppOpenCL_Utils)tg->OpenCL_Utils.prv;
1060
1061 px ->_GPU_Routes_out += incr;
1062
1063 if (tg->OpenCL_Utils.OpenCL_Initialized) {
1064 printf ("OpenCL initialized in routes\n");
1065 } else {
1066 printf("OPENCL NOT INITIALIZED YET\n");
1067 }
1068
1069 while (!tg->OpenCL_Utils.OpenCL_Initialized) {
1070 usleep (100000);
1071 printf ("sleeping, waiting for CL to be initialized\n");
1072 }
1073
1074
1075
1076 CL_Interpolator = p->coordinateInterpolatorKernel;
1077 } else {
1078 printf ("CRoutes Register, have a CoordinateInterpolator to Coordinate, but dest node type not supported yet\n");
1079 px->_CPU_Routes_out+= incr;
1080 }
1081 } else {
1082
1083 px->_CPU_Routes_out += incr;
1084 }
1085 #else
1086 px->_CPU_Routes_out += incr;
1087 #endif //HAVE_OPENCL
1088 }
1089
1090 MUTEX_LOCK_ROUTING_UPDATES
1091
1092 if (p->routesToRegister == NULL) {
1093 p->routesToRegister = newVector(struct CR_RegStruct *, 16);
1094 }
1095
1096
1097 newEntry = MALLOC(struct CR_RegStruct *, sizeof (struct CR_RegStruct));
1098 newEntry->adrem = adrem;
1099 newEntry->from = from;
1100 newEntry->fromoffset = fromoffset;
1101 newEntry->to = to;
1102 newEntry->toOfs = toOfs;
1103 newEntry->fieldType = type;
1104 newEntry->intptr = intptr;
1105 newEntry->scrdir = scrdir;
1106 newEntry->extra = extra;
1107 #ifdef HAVE_OPENCL
1108 newEntry->CL_Interpolator = CL_Interpolator;
1109 #endif
1110
1111 vector_pushBack(struct CR_RegStruct *, p->routesToRegister, newEntry);
1112
1113 MUTEX_FREE_LOCK_ROUTING_UPDATES
1114
1115}
1116void free_routes_to_register(struct Vector * routesToRegister){
1117
1118 if(routesToRegister){
1119 struct CR_RegStruct *r;
1120 int i;
1121 for(i=0;i<vectorSize(routesToRegister);i++){
1122 r = vector_get(struct CR_RegStruct*,routesToRegister,i);
1123 FREE_IF_NZ(r);
1124 }
1125 deleteVector(struct CR_RegStruct *,routesToRegister);
1126 FREE_IF_NZ(routesToRegister);
1127 }
1128}
1129
1130void print_routes_ready_to_register(FILE* fp)
1131{
1132 int numRoutes;
1133 int count;
1134 struct X3D_Node *fromNode;
1135 struct X3D_Node *toNode;
1136 int fromOffset;
1137 int toOffset;
1138 char *fromName;
1139 char *toName;
1140 struct CR_RegStruct *entry;
1141 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1142
1143 if(p->routesToRegister == NULL) return;
1144 numRoutes = vectorSize(p->routesToRegister);
1145 fprintf(fp,"Number of Routes Ready to Register %d\n",numRoutes);
1146 if (numRoutes < 1) {
1147 return;
1148 }
1149
1150 for (count = 0; count < (numRoutes); count++) {
1151 entry = vector_get(struct CR_RegStruct *, p->routesToRegister, count);
1152 fromNode = entry->from;
1153 fromOffset = entry->fromoffset;
1154 toNode = entry->to;
1155 toOffset = entry->toOfs;
1156 fromName = parser_getNameFromNode(fromNode);
1157 toName = parser_getNameFromNode(toNode);
1158 fprintf (fp, " %p %s.%s TO %p %s.%s \n",fromNode,fromName,
1159 findFIELDNAMESfromNodeOffset0(fromNode,fromOffset),
1160 toNode,toName,
1161 findFIELDNAMESfromNodeOffset0(toNode,toOffset)
1162 );
1163 }
1164}
1165
1166
1167static void actually_do_CRoutes_Register() {
1168 int insert_here, check_here, shifter, isDuplicate;
1169 CRnodeStruct *to_ptr = NULL;
1170 size_t toof; /* used to help determine duplicate routes */
1171 struct X3D_Node *toN;
1172 indexT ind;
1173 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1174
1175 if (p->routesToRegister == NULL) return; /* should never get here, but... */
1176
1177#ifdef CRVERBOSE
1178 printf ("actually_do_CRoutes_Register, vector size %d\n",vectorSize(p->routesToRegister));
1179#endif
1180
1181 for (ind=0; ind<vectorSize(p->routesToRegister); ind++ ) {
1182 struct CR_RegStruct *newEntry;
1183
1184 newEntry = vector_get(struct CR_RegStruct *, p->routesToRegister, ind);
1185
1186#ifdef CRVERBOSE
1187 printf ("CRoutes_Register adrem %d from %u ",newEntry->adrem, newEntry->from);
1188 //if (newEntry->from > JSMaxScript) printf ("(%s) ",stringNodeType(X3D_NODE(newEntry->from->_nodeType)));
1189
1190 printf ("off %u to %u intptr %p\n",
1191 newEntry->fromoffset, newEntry->to, newEntry->intptr);
1192 printf ("CRoutes_Register, CRoutes_Count is %d\n",p->CRoutes_Count);
1193#endif
1194
1195 /* first time through, create minimum and maximum for insertion sorts */
1196 if (!p->CRoutes_Initiated) {
1197 /* allocate the CRoutes structure */
1198 p->CRoutes_MAX = 25; /* arbitrary number; max 25 routes to start off with */
1199 p->CRoutes = MALLOC (struct CRStruct *, sizeof (*p->CRoutes) * p->CRoutes_MAX);
1200
1201 p->CRoutes[0].routeFromNode = X3D_NODE(0);
1202 p->CRoutes[0].fnptr = 0;
1203 p->CRoutes[0].tonode_count = 0;
1204 p->CRoutes[0].tonodes = NULL;
1205 p->CRoutes[0].isActive = FALSE;
1206 p->CRoutes[0].interpptr = 0;
1207 p->CRoutes[0].intTimeStamp = 0;
1208 p->CRoutes[1].routeFromNode = X3D_NODE(-1);
1209 p->CRoutes[1].fnptr = 0x8FFFFFFF;
1210 p->CRoutes[1].tonode_count = 0;
1211 p->CRoutes[1].tonodes = NULL;
1212 p->CRoutes[1].isActive = FALSE;
1213 p->CRoutes[1].interpptr = 0;
1214 p->CRoutes[1].intTimeStamp = 0;
1215 p->CRoutes_Count = 2;
1216 p->CRoutes_Initiated = TRUE;
1217
1218 #ifdef HAVE_OPENCL
1219 p->CRoutes[0].CL_Interpolator = NULL;
1220 p->CRoutes[1].CL_Interpolator = NULL;
1221 #endif
1222 }
1223
1224 insert_here = 1;
1225
1226 /* go through the routing list, finding where to put it */
1227 while (newEntry->from > p->CRoutes[insert_here].routeFromNode) {
1228 #ifdef CRVERBOSE
1229 printf ("comparing %u to %u\n",newEntry->from, p->CRoutes[insert_here].routeFromNode);
1230 #endif
1231 insert_here++;
1232 }
1233
1234 /* hmmm - do we have a route from this node already? If so, go
1235 through and put the offsets in order */
1236 while ((newEntry->from == p->CRoutes[insert_here].routeFromNode) &&
1237 (newEntry->fromoffset > p->CRoutes[insert_here].fnptr)) {
1238 #ifdef CRVERBOSE
1239 printf ("same routeFromNode, different offset\n");
1240 #endif
1241 insert_here++;
1242 }
1243
1244
1245 /* Quick check to verify that we don't have a duplicate route here
1246 OR to delete a route... */
1247
1248 #ifdef CRVERBOSE
1249 printf ("ok, CRoutes_Register - is this a duplicate? comparing from (%d %d), fnptr (%d %d) intptr (%d %d) and tonodes %d\n",
1250 p->CRoutes[insert_here].routeFromNode, newEntry->from,
1251 p->CRoutes[insert_here].fnptr, newEntry->fromoffset,
1252 p->CRoutes[insert_here].interpptr, newEntry->intptr,
1253 p->CRoutes[insert_here].tonodes);
1254 #endif
1255
1256 check_here = insert_here;
1257 isDuplicate = 0;
1258 while ((p->CRoutes[check_here].routeFromNode==newEntry->from) &&
1259 (p->CRoutes[check_here].fnptr==newEntry->fromoffset) &&
1260 (newEntry->adrem == 0 || p->CRoutes[check_here].interpptr==newEntry->intptr) &&
1261 (p->CRoutes[check_here].tonodes!=0)) {
1262 /* possible duplicate route */
1263 toN = newEntry->to;
1264 toof = newEntry->toOfs;
1265
1266 if ((toN == (p->CRoutes[check_here].tonodes)->routeToNode) &&
1267 (toof == (p->CRoutes[check_here].tonodes)->foffset)) {
1268 /* this IS a duplicate, now, what to do? */
1269
1270 #ifdef CRVERBOSE
1271 printf ("duplicate route; maybe this is a remove? \n");
1272 #endif
1273
1274 /* is this an add? */
1275 if (newEntry->adrem == 1) {
1276 #ifdef CRVERBOSE
1277 printf ("definite duplicate, returning\n");
1278 #endif
1279 //continue; //return;
1280 isDuplicate = 1;
1281 break;
1282 } else {
1283 /* this is a remove */
1284 FREE_IF_NZ(p->CRoutes[check_here].tonodes);
1285 for (shifter = check_here; shifter < p->CRoutes_Count; shifter++) {
1286 #ifdef CRVERBOSE
1287 printf ("copying from %d to %d\n",shifter, shifter-1);
1288 #endif
1289 memcpy ((void *)&p->CRoutes[shifter],
1290 (void *)&p->CRoutes[shifter+1],
1291 sizeof (struct CRStruct));
1292 }
1293 p->CRoutes_Count --;
1294 #ifdef CRVERBOSE
1295 printf ("routing table now %d\n",p->CRoutes_Count);
1296 for (shifter = 0; shifter < p->CRoutes_Count; shifter ++) {
1297 printf ("%d: %u %u %u\n",shifter, p->CRoutes[shifter].routeFromNode, p->CRoutes[shifter].fnptr,
1298 p->CRoutes[shifter].interpptr);
1299 }
1300 #endif
1301
1302 /* return; */
1303 }
1304 }
1305 check_here++;
1306 }
1307
1308 /* this is an Add; removes should be handled above. */
1309 if (newEntry->adrem == 1 && !isDuplicate) {
1310 #ifdef CRVERBOSE
1311 printf ("CRoutes, inserting at %d\n",insert_here);
1312 #endif
1313
1314 /* create the space for this entry. */
1315 for (shifter = p->CRoutes_Count; shifter > insert_here; shifter--) {
1316 memcpy ((void *)&p->CRoutes[shifter], (void *)&p->CRoutes[shifter-1],sizeof(struct CRStruct));
1317 #ifdef CRVERBOSE
1318 printf ("Copying from index %d to index %d\n",shifter, shifter-1);
1319 #endif
1320 }
1321
1322
1323 /* and put it in */
1324 p->CRoutes[insert_here].routeFromNode = newEntry->from;
1325 p->CRoutes[insert_here].fnptr = newEntry->fromoffset;
1326 p->CRoutes[insert_here].isActive = FALSE;
1327 p->CRoutes[insert_here].tonode_count = 0;
1328 p->CRoutes[insert_here].tonodes = NULL;
1329 p->CRoutes[insert_here].len = returnRoutingElementLength(newEntry->fieldType);
1330 p->CRoutes[insert_here].interpptr = (void (*)(void*))newEntry->intptr;
1331 p->CRoutes[insert_here].direction_flag = newEntry->scrdir;
1332 p->CRoutes[insert_here].extra = newEntry->extra;
1333 p->CRoutes[insert_here].intTimeStamp = 0;
1334 #ifdef HAVE_OPENCL
1335 p->CRoutes[insert_here].CL_Interpolator = newEntry->CL_Interpolator;
1336 #endif
1337
1338
1339 if ((p->CRoutes[insert_here].tonodes =
1340 MALLOC(CRnodeStruct *, sizeof(CRnodeStruct))) == NULL) {
1341 fprintf(stderr, "CRoutes_Register: calloc failed to allocate memory.\n");
1342 } else {
1343 p->CRoutes[insert_here].tonode_count = 1;
1344 /* printf ("inserting route, to %u, offset %d\n",newEntry->to, newEntry->toOfs); */
1345
1346 to_ptr = &(p->CRoutes[insert_here].tonodes[0]);
1347 to_ptr->routeToNode = newEntry->to;
1348 to_ptr->foffset = newEntry->toOfs;
1349 }
1350
1351 /* record that we have one more route, with upper limit checking... */
1352 if (p->CRoutes_Count >= (p->CRoutes_MAX-2)) {
1353 /* printf("WARNING: expanding routing table\n"); */
1354 p->CRoutes_MAX += 50; /* arbitrary expansion number */
1355 p->CRoutes =(struct CRStruct *) REALLOC (p->CRoutes, sizeof (*p->CRoutes) * p->CRoutes_MAX);
1356 }
1357
1358 p->CRoutes_Count ++;
1359
1360 #ifdef CRVERBOSE
1361 printf ("routing table now %d\n",p->CRoutes_Count);
1362 for (shifter = 0; shifter < p->CRoutes_Count; shifter ++) {
1363 printf ("%d: from: %p offset: %u Interpolator %p direction %d, len %d extra %p : ",shifter,
1364 p->CRoutes[shifter].routeFromNode, p->CRoutes[shifter].fnptr,
1365 p->CRoutes[shifter].interpptr, p->CRoutes[shifter].direction_flag, p->CRoutes[shifter].len, p->CRoutes[shifter].extra);
1366 for (insert_here = 0; insert_here < p->CRoutes[shifter].tonode_count; insert_here++) {
1367 printf (" to: %p %u",p->CRoutes[shifter].tonodes[insert_here].routeToNode,
1368 p->CRoutes[shifter].tonodes[insert_here].foffset);
1369 }
1370 printf ("\n");
1371 }
1372 #endif
1373 //FREE_IF_NZ(newEntry);
1374 }
1375 }
1376 free_routes_to_register(p->routesToRegister); //free all newEntries
1377 p->routesToRegister = NULL;
1378 #ifdef CRVERBOSE
1379 printf ("routing table now %d\n",p->CRoutes_Count);
1380 for (shifter = 0; shifter < p->CRoutes_Count; shifter ++) {
1381 printf ("%3d from: %p offset: %u Interp %p dir %d, len %d extra %p :\n",shifter,
1382 p->CRoutes[shifter].routeFromNode, p->CRoutes[shifter].fnptr,
1383 p->CRoutes[shifter].interpptr, p->CRoutes[shifter].direction_flag, p->CRoutes[shifter].len, p->CRoutes[shifter].extra);
1384 for (insert_here = 0; insert_here < p->CRoutes[shifter].tonode_count; insert_here++) {
1385 printf (" to: %p %u\n",p->CRoutes[shifter].tonodes[insert_here].routeToNode,
1386 p->CRoutes[shifter].tonodes[insert_here].foffset);
1387 }
1388 }
1389 #endif
1390
1391}
1392void lock_and_do_routes_register()
1393{
1394 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1395 MUTEX_LOCK_ROUTING_UPDATES
1396 actually_do_CRoutes_Register();
1397 MUTEX_FREE_LOCK_ROUTING_UPDATES
1398}
1399
1400
1401#ifdef DEBUG_VALIDNODE
1402/* only if DEBUG_VALIDNODE is defined; helps us find memory/routing problems */
1403void mark_event_check (struct X3D_Node *from, int totalptr, char *fn, int line) {
1404 printf ("mark_event_check: at %s:%d\n",fn,line);
1405 if (X3D_NODE_CHECK(from)) {
1406 #ifdef CRVERBOSE
1407 printf ("mark_event_check, routing from a %s\n",stringNodeType(from->_nodeType));
1408 #endif
1409 } else {
1410 printf ("mark_event_check, not a real node %d\n",from);
1411 }
1412 mark_event(from,totalptr);
1413 printf ("mark_event_check: finished at %s:%d\n",fn,line);
1414}
1415#endif
1416
1417/********************************************************************
1418
1419mark_event - something has generated an eventOut; record the node
1420data structure pointer, and the offset. Mark all relevant entries
1421in the routing table that this node/offset triggered an event.
1422
1423********************************************************************/
1424
1425void mark_event (struct X3D_Node *from, int totalptr) {
1426 int findit;
1427 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1428
1429 if(from == 0) return;
1430 /*if(totalptr == 0) return; */
1431
1432 X3D_NODE_CHECK(from);
1433
1434 /* maybe this MARK_EVENT is coming in during initial node startup, before routing is registered? */
1435 if (!p->CRoutes_Initiated) {
1436 LOCK_PREROUTETABLE
1437 /* printf ("routes not registered yet; lets save this one for a bit...\n"); */
1438 if (p->initialEventBeforeRoutesCount >= p->preRouteTableSize) {
1439 p->preRouteTableSize += POSSIBLEINITIALROUTES;
1440 p->preEvents=REALLOC (p->preEvents,
1441 sizeof (struct initialRouteStruct) * p->preRouteTableSize);
1442 }
1443 p->preEvents[p->initialEventBeforeRoutesCount].from = from;
1444 p->preEvents[p->initialEventBeforeRoutesCount].totalptr = totalptr;
1445 p->initialEventBeforeRoutesCount++;
1446 UNLOCK_PREROUTETABLE
1447
1448 return; /* no routes registered yet */
1449 }
1450
1451 findit = 1;
1452
1453 #ifdef CRVERBOSE
1454 printf ("\nmark_event, from %s (%u) fromoffset %u\n", stringNodeType(from->_nodeType),from, totalptr);
1455 #endif
1456
1457 /* events in the routing table are sorted by routeFromNode. Find
1458 out if we have at least one route from this node */
1459 while (from > p->CRoutes[findit].routeFromNode) {
1460 #ifdef CRVERBOSE
1461 printf ("mark_event, skipping past %x %x, index %d\n",from, p->CRoutes[findit].routeFromNode, findit);
1462 #endif
1463 findit ++;
1464 }
1465
1466 /* while we have an eventOut from this NODE/OFFSET, mark it as
1467 active. If no event from this NODE/OFFSET, ignore it */
1468 while ((from == p->CRoutes[findit].routeFromNode) &&
1469 (totalptr != p->CRoutes[findit].fnptr)) findit ++;
1470
1471 /* did we find the exact entry? */
1472 #ifdef CRVERBOSE
1473 printf ("ep, (%#x %#x) (%#x %#x) at %d \n",
1474 from,p->CRoutes[findit].routeFromNode, totalptr,
1475 p->CRoutes[findit].fnptr,findit);
1476 #endif
1477
1478 /* if we did, signal it to the CEvents loop - maybe more than one ROUTE,
1479 eg, a time sensor goes to multiple interpolators */
1480 while ((from == p->CRoutes[findit].routeFromNode) &&
1481 (totalptr == p->CRoutes[findit].fnptr)) {
1482 #ifdef CRVERBOSE
1483 printf ("found event at %d\n",findit);
1484 #endif
1485 if (p->CRoutes[findit].intTimeStamp!=p->thisIntTimeStamp) {
1486 p->CRoutes[findit].isActive=TRUE;
1487 p->CRoutes[findit].intTimeStamp=p->thisIntTimeStamp;
1488 }
1489
1490#ifdef CRVERBOSE
1491 else printf ("routing loop broken, findit %d\n",findit);
1492#endif
1493
1494 findit ++;
1495 }
1496 #ifdef CRVERBOSE
1497 printf ("done mark_event\n");
1498 #endif
1499}
1500
1501//experimental _B mark event for brotos, to stop cycling node.exposed to/from proto.exposed
1502void mark_event_B (struct X3D_Node *lastFrom, int lastptr, struct X3D_Node *from, int totalptr) {
1503 int findit;
1504 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1505
1506 if(from == 0) return;
1507 /*if(totalptr == 0) return; */
1508
1509 X3D_NODE_CHECK(from);
1510
1511 /* maybe this MARK_EVENT is coming in during initial node startup, before routing is registered? */
1512 if (!p->CRoutes_Initiated) {
1513 LOCK_PREROUTETABLE
1514 /* printf ("routes not registered yet; lets save this one for a bit...\n"); */
1515 if (p->initialEventBeforeRoutesCount >= p->preRouteTableSize) {
1516 p->preRouteTableSize += POSSIBLEINITIALROUTES;
1517 p->preEvents=REALLOC (p->preEvents,
1518 sizeof (struct initialRouteStruct) * p->preRouteTableSize);
1519 }
1520 p->preEvents[p->initialEventBeforeRoutesCount].from = from;
1521 p->preEvents[p->initialEventBeforeRoutesCount].totalptr = totalptr;
1522 p->initialEventBeforeRoutesCount++;
1523 UNLOCK_PREROUTETABLE
1524
1525 return; /* no routes registered yet */
1526 }
1527
1528 findit = 1;
1529
1530 #ifdef CRVERBOSE
1531 printf ("\nmark_event, from %s (%u) fromoffset %u\n", stringNodeType(from->_nodeType),from, totalptr);
1532 #endif
1533
1534 /* events in the routing table are sorted by routeFromNode. Find
1535 out if we have at least one route from this node */
1536 while (from > p->CRoutes[findit].routeFromNode) {
1537 #ifdef CRVERBOSE
1538 printf ("mark_event, skipping past %x %x, index %d\n",from, p->CRoutes[findit].routeFromNode, findit);
1539 #endif
1540 findit ++;
1541 }
1542
1543 /* while we have an eventOut from this NODE/OFFSET, mark it as
1544 active. If no event from this NODE/OFFSET, ignore it */
1545 while ((from == p->CRoutes[findit].routeFromNode) &&
1546 (totalptr != p->CRoutes[findit].fnptr)) findit ++;
1547
1548 /* did we find the exact entry? */
1549 #ifdef CRVERBOSE
1550 printf ("ep, (%#x %#x) (%#x %#x) at %d \n",
1551 from,p->CRoutes[findit].routeFromNode, totalptr,
1552 p->CRoutes[findit].fnptr,findit);
1553 #endif
1554
1555 /* if we did, signal it to the CEvents loop - maybe more than one ROUTE,
1556 eg, a time sensor goes to multiple interpolators */
1557 while ((from == p->CRoutes[findit].routeFromNode) &&
1558 (totalptr == p->CRoutes[findit].fnptr)) {
1559 BOOL isCycle = 0;
1560 #ifdef CRVERBOSE
1561 printf ("found event at %d\n",findit);
1562 #endif
1563 isCycle = (p->CRoutes[findit].tonodes[0].routeToNode == lastFrom &&
1564 p->CRoutes[findit].tonodes[0].foffset == lastptr);
1565 if(!isCycle)
1566 if (p->CRoutes[findit].intTimeStamp!=p->thisIntTimeStamp) {
1567 p->CRoutes[findit].isActive=TRUE;
1568 p->CRoutes[findit].intTimeStamp=p->thisIntTimeStamp;
1569 }
1570
1571#ifdef CRVERBOSE
1572 else printf ("routing loop broken, findit %d\n",findit);
1573#endif
1574
1575 findit ++;
1576 }
1577 #ifdef CRVERBOSE
1578 printf ("done mark_event\n");
1579 #endif
1580}
1581
1582//struct CRscriptStruct *getScriptControl()
1583//{
1584// ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1585// return p->ScriptControl;
1586//}
1587//void setScriptControl(struct CRscriptStruct *ScriptControl)
1588//{
1589// ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1590// p->ScriptControl = ScriptControl;
1591//}
1592int getScriptControlCount() {
1593
1594 ttglobal tg = (ttglobal)gglobal();
1595 return tg->CRoutes.max_script_found;
1596}
1597struct CRscriptStruct *getScriptControlIndex(int actualscript)
1598{
1599 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1600 return vector_get(struct CRscriptStruct*,p->ScriptControl,actualscript);
1601 //return &p->ScriptControl[actualscript];
1602}
1603void setScriptControlIndex(int actualscript, struct CRscriptStruct *sc){
1604 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1605 vector_set(struct CRscriptStruct*,p->ScriptControl,actualscript,sc);
1606}
1607int isScriptControlOK(int actualscript)
1608{
1609 struct CRscriptStruct* cs;
1610 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1611 cs = vector_get(struct CRscriptStruct*,p->ScriptControl,actualscript);
1612
1613 return cs->scriptOK;
1614}
1615int isScriptControlInitialized(int actualscript)
1616{
1617 int ret;
1618 struct CRscriptStruct* cs;
1619 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1620 ret = FALSE;
1621 if(actualscript < p->JSMaxScript){
1622 cs = vector_get(struct CRscriptStruct*,p->ScriptControl,actualscript);
1623 if(cs){
1624 if(cs->_initialized) ret = TRUE;
1625 }
1626 }
1627 return ret;
1628}
1629int loadstatus_Script(struct X3D_Script *script){
1630 int istate = 0;
1631 if(script){
1632 if(script->__scriptObj){
1633 struct Shader_Script * shader=X3D_SCRIPT(script)->__scriptObj;
1634 istate = isScriptControlInitialized(shader->num);
1635 }
1636 }
1637 return istate;
1638}
1639void initializeAnyScripts()
1640{
1641/*
1642 we want to run initialize() from the calling thread. NOTE: if
1643 initialize creates VRML/X3D nodes, it will call the ProdCon methods
1644 to do this, and these methods will check to see if nodes, yada,
1645 yada, yada, until we run out of stack. So, we check to see if we
1646 are initializing; if so, don't worry about checking for new scripts
1647 any scripts to initialize here? we do it here, because we may just
1648 have created new scripts during X3D/VRML parsing. Routing in the
1649 Display thread may have noted new scripts, but will ignore them
1650 until we have told it that the scripts are initialized. printf
1651 ("have scripts to initialize in fwl_RenderSceneUpdateScene old %d new
1652 %d\n",max_script_found, max_script_found_and_initialized);
1653*/
1654
1655//#define INITIALIZE_ANY_SCRIPTS
1656 ttglobal tg = (ttglobal)gglobal();
1657 if( tg->CRoutes.max_script_found != tg->CRoutes.max_script_found_and_initialized)
1658 {
1659 struct CRscriptStruct *ScriptControl; // = getScriptControl();
1660 int i; //jsval retval;
1661 for (i=tg->CRoutes.max_script_found_and_initialized+1; i <= tg->CRoutes.max_script_found; i++)
1662 {
1663 /* printf ("initializing script %d in thread %u\n",i,pthread_self()); */
1664 JSCreateScriptContext(i);
1665 JSInitializeScriptAndFields(i);
1666 ScriptControl = getScriptControlIndex(i);
1667 if (ScriptControl->scriptOK)
1668 jsActualrunScript(i, "initialize()");
1669 //ACTUALRUNSCRIPT(i, "initialize()" ,&retval);
1670 /* printf ("initialized script %d\n",i);*/
1671 }
1672 tg->CRoutes.max_script_found_and_initialized = tg->CRoutes.max_script_found;
1673 }
1674
1675}
1676
1677/*******************************************************************
1678
1679CRoutes_js_new;
1680
1681Register a new script for future routing
1682
1683********************************************************************/
1684
1685void CRoutes_js_new (int num, int scriptType) {
1686 /* record whether this is a javascript, class invocation, ... */
1687 ttglobal tg = gglobal();
1688 struct CRscriptStruct* cs;
1689 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
1690 cs = vector_get(struct CRscriptStruct*,p->ScriptControl,num);
1691
1692 //p->ScriptControl[num].thisScriptType = scriptType;
1693 cs->thisScriptType = scriptType;
1694
1695 /* compare with a intptr_t, because we need to compare to -1 */
1696 if (num > tg->CRoutes.max_script_found) tg->CRoutes.max_script_found = num;
1697}
1698
1699
1700
1701
1702/********************************************************************
1703
1704mark_script - indicate that this script has had an eventIn
1705zero_scripts - reset all script indicators
1706
1707********************************************************************/
1708void mark_script (int num) {
1709 //struct CRscriptstruct *cs;
1710 //ppCRoutes p;
1711 //ttglobal tg = gglobal();
1712 //p = (ppCRoutes)tg->CRoutes.prv;
1713
1714 //#ifdef CRVERBOSE
1715 // printf ("mark_script - script %d has been invoked\n",num);
1716 //#endif
1717 getScriptControlIndex(num)->scr_act = TRUE;
1718 //p->scr_act[num]= TRUE;
1719}
1720
1721
1722
1723
1724/********************************************************************
1725
1726gatherScriptEventOuts - at least one script has been triggered; get the
1727eventOuts for this script
1728
1729********************************************************************/
1730
1731static BOOL gatherScriptEventOut_B(union anyVrml* any, struct Shader_Script *shader,
1732 int JSparamNameIndex, int type, int extra, int len) {
1733 //dug9 this version stores the value back in the script field instead of toNode.
1734 //also, doesn't do 'new parents' in here if value is an SFNode or MFNode.
1735 //int route;
1736 //size_t fptr;
1737 //size_t tptr;
1738 //size_t len;
1739 // struct X3D_Node* tn;
1740 //struct X3D_Node* fn;
1741 //struct anyVrml* any;
1742
1743 //int fromalready=FALSE; /* we have already got the from value string */
1744 int touched_flag=FALSE;
1745 int actualscript;
1746 //unsigned int to_counter;
1747 //CRnodeStruct *to_ptr = NULL;
1748 //ppCRoutes p;
1749 ttglobal tg = gglobal();
1750
1751 #ifdef CRVERBOSE
1752 struct CRjsnameStruct *JSparamnames = getJSparamnames();
1753 #endif
1754
1755 //p = (ppCRoutes)tg->CRoutes.prv;
1756
1757 /* NOTE - parts of things in here might need to be wrapped by BeginRequest ??? */
1758
1759 /* go through all routes, looking for this script as an eventOut */
1760
1761 /* do we have any routes yet? - we can gather events before any routes are made */
1762 //if (!p->CRoutes_Initiated) return;
1763
1764 /* go from beginning to end in the routing table */
1765 //route=1;
1766 //while (route < (p->CRoutes_Count-1)) {
1767 // #ifdef CRVERBOSE
1768 // printf ("gather, routing %d is %s\n",route,
1769 // stringNodeType(X3D_NODE(p->CRoutes[route].routeFromNode)->_nodeType));
1770 // #endif
1771
1772 //if (X3D_NODE(p->CRoutes[route].routeFromNode)->_nodeType == NODE_Script) {
1773 //struct X3D_Script *mys = X3D_SCRIPT(p->CRoutes[route].routeFromNode);
1774 //struct Shader_Script *sp = (struct Shader_Script *) mys->__scriptObj;
1775 if(shader->num > -1 && shader->loaded){
1776 actualscript = shader->num;
1777
1778 /* printf ("gatherEvents, found a script at element %d, it is script number %d and node %u\n",
1779 route, actualscript,mys); */
1780 /* this script initialized yet? We make sure that on initialization that the Parse Thread
1781 does the initialization, once it is finished parsing. */
1782 //if (!p->ScriptControl[actualscript]._initialized) {
1783 if(!isScriptControlInitialized(actualscript)){
1784 /* printf ("waiting for initializing script %d at %s:%d\n",actualscript, __FILE__,__LINE__); */
1785 return FALSE;
1786 }
1787
1788 if (actualscript > tg->CRoutes.max_script_found_and_initialized) {
1789 /* printf ("gatherScriptEventOut, waiting for script %d to become initialized\n"); */
1790 return FALSE;
1791 }
1792
1793 //if (!p->ScriptControl[actualscript].scriptOK) {
1794 if(!isScriptControlOK(actualscript)){
1795 /* printf ("gatherScriptEventOuts - script initialized but not OK\n"); */
1796 return FALSE;
1797 }
1798
1799 /* is this the same from node/field as before? */
1800 //if ((p->CRoutes[route].routeFromNode == p->CRoutes[route-1].routeFromNode) &&
1801 // (p->CRoutes[route].fnptr == p->CRoutes[route-1].fnptr) &&
1802 // (route > 1)) {
1803 // fromalready=TRUE;
1804 //} else {
1805 // /* printf ("different from, have to get value\n"); */
1806 // fromalready=FALSE;
1807 //}
1808
1809 //fptr = p->CRoutes[route].fnptr;
1810 //fn = p->CRoutes[route].routeFromNode;
1811 //len = p->CRoutes[route].len;
1812
1813 #ifdef CRVERBOSE
1814 //printf ("\ngatherSentEvents, script %d from %s type %d len %d\n",actualscript, JSparamnames[fptr].name,
1815 // JSparamnames[fptr].type, len);
1816 #endif
1817
1818 /* now, set the actual properties - switch as documented above */
1819 //if (!fromalready) {
1820 #ifdef CRVERBOSE
1821 //printf ("Not found yet, getting touched flag fptr %d script %d \n",fptr,actualscript);
1822 #endif
1823 touched_flag = get_valueChanged_flag((int)JSparamNameIndex,actualscript);
1824 //}
1825
1826 if (touched_flag!= 0) {
1827 /* get some easy to use pointers */
1828 //for (to_counter = 0; to_counter < p->CRoutes[route].tonode_count; to_counter++) {
1829 // to_ptr = &(p->CRoutes[route].tonodes[to_counter]);
1830 // tn = to_ptr->routeToNode;
1831 // tptr = to_ptr->foffset;
1832
1833 #ifdef CRVERBOSE
1834 //printf ("%s script %d VALUE CHANGED! copy value and update %p\n",JSparamnames[fptr].name,actualscript,tn);
1835 #endif
1836
1837 /* eventOuts go to VRML data structures */
1838
1839 js_setField_javascriptEventOut_B(any,type, len, extra,
1840 actualscript);
1841 //p->ScriptControl[actualscript].cx);
1842 // void setField_javascriptEventOut_B(union anyVrml* any,
1843 //int fieldType, unsigned len, int extraData, JSContext *scriptContext
1844
1845 /* tell this node now needs to redraw */
1846 //markScriptResults(tn, (int) tptr, route, to_ptr->routeToNode);
1847 //MARK_EVENT (tn,tptr);
1848
1849 #ifdef CRVERBOSE
1850 //printf ("%s script %d has successfully updated %u\n",JSparamnames[fptr].name,actualscript,tn);
1851 #endif
1852
1853 //}
1854 /* unset the touched flag */
1855 resetScriptTouchedFlag ((int) actualscript, (int) JSparamNameIndex);
1856 return TRUE;
1857
1858 }
1859
1861 //resetScriptTouchedFlag ((int) actualscript, (int) fromOffset);
1862
1863 /*
1864#if defined(JS_THREADSAFE)
1865 JS_BeginRequest(p->ScriptControl[actualscript].cx);
1866#endif
1867 REMOVE_ROOT(p->ScriptControl[actualscript].cx,global_return_val);
1868#if defined(JS_THREADSAFE)
1869 JS_EndRequest(p->ScriptControl[actualscript].cx);
1870#endif
1871 */
1872 //}
1873 //route ++;
1874 //}
1875 }
1876 #ifdef CRVERBOSE
1877 printf ("%f finished gatherScriptEventOuts loop\n",TickTime());
1878 #endif
1879 return FALSE;
1880}
1881
1882void JSparamnamesShutdown(){
1883 ttglobal tg = gglobal();
1884 ppCRoutes p = (ppCRoutes)tg->CRoutes.prv;
1885 /* Script name/type table */
1886 FREE_IF_NZ(p->JSparamnames);
1887 tg->CRoutes.jsnameindex = -1;
1888 tg->CRoutes.MAXJSparamNames = 0;
1889}
1890
1891void kill_javascript(void) {
1892 int i;
1893 ttglobal tg = gglobal();
1894 ppCRoutes p = (ppCRoutes)tg->CRoutes.prv;
1895 struct CRscriptStruct *ScriptControl; // = getScriptControl();
1896
1897 printf ("calling kill_javascript()\n");
1898 zeroScriptHandles();
1899 if (jsIsRunning() != 0) {
1900 for (i=0; i<=tg->CRoutes.max_script_found_and_initialized; i++) {
1901 /* printf ("kill_javascript, looking at %d\n",i); */
1902 ScriptControl = getScriptControlIndex(i);
1903 if(ScriptControl){ //can be null already
1904 if (ScriptControl->cx != 0) {
1905 JSDeleteScriptContext(i);
1906 }
1907 setScriptControlIndex(i,NULL);
1908 }
1909 }
1910 }
1911 p->JSMaxScript = 0;
1912 tg->CRoutes.max_script_found = -1;
1913 tg->CRoutes.max_script_found_and_initialized = -1;
1914 jsShutdown();
1915 JSparamnamesShutdown();
1916 //vector_releaseData(struct CRscriptStruct *,p->ScriptControl);
1917 deleteVector(struct CRscriptStruct *,p->ScriptControl);
1918 //FREE_IF_NZ (ScriptControl);
1919 //FREE_IF_NZ(p->scr_act);
1920
1921 printf ("done kill_javascript\n");
1922
1923}
1924
1925void cleanupDie(int num, const char *msg) {
1926 kill_javascript();
1927 freewrlDie(msg);
1928}
1929struct CRscriptStruct *newScriptControl(){
1930 struct CRscriptStruct *sc = NULL;
1931 sc = MALLOCV(sizeof(struct CRscriptStruct));
1932 memset(sc,0,sizeof(struct CRscriptStruct));
1933 sc->thisScriptType = NOSCRIPT;
1934 sc->eventsProcessed = NULL;
1935 sc->cx = 0;
1936 sc->glob = 0;
1937 sc->_initialized = FALSE;
1938 sc->scriptOK = FALSE;
1939 sc->scriptText = NULL;
1940 sc->paramList = NULL;
1941 sc->script = NULL;
1942 return sc;
1943}
1944//void JSMaxAlloc() {
1945// /* perform some REALLOCs on JavaScript database stuff for interfacing */
1946// int count, istart, iend;
1947// int *scr_act, *new_scr_act;
1948// ttglobal tg = gglobal();
1949// ppCRoutes p = (ppCRoutes)tg->CRoutes.prv;
1950// /* printf ("start of JSMaxAlloc, JSMaxScript %d\n",JSMaxScript); */
1951// //struct CRscriptStruct *newScriptControl, *ScriptControl;
1952//
1953// //istart = p->JSMaxScript;
1954// //iend = istart + 20;
1955// ////printf("reallocing in JSMaxAlloc() from %d to %d\n",istart,iend);
1956// //ScriptControl = getScriptControl();
1957// //newScriptControl = malloc(sizeof (struct CRscriptStruct) * iend);
1958// //if(istart)
1959// // memcpy(newScriptControl,ScriptControl,sizeof (struct CRscriptStruct) *istart);
1960// //scr_act = p->scr_act;
1961// //new_scr_act = (int *)malloc(sizeof (int *) * iend);
1962// //if(istart)
1963// // memcpy(new_scr_act,scr_act,sizeof(int *)*istart);
1964//
1965// ///* mark these scripts inactive */
1966// ////for (count=p->JSMaxScript-10; count<p->JSMaxScript; count++) {
1967// //for(count = istart; count < iend; count++){
1968// // new_scr_act[count]= FALSE;
1969// // newScriptControl[count].thisScriptType = NOSCRIPT;
1970// // newScriptControl[count].eventsProcessed = NULL;
1971// // newScriptControl[count].cx = 0;
1972// // newScriptControl[count].glob = 0;
1973// // newScriptControl[count]._initialized = FALSE;
1974// // newScriptControl[count].scriptOK = FALSE;
1975// // newScriptControl[count].scriptText = NULL;
1976// // newScriptControl[count].paramList = NULL;
1977// // newScriptControl[count].script = NULL;
1978// //}
1979// //setScriptControl( newScriptControl);
1980// //p->scr_act = new_scr_act;
1981// //p->JSMaxScript = iend;
1982// //FREE_IF_NZ(ScriptControl);
1983// //FREE_IF_NZ(scr_act);
1984//
1985//}
1986
1987void JSMaxAlloc2(int num){
1988 ttglobal tg = gglobal();
1989 ppCRoutes p = (ppCRoutes)tg->CRoutes.prv;
1990 if(!p->ScriptControl)
1991 p->ScriptControl = newVector(struct CRscriptStruct *,0);
1992 //I suspect the following is like vector_ensurespace. We don't do a pushback here.
1993 if(p->ScriptControl->allocn <= num){
1994 int i,istart, iend;
1995
1996 istart = p->ScriptControl->allocn;
1997 iend = upper_power_of_two(num+1);
1998 p->ScriptControl->data = REALLOC(p->ScriptControl->data,iend*sizeof(struct CRscriptStruct *));
1999 p->ScriptControl->allocn = iend;
2000 p->JSMaxScript = p->ScriptControl->allocn;
2001 //not all Scripts get a control - if they are in the body of a ProtoDeclare they don't.
2002 //But they may get a script num. If so they may be null.
2003 //Or if an Inline is unloaded, some elements of ScriptControl may be null.
2004 for(i=istart;i<iend;i++)
2005 vector_set(struct CRscriptStruct *,p->ScriptControl,i,NULL);
2006 }
2007}
2008int unInitializeScript(struct X3D_Node *node){
2009 int iret = FALSE;
2010 if(node && node->_nodeType == NODE_Script){
2011 struct X3D_Script *scriptnode = (struct X3D_Script*)node;
2012 struct Shader_Script *sscript = scriptnode->__scriptObj;
2013 if(sscript){
2014 int count;
2015 struct CRscriptStruct *ScriptControl; // = getScriptControl();
2016
2017 //sscript->loaded = FALSE;
2018 count = sscript->num;
2019 ScriptControl = getScriptControlIndex(count);
2020 if (ScriptControl->cx != 0)
2021 JSDeleteScriptContext(count);
2022 setScriptControlIndex(count,NULL);
2023 FREE_IF_NZ(ScriptControl);
2024 iret = TRUE;
2025 }
2026 }
2027 return iret;
2028}
2029
2030/* set up table entry for this new script */
2031void JSInit(struct Shader_Script *script) { /* int num) { */
2032 struct CRscriptStruct *cs;
2033 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
2034 #ifdef JAVASCRIPTVERBOSE
2035 printf("JSinit: script %d\n",num);
2036 #endif
2037
2038 /* more scripts than we can handle right now? */
2039 if (script->num >= p->JSMaxScript) {
2040 JSMaxAlloc2(script->num);
2041 }
2042 cs = newScriptControl();
2043 setScriptControlIndex(script->num,cs);
2044 //getScriptControlIndex(script->num)->script = script;
2045 cs->script = script;
2046}
2047
2048
2049/* Save the text, so that when the script is initialized in the fwl_RenderSceneUpdateScene thread, it will be there */
2050void SaveScriptText(int num, const char *text) {
2051 ttglobal tg = gglobal();
2052 ppCRoutes p = (ppCRoutes)tg->CRoutes.prv;
2053 struct CRscriptStruct *ScriptControl; // = getScriptControl();
2054
2055 /* printf ("SaveScriptText, num %d, thread %u saving :%s:\n",num, pthread_self(),text); */
2056 if (num >= p->JSMaxScript) {
2057 ConsoleMessage ("SaveScriptText: warning, script %d initialization out of order",num);
2058 return;
2059 }
2060 ScriptControl = getScriptControlIndex(num);
2061 FREE_IF_NZ(ScriptControl->scriptText);
2062 ScriptControl->scriptText = STRDUP(text);
2063/* NOTE - seems possible that a script could be overwritten; if so then fix eventsProcessed */
2064 //jsClearScriptControlEntries(&ScriptControl[num]);
2065 jsClearScriptControlEntries(num);
2066
2067 if (((int)num) > tg->CRoutes.max_script_found) tg->CRoutes.max_script_found = num;
2068 /* printf ("SaveScriptText, for script %d scriptText %s\n",text);
2069 printf ("SaveScriptText, max_script_found now %d\n",max_script_found); */
2070}
2071
2072
2073struct CRjsnameStruct *getJSparamnames()
2074{
2075 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
2076 return p->JSparamnames;
2077}
2078void setJSparamnames(struct CRjsnameStruct *JSparamnames)
2079{
2080 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
2081 p->JSparamnames = JSparamnames;
2082}
2083
2084/********************************************************************
2085
2086JSparamIndex.
2087
2088stores ascii names with types (see code for type equivalences).
2089
2090********************************************************************/
2091
2092int JSparamIndex (const char *name, const char *type, int mod) {
2093 size_t len;
2094 int ty;
2095 int ctr;
2096 ttglobal tg = gglobal();
2097 struct CRjsnameStruct *JSparamnames = getJSparamnames();
2098
2099 #ifdef CRVERBOSE
2100 printf ("start of JSparamIndex, name %s, type %s\n",name,type);
2101 printf ("start of JSparamIndex, lengths name %d, type %d\n",
2102 strlen(name),strlen(type));
2103 #endif
2104
2105 ty = findFieldInFIELDTYPES(type);
2106
2107 #ifdef CRVERBOSE
2108 printf ("JSparamIndex, type %d, %s\n",ty,type);
2109 #endif
2110
2111 len = strlen(name);
2112 /* is this a duplicate name and type? types have to be same,
2113 name lengths have to be the same, and the strings have to be the same.
2114 */
2115 for (ctr=0; ctr<=tg->CRoutes.jsnameindex; ctr++) {
2116 if (ty==JSparamnames[ctr].type) {
2117 if ((strlen(JSparamnames[ctr].name) == len) &&
2118 (strncmp(name,JSparamnames[ctr].name,len)==0)) {
2119 #ifdef CRVERBOSE
2120 printf ("JSparamIndex, duplicate, returning %d\n",ctr);
2121 #endif
2122
2123 return ctr;
2124 }
2125 }
2126 }
2127
2128 /* nope, not duplicate */
2129
2130 tg->CRoutes.jsnameindex ++;
2131
2132 /* ok, we got a name and a type */
2133 if (tg->CRoutes.jsnameindex >= tg->CRoutes.MAXJSparamNames) {
2134 /* oooh! not enough room at the table */
2135 tg->CRoutes.MAXJSparamNames += 100; /* arbitrary number */
2136 setJSparamnames( (struct CRjsnameStruct*)REALLOC (JSparamnames, sizeof(*JSparamnames) * tg->CRoutes.MAXJSparamNames));
2137 JSparamnames = getJSparamnames();
2138 }
2139
2140 if (len > MAXJSVARIABLELENGTH-2) len = MAXJSVARIABLELENGTH-2; /* concatenate names to this length */
2141 strncpy (JSparamnames[tg->CRoutes.jsnameindex].name,name,len);
2142 JSparamnames[tg->CRoutes.jsnameindex].name[len] = 0; /* make sure terminated */
2143 JSparamnames[tg->CRoutes.jsnameindex].type = ty;
2144 JSparamnames[tg->CRoutes.jsnameindex].kind = mod;
2145 JSparamnames[tg->CRoutes.jsnameindex].eventInFunction = NULL;
2146 JSparamnames[tg->CRoutes.jsnameindex].traceable = NULL;
2147 #ifdef CRVERBOSE
2148 printf ("JSparamIndex, returning %d\n",tg->JScript.jsnameindex);
2149 #endif
2150
2151 return tg->CRoutes.jsnameindex;
2152}
2153
2154
2155
2156/********************************************************************
2157
2158propagate_events.
2159
2160Go through the event table, until the table is "active free". Some
2161nodes have eventins/eventouts - have to do the table multiple times
2162in this case.
2163
2164********************************************************************/
2165
2166//#ifdef CRVERBOSE
2167char * BOOL_STRING(int inp) {if (inp)return "true "; else return "false ";}
2168//#endif
2169
2170/*
2171 new strategy, to reduce combinations and permuations of to/from types
2172 from n x n to n + n (where n=3 (builtin, script, proto): 3x3=9 -> 3+3=6)
2173 after the introduction of PROTO instances with interfaces different
2174 than script and builtin.
2175 Steps:
2176 A. get anyVrml* of the from end - using switch/case/if/else of 3 items
2177 B. get anyVrml* of the to end - ditto of 3 items
2178 C. memcpy/shallow_copy of anyVrml for everyone
2179 D. touchup special target nodes like scripts and sensors
2180*/
2181union anyVrml* get_anyVrml(struct X3D_Node* node, int offset, int *type, int *mode)
2182{
2183 union anyVrml* fromAny;
2184 struct X3D_Node* fromNode;
2185 int fromMode, fromType, fromOffset;
2186
2187 fromType = INT_ID_UNDEFINED;
2188 fromMode = INT_ID_UNDEFINED;
2189 fromOffset = offset;
2190 fromNode = node;
2191
2192 switch(node->_nodeType)
2193 {
2194 case NODE_ShaderProgram:
2195 case NODE_ComposedShader:
2196 case NODE_PackagedShader:
2197 case NODE_Effect:
2198 case NODE_Script:
2199 {
2200 struct Shader_Script* shader = NULL;
2201 struct ScriptFieldDecl* sfield;
2202 switch(fromNode->_nodeType)
2203 {
2204 case NODE_Script: shader =(struct Shader_Script *)(X3D_SCRIPT(fromNode)->__scriptObj); break;
2205 case NODE_ComposedShader: shader =(struct Shader_Script *)(X3D_COMPOSEDSHADER(fromNode)->_shaderUserDefinedFields); break;
2206 case NODE_Effect: shader =(struct Shader_Script *)(X3D_EFFECT(fromNode)->_shaderUserDefinedFields); break;
2207 case NODE_ShaderProgram: shader =(struct Shader_Script *)(X3D_SHADERPROGRAM(fromNode)->_shaderUserDefinedFields); break;
2208 case NODE_PackagedShader: shader =(struct Shader_Script *)(X3D_PACKAGEDSHADER(fromNode)->_shaderUserDefinedFields); break;
2209 }
2210 sfield= vector_get(struct ScriptFieldDecl*, shader->fields, fromOffset);
2211 fromAny = &sfield->value;
2212 fromType = sfield->fieldDecl->fieldType;
2213 fromMode = sfield->fieldDecl->PKWmode;
2214
2215 }
2216 break;
2217 case NODE_Proto:
2218 {
2219 struct ProtoFieldDecl* pfield;
2220 struct X3D_Proto* pnode = (struct X3D_Proto*)fromNode;
2221 struct ProtoDefinition* pstruct = (struct ProtoDefinition*) pnode->__protoDef;
2222 pfield= vector_get(struct ProtoFieldDecl*, pstruct->iface, fromOffset);
2223 fromAny = &pfield->defaultVal;
2224 fromType = pfield->type;
2225 fromMode = pfield->mode;
2226 }
2227 break;
2228 default: //builtin
2229 {
2230 const int * offsets;
2231
2232 fromAny = (union anyVrml*)offsetPointer_deref(void *,fromNode , fromOffset);
2233 //I wish we had stored fromType when registering the route
2234 offsets = NODE_OFFSETS[fromNode->_nodeType];
2235 while(*offsets > -1)
2236 {
2237 //printf("%d %d %d %d %d\n",offsets[0],offsets[1],offsets[2],offsets[3],offsets[4]);
2238 if(offsets[1]==fromOffset)
2239 {
2240 fromType = offsets[2];
2241 fromMode = PKW_from_KW(offsets[3]);
2242 break;
2243 }
2244 offsets += FIELDOFFSET_LENGTH;
2245 }
2246 }
2247 break;
2248 }
2249 *mode = fromMode;
2250 *type = fromType;
2251 return fromAny;
2252}
2253
2254void cleanFieldIfManaged(int type,int mode,BOOL isPublic, struct X3D_Node* parent, int offset)
2255{
2256 //there should be a shallow_clean_field(type,toAny) that releases old mallocs
2257 // in UniString,MF p*, unlinks and/or killNodes
2258 //cleanFieldIfManaged()
2259 // 1. is toField a valueHolding field (inputOutput,initializeOnly)?
2260 // 2. if yes, is toField a node field (SFNode, MFNode)?
2261 // 3. if yes, is there something in toField now?
2262 // 4. if yes, get it, remove toNode as parent, refcount-- (let killNode in startofloopnodeupdates garbage collect it)
2263 // 5. if it was an MFNode, release the p* array
2264 //int isManagedField; //managed in the unlink_node sense, see unlink_node() killNode() policy
2265 //isManagedField = isPublic && (type == FIELDTYPE_SFNode || type == FIELDTYPE_MFNode);
2266 //isManagedField = isManagedField && (mode == PKW_initializeOnly || mode == PKW_inputOutput);
2267 //if(isManagedField)
2268 if(isManagedField(mode,type,isPublic))
2269 {
2270 int n,k,haveSomething,fromType,fromMode;
2271 struct X3D_Node **plist, *sfn;
2272 union anyVrml* any;
2273 any = get_anyVrml(parent,offset,&fromType,&fromMode);
2274 haveSomething = (type==FIELDTYPE_SFNode && any->sfnode) || (type==FIELDTYPE_MFNode && any->mfnode.n);
2275 haveSomething = haveSomething && parent;
2276 if(haveSomething){
2277 if(type==FIELDTYPE_SFNode){
2278 plist = &any->sfnode;
2279 n = 1;
2280 }else{
2281 plist = any->mfnode.p;
2282 n = any->mfnode.n;
2283 }
2284 for(k=0;k<n;k++)
2285 {
2286 sfn = plist[k];
2287 remove_parent(sfn,parent);
2288 //remove parent should return a bool if found, so we know if we can/should decrement referenceCount
2289 sfn->referenceCount--;
2290 }
2291 if(type==FIELDTYPE_MFNode) {
2292 FREE_IF_NZ(plist);
2293 }
2294 }
2295 }
2296}
2297
2298
2299void add_mfparents(struct X3D_Node* newParent, union anyVrml* mfnode, int mftype)
2300{
2301 int i;
2302 if(mftype != FIELDTYPE_MFNode) return;
2303 for(i=0;i<mfnode->mfnode.n;i++)
2304 {
2305 add_parent(mfnode->mfnode.p[i],newParent,__FILE__,__LINE__);
2306 }
2307 //case FIELDTYPE_SFNode:
2308 // {
2309 // if(source->sfnode){
2310 // memcpy(dest,source,isize);
2311 // add_parent(dest->sfnode,parent,__FILE__,__LINE__);
2312 // }else{
2313 // dest->sfnode = NULL;
2314 // }
2315 // }
2316 // break;
2317}
2318
2319//char *findFIELDNAMESfromNodeOffset0(struct X3D_Node *node, int offset);
2320char *findFIELDNAMES0(struct X3D_Node *node, int offset);
2321
2322
2323const char *stringMode(int pkwmode, int cute){
2324 const char **strmode;
2325 const char *cutemode[] = {"init","in","out","inOut" };
2326 const char *fullmode[] = {"initializeOnly","inputOnly","outputOnly","inputOutput"};
2327 strmode = fullmode;
2328 if(cute) strmode = cutemode;
2329
2330 switch(pkwmode)
2331 {
2332 case PKW_initializeOnly:
2333 return strmode[0];
2334 case PKW_inputOutput:
2335 return strmode[3];
2336 case PKW_inputOnly:
2337 return strmode[1];
2338 case PKW_outputOnly:
2339 return strmode[2];
2340 default:
2341 break;
2342 }
2343 return "_udef_"; /* gets rid of compile time warnings */
2344}
2345void print_field_value(FILE *fp, int typeIndex, union anyVrml* value);
2346
2347//bit functions - don't care about endien-ness as long as we are consistent
2348//0-based indexing ie k=0 sets the lowest bit to 1
2349void setBit(unsigned char *bitfield, int k)
2350{
2351 int kbit = k % 8;
2352 int kbyte = k / 8;
2353 bitfield[kbyte] = bitfield[kbyte] | (1 << kbit);
2354}
2355
2356void clearBit(unsigned char *bitfield, int k)
2357{
2358 int kbit = k % 8;
2359 int kbyte = k / 8;
2360 bitfield[kbyte] = bitfield[kbyte] & (~(1 << kbit));
2361}
2362
2363void toggleBit(unsigned char *bitfield, int k)
2364{
2365 int kbit = k % 8;
2366 int kbyte = k / 8;
2367 bitfield[kbyte] = bitfield[kbyte] ^ (1 << kbit);
2368}
2369int testBit(unsigned char *bitfield, int k)
2370{
2371 int kbit = k % 8;
2372 int kbyte = k / 8;
2373 return bitfield[kbyte] & (1 << kbit);
2374}
2375void printBits(unsigned char *bitfield, int nbytes){
2376 int nbits = nbytes * 8;
2377 for(int i=0;i<nbits;i++)
2378 printf("%d", testBit(bitfield,i)?1:0);
2379}
2380
2381void flag_fieldchange(struct X3D_Node * toNode,int toOffset){
2382 //to help nodes in their compile_ determine which fields changed, we want to set a bit flag
2383 //but to keep the math simple, and save some memeory, we assume all fields are some multiple
2384 // of 4 bytes in size ie float is 4, int 4, void* is 4 or 8, vec3f is 3x4,
2385 // so we take the toOffset (in bytes, from start of node struct) and devide by 4 to get
2386 // which bit flag to set (for a field thats 8 or 12 bytes we will waste / leave empty bits)
2387 int bit = toOffset / 4;
2388 setBit(toNode->_fieldchange,bit);
2389 //printf("%s\n",NODES[toNode->_nodeType]);
2390}
2391
2392void propagate_events_B() {
2393 int havinterp;
2394 int counter;
2395 int to_counter;
2396
2397 union anyVrml *fromAny, *toAny; //dug9
2398 struct X3D_Node *fromNode, *toNode, *lastFromNode;
2399 int fromOffset, toOffset, lastFromOffset, last_markme;
2400
2401 int markme;
2402
2403
2404 int len, isize, type, sftype, isMF, itime, nRoutesDone, modeFrom, modeTo, debugRoutes;
2405
2406 CRnodeStruct *to_ptr = NULL;
2407 ppCRoutes p;
2408 ttglobal tg = gglobal();
2409 p = (ppCRoutes)tg->CRoutes.prv;
2410
2411 #ifdef CRVERBOSE
2412 printf ("\npropagate_events start\n");
2413 #endif
2414 nRoutesDone = 0; //debug diagnosis
2415 type = INT_ID_UNDEFINED;
2416
2417 /* increment the "timestamp" for this entry */
2418 p->thisIntTimeStamp ++;
2419 lastFromOffset = -1; //used for from script
2420 lastFromNode = NULL; // "
2421 last_markme = FALSE; // "
2422 //#ifdef CRVERBOSE
2423 debugRoutes =0; //does a getchar() at bottom of function
2424 if(debugRoutes)
2425 printf("current time=%d routecount=%d\n",p->thisIntTimeStamp,p->CRoutes_Count);
2426 //#endif
2427
2428 do {
2429 havinterp=FALSE; /* assume no interpolators triggered */
2430
2431 for (counter = 1; counter < p->CRoutes_Count-1; counter++) {
2432 //dug9 >> fromAny
2433 //JAS union anyVrml tempAny;
2434 fromNode = p->CRoutes[counter].routeFromNode;
2435 fromOffset = p->CRoutes[counter].fnptr;
2436 itime = p->CRoutes[counter].intTimeStamp;
2437 switch(fromNode->_nodeType)
2438 {
2439 case NODE_ShaderProgram:
2440 case NODE_ComposedShader:
2441 case NODE_Effect:
2442 case NODE_PackagedShader:
2443 case NODE_Script:
2444 {
2445 //JAS struct X3D_Script* scr = (struct X3D_Script*)fromNode;
2446 struct Shader_Script* shader = NULL;
2447 struct ScriptFieldDecl* sfield;
2448 switch(fromNode->_nodeType)
2449 {
2450 case NODE_Script: shader =(struct Shader_Script *)(X3D_SCRIPT(fromNode)->__scriptObj); break;
2451 case NODE_ComposedShader: shader =(struct Shader_Script *)(X3D_COMPOSEDSHADER(fromNode)->_shaderUserDefinedFields); break;
2452 case NODE_Effect: shader =(struct Shader_Script *)(X3D_EFFECT(fromNode)->_shaderUserDefinedFields); break;
2453 case NODE_ShaderProgram: shader =(struct Shader_Script *)(X3D_SHADERPROGRAM(fromNode)->_shaderUserDefinedFields); break;
2454 case NODE_PackagedShader: shader =(struct Shader_Script *)(X3D_PACKAGEDSHADER(fromNode)->_shaderUserDefinedFields); break;
2455 }
2456 sfield= vector_get(struct ScriptFieldDecl*, shader->fields, fromOffset);
2457 fromAny = &sfield->value;
2458
2459 type = sfield->fieldDecl->fieldType;
2460 isMF = type % 2;
2461 sftype = type - isMF;
2462 //from EAI_C_CommonFunctions.c
2463 //isize = returnElementLength(sftype) * returnElementRowSize(sftype);
2464 isize = sizeofSForMF(sftype);
2465 if(isMF) len = sizeof(int) + sizeof(void*);
2466 else len = isize;
2467 modeFrom = sfield->fieldDecl->PKWmode;
2468
2469
2470 if(fromNode->_nodeType == NODE_Script){
2471 //continue; //let the gatherScriptEventOuts(); copy directly toNode.
2472 //there's an expensive operation in here, and the route fanout doesn't work
2473 //so we'll check if this is the same fromNode/fromOffset as the last loop and skip
2474 markme = last_markme;
2475 if(!(fromNode==lastFromNode && fromOffset==lastFromOffset)){
2476#ifdef JAVASCRIPT_SM
2477 if(SM_method() == 0){
2478 //gatherScriptEventOut_B copies from javascript to the script field ->value
2479 int JSparamNameIndex = sfield->fieldDecl->JSparamNameIndex;
2480 markme = gatherScriptEventOut_B(fromAny,shader,JSparamNameIndex,type,0,len);
2481 }else
2482#endif //JAVASCRIPT_SM
2483 {
2484 // Jan 2 - seems like all we needed was valueChanged, which method2 updates automatically
2485 markme = sfield->valueChanged;
2486 //printf("fromAny.sffloat %f\n",fromAny->sffloat);
2487 sfield->valueChanged = 0;
2488 }
2489
2490 }
2491 if(markme){
2492 if (p->CRoutes[counter].intTimeStamp!=p->thisIntTimeStamp) {
2493 p->CRoutes[counter].isActive=TRUE;
2494 p->CRoutes[counter].intTimeStamp=p->thisIntTimeStamp;
2495 }
2496 }
2497 last_markme = markme;
2498 }
2499
2500
2501
2502 }
2503 break;
2504 case NODE_Proto:
2505 {
2506 struct ProtoFieldDecl* pfield;
2507 struct X3D_Proto* pnode = (struct X3D_Proto*)fromNode;
2508 struct ProtoDefinition* pstruct = (struct ProtoDefinition*) pnode->__protoDef;
2509 pfield= vector_get(struct ProtoFieldDecl*, pstruct->iface, fromOffset);
2510 fromAny = &pfield->defaultVal;
2511 type = pfield->type;
2512 modeFrom = pfield->mode;
2513 }
2514 break;
2515 default: //builtin
2516 {
2517 const int * offsets;
2518
2519 fromAny = (union anyVrml*)offsetPointer_deref(void *,fromNode , fromOffset);
2520 //I wish we had stored fromType when registering the route
2521 offsets = NODE_OFFSETS[fromNode->_nodeType];
2522 while(*offsets > -1)
2523 {
2524 //printf("%d %d %d %d %d\n",offsets[0],offsets[1],offsets[2],offsets[3],offsets[4]);
2525 if(offsets[1]==fromOffset)
2526 {
2527 type = offsets[2];
2528 modeFrom = PKW_from_KW(offsets[3]);
2529 break;
2530 }
2531 offsets += FIELDOFFSET_LENGTH;
2532 }
2533 }
2534 break;
2535 }
2536
2537
2538 isMF = type % 2;
2539 sftype = type - isMF;
2540 //from EAI_C_CommonFunctions.c
2541 //isize = returnElementLength(sftype) * returnElementRowSize(sftype);
2542 isize = sizeofSForMF(sftype);
2543 if(isMF) len = sizeof(int) + sizeof(void*);
2544 else len = isize;
2545
2546
2547 for (to_counter = 0; to_counter < p->CRoutes[counter].tonode_count; to_counter++) {
2548 modeTo = PKW_inputOnly;
2549 to_ptr = &(p->CRoutes[counter].tonodes[to_counter]);
2550 if (to_ptr == NULL) {
2551 printf("WARNING: tonode at %u is NULL in propagate_events.\n",
2552 to_counter);
2553 continue;
2554 }
2555
2556 #ifdef CRVERBOSE
2557 printf("propagate_events: counter %d to_counter %u act %s from %u off %u to %u off %u oint %u dir %d\n",
2558 counter, to_counter, BOOL_STRING(p->CRoutes[counter].isActive),
2559 p->CRoutes[counter].routeFromNode, p->CRoutes[counter].fnptr,
2560 to_ptr->routeToNode, to_ptr->foffset, p->CRoutes[counter].interpptr,
2561 p->CRoutes[counter].direction_flag);
2562 #endif
2563
2564 if (p->CRoutes[counter].isActive == TRUE) {
2565 /* first thing, set this to FALSE */
2566 p->CRoutes[counter].isActive = FALSE;
2567 /* to get routing to/from exposedFields, lets
2568 * mark this to/offset as an event */
2569 //MARK_EVENT (to_ptr->routeToNode, to_ptr->foffset);
2570
2571
2572 //dug9 >> toAny
2573 toAny = NULL;
2574 toNode = to_ptr->routeToNode; //p->CRoutes[counter].routeFromNode;
2575 toOffset = to_ptr->foffset; //p->CRoutes[counter].fnptr;
2576 //MARK_EVENT(toNode, toOffset);
2577
2578 // EAI RegisterListener gives a node of NULL, so...
2579 if (toNode != NULL) {
2580 switch(toNode->_nodeType)
2581 {
2582 case NODE_ShaderProgram:
2583 case NODE_ComposedShader:
2584 case NODE_PackagedShader:
2585 case NODE_Effect:
2586 case NODE_Script:
2587 {
2588 struct Shader_Script* shader = NULL;
2589 struct ScriptFieldDecl* sfield;
2590 switch(toNode->_nodeType)
2591 {
2592 case NODE_Script: shader =(struct Shader_Script *)(X3D_SCRIPT(toNode)->__scriptObj); break;
2593 case NODE_ComposedShader: shader =(struct Shader_Script *)(X3D_COMPOSEDSHADER(toNode)->_shaderUserDefinedFields); break;
2594 case NODE_Effect: shader =(struct Shader_Script *)(X3D_EFFECT(toNode)->_shaderUserDefinedFields); break;
2595 case NODE_ShaderProgram: shader =(struct Shader_Script *)(X3D_SHADERPROGRAM(toNode)->_shaderUserDefinedFields); break;
2596 case NODE_PackagedShader: shader =(struct Shader_Script *)(X3D_PACKAGEDSHADER(toNode)->_shaderUserDefinedFields); break;
2597 }
2598 sfield= vector_get(struct ScriptFieldDecl*, shader->fields, toOffset);
2599 toAny = &sfield->value;
2600 modeTo = sfield->fieldDecl->PKWmode;
2601 }
2602 break;
2603 case NODE_Proto:
2604 {
2605 struct ProtoFieldDecl* pfield;
2606 struct X3D_Proto* pnode = (struct X3D_Proto*)toNode;
2607 struct ProtoDefinition* pstruct = (struct ProtoDefinition*) pnode->__protoDef;
2608 pfield= vector_get(struct ProtoFieldDecl*, pstruct->iface, toOffset);
2609 toAny = &pfield->defaultVal;
2610 modeTo = pfield->mode;
2611 }
2612 break;
2613 default: //builtin
2614 toAny = (union anyVrml*)offsetPointer_deref(void *,toNode , toOffset);
2615 //I wish we stored toMode when registering the route
2616 {
2617 const int *offsets = NODE_OFFSETS[toNode->_nodeType];
2618 while(*offsets > -1)
2619 {
2620 //printf("%d %d %d %d %d\n",offsets[0],offsets[1],offsets[2],offsets[3],offsets[4]);
2621 if(offsets[1]==fromOffset)
2622 {
2623 modeTo = PKW_from_KW(offsets[3]);
2624 break;
2625 }
2626 offsets += FIELDOFFSET_LENGTH;
2627 }
2628 }
2629 break;
2630 }
2631 } // of toNode != NULL...
2632
2633 //we now have from and to as *anyVrml, so lets copy
2634 //there should be a shallow_clean_field(type,toAny) that releases old mallocs
2635 // in UniString,MF p*, unlinks and/or killNodes
2636 //clean_field()
2637 // 1. is toField a valueHolding field (inputOutput,initializeOnly)?
2638 // 2. if yes, is toField a node field (SFNode, MFNode)?
2639 // 3. if yes, is there something in toField now?
2640 // 4. if yes, get it, remove toNode as parent, refcount-- (let killNode in startofloopnodeupdates garbage collect it)
2641 // 5. if it was an MFNode, release the p* array
2642
2643 // EAI RegisterListener gives a node of NULL, so...
2644 if (toNode != NULL) {
2645 cleanFieldIfManaged(type,modeTo,1,toNode,toOffset); //see unlink_node/killNode policy
2646
2647 shallow_copy_field(type,fromAny,toAny);
2648 flag_fieldchange(toNode,toOffset); //May 2020 - want to set a bit for the particular field that changed
2649 //if(isMF && sftype == FIELDTYPE_SFNode)
2650 // add_mfparents(toNode,toAny,type);
2651 registerParentIfManagedField(type,modeTo,1, toAny, toNode); //see unlink_node/killNode policy
2652
2653 }
2654
2655
2656 //OK we copied.
2657 //if(extra == 1 || extra == -1)
2658 mark_event_B(fromNode,fromOffset, toNode, toOffset);
2659 //MARK_EVENT(toNode, toOffset);
2660
2661 //#ifdef CRVERBOSE
2662 if(debugRoutes){
2663 char *fromName, *toName, *fromFieldName, *toFieldName, *fromModeName, *toModeName, *fromNodeType, *toNodeType;
2664 char fromNameP[100], toNameP[100];
2665 sprintf(fromNameP,"%p",fromNode);
2666 sprintf(toNameP,"%p",toNode);
2667 fromName = parser_getNameFromNode(fromNode);
2668 if(!fromName) fromName = &fromNameP[0];
2669 toName = parser_getNameFromNode(toNode);
2670 if(!toName) toName = &toNameP[0];
2671 fromFieldName = findFIELDNAMES0(fromNode,fromOffset);
2672 toFieldName = findFIELDNAMES0(toNode,toOffset);
2673 if(!toName) toName = &toNameP[0];
2674 fromNodeType = (char *)stringNodeType(fromNode->_nodeType);
2675 if(fromNode->_nodeType == NODE_Proto)
2676 fromNodeType = ((struct ProtoDefinition*)(X3D_PROTO(fromNode)->__protoDef))->protoName;
2677 toNodeType = (char *)stringNodeType(toNode->_nodeType);
2678 if(toNode->_nodeType == NODE_Proto)
2679 toNodeType = ((struct ProtoDefinition*)(X3D_PROTO(toNode)->__protoDef))->protoName;
2680 fromModeName = (char *)stringMode(modeFrom,1);
2681 toModeName = (char *)stringMode(modeTo, 1);
2682 printf(" %s %s.%s %s TO %s %s.%s %s %d ",fromNodeType,fromName,fromFieldName,fromModeName,
2683 toNodeType,toName,toFieldName,toModeName,itime);
2684 print_field_value(stdout,type,toAny);
2685 printf("\n");
2686
2687 }
2688 //#endif
2689 nRoutesDone++;
2690 //Some target node types need special processing ie sensors and scripts
2691 // EAI RegisterListener gives a node of NULL, so...
2692 if (toNode != NULL) {
2693 switch(toNode->_nodeType)
2694 {
2695 case NODE_Script:
2696 {
2697
2698 struct Shader_Script* shader;
2699 struct ScriptFieldDecl* sfield;
2700 shader =(struct Shader_Script *)(X3D_SCRIPT(toNode)->__scriptObj);
2701 //{
2702 // int kk;
2703 // struct CRjsnameStruct *JSparamnames; // = getJSparamnames();
2704 // JSObject *eventInFunction;
2705 // JSparamnames = getJSparamnames();
2706
2707 // for(kk=0;kk<shader->fields->n;kk++)
2708 // {
2709 // sfield= vector_get(struct ScriptFieldDecl*, shader->fields, kk);
2710 // //printf("sfield[%d]=%d",kk,sfield->fieldDecl->JSparamNameIndex);
2711 // eventInFunction = JSparamnames[sfield->fieldDecl->JSparamNameIndex].eventInFunction;
2712 // //printf(" func= %d\n",eventInFunction);
2713 // }
2714
2715 //}
2716 sfield= vector_get(struct ScriptFieldDecl*, shader->fields, toOffset);
2717
2718 //if (p->ScriptControl[shader->num]._initialized && p->ScriptControl[shader->num].scriptOK)
2719 if(isScriptControlInitialized(shader->num) && isScriptControlOK(shader->num))
2720 {
2721 int JSparamNameIndex = sfield->fieldDecl->JSparamNameIndex;
2722 /* mark that this script has been active SCRIPTS ARE INTEGER NUMBERS */
2723 mark_script(shader->num);
2724 if(isMF){
2725 // note the casting of parameter 4, the toAny type, seems unnecessary, bureaucratic
2726 getField_ToJavascript_B(shader->num, JSparamNameIndex, type, (union anyVrml* ) toAny->mfnode.p, toAny->mfnode.n); //mfp->p, mfp->n);
2727 } else {
2728 getField_ToJavascript_B(shader->num, JSparamNameIndex, type, toAny, len);
2729 }
2730 }else{
2731 /* printf ("waiting for initializing script %d at %s:%d\n",(uintptr_t)to_ptr->routeToNode, __FILE__,__LINE__); */
2732 }
2733 havinterp = TRUE;
2734 }
2735 break;
2736 case NODE_ShaderProgram:
2737 case NODE_ComposedShader:
2738 //case NODE_Effect: //an effect can apply to many compiled shader permutations, so update done in child_shape per appearance
2739 case NODE_PackagedShader:
2740 {
2741 // note, "shader" can not be NULL here...
2742 // otherwise we'd never be here in this switch
2743 getField_ToShader(toNode, toOffset, toAny, type); //feb2015 shader->num);
2744 havinterp = TRUE;
2745 }
2746 break;
2747 default:
2748 havinterp = FALSE;
2749 break;
2750 }
2751 } // end of test for toNode == NULL
2752
2753 if (p->CRoutes[counter].interpptr != 0)
2754 {
2755 /* this is an interpolator, call it */
2756 havinterp = TRUE;
2757 #ifdef CRVERBOSE
2758 printf("propagate_events: index %d is an interpolator\n",counter);
2759 #endif
2760 /* copy over this "extra" data, EAI "advise" calls need this */
2761
2762 tg->CRoutes.CRoutesExtra = p->CRoutes[counter].extra;
2763
2764 p->CRoutes[counter].interpptr((void *)(toNode));
2765 } else {
2766 /* just an eventIn node. signal to the reciever to update */
2767 //marked above
2768 //MARK_EVENT(toNode, toOffset);
2769
2770 /* make sure that this is pointing to a real node,
2771 * not to a block of memory created by
2772 * EAI - extra memory - if it has an offset of
2773 * zero, it is most certainly made.
2774 * dug9,feb2013: with new Broto code I changed Proto and Script offset
2775 * to field index (0 to nfield-1) (instead of offset=JSparamNameIndex)
2776 */
2777 //dug9 if(toOffset != 0)
2778 update_node(toNode);
2779 }
2780 } //if isActive
2781 } //for(to_counter)
2782 lastFromNode = fromNode;
2783 lastFromOffset = fromOffset;
2784 } //for(counter)
2785
2786 /* run gatherScriptEventOuts for each active script */
2787 havinterp = havinterp || runQueuedDirectOutputs();
2788 //gatherScriptEventOuts();
2789
2790 } while (havinterp==TRUE);
2791
2792 /* now, go through and clean up all of the scripts */
2793 for (counter =0; counter <= tg->CRoutes.max_script_found_and_initialized; counter++) {
2794 struct CRscriptStruct *sc = getScriptControlIndex(counter);
2795 if(sc)
2796 if (sc->scr_act){ //p->scr_act[counter]) {
2797 sc->scr_act = FALSE; //p->scr_act[counter] = FALSE;
2798 js_cleanup_script_context(counter);
2799 //CLEANUP_JAVASCRIPT(p->ScriptControl[counter].cx);
2800 }
2801 }
2802
2803 if(debugRoutes){
2804 printf(" *\n");
2805 if(nRoutesDone)
2806 getchar();
2807 }
2808 #ifdef CRVERBOSE
2809 printf ("done propagate_events\n\n");
2810 #endif
2811}
2812void propagate_events()
2813{
2814 propagate_events_B();
2815}
2816
2817
2818/*******************************************************************
2819
2820do_first()
2821
2822
2823Call the sensor nodes to get the results of the clock ticks; this is
2824the first thing in the event loop.
2825
2826********************************************************************/
2827void printStatsEvents(){
2828 ConsoleMessage("%25s %d\n","ClockEvent count", ((ppCRoutes)gglobal()->CRoutes.prv)->num_ClockEvents);
2829}
2830void usehit_clear();
2831void do_first() {
2832 int counter, ne;
2833 struct FirstStruct ce;
2834 /* go through the array; add_first will NOT add a null pointer
2835 to either field, so we don't need to bounds check here */
2836 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
2837
2838 if(0){
2839 ne = p->num_ClockEvents;
2840 for (counter =0; counter < ne; counter ++) {
2841 ce = p->ClockEvents[counter];
2842 if (ce.tonode) {
2843 ce.interpptr(ce.tonode);
2844 }
2845 }
2846 //for (counter = 0; counter < p->num_ClockEvents; counter++) {
2847 // if (p->ClockEvents[counter].tonode)
2848 // p->ClockEvents[counter].interpptr(p->ClockEvents[counter].tonode);
2849 //}
2850
2851 /* now, propagate these events */
2852 propagate_events();
2853 }
2854
2855 /* any new routes waiting in the wings for buffering to happen? */
2856 /* Note - rTr will be incremented by either parsing (in which case,
2857 events are not run, correct?? or by a script within a route,
2858 which will be this thread, or by EAI, which will also be this
2859 thread, so the following should be pretty thread_safe */
2860
2861 if (p->routesToRegister != NULL) {
2862 MUTEX_LOCK_ROUTING_UPDATES
2863 actually_do_CRoutes_Register();
2864 MUTEX_FREE_LOCK_ROUTING_UPDATES
2865 }
2866
2867 /* any mark_events kicking around, waiting for someone to come in and tell us off?? */
2868 /* CRoutes_Inititated should be set here, as it would have been created in
2869 actually_do_CRoutes_Register */
2870 if (p->preEvents != NULL) {
2871 if (p->CRoutes_Initiated) {
2872 LOCK_PREROUTETABLE
2873
2874 #ifdef CRVERBOSE
2875 printf ("doing preEvents, we have %d events \n",p->initialEventBeforeRoutesCount);
2876 #endif
2877
2878 for (counter = 0; counter < p->initialEventBeforeRoutesCount; counter ++) {
2879 MARK_EVENT(p->preEvents[counter].from, p->preEvents[counter].totalptr);
2880 }
2881 p->initialEventBeforeRoutesCount = 0;
2882 p->preRouteTableSize = 0;
2883 FREE_IF_NZ(p->preEvents);
2884 UNLOCK_PREROUTETABLE
2885 }
2886 }
2887
2888 if(1){
2889 // http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/concepts.html#ExecutionModel
2890 // if the do_ are b. Evaluate Sensors, and propagate_events are c. evaluate Routes,
2891 // and according to d. if any events generated repeate b, c,
2892 // then we should in theory have a loop here
2893 // (but looks like we don't, so sensors done once per loop.
2894 // But script eval in propagate events is in that route loop)
2895 //all the do_ functions are called here
2896 ne = p->num_ClockEvents;
2897 for (counter =0; counter < ne; counter ++) {
2898 ce = p->ClockEvents[counter];
2899 if (ce.tonode) {
2900 ce.interpptr(ce.tonode);
2901 }
2902 }
2903 usehit_clear();
2904 //for (counter = 0; counter < p->num_ClockEvents; counter++) {
2905 // if (p->ClockEvents[counter].tonode)
2906 // p->ClockEvents[counter].interpptr(p->ClockEvents[counter].tonode);
2907 //}
2908
2909 /* now, propagate these events */
2910 propagate_events();
2911 }
2912
2913}
2914
2915
2916/*******************************************************************
2917
2918Interface to allow EAI/SAI to get routing information.
2919
2920********************************************************************/
2921
2922int getRoutesCount(void) {
2923 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
2924
2925 return p->CRoutes_Count;
2926}
2927
2928void getSpecificRoute (int routeNo, struct X3D_Node **fromNode, int *fromOffset,
2929 struct X3D_Node **toNode, int *toOffset) {
2930 CRnodeStruct *to_ptr = NULL;
2931 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
2932
2933
2934 if ((routeNo <1) || (routeNo >= p->CRoutes_Count)) {
2935 *fromNode = NULL; *fromOffset = 0; *toNode = NULL; *toOffset = 0;
2936 }
2937/*
2938 printf ("getSpecificRoute, fromNode %d fromPtr %d tonode_count %d\n",
2939 CRoutes[routeNo].routeFromNode, CRoutes[routeNo].fnptr, CRoutes[routeNo].tonode_count);
2940*/
2941 *fromNode = p->CRoutes[routeNo].routeFromNode;
2942 *fromOffset = p->CRoutes[routeNo].fnptr;
2943 /* there is not a case where tonode_count != 1 for a valid route... */
2944 if (p->CRoutes[routeNo].tonode_count != 1) {
2945 printf ("huh? tonode count %d\n",p->CRoutes[routeNo].tonode_count);
2946 *toNode = 0; *toOffset = 0;
2947 return;
2948 }
2949
2950 /* get the first toNode,toOffset */
2951 to_ptr = &(p->CRoutes[routeNo].tonodes[0]);
2952 *toNode = to_ptr->routeToNode;
2953 *toOffset = to_ptr->foffset;
2954
2955
2956
2957
2958}
2959/*******************************************************************
2960
2961kill_routing()
2962
2963Stop routing, remove structure. Used for ReplaceWorld style calls.
2964
2965********************************************************************/
2966
2967void kill_routing (void) {
2968 ppCRoutes p = (ppCRoutes)gglobal()->CRoutes.prv;
2969
2970 //ConsoleMessage ("kill_routing called\n");
2971
2972 if (p->CRoutes_Initiated) {
2973 p->CRoutes_Initiated = FALSE;
2974 p->CRoutes_Count = 0;
2975 p->CRoutes_MAX = 0;
2976 FREE_IF_NZ (p->CRoutes);
2977 }
2978 printf ("kill_routing done\n");
2979}
2980
2981
2982/* internal variable to copy a C structure's Multi* field */
2983void Multimemcpy (struct X3D_Node *toNode, struct X3D_Node *fromNode, void *tn, void *fn, size_t multitype) {
2984 size_t structlen;
2985 int fromcount;
2986
2987 #ifdef CRVERBOSE
2988 int tocount;
2989 #endif
2990
2991 void *fromptr, *toptr;
2992
2993 struct Multi_Vec3f *mv3ffn, *mv3ftn;
2994
2995 #ifdef CRVERBOSE
2996 printf ("Multimemcpy, copying structures from %p (%s) to %p (%s) %p %p type %d\n",
2997 fromNode, stringNodeType(fromNode->_nodeType),
2998 toNode, stringNodeType(toNode->_nodeType),
2999
3000 tn,fn,multitype);
3001 #endif
3002
3003 /* copy a complex (eg, a MF* node) node from one to the other
3004 grep for the ROUTING_SF and ROUTING_MF defines to see them all. */
3005
3006 /* Multi_XXX nodes always consist of a count then a pointer - see
3007 Structs.h */
3008
3009 /* making the input pointers into a (any) structure helps deciphering params */
3010 mv3ffn = (struct Multi_Vec3f *)fn;
3011 mv3ftn = (struct Multi_Vec3f *)tn;
3012
3013 /* so, get the from memory pointer, and the to memory pointer from the structs */
3014 fromptr = (void *)mv3ffn->p;
3015
3016 /* and the from and to sizes */
3017 fromcount = mv3ffn->n;
3018 //printf("fn = %u value *fn = %u fromcount = %u\n",(unsigned int)fn, *(unsigned int *)fn, (unsigned int) fromcount);
3019
3020 #ifdef CRVERBOSE
3021 tocount = mv3ftn->n;
3022 printf ("Multimemcpy, fromcount %d\n",fromcount);
3023 #endif
3024
3025 /* get the structure length */
3026 switch (multitype) {
3027 case ROUTING_SFNODE: structlen = sizeof (void *); break;
3028 case ROUTING_MFNODE: structlen = sizeof (void *); break;
3029 case ROUTING_SFIMAGE: structlen = sizeof (void *); break;
3030 case ROUTING_MFSTRING: structlen = sizeof (void *); break;
3031 case ROUTING_MFFLOAT: structlen = sizeof (float); break;
3032 case ROUTING_MFROTATION: structlen = sizeof (struct SFRotation); break;
3033 case ROUTING_MFINT32: structlen = sizeof (int); break;
3034 case ROUTING_MFCOLOR: structlen = sizeof (struct SFColor); break;
3035 case ROUTING_MFVEC2F: structlen = sizeof (struct SFVec2f); break;
3036 case ROUTING_MFVEC3F: structlen = sizeof (struct SFColor); break; /* This is actually SFVec3f - but no struct of this type */
3037 case ROUTING_MFVEC3D: structlen = sizeof (struct SFVec3d); break;
3038 case ROUTING_MFDOUBLE: structlen = sizeof (double); break;
3039 case ROUTING_MFMATRIX4F: structlen = sizeof (struct SFMatrix4f); break;
3040 case ROUTING_MFMATRIX4D: structlen = sizeof (struct SFMatrix4d); break;
3041 case ROUTING_MFVEC2D: structlen = sizeof (struct SFVec2d); break;
3042 case ROUTING_MFVEC4F: structlen = sizeof (struct SFVec4f); break;
3043 case ROUTING_MFVEC4D: structlen = sizeof (struct SFVec4d); break;
3044 case ROUTING_MFMATRIX3F: structlen = sizeof (struct SFMatrix3f); break;
3045 case ROUTING_MFMATRIX3D: structlen = sizeof (struct SFMatrix3d); break;
3046
3047 case ROUTING_SFSTRING: {
3048 /* SFStrings are "special" */
3049 /* remember:
3050 struct Uni_String {
3051 int len;
3052 char * strptr;
3053 int touched;
3054 };
3055 */
3056 struct Uni_String *fStr;
3057 struct Uni_String *tStr;
3058
3059 /* get the CONTENTS of the fn and tn pointers */
3060 memcpy (&fStr,fn,sizeof (void *));
3061 memcpy (&tStr,tn,sizeof (void *));
3062
3063
3064 /* printf ("copying over a SFString in Multi from %u to %u\n",fStr, tStr);
3065 printf ("string was :%s:\n",tStr->strptr); */
3066 verify_Uni_String(tStr, fStr->strptr);
3067 /* printf ("string is :%s:\n",tStr->strptr); */
3068 return; /* we have done the needed stuff here */
3069 break;
3070 }
3071 default: {
3072 /* this is MOST LIKELY for an EAI handle_Listener call - if not, it is a ROUTING problem... */
3073 /* printf("WARNING: Multimemcpy, don't handle type %d yet\n", multitype); */
3074 structlen=0;
3075 return;
3076 }
3077 }
3078
3079
3080 if(multitype==ROUTING_SFNODE){
3081 /* and do the copy of the data */
3082 memcpy (tn,fn,structlen);
3083 //*(unsigned int)toptr = (unsigned int)fromcount;
3084 //memcpy(toptr,&fromcount,structlen);
3085 //printf("tn=%u *tn=%u\n",tn,*(unsigned int *)tn);
3086 }else{
3087 int nele = fromcount;
3088 FREE_IF_NZ (mv3ftn->p);
3089 /* MALLOC the toptr */
3090 if( multitype == ROUTING_MFNODE ) nele = (int) upper_power_of_two(nele);
3091 mv3ftn->p = MALLOC (struct SFVec3f *, structlen*nele); //fromcount);
3092 toptr = (void *)mv3ftn->p;
3093
3094 /* tell the recipient how many elements are here */
3095 mv3ftn->n = fromcount;
3096
3097 #ifdef CRVERBOSE
3098 printf ("Multimemcpy, fromcount %d tocount %d fromptr %p toptr %p\n",fromcount,tocount,fromptr,toptr);
3099 #endif
3100
3101 /* and do the copy of the data */
3102 memcpy (toptr,fromptr,structlen * fromcount);
3103 }
3104 /* is this an MFNode or SFNode? */
3105 {
3106 //ppEAICore p = (ppEAICore)gglobal()->EAICore.prv;
3107
3108
3109
3110
3111 if (toNode != NULL) {
3112 if (multitype==ROUTING_SFNODE) {
3113 //unsigned int fnvalue;
3114 //unsigned int *fnlocation;
3115 union anyVrml *any;
3116 struct X3D_Node *sfnodeptr;
3117 //fnlocation = (unsigned int*)fn;
3118 //fnvalue= *fnlocation;
3119 //sfnodeptr = (struct X3D_Node*)fnvalue;
3120 any = (union anyVrml*)fn;
3121 sfnodeptr = any->sfnode;
3122#ifdef CRVERBOSE
3123 printf ("got a ROUTING_SFNODE, adding %u to %u\n",(unsigned int) fn, (unsigned int) toNode);
3124#endif
3125 ADD_PARENT(X3D_NODE(sfnodeptr),toNode);
3126 }
3127 if (multitype==ROUTING_MFNODE) {
3128 int count;
3129 struct X3D_Node **arrptr = (struct X3D_Node **)mv3ffn->p;
3130
3131 #ifdef CRVERBOSE
3132 printf ("fromcount %d tocount %d\n",fromcount, tocount);
3133 printf ("ROUTING - have to add parents... \n");
3134 #endif
3135
3136 for (count = 0; count < mv3ffn->n; count++) {
3137 #ifdef CRVERBOSE
3138 printf ("node in place %d is %u ",count,arrptr[count]);
3139 printf ("%s ",stringNodeType(arrptr[count]->_nodeType));
3140 printf ("\n");
3141 #endif
3142
3143 ADD_PARENT(arrptr[count],toNode);
3144 }
3145 }
3146 }
3147 }
3148}
3149
3150
3151/*********************************************************************************************/
3152
3153
3154#ifdef HAVE_OPENCL
3155static bool canRouteOnGPUTo(struct X3D_Node *me) {
3156 int i;
3157
3158 if (me == NULL) return FALSE;
3159 printf ("canRouteOnGPUTo = %s\n",stringNodeType(me->_nodeType));
3160 for (i=0; i< vectorSize(me->_parentVector); i++) {
3161 struct X3D_Node *par = vector_get(struct X3D_Node *,me->_parentVector,i);
3162 printf ("parent %d is a %s\n",i,stringNodeType(par->_nodeType));
3163 switch (par->_nodeType) {
3164 case NODE_TriangleSet :
3165 case NODE_IndexedTriangleSet:
3166 return TRUE;
3167 break;
3168 default: return FALSE;
3169 }
3170 }
3171
3172 return TRUE;
3173
3174}
3175#endif //HAVE_OPENCL