ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.8
Committed: Wed Apr 3 15:20:35 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +157 -40 lines
Log Message:
added rather sophisticated LRU scanline replacement scheme

File Contents

# Content
1 /* Copyright (c) 1991 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * Compute pixels for glare calculation
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)
18
19 #ifndef BSD
20 #define vfork fork
21 #endif
22
23 #define MAXSBUF 409580 /* maximum total size of scanline buffer */
24 #define HSIZE 227 /* size of scanline hash table */
25 #define NRETIRE 16 /* number of scanlines to retire at once */
26
27 int rt_pid = -1; /* process id for rtrace */
28 int fd_tort, fd_fromrt; /* pipe descriptors */
29
30 FILE *pictfp = NULL; /* picture file pointer */
31 double exposure; /* picture exposure */
32 int pxsiz, pysiz; /* picture dimensions */
33
34 static int curpos; /* current scanline */
35 static long *scanpos; /* scanline positions */
36
37 typedef struct scan {
38 int y; /* scanline position */
39 long lused; /* for LRU replacement */
40 struct scan *next; /* next in this hash or free list */
41 /* followed by the scanline data */
42 } SCAN; /* buffered scanline */
43
44 #define scandata(sl) ((COLR *)((sl)+1))
45 #define shash(y) ((y)%HSIZE)
46
47 static SCAN *freelist; /* scanline free list */
48 static SCAN *hashtab[HSIZE]; /* scanline hash table */
49
50 static long ncall = 0L; /* number of calls to getpictscan */
51 static long nread = 0L; /* number of scanlines read */
52
53 SCAN *scanretire();
54
55 extern long ftell();
56
57
58 SCAN *
59 claimscan(y) /* claim scanline from buffers */
60 int y;
61 {
62 int hi = shash(y);
63 SCAN *slast;
64 register SCAN *sl;
65
66 for (sl = hashtab[hi]; sl != NULL; sl = sl->next)
67 if (sl->y == y) /* active scanline */
68 return(sl);
69 for (slast = NULL, sl = freelist; sl != NULL; slast = sl, sl = sl->next)
70 if (sl->y == -1 || sl->y == y || sl->next == NULL) {
71 if (slast == NULL) /* remove from free */
72 freelist = sl->next;
73 else
74 slast->next = sl->next;
75 if (sl->y == y) { /* reclaim */
76 sl->next = hashtab[hi];
77 hashtab[hi] = sl;
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 register SCAN *sl;
90 register int i;
91 /* first check our buffers */
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(scandata(sl), pxsiz, pictfp) < 0)
110 goto readerr;
111 nread++;
112 curpos--;
113 }
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 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
142 if (ncall == lastcall)
143 return;
144 fprintf(stderr, "%s: %ld scanlines read in %ld calls\n",
145 progname, nread-lastread, ncall-lastcall);
146 lastcall = ncall;
147 lastread = nread;
148 }
149 #endif
150
151
152 double
153 pict_val(vd) /* find picture value for view direction */
154 FVECT vd;
155 {
156 FVECT pp;
157 double vpx, vpy, vpz;
158 COLOR res;
159
160 if (pictfp == NULL)
161 return(-1.0);
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.)
167 return(-1.0);
168 colr_color(res, getpictscan((int)(vpy*pysiz))[(int)(vpx*pxsiz)]);
169 return(luminance(res)/exposure);
170 }
171
172
173 double
174 getviewpix(vh, vv) /* compute single view pixel */
175 int vh, vv;
176 {
177 FVECT dir;
178 float rt_buf[6];
179 double res;
180
181 if (compdir(dir, vh, vv) < 0)
182 return(-1.0);
183 npixinvw++;
184 if ((res = pict_val(dir)) >= 0.0)
185 return(res);
186 if (rt_pid == -1) {
187 npixmiss++;
188 return(-1.0);
189 }
190 rt_buf[0] = ourview.vp[0];
191 rt_buf[1] = ourview.vp[1];
192 rt_buf[2] = ourview.vp[2];
193 rt_buf[3] = dir[0];
194 rt_buf[4] = dir[1];
195 rt_buf[5] = dir[2];
196 rt_compute(rt_buf, 1);
197 return(luminance(rt_buf));
198 }
199
200
201 getviewspan(vv, vb) /* compute a span of view pixels */
202 int vv;
203 float *vb;
204 {
205 float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
206 register int n; /* number of pixels in buffer */
207 short buf_vh[MAXPIX]; /* pixel positions */
208 FVECT dir;
209 register int vh;
210
211 #ifdef DEBUG
212 if (verbose)
213 fprintf(stderr, "%s: computing view span at %d...\n",
214 progname, vv);
215 #endif
216 n = 0;
217 for (vh = -hsize; vh <= hsize; vh++) {
218 if (compdir(dir, vh, vv) < 0) { /* off viewable region */
219 vb[vh+hsize] = -1.0;
220 continue;
221 }
222 npixinvw++;
223 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
224 continue;
225 if (rt_pid == -1) { /* missing information */
226 npixmiss++;
227 continue;
228 }
229 /* send to rtrace */
230 if (n >= MAXPIX) { /* flush */
231 rt_compute(rt_buf, n);
232 while (n-- > 0)
233 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
234 }
235 rt_buf[6*n] = ourview.vp[0];
236 rt_buf[6*n+1] = ourview.vp[1];
237 rt_buf[6*n+2] = ourview.vp[2];
238 rt_buf[6*n+3] = dir[0];
239 rt_buf[6*n+4] = dir[1];
240 rt_buf[6*n+5] = dir[2];
241 buf_vh[n++] = vh;
242 }
243 #ifdef DEBUG
244 if (verbose)
245 pict_stats();
246 #endif
247 if (n > 0) { /* process pending buffer */
248 rt_compute(rt_buf, n);
249 while (n-- > 0)
250 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
251 }
252 }
253
254
255 rt_compute(pb, np) /* process buffer through rtrace */
256 float *pb;
257 int np;
258 {
259 static float nbuf[6] = {0.,0.,0.,0.,0.,0.};
260
261 #ifdef DEBUG
262 if (verbose && np > 1)
263 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
264 progname, np);
265 #endif
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",
269 progname);
270 exit(1);
271 }
272 if (readbuf(fd_fromrt, (char *)pb, 3*sizeof(float)*np)
273 < 3*sizeof(float)*np) {
274 fprintf(stderr, "%s: error reading from rtrace process\n",
275 progname);
276 exit(1);
277 }
278 }
279
280
281 getexpos(s) /* get exposure from header line */
282 char *s;
283 {
284 if (isexpos(s))
285 exposure *= exposval(s);
286 }
287
288
289 open_pict(fn) /* open picture file */
290 char *fn;
291 {
292 register int i;
293
294 if ((pictfp = fopen(fn, "r")) == NULL) {
295 fprintf("%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);
302 exit(1);
303 }
304 initscans();
305 }
306
307
308 close_pict() /* done with picture */
309 {
310 register int i;
311
312 if (pictfp == NULL)
313 return;
314 fclose(pictfp);
315 donescans();
316 pictfp = NULL;
317 }
318
319
320 fork_rtrace(av) /* open pipe and start rtrace */
321 char *av[];
322 {
323 int p0[2], p1[2];
324
325 if (pipe(p0) < 0 || pipe(p1) < 0) {
326 perror(progname);
327 exit(1);
328 }
329 if ((rt_pid = vfork()) == 0) { /* if child */
330 close(p0[1]);
331 close(p1[0]);
332 if (p0[0] != 0) { /* connect p0 to stdin */
333 dup2(p0[0], 0);
334 close(p0[0]);
335 }
336 if (p1[1] != 0) { /* connect p1 to stdout */
337 dup2(p1[1], 1);
338 close(p1[1]);
339 }
340 execvp(av[0], av);
341 perror(av[0]);
342 _exit(127);
343 }
344 if (rt_pid == -1) {
345 perror(progname);
346 exit(1);
347 }
348 close(p0[0]);
349 close(p1[1]);
350 fd_tort = p0[1];
351 fd_fromrt = p1[0];
352 }
353
354
355 done_rtrace() /* wait for rtrace to finish */
356 {
357 int pid, status;
358
359 if (rt_pid == -1)
360 return;
361 close(fd_tort);
362 close(fd_fromrt);
363 while ((pid = wait(&status)) != -1 && pid != rt_pid)
364 ;
365 if (pid == rt_pid && status != 0) {
366 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
367 progname, status);
368 exit(1);
369 }
370 rt_pid = -1;
371 }
372
373
374 int
375 readbuf(fd, bpos, siz)
376 int fd;
377 char *bpos;
378 int siz;
379 {
380 register int cc, nrem = siz;
381
382 while (nrem > 0 && (cc = read(fd, bpos, nrem)) > 0) {
383 bpos += cc;
384 nrem -= cc;
385 }
386 if (cc < 0)
387 return(cc);
388 return(siz-nrem);
389 }
390
391
392 int
393 writebuf(fd, bpos, siz)
394 char *bpos;
395 int siz;
396 {
397 register int cc, nrem = siz;
398
399 while (nrem > 0 && (cc = write(fd, bpos, nrem)) > 0) {
400 bpos += cc;
401 nrem -= cc;
402 }
403 if (cc < 0)
404 return(cc);
405 return(siz-nrem);
406 }
407
408
409 SCAN *
410 scanretire() /* retire old scanlines to free list */
411 {
412 SCAN *sold[NRETIRE];
413 SCAN head;
414 int n;
415 int h;
416 register SCAN *sl;
417 register int i;
418 /* grab the NRETIRE oldest scanlines */
419 sold[n = 0] = NULL;
420 for (h = 0; h < HSIZE; h++) {
421 head.next = hashtab[h];
422 sl = &head;
423 while (sl->next != NULL) {
424 for (i = n; i && sold[i-1]->lused > sl->next->lused; i--)
425 if (i == NRETIRE) { /* reallocate */
426 register int oh;
427 oh = shash(sold[NRETIRE-1]->y);
428 sold[NRETIRE-1]->next = hashtab[oh];
429 if (h == oh && sl == &head)
430 head.next = sl = sold[NRETIRE-1];
431 else
432 hashtab[oh] = sold[NRETIRE-1];
433 } else /* else bubble up */
434 sold[i] = sold[i-1];
435 if (i < NRETIRE) {
436 sold[i] = sl->next;
437 sl->next = sl->next->next;
438 if (n < NRETIRE) /* grow list */
439 n++;
440 } else
441 sl = sl->next;
442 }
443 hashtab[h] = head.next;
444 }
445 /* put scanlines into free list */
446 for (i = 1; i < n; i++) {
447 sold[i]->next = freelist;
448 freelist = sold[i];
449 }
450 return(sold[0]);
451 }
452
453
454 static char *scan_buf;
455
456
457 initscans() /* initialize scanline buffers */
458 {
459 int scansize;
460 register SCAN *ptr;
461 register int i;
462 /* initialize positions */
463 scanpos = (long *)malloc(pysiz*sizeof(long));
464 if (scanpos == NULL)
465 memerr("scanline positions");
466 for (i = pysiz-1; i >= 0; i--)
467 scanpos[i] = -1L;
468 curpos = pysiz-1;
469 /* clear hash table */
470 for (i = 0; i < HSIZE; i++)
471 hashtab[i] = NULL;
472 /* allocate scanline buffers */
473 scansize = sizeof(SCAN) + pxsiz*sizeof(COLR);
474 #ifdef ALIGN
475 scansize = scansize+(sizeof(ALIGN)-1)) & ~(sizeof(ALIGN)-1);
476 #endif
477 i = MAXSBUF / scansize; /* compute number to allocate */
478 if (i > HSIZE)
479 i = HSIZE;
480 scan_buf = malloc(i*scansize); /* get in one big chunk */
481 if (scan_buf == NULL)
482 memerr("scanline buffers");
483 ptr = (SCAN *)scan_buf;
484 freelist = NULL; /* build our free list */
485 while (i-- > 0) {
486 ptr->y = -1;
487 ptr->lused = -1;
488 ptr->next = freelist;
489 freelist = ptr;
490 ptr = (SCAN *)((char *)ptr + scansize); /* beware of C bugs */
491 }
492 }
493
494
495 donescans() /* free up scanlines */
496 {
497 free(scan_buf);
498 free((char *)scanpos);
499 }