ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.9
Committed: Wed Apr 3 15:43:12 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.8: +7 -5 lines
Log Message:
fixed bug in scanretire and increased scanline buffer lims

File Contents

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