[xiph-commits] r14003 - trunk/sushivision

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Tue Oct 16 15:01:54 PDT 2007


Author: xiphmont
Date: 2007-10-16 15:01:53 -0700 (Tue, 16 Oct 2007)
New Revision: 14003

Modified:
   trunk/sushivision/example_fractal.c
   trunk/sushivision/objective.h
   trunk/sushivision/panel-2d.c
   trunk/sushivision/panel-2d.h
   trunk/sushivision/plane-2d.c
   trunk/sushivision/plane.h
Log:
Ongoing work (moving to another machine)


Modified: trunk/sushivision/example_fractal.c
===================================================================
--- trunk/sushivision/example_fractal.c	2007-10-16 17:04:07 UTC (rev 14002)
+++ trunk/sushivision/example_fractal.c	2007-10-16 22:01:53 UTC (rev 14003)
@@ -78,14 +78,12 @@
 		    "100000:one hundred thousand");
   sv_dim_set_value(10000);
 
-  sv_obj_new("outer",fractal_objective,"rc,ic,rz,iz,it", "Z,*");
-  sv_obj_make_scale("0, .001, .01, .1, 1.0");
+  sv_obj_new("fractal",fractal_objective,"rc,ic,rz,iz,it", "outer,inner");
+  sv_obj_make_scale("outer","0, .001, .01, .1, 1.0");
+  sv_obj_make_scale("inner","0, .001, .01, .1, 1.0");
   
-  sv_obj_new("inner",fractal_objective,"rc,ic,rz,iz,it", "*,Z");
-  sv_obj_make_scale("0, .001, .01, .1, 1.0");
-  
   sv_panel_new_2d(0,"Mandel/Julia Fractal",
-		  "inner, outer",
+		  "fractal(2d,Z=inner), fractal(2d,Z=outer)",
 		  "rc(X,Y), ic(X,Y), rz(X,Y), iz(X,Y), it",
 		  0);
   

Modified: trunk/sushivision/objective.h
===================================================================
--- trunk/sushivision/objective.h	2007-10-16 17:04:07 UTC (rev 14002)
+++ trunk/sushivision/objective.h	2007-10-16 22:01:53 UTC (rev 14003)
@@ -28,7 +28,7 @@
 
   void (*function)(double *,double *);
   int inputs;
-  sv_dim_t **input_dims;
+  int *input_dims;
   int outputs;
   int *output_axes;
 

Modified: trunk/sushivision/panel-2d.c
===================================================================
--- trunk/sushivision/panel-2d.c	2007-10-16 17:04:07 UTC (rev 14002)
+++ trunk/sushivision/panel-2d.c	2007-10-16 22:01:53 UTC (rev 14003)
@@ -154,6 +154,11 @@
   pthread_mutex_lock(p->status_m);
 
   // recomute setup
+
+  // plane recompute calls will do nothing if recomputation is not
+  // required.  Even if computation not required, will still request
+  // an image resize; the image resize code will later noop if there's
+  // no need to resize either.
   if(p->recompute_pending){
     p->recompute_pending=0;
     p->comp_serialno++;
@@ -183,6 +188,8 @@
   serialno = p->comp_serialno;
 
   // image resize
+
+  // again, each plane checks to see if a resize is really necessary.  If not, does nothing.
   if(p->image_resize){
     status = plane_loop(p,&p->image_next_plane,image_resize);
     if(status == STATUS_WORKING) return done_working(p);

Modified: trunk/sushivision/panel-2d.h
===================================================================
--- trunk/sushivision/panel-2d.h	2007-10-16 17:04:07 UTC (rev 14002)
+++ trunk/sushivision/panel-2d.h	2007-10-16 22:01:53 UTC (rev 14003)
@@ -23,25 +23,28 @@
   pthread_rwlock_t panel_m;
   pthread_mutex_t  status_m;
   
-  // request payload (locked by status)
+  // mem and data locked by status_m
   int               recompute_pending;
-  int               dims;
-  int               w;
+  int               dims; 
+  int               w; 
   int               h;
-  int               xdim;
-  int               ydim;
   sv_dim_data_t    *dim_data;
 
-  // composite 'background' plane
-  _sv_plane_bg_t *bg;
+  // axis 0 == X 
+  // axis 1 == Y 
+  // axis 2 == Z
+  // >2 == auxiliary axes
+  char            **axis_names;
+  int              *axis_dims;
+  int               axes;
 
-  // objective planes
+  // locked by panel_m
+  _sv_plane_bg_t *bg; // composite background plane
+
   int planes;
   _sv_plane_t **plane_list;
   int next_plane; 
-  pthread_mutex_t  planelock; // locks plane status, not data
-  
-  // UI elements
+
   GtkWidget *obj_table;
   GtkWidget *dim_table;
 
@@ -52,8 +55,7 @@
 
   _sv_dim_widget_t *x_scale; // pointer to current X axis dimwidget
   _sv_dim_widget_t *y_scale; // pointer to current Y axis dimwidget
-  int x_dnum; // panel, not global list context
-  int y_dnum; // panel, not global list context
+  //_sv_dim_widget_t *z_scale; // pointer to current Z axis dimwidget
 
 } _sv_panel2d_t;
 

Modified: trunk/sushivision/plane-2d.c
===================================================================
--- trunk/sushivision/plane-2d.c	2007-10-16 17:04:07 UTC (rev 14002)
+++ trunk/sushivision/plane-2d.c	2007-10-16 22:01:53 UTC (rev 14003)
@@ -125,7 +125,7 @@
     float idel = pl->resample_yscalemul * pl->resample_xscalemul;
     
     /* by column */
-    /* XXXXX by row would be far more efficient... */
+    /* XXXXX by row should be more efficient... */
     int ydelA=pl->resample_ydelA[i];
     int ydelB=pl->resample_ydelB[i];
     int ystart=pl->resample_ynumA[i];
@@ -320,31 +320,140 @@
   }
 }
 
