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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines