ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/rpiece.c
Revision: 2.14
Committed: Wed Dec 2 17:07:00 1992 UTC (31 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.13: +2 -1 lines
Log Message:
added ability to create synchronization file if nonexistent

File Contents

# Content
1 /* Copyright (c) 1992 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * Generate sections of a picture.
9 */
10
11 #include "standard.h"
12 #include <fcntl.h>
13 #include <signal.h>
14 #include "color.h"
15 #include "view.h"
16 #include "resolu.h"
17
18 #ifndef NFS
19 #define NFS 1
20 #endif
21 /* set the following to 0 to forgo forking */
22 #ifndef MAXFORK
23 #if NFS
24 #define MAXFORK 3 /* allotment of duped processes */
25 #else
26 #define MAXFORK 0
27 #endif
28 #endif
29
30 /* rpict command */
31 char *rpargv[128] = {"rpict", "-S", "1", "-x", "512", "-y", "512", "-pa", "1"};
32 int rpargc = 9;
33 int rpd[3];
34 FILE *torp, *fromrp;
35 COLR *pbuf;
36 /* our view parameters */
37 VIEW ourview = STDVIEW;
38 double pixaspect = 1.0;
39 int hres = 512, vres = 512, hmult = 2, vmult = 2;
40 /* output file */
41 char *outfile = NULL;
42 int outfd;
43 long scanorig;
44 int syncfd = -1; /* lock file descriptor */
45 int nforked = 0;
46
47 char *progname;
48 int verbose = 0;
49
50 extern long lseek(), ftell();
51
52 int gotalrm = 0;
53 int onalrm() { gotalrm++; }
54
55
56 main(argc, argv)
57 int argc;
58 char *argv[];
59 {
60 register int i, rval;
61
62 progname = argv[0];
63 for (i = 1; i < argc; i++) {
64 if (argv[i][0] == '-')
65 switch (argv[i][1]) {
66 case 'v':
67 switch (argv[i][2]) {
68 case '\0': /* verbose option */
69 verbose = !verbose;
70 continue;
71 case 'f': /* view file */
72 if (viewfile(argv[++i], &ourview, NULL) <= 0) {
73 fprintf(stderr,
74 "%s: not a view file\n", argv[i]);
75 exit(1);
76 }
77 continue;
78 default: /* view option? */
79 rval = getviewopt(&ourview, argc-i, argv+i);
80 if (rval >= 0) {
81 i += rval;
82 continue;
83 }
84 break;
85 }
86 break;
87 case 'p': /* pixel aspect ratio? */
88 if (argv[i][2] == 'a' && !argv[i][3])
89 pixaspect = atof(argv[i+1]);
90 break;
91 case 'x': /* piece x resolution */
92 if (!argv[i][2])
93 hres = atoi(argv[i+1]);
94 break;
95 case 'y': /* piece y resolution */
96 if (!argv[i][2])
97 vres = atoi(argv[i+1]);
98 break;
99 case 'X': /* horizontal multiplier */
100 if (argv[i][2])
101 break;
102 hmult = atoi(argv[++i]);
103 continue;
104 case 'Y': /* vertical multiplier */
105 if (argv[i][2])
106 break;
107 vmult = atoi(argv[++i]);
108 continue;
109 case 'F': /* syncronization file */
110 if (argv[i][2])
111 break;
112 if ((syncfd = open(argv[++i],
113 O_RDWR|O_CREAT, 0666)) < 0) {
114 fprintf(stderr, "%s: cannot open\n",
115 argv[i]);
116 exit(1);
117 }
118 continue;
119 case 'o': /* output file */
120 if (argv[i][2])
121 break;
122 outfile = argv[++i];
123 continue;
124 }
125 rpargv[rpargc++] = argv[i];
126 }
127 rpargv[rpargc] = NULL;
128 if (outfile == NULL) {
129 fprintf(stderr, "%s: missing output file\n", argv[0]);
130 exit(1);
131 }
132 init(argc, argv);
133 rpiece();
134 rval = cleanup(0);
135 exit(rval);
136 }
137
138
139 init(ac, av) /* set up output file and start rpict */
140 int ac;
141 char **av;
142 {
143 extern char VersionID[];
144 char *err;
145 FILE *fp;
146 int hr, vr;
147 /* set up view */
148 if ((err = setview(&ourview)) != NULL) {
149 fprintf(stderr, "%s: %s\n", progname, err);
150 exit(1);
151 }
152 if (syncfd != -1) {
153 char buf[32];
154 buf[read(syncfd, buf, sizeof(buf)-1)] = '\0';
155 sscanf(buf, "%d %d", &hmult, &vmult);
156 }
157 normaspect(viewaspect(&ourview)*hmult/vmult, &pixaspect, &hres, &vres);
158 /* open output file */
159 if ((outfd = open(outfile, O_WRONLY|O_CREAT|O_EXCL, 0666)) >= 0) {
160 if ((fp = fdopen(dup(outfd), "w")) == NULL)
161 goto filerr;
162 printargs(ac, av, fp); /* write header */
163 fprintf(fp, "SOFTWARE= %s\n", VersionID);
164 fputs(VIEWSTR, fp);
165 fprintview(&ourview, fp);
166 putc('\n', fp);
167 if (pixaspect < .99 || pixaspect > 1.01)
168 fputaspect(pixaspect, fp);
169 fputformat(COLRFMT, fp);
170 putc('\n', fp);
171 fprtresolu(hres*hmult, vres*vmult, fp);
172 } else if ((outfd = open(outfile, O_RDWR)) >= 0) {
173 if ((fp = fdopen(dup(outfd), "r+")) == NULL)
174 goto filerr;
175 getheader(fp, NULL, NULL); /* skip header */
176 if (fscnresolu(&hr, &vr, fp) < 0 || /* check resolution */
177 hr != hres*hmult || vr != vres*vmult) {
178 fprintf(stderr, "%s: resolution mismatch on file \"%s\"\n",
179 progname, outfile);
180 exit(1);
181 }
182 } else {
183 fprintf(stderr, "%s: cannot open file \"%s\"\n",
184 progname, outfile);
185 exit(1);
186 }
187 scanorig = ftell(fp); /* record position of first scanline */
188 if (fclose(fp) == -1) /* done with stream i/o */
189 goto filerr;
190 #if NFS
191 sync(); /* flush NFS buffers */
192 #endif
193 /* start rpict process */
194 if (open_process(rpd, rpargv) <= 0) {
195 fprintf(stderr, "%s: cannot start %s\n", progname, rpargv[0]);
196 exit(1);
197 }
198 if ((fromrp = fdopen(rpd[0], "r")) == NULL ||
199 (torp = fdopen(rpd[1], "w")) == NULL) {
200 fprintf(stderr, "%s: cannot open stream to %s\n",
201 progname, rpargv[0]);
202 exit(1);
203 }
204 if ((pbuf = (COLR *)malloc(hres*vres*sizeof(COLR))) == NULL) {
205 fprintf(stderr, "%s: out of memory\n", progname);
206 exit(1);
207 }
208 signal(SIGALRM, onalrm);
209 return;
210 filerr:
211 fprintf(stderr, "%s: i/o error on file \"%s\"\n", progname, outfile);
212 exit(1);
213 }
214
215
216 int
217 nextpiece(xp, yp) /* get next piece assignment */
218 int *xp, *yp;
219 {
220 extern char *fgets();
221 struct flock fls;
222 char buf[64];
223
224 if (gotalrm) /* someone wants us to quit */
225 return(0);
226 if (syncfd != -1) { /* use sync file */
227 fls.l_type = F_WRLCK; /* gain exclusive access */
228 fls.l_whence = 0;
229 fls.l_start = 0L;
230 fls.l_len = 0L;
231 fcntl(syncfd, F_SETLKW, &fls);
232 lseek(syncfd, 0L, 0);
233 buf[read(syncfd, buf, sizeof(buf)-1)] = '\0';
234 if (sscanf(buf, "%*d %*d %d %d", xp, yp) < 2) {
235 *xp = hmult-1;
236 *yp = vmult;
237 }
238 if (--(*yp) < 0) { /* decrement position */
239 *yp = vmult-1;
240 if (--(*xp) < 0) { /* all done! */
241 close(syncfd);
242 return(0);
243 }
244 }
245 sprintf(buf, "%d %d\n%d %d\n", hmult, vmult, *xp, *yp);
246 lseek(syncfd, 0L, 0); /* write new position */
247 write(syncfd, buf, strlen(buf));
248 fls.l_type = F_UNLCK; /* release sync file */
249 fcntl(syncfd, F_SETLKW, &fls);
250 return(1);
251 }
252 if (fgets(buf, sizeof(buf), stdin) == NULL) /* use stdin */
253 return(0);
254 if (sscanf(buf, "%d %d", xp, yp) == 2)
255 return(1);
256 fprintf(stderr, "%s: input format error\n", progname);
257 exit(cleanup(1));
258 }
259
260
261 int
262 cleanup(rstat) /* close rpict process and clean up */
263 int rstat;
264 {
265 int status;
266
267 free((char *)pbuf);
268 fclose(torp);
269 fclose(fromrp);
270 while (wait(&status) != -1)
271 if (rstat == 0)
272 rstat = status>>8 & 0xff;
273 return(rstat);
274 }
275
276
277 rpiece() /* render picture piece by piece */
278 {
279 VIEW pview;
280 int xorg, yorg;
281 /* compute view parameters */
282 copystruct(&pview, &ourview);
283 switch (ourview.type) {
284 case VT_PER:
285 pview.horiz = 2.*180./PI*atan(
286 tan(PI/180./2.*ourview.horiz)/hmult );
287 pview.vert = 2.*180./PI*atan(
288 tan(PI/180./2.*ourview.vert)/vmult );
289 break;
290 case VT_PAR:
291 case VT_ANG:
292 pview.horiz = ourview.horiz / hmult;
293 pview.vert = ourview.vert / vmult;
294 break;
295 case VT_HEM:
296 pview.horiz = 2.*180./PI*asin(
297 sin(PI/180./2.*ourview.horiz)/hmult );
298 pview.vert = 2.*180./PI*asin(
299 sin(PI/180./2.*ourview.vert)/vmult );
300 break;
301 default:
302 fprintf(stderr, "%s: unknown view type '-vt%c'\n",
303 progname, ourview.type);
304 exit(cleanup(1));
305 }
306 /* render each piece */
307 while (nextpiece(&xorg, &yorg)) {
308 pview.hoff = ourview.hoff + xorg - 0.5*(hmult-1);
309 pview.voff = ourview.voff + yorg - 0.5*(vmult-1);
310 fputs(VIEWSTR, torp);
311 fprintview(&pview, torp);
312 putc('\n', torp);
313 fflush(torp); /* assigns piece to rpict */
314 putpiece(xorg, yorg); /* place piece in output */
315 if (verbose) { /* notify caller */
316 printf("%d %d done\n", xorg, yorg);
317 fflush(stdout);
318 }
319 }
320 }
321
322
323 int
324 putpiece(xpos, ypos) /* get next piece from rpict */
325 int xpos, ypos;
326 {
327 struct flock fls;
328 int pid, status;
329 int hr, vr;
330 register int y;
331 /* check bounds */
332 if (xpos < 0 | ypos < 0 | xpos >= hmult | ypos >= vmult) {
333 fprintf(stderr, "%s: requested piece (%d,%d) out of range\n",
334 progname, xpos, ypos);
335 exit(cleanup(1));
336 }
337 /* check header from rpict */
338 getheader(fromrp, NULL, NULL);
339 if (fscnresolu(&hr, &vr, fromrp) < 0 || hr != hres | vr != vres) {
340 fprintf(stderr, "%s: resolution mismatch from %s\n",
341 progname, rpargv[0]);
342 exit(cleanup(1));
343 }
344 /* load new piece into buffer */
345 for (y = 0; y < vr; y++)
346 if (freadcolrs(pbuf+y*hr, hr, fromrp) < 0) {
347 fprintf(stderr, "%s: read error from %s\n",
348 progname, rpargv[0]);
349 exit(cleanup(1));
350 }
351 #if MAXFORK
352 /* fork so we don't slow rpict down */
353 if ((pid = fork()) > 0) {
354 if (++nforked >= MAXFORK) {
355 wait(&status); /* reap a child */
356 if (status)
357 exit(cleanup(status>>8 & 0xff));
358 nforked--;
359 }
360 return(pid);
361 }
362 #else
363 pid = -1; /* no forking */
364 #endif
365 #if NFS
366 /* lock file section so NFS doesn't mess up */
367 fls.l_whence = 0;
368 fls.l_len = (long)vres*hmult*hres*sizeof(COLR);
369 fls.l_start = scanorig + (vmult-1-ypos)*fls.l_len;
370 fls.l_type = F_WRLCK;
371 fcntl(outfd, F_SETLKW, &fls);
372 #endif
373 /* write new piece to file */
374 if (lseek(outfd, fls.l_start+(long)xpos*hres*sizeof(COLR), 0) == -1)
375 goto seekerr;
376 if (hmult == 1) {
377 if (writebuf(outfd, (char *)pbuf,
378 vr*hr*sizeof(COLR)) != vr*hr*sizeof(COLR))
379 goto writerr;
380 } else
381 for (y = 0; y < vr; y++) {
382 if (writebuf(outfd, (char *)(pbuf+y*hr),
383 hr*sizeof(COLR)) != hr*sizeof(COLR))
384 goto writerr;
385 if (y < vr-1 && lseek(outfd,
386 (long)(hmult-1)*hr*sizeof(COLR),
387 1) == -1)
388 goto seekerr;
389 }
390 if (pid == -1) { /* fork failed */
391 #if NFS
392 fls.l_type = F_UNLCK; /* release lock */
393 fcntl(outfd, F_SETLKW, &fls);
394 #endif
395 return(0);
396 }
397 _exit(0); /* else exit child process (releasing lock) */
398 seekerr:
399 fprintf(stderr, "%s: seek error on file \"%s\"\n", progname, outfile);
400 _exit(1);
401 writerr:
402 fprintf(stderr, "%s: write error on file \"%s\"\n", progname, outfile);
403 _exit(1);
404 }