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