ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/glareval.c
Revision: 2.18
Committed: Thu May 14 20:58:03 2020 UTC (2 years, 4 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R3, HEAD
Changes since 2.17: +2 -2 lines
Log Message:
Fixed return-value checking for viewloc()

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: glareval.c,v 2.17 2020/02/28 05:18:49 greg Exp $";
3 #endif
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"
16
17 /* maximum rtrace buffer size */
18 #define MAXPIX (4096/(6*sizeof(float)))
19
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 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
30 static int curpos; /* current scanline */
31 static long *scanpos; /* scanline positions */
32
33 typedef struct scan {
34 int y; /* scanline position */
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 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 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 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(scandata(sl), pxsiz, pictfp) < 0)
121 goto readerr;
122 nread++;
123 curpos--;
124 }
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 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 #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 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 static double
167 pict_val( /* find picture value for view direction */
168 FVECT vd
169 )
170 {
171 FVECT pp;
172 FVECT ip;
173 COLOR res;
174
175 if (pictfp == NULL)
176 return(-1.0);
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 if (viewloc(ip, &pictview, pp) != VL_GOOD)
181 return(-1.0);
182 colr_color(res, getpictscan((int)(ip[1]*pysiz))[(int)(ip[0]*pxsiz)]);
183 return(luminance(res)/exposure);
184 }
185
186
187 extern double
188 getviewpix( /* compute single view pixel */
189 int vh,
190 int vv
191 )
192 {
193 FVECT dir;
194 float rt_buf[12];
195 double res;
196
197 if (compdir(dir, vh, vv) < 0)
198 return(-1.0);
199 npixinvw++;
200 if ((res = pict_val(dir)) >= 0.0)
201 return(res);
202 if (!(rt_pd.flags & PF_RUNNING)) {
203 npixmiss++;
204 return(-1.0);
205 }
206 rt_buf[0] = ourview.vp[0];
207 rt_buf[1] = ourview.vp[1];
208 rt_buf[2] = ourview.vp[2];
209 rt_buf[3] = dir[0];
210 rt_buf[4] = dir[1];
211 rt_buf[5] = dir[2];
212 rt_compute(rt_buf, 1);
213 return(luminance(rt_buf));
214 }
215
216
217 extern void
218 getviewspan( /* compute a span of view pixels */
219 int vv,
220 float *vb
221 )
222 {
223 float rt_buf[6*MAXPIX]; /* rtrace send/receive buffer */
224 register int n; /* number of pixels in buffer */
225 short buf_vh[MAXPIX]; /* pixel positions */
226 FVECT dir;
227 register int vh;
228
229 #ifdef DEBUG
230 if (verbose)
231 fprintf(stderr, "%s: computing view span at %d...\n",
232 progname, vv);
233 #endif
234 n = 0;
235 for (vh = -hsize; vh <= hsize; vh++) {
236 if (compdir(dir, vh, vv) < 0) { /* not in view */
237 vb[vh+hsize] = -1.0;
238 continue;
239 }
240 npixinvw++;
241 if ((vb[vh+hsize] = pict_val(dir)) >= 0.0)
242 continue;
243 if (!(rt_pd.flags & PF_RUNNING)) { /* missing information */
244 npixmiss++;
245 continue;
246 }
247 /* send to rtrace */
248 if (n >= maxpix) { /* flush */
249 rt_compute(rt_buf, n);
250 while (n > 0) {
251 --n;
252 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
253 }
254 }
255 rt_buf[6*n] = ourview.vp[0];
256 rt_buf[6*n+1] = ourview.vp[1];
257 rt_buf[6*n+2] = ourview.vp[2];
258 rt_buf[6*n+3] = dir[0];
259 rt_buf[6*n+4] = dir[1];
260 rt_buf[6*n+5] = dir[2];
261 buf_vh[n++] = vh;
262 }
263 #ifdef DEBUG
264 if (verbose)
265 pict_stats();
266 #endif
267 if (n > 0) { /* process pending buffer */
268 rt_compute(rt_buf, n);
269 while (n-- > 0)
270 vb[buf_vh[n]+hsize] = luminance(rt_buf+3*n);
271 }
272 }
273
274
275 static void
276 rt_compute( /* process buffer through rtrace */
277 float *pb,
278 int np
279 )
280 {
281 #ifdef DEBUG
282 if (verbose && np > 1)
283 fprintf(stderr, "%s: sending %d samples to rtrace...\n",
284 progname, np);
285 #endif
286 memset(pb+6*np, '\0', 6*sizeof(float));
287 if (process(&rt_pd, (char *)pb, (char *)pb, 3*sizeof(float)*(np+1),
288 6*sizeof(float)*(np+1)) < 3*sizeof(float)*(np+1)) {
289 fprintf(stderr, "%s: rtrace communication error\n",
290 progname);
291 exit(1);
292 }
293 }
294
295
296 static int
297 getexpos( /* get exposure from header line */
298 char *s,
299 void *p
300 )
301 {
302 char fmt[MAXFMTLEN];
303
304 if (isexpos(s))
305 exposure *= exposval(s);
306 else if (isformat(s)) {
307 formatval(fmt, s);
308 wrongformat = strcmp(fmt, COLRFMT);
309 }
310 return(0);
311 }
312
313
314 extern void
315 open_pict( /* open picture file */
316 char *fn
317 )
318 {
319 if ((pictfp = fopen(fn, "r")) == NULL) {
320 fprintf(stderr, "%s: cannot open\n", fn);
321 exit(1);
322 }
323 SET_FILE_BINARY(pictfp);
324 exposure = 1.0;
325 getheader(pictfp, getexpos, NULL);
326 if (wrongformat || !fscnresolu(&pxsiz, &pysiz, pictfp)) {
327 fprintf(stderr, "%s: incompatible picture format\n", fn);
328 exit(1);
329 }
330 initscans();
331 }
332
333
334 extern void
335 close_pict(void) /* done with picture */
336 {
337 if (pictfp == NULL)
338 return;
339 fclose(pictfp);
340 donescans();
341 pictfp = NULL;
342 }
343
344
345 extern void
346 fork_rtrace( /* open pipe and start rtrace */
347 char *av[]
348 )
349 {
350 int rval;
351
352 rval = open_process(&rt_pd, av);
353 if (rval < 0) {
354 perror(progname);
355 exit(1);
356 }
357 if (rval == 0) {
358 fprintf(stderr, "%s: command not found\n", av[0]);
359 exit(1);
360 }
361 maxpix = rval/(6*sizeof(float));
362 if (maxpix > MAXPIX)
363 maxpix = MAXPIX;
364 maxpix--;
365 }
366
367
368 extern void
369 done_rtrace(void) /* wait for rtrace to finish */
370 {
371 int status;
372
373 status = close_process(&rt_pd);
374 if (status > 0) {
375 fprintf(stderr, "%s: bad status (%d) from rtrace\n",
376 progname, status);
377 exit(1);
378 }
379 }
380
381
382 static SCAN *
383 scanretire(void) /* retire old scanlines to free list */
384 {
385 SCAN *sold[NRETIRE];
386 int n;
387 int h;
388 register SCAN *sl;
389 register int i;
390 /* grab the NRETIRE oldest scanlines */
391 sold[n = 0] = NULL;
392 for (h = 0; h < HSIZE; h++)
393 for (sl = hashtab[h]; sl != NULL; sl = sl->next) {
394 for (i = n; i && sold[i-1]->lused > sl->lused; i--)
395 if (i < NRETIRE)
396 sold[i] = sold[i-1];
397 if (i < NRETIRE) {
398 sold[i] = sl;
399 if (n < NRETIRE) /* grow list */
400 n++;
401 }
402 }
403 /* put scanlines into free list */
404 for (i = 0; i < n; i++) {
405 h = shash(sold[i]->y);
406 sl = hashtab[h];
407 if (sl == sold[i])
408 hashtab[h] = sl->next;
409 else {
410 while (sl->next != sold[i]) /* IS in list */
411 sl = sl->next;
412 sl->next = sold[i]->next;
413 }
414 if (i > 0) { /* save oldest as return value */
415 sold[i]->next = freelist;
416 freelist = sold[i];
417 }
418 }
419 return(sold[0]);
420 }
421
422
423 static char *scan_buf;
424
425
426 static void
427 initscans(void) /* initialize scanline buffers */
428 {
429 int scansize;
430 register SCAN *ptr;
431 register int i;
432 /* initialize positions */
433 scanpos = (long *)bmalloc(pysiz*sizeof(long));
434 if (scanpos == NULL)
435 memerr("scanline positions");
436 for (i = pysiz-1; i >= 0; i--)
437 scanpos[i] = -1L;
438 curpos = pysiz-1;
439 /* clear hash table */
440 for (i = 0; i < HSIZE; i++)
441 hashtab[i] = NULL;
442 /* allocate scanline buffers */
443 scansize = sizeof(SCAN) + pxsiz*sizeof(COLR);
444 #ifdef ALIGNT
445 scansize = scansize+(sizeof(ALIGNT)-1) & ~(sizeof(ALIGNT)-1);
446 #endif
447 i = MAXSBUF / scansize; /* compute number to allocate */
448 if (i > HSIZE)
449 i = HSIZE;
450 scanbufsiz = i*scansize;
451 scan_buf = bmalloc(scanbufsiz); /* get in one big chunk */
452 if (scan_buf == NULL)
453 memerr("scanline buffers");
454 ptr = (SCAN *)scan_buf;
455 freelist = NULL; /* build our free list */
456 while (i-- > 0) {
457 ptr->y = -1;
458 ptr->lused = -1;
459 ptr->next = freelist;
460 freelist = ptr;
461 ptr = (SCAN *)((char *)ptr + scansize); /* beware of C bugs */
462 }
463 }
464
465
466 static void
467 donescans(void) /* free up scanlines */
468 {
469 bfree(scan_buf, scanbufsiz);
470 bfree((char *)scanpos, pysiz*sizeof(long));
471 }