ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 2.14
Committed: Wed Oct 10 21:41:02 2012 UTC (11 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad5R0, rad5R1, rad4R2, rad4R2P1
Changes since 2.13: +4 -2 lines
Log Message:
Fixed array-underflow (original bug discovered by Pally Sandher)

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.14 static const char RCSid[] = "$Id: glareval.c,v 2.13 2010/12/02 18:08:11 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * Compute pixels for glare calculation
6     */
7    
8 schorsch 2.9 #include "copyright.h"
9    
10 schorsch 2.10 #include <stdlib.h>
11 schorsch 2.9 #include <string.h>
12    
13 greg 2.13 #include "platform.h"
14 schorsch 2.7 #include "rtprocess.h" /* Windows: must come first because of conflicts */
15 greg 1.1 #include "glare.h"
16 schorsch 2.7
17 greg 1.19 /* maximum rtrace buffer size */
18     #define MAXPIX (4096/(6*sizeof(float)))
19 greg 1.1
20 greg 1.16 #define MAXSBUF 786432 /* maximum total size of scanline buffer */
21 greg 1.9 #define HSIZE 317 /* size of scanline hash table */
22 greg 1.8 #define NRETIRE 16 /* number of scanlines to retire at once */
23 greg 1.1
24 schorsch 2.7 static SUBPROC rt_pd = SP_INACTIVE; /* process id & descriptors for rtrace */
25 greg 1.1
26     FILE *pictfp = NULL; /* picture file pointer */
27     double exposure; /* picture exposure */
28     int pxsiz, pysiz; /* picture dimensions */
29 greg 1.8
30     static int curpos; /* current scanline */
31     static long *scanpos; /* scanline positions */
32    
33     typedef struct scan {
34     int y; /* scanline position */
35 greg 1.1 long lused; /* for LRU replacement */
36 greg 1.8 struct scan *next; /* next in this hash or free list */
37     /* followed by the scanline data */
38     } SCAN; /* buffered scanline */
39 greg 1.1
40 greg 1.8 #define scandata(sl) ((COLR *)((sl)+1))
41     #define shash(y) ((y)%HSIZE)
42    
43 greg 1.19 static int maxpix; /* maximum number of pixels to buffer */
44    
45 greg 1.8 static SCAN *freelist; /* scanline free list */
46     static SCAN *hashtab[HSIZE]; /* scanline hash table */
47    
48 greg 2.2 static long scanbufsiz; /* size of allocated scanline buffer */
49    
50 greg 1.2 static long ncall = 0L; /* number of calls to getpictscan */
51     static long nread = 0L; /* number of scanlines read */
52 greg 1.15 static long nrecl = 0L; /* number of scanlines reclaimed */
53 greg 1.1
54 greg 1.13 static int wrongformat = 0;
55    
56 schorsch 2.11 static SCAN * claimscan(int y);
57     static COLR * getpictscan(int y);
58     static double pict_val(FVECT vd);
59     static void rt_compute(float *pb, int np);
60     static gethfunc getexpos;
61     static SCAN * scanretire(void);
62     static void initscans(void);
63     static void donescans(void);
64 greg 1.8
65 greg 1.2
66 schorsch 2.11 static SCAN *
67     claimscan( /* claim scanline from buffers */
68     int y
69     )
70 greg 1.8 {
71     int hi = shash(y);
72     SCAN *slast;
73     register SCAN *sl;
74    
75     for (sl = hashtab[hi]; sl != NULL; sl = sl->next)
76     if (sl->y == y) /* active scanline */
77     return(sl);
78     for (slast = NULL, sl = freelist; sl != NULL; slast = sl, sl = sl->next)
79     if (sl->y == -1 || sl->y == y || sl->next == NULL) {
80     if (slast == NULL) /* remove from free */
81     freelist = sl->next;
82     else
83     slast->next = sl->next;
84     if (sl->y == y) { /* reclaim */
85     sl->next = hashtab[hi];
86     hashtab[hi] = sl;
87 greg 1.15 nrecl++;
88 greg 1.8 }
89     return(sl);
90     }
91     return(scanretire()); /* need more free scanlines */
92     }
93    
94    
95 schorsch 2.11 static COLR *
96     getpictscan( /* get picture scanline */
97     int y
98     )
99 greg 1.1 {
100 greg 1.8 register SCAN *sl;
101 greg 1.1 register int i;
102     /* first check our buffers */
103 greg 1.8 sl = claimscan(y);
104     if (sl == NULL)
105     memerr("claimscan()");
106     sl->lused = ncall++;
107     if (sl->y == y) /* scan hit */
108     return(scandata(sl));
109     /* else read in replacement */
110 greg 1.5 if (scanpos[y] < 0) { /* need to search */
111     for (i = y+1; i < curpos; i++)
112     if (scanpos[i] >= 0) {
113     if (fseek(pictfp, scanpos[i], 0) < 0)
114     goto seekerr;
115     curpos = i;
116     break;
117     }
118     while (curpos >= y) {
119 greg 1.1 scanpos[curpos] = ftell(pictfp);
120 greg 1.8 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
121 greg 1.1 goto readerr;
122 greg 1.5 nread++;
123 greg 1.1 curpos--;
124     }
125 greg 1.5 } else {
126     if (curpos != y && fseek(pictfp, scanpos[y], 0) < 0)
127     goto seekerr;
128 greg 1.8 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
129 greg 1.5 goto readerr;
130     nread++;
131     curpos = y-1;
132 greg 1.1 }
133 greg 1.8 sl->y = y;
134     i = shash(y); /* add to hash list */
135     sl->next = hashtab[i];
136     hashtab[i] = sl;
137     return(scandata(sl));
138 greg 1.1 readerr:
139     fprintf(stderr, "%s: picture read error\n", progname);
140     exit(1);
141 greg 1.5 seekerr:
142     fprintf(stderr, "%s: picture seek error\n", progname);
143     exit(1);
144 greg 1.1 }
145    
146    
147 greg 1.6 #ifdef DEBUG
148 greg 2.12 void
149 schorsch 2.11 pict_stats(void) /* print out picture read statistics */
150 greg 1.2 {
151     static long lastcall = 0L; /* ncall at last report */
152     static long lastread = 0L; /* nread at last report */
153 greg 1.15 static long lastrecl = 0L; /* nrecl at last report */
154 greg 1.2
155     if (ncall == lastcall)
156     return;
157 greg 1.15 fprintf(stderr, "%s: %ld scanlines read (%ld reclaimed) in %ld calls\n",
158     progname, nread-lastread, nrecl-lastrecl, ncall-lastcall);
159 greg 1.2 lastcall = ncall;
160     lastread = nread;
161 greg 1.15 lastrecl = nrecl;
162 greg 1.2 }
163 greg 1.6 #endif
164 greg 1.2
165    
166 schorsch 2.11 static double
167     pict_val( /* find picture value for view direction */
168     FVECT vd
169     )
170 greg 1.1 {
171     FVECT pp;
172 greg 1.21 FVECT ip;
173 greg 1.1 COLOR res;
174    
175     if (pictfp == NULL)
176     return(-1.0);
177     pp[0] = pictview.vp[0] + vd[0];
178     pp[1] = pictview.vp[1] + vd[1];
179     pp[2] = pictview.vp[2] + vd[2];
180 greg 1.21 viewloc(ip, &pictview, pp);
181     if (ip[2] <= FTINY || ip[0] < 0. || ip[0] >= 1. ||
182     ip[1] < 0. || ip[1] >= 1.)
183 greg 1.1 return(-1.0);
184 greg 1.21 colr_color(res, getpictscan((int)(ip[1]*pysiz))[(int)(ip[0]*pxsiz)]);
185 greg 1.1 return(luminance(res)/exposure);
186     }
187    
188    
189 schorsch 2.11 extern double
190     getviewpix( /* compute single view pixel */
191     int vh,
192     int vv
193     )
194 greg 1.1 {
195     FVECT dir;
196 greg 1.19 float rt_buf[12];
197 greg 1.1 double res;
198    
199 greg 1.14 if (compdir(dir, vh, vv) < 0)
200 greg 1.1 return(-1.0);
201 greg 1.7 npixinvw++;
202 greg 1.1 if ((res = pict_val(dir)) >= 0.0)
203     return(res);
204 schorsch 2.7 if (rt_pd.r == -1) {
205 greg 1.7 npixmiss++;
206 greg 1.1 return(-1.0);
207 greg 1.7 }
208 greg 1.1 rt_buf[0] = ourview.vp[0];
209     rt_buf[1] = ourview.vp[1];
210     rt_buf[2] = ourview.vp[2];
211     rt_buf[3] = dir[0];
212     rt_buf[4] = dir[1];
213     rt_buf[5] = dir[2];
214     rt_compute(rt_buf, 1);
215     return(luminance(rt_buf));
216     }
217    
218    
219 schorsch 2.11 extern void
220     getviewspan( /* compute a span of view pixels */
221     int vv,
222     float *vb
223     )
224 greg 1.1 {
225     float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
226 greg 1.3 register int n; /* number of pixels in buffer */
227 greg 1.1 short buf_vh[MAXPIX]; /* pixel positions */
228     FVECT dir;
229     register int vh;
230    
231 greg 1.4 #ifdef DEBUG
232 greg 1.1 if (verbose)
233     fprintf(stderr, "%s: computing view span at %d...\n",
234     progname, vv);
235 greg 1.4 #endif
236 greg 1.3 n = 0;
237 greg 1.1 for (vh = -hsize; vh <= hsize; vh++) {
238 greg 1.14 if (compdir(dir, vh, vv) < 0) { /* not in view */
239 greg 1.1 vb[vh+hsize] = -1.0;
240     continue;
241     }
242 greg 1.7 npixinvw++;
243 greg 1.1 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
244     continue;
245 schorsch 2.7 if (rt_pd.r == -1) { /* missing information */
246 greg 1.7 npixmiss++;
247 greg 1.1 continue;
248 greg 1.7 }
249 greg 1.1 /* send to rtrace */
250 greg 1.19 if (n >= maxpix) { /* flush */
251 greg 1.3 rt_compute(rt_buf, n);
252 greg 2.14 while (n > 0) {
253     --n;
254 greg 1.3 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
255 greg 2.14 }
256 greg 1.1 }
257 greg 1.3 rt_buf[6*n] = ourview.vp[0];
258     rt_buf[6*n+1] = ourview.vp[1];
259     rt_buf[6*n+2] = ourview.vp[2];
260     rt_buf[6*n+3] = dir[0];
261     rt_buf[6*n+4] = dir[1];
262     rt_buf[6*n+5] = dir[2];
263     buf_vh[n++] = vh;
264 greg 1.1 }
265 greg 1.4 #ifdef DEBUG
266 greg 1.2 if (verbose)
267     pict_stats();
268 greg 1.4 #endif
269 greg 1.3 if (n > 0) { /* process pending buffer */
270     rt_compute(rt_buf, n);
271     while (n-- > 0)
272     vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
273     }
274 greg 1.1 }
275    
276    
277 schorsch 2.11 static void
278     rt_compute( /* process buffer through rtrace */
279     float *pb,
280     int np
281     )
282 greg 1.1 {
283 greg 1.4 #ifdef DEBUG
284 greg 1.1 if (verbose && np > 1)
285     fprintf(stderr, "%s: sending %d samples to rtrace...\n",
286     progname, np);
287 greg 1.4 #endif
288 schorsch 2.9 memset(pb+6*np, '\0', 6*sizeof(float));
289 schorsch 2.7 if (process(&rt_pd, (char *)pb, (char *)pb, 3*sizeof(float)*(np+1),
290 gregl 2.4 6*sizeof(float)*(np+1)) < 3*sizeof(float)*(np+1)) {
291 greg 1.19 fprintf(stderr, "%s: rtrace communication error\n",
292 greg 1.1 progname);
293     exit(1);
294     }
295     }
296    
297    
298 schorsch 2.11 static int
299     getexpos( /* get exposure from header line */
300     char *s,
301     void *p
302     )
303 greg 1.1 {
304 greg 1.13 char fmt[32];
305    
306 greg 1.1 if (isexpos(s))
307     exposure *= exposval(s);
308 greg 1.13 else if (isformat(s)) {
309     formatval(fmt, s);
310     wrongformat = strcmp(fmt, COLRFMT);
311     }
312 gwlarson 2.5 return(0);
313 greg 1.1 }
314    
315    
316 schorsch 2.11 extern void
317     open_pict( /* open picture file */
318     char *fn
319     )
320 greg 1.1 {
321     if ((pictfp = fopen(fn, "r")) == NULL) {
322 greg 2.3 fprintf(stderr, "%s: cannot open\n", fn);
323 greg 1.1 exit(1);
324     }
325 greg 2.13 SET_FILE_BINARY(pictfp);
326 greg 1.1 exposure = 1.0;
327 greg 1.13 getheader(pictfp, getexpos, NULL);
328 greg 1.21 if (wrongformat || !fscnresolu(&pxsiz, &pysiz, pictfp)) {
329     fprintf(stderr, "%s: incompatible picture format\n", fn);
330 greg 1.1 exit(1);
331     }
332 greg 1.8 initscans();
333 greg 1.1 }
334    
335    
336 schorsch 2.11 extern void
337     close_pict(void) /* done with picture */
338 greg 1.1 {
339     if (pictfp == NULL)
340     return;
341     fclose(pictfp);
342 greg 1.8 donescans();
343 greg 1.1 pictfp = NULL;
344     }
345    
346    
347 schorsch 2.11 extern void
348     fork_rtrace( /* open pipe and start rtrace */
349     char *av[]
350     )
351 greg 1.1 {
352 greg 1.19 int rval;
353 greg 1.1
354 schorsch 2.7 rval = open_process(&rt_pd, av);
355 greg 1.19 if (rval < 0) {
356 greg 1.1 perror(progname);
357     exit(1);
358     }
359 greg 1.19 if (rval == 0) {
360     fprintf(stderr, "%s: command not found\n", av[0]);
361 greg 1.1 exit(1);
362     }
363 greg 1.19 maxpix = rval/(6*sizeof(float));
364     if (maxpix > MAXPIX)
365     maxpix = MAXPIX;
366     maxpix--;
367 greg 1.1 }
368    
369    
370 schorsch 2.11 extern void
371     done_rtrace(void) /* wait for rtrace to finish */
372 greg 1.1 {
373 greg 1.19 int status;
374 greg 1.1
375 schorsch 2.7 status = close_process(&rt_pd);
376 greg 1.19 if (status > 0) {
377 greg 1.1 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
378     progname, status);
379     exit(1);
380     }
381 schorsch 2.7 rt_pd.r = -1;
382 greg 1.8 }
383    
384    
385 schorsch 2.11 static SCAN *
386     scanretire(void) /* retire old scanlines to free list */
387 greg 1.8 {
388     SCAN *sold[NRETIRE];
389     int n;
390     int h;
391     register SCAN *sl;
392     register int i;
393     /* grab the NRETIRE oldest scanlines */
394     sold[n = 0] = NULL;
395 greg 1.10 for (h = 0; h < HSIZE; h++)
396     for (sl = hashtab[h]; sl != NULL; sl = sl->next) {
397     for (i = n; i && sold[i-1]->lused > sl->lused; i--)
398     if (i < NRETIRE)
399 greg 1.8 sold[i] = sold[i-1];
400     if (i < NRETIRE) {
401 greg 1.10 sold[i] = sl;
402 greg 1.8 if (n < NRETIRE) /* grow list */
403     n++;
404 greg 1.10 }
405     }
406     /* put scanlines into free list */
407     for (i = 0; i < n; i++) {
408     h = shash(sold[i]->y);
409     sl = hashtab[h];
410     if (sl == sold[i])
411     hashtab[h] = sl->next;
412     else {
413     while (sl->next != sold[i]) /* IS in list */
414 greg 1.8 sl = sl->next;
415 greg 1.10 sl->next = sold[i]->next;
416 greg 1.8 }
417 greg 1.10 if (i > 0) { /* save oldest as return value */
418     sold[i]->next = freelist;
419     freelist = sold[i];
420     }
421 greg 1.8 }
422     return(sold[0]);
423     }
424    
425    
426     static char *scan_buf;
427    
428    
429 schorsch 2.11 static void
430     initscans(void) /* initialize scanline buffers */
431 greg 1.8 {
432     int scansize;
433     register SCAN *ptr;
434     register int i;
435     /* initialize positions */
436 greg 2.2 scanpos = (long *)bmalloc(pysiz*sizeof(long));
437 greg 1.8 if (scanpos == NULL)
438     memerr("scanline positions");
439     for (i = pysiz-1; i >= 0; i--)
440     scanpos[i] = -1L;
441     curpos = pysiz-1;
442     /* clear hash table */
443     for (i = 0; i < HSIZE; i++)
444     hashtab[i] = NULL;
445     /* allocate scanline buffers */
446     scansize = sizeof(SCAN) + pxsiz*sizeof(COLR);
447 greg 2.8 #ifdef ALIGNT
448     scansize = scansize+(sizeof(ALIGNT)-1) & ~(sizeof(ALIGNT)-1);
449 greg 1.8 #endif
450     i = MAXSBUF / scansize; /* compute number to allocate */
451     if (i > HSIZE)
452     i = HSIZE;
453 greg 2.2 scanbufsiz = i*scansize;
454     scan_buf = bmalloc(scanbufsiz); /* get in one big chunk */
455 greg 1.8 if (scan_buf == NULL)
456     memerr("scanline buffers");
457     ptr = (SCAN *)scan_buf;
458     freelist = NULL; /* build our free list */
459     while (i-- > 0) {
460     ptr->y = -1;
461     ptr->lused = -1;
462     ptr->next = freelist;
463     freelist = ptr;
464     ptr = (SCAN *)((char *)ptr + scansize); /* beware of C bugs */
465     }
466     }
467    
468    
469 schorsch 2.11 static void
470     donescans(void) /* free up scanlines */
471 greg 1.8 {
472 greg 2.2 bfree(scan_buf, scanbufsiz);
473     bfree((char *)scanpos, pysiz*sizeof(long));
474 greg 1.1 }