ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
(Generate patch)

Comparing ray/src/util/glareval.c (file contents):
Revision 1.2 by greg, Mon Mar 18 14:33:53 1991 UTC vs.
Revision 2.10 by schorsch, Thu Jul 3 22:41:45 2003 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines