ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 1.11
Committed: Fri Apr 5 14:57:28 1991 UTC (33 years ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.10: +7 -1 lines
Log Message:
reduced scanline buffer size and added debugging output for reclaims

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 524268 /* maximum total size of scanline buffer */
24 #define HSIZE 317 /* 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 #ifdef DEBUG
79 if (verbose)
80 fprintf(stderr,
81 "%s: scanline %d reclaimed\n",
82 progname, y);
83 #endif
84 }
85 return(sl);
86 }
87 return(scanretire()); /* need more free scanlines */
88 }
89
90
91 COLR *
92 getpictscan(y) /* get picture scanline */
93 int y;
94 {
95 register SCAN *sl;
96 register int i;
97 /* first check our buffers */
98 sl = claimscan(y);
99 if (sl == NULL)
100 memerr("claimscan()");
101 sl->lused = ncall++;
102 if (sl->y == y) /* scan hit */
103 return(scandata(sl));
104 /* else read in replacement */
105 if (scanpos[y] < 0) { /* need to search */
106 for (i = y+1; i < curpos; i++)
107 if (scanpos[i] >= 0) {
108 if (fseek(pictfp, scanpos[i], 0) < 0)
109 goto seekerr;
110 curpos = i;
111 break;
112 }
113 while (curpos >= y) {
114 scanpos[curpos] = ftell(pictfp);
115 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
116 goto readerr;
117 nread++;
118 curpos--;
119 }
120 } else {
121 if (curpos != y && fseek(pictfp, scanpos[y], 0) < 0)
122 goto seekerr;
123 if (freadcolrs(scandata(sl), pxsiz, pictfp) < 0)
124 goto readerr;
125 nread++;
126 curpos = y-1;
127 }
128 sl->y = y;
129 i = shash(y); /* add to hash list */
130 sl->next = hashtab[i];
131 hashtab[i] = sl;
132 return(scandata(sl));
133 readerr:
134 fprintf(stderr, "%s: picture read error\n", progname);
135 exit(1);
136 seekerr:
137 fprintf(stderr, "%s: picture seek error\n", progname);
138 exit(1);
139 }
140
141
142 #ifdef DEBUG
143 pict_stats() /* print out picture read statistics */
144 {
145 static long lastcall = 0L; /* ncall at last report */
146 static long lastread = 0L; /* nread at last report */
147
148 if (ncall == lastcall)
149 return;
150 fprintf(stderr, "%s: %ld scanlines read in %ld calls\n",
151 progname, nread-lastread, ncall-lastcall);
152 lastcall = ncall;
153 lastread = nread;
154 }
155 #endif
156
157
158 double
159 pict_val(vd) /* find picture value for view direction */
160 FVECT vd;
161 {
162 FVECT pp;
163 double vpx, vpy, vpz;
164 COLOR res;
165
166 if (pictfp == NULL)
167 return(-1.0);
168 pp[0] = pictview.vp[0] + vd[0];
169 pp[1] = pictview.vp[1] + vd[1];
170 pp[2] = pictview.vp[2] + vd[2];
171 viewpixel(&vpx, &vpy, &vpz, &pictview, pp);
172 if (vpz <= FTINY || vpx < 0. || vpx >= 1. || vpy < 0. || vpy >= 1.)
173 return(-1.0);
174 colr_color(res, getpictscan((int)(vpy*pysiz))[(int)(vpx*pxsiz)]);
175 return(luminance(res)/exposure);
176 }
177
178
179 double
180 getviewpix(vh, vv) /* compute single view pixel */
181 int vh, vv;
182 {
183 FVECT dir;
184 float rt_buf[6];
185 double res;
186
187 if (compdir(dir, vh, vv) < 0)
188 return(-1.0);
189 npixinvw++;
190 if ((res = pict_val(dir)) >= 0.0)
191 return(res);
192 if (rt_pid == -1) {
193 npixmiss++;
194 return(-1.0);
195 }
196 rt_buf[0] = ourview.vp[0];
197 rt_buf[1] = ourview.vp[1];
198 rt_buf[2] = ourview.vp[2];
199 rt_buf[3] = dir[0];
200 rt_buf[4] = dir[1];
201 rt_buf[5] = dir[2];
202 rt_compute(rt_buf, 1);
203 return(luminance(rt_buf));
204 }
205
206
207 getviewspan(vv, vb) /* compute a span of view pixels */
208 int vv;
209 float *vb;
210 {
211 float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
212 register int n; /* number of pixels in buffer */
213 short buf_vh[MAXPIX]; /* pixel positions */
214 FVECT dir;
215 register int vh;
216
217 #ifdef DEBUG
218 if (verbose)
219 fprintf(stderr, "%s: computing view span at %d...\n",
220 progname, vv);
221 #endif
222 n = 0;
223 for (vh = -hsize; vh <= hsize; vh++) {
224 if (compdir(dir, vh, vv) < 0) { /* off viewable region */
225 vb[vh+hsize] = -1.0;
226 continue;
227 }
228 npixinvw++;
229 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
230 continue;
231 if (rt_pid == -1) { /* missing information */
232 npixmiss++;
233 continue;
234 }
235 /* send to rtrace */
236 if (n >= MAXPIX) { /* flush */
237 rt_compute(rt_buf, n);
238 while (n-- > 0)
239 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
240 }
241 rt_buf[6*n] = ourview.vp[0];
242 rt_buf[6*n+1] = ourview.vp[1];
243 rt_buf[6*n+2] = ourview.vp[2];
244 rt_buf[6*n+3] = dir[0];
245 rt_buf[6*n+4] = dir[1];
246 rt_buf[6*n+5] = dir[2];
247 buf_vh[n++] = vh;
248 }
249 #ifdef DEBUG
250 if (verbose)
251 pict_stats();
252 #endif
253 if (n > 0) { /* process pending buffer */
254 rt_compute(rt_buf, n);
255 while (n-- > 0)
256 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
257 }
258 }
259
260
261 rt_compute(pb, np) /* process buffer through rtrace */
262 float *pb;
263 int np;
264 {
265 static float nbuf[6] = {0.,0.,0.,0.,0.,0.};
266
267 #ifdef DEBUG
268 if (verbose && np > 1)
269 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
270 progname, np);
271 #endif
272 if (writebuf(fd_tort,(char *)pb,6*sizeof(float)*np) < 6*sizeof(float)*np
273 || writebuf(fd_tort,(char *)nbuf,sizeof(nbuf)) < sizeof(nbuf)) {
274 fprintf(stderr, "%s: error writing to rtrace process\n",
275 progname);
276 exit(1);
277 }
278 if (readbuf(fd_fromrt, (char *)pb, 3*sizeof(float)*np)
279 < 3*sizeof(float)*np) {
280 fprintf(stderr, "%s: error reading from rtrace process\n",
281 progname);
282 exit(1);
283 }
284 }
285
286
287 getexpos(s) /* get exposure from header line */
288 char *s;
289 {
290 if (isexpos(s))
291 exposure *= exposval(s);
292 }
293
294
295 open_pict(fn) /* open picture file */
296 char *fn;
297 {
298 register int i;
299
300 if ((pictfp = fopen(fn, "r")) == NULL) {
301 fprintf("%s: cannot open\n", fn);
302 exit(1);
303 }
304 exposure = 1.0;
305 getheader(pictfp, getexpos);
306 if (fgetresolu(&pxsiz, &pysiz, pictfp) != (YMAJOR|YDECR)) {
307 fprintf("%s: bad picture resolution\n", fn);
308 exit(1);
309 }
310 initscans();
311 }
312
313
314 close_pict() /* done with picture */
315 {
316 register int i;
317
318 if (pictfp == NULL)
319 return;
320 fclose(pictfp);
321 donescans();
322 pictfp = NULL;
323 }
324
325
326 fork_rtrace(av) /* open pipe and start rtrace */
327 char *av[];
328 {
329 int p0[2], p1[2];
330
331 if (pipe(p0) < 0 || pipe(p1) < 0) {
332 perror(progname);
333 exit(1);
334 }
335 if ((rt_pid = vfork()) == 0) { /* if child */
336 close(p0[1]);
337 close(p1[0]);
338 if (p0[0] != 0) { /* connect p0 to stdin */
339 dup2(p0[0], 0);
340 close(p0[0]);
341 }
342 if (p1[1] != 0) { /* connect p1 to stdout */
343 dup2(p1[1], 1);
344 close(p1[1]);
345 }
346 execvp(av[0], av);
347 perror(av[0]);
348 _exit(127);
349 }
350 if (rt_pid == -1) {
351 perror(progname);
352 exit(1);
353 }
354 close(p0[0]);
355 close(p1[1]);
356 fd_tort = p0[1];
357 fd_fromrt = p1[0];
358 }
359
360
361 done_rtrace() /* wait for rtrace to finish */
362 {
363 int pid, status;
364
365 if (rt_pid == -1)
366 return;
367 close(fd_tort);
368 close(fd_fromrt);
369 while ((pid = wait(&status)) != -1 && pid != rt_pid)
370 ;
371 if (pid == rt_pid && status != 0) {
372 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
373 progname, status);
374 exit(1);
375 }
376 rt_pid = -1;
377 }
378
379
380 int
381 readbuf(fd, bpos, siz)
382 int fd;
383 char *bpos;
384 int siz;
385 {
386 register int cc, nrem = siz;
387
388 while (nrem > 0 && (cc = read(fd, bpos, nrem)) > 0) {
389 bpos += cc;
390 nrem -= cc;
391 }
392 if (cc < 0)
393 return(cc);
394 return(siz-nrem);
395 }
396
397
398 int
399 writebuf(fd, bpos, siz)
400 char *bpos;
401 int siz;
402 {
403 register int cc, nrem = siz;
404
405 while (nrem > 0 && (cc = write(fd, bpos, nrem)) > 0) {
406 bpos += cc;
407 nrem -= cc;
408 }
409 if (cc < 0)
410 return(cc);
411 return(siz-nrem);
412 }
413
414
415 SCAN *
416 scanretire() /* retire old scanlines to free list */
417 {
418 SCAN *sold[NRETIRE];
419 int n;
420 int h;
421 register SCAN *sl;
422 register int i;
423 /* grab the NRETIRE oldest scanlines */
424 sold[n = 0] = NULL;
425 for (h = 0; h < HSIZE; h++)
426 for (sl = hashtab[h]; sl != NULL; sl = sl->next) {
427 for (i = n; i && sold[i-1]->lused > sl->lused; i--)
428 if (i < NRETIRE)
429 sold[i] = sold[i-1];
430 if (i < NRETIRE) {
431 sold[i] = sl;
432 if (n < NRETIRE) /* grow list */
433 n++;
434 }
435 }
436 /* put scanlines into free list */
437 for (i = 0; i < n; i++) {
438 h = shash(sold[i]->y);
439 sl = hashtab[h];
440 if (sl == sold[i])
441 hashtab[h] = sl->next;
442 else {
443 while (sl->next != sold[i]) /* IS in list */
444 sl = sl->next;
445 sl->next = sold[i]->next;
446 }
447 if (i > 0) { /* save oldest as return value */
448 sold[i]->next = freelist;
449 freelist = sold[i];
450 }
451 }
452 return(sold[0]);
453 }
454
455
456 static char *scan_buf;
457
458
459 initscans() /* initialize scanline buffers */
460 {
461 int scansize;
462 register SCAN *ptr;
463 register int i;
464 /* initialize positions */
465 scanpos = (long *)malloc(pysiz*sizeof(long));
466 if (scanpos == NULL)
467 memerr("scanline positions");
468 for (i = pysiz-1; i >= 0; i--)
469 scanpos[i] = -1L;
470 curpos = pysiz-1;
471 /* clear hash table */
472 for (i = 0; i < HSIZE; i++)
473 hashtab[i] = NULL;
474 /* allocate scanline buffers */
475 scansize = sizeof(SCAN) + pxsiz*sizeof(COLR);
476 #ifdef ALIGN
477 scansize = scansize+(sizeof(ALIGN)-1)) & ~(sizeof(ALIGN)-1);
478 #endif
479 i = MAXSBUF / scansize; /* compute number to allocate */
480 if (i > HSIZE)
481 i = HSIZE;
482 scan_buf = malloc(i*scansize); /* get in one big chunk */
483 if (scan_buf == NULL)
484 memerr("scanline buffers");
485 ptr = (SCAN *)scan_buf;
486 freelist = NULL; /* build our free list */
487 while (i-- > 0) {
488 ptr->y = -1;
489 ptr->lused = -1;
490 ptr->next = freelist;
491 freelist = ptr;
492 ptr = (SCAN *)((char *)ptr + scansize); /* beware of C bugs */
493 }
494 }
495
496
497 donescans() /* free up scanlines */
498 {
499 free(scan_buf);
500 free((char *)scanpos);
501 }