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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines