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.3 by greg, Tue Mar 19 17:06:27 1991 UTC vs.
Revision 2.5 by gwlarson, Tue Oct 27 08:47:18 1998 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines