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