void newimage( /* start a new image */ char *s ) { int newnp = 0; /* # rendering procs arg? */ if (s != NULL) sscanf(s, "%d", &newnp); /* free old image */ freepkids(&ptrunk); /* compute resolution */ hresolu = dev->xsiz; vresolu = dev->ysiz; normaspect(viewaspect(&ourview), &dev->pixaspect, &hresolu, &vresolu); ptrunk.xmin = ptrunk.ymin = pframe.l = pframe.d = 0; ptrunk.xmax = pframe.r = hresolu; ptrunk.ymax = pframe.u = vresolu; pdepth = 0; /* clear device */ (*dev->clear)(hresolu, vresolu); if (newparam) { /* (re)start rendering procs */ if (ray_pnprocs) ray_pclose(0); /* should already be closed */ if (newnp > 0) nproc = newnp; if (nproc > 1) ray_popen(nproc); newparam = 0; } else if ((newnp > 0) & (newnp != nproc)) { if (newnp == 1) /* change # rendering procs */ ray_pclose(0); else if (newnp < ray_pnprocs) ray_pclose(ray_pnprocs - newnp); else ray_popen(newnp - ray_pnprocs); nproc = newnp; } niflush = 0; /* get first value */ paint(&ptrunk); }
void ray_pdone( /* reap children and free data */ int freall ) { ray_pclose(0); /* close child processes */ if (shm_boundary != NULL) { /* clear shared memory boundary */ free((void *)shm_boundary); shm_boundary = NULL; } ray_done(freall); /* free rendering data */ }
int ray_presult( /* check for a completed ray */ RAY *r, int poll ) { static struct timeval tpoll; /* zero timeval struct */ static fd_set readset, errset; int n, ok; register int pn; if (r == NULL) return(0); /* check queued results first */ if (r_recv_first < r_recv_next) { *r = r_queue[r_recv_first++]; return(1); } if (poll < 0) /* immediate polling mode? */ return(0); n = ray_pnprocs - ray_pnidle; /* pending before flush? */ if (ray_pflush() < 0) /* send new rays to process */ return(-1); /* reset receive queue */ r_recv_first = r_recv_next = RAYQLEN; if (!poll) /* count newly sent unless polling */ n = ray_pnprocs - ray_pnidle; if (n <= 0) /* return if nothing to await */ return(0); if (!poll && ray_pnprocs == 1) /* one process -> skip select() */ FD_SET(r_proc[0].fd_recv, &readset); getready: /* any children waiting for us? */ for (pn = ray_pnprocs; pn--; ) if (FD_ISSET(r_proc[pn].fd_recv, &readset) || FD_ISSET(r_proc[pn].fd_recv, &errset)) break; /* call select() if we must */ if (pn < 0) { FD_ZERO(&readset); FD_ZERO(&errset); n = 0; for (pn = ray_pnprocs; pn--; ) { if (r_proc[pn].npending > 0) FD_SET(r_proc[pn].fd_recv, &readset); FD_SET(r_proc[pn].fd_recv, &errset); if (r_proc[pn].fd_recv >= n) n = r_proc[pn].fd_recv + 1; } /* find out who is ready */ while ((n = select(n, &readset, (fd_set *)NULL, &errset, poll ? &tpoll : (struct timeval *)NULL)) < 0) if (errno != EINTR) { error(WARNING, "select call failed in ray_presult()"); ray_pclose(0); return(-1); } if (n > 0) /* go back and get it */ goto getready; return(0); /* else poll came up empty */ } if (r_recv_next + r_proc[pn].npending > sizeof(r_queue)/sizeof(RAY)) error(CONSISTENCY, "buffer shortage in ray_presult()"); /* read rendered ray data */ n = readbuf(r_proc[pn].fd_recv, (char *)&r_queue[r_recv_next], sizeof(RAY)*r_proc[pn].npending); if (n > 0) { r_recv_next += n/sizeof(RAY); ok = (n == sizeof(RAY)*r_proc[pn].npending); } else ok = 0; /* reset child's status */ FD_CLR(r_proc[pn].fd_recv, &readset); if (n <= 0) FD_CLR(r_proc[pn].fd_recv, &errset); r_proc[pn].npending = 0; ray_pnidle++; /* check for rendering errors */ if (!ok) { ray_pclose(0); /* process died -- clean up */ return(-1); } /* preen returned rays */ for (n = r_recv_next - r_recv_first; n--; ) { register RAY *rp = &r_queue[r_recv_first + n]; rp->rno = r_proc[pn].rno[n]; rp->parent = NULL; rp->newcset = rp->clipset = NULL; rp->rox = NULL; rp->slights = NULL; } /* return first ray received */ *r = r_queue[r_recv_first++]; return(1); }