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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines