[xiph-commits] r12404 - trunk/sushivision
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Wed Jan 31 11:20:18 PST 2007
Author: xiphmont
Date: 2007-01-31 11:20:14 -0800 (Wed, 31 Jan 2007)
New Revision: 12404
Modified:
trunk/sushivision/example_fractal.c
trunk/sushivision/mapping.c
trunk/sushivision/mapping.h
trunk/sushivision/panel-1d.c
trunk/sushivision/panel-2d.c
trunk/sushivision/panel-2d.h
Log:
Incremental commit of in progress changes; DON'T USE THIS VERSION
Move the 2d panel to full-sized mapping planes on discrete
computation/map with resampling happing during remap rendering. This is
necessary to avoid unexpected boundary behavior, even if it is
slower/larger.
Modified: trunk/sushivision/example_fractal.c
===================================================================
--- trunk/sushivision/example_fractal.c 2007-01-31 18:09:34 UTC (rev 12403)
+++ trunk/sushivision/example_fractal.c 2007-01-31 19:20:14 UTC (rev 12404)
@@ -54,12 +54,12 @@
s=sushiv_new_instance();
- sushiv_new_dimension(s,0,"Re(c)",
+ sushiv_new_dimension_discrete(s,0,"Re(c)",
5,(double []){-2.25,-0.75,0,0.25,0.75},
- NULL,0);
- sushiv_new_dimension(s,1,"Im(c)",
+ NULL,1,1000,0);
+ sushiv_new_dimension_discrete(s,1,"Im(c)",
5,(double []){-2,-1,0,1,2},
- NULL,0);
+ NULL,1,1000,0);
sushiv_new_dimension(s,2,"Re(z0)",
5,(double []){-2.25,-1,0,1,2.25},
Modified: trunk/sushivision/mapping.c
===================================================================
--- trunk/sushivision/mapping.c 2007-01-31 18:09:34 UTC (rev 12403)
+++ trunk/sushivision/mapping.c 2007-01-31 19:20:14 UTC (rev 12404)
@@ -319,34 +319,6 @@
}
}
-u_int32_t mapping_calc_a(mapping *m, float num, float den, u_int32_t mix){
- u_int32_t o;
- int r = (mix>>16)&0xff;
- int g = (mix>>8)&0xff;
- int b = mix&0xff;
-
- if(m->i_range==0){
- if(num<=m->low)
- o = m->mapfunc(0.,mix);
- else
- o = m->mapfunc(1.,mix);
- }else{
- double val = (num - m->low) * m->i_range;
- o = m->mapfunc(val,mix);
- }
-
- r += ((int)((o>>16)&0xff) - r)*den;
- g += ((int)((o>>8)&0xff) - g)*den;
- b += ((int)(o&0xff) - b)*den;
- if(r<0)r=0;
- if(g<0)g=0;
- if(b<0)b=0;
- if(r>255)r=255;
- if(g>255)g=255;
- if(b>255)b=255;
- return (r<<16) + (g<<8) + b;
-}
-
int mapping_inactive_p(mapping *m){
if(m->mapfunc == inactive)return 1;
return 0;
Modified: trunk/sushivision/mapping.h
===================================================================
--- trunk/sushivision/mapping.h 2007-01-31 18:09:34 UTC (rev 12403)
+++ trunk/sushivision/mapping.h 2007-01-31 19:20:14 UTC (rev 12404)
@@ -36,7 +36,6 @@
extern void mapping_set_func(mapping *m, int funcnum);
extern double mapping_val(mapping *m, double in);
extern u_int32_t mapping_calc(mapping *m, double in, u_int32_t mix);
-extern u_int32_t mapping_calc_a(mapping *m, float num, float den, u_int32_t mix);
extern int mapping_inactive_p(mapping *m);
extern int num_solids();
Modified: trunk/sushivision/panel-1d.c
===================================================================
--- trunk/sushivision/panel-1d.c 2007-01-31 18:09:34 UTC (rev 12403)
+++ trunk/sushivision/panel-1d.c 2007-01-31 19:20:14 UTC (rev 12404)
@@ -70,7 +70,7 @@
if(plot){
int xi,i,j;
- double h = p1->panel_h;
+ //double h = p1->panel_h;
int dw = p1->data_size;
double r = (p1->flip?p1->panel_w:p1->panel_h);
Modified: trunk/sushivision/panel-2d.c
===================================================================
--- trunk/sushivision/panel-2d.c 2007-01-31 18:09:34 UTC (rev 12403)
+++ trunk/sushivision/panel-2d.c 2007-01-31 19:20:14 UTC (rev 12404)
@@ -35,410 +35,70 @@
/* helper functions for performing progressive computation */
-/* performs render helper cleanup after finishing a progressive
- render; makes sure old map is completely replaced by new. */
-/* Don't check serialno or size; we must force any completion before a
- resize/rerender, so it will always match anyway */
-/* call from lock */
-static void compute_complete_render(sushiv_panel_t *p,
- int true_complete){
-
- sushiv_panel2d_t *p2 = p->subtype->p2;
- scalespace *panelx = &p2->x;
- scalespace *panely = &p2->y;
- scalespace *datay = &p2->y_v;
-
- int i,x,y;
- int w = panelx->pixels;
- int h = panely->pixels;
-
- /* these progressive rendering helpers are specific to resampled y;
- if ph=dh, there's nothing to do */
-
- if(h != datay->pixels){
- if(p2->render_flag){
- if(true_complete){
- /* fully complete render; swap and zero */
-
- for(i=0;i<p2->y_obj_num;i++){
- float *n = p2->y_num_rend[i];
- float *d = p2->y_den_rend[i];
-
- p2->y_num_rend[i] = p2->y_num[i];
- p2->y_num[i] = n;
- p2->y_den_rend[i] = p2->y_den[i];
- p2->y_den[i] = d;
-
- memset(p2->y_num_rend[i],0,sizeof(**p2->y_num_rend)*w*h);
- memset(p2->y_den_rend[i],0,sizeof(**p2->y_den_rend)*w*h);
-
- }
-
- }else{
- /* partially complete render; force the completion as a mix of current/pending */
-
- for(i=0;i<p2->y_obj_num;i++){
- for(y=0;y<h;y++){
- float del = p2->y_rend[y];
- if(del>0){
- float *na = p2->y_num[i] + y*w;
- float *nb = p2->y_num_rend[i] + y*w;
- float *da = p2->y_den[i] + y*w;
- float *db = p2->y_den_rend[i] + y*w;
-
- for(x=0;x<w;x++){
- *na = (*na) + (*na - *nb++)*del;
- na++;
- }
-
- for(x=0;x<w;x++){
- *da = (*da) + (*da - *db++)*del;
- da++;
- }
- }
- }
-
- memset(p2->y_num_rend[i],0,sizeof(**p2->y_num_rend)*w*h);
- memset(p2->y_den_rend[i],0,sizeof(**p2->y_den_rend)*w*h);
-
- }
-
- }
-
- memset(p2->y_rend,0,sizeof(*p2->y_rend)*h);
- }
-
- p2->render_flag = 0;
- }
-}
-
-/* prepares for a render (checks for / sets up resampling) */
-// call from lock
-static void compute_prepare_render(sushiv_panel_t *p){
- sushiv_panel2d_t *p2 = p->subtype->p2;
- scalespace *panelx = &p2->x;
- scalespace *panely = &p2->y;
- scalespace *datay = &p2->y_v;
-
- int i;
- int w = panelx->pixels;
- int h = panely->pixels;
-
- if(p2->render_flag)
- compute_complete_render(p, 0);
-
- /* progressive rendering helpers are specific to resampled y;
- if ph=dh, there's nothing to do */
- if(h != datay->pixels){
- if(!p2->y_rend){
-
- p2->y_rend = calloc(h,sizeof(*p2->y_rend));
-
- if(!p2->y_num_rend)
- p2->y_num_rend = calloc(p2->y_obj_num,sizeof(*p2->y_num_rend));
- if(!p2->y_den_rend)
- p2->y_den_rend = calloc(p2->y_obj_num,sizeof(*p2->y_den_rend));
-
- for(i=0;i<p2->y_obj_num;i++){
- p2->y_num_rend[i] = calloc(w*h,sizeof(**p2->y_num_rend));
- p2->y_den_rend[i] = calloc(w*h,sizeof(**p2->y_den_rend));
- }
- }
- p2->render_flag = 1;
- }
-}
-
-static void compute_free_render(sushiv_panel_t *p){
- sushiv_panel2d_t *p2 = p->subtype->p2;
- int i;
-
- if(p2->y_rend){
- free(p2->y_rend);
- p2->y_rend = NULL;
- }
-
- if(p2->y_num_rend){
- for(i=0;i<p2->y_obj_num;i++){
- free(p2->y_num_rend[i]);
- p2->y_num_rend[i]=NULL;
- }
- }
-
- if(p2->y_den_rend){
- for(i=0;i<p2->y_obj_num;i++){
- free(p2->y_den_rend[i]);
- p2->y_den_rend[i]=NULL;
- }
- }
-}
-
// enter unlocked
static void compute_one_data_line_2d(sushiv_panel_t *p,
- scalespace panelx,
- scalespace datax,
+ int serialno,
+ int dw,
+ int y,
int x_d,
double x_min,
double x_max,
double *dim_vals,
_sushiv_compute_cache_2d *c){
- int pw = panelx.pixels;
- int dw = datax.pixels;
sushiv_panel2d_t *p2 = p->subtype->p2;
int i,j;
-
+
/* cache access is unlocked because the cache is private to this
worker thread */
- if(pw != dw){
- /* resampled computation */
- float scaledel = scalespace_scaledel(&datax,&panelx);
- float outdel = scalespace_pixel(&panelx,scalespace_value(&datax,-.5))+.5;
- int outbin = floor(outdel);
- outdel -= outbin;
+ for(j=0;j<dw;j++){
+ double *fout = c->fout;
+ sushiv_function_t **f = p2->used_function_list;
+ int *obj_y_off = p2->y_fout_offset;
+ int *onum = p2->y_obj_to_panel;
- /* zero obj line cache */
- for(i=0;i<p->objectives;i++){
- if(c->y_num[i])
- memset(c->y_num[i],0, c->storage_width * sizeof(**c->y_num));
- if(c->y_den[i])
- memset(c->y_den[i],0, c->storage_width * sizeof(**c->y_den));
+ /* by function */
+ dim_vals[x_d] = (x_max-x_min) * j / dw + x_min;
+ 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++)
+ c->y_map[i][j] = (float)slider_val_to_del(p2->range_scales[*onum++], c->fout[*obj_y_off++]);
- /* by x */
- for(j=0;j<dw;j++){
- float outdel2 = outdel + scaledel;
+ }
- double *fout = c->fout;
- sushiv_function_t **f = p2->used_function_list;
- int *obj_y_off = p2->y_fout_offset;
-
- float obj_y[p2->y_obj_num];
- int *onum = p2->y_obj_to_panel;
+ gdk_threads_enter ();
+ if(p2->serialno == serialno){
+ for(j=0;j<p2->y_obj_num;j++){
+ float *d = p2->y_map[j] + y*dw;
+ float *td = c->y_map[j];
- /* by function */
- dim_vals[x_d] = (x_max-x_min) * j / dw + x_min;
- 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++){
- obj_y[i] = (float)slider_val_to_del(p2->range_scales[*onum], c->fout[*obj_y_off]);
- obj_y_off++;
- onum++;
- }
+ memcpy(d,td,dw*sizeof(*d));
- /* resample */
- while(outdel2>1.f){
- float addel = (1.f - outdel);
-
- if(outbin >= 0 && outbin < pw){
- for(i=0;i<p2->y_obj_num;i++){
- if(!isnan(obj_y[i])){
- c->y_num[i][outbin] += obj_y[i] * addel;
- c->y_den[i][outbin] += addel;
- }
- }
- }
-
- outdel2--;;
- outbin++;
- outdel = 0.f;
- }
-
- if(outdel2>0.f){
- float addel = (outdel2 - outdel);
-
- if(outbin >= 0 && outbin < pw){
- for(i=0;i<p2->y_obj_num;i++){
- if(!isnan(obj_y[i])){
- c->y_num[i][outbin] += obj_y[i] * addel;
- c->y_den[i][outbin] += addel;
- }
- }
- }
- outdel += addel;
- }
}
-
- }else{
- /* simpler non-resampling case */
- /* by x */
- for(j=0;j<dw;j++){
- double *fout = c->fout;
- sushiv_function_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] = (x_max-x_min) * j / dw + x_min;
- 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 yval = (float)slider_val_to_del(p2->range_scales[*onum], c->fout[*obj_y_off]);
-
- if(!isnan(yval)){
- c->y_num[i][j] = yval;
- c->y_den[i][j] = 1.f;
- }else{
- c->y_num[i][j] = 0.f;
- c->y_den[i][j] = 0.f;
- }
-
- obj_y_off++;
- onum++;
- }
- }
}
-}
+ gdk_threads_leave ();
-/* Although render/swizzle is done by data line, we still need to
- display panel lines. This is a wrapper around data line rendering
- that updates the relevant panel line[s] with the computed
- data. */
-static void compute_one_line_2d(sushiv_panel_t *p,
- int serialno,
- scalespace panelx,
- scalespace datax,
- scalespace panely,
- scalespace datay,
-
- int y, // data line
- int x_d,
- double x_min,
- double x_max,
- double *dim_vals,
- _sushiv_compute_cache_2d *c){
-
- sushiv_panel2d_t *p2 = p->subtype->p2;
- int i,j;
- int w = panelx.pixels;
- int ph = panely.pixels;
- int dh = datay.pixels;
-
- /* before anything else-- compute the line. */
- compute_one_data_line_2d(p, panelx, datax, x_d, x_min, x_max,
- dim_vals, c);
-
- if(ph != dh){
- /* this is a resampling population */
-
- float scaledel = scalespace_scaledel(&datay,&panely);
- float outdel = scalespace_pixel(&panely,scalespace_value(&datay,y-.5))+.5;
- int outbin = floor(outdel);
- float outdel2 = (outdel-outbin) + scaledel;
- outdel -= outbin;
-
- while(outdel2>1.f){
- float addel = (1.f - outdel);
-
- if(outbin >= 0 && outbin < ph){
- gdk_threads_enter ();
-
- if(p2->serialno == serialno){
- for(j=0;j<p2->y_obj_num;j++){
- float *n = p2->y_num_rend[j] + outbin*w;
- float *d = p2->y_den_rend[j] + outbin*w;
- float *tn = c->y_num[j];
- float *td = c->y_den[j];
-
- for(i=0;i<w;i++){
- n[i] += tn[i] * addel;
- d[i] += td[i] * addel;
- }
-
- }
- p2->y_rend[outbin]+=addel;
- gdk_threads_leave ();
- }else{
- gdk_threads_leave ();
- return;
- }
- }
-
- outdel2--;
- outbin++;
- outdel = 0.f;
- }
-
- if(outdel2>0.f){
- float addel = (outdel2 - outdel);
-
- if(outbin >= 0 && outbin < ph){
- gdk_threads_enter ();
- if(p2->serialno == serialno){
- for(j=0;j<p2->y_obj_num;j++){
- float *n = p2->y_num_rend[j] + outbin*w;
- float *d = p2->y_den_rend[j] + outbin*w;
- float *tn = c->y_num[j];
- float *td = c->y_den[j];
-
- for(i=0;i<w;i++){
- n[i] += tn[i] * addel;
- d[i] += td[i] * addel;
- }
-
- }
- p2->y_rend[outbin]+=addel;
- }
- gdk_threads_leave ();
- }
- }
- }else{
-
- gdk_threads_enter ();
-
- if(p2->serialno == serialno){
- for(j=0;j<p2->y_obj_num;j++){
- float *n = p2->y_num[j] + y*w;
- float *d = p2->y_den[j] + y*w;
- float *tn = c->y_num[j];
- float *td = c->y_den[j];
-
- memcpy(n,tn,w*sizeof(*n));
- memcpy(d,td,w*sizeof(*n));
-
- }
- }
- gdk_threads_leave ();
- }
}
// call with lock
static void clear_pane(sushiv_panel_t *p){
sushiv_panel2d_t *p2 = p->subtype->p2;
- scalespace *panelx = &p2->x;
- scalespace *panely = &p2->y;
int i;
- int w = panelx->pixels;
- int h = panely->pixels;
for(i=0;i<p2->y_obj_num;i++){
- memset(p2->y_num[i],0,sizeof(**p2->y_num)*w*h);
- memset(p2->y_den[i],0,sizeof(**p2->y_den)*w*h);
- if(p2->y_num_rend && p2->y_num_rend[i])
- memset(p2->y_num_rend[i],0,sizeof(**p2->y_num_rend)*w*h);
- if(p2->y_den_rend && p2->y_den_rend[i])
- memset(p2->y_den_rend[i],0,sizeof(**p2->y_den_rend)*w*h);
- }
- if(p2->y_rend)
- memset(p2->y_rend,0,sizeof(*p2->y_rend)*h);
- p2->render_flag = 0;
+ free(p2->y_map[i]);
+ p2->y_map[i]=NULL;
+ }
}
typedef struct{
@@ -543,48 +203,161 @@
}
}
-static void render_y_plane(sushiv_panel_t *p, int y, int objnum, u_int32_t *render){
- sushiv_panel2d_t *p2 = p->subtype->p2;
+static void resample_render_y_plane_line(mapping *map, float obj_alpha,
+ float *r, float *g, float *b, float linedel,
+ u_int32_t *panel, scalespace panelx,
+ float *data, scalespace datax){
+ int pw = panelx.pixels;
+ int dw = datax.pixels;
+ int i;
- int w,h,x;
- int cond_onum = p2->y_obj_from_panel[objnum];
- double alpha = p2->alphadel[objnum];
- w = p2->x.pixels;
- h = p2->y.pixels;
+ float x_scaledel = scalespace_scaledel(&panelx,&datax);
+ float x_del = scalespace_pixel(&datax,scalespace_value(&panelx,-.5))+.5;
+ int x_bin = floor(x_del);
+ x_del -= x_bin;
+ linedel *= .00392156862745; // 1./255
+ for(i=0;i<pw;i++){
+ float alpha=1.f;
+ float x_del2 = x_del + x_scaledel;
+
+ while(x_del2>=1.f){
+ float addel = (1.f - x_del);
+ float pixdel = addel*linedel;
- // is this a resampled render in-progress?
- if(p2->render_flag){
- // resampled render in-progress; we must merge the panel and render buffers
- float del = p2->y_rend[y];
- float *numA = p2->y_num[cond_onum] + w*y;
- float *denA = p2->y_den[cond_onum] + w*y;
- float *numB = p2->y_num_rend[cond_onum] + w*y;
- float *denB = p2->y_den_rend[cond_onum] + w*y;
-
- for(x=0;x<w;x++){
- float num = numA[x] + (numB[x] - numA[x])*del;
- float den = denA[x] + (denB[x] - denA[x])*del;
- if(den>0.f && !isnan(num)){
- num /= den;
- /* map/render result */
- if(num>=alpha)
- render[x] = mapping_calc_a(p2->mappings+objnum,num,den,render[x]);
+ if(x_bin >= 0 && x_bin < dw){
+ float val = data[x_bin];
+ if(!isnan(val) && val >= obj_alpha){
+ u_int32_t partial = mapping_calc(map,val,panel[i]);
+ r[i] += ((partial>>16)&0xff) * pixdel/x_scaledel;
+ g[i] += ((partial>>8)&0xff) * pixdel/x_scaledel;
+ b[i] += ((partial)&0xff) * pixdel/x_scaledel;
+ alpha -= addel/x_scaledel;
+ }
}
+
+ x_del2--;
+ x_bin++;
+ x_del = 0.f;
}
- }else{
- // normal render or fully complete resampled render
+ if(x_del2>0.f){
+ float addel = (x_del2 - x_del);
+ float pixdel = addel*linedel;
+
+ if(x_bin >= 0 && x_bin < dw){
+ float val = data[x_bin];
+ if(!isnan(val) && val >= obj_alpha){
+ u_int32_t partial = mapping_calc(map,val,panel[i]);
+ r[i] += ((partial>>16)&0xff) * pixdel/x_scaledel;
+ g[i] += ((partial>>8)&0xff) * pixdel/x_scaledel;
+ b[i] += ((partial)&0xff) * pixdel/x_scaledel;
+ alpha -= addel/x_scaledel;
+ }
+ }
+ x_del = x_del2;
+ }
+
+ /* partial pixels need some of the background mixed in */
+ if(alpha>0.f){
+ float pixdel = alpha*linedel;
+ u_int32_t bg = panel[i];
+ r[i] += ((bg>>16)&0xff) * pixdel;
+ g[i] += ((bg>>8)&0xff) * pixdel;
+ b[i] += ((bg)&0xff) * pixdel;
+ }
+ }
+}
+
+/* the data rectangle is data width/height mapped deltas. we render
+ and subsample at the same time. */
+static void resample_render_y_plane(mapping *map, float obj_alpha,
+ u_int32_t *panel, scalespace panelx, scalespace panely,
+ float *data, scalespace datax, scalespace datay){
+ int pw = panelx.pixels;
+ int dw = datax.pixels;
+ int ph = panely.pixels;
+ int dh = datay.pixels;
+ int i,j;
+
+ if(ph!=dh || pw!=dw){
+ /* resampled row computation */
- float *num = p2->y_num[cond_onum] + w*y;
- float *den = p2->y_den[cond_onum] + w*y;
+ /* by line */
+ float y_scaledel = scalespace_scaledel(&panely,&datay);
+ float y_del = scalespace_pixel(&datay,scalespace_value(&panely,-.5))+.5;
+ int y_bin = floor(y_del);
+ y_del -= y_bin;
+
+ for(i=0;i<ph;i++){
+ /* render is done into a temporary line because of the way alpha
+ blending is done; the background for the blend must be taken
+ from the original line */
+ float r[pw];
+ float g[pw];
+ float b[pw];
+ float alpha=1.f;
+ float y_del2 = y_del + y_scaledel;
+ u_int32_t *line = panel+i*pw;
+
+ /* the x resample may have blends as well */
+ memset(r,0,sizeof(r));
+ memset(g,0,sizeof(g));
+ memset(b,0,sizeof(b));
+
+ while(y_del2>=1.f){
+ float addel = (1.f - y_del);
+
+ if(y_bin >= 0 && y_bin < dh){
+ resample_render_y_plane_line(map,obj_alpha,
+ r,g,b,addel/y_scaledel,
+ line,
+ panelx,
+ data+y_bin*dw,
+ datax);
+ alpha -= addel/y_scaledel;
+ }
+
+ y_del2--;
+ y_bin++;
+ y_del = 0.f;
+ }
+
+ if(y_del2>0.f){
+ float addel = (y_del2 - y_del);
+
+ if(y_bin >= 0 && y_bin < dh){
+ resample_render_y_plane_line(map,obj_alpha,
+ r,g,b,addel/y_scaledel,
+ line,
+ panelx,
+ data+y_bin*dw,
+ datax);
+ alpha -= addel/y_scaledel;
+ }
+ y_del += addel;
+ }
- for(x=0;x<w;x++){
- if(den[x]>0.f && !isnan(num[x])){
- float val = num[x] / den[x];
- /* map/render result */
- if(val>=alpha)
- render[x] = mapping_calc_a(p2->mappings+objnum,val,den[x],render[x]);
+ /* work is finished; replace panel line with it */
+ if(alpha<0.f)alpha=0.f; // guard rounding error;
+
+ for(j=0;j<pw;j++){
+ int ri = rint(r[j]*0xff0000.p0f + (line[j]&0xff0000) * alpha);
+ int gi = rint(g[j]*0xff00.p0f + (line[j]&0xff00) * alpha);
+ int bi = rint(b[j]*0xff.p0f + (line[j]&0xff) * alpha);
+
+ line[j] = (ri&0xff0000) + (gi&0xff00) + (bi&0xff);
}
+ }
+ }else{
+ /* non-resampling render */
+ for(i=0;i<ph;i++){
+ u_int32_t *pline = panel+i*pw;
+ float *dline = data+i*pw;
+ for(j=0;j<pw;j++){
+ float val = dline[j];
+ if(!isnan(val) && val >= obj_alpha)
+ pline[j] = mapping_calc(map,val,pline[j]);
+ }
}
}
}
@@ -593,28 +366,29 @@
sushiv_panel2d_t *p2 = p->subtype->p2;
Plot *plot = PLOT(p->private->graph);
- int w,h,y,i;
- w = p2->x.pixels;
- h = p2->y.pixels;
+ int pw,ph,y,i;
+ pw = p2->x.pixels;
+ ph = p2->y.pixels;
if(plot){
- for(y = 0; y<h; y++){
- u_int32_t *render = plot->datarect + y*w;
+ /* background checks */
+ for(y = 0; y<ph; y++)
+ render_checks(pw,y,plot->datarect + y*pw);
- /* background checks */
- render_checks(w,y,render);
+ /* by objective */
+ for(i=0;i<p->objectives;i++){
+
+ /**** render Y plane */
+ int o_ynum = p2->y_obj_from_panel[i];
+ if(p2->y_map[o_ynum])
+ resample_render_y_plane(p2->mappings+i, p2->alphadel[i],
+ plot->datarect, p2->x, p2->y,
+ p2->y_map[o_ynum], p2->x_v, p2->y_v);
- /* by objective */
- for(i=0;i<p->objectives;i++){
-
- /**** render Y plane */
- render_y_plane(p, y, i, render);
-
- /**** render Z plane */
+ /**** render Z plane */
+
+ /**** render vector plane */
- /**** render vector plane */
-
- }
}
}
}
@@ -847,12 +621,15 @@
float *data_line = data+y*w;
for(x=0;x<w;x++){
if(mapbase[x]<0 || mapbase[x]>=(w-1)){
- work[x]=0.f;
+ work[x]=NAN;
}else{
int base = mapbase[x];
float del = mapdel[x];
float A = data_line[base];
float B = data_line[base+1];
+ if(isnan(A) || isnan(B))
+ work[x]=NAN;
+ else
work[x]= A + (B - A)*del;
}
@@ -892,15 +669,17 @@
int stride = w;
for(y=0;y<h;y++){
if(mapbase[y]<0 || mapbase[y]>=(h-1)){
- work[y]=0.f;
+ work[y]=NAN;
}else{
int base = mapbase[y]*stride;
float del = mapdel[y];
float A = data_column[base];
float B = data_column[base+stride];
+ if(isnan(A) || isnan(B))
+ work[y]=NAN;
+ else
+ work[y]= A + (B-A)*del;
- work[y]= A + (B-A)*del;
-
}
}
for(y=0;y<h;y++){
@@ -969,118 +748,23 @@
}
}
-// call only from main gtk thread!
+// call only from main gtk thread
static void _mark_recompute_2d(sushiv_panel_t *p){
if(!p->private->realized) return;
sushiv_panel2d_t *p2 = p->subtype->p2;
Plot *plot = PLOT(p->private->graph);
- int w = plot->w.allocation.width;
- int h = plot->w.allocation.height;
- int remapflag = 0;
if(plot && GTK_WIDGET_REALIZED(GTK_WIDGET(plot))){
-
- if( p2->serialno && // we've been through once and alloced
- (p2->x.pixels != w ||
- p2->y.pixels != h)){
-
- // if a render was in progress, force completion
- compute_complete_render(p, 0);
- compute_free_render(p);
- // make new rects, do a fast/dirty scaling job from old to new
- int i;
-
- /* Y planes */
- for(i=0;i<p2->y_obj_num;i++){
- float *new_n = calloc(w*h,sizeof(*new_n));
- float *new_d = calloc(w*h,sizeof(*new_d));
-
- fast_scale(new_n,plot->x,plot->y,p2->y_num[i],p2->x,p2->y);
- fast_scale(new_d,plot->x,plot->y,p2->y_den[i],p2->x,p2->y);
-
- free(p2->y_num[i]);
- free(p2->y_den[i]);
- p2->y_num[i] = new_n;
- p2->y_den[i] = new_d;
- }
-
- /* match data scales to new panel size/scale */
- p2->x = plot->x;
- _sushiv_dimension_scales_from_panel(p2->x_d,
- p2->x,
- p2->x.pixels, // over/undersample will go here
- &p2->x_v,
- &p2->x_i);
- p2->y = plot->y;
- _sushiv_dimension_scales_from_panel(p2->y_d,
- p2->y,
- p2->y.pixels, // over/undersample will go here
- &p2->y_v,
- &p2->y_i);
- _sushiv_panel2d_map_redraw(p);
- }else{
-
- _sushiv_dimension_scales(p2->x_d,
- p2->x_d->bracket[0],
- p2->x_d->bracket[1],
- w,w,// over/undersample will go here
- plot->scalespacing,
- p2->x_d->name,
- &p2->x,
- &p2->x_v,
- &p2->x_i);
- _sushiv_dimension_scales(p2->y_d,
- p2->y_d->bracket[1],
- p2->y_d->bracket[0],
- h,h,// over/undersample will go here
- plot->scalespacing,
- p2->y_d->name,
- &p2->y,
- &p2->y_v,
- &p2->y_i);
- }
-
- if(!p2->y_num){
- int i;
- // allocate it
-
- p2->y_num = calloc(p2->y_obj_num,sizeof(*p2->y_num));
- for(i=0;i<p2->y_obj_num;i++)
- p2->y_num[i] = calloc(w*h, sizeof(**p2->y_num));
-
- remapflag = 1;
- }
-
- if(!p2->y_den){
- int i;
- // allocate it
-
- p2->y_den = calloc(p2->y_obj_num,sizeof(*p2->y_den));
- for(i=0;i<p2->y_obj_num;i++)
- p2->y_den[i] = calloc(w*h, sizeof(**p2->y_den));
-
- remapflag = 1;
- }
-
- if(remapflag)
- _sushiv_panel2d_map_redraw(p);
-
p2->serialno++;
p2->last_line = 0;
p2->completed_lines = 0;
_sushiv_panel1d_mark_recompute_linked(p);
-
_sushiv_wake_workers();
}
}
-static void recompute_callback_2d(void *ptr){
- sushiv_panel_t *p = (sushiv_panel_t *)ptr;
- _mark_recompute_2d(p);
-}
-
static void update_crosshairs(sushiv_panel_t *p){
sushiv_panel2d_t *p2 = p->subtype->p2;
Plot *plot = PLOT(p->private->graph);
@@ -1222,24 +906,20 @@
c->fout = calloc(count, sizeof(*c->fout));
/* objective line buffer index */
- c->y_num = calloc(p2->y_obj_num,sizeof(*c->y_num));
- c->y_den = calloc(p2->y_obj_num,sizeof(*c->y_den));
- for(i=0;i<p2->y_obj_num;i++){
- c->y_num[i] = calloc(w,sizeof(**c->y_num));
- c->y_den[i] = calloc(w,sizeof(**c->y_den));
- }
+ 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));
- for(i=0;i<p2->y_obj_num;i++){
- c->y_num[i] = realloc(c->y_num[i],w*sizeof(**c->y_num));
- c->y_den[i] = realloc(c->y_den[i],w*sizeof(**c->y_den));
- }
}
}
@@ -1259,27 +939,94 @@
double y_min, y_max;
int x_d=-1, y_d=-1;
int render_scale_flag = 0;
- scalespace sx,sx_v;
- scalespace sy,sy_v;
+ scalespace sx,sx_v,sx_i;
+ scalespace sy,sy_v,sy_i;
// lock during setup
gdk_threads_enter ();
- sx = p2->x;
- sx_v = p2->x_i;
- sy = p2->y;
- sy_v = p2->y_i;
+ plot = PLOT(p->private->graph);
+ pw = plot->x.pixels;
+ ph = plot->y.pixels;
- pw = sx.pixels;
- ph = sy.pixels;
+ x_d = p2->x_d->number;
+ y_d = p2->y_d->number;
+
+ // beginning of computation init
+ if(p2->last_line==0){
+
+ // generate new scales
+ _sushiv_dimension_scales(p2->x_d,
+ p2->x_d->bracket[0],
+ p2->x_d->bracket[1],
+ pw,pw,// over/undersample will go here
+ plot->scalespacing,
+ p2->x_d->name,
+ &sx,
+ &sx_v,
+ &sx_i);
+ _sushiv_dimension_scales(p2->y_d,
+ p2->y_d->bracket[1],
+ p2->y_d->bracket[0],
+ ph,ph,// over/undersample will go here
+ plot->scalespacing,
+ p2->y_d->name,
+ &sy,
+ &sy_v,
+ &sy_i);
+
+ // maintain data planes
+ for(i=0;i<p2->y_obj_num;i++){
+ // allocate new storage
+ float *newmap = calloc(sx_v.pixels*sy_v.pixels,sizeof(*newmap));
+ float *oldmap = p2->y_map[i];
+ int j;
+ for(j=0;j<sx_v.pixels*sy_v.pixels;j++)
+ newmap[j]=NAN;
+
+ // zoom scale data in map planes as placeholder for render
+ if(oldmap)
+ fast_scale(newmap, sx_v, sy_v,
+ oldmap,p2->x_v, p2->y_v);
+
+ p2->y_map[i] = newmap;
+ if(oldmap) free(oldmap);
+ }
+
+ 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;
+
+ _sushiv_panel2d_remap(p);
+ p2->last_line++;
+ gdk_threads_leave ();
+ plot_draw_scales(plot);
+
+ 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;
+ }
+
dw = sx_v.pixels;
dh = sy_v.pixels;
- if(p2->last_line>=dh){
+ if(p2->last_line>dh){
gdk_threads_leave ();
return 0;
}
- plot = PLOT(p->private->graph);
+ _maintain_cache_2d(p,&c->p2,dw);
+
serialno = p2->serialno;
d = p->dimensions;
@@ -1289,42 +1036,10 @@
x_min = scalespace_value(&p2->x_i,0);
x_max = scalespace_value(&p2->x_i,dw);
- x_d = p2->x_d->number;
y_min = scalespace_value(&p2->y_i,0);
y_max = scalespace_value(&p2->y_i,dh);
- y_d = p2->y_d->number;
- // preparation and init before first line render attempt
- _maintain_cache_2d(p,&c->p2,pw);
- if(p2->last_line==0){
- render_scale_flag = 1;
- compute_prepare_render(p);
-
- // if the scale bound has changed, fast scale our background data to fill
- // the pane while new, more precise data renders.
- if(memcmp(&sx,&plot->x,sizeof(sx))){
- for(i=0;i<p2->y_obj_num;i++){
- fast_scale_x(p2->y_num[i],pw,ph,
- sx,plot->x);
- fast_scale_x(p2->y_den[i],pw,ph,
- sx,plot->x);
- }
- plot->x = sx;
- _sushiv_panel2d_remap(p);
- }
- if(memcmp(&sy,&plot->y,sizeof(sy))){
- for(i=0;i<p2->y_obj_num;i++){
- fast_scale_y(p2->y_num[i],pw,ph,
- sy,plot->y);
- fast_scale_y(p2->y_den[i],pw,ph,
- sy,plot->y);
- }
- plot->y = sy;
- _sushiv_panel2d_remap(p);
- }
- }
-
// Initialize local dimension value array
for(i=0;i<p->sushi->dimensions;i++){
sushiv_dimension_t *dim = p->sushi->dimension_list[i];
@@ -1333,34 +1048,27 @@
/* iterate */
/* by line */
- if(p2->last_line<dh &&
+ if(p2->last_line<=dh &&
serialno == p2->serialno){
- int y = v_swizzle(p2->last_line,dh);
+ int y = v_swizzle(p2->last_line-1,dh);
p2->last_line++;
/* unlock for computation */
gdk_threads_leave ();
- if(render_scale_flag){
- plot_draw_scales(plot);
- render_scale_flag = 0;
- }
-
dim_vals[y_d]= (y_max - y_min) / dh * y + y_min;
/* compute line */
- compute_one_line_2d(p, serialno, sx, sx_v, sy, sy_v, y, x_d, x_min, x_max, dim_vals, &c->p2);
+ compute_one_data_line_2d(p, serialno, dw, y, x_d, x_min, x_max, dim_vals, &c->p2);
gdk_threads_enter ();
if(p2->serialno == serialno){
p2->completed_lines++;
- if(p2->completed_lines==dh){
- compute_complete_render(p, 1);
+ if(p2->completed_lines>=dh){
_sushiv_panel_dirty_map(p);
_sushiv_panel_dirty_legend(p);
- plot_expose_request(plot);
}else{
_sushiv_panel_dirty_map_throttled(p);
}
@@ -1371,6 +1079,13 @@
return 1;
}
+static void recompute_callback_2d(void *ptr){
+ sushiv_panel_t *p = (sushiv_panel_t *)ptr;
+ _mark_recompute_2d(p);
+ // force the remap scaling to happen before an expose blanks the pane
+ _sushiv_panel_cooperative_compute_2d(p,NULL);
+}
+
static void panel2d_undo_log(sushiv_panel_undo_t *u, sushiv_panel_t *p){
sushiv_panel2d_t *p2 = p->subtype->p2;
int i;
@@ -1867,6 +1582,8 @@
p2->y_fout_offset[i] = fout_offsets[funcnum] + o->private->y_fout;
}
}
+
+ p2->y_map = calloc(p2->y_obj_num,sizeof(*p2->y_map));
return 0;
}
Modified: trunk/sushivision/panel-2d.h
===================================================================
--- trunk/sushivision/panel-2d.h 2007-01-31 18:09:34 UTC (rev 12403)
+++ trunk/sushivision/panel-2d.h 2007-01-31 19:20:14 UTC (rev 12404)
@@ -33,25 +33,14 @@
sushiv_function_t **used_function_list;
/**** Y PLANES ******/
- float **y_num; // not indirected; unused planes are simply empty
- float **y_den; // not indirected; unused planes are simply empty
-
int y_obj_num;
+ float **y_map; // indirected, dw*dh
+
sushiv_objective_t **y_obj_list; // list of objectives with a y plane
int *y_obj_to_panel; /* maps from position in condensed list to position in full list */
int *y_obj_from_panel; /* maps from position in full list to position in condensed list */
int *y_fout_offset;
- /* these are gratuitous temporary storage to make progressive
- resampled render after a fast scale look nicer. They're here
- purely on the premise that 'lots of memory is cheap'. I'm sure
- Firefox is at least this stupidly wasteful of memory for cosmetic
- benefit. */
- int render_flag;
- float **y_num_rend;
- float **y_den_rend;
- float *y_rend;
-
/* scales and data -> display scale mapping */
scalespace x;
scalespace x_v;
@@ -89,8 +78,7 @@
typedef struct {
double *fout; // [function number * outval_number]
- float **y_num; // [y_obj_list[i]][px]
- float **y_den; // [y_obj_list[i]][px]
+ float **y_map; // [y_obj_list[i]][px]
int storage_width;
More information about the commits
mailing list