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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: glareval.c,v 2.13 2010/12/02 18:08:11 greg Exp $";
3 #endif
4 /*
5 * Compute pixels for glare calculation
6 */
7
8 #include "copyright.h"
9
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "platform.h"
14 #include "rtprocess.h" /* Windows: must come first because of conflicts */
15 #include "glare.h"
16
17 /* maximum rtrace buffer size */
18 #define MAXPIX (4096/(6*sizeof(float)))
19
20 #define MAXSBUF 786432 /* maximum total size of scanline buffer */
21 #define HSIZE 317 /* size of scanline hash table */
22 #define NRETIRE 16 /* number of scanlines to retire at once */
23
24 static SUBPROC rt_pd = SP_INACTIVE; /* process id & descriptors for rtrace */
25
26 FILE *pictfp = NULL; /* picture file pointer */
27 double exposure; /* picture exposure */
28 int pxsiz, pysiz; /* picture dimensions */
29
30 static int curpos; /* current scanline */
31 static long *scanpos; /* scanline positions */
32
33 typedef struct scan {
34 int y; /* scanline position */
35 long lused; /* for LRU replacement */
36 struct scan *next; /* next in this hash or free list */
37 /* followed by the scanline data */
38 } SCAN; /* buffered scanline */
39
40 #define scandata(sl) ((COLR *)((sl)+1))
41 #define shash(y) ((y)%HSIZE)
42
43 static int maxpix; /* maximum number of pixels to buffer */
44
45 static SCAN *freelist; /* scanline free list */
46 static SCAN *hashtab[HSIZE]; /* scanline hash table */
47
48 static long scanbufsiz; /* size of allocated scanline buffer */
49
50 static long ncall = 0L; /* number of calls to getpictscan */
51 static long nread = 0L; /* number of scanlines read */
52 static long nrecl = 0L; /* number of scanlines reclaimed */
53
54 static int wrongformat = 0;
55
56 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
65
66 static SCAN *
67 claimscan( /* claim scanline from buffers */
68 int y
69 )
70 {
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 nrecl++;
88 }
89 return(sl);
90 }
91 return(scanretire()); /* need more free scanlines */
92 }
93
94
95 static COLR *
96 getpictscan( /* get picture scanline */
97 int y
98 )
99 {
100 register SCAN *sl;
101 register int i;
102 /* first check our buffers */
103 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 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 scanpos[curpos] = ftell(pictfp);
120 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
121 goto readerr;
122 nread++;
123 curpos--;
124 }
125 } else {
126 if (curpos != y && fseek(pictfp, scanpos[y], 0) < 0)
127 goto seekerr;
128 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
129 goto readerr;
130 nread++;
131 curpos = y-1;
132 }
133 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 readerr:
139 fprintf(stderr, "%s: picture read error\n", progname);
140 exit(1);
141 seekerr:
142 fprintf(stderr, "%s: picture seek error\n", progname);
143 exit(1);
144 }
145
146
147 #ifdef DEBUG
148 void
149 pict_stats(void) /* print out picture read statistics */
150 {
151 static long lastcall = 0L; /* ncall at last report */
152 static long lastread = 0L; /* nread at last report */
153 static long lastrecl = 0L; /* nrecl at last report */
154
155 if (ncall == lastcall)
156 return;
157 fprintf(stderr, "%s: %ld scanlines read (%ld reclaimed) in %ld calls\n",
158 progname, nread-lastread, nrecl-lastrecl, ncall-lastcall);
159 lastcall = ncall;
160 lastread = nread;
161 lastrecl = nrecl;
162 }
163 #endif
164
165
166 static double
167 pict_val( /* find picture value for view direction */
168 FVECT vd
169 )
170 {
171 FVECT pp;
172 FVECT ip;
173 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 viewloc(ip, &pictview, pp);
181 if (ip[2] <= FTINY || ip[0] < 0. || ip[0] >= 1. ||
182 ip[1] < 0. || ip[1] >= 1.)
183 return(-1.0);
184 colr_color(res, getpictscan((int)(ip[1]*pysiz))[(int)(ip[0]*pxsiz)]);
185 return(luminance(res)/exposure);
186 }
187
188
189 extern double
190 getviewpix( /* compute single view pixel */
191 int vh,
192 int vv
193 )
194 {
195 FVECT dir;
196 float rt_buf[12];
197 double res;
198
199 if (compdir(dir, vh, vv) < 0)
200 return(-1.0);
201 npixinvw++;
202 if ((res = pict_val(dir)) >= 0.0)
203 return(res);
204 if (rt_pd.r == -1) {
205 npixmiss++;
206 return(-1.0);
207 }
208 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 extern void
220 getviewspan( /* compute a span of view pixels */
221 int vv,
222 float *vb
223 )
224 {
225 float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
226 register int n; /* number of pixels in buffer */
227 short buf_vh[MAXPIX]; /* pixel positions */
228 FVECT dir;
229 register int vh;
230
231 #ifdef DEBUG
232 if (verbose)
233 fprintf(stderr, "%s: computing view span at %d...\n",
234 progname, vv);
235 #endif
236 n = 0;
237 for (vh = -hsize; vh <= hsize; vh++) {
238 if (compdir(dir, vh, vv) < 0) { /* not in view */
239 vb[vh+hsize] = -1.0;
240 continue;
241 }
242 npixinvw++;
243 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
244 continue;
245 if (rt_pd.r == -1) { /* missing information */
246 npixmiss++;
247 continue;
248 }
249 /* send to rtrace */
250 if (n >= maxpix) { /* flush */
251 rt_compute(rt_buf, n);
252 while (n > 0) {
253 --n;
254 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
255 }
256 }
257 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 }
265 #ifdef DEBUG
266 if (verbose)
267 pict_stats();
268 #endif
269 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 }
275
276
277 static void
278 rt_compute( /* process buffer through rtrace */
279 float *pb,
280 int np
281 )
282 {
283 #ifdef DEBUG
284 if (verbose && np > 1)
285 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
286 progname, np);
287 #endif
288 memset(pb+6*np, '\0', 6*sizeof(float));
289 if (process(&rt_pd, (char *)pb, (char *)pb, 3*sizeof(float)*(np+1),
290 6*sizeof(float)*(np+1)) < 3*sizeof(float)*(np+1)) {
291 fprintf(stderr, "%s: rtrace communication error\n",
292 progname);
293 exit(1);
294 }
295 }
296
297
298 static int
299 getexpos( /* get exposure from header line */
300 char *s,
301 void *p
302 )
303 {
304 char fmt[32];
305
306 if (isexpos(s))
307 exposure *= exposval(s);
308 else if (isformat(s)) {
309 formatval(fmt, s);
310 wrongformat = strcmp(fmt, COLRFMT);
311 }
312 return(0);
313 }
314
315
316 extern void
317 open_pict( /* open picture file */
318 char *fn
319 )
320 {
321 if ((pictfp = fopen(fn, "r")) == NULL) {
322 fprintf(stderr, "%s: cannot open\n", fn);
323 exit(1);
324 }
325 SET_FILE_BINARY(pictfp);
326 exposure = 1.0;
327 getheader(pictfp, getexpos, NULL);
328 if (wrongformat || !fscnresolu(&pxsiz, &pysiz, pictfp)) {
329 fprintf(stderr, "%s: incompatible picture format\n", fn);
330 exit(1);
331 }
332 initscans();
333 }
334
335
336 extern void
337 close_pict(void) /* done with picture */
338 {
339 if (pictfp == NULL)
340 return;
341 fclose(pictfp);
342 donescans();
343 pictfp = NULL;
344 }
345
346
347 extern void
348 fork_rtrace( /* open pipe and start rtrace */
349 char *av[]
350 )
351 {
352 int rval;
353
354 rval = open_process(&rt_pd, av);
355 if (rval < 0) {
356 perror(progname);
357 exit(1);
358 }
359 if (rval == 0) {
360 fprintf(stderr, "%s: command not found\n", av[0]);
361 exit(1);
362 }
363 maxpix = rval/(6*sizeof(float));
364 if (maxpix > MAXPIX)
365 maxpix = MAXPIX;
366 maxpix--;
367 }
368
369
370 extern void
371 done_rtrace(void) /* wait for rtrace to finish */
372 {
373 int status;
374
375 status = close_process(&rt_pd);
376 if (status > 0) {
377 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
378 progname, status);
379 exit(1);
380 }
381 rt_pd.r = -1;
382 }
383
384
385 static SCAN *
386 scanretire(void) /* retire old scanlines to free list */
387 {
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 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 sold[i] = sold[i-1];
400 if (i < NRETIRE) {
401 sold[i] = sl;
402 if (n < NRETIRE) /* grow list */
403 n++;
404 }
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 sl = sl->next;
415 sl->next = sold[i]->next;
416 }
417 if (i > 0) { /* save oldest as return value */
418 sold[i]->next = freelist;
419 freelist = sold[i];
420 }
421 }
422 return(sold[0]);
423 }
424
425
426 static char *scan_buf;
427
428
429 static void
430 initscans(void) /* initialize scanline buffers */
431 {
432 int scansize;
433 register SCAN *ptr;
434 register int i;
435 /* initialize positions */
436 scanpos = (long *)bmalloc(pysiz*sizeof(long));
437 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 #ifdef ALIGNT
448 scansize = scansize+(sizeof(ALIGNT)-1) & ~(sizeof(ALIGNT)-1);
449 #endif
450 i = MAXSBUF / scansize; /* compute number to allocate */
451 if (i > HSIZE)
452 i = HSIZE;
453 scanbufsiz = i*scansize;
454 scan_buf = bmalloc(scanbufsiz); /* get in one big chunk */
455 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 static void
470 donescans(void) /* free up scanlines */
471 {
472 bfree(scan_buf, scanbufsiz);
473 bfree((char *)scanpos, pysiz*sizeof(long));
474 }