-
-// called from worker thread
-static void recompute_setup(sv_plane_t *in, sv_panel_t *p){
-  sv_plane_2d_t *pl = (sv_plane_2d_t *)in;
-  sv_dim_data_t *ddx = p->dim_data+p->x_dim;
-  sv_dim_data_t *ddy = p->dim_data+p->y_dim;
+int _sv_plane_recompute_setup_common(sv_plane_t *pl){
+  sv_plane_common_t *c = &pl->c;
+  sv_panel_t *p = c->panel;
   int w = p->bg->image_x->pixels;
   int h = p->bg->image_y->pixels;
+  sv_scalespace_t pending_scales[pl->c.axes];
+  double pending_input[pl->o->inputs];
+  int flag=0;
+  
+  // generate new pending scales
+  for(i=0;i<pl->c.axes;i++){
+    int axisnum = c->axis_list[i];
+    int dimnum = p->axis_dims[axisnum];
 
-  pl->pending_data_x = 
-    _sv_dim_datascale(ddx, p->bg->image_x, 
-		      w * p->oversample_n / p->oversample_d, 0);
-  pl->pending_data_y = 
-    _sv_dim_datascale(ddy, p->bg->image_y, 
-		      h * p->oversample_n / p->oversample_d, 1);
+    // check that dims are actually set 
+    // should only come up if dimensions are declared to provide an
+    // axis, but there are too few dims to actually populate all
+    // declared axes.
+    if(dimnum<0){
+      fprintf(stderr,"sushivision: Panel \"%s\" has not set the %s axis\n"
+	      "\tfor objective \"%s\".\n",
+	      p->name,p->axis_names[axisnum],o->name);
+      pending_scales[i] = {0};
+    }else{
+
+      switch(axisnum){
+      case 0: // X
+	pending_scales[i] = 
+	  _sv_dim_datascale(p->dim_data+dimnum, p->bg->image_x, 
+			    w * p->oversample_n / p->oversample_d, 0);
+	break;
+	
+      case 1: // Y
+	pending_scales[i] = 
+	  _sv_dim_datascale(p->dim_data+dimnum, p->bg->image_y, 
+			    h * p->oversample_n / p->oversample_d, 1);
+	break;
+	
+      case 2: // Z
+	fprintf(stderr,"Z axis unimplemented!\n");
+	pending_scales[i] = {0};
+	break;
+	
+      default: // all auxiliary scales 
+	fprintf(stderr,"auxiliary axes unimplemented!\n");
+	pending_scales[i] = {0};
+	break;
+      }
+    }
+  }
+
+  // precompute non-iteration values in function input vector
+  for(i=0;i<pl->o->inputs;i++){
+    int dim = pl->o->input_dims[i]; 
+    for(j=0;j<pl->c.axes;j++)
+      if(dim == p->axis_dims[pl->c.axis_list[j]])
+	pending_input[i]=NAN;
+      else
+	pending_input[i]=p->dim_data[dim].val;
+  }
+	  
+  // Do we really need to recompute?  Check dims and axes for changes.
+  // Any changes, we must recompute.  
+
+  // check that the axes dimensions have not changed
+  //for(i=0;i<pl->c.axes;i++)
+  //if(pl->c.axis_dims[i] != p->axis_dims[pl->c.axis_list[i]]){
+  //  flag=1;
+  //  break;
+  //}
+
+  // check that the axes scales have not changed
+  if(!flag)
+    for(i=0;i<pl->c.axes;i++)
+      if(_sv_scalecmp(c->data_scales+i,pending_scales+i)){
+	flag = 1;
+	break;
+      }
   
-  pl->image_serialno++;
-  pl->data_waiting=0;
-  pl->data_incomplete=0;
-  pl->data_next=0;
+  // check whether dimension values have changed.
+  // the fact that axis dim values are NAN allows this to double as a
+  // check that the axes dims have not changed.
+  if(!flag)
+    for(i=0;i<pl->o->inputs;i++)
+      if(pending_input[i] != c->dim_input[i]){
+	flag=1;
+	break;
+      }
 
-  pl->image_task=0;
+  if(flag){
+    memcpy(c->dim_input,pending_input,sizeof(pending_input));
+    memcpy(c->pending_data_scales,pending_scales,sizeof(pending_scales));
+  }
+	
+  return flag;
+}
 
+int _sv_plane_resize_check(sv_plane_t *in){
+  sv_plane_common_t *c = &pl->c;
+  sv_panel_t *p = c->panel;
+  int w = p->bg->image_x->pixels;
+  int h = p->bg->image_y->pixels;
+  
+  if(c->image_x.pixels != w || c->image_y.pixels != y) return 1;
+  return 0;
 }
 
+// called from worker thread 
+static void recompute_setup(sv_plane_t *in){
+  sv_plane_2d_t *pl = (sv_plane_2d_t *)in;
+  sv_panel_t *p = pl->panel;
+
+  int flag=_sv_plane_recompute_presetup(in);
+
+  // Do we really need to recompute? 
+  if(flag){
+    pl->data_task=0;
+    pl->data_outstanding=0;
+    pl->data_next=0;
+  }
+
+  // Regardless of recomputation, we check for remap (eg, resizing the
+  // plane of a fixed size data set requires a rerender, but not a
+  // recompute)
+
+  flag|=_sv_plane_resize_check(in);
+
+  if(flag){
+    pl->image_serialno++;
+    pl->image_outstanding=0;
+    pl->image_task=0;
+  }
+}
+
 // called from worker thread
 static int image_resize(sv_plane_t *in, sv_panel_t *p){
   sv_plane_2d_t *pl = (sv_plane_2d_t *)in;
@@ -389,12 +498,10 @@
       
       if(new_w > old_w){
 	// y then x
-	pl->image_waiting=old_w;
-	pl->image_incomplete=old_w;
+	pl->image_outstanding=0;
       }else{
 	// x then y
-	pl->image_waiting=old_h;
-	pl->image_incomplete=old_h;
+	pl->image_outstanding=0;
       }      
       image = NULL;
       map = NULL;
@@ -413,78 +520,96 @@
   }
 
   if(pl->image_task==1){ // scale first dim
-    int next = pl->image_next++;
-    if(pl->image_waiting==0)return STATUS_BUSY;
-    pl->image_waiting--;
-
     if(new_w > old_w){
       // y then x
-      pthread_mutex_unlock(pl->status_m);
-      fast_scale_imagey(olddata+next,newdata+next,new_w,old_w,newy,oldy,pl->map);
-      pthread_mutex_lock(pl->status_m);
-      if(p->comp_serialno == serialno){
-	if(--pl->image_incomplete==0){
 
-	  pl->image_task=-1;
-	  pthread_mutex_unlock(pl->status_m);
-	  fast_scale_map(map,new_w,newx,oldx);
-	  pthread_mutex_lock(pl->status_m);
+      int next = pl->image_next;
+      if(next >= oldx){
+	if(pl->image_outstanding) return STATUS_BUSY;
 
-	  if(p->comp_serialno == serialno){
-	    pl->image_waiting=new_h;
-	    pl->image_incomplete=new_h;
-	    pl->image_task=2;
-	    pl->image_next=0;
-	  }
+	pl->image_task=-1;
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_map(map,new_w,newx,oldx);
+	pthread_mutex_lock(pl->status_m);
+	
+	if(p->comp_serialno == serialno){
+	  pl->image_task=2;
+	  pl->image_next=0;
 	}
+      }else{
+
+	pl->image_next++;
+	pl->image_outstanding++;
+	
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_imagey(olddata+next,newdata+next,new_w,old_w,newy,oldy,pl->map);
+	pthread_mutex_lock(pl->status_m);
+	
+	if(p->comp_serialno == serialno)
+	  pl->image_outstanding--;
       }
     }else{
       // x then y
-      pthread_mutex_unlock(pl->status_m);
-      fast_scale_imagex(olddata+next*old_w,newx,oldx,pl->map);
-      pthread_mutex_lock(pl->status_m);
-      if(p->comp_serialno == serialno){
-	if(--pl->image_incomplete==0){
 
-	  pl->image_task=-1;
-	  pthread_mutex_unlock(pl->status_m);
-	  fast_scale_map(map,new_h,newy,oldy);
-	  pthread_mutex_lock(pl->status_m);
-
-	  if(p->comp_serialno == serialno){
-	    pl->image_waiting=new_w;
-	    pl->image_incomplete=new_w;
-	    pl->image_task=2;
-	    pl->image_next=0;
-	  }
+      int next = pl->image_next;
+      if(next >= oldy){
+	if(pl->image_outstanding) return STATUS_BUSY;
+	  
+	pl->image_task=-1;
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_map(map,new_w,newy,oldy);
+	pthread_mutex_lock(pl->status_m);
+	
+	if(p->comp_serialno == serialno){
+	  pl->image_task=2;
+	  pl->image_next=0;
 	}
+      }else{
+
+	pl->image_next++;
+	pl->image_outstanding++;
+
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_imagex(olddata+next*old_w,newx,oldx,pl->map);
+	pthread_mutex_lock(pl->status_m);
+	if(p->comp_serialno == serialno)
+	  pl->image_outstanding--;
       }
     }
     return STATUS_WORKING;    
   }
 
-  if(pl->image_task==2){ // scale first dim
-    int next = pl->image_next++;
-    if(pl->image_waiting==0)return STATUS_BUSY;
-    pl->image_waiting--;
-
+  if(pl->image_task==2){ // scale second dim
     if(new_w > old_w){
       // now x
-      pthread_mutex_unlock(pl->status_m);
-      fast_scale_imagex(newdata+next*new_w,newx,oldx,pl->map);
-      pthread_mutex_lock(pl->status_m);
-      if(p->comp_serialno == serialno){
-	if(--pl->image_incomplete==0)
+
+      int next = pl->image_next;
+      if(next >= newy){
+	if(pl->image_outstanding) return STATUS_BUSY;
+	if(p->comp_serialno == serialno)
 	  pl->image_task=3;
+      }else{
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_imagex(newdata+next*new_w,newx,oldx,pl->map);
+	pthread_mutex_lock(pl->status_m);
+	if(p->comp_serialno == serialno)
+	  pl->image_outstanding--;
       }
+
     }else{
       // now y
-      pthread_mutex_unlock(pl->status_m);
-      fast_scale_imagey(olddata+next,newdata+next,new_w,old_w,newy,oldy,pl->map);
-      pthread_mutex_lock(pl->status_m);
-      if(p->comp_serialno == serialno){
-	if(--pl->image_incomplete==0)
+
+      int next = pl->image_next;
+      if(next >= newx){
+	if(pl->image_outstanding) return STATUS_BUSY;
+	if(p->comp_serialno == serialno)
 	  pl->image_task=3;
+      }else{
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_imagey(olddata+next,newdata+next,new_w,old_w,newy,oldy,pl->map);
+	pthread_mutex_lock(pl->status_m);
+	if(p->comp_serialno == serialno)
+	  pl->image_outstanding--;
       }
     }
     return STATUS_WORKING;    
@@ -546,13 +671,12 @@
       pl->resample_yscalemul = yscalemul;
 
       pl->image_task = 4;
-      pl->image_waiting=0;
-      pl->image_incomplete=0;
+      pl->image_outstanding=0;
     }
       
     //pthread_mutex_unlock(pl->status_m);
     pthread_rwlock_unlock(pl->panel_m);
-
+    
     if(map)free(map);
     if(flags)free(flags);
 
@@ -569,7 +693,7 @@
     pthread_mutex_lock(pl->status_m);
     return STATUS_WORKING;
   }
-
+  
   return STATUS_IDLE;
 }
 
@@ -648,83 +772,105 @@
   }
 
   if(pl->data_task==1){ // scale first dim
-    int next = pl->data_next++;
-    if(pl->data_waiting==0)return STATUS_BUSY;
-    pl->data_waiting--;
-
     if(new_w > old_w){
       // y then x
-      pthread_mutex_unlock(pl->status_m);
-      fast_scale_datay(olddata+next,newdata+next,new_w,old_w,newy,oldy,pl->map);
-      pthread_mutex_lock(pl->status_m);
-      if(p->comp_serialno == serialno){
-	if(--pl->data_incomplete==0){
 
-	  pl->data_task=-1;
-	  pthread_mutex_unlock(pl->status_m);
-	  fast_scale_map(map,new_w,newx,oldx);
-	  pthread_mutex_lock(pl->status_m);
+      int next = pl->data_next;
+      if(next >= oldx){
+	if(pl->data_outstanding)return STATUS_BUSY;
 
-	  if(p->comp_serialno == serialno){
-	    pl->data_waiting=new_h;
-	    pl->data_incomplete=new_h;
-	    pl->data_task=2;
-	    pl->data_next=0;
-	  }
+	pl->data_task=-1;
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_map(map,new_w,newx,oldx);
+	pthread_mutex_lock(pl->status_m);
+	
+	if(p->comp_serialno == serialno){
+	  pl->data_task=2;
+	  pl->data_next=0;
 	}
+      }else{
+
+	pl->data_next++;
+	pl->data_outstanding++;
+
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_datay(olddata+next,newdata+next,new_w,old_w,newy,oldy,pl->map);
+	pthread_mutex_lock(pl->status_m);
+	if(p->comp_serialno == serialno)
+	  pl->data_outstanding--;
       }
     }else{
       // x then y
-      pthread_mutex_unlock(pl->status_m);
-      fast_scale_datax(olddata+next*old_w,newx,oldx,pl->map);
-      pthread_mutex_lock(pl->status_m);
-      if(p->comp_serialno == serialno){
-	if(--pl->data_incomplete==0){
 
-	  pl->data_task=-1;
-	  pthread_mutex_unlock(pl->status_m);
-	  fast_scale_map(map,new_h,newy,oldy);
-	  pthread_mutex_lock(pl->status_m);
+      int next = pl->data_next;
+      if(next >= oldy){
+	if(pl->data_outstanding)return STATUS_BUSY;
 
-	  if(p->comp_serialno == serialno){
-	    pl->data_waiting=new_w;
-	    pl->data_incomplete=new_w;
-	    pl->data_task=2;
-	    pl->data_next=0;
-	  }
+	pl->data_task=-1;
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_map(map,new_w,newy,oldy);
+	pthread_mutex_lock(pl->status_m);
+	
+	if(p->comp_serialno == serialno){
+	  pl->data_task=2;
+	  pl->data_next=0;
 	}
+      }else{
+
+	pl->data_next++;
+	pl->data_outstanding++;
+
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_datax(olddata+next*old_w,newx,oldx,pl->map);
+	pthread_mutex_lock(pl->status_m);
+	if(p->comp_serialno == serialno)
+
+	if(--pl->data_incomplete==0)
+	  pl->data_outstanding--;
       }
     }
     return STATUS_WORKING;    
   }
 
-  if(pl->data_task==2){ // scale first dim
-    int next = pl->data_next++;
-    if(pl->data_waiting==0)return STATUS_BUSY;
-    pl->data_waiting--;
-
+  if(pl->data_task==2){ // scale second dim
     if(new_w > old_w){
       // now x
-      pthread_mutex_unlock(pl->status_m);
-      fast_scale_datax(newdata+next*new_w,newx,oldx,pl->map);
-      pthread_mutex_lock(pl->status_m);
-      if(p->comp_serialno == serialno){
-	if(--pl->data_incomplete==0)
+
+      int next = pl->data_next;
+      if(next >= newy){
+	if(pl->data_outstanding)return STATUS_BUSY;
+	if(p->comp_serialno == serialno)
 	  pl->data_task=3;
+      }else{
+	pl->data_next++;
+	pl->data_outstanding++;
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_datax(newdata+next*new_w,newx,oldx,pl->map);
+	pthread_mutex_lock(pl->status_m);
+	if(p->comp_serialno == serialno)
+	  pl->data_outstanding--;
       }
     }else{
       // now y
-      pthread_mutex_unlock(pl->status_m);
-      fast_scale_datay(olddata+next,newdata+next,new_w,old_w,newy,oldy,pl->map);
-      pthread_mutex_lock(pl->status_m);
-      if(p->comp_serialno == serialno){
-	if(--pl->data_incomplete==0)
+
+      int next = pl->data_next;
+      if(next >= newx){
+	if(pl->data_outstanding)return STATUS_BUSY;
+	if(p->comp_serialno == serialno)
 	  pl->data_task=3;
+      }else{
+	pl->data_next++;
+	pl->data_outstanding++;
+	pthread_mutex_unlock(pl->status_m);
+	fast_scale_datay(olddata+next,newdata+next,new_w,old_w,newy,oldy,pl->map);
+	pthread_mutex_lock(pl->status_m);
+	if(p->comp_serialno == serialno)
+	  pl->data_outstanding--;
       }
     }
     return STATUS_WORKING;    
   }
-
+  
   if(pl->data_task==3){ // commit new data 
     int *map = NULL;
 
@@ -740,8 +886,7 @@
       pl->data_x = p->bg->data_x;
       pl->data_y = p->bg->data_y;
       pl->data_task = 4;
-      pl->data_waiting = new_h;
-      pl->data_incomplete = new_h;
+      pl->data_outstanding=0;
       map = pl->map;
       pl->map = NULL;
     }
@@ -766,17 +911,17 @@
   int h = pl->image_y.pixels;
   int w = pl->image_x.pixels;
   int last = pl->image_next;
-  int mapno = pl->map_serialno;
+  int mapno = pl->image_serialno;
   int i;
   sv_ucolor_t work[w];
 
-  if(pl->waiting == 0) return STATUS_IDLE;
+  if(pl->image_task != 4) return STATUS_IDLE;
   
   do{
     i = pl->image_next;
     pl->image_next++;
     if(pl->image_next>=h)pl->image_next=0;
-
+    
     if(pl->image_flags[i]){
       sv_scalespace_t dx = pl->data_x;
       sv_scalespace_t dy = pl->data_y;
@@ -784,57 +929,207 @@
       sv_scalespace_t iy = pl->image_y;
       void (*mapping)(int, int, _sv_lcolor_t *)=mapfunc[pl->image_mapnum];
       pl->image_flags[i]=0;
-      pl->waiting--;
+      pl->image_outstanding++;
 
       pthread_mutex_unlock(pl->status_m);
       slow_scale(dx,dy,ix,iy,mapping,i);
       pthread_mutex_lock(pl->status_m);
-
-      if(p->comp_serialno == serialno &&
-	 pl->map_serialno == mapno){
-	
+      
+      if(pl->image_serialno == mapno){
+	pl->image_outstanding--;
 	p->bg->image_flags[i] = 1;
-
-	if(pl->incomplete-- == 0){
+	if(pl->image_task == 5) // idled while we were working; bg render is waiting for us
 	  p->bg_render = 1;
-	  p->map_render = 0;
-	}
       }
+
       return STATUS_WORKING;
     }
   }while(i!=last);
-  
-  // shouldn't get here...
-  pl->waiting = 0;
-  fprintf(stderr,"sushivision: image render found no work despite status flags\n");
+
+  pl->image_task = 5;
+  if(!pl->image_outstanding)
+    p->bg_render = 1;
+
   return STATUS_IDLE;
 }
 
+static int vswizzle(int y, int height){
+  int yy = height >> 5;
+  if(y < yy)
+    return (y<<5)+31;
+
+  y -= yy;
+  yy = (height+16) >> 5;
+  if(y < yy)
+    return (y<<5)+15;
+
+  y -= yy;
+  yy = (height+8) >> 4;
+  if(y < yy)
+    return (y<<4)+7;
+
+  y -= yy;
+  yy = (height+4) >> 3;
+  if(y < yy)
+    return (y<<3)+3;
+
+  y -= yy;
+  yy = (height+2) >> 2;
+  if(y < yy)
+    return (y<<2)+1;
+
+  y -= yy;
+  return y<<1;
+}
+
+static void data_demultiplex_2d(sv_plane_t *in,sv_panel_t *p,double *output,
+				int w, int xoff, int yoff, int n){
+  sv_plane_2d_t *pl = (sv_plane_2d_t *)in;
+  int i,on=pl->o->outputs;
+  float *data_line = pl->data+w*yoff+xoff;
+  output += pl->data_z_output;
+
+  for(i=0;i<n;i++){
+    *data_line++ = *output;
+    output+=on;
+  }
+}
+
 // called from worker thread
 static int data_work(sv_plane_t *in, sv_panel_t *p){
   sv_plane_2d_t *pl = (sv_plane_2d_t *)in;
+  int serialno = p->comp_serialno;
+  int next = pl->data_next;
+  int i,j; 
 
   // each plane is associated with a single objective, however
   // multiple objectives may be associated with a given computation.
   // This is an optimization for dealing with multiple display
   // ojectives drawing from different output values of the exact same
   // input computation.  The plane types sharing a computation may be
-  // different, but the input dimension value vector will be identical.
+  // different, but the input dimension value vector and input axes
+  // will be identical.
 
   // if this is a 'slave' plane in the computation chain, return idle;
   // some other plane is doing the calculation for us.
-  if(pl->c.share_prev)return STATUS_IDLE;
+  if(pl->c.share_prev)return STATUS_IDLE; 
+  if(pl->data_task != 4)return STATUS_IDLE;
+  if(next >= pl->data_y.pixels){
+    // not the same thing as completion; a computation may yet be
+    // outstanding.  Simply mark this plane so that there are no
+    // further dispatch attempts
+    pl->data_task = 5;
+    return STATUS_IDLE; 
+  }
+  pl->data_next++;
 
-  // marshal iterators, dimension value vector
+  // marshal iterators, dimension value vectors
+  int outputs = pl->o->outputs;
+  double input[pl->o->inputs];
+  int xpos = -1;
+  int yline = vswizzle(next);
+  sv_scalespace_t dx = pl->data_x;
+  int dw = dx.pixels;
+  int dh = pl->data_y.pixels;
+  int iw = pl->image_x.pixels;
+  int ih = pl->image_y.pixels;
 
+  for(i=0;i<pl->o->inputs;i++){
+    int dim = pl->o->input_dims[i]; // dim setup in an objective is immutable
+    if(dim == p->ydim){
+      input[i] = _sv_scalespace_value(&pl->data_y,yline);   
+    }else 
+      input[i] = p->dim_data[dim].val;
+    
+    if(dim == p->xdim) xpos = i;
+  }
 
+  // drop status lock and compute.  Writes to the data plane are not
+  // locked because we still hold the panel concurrent lock; changes
+  // to the computational parameters (and heap) can't happen.  Reads
+  // from the data array may get inconsistent information, but a
+  // completed line flushes which causes a new read to replace the
+  // inconsistent one.
 
+  pl->data_outstanding++;
+  pthread_mutex_unlock(pl->status_m);
   
+  int sofar = 0;
+  int step = (1024+outputs-1)/outputs; // at least one
+  sv_plane_t *slave;
+  while(sofar < w){
+    int this_step = (step>w-sofar?w-sofar:step);
+    double output[outputs*step];
+    double *outptr=output;
+    slave = pl->c.share.next;
 
+    // compute
+    for(i=0;i<this_step;i++){
+      // set x val
+      input[xpos] = _sv_scalespace_value(&dx,i+sofar);   
+      pl->o->function(input,outptr); // func setup in an objective is immutable
+      outptr+=outputs;
+    }
 
+    // demultiplex
+    data_demultiplex_2d(pl,p,output,yline,sofar,this_step);
+    while(slave){
+      slave->data_demultiplex_2d(slave,p,output,yline,sofar,this_step);
+      slave = slave->c.share_next;
+    }
+    sofar+= this_step;
+  }
+
+  pthread_mutex_lock(pl->status_m);
+  if(p->comp_serialno != serialno)return STATUS_WORKING;
+
+  pl->data_outstanding--;
+  
+  // determine all image lines this y data line affects
+  slave = pl;
+  while(slave){
+    if(ih!=dh || iw!=dw){
+      /* resampled row computation; may involve multiple data rows */
+      for(i=0;i<ih;i++)
+	if(pl->resample_ynumA[i]<=yline && pl->resample_ynumB[i]>yline)
+	  pl->image_flags[i]=1;
+    }else
+      pl->image_flags[yline]=1;  
+    slave = slave->c.share_next;
+  }
+
+  pl->image_task = 4;
+
+  if(pl->data_next>=dh){
+    pl->data_task = 5; 
+    if(!pl->data_outstanding) {
+      // immediate image render 
+      p->map_render = 1;
+    }
+  }
+
+  // throttled image render
+  if(p->map_render==0){
+    // no render currently in progress
+    struct timeval now;
+    gettimeofday(&now,NULL);
+    
+    if(p->map_throttle_last.tv_sec==0){
+      p->map_throttle_last=now;
+    }else{
+      long test = (now.tv_sec - p->map_throttle_last.tv_sec)*1000 + 
+	(now.tv_usec - p->map_throttle_last.tv_usec)/1000;
+      if(test>500)
+	// first request since throttle
+	p->map_render=1;
+    }
+  }
+
+  return STATUS_WORKING;
+  
 }
 
-// called from GTK/API
+// called from GTK/API for map scale changes
 static void plane_remap(sv_plane_t *in, sv_panel_t *p){
   sv_plane_2d_t *pl = (sv_plane_2d_t *)in;
   int i,flag=1;
@@ -869,6 +1164,8 @@
   for(i=0;i<pl->image_y.pixels;i++)
     pl->image_flags[i]=1;
   pl->image_mapnum = gtk_combo_box_get_active(GTK_COMBO_BOX(pl->range_rulldown));
+  p->image_serialno++;
+  p->image_outstanding=0;
 
   if(flag){
     pthread_rwlock_unlock(pl->panel_m);
@@ -922,356 +1219,6 @@
 }
 
 
-
-
-
-
-
-
-
-// enter unlocked
-static void _sv_planez_compute_line(sv_panel_t *p, 
-				    _sv_plane2d_t *z,
-
-				    int serialno,
-
-				    int dw,
-				    int y,
-				    int x_d, 
-				    _sv_scalespace_t sxi,
-				    double *dim_vals, 
-				    _sv_bythread_cache_2d_t *c){
-
-  _sv_panel2d_t *p2 = p->subtype->p2;
-  int i,j;
-  
-  /* cache access is unlocked because the cache is private to this
-     worker thread */
-
-  for(j=0;j<dw;j++){
-    double *fout = c->fout;
-    sv_func_t **f = p2->used_function_list;
-    int *obj_y_off = p2->y_fout_offset;
-    int *onum = p2->y_obj_to_panel;
-    
-    /* by function */
-    dim_vals[x_d] = _sv_scalespace_value(&sxi,j);   
-    for(i=0;i<p2->used_functions;i++){
-      (*f)->callback(dim_vals,fout);
-      fout += (*f)->outputs;
-      f++;
-    }
-    
-    /* process function output by plane type/objective */
-    /* 2d panels currently only care about the Y output value */
-    
-    /* slider map */
-    for(i=0;i<p2->y_obj_num;i++){
-      float val = (float)_sv_slider_val_to_del(p2->range_scales[*onum++], c->fout[*obj_y_off++]);
-      if(isnan(val)){
-	c->y_map[i][j] = -1;
-      }else{
-	if(val<0)val=0;
-	if(val>1)val=1;
-	c->y_map[i][j] = rint(val * (256.f*256.f*256.f));
-      }
-    }
-  }
-
-  gdk_lock ();
-  if(p->private->plot_serialno == serialno){
-    for(j=0;j<p2->y_obj_num;j++){
-      int *d = p2->y_map[j] + y*dw;
-      int *td = c->y_map[j];
-      
-      memcpy(d,td,dw*sizeof(*d));
-      
-    }
-  }
-  gdk_unlock ();
-}
-
-typedef struct{
-  double x;
-  double y;
-  double z;
-} compute_result;
-
-// used by the legend code. this lets us get away with having only a mapped display pane
-// call with lock
-static void _sv_panel2d_compute_point(sv_panel_t *p,sv_obj_t *o, double x, double y, compute_result *out){
-  double dim_vals[_sv_dimensions];
-  int i,j;
-  int pflag=0;
-  int eflag=0;
-
-  // fill in dimensions
-  int x_d = p->private->x_d->number;
-  int y_d = p->private->y_d->number;
-
-  for(i=0;i<_sv_dimensions;i++){
-    sv_dim_t *dim = _sv_dimension_list[i];
-    dim_vals[i]=dim->val;
-  }
-
-  gdk_unlock ();
-
-  dim_vals[x_d] = x;
-  dim_vals[y_d] = y;
-
-  *out = (compute_result){NAN,NAN,NAN,NAN,NAN,NAN,NAN,NAN};
-
-  // compute
-  for(i=0;i<_sv_functions;i++){
-    sv_func_t *f = _sv_function_list[i];
-    int compflag = 0;
-    double fout[f->outputs];
-    double val;
-
-    // compute and demultiplex output
-    for(j=0;j<o->outputs;j++){
-      if(o->function_map[j] == i){
-
-	if(!compflag) f->callback(dim_vals,fout);
-	compflag = 1;
-	
-	val = fout[o->output_map[j]];
-	switch(o->output_types[j]){
-	case 'X':
-	  out->x = val;
-	  break;
-	case 'Y':
-	  out->y = val;
-	  break;
-	case 'Z':
-	  out->z = val;
-	  break;
-	case 'E':
-	  if(eflag)
-	    out->e2 = val;
-	  else
-	    out->e1 = val;
-	  eflag = 1;
-	  break;
-	case 'P':
-	  if(pflag)
-	    out->p2 = val;
-	  else
-	    out->p1 = val;
-	  pflag = 1;
-	  break;
-	case 'M':
-	  out->m = val;
-	  break;
-	}
-      }
-    }
-  }
-  gdk_lock ();
-
-}
-
-// enter with lock; returns zero if thread should sleep / get distracted
-static int _sv_panel2d_remap(sv_panel_t *p, _sv_bythread_cache_2d_t *thread_cache){
-  _sv_panel2d_t *p2 = p->subtype->p2;
-  _sv_plot_t *plot = PLOT(p->private->graph);
-
-  if(!plot) goto abort;
-  int ph = plot->y.pixels;
-  int pw = plot->x.pixels;
-  
-  int plot_serialno = p->private->plot_serialno; 
-  int map_serialno = p->private->map_serialno; 
-
-  /* brand new remap indicated by the generic progress indicator being set to 0 */
-  if(p->private->map_progress_count == 0){
-
-    p->private->map_progress_count = 1; // 'in progress'
-    p->private->map_complete_count = p2->y_obj_num * ph; // count down to 0; 0 indicates completion
-
-    // set up Y plane rendering
-    p2->y_next_plane = 0;
-    p2->y_next_line = 0;
-
-    // bg mix
-    p2->bg_next_line = 0;
-    p2->bg_first_line = ph;
-    p2->bg_last_line = 0;
-
-    if(!p2->partial_remap)
-      _sv_panel2d_mark_map_full(p);
-  }
-
-  /* by plane, by line; each plane renders independently */
-  /* Y planes */
-  if(p2->y_planetodo){
-    if(p2->y_next_plane < p2->y_obj_num){
-      int status = _sv_panel2d_resample_render_y_plane_line(p, thread_cache, 
-							    plot_serialno, map_serialno, 
-							    p2->y_next_plane);
-      if(status == -1) goto abort;
-      if(status == 1){
-	p2->y_next_plane++;
-	p2->y_next_line = 0;
-      }
-      return 1;
-    }
-  }else{
-    p->private->map_complete_count = 0;
-  }
-
-  /* renders have been completely dispatched, but are they complete? */
-  /* the below is effectively a a thread join */
-  if(p2->bg_next_line == 0){
-
-    // join still needs to complete....
-    if(p->private->map_complete_count){
-      // nonzero complete count, not finished.  returning zero will cause
-      // this worker thread to sleep or go on to do other things.
-      return 0; 
-    }else{
-      // zero complete count, the planes are done; we can begin
-      // background render.  At least one thread is guaranteed to get
-      // here, which is enough; we can now wake the others [if they were
-      // asleep] and have them look for work here. */
-      p->private->map_complete_count = ph; // [ph] lines to render in bg plane
-      p2->bg_next_line = 0;
-
-      _sv_wake_workers();
-    }
-  }
-
-  /* mix new background, again line by line */
-  if(p2->bg_next_line < ph){
-    int status = _sv_panel2d_render_bg_line(p, plot_serialno, map_serialno);
-    if(status == -1) goto abort;
-    if(p->private->map_complete_count)return status;
-  }else
-    return 0; // nothing left to dispatch
-
-  // entirely finished.
-
-  // remap completed; flush background to screen
-  _sv_plot_expose_request_partial (plot,0,p2->bg_first_line,
-			       pw,p2->bg_last_line - p2->bg_first_line);
-  gdk_flush();
-
-  // clean bg todo list
-  memset(p2->bg_todo,0,ph*sizeof(*p2->bg_todo));
-
-  // clear 'panel in progress' flag
-  p2->partial_remap = 0;
-  _sv_panel_clean_map(p);
-  return 0;
-
- abort:
-  // reset progress to 'start over'
-  return 1;
-}
-
-// call while locked 
-static void _sv_panel2d_mark_map_line_y(sv_panel_t *p, int line){
-  // determine all panel lines this y data line affects
-  _sv_panel2d_t *p2 = p->subtype->p2;
-  int ph = p2->y.pixels;
-  int pw = p2->x.pixels;
-  int dw = p2->x_v.pixels;
-  int dh = p2->y_v.pixels;
-  int i,j;
-
-  p2->partial_remap = 1;
-
-  if(ph!=dh || pw!=dw){
-    /* resampled row computation; may involve multiple data rows */
-    if(p2->y_planetodo){
-      _sv_panel2d_resample_helpers_manage_y(p);
-      
-      for(i=0;i<ph;i++)
-	if(p2->ynumA[i]<=line &&
-	   p2->ynumB[i]>line){
-	  
-	  for(j=0;j<p2->y_obj_num;j++)
-	    if(p2->y_planetodo[j])
-	      p2->y_planetodo[j][i]=1;
-      }
-    }
-  }else{
-    if(p2->y_planetodo)
-      if(line>=0 && line<ph)
-	for(j=0;j<p2->y_obj_num;j++)
-	  if(p2->y_planetodo[j])
-	    p2->y_planetodo[j][line]=1;
-  }
-}
-
-static int _v_swizzle(int y, int height){
-  int yy = height >> 5;
-  if(y < yy)
-    return (y<<5)+31;
-
-  y -= yy;
-  yy = (height+16) >> 5;
-  if(y < yy)
-    return (y<<5)+15;
-
-  y -= yy;
-  yy = (height+8) >> 4;
-  if(y < yy)
-    return (y<<4)+7;
-
-  y -= yy;
-  yy = (height+4) >> 3;
-  if(y < yy)
-    return (y<<3)+3;
-
-  y -= yy;
-  yy = (height+2) >> 2;
-  if(y < yy)
-    return (y<<2)+1;
-
-  y -= yy;
-  return y<<1;
-}
-
-void _sv_panel2d_maintain_cache(sv_panel_t *p, _sv_bythread_cache_2d_t *c, int w){
-  _sv_panel2d_t *p2 = p->subtype->p2;
-  
-  /* toplevel initialization */
-  if(c->fout == 0){
-    int i,count=0;
-    
-    /* allocate output temporary buffer */
-    for(i=0;i<p2->used_functions;i++){
-      int fnum = p2->used_function_list[i]->number;
-      sv_func_t *f = _sv_function_list[fnum];
-      count += f->outputs;
-    }
-    c->fout = calloc(count, sizeof(*c->fout));
-
-    /* objective line buffer index */
-    c->y_map = calloc(p2->y_obj_num,sizeof(*c->y_map));
-    for(i=0;i<p2->y_obj_num;i++)
-      c->y_map[i] = calloc(w,sizeof(**c->y_map));
-    c->storage_width = w;
-  }
-  
-  /* anytime the data width changes */
-  if(c->storage_width != w){
-    int i;
-    c->storage_width = w;
-    
-    for(i=0;i<p2->y_obj_num;i++)
-      c->y_map[i] = realloc(c->y_map[i],w*sizeof(**c->y_map));
-
-  }
-}
-
-
-// subtype entry point for plot remaps; lock held
-static int _sv_panel2d_map_redraw(sv_panel_t *p, _sv_bythread_cache_t *c){
-  return _sv_panel2d_remap(p,&c->p2);
-}
-
 // subtype entry point for legend redraws; lock held
 static int _sv_panel2d_legend_redraw(sv_panel_t *p){
   _sv_plot_t *plot = PLOT(p->private->graph);
@@ -1289,190 +1236,6 @@
   return 1;
 }
 
-// subtype entry point for recomputation; lock held
-static int _sv_panel2d_compute(sv_panel_t *p,
-			       _sv_bythread_cache_t *c){
-
-  _sv_panel2d_t *p2 = p->subtype->p2;
-  _sv_plot_t *plot;
-  
-  int pw,ph,dw,dh,i,d;
-  int serialno;
-  double x_min, x_max;
-  double y_min, y_max;
-  int x_d=-1, y_d=-1;
-  _sv_scalespace_t sx,sx_v,sx_i;
-  _sv_scalespace_t sy,sy_v,sy_i;
-
-  plot = PLOT(p->private->graph);
-  pw = plot->x.pixels;
-  ph = plot->y.pixels;
-  
-  x_d = p->private->x_d->number;
-  y_d = p->private->y_d->number;
-
-  // beginning of computation init
-  if(p->private->plot_progress_count==0){
-    int remapflag = 0;
-
-    _sv_scalespace_t old_x = p2->x;
-    _sv_scalespace_t old_y = p2->y;
-    _sv_scalespace_t old_xv = p2->x_v;
-    _sv_scalespace_t old_yv = p2->y_v;
-
-    // generate new scales
-    _sv_dim_scales(p->private->x_d, 
-		   p->private->x_d->bracket[0],
-		   p->private->x_d->bracket[1],
-		   pw,pw * p->private->oversample_n / p->private->oversample_d,
-		   plot->scalespacing,
-		   p->private->x_d->legend,
-		   &sx,
-		   &sx_v,
-		   &sx_i);
-    _sv_dim_scales(p->private->y_d, 
-		   p->private->y_d->bracket[1],
-		   p->private->y_d->bracket[0],
-		   ph,ph * p->private->oversample_n / p->private->oversample_d,
-		   plot->scalespacing,
-		   p->private->y_d->legend,
-		   &sy,
-		   &sy_v,
-		   &sy_i);
-    
-    p2->x = sx;
-    p2->x_v = sx_v;
-    p2->x_i = sx_i;
-    p2->y = sy;
-    p2->y_v = sy_v;
-    p2->y_i = sy_i;
-
-    plot->x = sx;
-    plot->y = sy;
-    plot->x_v = sx_v;
-    plot->y_v = sy_v;
-
-    p->private->plot_progress_count++;
-    p->private->plot_serialno++; // we're about to free the old data rectangles
-
-    // realloc/fast scale the current data contents if appropriate
-    if(memcmp(&sx_v,&old_xv,sizeof(sx_v)) || memcmp(&sy_v,&old_yv,sizeof(sy_v))){
-      
-      // maintain data planes
-      for(i=0;i<p2->y_obj_num;i++){
-	// allocate new storage
-	int *newmap = calloc(sx_v.pixels*sy_v.pixels,sizeof(*newmap));
-	int *oldmap = p2->y_map[i];
-	int j;
-	
-	for(j=0;j<sx_v.pixels*sy_v.pixels;j++)
-	  newmap[j]=-1;
-	
-	// zoom scale data in map planes as placeholder for render
-	if(oldmap){
-	  _sv_panel2d_fast_scale(p->private->spinner,newmap, sx_v, sy_v,
-				 oldmap,old_xv, old_yv);
-	  free(oldmap);
-	}
-	p2->y_map[i] = newmap; 
-      }
-      remapflag = 1;
-    }
-
-    // realloc render planes if appropriate
-    if(memcmp(&sx,&old_x,sizeof(sx)) || memcmp(&sy,&old_y,sizeof(sy))){
-      for(i=0;i<p2->y_obj_num;i++){
-
-	// y planes
-	if(p2->y_planes[i])
-	  free(p2->y_planes[i]);
-	p2->y_planes[i] = calloc(sx.pixels*sy.pixels,sizeof(**p2->y_planes));
-
-	// todo lists
-	if(p2->y_planetodo[i])
-	  free(p2->y_planetodo[i]);
-	p2->y_planetodo[i] = calloc(sy.pixels,sizeof(**p2->y_planetodo));
-	
-      }
-
-      if(p2->bg_todo)
-	free(p2->bg_todo);
-      p2->bg_todo=calloc(ph,sizeof(*p2->bg_todo));
-      
-      remapflag = 1;
-    }
-
-    if(remapflag){
-      _sv_panel2d_mark_map_full(p);
-      _sv_panel_dirty_map(p);
-
-      gdk_unlock ();      
-      _sv_plot_draw_scales(plot); // this should happen outside lock
-      gdk_lock ();      
-    }
-
-    _sv_map_set_throttle_time(p); // swallow the first 'throttled' remap which would only be a single line;
-
-    return 1;
-  }else{
-    sx = p2->x;
-    sx_v = p2->x_v;
-    sx_i = p2->x_i;
-    sy = p2->y;
-    sy_v = p2->y_v;
-    sy_i = p2->y_i;
-    serialno = p->private->plot_serialno; 
-  }
-
-  dw = sx_v.pixels;
-  dh = sy_v.pixels;
-
-  if(p->private->plot_progress_count>dh) return 0;
-
-  _sv_panel2d_maintain_cache(p,&c->p2,dw);
-  
-  d = p->dimensions;
-
-  /* render using local dimension array; several threads will be
-     computing objectives */
-  double dim_vals[_sv_dimensions];
-  int y = _v_swizzle(p->private->plot_progress_count-1,dh);
-  p->private->plot_progress_count++;
-
-  x_min = _sv_scalespace_value(&p2->x_i,0);
-  x_max = _sv_scalespace_value(&p2->x_i,dw);
-
-  y_min = _sv_scalespace_value(&p2->y_i,0);
-  y_max = _sv_scalespace_value(&p2->y_i,dh);
-
-  // Initialize local dimension value array
-  for(i=0;i<_sv_dimensions;i++){
-    sv_dim_t *dim = _sv_dimension_list[i];
-    dim_vals[i]=dim->val;
-  }
-
-  /* unlock for computation */
-  gdk_unlock ();
-    
-  dim_vals[y_d]=_sv_scalespace_value(&sy_i, y);
-  _sv_panel2d_compute_line(p, serialno, dw, y, x_d, sx_i, dim_vals, &c->p2);
-
-  gdk_lock ();
-
-  if(p->private->plot_serialno == serialno){
-    p->private->plot_complete_count++;
-    _sv_panel2d_mark_map_line_y(p,y);
-    if(p->private->plot_complete_count>=dh){ 
-      _sv_panel_dirty_map(p);
-      _sv_panel_dirty_legend(p);
-      _sv_panel_clean_plot(p);
-    }else
-      _sv_panel_dirty_map_throttled(p); 
-  }
-
-  return 1;
-}
-
 static void _sv_panel2d_realize(sv_panel_t *p){
   _sv_panel2d_t *p2 = p->subtype->p2;
   int i;

Modified: trunk/sushivision/plane.h
===================================================================
--- trunk/sushivision/plane.h	2007-10-16 17:04:07 UTC (rev 14002)
+++ trunk/sushivision/plane.h	2007-10-16 22:01:53 UTC (rev 14003)
@@ -23,32 +23,32 @@
 typedef struct sv_plane_bg sv_plane_bg_t;
 typedef struct sv_plane_2d sv_plane_2d_t;
 
-struct sv_zmap {
-
-  double *label_vals;
-  int labels;
-  int neg;
-  double al;
-  double lo;
-  double hi;
-  double lodel;
-  double *labeldelB;
-  double *labelvalB;
-
-};
-
 struct sv_plane_common {
   int              plane_type;
   sv_obj_t        *o;
   sv_plane_t      *share_next;
   sv_plane_t      *share_prev;
   sv_panel_t      *panel;
+  int             *axis_list;
+  int             *axis_dims;
+  double          *dim_input; // function input vector (without iterator values)
+  sv_scalespace_t *pending_data_scales;
+  sv_scalespace_t *data_scales;
+  sv_scalespace_t  image_x;
+  sv_scalespace_t  image_y;
+  int              axes;
 
-  void (*recompute_setup)(sv_plane_t *, sv_panel_t *);
-  int (*image_resize)(sv_plane_t *, sv_panel_t *);
-  int (*data_resize)(sv_plane_t *, sv_panel_t *);
-  int (*image_work)(sv_plane_t *, sv_panel_t *);
-  int (*data_work)(sv_plane_t *, sv_panel_t *);
+  void (*recompute_setup)(sv_plane_t *);
+  int (*image_resize)(sv_plane_t *);
+  int (*data_resize)(sv_plane_t *);
+  int (*image_work)(sv_plane_t *);
+  int (*data_work)(sv_plane_t *);
+
+  void (*plane_remap)(sv_plane_t *);
+  void (*plane_free)(sv_plane_t *);
+
+  void (*demultiplex_2d)(sv_plane_t *, double *out, int dw, int x, int y, int n);
+
 } sv_plane_common_t;
 
 struct sv_plane_bg {
@@ -71,7 +71,10 @@
 struct sv_plane_2d {
   sv_plane_common_t c;
 
-  // data
+  // cached/helper 
+  int              data_z_output; 
+
+  // data; access unlocked
   float           *data;  
   float           *pending_data;  
   sv_ucolor_t     *image;
@@ -80,23 +83,16 @@
   slider_map_t     scale;
 
   // status 
-  sv_scalespace_t  data_x;
-  sv_scalespace_t  data_y;
-  sv_scalespace_t  pending_data_x;
-  sv_scalespace_t  pending_data_y;
-  int              data_waiting; 
-  int              data_incomplete; 
-  int              data_task;
+  int              data_outstanding; 
+  int              data_task; /* -1 busy, 0 realloc, 1 resizeA, 2 resizeB, 3 commit, 4 working, 5 idle */
   int              data_next;
 
   int              image_serialno;
-  sv_scalespace_t  image_x; 
-  sv_scalespace_t  image_y;
-  int              image_task;
+  int              image_outstanding;
+  int              image_task; /* -1 busy, 0 realloc, 1 resizeA, 2 resizeB, 3 commit, 4 working, 5 idle */
   int              image_next;
   int              image_mapnum;
   int             *image_flags;
-  int              image_remap_request;
   
   // resampling helpers
   unsigned char   *resample_xdelA;



More information about the commits mailing list