ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp.c
Revision: 3.13
Committed: Thu Dec 11 16:45:58 1997 UTC (26 years, 3 months ago) by gregl
Content type: text/plain
Branch: MAIN
Changes since 3.12: +13 -10 lines
Log Message:
normalized commands between driver and standard input

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