ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.15
Committed: Mon Apr 22 15:41:01 1991 UTC (32 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.14: +6 -8 lines
Log Message:
changed reporting of scanline reclamation

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