ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp.c
Revision: 3.15
Committed: Mon Dec 15 20:43:48 1997 UTC (26 years, 4 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.14: +11 -4 lines
Log Message:
resume calculation after restart

File Contents

# Content
1 /* Copyright (c) 1997 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Holodeck display process.
9 */
10
11 #include "rholo.h"
12 #include "rhdisp.h"
13 #include "rhdriver.h"
14 #include "selcall.h"
15 #include <ctype.h>
16
17 #ifndef VIEWHISTLEN
18 #define VIEWHISTLEN 2 /* number of remembered views */
19 #endif
20
21 HOLO *hdlist[HDMAX+1]; /* global holodeck list */
22
23 char cmdlist[DC_NCMDS][8] = DC_INIT;
24
25 int imm_mode = 0; /* bundles are being delivered immediately */
26
27 char *progname; /* global argv[0] */
28
29 FILE *sstdin, *sstdout; /* server's standard input and output */
30
31 #define RDY_SRV 01
32 #define RDY_DEV 02
33 #define RDY_SIN 04
34
35
36 main(argc, argv)
37 int argc;
38 char *argv[];
39 {
40 extern int eputs();
41 int rdy, inp, res = 0, pause = 0;
42
43 progname = argv[0];
44 if (argc < 3)
45 error(USER, "bad command line arguments");
46 /* open our device */
47 dev_open(argv[1]);
48 /* open server process i/o */
49 sstdout = fdopen(atoi(argv[2]), "w");
50 if (argc < 4 || (inp = atoi(argv[3])) < 0)
51 sstdin = NULL;
52 else
53 sstdin = fdopen(inp, "r");
54 /* set command error vector */
55 erract[COMMAND].pf = eputs;
56 /* enter main loop */
57 do {
58 rdy = disp_wait();
59 if (rdy & RDY_DEV) { /* user input from driver */
60 inp = dev_input();
61 if (inp & DFL(DC_SETVIEW))
62 new_view(&odev.v);
63 if (inp & DFL(DC_GETVIEW))
64 printview();
65 if (inp & DFL(DC_LASTVIEW))
66 new_view(NULL);
67 if (inp & DFL(DC_RESUME)) {
68 serv_request(DR_NOOP, 0, NULL);
69 pause = 0;
70 }
71 if (inp & DFL(DC_PAUSE))
72 pause = 1;
73 if (inp & DFL(DC_REDRAW))
74 imm_mode = beam_sync() > 0;
75 if (inp & DFL(DC_KILL)) {
76 serv_request(DR_KILL, 0, NULL);
77 pause = 0;
78 }
79 if (inp & DFL(DC_CLOBBER))
80 serv_request(DR_CLOBBER, 0, NULL);
81 if (inp & DFL(DC_RESTART)) {
82 serv_request(DR_RESTART, 0, NULL);
83 pause = 0;
84 }
85 if (inp & DFL(DC_QUIT))
86 serv_request(DR_SHUTDOWN, 0, NULL);
87 }
88 if (rdy & RDY_SIN) /* user input from sstdin */
89 switch (usr_input()) {
90 case DC_PAUSE:
91 pause = 1;
92 break;
93 case DC_RESUME:
94 serv_request(DR_NOOP, 0, NULL);
95 /* fall through */
96 case DC_KILL:
97 case DC_RESTART:
98 pause = 0;
99 break;
100 }
101 if (rdy & RDY_SRV) { /* process server result */
102 res = serv_result();
103 if (pause && res != DS_SHUTDOWN) {
104 serv_request(DR_ATTEN, 0, NULL);
105 while ((res = serv_result()) != DS_ACKNOW &&
106 res != DS_SHUTDOWN)
107 ;
108 }
109 }
110 } while (res != DS_SHUTDOWN);
111 /* all done */
112 quit(0);
113 }
114
115
116 int
117 disp_wait() /* wait for more input */
118 {
119 fd_set readset, errset;
120 int flgs;
121 int n;
122 register int i;
123 /* see if we can avoid select call */
124 if (imm_mode || stdin->_cnt > 0)
125 return(RDY_SRV);
126 if (sstdin != NULL && sstdin->_cnt > 0)
127 return(RDY_SIN);
128 if (dev_flush())
129 return(RDY_DEV);
130 /* make the call */
131 FD_ZERO(&readset); FD_ZERO(&errset);
132 FD_SET(0, &readset);
133 FD_SET(0, &errset);
134 FD_SET(odev.ifd, &readset);
135 FD_SET(odev.ifd, &errset);
136 n = odev.ifd+1;
137 if (sstdin != NULL) {
138 FD_SET(fileno(sstdin), &readset);
139 if (fileno(sstdin) >= n)
140 n = fileno(sstdin) + 1;
141 }
142 n = select(n, &readset, NULL, &errset, NULL);
143 if (n < 0) {
144 if (errno == EINTR)
145 return(0);
146 error(SYSTEM, "select call failure in disp_wait");
147 }
148 flgs = 0; /* flag what's ready */
149 if (FD_ISSET(0, &readset) || FD_ISSET(0, &errset))
150 flgs |= RDY_SRV;
151 if (FD_ISSET(odev.ifd, &readset) || FD_ISSET(odev.ifd, &errset))
152 flgs |= RDY_DEV;
153 if (sstdin != NULL && FD_ISSET(fileno(sstdin), &readset))
154 flgs |= RDY_SIN;
155 return(flgs);
156 }
157
158
159 add_holo(hdg) /* register a new holodeck section */
160 HDGRID *hdg;
161 {
162 VIEW nv;
163 register int hd;
164
165 for (hd = 0; hd < HDMAX && hdlist[hd] != NULL; hd++)
166 ;
167 if (hd >= HDMAX)
168 error(INTERNAL, "too many holodeck sections in add_holo");
169 hdlist[hd] = (HOLO *)malloc(sizeof(HOLO));
170 if (hdlist[hd] == NULL)
171 error(SYSTEM, "out of memory in add_holo");
172 bcopy((char *)hdg, (char *)hdlist[hd], sizeof(HDGRID));
173 hdcompgrid(hdlist[hd]);
174 if (hd)
175 return;
176 /* set initial viewpoint */
177 copystruct(&nv, &odev.v);
178 VSUM(nv.vp, hdlist[0]->orig, hdlist[0]->xv[0], 0.5);
179 VSUM(nv.vp, nv.vp, hdlist[0]->xv[1], 0.5);
180 VSUM(nv.vp, nv.vp, hdlist[0]->xv[2], 0.5);
181 fcross(nv.vdir, hdlist[0]->xv[1], hdlist[0]->xv[2]);
182 VCOPY(nv.vup, hdlist[0]->xv[2]);
183 new_view(&nv);
184 }
185
186
187 disp_bundle(p) /* display a ray bundle */
188 register PACKHEAD *p;
189 {
190 GCOORD gc[2];
191 FVECT ro, rd, wp;
192 double d;
193 register int i;
194 /* get beam coordinates */
195 if (p->hd < 0 | p->hd >= HDMAX || hdlist[p->hd] == NULL)
196 error(INTERNAL, "bad holodeck number in disp_bundle");
197 if (!hdbcoord(gc, hdlist[p->hd], p->bi))
198 error(INTERNAL, "bad beam index in disp_bundle");
199 /* display each ray */
200 for (i = p->nr; i--; ) {
201 hdray(ro, rd, hdlist[p->hd], gc, packra(p)[i].r);
202 d = hddepth(hdlist[p->hd], packra(p)[i].d);
203 VSUM(wp, ro, rd, d); /* might be behind viewpoint */
204 dev_value(packra(p)[i].v, wp, rd);
205 }
206 }
207
208
209 new_view(v) /* change view parameters */
210 register VIEW *v;
211 {
212 static VIEW viewhist[VIEWHISTLEN];
213 static unsigned nhist;
214 char *err;
215 /* restore previous view? */
216 if (v == NULL) {
217 if (nhist < 2) {
218 error(COMMAND, "no previous view");
219 return;
220 }
221 nhist--; /* get one before last setting */
222 v = viewhist + ((nhist-1)%VIEWHISTLEN);
223 } else if ((err = setview(v)) != NULL) {
224 error(COMMAND, err);
225 return;
226 }
227 again:
228 if (v->type == VT_PAR) {
229 error(COMMAND, "cannot handle parallel views");
230 return;
231 }
232 if (!dev_view(v)) /* update display driver */
233 goto again;
234 dev_flush(); /* update screen */
235 if (!beam_view(v)) /* update beam list */
236 goto again;
237 /* record new view */
238 if (v < viewhist || v >= viewhist+VIEWHISTLEN) {
239 copystruct(viewhist + (nhist%VIEWHISTLEN), v);
240 nhist++;
241 }
242 }
243
244
245 int
246 usr_input() /* get user input and process it */
247 {
248 VIEW vparams;
249 char cmd[128];
250 register char *args;
251 register int i;
252
253 if (fgets(cmd, sizeof(cmd), sstdin) == NULL)
254 return(DC_QUIT);
255 for (args = cmd; *args && !isspace(*args); args++)
256 ;
257 while (isspace(*args))
258 *args++ = '\0';
259 if (!*cmd)
260 return(DC_RESUME);
261 if (*args && args[i=strlen(args)-1] == '\n')
262 args[i] = '\0';
263 for (i = 0; i < DC_NCMDS; i++)
264 if (!strcmp(cmd, cmdlist[i]))
265 break;
266 if (i >= DC_NCMDS) {
267 sprintf(errmsg, "unknown command: %s", cmd);
268 error(COMMAND, errmsg);
269 return(-1);
270 }
271 switch (i) {
272 case DC_SETVIEW: /* set the view */
273 copystruct(&vparams, &odev.v);
274 if (!sscanview(&vparams, args))
275 error(COMMAND, "missing view options");
276 else
277 new_view(&vparams);
278 break;
279 case DC_GETVIEW: /* print the current view */
280 printview();
281 break;
282 case DC_LASTVIEW: /* restore previous view */
283 new_view(NULL);
284 break;
285 case DC_PAUSE: /* pause the current calculation */
286 case DC_RESUME: /* resume the calculation */
287 /* handled in main() */
288 break;
289 case DC_REDRAW: /* redraw from server */
290 imm_mode = beam_sync() > 0;
291 break;
292 case DC_KILL: /* kill rtrace process(es) */
293 serv_request(DR_KILL, 0, NULL);
294 break;
295 case DC_CLOBBER: /* clobber holodeck */
296 serv_request(DR_CLOBBER, 0, NULL);
297 break;
298 case DC_RESTART: /* restart rtrace */
299 serv_request(DR_RESTART, 0, NULL);
300 break;
301 case DC_QUIT: /* quit request */
302 serv_request(DR_SHUTDOWN, 0, NULL);
303 break;
304 default:
305 error(CONSISTENCY, "bad command id in usr_input");
306 }
307 return(i);
308 }
309
310
311 printview() /* print our current view to server stdout */
312 {
313 fputs(VIEWSTR, sstdout);
314 fprintview(&odev.v, sstdout);
315 fputc('\n', sstdout);
316 fflush(sstdout);
317 }
318
319
320 int
321 serv_result() /* get next server result and process it */
322 {
323 static char *buf = NULL;
324 static int bufsiz = 0;
325 MSGHEAD msg;
326 int n;
327 /* read message header */
328 if (fread((char *)&msg, sizeof(MSGHEAD), 1, stdin) != 1)
329 goto readerr;
330 if (msg.nbytes > 0) { /* get the message body */
331 if (msg.nbytes > bufsiz) {
332 if (buf == NULL)
333 buf = (char *)malloc(bufsiz=msg.nbytes);
334 else
335 buf = (char *)realloc(buf, bufsiz=msg.nbytes);
336 if (buf == NULL)
337 error(SYSTEM, "out of memory in serv_result");
338 }
339 if (fread(buf, 1, msg.nbytes, stdin) != msg.nbytes)
340 goto readerr;
341 }
342 switch (msg.type) { /* process results */
343 case DS_BUNDLE:
344 if (msg.nbytes < sizeof(PACKHEAD) ||
345 msg.nbytes != packsiz(((PACKHEAD *)buf)->nr))
346 error(INTERNAL, "bad display packet from server");
347 disp_bundle((PACKHEAD *)buf);
348 break;
349 case DS_ADDHOLO:
350 if (msg.nbytes != sizeof(HDGRID))
351 error(INTERNAL, "bad holodeck record from server");
352 add_holo((HDGRID *)buf);
353 break;
354 case DS_STARTIMM:
355 case DS_ENDIMM:
356 imm_mode = msg.type==DS_STARTIMM;
357 if (msg.type == DS_ENDIMM)
358 dev_flush(); /* update display NOW */
359 /* fall through */
360 case DS_ACKNOW:
361 case DS_SHUTDOWN:
362 if (msg.nbytes) {
363 sprintf(errmsg,
364 "unexpected body with server message %d",
365 msg.type);
366 error(INTERNAL, errmsg);
367 }
368 break;
369 default:
370 error(INTERNAL, "unrecognized result from server process");
371 }
372 return(msg.type); /* return message type */
373 readerr:
374 if (feof(stdin))
375 error(SYSTEM, "server process died");
376 error(SYSTEM, "error reading from server process");
377 }
378
379
380 serv_request(type, nbytes, p) /* send a request to the server process */
381 int type, nbytes;
382 char *p;
383 {
384 MSGHEAD msg;
385 int m;
386 /* get server's attention for big request */
387 if (nbytes >= BIGREQSIZ-sizeof(MSGHEAD)) {
388 serv_request(DR_ATTEN, 0, NULL);
389 while ((m = serv_result()) != DS_ACKNOW)
390 if (m == DS_SHUTDOWN) /* the bugger quit on us */
391 quit(0);
392 }
393 msg.type = type; /* write and flush the message */
394 msg.nbytes = nbytes;
395 fwrite((char *)&msg, sizeof(MSGHEAD), 1, stdout);
396 if (nbytes > 0)
397 fwrite(p, 1, nbytes, stdout);
398 if (fflush(stdout) < 0)
399 error(SYSTEM, "write error in serv_request");
400 }
401
402
403 eputs(s) /* put error message to stderr */
404 register char *s;
405 {
406 static int midline = 0;
407
408 if (!*s)
409 return;
410 if (!midline++) { /* prepend line with program name */
411 fputs(progname, stderr);
412 fputs(": ", stderr);
413 }
414 fputs(s, stderr);
415 if (s[strlen(s)-1] == '\n') {
416 fflush(stderr);
417 midline = 0;
418 }
419 }
420
421
422 quit(code) /* clean up and exit */
423 int code;
424 {
425 if (odev.v.type)
426 dev_close();
427 exit(code);
428 }